diff --git a/sessions/demo/.env.example b/sessions/demo/.env.example new file mode 100644 index 0000000000..ac1967de8e --- /dev/null +++ b/sessions/demo/.env.example @@ -0,0 +1,18 @@ +ANTHROPIC_API_KEY= +OPENAI_API_KEY= + +DAYTONA_API_KEY= +E2B_API_KEY= +MODAL_TOKEN_ID= +MODAL_TOKEN_SECRET= +NORTHFLANK_TOKEN= + +NGROK_AUTHTOKEN= + +SEAWEEDFS_S3_ACCESS_KEY=demo +SEAWEEDFS_S3_SECRET_KEY=demosecret +SEAWEEDFS_S3_URL=http://seaweedfs:8333 +SEAWEEDFS_S3_BUCKET=demo + +POSTGRES_URI=postgresql://postgres:postgres@postgres:5432 +POSTGRES_DB=demo diff --git a/sessions/demo/api/Dockerfile b/sessions/demo/api/Dockerfile new file mode 100644 index 0000000000..ac31d354cb --- /dev/null +++ b/sessions/demo/api/Dockerfile @@ -0,0 +1,8 @@ +FROM python:3.12-slim +WORKDIR /app +COPY requirements.txt ./ +RUN pip install --no-cache-dir -r requirements.txt +COPY db.py main.py ./ +COPY static ./static +EXPOSE 8000 +CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"] diff --git a/sessions/demo/api/db.py b/sessions/demo/api/db.py new file mode 100644 index 0000000000..e858ad4c93 --- /dev/null +++ b/sessions/demo/api/db.py @@ -0,0 +1,246 @@ +import json +import os +import struct +import time +import uuid + +import asyncpg + +DSN = f"{os.environ['POSTGRES_URI'].rstrip('/')}/{os.environ['POSTGRES_DB']}" + + +def uuid7() -> uuid.UUID: + # Time-ordered UUIDv7: 48-bit ms timestamp + version/variant + random. + ms = int(time.time() * 1000) + rand = uuid.uuid4().bytes + b = struct.pack(">Q", ms)[2:] + rand[6:] # 6 ts bytes + 10 random bytes + b = bytearray(b) + b[6] = (b[6] & 0x0F) | 0x70 # version 7 + b[8] = (b[8] & 0x3F) | 0x80 # RFC 4122 variant + return uuid.UUID(bytes=bytes(b)) + + +SCHEMA = """ +CREATE TABLE IF NOT EXISTS sessions ( + id UUID PRIMARY KEY, + sandbox TEXT NOT NULL DEFAULT 'local', -- where it runs: local | modal | e2b | daytona + harness TEXT NOT NULL DEFAULT 'claude', -- coding agent: claude | codex | opencode | pi + runner TEXT NOT NULL DEFAULT 'local', -- derived: local (sandbox=local) | rivet + provider TEXT NOT NULL DEFAULT 'anthropic', -- LLM API: anthropic | openai + model TEXT, -- model id (keyed by provider) + reasoning TEXT NOT NULL DEFAULT 'none', -- thoughtLevel: none | low | medium | high + cwd TEXT NOT NULL, + bucket_prefix TEXT NOT NULL, + sandbox_id TEXT, -- remote sandbox id (modal/e2b) for resume + status TEXT NOT NULL DEFAULT 'active', + created_at TIMESTAMPTZ NOT NULL DEFAULT now(), + updated_at TIMESTAMPTZ NOT NULL DEFAULT now() +); + +-- No global sequence: id is a UUIDv7 (time-ordered), ordering is a per-session counter. +CREATE TABLE IF NOT EXISTS session_transcripts ( + id UUID PRIMARY KEY, + session_id UUID NOT NULL REFERENCES sessions(id), + seq INT NOT NULL, -- dense per-session index (count at insert) + event_index INT, -- agent's raw eventIndex (resets per resume) + sender TEXT, + session_update TEXT, + payload JSONB NOT NULL, + created_at TIMESTAMPTZ NOT NULL DEFAULT now(), + UNIQUE (session_id, seq) +); + +-- The sandbox-agent SDK's per-session record (its SessionPersistDriver state): the +-- local-id -> agentSessionId mapping, sessionInit, modes, etc. It is metadata that rides +-- ALONGSIDE the transcript, not the transcript itself. Persisting it across the fresh +-- SandboxAgent.connect() each /run does is what lets resumeOrCreateSession actually RESUME +-- the prior agent session (and replay the transcript as context) instead of starting cold. +CREATE TABLE IF NOT EXISTS session_state ( + session_id UUID PRIMARY KEY REFERENCES sessions(id), + record JSONB NOT NULL, + updated_at TIMESTAMPTZ NOT NULL DEFAULT now() +); +""" + +_pool: asyncpg.Pool | None = None + + +async def init(): + global _pool + _pool = await asyncpg.create_pool(DSN, min_size=1, max_size=5) + async with _pool.acquire() as con: + await con.execute(SCHEMA) + + +async def pool() -> asyncpg.Pool: + assert _pool is not None + return _pool + + +async def create_session( + sid: str, + cwd: str, + prefix: str, + sandbox: str, + harness: str, + runner: str = "local", + provider: str = "anthropic", + model: str | None = None, + reasoning: str = "none", +): + async with (await pool()).acquire() as con: + await con.execute( + """INSERT INTO sessions + (id, sandbox, harness, runner, provider, model, reasoning, cwd, bucket_prefix) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9) ON CONFLICT (id) DO NOTHING""", + sid, + sandbox, + harness, + runner, + provider, + model, + reasoning, + cwd, + prefix, + ) + + +async def get_session(sid: str): + async with (await pool()).acquire() as con: + return await con.fetchrow( + """SELECT id, sandbox, harness, runner, provider, model, reasoning, + cwd, bucket_prefix, sandbox_id FROM sessions WHERE id = $1""", + sid, + ) + + +async def set_sandbox_id(sid: str, sandbox_id: str): + async with (await pool()).acquire() as con: + await con.execute( + "UPDATE sessions SET sandbox_id = $2 WHERE id = $1", sid, sandbox_id + ) + + +async def session_exists(sid: str) -> bool: + return (await get_session(sid)) is not None + + +async def delete_session(sid: str): + async with (await pool()).acquire() as con: + await con.execute("DELETE FROM session_state WHERE session_id = $1", sid) + await con.execute("DELETE FROM session_transcripts WHERE session_id = $1", sid) + await con.execute("DELETE FROM sessions WHERE id = $1", sid) + + +async def get_session_state(sid: str): + # The SDK SessionRecord (JSON), or None if the session has never been persisted. + async with (await pool()).acquire() as con: + row = await con.fetchrow( + "SELECT record FROM session_state WHERE session_id = $1", sid + ) + if row is None: + return None + rec = row["record"] + return json.loads(rec) if isinstance(rec, str) else rec + + +async def set_session_state(sid: str, record: dict): + async with (await pool()).acquire() as con: + await con.execute( + """INSERT INTO session_state (session_id, record, updated_at) + VALUES ($1, $2, now()) + ON CONFLICT (session_id) + DO UPDATE SET record = EXCLUDED.record, updated_at = now()""", + sid, + json.dumps(record), + ) + + +async def append_event(sid: str, event_index, sender, session_update, payload: dict): + # seq = current count of this session's events (dense, monotonic per session). + async with (await pool()).acquire() as con: + seq = await con.fetchval( + "SELECT count(*) FROM session_transcripts WHERE session_id = $1", sid + ) + await con.execute( + """INSERT INTO session_transcripts + (id, session_id, seq, event_index, sender, session_update, payload) + VALUES ($1, $2, $3, $4, $5, $6, $7) + ON CONFLICT (session_id, seq) DO NOTHING""", + uuid7(), + sid, + seq, + event_index, + sender, + session_update, + json.dumps(payload), + ) + await con.execute("UPDATE sessions SET updated_at = now() WHERE id = $1", sid) + + +# A remote sandbox is treated as "live" only for this window after the session's last +# activity. Cloud sandboxes auto-stop/pause on their own (e2b auto-pause, daytona +# autoStop), so a recorded sandbox_id past this TTL is almost certainly dead — we drop the +# live badge / kill button rather than probe each one per refresh. Resume still works +# regardless (it recreates + remounts the durable cwd). +SANDBOX_LIVE_TTL_SECONDS = 5 * 60 + + +async def list_sessions(): + import datetime + + now = datetime.datetime.now(datetime.timezone.utc) + async with (await pool()).acquire() as con: + rows = await con.fetch( + """SELECT s.id, s.sandbox, s.harness, s.runner, s.provider, s.model, s.reasoning, + s.cwd, s.bucket_prefix, s.sandbox_id, + s.status, s.updated_at, count(t.id) AS events + FROM sessions s LEFT JOIN session_transcripts t ON t.session_id = s.id + GROUP BY s.id ORDER BY s.updated_at DESC""" + ) + out = [] + for r in rows: + fresh = (now - r["updated_at"]).total_seconds() < SANDBOX_LIVE_TTL_SECONDS + live = bool(r["sandbox_id"]) and fresh + out.append( + { + "id": str(r["id"]), + "sandbox": r["sandbox"], + "harness": r["harness"], + "runner": r["runner"], + "provider": r["provider"], + "model": r["model"], + "reasoning": r["reasoning"], + "cwd": r["cwd"], + "bucket_prefix": r["bucket_prefix"], + "sandbox_id": r["sandbox_id"], + "live": live, # sandbox_id recorded AND within the live TTL + "status": r["status"], + "updated_at": r["updated_at"].isoformat(), + "events": r["events"], + } + ) + return out + + +async def get_transcript(sid: str): + async with (await pool()).acquire() as con: + rows = await con.fetch( + """SELECT seq, event_index, sender, session_update, payload, created_at + FROM session_transcripts WHERE session_id = $1 + ORDER BY seq""", + sid, + ) + return [ + { + "seq": r["seq"], + "event_index": r["event_index"], + "sender": r["sender"], + "session_update": r["session_update"], + "payload": json.loads(r["payload"]) + if isinstance(r["payload"], str) + else r["payload"], + "created_at": r["created_at"].isoformat(), + } + for r in rows + ] diff --git a/sessions/demo/api/locks.py b/sessions/demo/api/locks.py new file mode 100644 index 0000000000..f0ad43553a --- /dev/null +++ b/sessions/demo/api/locks.py @@ -0,0 +1,135 @@ +"""FastAPI-owned `attached` lock — "is a BROWSER currently watching this session's run?". + +This lives in FastAPI (not the sidecar) because the browser talks to FastAPI: only FastAPI +sits at the browser boundary and can observe a client connecting / disconnecting. It is the +counterpart to the sidecar's `live` lock ("is a run executing?"). The two are independent: + + alive=yes, attached=yes -> running, someone is watching -> 409 (force to take over) + alive=yes, attached=no -> running but DETACHED (driver left) -> reattachable + alive=no -> idle + +Critically, dropping `attached` on browser disconnect must NOT cancel the run or stop +persistence — those are wholly the sidecar's job now (it persists every event to /events as it +is produced). `attached` is purely "who is watching the live view", and the live view is +disposable. The short TTL is a backstop for a hard client crash; the explicit drop on +disconnect is the fast path. +""" + +import os + +import redis.asyncio as aioredis + +REDIS_URL = os.environ.get("REDIS_URL", "redis://redis:6379") +# short TTL: this tracks a live browser connection, so it must expire quickly if the holder +# dies without a clean disconnect. Refreshed well under the TTL while connected. +ATTACHED_TTL_MS = int(os.environ.get("ATTACHED_TTL_MS", 20_000)) +ATTACHED_REFRESH_S = max(1, (ATTACHED_TTL_MS // 1000) // 3) + +_redis: aioredis.Redis | None = None + + +def _client() -> aioredis.Redis: + global _redis + if _redis is None: + _redis = aioredis.from_url(REDIS_URL, decode_responses=True) + return _redis + + +def _key(sid: str) -> str: + return f"attached:session:{sid}" + + +def _displaced_channel(sid: str) -> str: + # a steal of `attached` publishes here so the displaced watcher tears down IMMEDIATELY + # (no tick wait). The token TTL probe remains a backstop if the message is missed. + return f"displaced:session:{sid}" + + +# release only if we still hold the token (never drop someone else's attach) +_RELEASE_LUA = ( + "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) " + "else return 0 end" +) + + +async def acquire_attached(sid: str, token: str) -> None: + # The `live` lock is the real gate (a run owns it); `attached` is just "who is watching", + # so take it unconditionally (a stale watcher loses the view, nothing else). Read the PRIOR + # holder first; if there was a DIFFERENT one, kick it (publish its token) so its watch unwinds + # at once — no tick wait. We publish the displaced token, not ours, so we never kick ourselves + # and an unrelated watcher ignores it (it only reacts to its own token being kicked). + r = _client() + prior = await r.get(_key(sid)) + await r.set(_key(sid), token, px=ATTACHED_TTL_MS) + print( + f"[acquire {sid[:8]}] tok={token[:8]} prior={(prior or '-')[:8]} " + f"{'KICK' if (prior and prior != token) else 'no-kick'}", + flush=True, + ) + if prior and prior != token: + await r.publish(_displaced_channel(sid), prior) + + +async def wait_displaced(sid: str, token: str) -> None: + """Block until OUR `token` is kicked off `attached` — i.e. a newer watcher acquired the lock and + published our (now-prior) token on the displacement channel. Lets a displaced watcher close with + no tick lag. The per-tick TTL probe is the backstop if the kick is missed (e.g. published before + we subscribed).""" + pubsub = _client().pubsub() + try: + await pubsub.subscribe(_displaced_channel(sid)) + async for msg in pubsub.listen(): + if msg.get("type") != "message": + continue + if msg.get("data") == token: # OUR token was kicked -> we've been displaced + print( + f"[displaced {sid[:8]}] OUR tok={token[:8]} was kicked", flush=True + ) + return + finally: + try: + await pubsub.unsubscribe(_displaced_channel(sid)) + await pubsub.aclose() + except Exception: + pass + + +async def refresh_attached(sid: str, token: str, ttl: bool = True) -> bool: + # Returns whether we STILL OWN the lock (a cheap ownership probe). False means another watcher + # STOLE it (attach is an unconditional SET), so the caller's watch must unwind — the displaced + # browser stops being the watcher. `ttl=True` also re-arms the TTL; pass ttl=False to probe + # ownership without resetting the expiry (so the steal check can run every tick, cheaply). + r = _client() + if await r.get(_key(sid)) != token: + return False + if ttl: + await r.pexpire(_key(sid), ATTACHED_TTL_MS) + return True + + +async def release_attached(sid: str, token: str) -> None: + try: + await _client().eval(_RELEASE_LUA, 1, _key(sid), token) + except Exception: + pass + + +async def status_many(sids: list[str]) -> dict[str, dict]: + """Read alive + attached for many sessions in one round-trip each. Returns + {sid: {"alive": bool, "attached": bool, "reattachable": bool}}.""" + if not sids: + return {} + r = _client() + keys = [f"alive:session:{s}" for s in sids] + [_key(s) for s in sids] + vals = await r.mget(keys) + n = len(sids) + out = {} + for i, s in enumerate(sids): + alive = vals[i] is not None + attached = vals[n + i] is not None + out[s] = { + "alive": alive, + "attached": attached, + "reattachable": alive and not attached, + } + return out diff --git a/sessions/demo/api/main.py b/sessions/demo/api/main.py new file mode 100644 index 0000000000..6d81e6ceef --- /dev/null +++ b/sessions/demo/api/main.py @@ -0,0 +1,592 @@ +import asyncio +import json +import os +import uuid + +import httpx +from fastapi import FastAPI, HTTPException, Request +from fastapi.responses import JSONResponse +from pydantic import BaseModel + +import db +import locks + +SIDECAR_URL = os.environ.get("SIDECAR_URL", "http://sidecar:8080") +S3_URL = os.environ.get("SEAWEEDFS_S3_URL", "http://seaweedfs:8333") +S3_KEY = os.environ.get("SEAWEEDFS_S3_ACCESS_KEY", "demo") +S3_SECRET = os.environ.get("SEAWEEDFS_S3_SECRET_KEY", "demosecret") +S3_BUCKET = os.environ.get("SEAWEEDFS_S3_BUCKET", "demo") + +app = FastAPI(title="persistent-sessions demo") + + +@app.on_event("startup") +async def _startup(): + await db.init() + + +class Message(BaseModel): + role: str = "user" + content: str + + +class Inputs(BaseModel): + messages: list[Message] = [] + + +class Parameters(BaseModel): + # session dimensions — fixed at creation, ignored on resume (read back from the DB). + sandbox: str = "local" # where it runs: local | modal | e2b | daytona + harness: str = "claude" # coding agent: claude | codex | opencode | pi + provider: str = "anthropic" # LLM API: anthropic | openai + model: str | None = None # model id (keyed by provider) + reasoning: str = "none" # thoughtLevel: none | low | medium | high + + +class RequestData(BaseModel): + inputs: Inputs = Inputs() + parameters: Parameters = Parameters() + + +class InvokeBody(BaseModel): + # Control-plane envelope. `data` carries the work (a prompt + its parameters); `force` + # is the cross-cutting "ENFORCE over another tab" knob. The DATA/FORCE matrix is the whole + # protocol: + # data + msg, force=F -> SEND (409 if a run is alive) + # data + msg, force=T -> STEER (enforce: cancel the holder, run the new prompt) + # data=None, force=F -> CANCEL (cancel the alive holder, run nothing) + # data=None, force=T -> ATTACH (enforce: steal `attached`, watch a live run) + # (client closes conn) -> DETACH (drop `attached`, run keeps going) + # The force=T row is the ENFORCEMENT pair (steer, attach). A caller that doesn't support force + # still gets send / cancel / detach — the meaningful, non-contentious actions. We'd rather lose + # attach than cancel, so cancel is the force=F control and attach the force=T one. + # data=None means "no work, control only" — distinct from data with EMPTY inputs, which is + # a real (different) payload and must NOT be hijacked as a control signal. + session_id: uuid.UUID | None = None + data: RequestData | None = None + force: bool = False + + +def _runner_for(sandbox: str) -> str: + # runner is derived, not chosen: local container vs rivet cloud sandbox. + return "local" if sandbox == "local" else "rivet" + + +def _response( + sid: str, + *, + status: str, + text: str | None = None, + stop_reason: str | None = None, + events: list | None = None, + extra: dict | None = None, +) -> dict: + """The Response envelope — mirror of the Request. The final output is the LAST element of + data.outputs.messages; data.outputs.events is the batch event list (empty for control calls). + `status` is the control/run disposition (done | detached | cancelled | attached | ended | …).""" + messages = [] + if text is not None or stop_reason is not None: + messages.append( + {"role": "assistant", "content": text or "", "stop_reason": stop_reason} + ) + out = { + "session_id": sid, + "status": status, + "data": {"outputs": {"messages": messages, "events": events or []}}, + } + if extra: + out.update(extra) + return out + + +def _prompt_of(body: InvokeBody) -> str | None: + # The prompt is data.inputs.messages[0].content. `data is None` is the control-plane signal + # (no work, intent only); EMPTY inputs is a real-but-different payload, NOT a control signal. + if body.data is None: + return None + msgs = body.data.inputs.messages + return msgs[0].content if msgs else None + + +async def _await_displaced(sid: str, token: str, flag: asyncio.Event) -> None: + """Set `flag` the moment another watcher steals `attached` from `token` (Redis pub/sub).""" + try: + await locks.wait_displaced(sid, token) + flag.set() + except asyncio.CancelledError: + raise + except Exception: + pass # backstop tick still catches the steal + + +async def _watch_attached(sid: str, request: Request, source, token: str | None = None): + """Hold `attached` for this browser and drive `source` (an async iterator of events) until it + ends OR the browser disconnects. On disconnect we drop `attached` and stop — the run and its + persistence are sidecar-side and keep going (detach must never cancel). Returns the final + {stop_reason, error, text, events} if the source ran to completion, or None if we detached + first. `text` = the last agent_message's text (the final output); `events` = the view events. + + Pass `token` to ADOPT an already-acquired attach lock (the steer path grabs `attached` up + front to displace the prior watcher before the slow force-cancel); otherwise acquire here.""" + if token is None: + token = str(uuid.uuid4()) + await locks.acquire_attached(sid, token) + result = None + events: list = [] + text = "" + # A steal of `attached` PUBLISHES a displacement kick; this background task flips the event the + # instant it arrives, so a displaced watcher closes with NO tick lag. The per-tick token probe + # below stays as a backstop for the small window before this subscription is live. + displaced = asyncio.Event() + displaced_task = asyncio.create_task(_await_displaced(sid, token, displaced)) + # ONE persistent pull of the next event; we await it WITHOUT cancelling on timeout (cancelling + # a half-read httpx stream corrupts it and ends the watch early). On timeout we just loop back + # to re-check disconnect/displaced, leaving the same pending pull in flight for next time. + ait = source.__aiter__() + evt_task = asyncio.ensure_future(ait.__anext__()) + displaced_wait = asyncio.ensure_future(displaced.wait()) + print(f"[watch {sid[:8]}] START tok={token[:8]}", flush=True) + try: + last_refresh = 0.0 + # Short timeout so we still wake to check disconnect even when the run produces events + # SLOWLY (e.g. codex appending one line per tool call). The displacement kick is handled + # out-of-band by `displaced`, not by this timeout. + while True: + now = asyncio.get_event_loop().time() + # check ownership (cheap GET) as a backstop for a missed kick. Only re-arm the TTL on + # the slower refresh cadence. + do_refresh = now - last_refresh >= locks.ATTACHED_REFRESH_S + if not await locks.refresh_attached(sid, token, ttl=do_refresh): + print( + f"[watch {sid[:8]}] BREAK lost-token (displaced via TTL probe)", + flush=True, + ) + break + if do_refresh: + last_refresh = now + if await request.is_disconnected(): + print(f"[watch {sid[:8]}] BREAK client-disconnected", flush=True) + break # browser left -> detach (run + persistence continue server-side) + # race the (persistent) next-event pull against the displacement kick. + done_set, _ = await asyncio.wait( + {evt_task, displaced_wait}, + timeout=1.0, + return_when=asyncio.FIRST_COMPLETED, + ) + if displaced_wait in done_set: + print(f"[watch {sid[:8]}] BREAK displaced-kick", flush=True) + break # someone stole `attached` -> tear down at once + if evt_task not in done_set: + continue # timeout, no event yet -> keep the SAME pull in flight, re-check above + try: + evt = evt_task.result() + except StopAsyncIteration: + print( + f"[watch {sid[:8]}] BREAK stream-ended (StopAsyncIteration)", + flush=True, + ) + break + evt_task = asyncio.ensure_future(ait.__anext__()) # arm the next pull + if evt.get("_done"): + result = { + "stop_reason": evt.get("stop_reason"), + "error": evt.get("error"), + } + continue + if not evt or evt.get("_sandbox_id") is not None or "_sandbox_id" in evt: + continue + events.append(evt) + if evt.get("session_update") == "agent_message": + t = ( + evt.get("payload", {}) + .get("params", {}) + .get("update", {}) + .get("content", {}) + .get("text", "") + ) + if t: + text = t + finally: + print( + f"[watch {sid[:8]}] END tok={token[:8]} displaced={displaced.is_set()} " + f"result={result is not None} nevents={len(events)}", + flush=True, + ) + evt_task.cancel() + displaced_wait.cancel() + displaced_task.cancel() + await locks.release_attached(sid, token) + if result is not None: + result["text"], result["events"] = text, events + return result + + +async def _attach_poll(sid: str): + """ATTACH source: poll the durable transcript while the run stays alive (no sidecar call). + Yields a synthetic _done once `alive` clears, so _watch_attached unwinds like a real run.""" + while True: + await asyncio.sleep(locks.ATTACHED_REFRESH_S) + st = (await locks.status_many([sid])).get(sid, {}) + if not st.get("alive"): + yield {"_done": True, "stop_reason": "ended"} + return + yield {} # tick: keeps the loop alive so the disconnect check + refresh run + + +@app.post("/invoke") +async def invoke(body: InvokeBody, request: Request): + prompt = _prompt_of(body) + control = body.data is None # no work, control plane only (cancel / attach) + _sid = str(body.session_id)[:8] if body.session_id else "new" + _kind = ( + "attach" + if (control and body.force) + else "cancel" + if control + else "steer" + if body.force + else "send" + ) + print(f"[invoke {_sid}] {_kind} (control={control} force={body.force})", flush=True) + + # CONTROL PLANE (data is None): no session is created, no prompt runs. + if control: + if body.session_id is None: + raise HTTPException( + 400, "control-plane invoke (data=null) requires a session_id" + ) + sid = str(body.session_id) + if await db.get_session(sid) is None: + raise HTTPException(404, "no such session") + st = (await locks.status_many([sid])).get(sid, {}) + if not body.force: + # CANCEL (force=F): cancel the alive holder, run nothing. Cancel is a non-enforcement + # control — it interrupts THIS session's own run, it doesn't override another tab — so + # it lives on the force=F side and survives for callers without force support. (The + # sidecar's own `force:True` below is its alive-lock "interrupt the holder" knob, a + # different layer from our client-facing flag.) + if not st.get("alive"): + return _response(sid, status="no_live_run") + async with httpx.AsyncClient(timeout=60) as client: + r = await client.post( + f"{SIDECAR_URL}/run", + json={"session_id": sid, "data": None, "force": True}, + ) + ok = r.status_code == 200 + return _response(sid, status="cancelled" if ok else "cancel_failed") + # ATTACH (force=T): adopt a live run's watch. `attached` is just "who is watching" (not a run + # gate), so attach STEALS it — the prior watcher merely loses the live view. That steal is an + # ENFORCEMENT over another tab, which is why attach is the force=T control (and the first + # thing a no-force caller loses; cancel is kept instead). + if not st.get("alive"): + return _response(sid, status="no_live_run") + # acquire (steal) `attached` up front, then watch — adopting the token so the loop refreshes + # this one instead of grabbing another. + token = str(uuid.uuid4()) + await locks.acquire_attached(sid, token) + await _watch_attached(sid, request, _attach_poll(sid), token=token) + st2 = (await locks.status_many([sid])).get(sid, {}) + if st2.get("alive"): + return _response(sid, status="detached") # we left, run continues + return _response(sid, status="ended", stop_reason="ended") + + # DATA PLANE: a prompt to run (send / force-takeover). + # null id -> mint + create with requested dimensions; + # provided -> resume; sandbox/harness/provider/model/reasoning are FIXED to creation. + p = body.data.parameters + sandbox_id = None + if body.session_id is None or (await db.get_session(str(body.session_id))) is None: + sid = str(body.session_id) if body.session_id else str(uuid.uuid4()) + sandbox, harness = p.sandbox, p.harness + provider, model, reasoning = p.provider, p.model, p.reasoning + await db.create_session( + sid, + f"/work/{sid}", + f"{S3_BUCKET}/{sid}/", + sandbox, + harness, + runner=_runner_for(sandbox), + provider=provider, + model=model, + reasoning=reasoning, + ) + else: + sid = str(body.session_id) + row = await db.get_session(sid) + sandbox, harness = row["sandbox"], row["harness"] + provider, model, reasoning = row["provider"], row["model"], row["reasoning"] + sandbox_id = row["sandbox_id"] + + # STEER = detach A, attach B, cancel A, run B. On a force takeover, grab `attached` for THIS + # tab NOW — before the sidecar's force-cancel (which can take seconds to re-acquire `alive`). + # acquire_attached is an unconditional SET, so it displaces the prior watcher (A) immediately; + # without this, A keeps `attached` for the whole cancel window and B looks unattached. We then + # hand this token to _watch_attached so it adopts (doesn't re-acquire) it. + attach_token = None + if body.force: + attach_token = str(uuid.uuid4()) + await locks.acquire_attached(sid, attach_token) + + done = None + async with httpx.AsyncClient(timeout=None) as client: + async with client.stream( + "POST", + f"{SIDECAR_URL}/run", + json={ + "session_id": sid, + "prompt": prompt, + "sandbox": sandbox, + "harness": harness, + "provider": provider, + "model": model, + "reasoning": reasoning, + "sandbox_id": sandbox_id, + "force": body.force, + }, + ) as resp: + # 409 = a run is already live for this session (and force wasn't set). The sidecar + # body says WHICH kind of busy: a detached live run is `reattachable` (the driving + # client left), an attached one is being watched. Surface that so the UI can offer + # reattach vs. force. (httpx must read the streamed 409 body before we use it.) + if resp.status_code == 409: + # takeover failed (e.g. cancel timed out) — drop the attach we optimistically took + if attach_token: + await locks.release_attached(sid, attach_token) + await resp.aread() + info = json.loads(resp.text or "{}") + return JSONResponse( + status_code=409, + content=_response( + sid, + status="in_use", + extra={ + "code": "in_use", + "alive": info.get("alive", True), + "attached": info.get("attached", False), + "reattachable": info.get("reattachable", False), + "detail": ( + "session in use — detached, reattachable" + if info.get("reattachable") + else "session in use — another tab is attached" + ), + }, + ), + ) + + # The run started: hold `attached` while this browser drains the live view. The view + # is disposable (persistence is producer-driven via /events); we walk it only for the + # final stop_reason, and detach (drop `attached`, keep the run) on browser disconnect. + async def _ndjson(): + async for line in resp.aiter_lines(): + line = line.strip() + if line: + yield json.loads(line) + + done = await _watch_attached(sid, request, _ndjson(), token=attach_token) + + if done and done.get("error"): + raise HTTPException(status_code=500, detail=done["error"]) + if not done: + # we returned before the run finished (browser detached) — report detached, not done + return _response(sid, status="detached") + return _response( + sid, + status="done", + text=done.get("text"), + stop_reason=done.get("stop_reason"), + events=done.get("events"), + ) + + +class EventBody(BaseModel): + session_id: str + event_index: int | None = None + sender: str | None = None + session_update: str | None = None + payload: dict = {} + + +@app.post("/events") +async def ingest_event(body: EventBody): + # Producer-driven persistence: the sidecar POSTs every transcript event here as rivet + # produces it — independent of any /invoke client. This is the durable transcript write; + # /invoke no longer persists. Keeping the DB write here (not in the sidecar) keeps all SQL + # in one place. + await db.append_event( + body.session_id, + body.event_index, + body.sender, + body.session_update, + body.payload or {}, + ) + return {"ok": True} + + +class SandboxIdBody(BaseModel): + sandbox_id: str | None = None + + +@app.put("/sessions/{sid}/sandbox-id") +async def put_sandbox_id(sid: str, body: SandboxIdBody): + # The sidecar records the remote sandbox id (for resume) here, independent of the view + # stream, so a detached run still persists where it ran. null clears it (docker teardown). + await db.set_sandbox_id(sid, body.sandbox_id) + return {"ok": True} + + +@app.get("/sessions") +async def sessions(): + rows = await db.list_sessions() + # enrich with run-lock state: run_alive = a run is executing now; attached = a browser is + # watching it; reattachable = live but unwatched (a returning tab can adopt the stream). + # (db's own `live` is sandbox-aliveness for the kill badge — a different axis.) + st = await locks.status_many([r["id"] for r in rows]) + for r in rows: + s = st.get(r["id"], {}) + r["run_alive"] = s.get("alive", False) + r["attached"] = s.get("attached", False) + r["reattachable"] = s.get("reattachable", False) + return {"sessions": rows} + + +@app.delete("/sessions/{sid}/sandbox") +async def kill_sandbox(sid: str): + # Destroy the remote sandbox; the cwd stays durable in SeaweedFS, so the next + # /invoke spins a fresh sandbox and remounts the same prefix. + row = await db.get_session(sid) + if row is None: + raise HTTPException(404, "no such session") + if not row["sandbox_id"]: + return {"killed": None, "note": "no live sandbox for this session"} + # The sidecar /kill is idempotent (a sandbox already gone reports success). Clear the + # persisted sandbox_id regardless so the "live" badge / kill button don't get stranded + # on a dead sandbox; surface a sidecar failure as a note rather than blocking cleanup. + note = None + try: + async with httpx.AsyncClient(timeout=60) as client: + r = await client.post( + f"{SIDECAR_URL}/kill", + json={"sandbox": row["sandbox"], "sandbox_id": row["sandbox_id"]}, + ) + r.raise_for_status() + except httpx.HTTPError as e: + note = f"sidecar kill error (cleared anyway): {e}" + await db.set_sandbox_id(sid, None) + return {"killed": row["sandbox_id"], "note": note} + + +@app.delete("/sessions/{sid}") +async def delete_session(sid: str): + if not await db.session_exists(sid): + raise HTTPException(404, "no such session") + # 1) unmount + remove the cwd in the sandbox (best-effort; sandbox may be down) + try: + async with httpx.AsyncClient(timeout=20) as client: + await client.post(f"{SIDECAR_URL}/unmount", json={"session_id": sid}) + except httpx.HTTPError: + pass + # 2) delete the SeaweedFS prefix demo// + await _delete_s3_prefix(sid) + # 3) delete the Postgres rows (transcripts + session) + await db.delete_session(sid) + return {"deleted": sid} + + +async def _delete_s3_prefix(sid: str): + import aioboto3 + + s = aioboto3.Session() + async with s.client( + "s3", + endpoint_url=S3_URL, + aws_access_key_id=S3_KEY, + aws_secret_access_key=S3_SECRET, + region_name="us-east-1", + ) as s3: + resp = await s3.list_objects_v2(Bucket=S3_BUCKET, Prefix=f"{sid}/") + keys = [{"Key": o["Key"]} for o in resp.get("Contents", [])] + if keys: + await s3.delete_objects(Bucket=S3_BUCKET, Delete={"Objects": keys}) + + +@app.get("/sessions/{sid}/transcript") +async def transcript(sid: str): + if not await db.session_exists(sid): + raise HTTPException(404, "no such session") + return {"session_id": sid, "events": await db.get_transcript(sid)} + + +# The sandbox-agent SDK's per-session record (its SessionPersistDriver state). The sidecar +# spins a fresh SDK client every /run, so it round-trips this record through here to make +# resumeOrCreateSession actually resume (and replay the transcript) instead of starting cold. +@app.get("/sessions/{sid}/state") +async def get_state(sid: str): + return {"record": await db.get_session_state(sid)} + + +@app.put("/sessions/{sid}/state") +async def put_state(sid: str, body: dict): + if not await db.session_exists(sid): + raise HTTPException(404, "no such session") + await db.set_session_state(sid, body) + return {"ok": True} + + +@app.get("/sessions/{sid}/files") +async def files(sid: str, read: str | None = None): + # Read the cwd straight from SeaweedFS (works whether or not the sandbox is up). + import aioboto3 + + s = aioboto3.Session() + async with s.client( + "s3", + endpoint_url=S3_URL, + aws_access_key_id=S3_KEY, + aws_secret_access_key=S3_SECRET, + region_name="us-east-1", + ) as s3: + if read is not None: + try: + obj = await s3.get_object(Bucket=S3_BUCKET, Key=f"{sid}/{read}") + body = await obj["Body"].read() + return {"path": read, "content": body.decode("utf-8", "replace")} + except s3.exceptions.NoSuchKey: + raise HTTPException(404, "no such file") + resp = await s3.list_objects_v2(Bucket=S3_BUCKET, Prefix=f"{sid}/") + return { + "source": "seaweedfs", + "files": [ + {"path": o["Key"][len(sid) + 1 :], "size": o["Size"]} + for o in resp.get("Contents", []) + if o["Key"] != f"{sid}/" + ], + } + + +@app.delete("/sessions/{sid}/files") +async def delete_file(sid: str, path: str): + # Delete a file (or a whole folder prefix, trailing '/') from the cwd in SeaweedFS. The + # change lands in the durable store; the next sandbox sees it via the geesefs mount. + import aioboto3 + + s = aioboto3.Session() + async with s.client( + "s3", + endpoint_url=S3_URL, + aws_access_key_id=S3_KEY, + aws_secret_access_key=S3_SECRET, + region_name="us-east-1", + ) as s3: + prefix = f"{sid}/{path}" + resp = await s3.list_objects_v2(Bucket=S3_BUCKET, Prefix=prefix) + keys = [{"Key": o["Key"]} for o in resp.get("Contents", [])] + if not keys: + raise HTTPException(404, "no such file or folder") + await s3.delete_objects(Bucket=S3_BUCKET, Delete={"Objects": keys}) + return {"deleted": path, "count": len(keys)} + + +# Static playground UI (filesystem viewer + invoke form + session list). +from fastapi.staticfiles import StaticFiles # noqa: E402 + +app.mount("/", StaticFiles(directory="static", html=True), name="static") diff --git a/sessions/demo/api/requirements.txt b/sessions/demo/api/requirements.txt new file mode 100644 index 0000000000..2183579715 --- /dev/null +++ b/sessions/demo/api/requirements.txt @@ -0,0 +1,6 @@ +fastapi==0.115.6 +uvicorn[standard]==0.34.0 +asyncpg==0.30.0 +httpx==0.28.1 +aioboto3==13.4.0 +redis==5.2.1 diff --git a/sessions/demo/api/static/index.html b/sessions/demo/api/static/index.html new file mode 100644 index 0000000000..a3e0314ce7 --- /dev/null +++ b/sessions/demo/api/static/index.html @@ -0,0 +1,943 @@ + + + + +persistent-sessions playground + + + +
+
+ +
+

Parameters

+ + + + + +
+ +
+
+ + +
+
+
+ Filesystem +
+
+
+
select a file
+
+
+
+
+ Transcript +
+
+
+
+
+ +
+
+
+
+
+
+ +
+ +
+
+ +
+
+
+
+ + + diff --git a/sessions/demo/bin/geesefs b/sessions/demo/bin/geesefs new file mode 100755 index 0000000000..0f7c9dc807 Binary files /dev/null and b/sessions/demo/bin/geesefs differ diff --git a/sessions/demo/daytona-smoketest/durability.mjs b/sessions/demo/daytona-smoketest/durability.mjs new file mode 100644 index 0000000000..38527dc5b5 --- /dev/null +++ b/sessions/demo/daytona-smoketest/durability.mjs @@ -0,0 +1,43 @@ +// Definitive Daytona durability test. Write the mount+write script to a FILE on the +// sandbox (avoids nested-quote breakage), run it detached, poll. Host then verifies the +// object actually landed in SeaweedFS (the real proof). Leaves the object behind. +import { Daytona } from "@daytonaio/sdk"; +const TUNNEL = process.env.TUNNEL; +const SID = process.env.SID || "daytona-durable"; +const GEESEFS = "https://github.com/yandex-cloud/geesefs/releases/latest/download/geesefs-linux-amd64"; +const daytona = new Daytona({ apiKey: process.env.DAYTONA_API_KEY }); +async function exec(sbx, cmd, t = 60) { + const r = await sbx.process.executeCommand(cmd, undefined, undefined, t); + console.log(`$ ${cmd.slice(0, 70)}\n exit=${r.exitCode} ${String(r.result || "").trim().slice(0, 400)}`); + return r; +} +const RUNNER = `#!/bin/bash +set -x +mkdir -p /root/work +AWS_ACCESS_KEY_ID=demo AWS_SECRET_ACCESS_KEY=demosecret \\ + geesefs --endpoint ${TUNNEL} --region us-east-1 --no-detect --fsync-on-close \\ + --debug_s3 -o allow_other demo:${SID} /root/work >/tmp/mount.log 2>&1 +echo "mount_exit=$?" >>/tmp/result +sleep 3 +mountpoint -q /root/work && echo IS_MOUNT >>/tmp/result || echo NOT_MOUNT >>/tmp/result +echo 'daytona durable write' > /root/work/hello.md 2>>/tmp/result && echo WROTE >>/tmp/result || echo WRITE_FAIL >>/tmp/result +sync +cat /root/work/hello.md >>/tmp/result 2>&1 && echo READBACK_OK >>/tmp/result || echo READBACK_FAIL >>/tmp/result +`; +const sbx = await daytona.create({ image: "debian:12.9" }, { timeout: 240 }); +console.log("sandbox:", sbx.id, "sid:", SID); +try { + await exec(sbx, "apt-get update -qq && apt-get install -y -qq curl ca-certificates fuse >/dev/null 2>&1; echo ready", 150); + await exec(sbx, `curl -fsSL -o /usr/local/bin/geesefs ${GEESEFS} && chmod +x /usr/local/bin/geesefs && echo ok`); + // write the runner via base64 to dodge all quoting + const b64 = Buffer.from(RUNNER).toString("base64"); + await exec(sbx, `echo ${b64} | base64 -d > /root/run.sh && chmod +x /root/run.sh && echo wrote-runner`); + await exec(sbx, `setsid bash /root/run.sh >/tmp/runner.log 2>&1 < /dev/null & echo "pid $!"`); + for (let i = 0; i < 9; i++) { + await new Promise((r) => setTimeout(r, 5000)); + const r = await exec(sbx, "echo '--result--'; cat /tmp/result 2>/dev/null; echo '--s3 log--'; grep -iE 'PUT |DEBUG|http|denied|signature|x-amz' /tmp/mount.log 2>/dev/null | tail -6"); + if (String(r.result || "").includes("READBACK")) { console.log(">>> ROUND-TRIP DONE"); break; } + } + console.log("=== mount.log tail ==="); + await exec(sbx, "tail -20 /tmp/mount.log 2>/dev/null"); +} finally { await daytona.delete(sbx); console.log("deleted"); } diff --git a/sessions/demo/daytona-smoketest/package-lock.json b/sessions/demo/daytona-smoketest/package-lock.json new file mode 100644 index 0000000000..2d6c8fc41e --- /dev/null +++ b/sessions/demo/daytona-smoketest/package-lock.json @@ -0,0 +1,2645 @@ +{ + "name": "app", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "dependencies": { + "@daytonaio/sdk": "^0.190.1" + } + }, + "node_modules/@aws-crypto/crc32": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/crc32/-/crc32-5.2.0.tgz", + "integrity": "sha512-nLbCWqQNgUiwwtFsen1AdzAtvuLRsQS8rYgMuxCrdKf9kOssamGLuPwyTY9wyYblNr9+1XM8v6zoDTPPSIeANg==", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-crypto/crc32c": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/crc32c/-/crc32c-5.2.0.tgz", + "integrity": "sha512-+iWb8qaHLYKrNvGRbiYRHSdKRWhto5XlZUEBwDjYNf+ly5SVYG6zEoYIdxvf5R3zyeP16w4PLBn3rH1xc74Rag==", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-crypto/sha1-browser": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha1-browser/-/sha1-browser-5.2.0.tgz", + "integrity": "sha512-OH6lveCFfcDjX4dbAvCFSYUjJZjDr/3XJ3xHtjn3Oj5b9RjojQo8npoLeA/bNwkOkrSQ0wgrHzXk4tDRxGKJeg==", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/supports-web-crypto": "^5.2.0", + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "@aws-sdk/util-locate-window": "^3.0.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-crypto/sha256-browser": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-browser/-/sha256-browser-5.2.0.tgz", + "integrity": "sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw==", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/sha256-js": "^5.2.0", + "@aws-crypto/supports-web-crypto": "^5.2.0", + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "@aws-sdk/util-locate-window": "^3.0.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-crypto/sha256-js": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-js/-/sha256-js-5.2.0.tgz", + "integrity": "sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA==", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-crypto/supports-web-crypto": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/supports-web-crypto/-/supports-web-crypto-5.2.0.tgz", + "integrity": "sha512-iAvUotm021kM33eCdNfwIN//F77/IADDSs58i+MDaOqFrVjZo9bAal0NK7HurRuWLLpF1iLX7gbWrjHjeo+YFg==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-crypto/util": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/util/-/util-5.2.0.tgz", + "integrity": "sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "^3.222.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-sdk/checksums": { + "version": "3.1000.8", + "resolved": "https://registry.npmjs.org/@aws-sdk/checksums/-/checksums-3.1000.8.tgz", + "integrity": "sha512-v0U9S7gBIme3OTgt1LdbAF4RpvavCc+4GK1+1xqAcqtbrHsEhjQo6R45LKcjhs/+WrRJij1Y0Gztw7QPAIeUfA==", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/crc32": "5.2.0", + "@aws-crypto/crc32c": "5.2.0", + "@aws-crypto/util": "5.2.0", + "@aws-sdk/core": "^3.974.23", + "@aws-sdk/types": "^3.973.13", + "@smithy/core": "^3.24.6", + "@smithy/types": "^4.14.3", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/client-s3": { + "version": "3.1075.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.1075.0.tgz", + "integrity": "sha512-h1A6nIl1YX6Y45enGsTK7ef3ZrOnBiQJ1qF5R2K/nMWfsu6A9mc2Y5T66nxerABzyjjyyvign3MrzafnFoQKmA==", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/sha1-browser": "5.2.0", + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "^3.974.23", + "@aws-sdk/credential-provider-node": "^3.972.58", + "@aws-sdk/middleware-flexible-checksums": "^3.974.33", + "@aws-sdk/middleware-sdk-s3": "^3.972.54", + "@aws-sdk/signature-v4-multi-region": "^3.996.35", + "@aws-sdk/types": "^3.973.13", + "@smithy/core": "^3.24.6", + "@smithy/fetch-http-handler": "^5.4.6", + "@smithy/node-http-handler": "^4.7.6", + "@smithy/types": "^4.14.3", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/core": { + "version": "3.974.23", + "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.974.23.tgz", + "integrity": "sha512-MiWR/uWjxjFXGzrE0Ghc5lWxUxzHsUWFhV+OX7M4cR9SrmrnZs6TXavnCWnzzdwJeFri34xQo81rvGNzK3c4BQ==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "^3.973.13", + "@aws-sdk/xml-builder": "^3.972.31", + "@aws/lambda-invoke-store": "^0.2.2", + "@smithy/core": "^3.24.6", + "@smithy/signature-v4": "^5.4.6", + "@smithy/types": "^4.14.3", + "bowser": "^2.11.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-env": { + "version": "3.972.49", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.972.49.tgz", + "integrity": "sha512-liB3yQNHCM9k/gu/w36XHMKPluT7HTlnGUhRbBGSISDQkcr/Sy1zsZabiuvQj8WG5yW573u9RehrBvvnIQ9OEQ==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "^3.974.23", + "@aws-sdk/types": "^3.973.13", + "@smithy/core": "^3.24.6", + "@smithy/types": "^4.14.3", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-http": { + "version": "3.972.51", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.972.51.tgz", + "integrity": "sha512-XET0H2oofciJ5lMRWNIvRjAP7Q3wv2XT+JtJJEdhPWUMwe3TvQ9qcxonpu7vXmNngncvFpi4E2It+Tamas/naA==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "^3.974.23", + "@aws-sdk/types": "^3.973.13", + "@smithy/core": "^3.24.6", + "@smithy/fetch-http-handler": "^5.4.6", + "@smithy/node-http-handler": "^4.7.6", + "@smithy/types": "^4.14.3", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-ini": { + "version": "3.972.56", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.972.56.tgz", + "integrity": "sha512-IAmc61hbgQiHht9U3x0tnRwz0lzdwOwD/i9voRgdJrKamF+JtmrBOsW9GwB7mfFonNWOWL4qARWYrF8veEMe3w==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "^3.974.23", + "@aws-sdk/credential-provider-env": "^3.972.49", + "@aws-sdk/credential-provider-http": "^3.972.51", + "@aws-sdk/credential-provider-login": "^3.972.55", + "@aws-sdk/credential-provider-process": "^3.972.49", + "@aws-sdk/credential-provider-sso": "^3.972.55", + "@aws-sdk/credential-provider-web-identity": "^3.972.55", + "@aws-sdk/nested-clients": "^3.997.23", + "@aws-sdk/types": "^3.973.13", + "@smithy/core": "^3.24.6", + "@smithy/credential-provider-imds": "^4.3.7", + "@smithy/types": "^4.14.3", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-login": { + "version": "3.972.55", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-login/-/credential-provider-login-3.972.55.tgz", + "integrity": "sha512-hBBkANo3cDn+h2qxxzER4a+J8JCO9o9Z/YYmU7iky6AcaarX5RRdRcHNC6SLdwY0vAXQygn6soUbDqPn3GghaA==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "^3.974.23", + "@aws-sdk/nested-clients": "^3.997.23", + "@aws-sdk/types": "^3.973.13", + "@smithy/core": "^3.24.6", + "@smithy/types": "^4.14.3", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-node": { + "version": "3.972.58", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.972.58.tgz", + "integrity": "sha512-OyCLVmSI7pZO8hxwNVX6pXhTVlJqRBTp+ijdEfJSUj0RyjHnF602OfAarOzGq6wkGodeFkYBt8MmJ6A6ycRgWw==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/credential-provider-env": "^3.972.49", + "@aws-sdk/credential-provider-http": "^3.972.51", + "@aws-sdk/credential-provider-ini": "^3.972.56", + "@aws-sdk/credential-provider-process": "^3.972.49", + "@aws-sdk/credential-provider-sso": "^3.972.55", + "@aws-sdk/credential-provider-web-identity": "^3.972.55", + "@aws-sdk/types": "^3.973.13", + "@smithy/core": "^3.24.6", + "@smithy/credential-provider-imds": "^4.3.7", + "@smithy/types": "^4.14.3", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-process": { + "version": "3.972.49", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.972.49.tgz", + "integrity": "sha512-C8h36lBuC/RnBSsjlO+dn6xZm3KbAl5vpJaVPAfQnMmz2/OISmKOc8XZcqMQgO2ADwBYNRMM6Kf3vz9G/TulMQ==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "^3.974.23", + "@aws-sdk/types": "^3.973.13", + "@smithy/core": "^3.24.6", + "@smithy/types": "^4.14.3", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-sso": { + "version": "3.972.55", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.972.55.tgz", + "integrity": "sha512-1FkOz74Ea5QGS9jtIoXp55T/IkSS3spv+nLTT07fRY/+T5xmEOqaYBVIaEmX4zTNvbV6g2lrtlaVKWEoNyJt3w==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "^3.974.23", + "@aws-sdk/nested-clients": "^3.997.23", + "@aws-sdk/token-providers": "3.1074.0", + "@aws-sdk/types": "^3.973.13", + "@smithy/core": "^3.24.6", + "@smithy/types": "^4.14.3", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-web-identity": { + "version": "3.972.55", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.972.55.tgz", + "integrity": "sha512-g2BoECD1q01kTPByi56+VLVvdWDzMkKIcr77qixpqH0okw2t0U5CoPv+6S8v/D1Y2Wa6QKKtn6XAtDzP+Kfpvg==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "^3.974.23", + "@aws-sdk/nested-clients": "^3.997.23", + "@aws-sdk/types": "^3.973.13", + "@smithy/core": "^3.24.6", + "@smithy/types": "^4.14.3", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/lib-storage": { + "version": "3.1075.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/lib-storage/-/lib-storage-3.1075.0.tgz", + "integrity": "sha512-Npdac3/Fv994iCdFFeqloPel+95Zv6dRiRUpfey6W/CqpB/QdnYP60U4YBhBgJj6V5020Pm3ad0HV4WzCE5hHQ==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/core": "^3.24.6", + "@smithy/types": "^4.14.3", + "buffer": "5.6.0", + "events": "3.3.0", + "stream-browserify": "3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "@aws-sdk/client-s3": "^3.1075.0" + } + }, + "node_modules/@aws-sdk/middleware-flexible-checksums": { + "version": "3.974.33", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.974.33.tgz", + "integrity": "sha512-qMgQSPemQq2/eW/e/0+SpY4kYR5L7dUgBiVdEc5bd+ztHNv07ZMYiI+sTiir3TgKndFfglSw/VFi7oZJ6bZ63g==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/checksums": "^3.1000.8", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/middleware-sdk-s3": { + "version": "3.972.54", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.972.54.tgz", + "integrity": "sha512-GDfDQ0gwLFRKN9gWIKcmVrHJ3e7XagnY7N1LLzMVNgnOnuY7f/ALgmy3CuBjosWD95T/Z6e+gs1IeWmLPkyLKQ==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "^3.974.23", + "@aws-sdk/signature-v4-multi-region": "^3.996.35", + "@aws-sdk/types": "^3.973.13", + "@smithy/core": "^3.24.6", + "@smithy/types": "^4.14.3", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/nested-clients": { + "version": "3.997.23", + "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.997.23.tgz", + "integrity": "sha512-gO93ZPsI2bxeFZD42f1/qjDw6FAZkNZcKRO94LIiT03fzOmcJ9e/tunxjVjA1Rl69ClmVJzz8H3G9CdKef10PA==", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "^3.974.23", + "@aws-sdk/signature-v4-multi-region": "^3.996.35", + "@aws-sdk/types": "^3.973.13", + "@smithy/core": "^3.24.6", + "@smithy/fetch-http-handler": "^5.4.6", + "@smithy/node-http-handler": "^4.7.6", + "@smithy/types": "^4.14.3", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/signature-v4-multi-region": { + "version": "3.996.35", + "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.996.35.tgz", + "integrity": "sha512-6L/VWs+Wch2stHemCGTmUNqKLMzURxQDK5boNG3Jn3kAOp71meDUuS5sbObpEvFxHDq0uWeSLFDNSYsjNt+Dlg==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "^3.973.13", + "@smithy/signature-v4": "^5.4.6", + "@smithy/types": "^4.14.3", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/token-providers": { + "version": "3.1074.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.1074.0.tgz", + "integrity": "sha512-pv80IzgGW4RnXWtft692chZOM9i6PhebVsLCcnaM4dBEPZva2fE6FXAHs76G7Rc7s3yGyX/68G0nZMrUy+Vmpg==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "^3.974.23", + "@aws-sdk/nested-clients": "^3.997.23", + "@aws-sdk/types": "^3.973.13", + "@smithy/core": "^3.24.6", + "@smithy/types": "^4.14.3", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/types": { + "version": "3.973.13", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.973.13.tgz", + "integrity": "sha512-pEHZqRkAlHfnfAU9tK+WpKv/gBNjGJrHMgA3A0iYRGyswBS2t0pfez+lWlwktb3Bqa0ovh7w/QJTFwp3fDxLNg==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.14.3", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/util-locate-window": { + "version": "3.965.8", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.965.8.tgz", + "integrity": "sha512-uUbMs1cBZPafD0ohUj6EwNf0fPZ534NvBxHox4hjX+0Rxq5paSYUem7+hi833pYrzrcnBATKIYpR02MDXT5M9g==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/xml-builder": { + "version": "3.972.31", + "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.972.31.tgz", + "integrity": "sha512-SzE4Pgyl+hDF+BuyuzxUSpwnuUu9lJuO1YGgteG89/4Qv0+2IQiVQqdbPV32IozLvXWQChPQcdkk/sKvb1QHiQ==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.14.3", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws/lambda-invoke-store": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/@aws/lambda-invoke-store/-/lambda-invoke-store-0.2.4.tgz", + "integrity": "sha512-iY8yvjE0y651BixKNPgmv1WrQc+GZ142sb0z4gYnChDDY2YqI4P/jsSopBWrKfAt7LOJAkOXt7rC/hms+WclQQ==", + "license": "Apache-2.0", + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@daytona/api-client": { + "version": "0.190.1", + "resolved": "https://registry.npmjs.org/@daytona/api-client/-/api-client-0.190.1.tgz", + "integrity": "sha512-69/J9B1YuJIVa4DT4/r5zSzy6vKpV7Cz2l6xZYhYyAjiLunqn7nlAxbDOXE08pmhuOK38C/8g/4SeBHdkARFQg==", + "license": "Apache-2.0", + "dependencies": { + "axios": "^1.6.1" + } + }, + "node_modules/@daytona/toolbox-api-client": { + "version": "0.190.1", + "resolved": "https://registry.npmjs.org/@daytona/toolbox-api-client/-/toolbox-api-client-0.190.1.tgz", + "integrity": "sha512-vObFluXvY7tJpU4en58TrZHdjueUDpTD7yZlDnYHypPUdGsTUdyWbAJUOSs0WyV9HHWBzwEzauOdif0e5Xytkg==", + "license": "Apache-2.0", + "dependencies": { + "axios": "^1.6.1" + } + }, + "node_modules/@daytonaio/sdk": { + "version": "0.190.1", + "resolved": "https://registry.npmjs.org/@daytonaio/sdk/-/sdk-0.190.1.tgz", + "integrity": "sha512-mLGLZWFVvwLfhFpdMQG1OvfskQL/04go+iXC81n1Xcnkd6qR/vhVLDuIakN0/dn55zIGjhW7f/8U4PozLSHeBg==", + "deprecated": "Moved to @daytona/sdk, same API, no breaking changes. Please update: npm uninstall @daytonaio/sdk && npm i @daytona/sdk", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/client-s3": "^3.787.0", + "@aws-sdk/lib-storage": "^3.798.0", + "@daytona/api-client": "0.190.1", + "@daytona/toolbox-api-client": "0.190.1", + "@iarna/toml": "^2.2.5", + "@opentelemetry/api": "^1.9.0", + "@opentelemetry/exporter-trace-otlp-http": "^0.217.0", + "@opentelemetry/instrumentation-http": "^0.217.0", + "@opentelemetry/otlp-exporter-base": "0.217.0", + "@opentelemetry/resources": "2.7.1", + "@opentelemetry/sdk-node": "^0.217.0", + "@opentelemetry/sdk-trace-base": "^2.7.1", + "@opentelemetry/semantic-conventions": "^1.40.0", + "axios": "^1.15.2", + "busboy": "^1.0.0", + "dotenv": "^17.0.1", + "expand-tilde": "^2.0.2", + "fast-glob": "^3.3.0", + "form-data": "^4.0.4", + "isomorphic-ws": "^5.0.0", + "pathe": "^2.0.3", + "shell-quote": "^1.8.2", + "tar": "^7.5.11" + } + }, + "node_modules/@grpc/grpc-js": { + "version": "1.14.4", + "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.14.4.tgz", + "integrity": "sha512-k9Dj3DV/itK9D06Y8f190Qgop7/Ui+D0njFV3LHMPwPT75DpXLQohE9Wmz0QElrJnzsjB7KPWiKJbOl7IPDArQ==", + "license": "Apache-2.0", + "dependencies": { + "@grpc/proto-loader": "^0.8.0", + "@js-sdsl/ordered-map": "^4.4.2" + }, + "engines": { + "node": ">=12.10.0" + } + }, + "node_modules/@grpc/proto-loader": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.8.1.tgz", + "integrity": "sha512-wtF6h+DY6M3YaDBPAmvuuA6jV8Sif9MjtOI5euKFWRgCDl5PeDpPsHR9u2l6St5ceY8AZgoNDww5+HvEsXFsGg==", + "license": "Apache-2.0", + "dependencies": { + "lodash.camelcase": "^4.3.0", + "long": "^5.0.0", + "protobufjs": "^7.5.5", + "yargs": "^17.7.2" + }, + "bin": { + "proto-loader-gen-types": "build/bin/proto-loader-gen-types.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@grpc/proto-loader/node_modules/protobufjs": { + "version": "7.6.4", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.6.4.tgz", + "integrity": "sha512-RJJPTTpvFfHcWLkIa2JFWK4XvtSzS0yEWDmunqHXli1h3JlkbcQZXDZdcWxv+JK3Xsl5/UFDPZ0iGm7DAengYw==", + "hasInstallScript": true, + "license": "BSD-3-Clause", + "dependencies": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.5", + "@protobufjs/eventemitter": "^1.1.1", + "@protobufjs/fetch": "^1.1.1", + "@protobufjs/float": "^1.0.2", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.1", + "@types/node": ">=13.7.0", + "long": "^5.3.2" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/@iarna/toml": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/@iarna/toml/-/toml-2.2.5.tgz", + "integrity": "sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg==", + "license": "ISC" + }, + "node_modules/@isaacs/fs-minipass": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", + "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==", + "license": "ISC", + "dependencies": { + "minipass": "^7.0.4" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@js-sdsl/ordered-map": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/@js-sdsl/ordered-map/-/ordered-map-4.4.2.tgz", + "integrity": "sha512-iUKgm52T8HOE/makSxjqoWhe95ZJA1/G1sYsGev2JDKUSS14KAgg1LHb+Ba+IPow0xflbnSkOsZcO08C7w1gYw==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/js-sdsl" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@opentelemetry/api": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.1.tgz", + "integrity": "sha512-gLyJlPHPZYdAk1JENA9LeHejZe1Ti77/pTeFm/nMXmQH/HFZlcS/O2XJB+L8fkbrNSqhdtlvjBVjxwUYanNH5Q==", + "license": "Apache-2.0", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@opentelemetry/api-logs": { + "version": "0.217.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.217.0.tgz", + "integrity": "sha512-Cdq0jW2lknrNfrAm92MyEAvpe2cRsKjdnQLHUL6xRA4IVUnsWx6P65E7NcUO0Y+L4w1Aee5iV8FvjSwd+lrs9A==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api": "^1.3.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@opentelemetry/configuration": { + "version": "0.217.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/configuration/-/configuration-0.217.0.tgz", + "integrity": "sha512-xCtrYOhBqdy6ZOMfe0Oa73ZKF+2LMhoOv4L5vmwAHVvOXUg+V3fvKuEIr9ZyD0Ow+vxllEjWO6PV1wd0DOtyvw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "2.7.1", + "yaml": "^2.0.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.9.0" + } + }, + "node_modules/@opentelemetry/context-async-hooks": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/context-async-hooks/-/context-async-hooks-2.7.1.tgz", + "integrity": "sha512-OPFBYuXEn1E4ja3Y6eeA7O+ZnLBNcXTV5Cgsn1VaqBZ6hC5FnpZPLBNme1LJY8ZtF4aOujPKFoeWN4ik487KuQ==", + "license": "Apache-2.0", + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/core": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-2.7.1.tgz", + "integrity": "sha512-QAqIj32AtK6+pEVNG7EOVxHdE06RP+FM5qpiEJ4RtDcFIqKUZHYhl7/7UY5efhwmwNAg7j8QbJVBLxMerc0+gw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/semantic-conventions": "^1.29.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/exporter-logs-otlp-grpc": { + "version": "0.217.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-logs-otlp-grpc/-/exporter-logs-otlp-grpc-0.217.0.tgz", + "integrity": "sha512-vC5S0Dc+noxD86CVtNu1+awCHPA5Kewi1Sg23ps+9lh4YifwsKXh3pe4XTNEKtUJiAcjpJ5dqStGakLbrSE+YQ==", + "license": "Apache-2.0", + "dependencies": { + "@grpc/grpc-js": "^1.14.3", + "@opentelemetry/core": "2.7.1", + "@opentelemetry/otlp-exporter-base": "0.217.0", + "@opentelemetry/otlp-grpc-exporter-base": "0.217.0", + "@opentelemetry/otlp-transformer": "0.217.0", + "@opentelemetry/sdk-logs": "0.217.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/exporter-logs-otlp-http": { + "version": "0.217.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-logs-otlp-http/-/exporter-logs-otlp-http-0.217.0.tgz", + "integrity": "sha512-KfLAdt1uilVE+3FxbgVnp2ZrzqbIawzcesnRoi+Kh9ckB5Ld5D8btUgoBvwTbdmuNx1j6b132Wsh72azq+pPNQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.217.0", + "@opentelemetry/core": "2.7.1", + "@opentelemetry/otlp-exporter-base": "0.217.0", + "@opentelemetry/otlp-transformer": "0.217.0", + "@opentelemetry/sdk-logs": "0.217.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/exporter-logs-otlp-proto": { + "version": "0.217.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-logs-otlp-proto/-/exporter-logs-otlp-proto-0.217.0.tgz", + "integrity": "sha512-Se0GG/ZO24mQTlQj7zprR4pNI0nKe4lPDPBsuJmi6508b9TlZEuUd3EfyuHk6oJxzL7fGyDFYAbxNigQvRP2ZQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.217.0", + "@opentelemetry/core": "2.7.1", + "@opentelemetry/otlp-exporter-base": "0.217.0", + "@opentelemetry/otlp-transformer": "0.217.0", + "@opentelemetry/resources": "2.7.1", + "@opentelemetry/sdk-logs": "0.217.0", + "@opentelemetry/sdk-trace-base": "2.7.1" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/exporter-logs-otlp-proto/node_modules/@opentelemetry/sdk-trace-base": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-2.7.1.tgz", + "integrity": "sha512-NAYIlsF8MPUsKqJMiDQJTMPOmlbawC1Iz/omMLygZ1C9am8fTKYjTaI+OZM+WTY3t3Glo0wnOg/6/pac6RGPPw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "2.7.1", + "@opentelemetry/resources": "2.7.1", + "@opentelemetry/semantic-conventions": "^1.29.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.3.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/exporter-metrics-otlp-grpc": { + "version": "0.217.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-metrics-otlp-grpc/-/exporter-metrics-otlp-grpc-0.217.0.tgz", + "integrity": "sha512-0GpJKnCoVaVA1rKBMVPHziznfOQlXgH72S9ktjBAF1AnAVPzX7vVEBGrhwiSxxHDAiefXk+J8znApsMb/K6Z3w==", + "license": "Apache-2.0", + "dependencies": { + "@grpc/grpc-js": "^1.14.3", + "@opentelemetry/core": "2.7.1", + "@opentelemetry/exporter-metrics-otlp-http": "0.217.0", + "@opentelemetry/otlp-exporter-base": "0.217.0", + "@opentelemetry/otlp-grpc-exporter-base": "0.217.0", + "@opentelemetry/otlp-transformer": "0.217.0", + "@opentelemetry/resources": "2.7.1", + "@opentelemetry/sdk-metrics": "2.7.1" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/exporter-metrics-otlp-http": { + "version": "0.217.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-metrics-otlp-http/-/exporter-metrics-otlp-http-0.217.0.tgz", + "integrity": "sha512-1zkMzzhiNJdVmLxuwkltqWGw4fOOam47bqRxmuQNjyKJe/9NmY5cIrZ4kiQV7sVGxoOgT0ZvGUfLcjvtpC/b9Q==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "2.7.1", + "@opentelemetry/otlp-exporter-base": "0.217.0", + "@opentelemetry/otlp-transformer": "0.217.0", + "@opentelemetry/resources": "2.7.1", + "@opentelemetry/sdk-metrics": "2.7.1" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/exporter-metrics-otlp-proto": { + "version": "0.217.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-metrics-otlp-proto/-/exporter-metrics-otlp-proto-0.217.0.tgz", + "integrity": "sha512-nfxt/KxVGFkjkO/M+58y1ugHu/dwPtxG4eYq0KApcQ7xk5CHzhdn+IuLZfDSvNDrJ3Uy5q++Fj/wbK7i8yryfQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "2.7.1", + "@opentelemetry/exporter-metrics-otlp-http": "0.217.0", + "@opentelemetry/otlp-exporter-base": "0.217.0", + "@opentelemetry/otlp-transformer": "0.217.0", + "@opentelemetry/resources": "2.7.1", + "@opentelemetry/sdk-metrics": "2.7.1" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/exporter-prometheus": { + "version": "0.217.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-prometheus/-/exporter-prometheus-0.217.0.tgz", + "integrity": "sha512-U9MCXxJu0sBCh5aEkylYRR4xVIL8D1CW6dGwvYXbfFr0qveSorfD0XJchCAWoW6QfAAIcY/yxjf4Dj8OgkHBPw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "2.7.1", + "@opentelemetry/resources": "2.7.1", + "@opentelemetry/sdk-metrics": "2.7.1", + "@opentelemetry/semantic-conventions": "^1.29.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/exporter-trace-otlp-grpc": { + "version": "0.217.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-trace-otlp-grpc/-/exporter-trace-otlp-grpc-0.217.0.tgz", + "integrity": "sha512-fPZs2fw7veLH3pEKu8vSepUa2fQpAE2P7al6qU10aH9GrEJJ8YaPgsd5xON7by5rbcEVS71FOU2aWyK6nzB7VQ==", + "license": "Apache-2.0", + "dependencies": { + "@grpc/grpc-js": "^1.14.3", + "@opentelemetry/core": "2.7.1", + "@opentelemetry/otlp-exporter-base": "0.217.0", + "@opentelemetry/otlp-grpc-exporter-base": "0.217.0", + "@opentelemetry/otlp-transformer": "0.217.0", + "@opentelemetry/resources": "2.7.1", + "@opentelemetry/sdk-trace-base": "2.7.1" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/exporter-trace-otlp-grpc/node_modules/@opentelemetry/sdk-trace-base": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-2.7.1.tgz", + "integrity": "sha512-NAYIlsF8MPUsKqJMiDQJTMPOmlbawC1Iz/omMLygZ1C9am8fTKYjTaI+OZM+WTY3t3Glo0wnOg/6/pac6RGPPw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "2.7.1", + "@opentelemetry/resources": "2.7.1", + "@opentelemetry/semantic-conventions": "^1.29.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.3.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/exporter-trace-otlp-http": { + "version": "0.217.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-trace-otlp-http/-/exporter-trace-otlp-http-0.217.0.tgz", + "integrity": "sha512-38YQoqtYjglz2GV94LGUN/djLvxtvGIQO68o6qAFPVshjmwSdX1F2i0c7vn3lEl1L5B/YqjB/bgKXaVx7KO+RQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "2.7.1", + "@opentelemetry/otlp-exporter-base": "0.217.0", + "@opentelemetry/otlp-transformer": "0.217.0", + "@opentelemetry/resources": "2.7.1", + "@opentelemetry/sdk-trace-base": "2.7.1" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/exporter-trace-otlp-http/node_modules/@opentelemetry/sdk-trace-base": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-2.7.1.tgz", + "integrity": "sha512-NAYIlsF8MPUsKqJMiDQJTMPOmlbawC1Iz/omMLygZ1C9am8fTKYjTaI+OZM+WTY3t3Glo0wnOg/6/pac6RGPPw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "2.7.1", + "@opentelemetry/resources": "2.7.1", + "@opentelemetry/semantic-conventions": "^1.29.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.3.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/exporter-trace-otlp-proto": { + "version": "0.217.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-trace-otlp-proto/-/exporter-trace-otlp-proto-0.217.0.tgz", + "integrity": "sha512-nPV8gKHUiSuTZpQcnZU3/pBlK7crSyEGpZuh5MtWySB0vv6NNG0QvvfKitQt+Fc2Mc6qfyU54KlZcurwoTbrVg==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "2.7.1", + "@opentelemetry/otlp-exporter-base": "0.217.0", + "@opentelemetry/otlp-transformer": "0.217.0", + "@opentelemetry/resources": "2.7.1", + "@opentelemetry/sdk-trace-base": "2.7.1" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/exporter-trace-otlp-proto/node_modules/@opentelemetry/sdk-trace-base": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-2.7.1.tgz", + "integrity": "sha512-NAYIlsF8MPUsKqJMiDQJTMPOmlbawC1Iz/omMLygZ1C9am8fTKYjTaI+OZM+WTY3t3Glo0wnOg/6/pac6RGPPw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "2.7.1", + "@opentelemetry/resources": "2.7.1", + "@opentelemetry/semantic-conventions": "^1.29.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.3.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/exporter-zipkin": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-zipkin/-/exporter-zipkin-2.7.1.tgz", + "integrity": "sha512-mfsD9bKAxcKrh5+y08TPodvClBO0CznBE3p79YAGnO81WI4LrdsGA65T53e4iTSbCalW4WaUpkbeJcbpyIUHfg==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "2.7.1", + "@opentelemetry/resources": "2.7.1", + "@opentelemetry/sdk-trace-base": "2.7.1", + "@opentelemetry/semantic-conventions": "^1.29.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.0.0" + } + }, + "node_modules/@opentelemetry/exporter-zipkin/node_modules/@opentelemetry/sdk-trace-base": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-2.7.1.tgz", + "integrity": "sha512-NAYIlsF8MPUsKqJMiDQJTMPOmlbawC1Iz/omMLygZ1C9am8fTKYjTaI+OZM+WTY3t3Glo0wnOg/6/pac6RGPPw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "2.7.1", + "@opentelemetry/resources": "2.7.1", + "@opentelemetry/semantic-conventions": "^1.29.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.3.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/instrumentation": { + "version": "0.217.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.217.0.tgz", + "integrity": "sha512-24ucQMjz7Y34Kw3trbxL2ZrssbtgWnR+Clpaa+YdeWuuyH3Cvk23Q03PcQvqiZrDvt8AmQmjgg9v6Y9PHoxG7w==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.217.0", + "import-in-the-middle": "^3.0.0", + "require-in-the-middle": "^8.0.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-http": { + "version": "0.217.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-http/-/instrumentation-http-0.217.0.tgz", + "integrity": "sha512-B88Y7k5A9a60pHUboFoeJlgVwXq2T0rsZKj6dTwzSMKSOsNXR4Jz5ovwprVn3kHLAZrkyLEjQtBJ34DYHs1U4Q==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "2.7.1", + "@opentelemetry/instrumentation": "0.217.0", + "@opentelemetry/semantic-conventions": "^1.29.0", + "forwarded-parse": "2.1.2" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/otlp-exporter-base": { + "version": "0.217.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-exporter-base/-/otlp-exporter-base-0.217.0.tgz", + "integrity": "sha512-eYfqnB3UhKu/5frhd1R6+FprKygbhkomuaceMXDyzxbfXB9tKgZOVmjaJ02CkLA6Tdzumxl+e2H+vo2a8jiMPQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "2.7.1", + "@opentelemetry/otlp-transformer": "0.217.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/otlp-grpc-exporter-base": { + "version": "0.217.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-grpc-exporter-base/-/otlp-grpc-exporter-base-0.217.0.tgz", + "integrity": "sha512-7RTAdZuOsCDnsyqTCG4+bDzrfnsWdzkRs7z0AVi/V3tEQx0oKeyc+OuRWYxnRsmaJXgxcmB8vb/lfxn58Dj6Ag==", + "license": "Apache-2.0", + "dependencies": { + "@grpc/grpc-js": "^1.14.3", + "@opentelemetry/core": "2.7.1", + "@opentelemetry/otlp-exporter-base": "0.217.0", + "@opentelemetry/otlp-transformer": "0.217.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/otlp-transformer": { + "version": "0.217.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-transformer/-/otlp-transformer-0.217.0.tgz", + "integrity": "sha512-MKK8UHKFUOGAvbZRWh90MhwHG+Fxm6OROBdjKPCF+HQobjuJ/Kuf8Chs8CR45X1aqotxrMj7OxTdsXe8sXuGVA==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.217.0", + "@opentelemetry/core": "2.7.1", + "@opentelemetry/resources": "2.7.1", + "@opentelemetry/sdk-logs": "0.217.0", + "@opentelemetry/sdk-metrics": "2.7.1", + "@opentelemetry/sdk-trace-base": "2.7.1", + "protobufjs": "8.0.1" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/otlp-transformer/node_modules/@opentelemetry/sdk-trace-base": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-2.7.1.tgz", + "integrity": "sha512-NAYIlsF8MPUsKqJMiDQJTMPOmlbawC1Iz/omMLygZ1C9am8fTKYjTaI+OZM+WTY3t3Glo0wnOg/6/pac6RGPPw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "2.7.1", + "@opentelemetry/resources": "2.7.1", + "@opentelemetry/semantic-conventions": "^1.29.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.3.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/propagator-b3": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/propagator-b3/-/propagator-b3-2.7.1.tgz", + "integrity": "sha512-RJid6E2CKyeGfKBzXKF21ejabGMHypFkPAh3qZ+NvI+SGjuIye79t3PmiqcDgtRzdKH6ynXzbfslQ8DfpRUg2A==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "2.7.1" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/propagator-jaeger": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/propagator-jaeger/-/propagator-jaeger-2.7.1.tgz", + "integrity": "sha512-KMjVBHzP4N60bOzxja76M1F1hZZ43lGPga5ix+mkv9+kk1nx9SbkxSvJsMbuVUxdPQmsPTqGShmhN8ulrMOg6Q==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "2.7.1" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/resources": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.7.1.tgz", + "integrity": "sha512-DeT6KKolmC4e/dRQvMQ/RwlnzhaqeiFOXY5ngoOPJ07GgVVKxZOg9EcrNZb5aTzUn+iCrJldAgOfQm1O/QfPAQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "2.7.1", + "@opentelemetry/semantic-conventions": "^1.29.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.3.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/sdk-logs": { + "version": "0.217.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-logs/-/sdk-logs-0.217.0.tgz", + "integrity": "sha512-BB+PcHItcZDL63dPMW+mJvwN9rk37wuIDjRxbVlg6pPDvDR/7GL7UJHbGsllgoggOoTimsKgENaWPoGch/oE1A==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.217.0", + "@opentelemetry/core": "2.7.1", + "@opentelemetry/resources": "2.7.1", + "@opentelemetry/semantic-conventions": "^1.29.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.4.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/sdk-metrics": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-metrics/-/sdk-metrics-2.7.1.tgz", + "integrity": "sha512-MpDJdkiFDs3Pm1RHO3KByuZbuBdJEXEAkiC0+yJdsZGVCdf1RpHR6n+LHDcS7ffmfrt5kVCzJSCfm4z2C7v0uQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "2.7.1", + "@opentelemetry/resources": "2.7.1" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.9.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/sdk-node": { + "version": "0.217.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-node/-/sdk-node-0.217.0.tgz", + "integrity": "sha512-K/60pSv42+NQiZKy1pAH18nYDkxltsDV4O3SJ233J0E9raU1ksyL9gsKuS8p30bYBb4AMPCfDuutHQaHYpcv0Q==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.217.0", + "@opentelemetry/configuration": "0.217.0", + "@opentelemetry/context-async-hooks": "2.7.1", + "@opentelemetry/core": "2.7.1", + "@opentelemetry/exporter-logs-otlp-grpc": "0.217.0", + "@opentelemetry/exporter-logs-otlp-http": "0.217.0", + "@opentelemetry/exporter-logs-otlp-proto": "0.217.0", + "@opentelemetry/exporter-metrics-otlp-grpc": "0.217.0", + "@opentelemetry/exporter-metrics-otlp-http": "0.217.0", + "@opentelemetry/exporter-metrics-otlp-proto": "0.217.0", + "@opentelemetry/exporter-prometheus": "0.217.0", + "@opentelemetry/exporter-trace-otlp-grpc": "0.217.0", + "@opentelemetry/exporter-trace-otlp-http": "0.217.0", + "@opentelemetry/exporter-trace-otlp-proto": "0.217.0", + "@opentelemetry/exporter-zipkin": "2.7.1", + "@opentelemetry/instrumentation": "0.217.0", + "@opentelemetry/otlp-exporter-base": "0.217.0", + "@opentelemetry/propagator-b3": "2.7.1", + "@opentelemetry/propagator-jaeger": "2.7.1", + "@opentelemetry/resources": "2.7.1", + "@opentelemetry/sdk-logs": "0.217.0", + "@opentelemetry/sdk-metrics": "2.7.1", + "@opentelemetry/sdk-trace-base": "2.7.1", + "@opentelemetry/sdk-trace-node": "2.7.1", + "@opentelemetry/semantic-conventions": "^1.29.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.3.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/sdk-node/node_modules/@opentelemetry/sdk-trace-base": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-2.7.1.tgz", + "integrity": "sha512-NAYIlsF8MPUsKqJMiDQJTMPOmlbawC1Iz/omMLygZ1C9am8fTKYjTaI+OZM+WTY3t3Glo0wnOg/6/pac6RGPPw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "2.7.1", + "@opentelemetry/resources": "2.7.1", + "@opentelemetry/semantic-conventions": "^1.29.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.3.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/sdk-trace-base": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-2.8.0.tgz", + "integrity": "sha512-mhU4jp+vW0mGbFRd+GeXHvmfA4aDqWjBjLC3pE5XMpLs0IE2ryYb019Ts2AQrOq67gaTF25D91+fgvEHDZEnuQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "2.8.0", + "@opentelemetry/resources": "2.8.0", + "@opentelemetry/semantic-conventions": "^1.29.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.3.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/sdk-trace-base/node_modules/@opentelemetry/core": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-2.8.0.tgz", + "integrity": "sha512-hd1Lfh8p545nNz+jq1Ejfz+Mn1hyLuxYn1YzTfFNrxr8urEWMNQLPf1Th8kjOH+HxwawCrtgBp8JpBUR4ZSgww==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/semantic-conventions": "^1.29.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/sdk-trace-base/node_modules/@opentelemetry/resources": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.8.0.tgz", + "integrity": "sha512-qmXQ27ilDbUK/vGMqwL8D4/rhn76C+sherM4wTbjlfknR8Nvfc/hCxjRJPhkzZzUsPiNg16SA31NxMabwttRjg==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "2.8.0", + "@opentelemetry/semantic-conventions": "^1.29.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.3.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/sdk-trace-node": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-node/-/sdk-trace-node-2.7.1.tgz", + "integrity": "sha512-pCpQxU68lV+I9s9svqMyVu5iHdDDUnqUpSxqwyCU8A9ejEsSnMPCbearwsUO4yk08ZJzAIUCFuReMdVQvHrdvg==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/context-async-hooks": "2.7.1", + "@opentelemetry/core": "2.7.1", + "@opentelemetry/sdk-trace-base": "2.7.1" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/sdk-trace-node/node_modules/@opentelemetry/sdk-trace-base": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-2.7.1.tgz", + "integrity": "sha512-NAYIlsF8MPUsKqJMiDQJTMPOmlbawC1Iz/omMLygZ1C9am8fTKYjTaI+OZM+WTY3t3Glo0wnOg/6/pac6RGPPw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "2.7.1", + "@opentelemetry/resources": "2.7.1", + "@opentelemetry/semantic-conventions": "^1.29.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.3.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/semantic-conventions": { + "version": "1.41.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.41.1.tgz", + "integrity": "sha512-/UhIkaZgPutTFmQ7RnIJGgDXZmtEJ7Dvi86xNTFWcnRxVRNk/aotsqDJYeEvDP+FSMB2SdW+pQzNMcWP0rwuNA==", + "license": "Apache-2.0", + "engines": { + "node": ">=14" + } + }, + "node_modules/@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/codegen": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.5.tgz", + "integrity": "sha512-zgXFLzW3Ap33e6d0Wlj4MGIm6Ce8O89n/apUaGNB/jx+hw+ruWEp7EwGUshdLKVRCxZW12fp9r40E1mQrf/34g==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/eventemitter": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.1.tgz", + "integrity": "sha512-vW1GmwMZNnL+gMRaovlh9yZX74kc+TTU3FObkkurpMaRtBfLP3ldjS9KQWlwZgraRE0+dheEEoAxdzcJQ8eXZg==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/fetch": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.1.tgz", + "integrity": "sha512-GpptLrs57adMSuHi3VNj0mAF8dwh36LMaYF6XyJ6JMWlVsc+t42tm1HSEDmOs3A8fC9yyeisgLhsTVQokOZ0zw==", + "license": "BSD-3-Clause", + "dependencies": { + "@protobufjs/aspromise": "^1.1.1" + } + }, + "node_modules/@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/inquire": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.2.tgz", + "integrity": "sha512-pa0vFRuws4wkvaXKK1uXZMAwAX4/t8ANaJo45iw/oQHNQ9q5xUzwgFmVJGXiga2BeN+zpX7Vf9vmsiIa2J+MUw==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/utf8": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.1.tgz", + "integrity": "sha512-oOAWABowe8EAbMyWKM0tYDKi8Yaox52D+HWZhAIJqQXbqe0xI/GV7FhLWqlEKreMkfDjshR5FKgi3mnle0h6Eg==", + "license": "BSD-3-Clause" + }, + "node_modules/@smithy/core": { + "version": "3.26.0", + "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.26.0.tgz", + "integrity": "sha512-mLUktFAn+Pa2agl1J7VgtYNFWCX8/b4GMJSK1hCu4YCvtBfM6F8Os3EP4ry+DFFlXOf3wyvlgXhuUdFoy52D3g==", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/crc32": "5.2.0", + "@smithy/types": "^4.15.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/credential-provider-imds": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-4.4.2.tgz", + "integrity": "sha512-18UMDMyrAbDcpmL1gLUA7ww0fRTcdCrSjSJOi2Sbld+tVjwD/pW+OAwjlScFLR7vvBnhZrIPQ7kVuTf1mnJLug==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/core": "^3.26.0", + "@smithy/types": "^4.15.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/fetch-http-handler": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-5.5.2.tgz", + "integrity": "sha512-Ei/UK/QMhq0rKaMqGPlOAkE2yS9DZeYmZdk1RAKc3vp3zxgleZHZyBLlZv8yLsxljX4svCRuMTD6u3LLIcU4Bg==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/core": "^3.26.0", + "@smithy/types": "^4.15.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/is-array-buffer": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz", + "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/node-http-handler": { + "version": "4.8.2", + "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.8.2.tgz", + "integrity": "sha512-wfl1uwrAqMH9/pi4kqBo5LBcFwrJLxuDLqL7p7qNcJIFcyZDUc6pzhYk4CYv+DP7fIUpQCZumwNnkhPKS52osQ==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/core": "^3.26.0", + "@smithy/types": "^4.15.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/signature-v4": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-5.5.2.tgz", + "integrity": "sha512-7xHpmPY4rt0IOmeAA8EfjgEH8isT+587TCdy9H6a7d4OMi5CQ0oEHhWllunvPu4j4Cq0vTFwdxXN/kABWPjdyA==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/core": "^3.26.0", + "@smithy/types": "^4.15.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/types": { + "version": "4.15.0", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.15.0.tgz", + "integrity": "sha512-Z5TAOxygoFvybJV3igo5SloFflSokHx2hu1eFA+DxDTcn+FtKxUSui+rbTRG1pAafMA888Z3MVvCWUuvCrTXjg==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-buffer-from": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz", + "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/is-array-buffer": "^2.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/util-utf8": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz", + "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/util-buffer-from": "^2.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@types/node": { + "version": "26.0.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-26.0.0.tgz", + "integrity": "sha512-vf2YFi1iY9lHGwNJMs01biZFbKJkrZR1T6/MlzjhJLPdntOHLhTrDSnSVcdtvjihi4VQNlrFRIxLsDBlQpAipA==", + "license": "MIT", + "dependencies": { + "undici-types": "~8.3.0" + } + }, + "node_modules/acorn": { + "version": "8.17.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.17.0.tgz", + "integrity": "sha512-xRQbDb9BnwDafYNn6Vwl839DYVjqXYb1XVGtWAZ1kcDc6iwAL4hg3B1dZlRiuENFeO2H53gFG3in621AdERVAg==", + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-import-attributes": { + "version": "1.9.5", + "resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz", + "integrity": "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==", + "license": "MIT", + "peerDependencies": { + "acorn": "^8" + } + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "license": "MIT", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, + "node_modules/axios": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.18.1.tgz", + "integrity": "sha512-3nTvFlvpn9Zu/RkHUqtc7/+al4UpRW5az71ap5zccp6e8RAYEzhMTecX8Dz1wWDYrPpUoB1HAQEGEAEvUr7S9g==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.16.0", + "form-data": "^4.0.5", + "https-proxy-agent": "^5.0.1", + "proxy-from-env": "^2.1.0" + } + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/bowser": { + "version": "2.14.1", + "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.14.1.tgz", + "integrity": "sha512-tzPjzCxygAKWFOJP011oxFHs57HzIhOEracIgAePE4pqB3LikALKnSzUyU4MGs9/iCEUuHlAJTjTc5M+u7YEGg==", + "license": "MIT" + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/buffer": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", + "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", + "license": "MIT", + "dependencies": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "node_modules/busboy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", + "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "dependencies": { + "streamsearch": "^1.1.0" + }, + "engines": { + "node": ">=10.16.0" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/chownr": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", + "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" + } + }, + "node_modules/cjs-module-lexer": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-2.2.0.tgz", + "integrity": "sha512-4bHTS2YuzUvtoLjdy+98ykbNB5jS0+07EvFNXerqZQJ89F7DI6ET7OQo/HJuW6K0aVsKA9hj9/RVb2kQVOrPDQ==", + "license": "MIT" + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/dotenv": { + "version": "17.4.2", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.4.2.tgz", + "integrity": "sha512-nI4U3TottKAcAD9LLud4Cb7b2QztQMUEfHbvhTH09bqXTxnSie8WnjPALV/WMCrJZ6UV/qHJ6L03OqO3LcdYZw==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.2.tgz", + "integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "license": "MIT", + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/expand-tilde": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", + "integrity": "sha512-A5EmesHW6rfnZ9ysHQjPdJRni0SRar0tjtG5MNtm9n5TUvsYU8oozprtRD4AqHxcZWWlVuAmQo2nWKfN9oyjTw==", + "license": "MIT", + "dependencies": { + "homedir-polyfill": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fastq": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz", + "integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==", + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/follow-redirects": { + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.0.tgz", + "integrity": "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/form-data": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.6.tgz", + "integrity": "sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.4", + "mime-types": "^2.1.35" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/forwarded-parse": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/forwarded-parse/-/forwarded-parse-2.1.2.tgz", + "integrity": "sha512-alTFZZQDKMporBH77856pXgzhEzaUVmLCDk+egLgIgHst3Tpndzz8MnKe+GzRJRfvVdn69HhpW7cmXzvtLvJAw==", + "license": "MIT" + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz", + "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/homedir-polyfill": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", + "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", + "license": "MIT", + "dependencies": { + "parse-passwd": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "license": "MIT", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/import-in-the-middle": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-3.2.0.tgz", + "integrity": "sha512-vR2B6HKIhaBjcZr2bLpFiJ1VbzOlRQ7aby4/gw5WPIzToLjqpfWw3VJ4sk1uDchoOODEirvO2jyrSPtUSL5CrQ==", + "license": "Apache-2.0", + "dependencies": { + "acorn": "^8.15.0", + "acorn-import-attributes": "^1.9.5", + "cjs-module-lexer": "^2.2.0", + "module-details-from-path": "^1.0.4" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/isomorphic-ws": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-5.0.0.tgz", + "integrity": "sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw==", + "license": "MIT", + "peerDependencies": { + "ws": "*" + } + }, + "node_modules/lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", + "license": "MIT" + }, + "node_modules/long": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz", + "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==", + "license": "Apache-2.0" + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minipass": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", + "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/minizlib": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.1.0.tgz", + "integrity": "sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==", + "license": "MIT", + "dependencies": { + "minipass": "^7.1.2" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/module-details-from-path": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/module-details-from-path/-/module-details-from-path-1.0.4.tgz", + "integrity": "sha512-EGWKgxALGMgzvxYF1UyGTy0HXX/2vHLkw6+NvDKW2jypWbHpjQuj4UMcqQWXHERJhVGKikolT06G3bcKe4fi7w==", + "license": "MIT" + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/parse-passwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", + "integrity": "sha512-1Y1A//QUXEZK7YKz+rD9WydcE1+EuPr6ZBgKecAB8tmoW6UFv0NREVJe1p+jRxtThkcbbKkfwIbWJe/IeE6m2Q==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "license": "MIT" + }, + "node_modules/picomatch": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/protobufjs": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-8.0.1.tgz", + "integrity": "sha512-NWWCCscLjs+cOKF/s/XVNFRW7Yih0fdH+9brffR5NZCy8k42yRdl5KlWKMVXuI1vfCoy4o1z80XR/W/QUb3V3w==", + "hasInstallScript": true, + "license": "BSD-3-Clause", + "dependencies": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/node": ">=13.7.0", + "long": "^5.0.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/proxy-from-env": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-2.1.0.tgz", + "integrity": "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-in-the-middle": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/require-in-the-middle/-/require-in-the-middle-8.0.1.tgz", + "integrity": "sha512-QT7FVMXfWOYFbeRBF6nu+I6tr2Tf3u0q8RIEjNob/heKY/nh7drD/k7eeMFmSQgnTtCzLDcCu/XEnpW2wk4xCQ==", + "license": "MIT", + "dependencies": { + "debug": "^4.3.5", + "module-details-from-path": "^1.0.3" + }, + "engines": { + "node": ">=9.3.0 || >=8.10.0 <9.0.0" + } + }, + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/shell-quote": { + "version": "1.8.4", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.4.tgz", + "integrity": "sha512-VsC6n6vz1ihYYyZZwX7YZSF5l5x36ca17OC+a69h94YqB7X6XLwf+5MOgynYir2SLFUbl8gIYvBo8K8RoNQ6bQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/stream-browserify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-3.0.0.tgz", + "integrity": "sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==", + "license": "MIT", + "dependencies": { + "inherits": "~2.0.4", + "readable-stream": "^3.5.0" + } + }, + "node_modules/streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tar": { + "version": "7.5.16", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.16.tgz", + "integrity": "sha512-56adEpPMouktRlBLXiaYFFzZ/3+JXa8P9n7WbR+ibIjtviN55mEaOkiysCnPnWm+7kkui1Dn8J9l+g6zV8731w==", + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/fs-minipass": "^4.0.0", + "chownr": "^3.0.0", + "minipass": "^7.1.2", + "minizlib": "^3.1.0", + "yallist": "^5.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/undici-types": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-8.3.0.tgz", + "integrity": "sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ==", + "license": "MIT" + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "license": "MIT" + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/ws": { + "version": "8.21.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.21.0.tgz", + "integrity": "sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", + "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" + } + }, + "node_modules/yaml": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.9.0.tgz", + "integrity": "sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA==", + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14.6" + }, + "funding": { + "url": "https://github.com/sponsors/eemeli" + } + }, + "node_modules/yargs": { + "version": "17.7.3", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.3.tgz", + "integrity": "sha512-GZtjxm/J/4TSxuL3FNYjCmLktBTnIw/rVmKSIyKeYAZpmJB2ig9VauCC5xsa82GNKVKDAqpOn3KVzNt0zmrU0g==", + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "license": "ISC", + "engines": { + "node": ">=12" + } + } + } +} diff --git a/sessions/demo/daytona-smoketest/package.json b/sessions/demo/daytona-smoketest/package.json new file mode 100644 index 0000000000..2c6dec8304 --- /dev/null +++ b/sessions/demo/daytona-smoketest/package.json @@ -0,0 +1,5 @@ +{ + "dependencies": { + "@daytonaio/sdk": "^0.190.1" + } +} diff --git a/sessions/demo/docker-compose.yml b/sessions/demo/docker-compose.yml new file mode 100644 index 0000000000..32fcbf464e --- /dev/null +++ b/sessions/demo/docker-compose.yml @@ -0,0 +1,153 @@ +name: persistent-sessions-demo + +services: + postgres: + image: postgres:17 + environment: + POSTGRES_USER: postgres + POSTGRES_PASSWORD: postgres + POSTGRES_DB: ${POSTGRES_DB} + healthcheck: + test: ["CMD-SHELL", "pg_isready -U postgres -d ${POSTGRES_DB}"] + interval: 2s + timeout: 3s + retries: 20 + + redis: + image: redis:7-alpine + healthcheck: + test: ["CMD", "redis-cli", "ping"] + interval: 2s + timeout: 3s + retries: 20 + + seaweedfs: + image: chrislusf/seaweedfs:latest + command: > + server -dir=/data -ip=seaweedfs + -master.volumeSizeLimitMB=1024 + -s3 -s3.port=8333 -s3.config=/etc/seaweedfs/s3.json + volumes: + - ./seaweedfs/s3.json:/etc/seaweedfs/s3.json:ro + - seaweed_data:/data + healthcheck: + test: ["CMD-SHELL", "curl -sf http://localhost:9333/cluster/healthz >/dev/null || exit 1"] + interval: 3s + timeout: 3s + retries: 30 + + # Creates the `demo` bucket once seaweedfs is up, then exits. + seaweedfs-init: + image: chrislusf/seaweedfs:latest + depends_on: + seaweedfs: + condition: service_healthy + environment: + SEAWEEDFS_S3_BUCKET: ${SEAWEEDFS_S3_BUCKET} + entrypoint: > + sh -c "echo \"s3.bucket.create -name $${SEAWEEDFS_S3_BUCKET}\" | weed shell -master=seaweedfs:9333 || true" + + # Public tunnel so cloud sandboxes (e2b/daytona) can reach local SeaweedFS. + # Only needed for remote providers — start with: docker compose --profile remote up -d + ngrok: + image: ngrok/ngrok:latest + profiles: ["remote"] + command: ["http", "seaweedfs:8333", "--log=stdout"] + environment: + NGROK_AUTHTOKEN: ${NGROK_AUTHTOKEN} + ports: + - "4040:4040" # ngrok local inspection API (sidecar reads the public URL from here) + depends_on: + seaweedfs: + condition: service_healthy + + sandbox: + build: + context: . + dockerfile: sandbox/Dockerfile + environment: + ANTHROPIC_API_KEY: ${ANTHROPIC_API_KEY} + OPENAI_API_KEY: ${OPENAI_API_KEY} + cap_add: + - SYS_ADMIN + devices: + - /dev/fuse + security_opt: + - apparmor:unconfined + healthcheck: + test: ["CMD-SHELL", "curl -sf http://localhost:2468/v1/health >/dev/null || exit 1"] + interval: 3s + timeout: 3s + retries: 30 + + sidecar: + build: + context: ./sidecar + # hot reload: mount source, keep image's node_modules (anonymous volume), node --watch + command: ["node", "--watch", "server.js"] + volumes: + - ./sidecar:/app + - /app/node_modules + # docker provider: spawn sibling sandbox containers via the host daemon + - /var/run/docker.sock:/var/run/docker.sock + extra_hosts: + - "host.docker.internal:host-gateway" + environment: + SANDBOX_AGENT_URL: http://sandbox:2468 + SEAWEEDFS_S3_URL: ${SEAWEEDFS_S3_URL} + SEAWEEDFS_S3_ACCESS_KEY: ${SEAWEEDFS_S3_ACCESS_KEY} + SEAWEEDFS_S3_SECRET_KEY: ${SEAWEEDFS_S3_SECRET_KEY} + SEAWEEDFS_S3_BUCKET: ${SEAWEEDFS_S3_BUCKET} + # agent creds forwarded into remote (e2b) sandboxes + ANTHROPIC_API_KEY: ${ANTHROPIC_API_KEY} + OPENAI_API_KEY: ${OPENAI_API_KEY} + # remote providers + E2B_API_KEY: ${E2B_API_KEY} + E2B_TEMPLATE: agenta-sandbox-agent + MODAL_TOKEN_ID: ${MODAL_TOKEN_ID} + MODAL_TOKEN_SECRET: ${MODAL_TOKEN_SECRET} + DAYTONA_API_KEY: ${DAYTONA_API_KEY} + DAYTONA_SNAPSHOT: agenta-sandbox-agent + # docker provider: local image baked from docker-image/ (docker build -t agenta-sandbox-agent:local docker-image/) + SANDBOX_AGENT_IMAGE: agenta-sandbox-agent:local + NGROK_API_URL: http://ngrok:4040/api/tunnels + # per-session run lock (force/steal concurrency control) + REDIS_URL: redis://redis:6379 + # FastAPI base URL: the SDK persist driver round-trips session-state + transcript here + API_URL: http://fastapi:8000 + # set to "1" to log each /events persist (boundary log for debugging the durable path) + PERSIST_DEBUG: "0" + depends_on: + sandbox: + condition: service_healthy + redis: + condition: service_healthy + + fastapi: + build: + context: ./api + # hot reload: mount source, uvicorn --reload watches db.py/main.py/static + command: ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000", "--reload"] + volumes: + - ./api:/app + ports: + - "8000:8000" + environment: + POSTGRES_URI: ${POSTGRES_URI} + POSTGRES_DB: ${POSTGRES_DB} + SIDECAR_URL: http://sidecar:8080 + REDIS_URL: redis://redis:6379 + SEAWEEDFS_S3_URL: ${SEAWEEDFS_S3_URL} + SEAWEEDFS_S3_ACCESS_KEY: ${SEAWEEDFS_S3_ACCESS_KEY} + SEAWEEDFS_S3_SECRET_KEY: ${SEAWEEDFS_S3_SECRET_KEY} + SEAWEEDFS_S3_BUCKET: ${SEAWEEDFS_S3_BUCKET} + depends_on: + postgres: + condition: service_healthy + redis: + condition: service_healthy + sidecar: + condition: service_started + +volumes: + seaweed_data: diff --git a/sessions/demo/docker-image/Dockerfile b/sessions/demo/docker-image/Dockerfile new file mode 100644 index 0000000000..3eb0247aee --- /dev/null +++ b/sessions/demo/docker-image/Dockerfile @@ -0,0 +1,71 @@ +# Local docker sandbox image: sandbox-agent + claude + codex + opencode + pi + geesefs. +# Used by the SDK's built-in `docker` provider (fresh container per session, AutoRemove). +# Mirrors the e2b template / daytona snapshot — x86_64 binaries; cwd is /root/work. +# docker build -t agenta-sandbox-agent:local docker-image/ +FROM debian:12-slim + +RUN apt-get update && apt-get install -y --no-install-recommends \ + bash ca-certificates curl git fuse procps sudo jq \ + && rm -rf /var/lib/apt/lists/* + +# node 22 (pi needs >=22.19) +RUN curl -fsSL https://deb.nodesource.com/setup_22.x | bash - \ + && apt-get install -y nodejs && node --version + +RUN echo "user_allow_other" >> /etc/fuse.conf + +# rivet sandbox-agent server binary +RUN curl -fsSL https://releases.rivet.dev/sandbox-agent/0.4.x/install.sh | sh \ + && (command -v sandbox-agent || cp "$(find / -name sandbox-agent -type f 2>/dev/null | head -1)" /usr/local/bin/sandbox-agent) \ + && sandbox-agent --version + +# claude: native binary + adapter + launcher +RUN mkdir -p /root/.local/share/sandbox-agent/bin && \ + CLAUDE_VER=$(curl -fsSL https://storage.googleapis.com/claude-code-dist-86c565f3-f756-42ad-8dfa-d59b1c096819/claude-code-releases/stable) && \ + curl -fsSL -o /root/.local/share/sandbox-agent/bin/claude "https://storage.googleapis.com/claude-code-dist-86c565f3-f756-42ad-8dfa-d59b1c096819/claude-code-releases/${CLAUDE_VER}/linux-x64/claude" && \ + chmod +x /root/.local/share/sandbox-agent/bin/claude +RUN mkdir -p /root/.local/share/sandbox-agent/bin/agent_processes/claude && \ + cd /root/.local/share/sandbox-agent/bin/agent_processes/claude && \ + npm install @agentclientprotocol/claude-agent-acp@^0.50.0 && \ + echo 'IyEvdXNyL2Jpbi9lbnYgc2gKc2V0IC1lCmV4ZWMgL3Jvb3QvLmxvY2FsL3NoYXJlL3NhbmRib3gtYWdlbnQvYmluL2FnZW50X3Byb2Nlc3Nlcy9jbGF1ZGUvbm9kZV9tb2R1bGVzLy5iaW4vY2xhdWRlLWFnZW50LWFjcCAiJEAiCg==' | base64 -d > /root/.local/share/sandbox-agent/bin/agent_processes/claude-acp && \ + chmod +x /root/.local/share/sandbox-agent/bin/agent_processes/claude-acp + +# codex: native binary + adapter + launcher +RUN curl -fsSL -o /tmp/codex.tgz "https://github.com/openai/codex/releases/latest/download/codex-x86_64-unknown-linux-musl.tar.gz" && \ + tar -xzf /tmp/codex.tgz -C /tmp && \ + mv "$(find /tmp -name 'codex-x86_64-unknown-linux-musl' -type f | head -1)" /root/.local/share/sandbox-agent/bin/codex && \ + chmod +x /root/.local/share/sandbox-agent/bin/codex && rm -f /tmp/codex.tgz +RUN mkdir -p /root/.local/share/sandbox-agent/bin/agent_processes/codex && \ + cd /root/.local/share/sandbox-agent/bin/agent_processes/codex && \ + npm install @agentclientprotocol/codex-acp@^1.0.0 && \ + echo 'IyEvdXNyL2Jpbi9lbnYgc2gKc2V0IC1lCmV4ZWMgL3Jvb3QvLmxvY2FsL3NoYXJlL3NhbmRib3gtYWdlbnQvYmluL2FnZW50X3Byb2Nlc3Nlcy9jb2RleC9ub2RlX21vZHVsZXMvLmJpbi9jb2RleC1hY3AgIiRAIgo=' | base64 -d > /root/.local/share/sandbox-agent/bin/agent_processes/codex-acp && \ + chmod +x /root/.local/share/sandbox-agent/bin/agent_processes/codex-acp + +# opencode: native x64 binary + launcher +RUN mkdir -p /root/.local/share/sandbox-agent/bin/agent_processes/opencode && \ + curl -fsSL -o /tmp/oc.tgz "https://github.com/anomalyco/opencode/releases/latest/download/opencode-linux-x64.tar.gz" && \ + rm -rf /tmp/ocx && mkdir -p /tmp/ocx && tar -xzf /tmp/oc.tgz -C /tmp/ocx && \ + install -m755 "$(find /tmp/ocx -name opencode -type f | head -1)" /root/.local/share/sandbox-agent/bin/agent_processes/opencode/opencode && \ + install -m755 "$(find /tmp/ocx -name opencode -type f | head -1)" /root/.local/share/sandbox-agent/bin/opencode && \ + rm -rf /tmp/oc.tgz /tmp/ocx && \ + echo 'IyEvdXNyL2Jpbi9lbnYgc2gKc2V0IC1lCmV4ZWMgL3Jvb3QvLmxvY2FsL3NoYXJlL3NhbmRib3gtYWdlbnQvYmluL2FnZW50X3Byb2Nlc3Nlcy9vcGVuY29kZS9vcGVuY29kZSBhY3AgIiRAIgo=' | base64 -d > /root/.local/share/sandbox-agent/bin/agent_processes/opencode-acp && \ + chmod +x /root/.local/share/sandbox-agent/bin/agent_processes/opencode-acp + +# pi: adapter + real CLI + launcher +RUN mkdir -p /root/.local/share/sandbox-agent/bin/agent_processes/pi && \ + cd /root/.local/share/sandbox-agent/bin/agent_processes/pi && \ + npm install pi-acp@^0.0.31 && \ + npm install -g @earendil-works/pi-coding-agent@0.80.2 && \ + echo 'IyEvdXNyL2Jpbi9lbnYgc2gKc2V0IC1lCmV4ZWMgL3Jvb3QvLmxvY2FsL3NoYXJlL3NhbmRib3gtYWdlbnQvYmluL2FnZW50X3Byb2Nlc3Nlcy9waS9ub2RlX21vZHVsZXMvLmJpbi9waS1hY3AgIiRAIgo=' | base64 -d > /root/.local/share/sandbox-agent/bin/agent_processes/pi-acp && \ + chmod +x /root/.local/share/sandbox-agent/bin/agent_processes/pi-acp + +# geesefs static binary — match the build arch (arm64 on Apple Silicon, amd64 on x86) +RUN ARCH=$(dpkg --print-architecture) && \ + case "$ARCH" in arm64) GA=geesefs-linux-arm64 ;; *) GA=geesefs-linux-amd64 ;; esac && \ + curl -fsSL -o /usr/local/bin/geesefs "https://github.com/yandex-cloud/geesefs/releases/latest/download/$GA" \ + && chmod +x /usr/local/bin/geesefs && /usr/local/bin/geesefs --version 2>/dev/null || true + +WORKDIR /root +# the SDK's docker provider runs Cmd: ["server", ...] — it expects sandbox-agent as the +# entrypoint so those become its args. +ENTRYPOINT ["sandbox-agent"] diff --git a/sessions/demo/e2b-smoketest/package-lock.json b/sessions/demo/e2b-smoketest/package-lock.json new file mode 100644 index 0000000000..1a86a891fc --- /dev/null +++ b/sessions/demo/e2b-smoketest/package-lock.json @@ -0,0 +1,419 @@ +{ + "name": "app", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "dependencies": { + "@e2b/code-interpreter": "^2.6.1" + } + }, + "node_modules/@bufbuild/protobuf": { + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/@bufbuild/protobuf/-/protobuf-2.12.1.tgz", + "integrity": "sha512-BvAMfS6LrgZiryOAZ4pBYucu4wG/Ei/9o9DZ9akbREnMLbPJiom2i8b9C8IsKErQoiKqVhrerzt3kOT/RrzLHg==", + "license": "(Apache-2.0 AND BSD-3-Clause)" + }, + "node_modules/@connectrpc/connect": { + "version": "2.0.0-rc.3", + "resolved": "https://registry.npmjs.org/@connectrpc/connect/-/connect-2.0.0-rc.3.tgz", + "integrity": "sha512-ARBt64yEyKbanyRETTjcjJuHr2YXorzQo0etyS5+P6oSeW8xEuzajA9g+zDnMcj1hlX2dQE93foIWQGfpru7gQ==", + "license": "Apache-2.0", + "peerDependencies": { + "@bufbuild/protobuf": "^2.2.0" + } + }, + "node_modules/@connectrpc/connect-web": { + "version": "2.0.0-rc.3", + "resolved": "https://registry.npmjs.org/@connectrpc/connect-web/-/connect-web-2.0.0-rc.3.tgz", + "integrity": "sha512-w88P8Lsn5CCsA7MFRl2e6oLY4J/5toiNtJns/YJrlyQaWOy3RO8pDgkz+iIkG98RPMhj2thuBvsd3Cn4DKKCkw==", + "license": "Apache-2.0", + "peerDependencies": { + "@bufbuild/protobuf": "^2.2.0", + "@connectrpc/connect": "2.0.0-rc.3" + } + }, + "node_modules/@e2b/code-interpreter": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/@e2b/code-interpreter/-/code-interpreter-2.6.1.tgz", + "integrity": "sha512-5sKJaw2w/XZNHq7NpcNm8cpGu3IHlwLjavRd6V5BsVQyyl+5zGnSWE+EvA6W1VHDbPXiSdm6pN8cREWAifdrJw==", + "license": "MIT", + "dependencies": { + "e2b": "^2.28.0" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/@isaacs/cliui": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-9.0.0.tgz", + "integrity": "sha512-AokJm4tuBHillT+FpMtxQ60n8ObyXBatq7jD2/JA9dxbDDokKQm8KMht5ibGzLVU9IJDIKK4TPKgMHEYMn3lMg==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" + } + }, + "node_modules/@isaacs/fs-minipass": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", + "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==", + "license": "ISC", + "dependencies": { + "minipass": "^7.0.4" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "license": "MIT", + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/brace-expansion": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz", + "integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==", + "license": "MIT", + "dependencies": { + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/chalk": { + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", + "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chownr": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", + "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" + } + }, + "node_modules/compare-versions": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-6.1.1.tgz", + "integrity": "sha512-4hm4VPpIecmlg59CHXnRDnqGplJFrbLG4aFEl5vl6cK1u76ws3LLvX7ikFnTDl5vo39sjWD6AaDPYodJp/NNHg==", + "license": "MIT" + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/dockerfile-ast": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/dockerfile-ast/-/dockerfile-ast-0.7.1.tgz", + "integrity": "sha512-oX/A4I0EhSkGqrFv0YuvPkBUSYp1XiY8O8zAKc8Djglx8ocz+JfOr8gP0ryRMC2myqvDLagmnZaU9ot1vG2ijw==", + "license": "MIT", + "dependencies": { + "vscode-languageserver-textdocument": "^1.0.8", + "vscode-languageserver-types": "^3.17.3" + }, + "engines": { + "node": "*" + } + }, + "node_modules/e2b": { + "version": "2.30.5", + "resolved": "https://registry.npmjs.org/e2b/-/e2b-2.30.5.tgz", + "integrity": "sha512-mw0tk5X3z+P8qr3z0+lNTHG2szfKtuBohIZVYqxw6LsKmPL49fEntLICeCfrenKlh7vQCcJRCnK3Bg0SwZS1HQ==", + "license": "MIT", + "dependencies": { + "@bufbuild/protobuf": "^2.6.2", + "@connectrpc/connect": "2.0.0-rc.3", + "@connectrpc/connect-web": "2.0.0-rc.3", + "chalk": "^5.3.0", + "compare-versions": "^6.1.0", + "dockerfile-ast": "^0.7.1", + "glob": "^11.1.0", + "openapi-fetch": "^0.14.1", + "platform": "^1.3.6", + "tar": "^7.5.16", + "undici": "^7.28.0" + }, + "engines": { + "node": ">=20.18.1" + } + }, + "node_modules/foreground-child": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-11.1.0.tgz", + "integrity": "sha512-vuNwKSaKiqm7g0THUBu2x7ckSs3XJLXE+2ssL7/MfTGPLLcrJQ/4Uq1CjPTtO5cCIiRxqvN6Twy1qOwhL0Xjcw==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "license": "BlueOak-1.0.0", + "dependencies": { + "foreground-child": "^3.3.1", + "jackspeak": "^4.1.1", + "minimatch": "^10.1.1", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^2.0.0" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "license": "ISC" + }, + "node_modules/jackspeak": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.2.3.tgz", + "integrity": "sha512-ykkVRwrYvFm1nb2AJfKKYPr0emF6IiXDYUaFx4Zn9ZuIH7MrzEZ3sD5RlqGXNRpHtvUHJyOnCEFxOlNDtGo7wg==", + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^9.0.0" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/lru-cache": { + "version": "11.5.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.5.1.tgz", + "integrity": "sha512-RPimw/7aMdv2oqRrxKwvZXcPfwBrn/JZ2xYcY9Hus/6LaS3VOAKVWKWgNLCFSiOm1ESXinjsDlidVU7JlnCN2A==", + "license": "BlueOak-1.0.0", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/minimatch": { + "version": "10.2.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", + "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", + "license": "BlueOak-1.0.0", + "dependencies": { + "brace-expansion": "^5.0.5" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minipass": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", + "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/minizlib": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.1.0.tgz", + "integrity": "sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==", + "license": "MIT", + "dependencies": { + "minipass": "^7.1.2" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/openapi-fetch": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/openapi-fetch/-/openapi-fetch-0.14.1.tgz", + "integrity": "sha512-l7RarRHxlEZYjMLd/PR0slfMVse2/vvIAGm75/F7J6MlQ8/b9uUQmUF2kCPrQhJqMXSxmYWObVgeYXbFYzZR+A==", + "license": "MIT", + "dependencies": { + "openapi-typescript-helpers": "^0.0.15" + } + }, + "node_modules/openapi-typescript-helpers": { + "version": "0.0.15", + "resolved": "https://registry.npmjs.org/openapi-typescript-helpers/-/openapi-typescript-helpers-0.0.15.tgz", + "integrity": "sha512-opyTPaunsklCBpTK8JGef6mfPhLSnyy5a0IN9vKtx3+4aExf+KxEqYwIy3hqkedXIB97u357uLMJsOnm3GVjsw==", + "license": "MIT" + }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "license": "BlueOak-1.0.0" + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-scurry": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.2.tgz", + "integrity": "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==", + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^11.0.0", + "minipass": "^7.1.2" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/platform": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/platform/-/platform-1.3.6.tgz", + "integrity": "sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg==", + "license": "MIT" + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/tar": { + "version": "7.5.16", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.16.tgz", + "integrity": "sha512-56adEpPMouktRlBLXiaYFFzZ/3+JXa8P9n7WbR+ibIjtviN55mEaOkiysCnPnWm+7kkui1Dn8J9l+g6zV8731w==", + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/fs-minipass": "^4.0.0", + "chownr": "^3.0.0", + "minipass": "^7.1.2", + "minizlib": "^3.1.0", + "yallist": "^5.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/undici": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.28.0.tgz", + "integrity": "sha512-cRZYrTDwWznlnRiPjggAGxZXanty6M8RV1ff8Wm4LWXBp7/IG8v5DnOm74DtUBp9OONpK75YlPnIjQqX0dBDtA==", + "license": "MIT", + "engines": { + "node": ">=20.18.1" + } + }, + "node_modules/vscode-languageserver-textdocument": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.12.tgz", + "integrity": "sha512-cxWNPesCnQCcMPeenjKKsOCKQZ/L6Tv19DTRIGuLWe32lyzWhihGVJ/rcckZXJxfdKCFvRLS3fpBIsV/ZGX4zA==", + "license": "MIT" + }, + "node_modules/vscode-languageserver-types": { + "version": "3.18.0", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.18.0.tgz", + "integrity": "sha512-8TsGPNMIMiiBdkORgRSvLjuiEIiAFtO+KssmYWxQ+uSVvlf7RjK8YKCOjPzZ+YA04jXEV7+7LvkSmHkhpNS99g==", + "license": "MIT" + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/yallist": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", + "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" + } + } + } +} diff --git a/sessions/demo/e2b-smoketest/package.json b/sessions/demo/e2b-smoketest/package.json new file mode 100644 index 0000000000..caa11c35ce --- /dev/null +++ b/sessions/demo/e2b-smoketest/package.json @@ -0,0 +1,5 @@ +{ + "dependencies": { + "@e2b/code-interpreter": "^2.6.1" + } +} diff --git a/sessions/demo/e2b-smoketest/smoke.mjs b/sessions/demo/e2b-smoketest/smoke.mjs new file mode 100644 index 0000000000..ca593323e0 --- /dev/null +++ b/sessions/demo/e2b-smoketest/smoke.mjs @@ -0,0 +1,62 @@ +// FUSE-in-E2B gate test: prove geesefs can mount SeaweedFS (via the ngrok tunnel) +// inside an E2B sandbox and that writes land in the bucket. If this fails, we don't +// ship E2B (durable cwd is mandatory). +// +// Usage (from the demo dir): +// docker compose --profile remote up -d ngrok +// TUNNEL=$(curl -s localhost:4040/api/tunnels | jq -r '.tunnels[0].public_url') +// docker run --rm --network persistent-sessions-demo_default \ +// -e E2B_API_KEY -e TUNNEL -e S3_KEY=demo -e S3_SECRET=demosecret \ +// -v "$PWD/e2b-smoketest:/app" -w /app node:22-bookworm-slim \ +// sh -c "npm i --silent @e2b/code-interpreter && node smoke.mjs" + +import { Sandbox } from "@e2b/code-interpreter"; + +const TUNNEL = process.env.TUNNEL; // https://xxxx.ngrok-free.app +const S3_KEY = process.env.S3_KEY || "demo"; +const S3_SECRET = process.env.S3_SECRET || "demosecret"; +const BUCKET = "demo"; +const SID = "smoketest"; + +if (!TUNNEL) throw new Error("TUNNEL env (ngrok public url) required"); +const GEESEFS_URL = + "https://github.com/yandex-cloud/geesefs/releases/latest/download/geesefs-linux-amd64"; + +async function sh(sbx, cmd, opts = {}) { + const r = await sbx.commands.run(cmd, { timeoutMs: 180000, ...opts }); + console.log(`$ ${cmd}\n exit=${r.exitCode}${r.stderr ? "\n stderr: " + r.stderr.slice(0, 400) : ""}`); + return r; +} + +const sbx = await Sandbox.create({ timeoutMs: 300000 }); +console.log("E2B sandbox:", sbx.sandboxId); +try { + // 1) FUSE available? (the load-bearing question) + await sh(sbx, "ls -l /dev/fuse || echo NO_FUSE_DEVICE"); + await sh(sbx, "sudo apt-get update -qq && sudo apt-get install -y -qq fuse || echo APT_FAIL"); + + // 2) geesefs binary + await sh(sbx, `curl -fsSL -o /tmp/geesefs ${GEESEFS_URL} && chmod +x /tmp/geesefs && /tmp/geesefs --version`); + + // 3) mount the bucket prefix from the tunnel and write a file. + // Mount as root but hand ownership to the running user (uid/gid) so non-root writes work. + const who = await sh(sbx, "id -u; id -g"); + const [uid, gid] = who.stdout.trim().split("\n"); + await sh(sbx, "mkdir -p /home/user/work"); + const mount = await sh( + sbx, + `AWS_ACCESS_KEY_ID=${S3_KEY} AWS_SECRET_ACCESS_KEY=${S3_SECRET} ` + + `sudo -E /tmp/geesefs --endpoint ${TUNNEL} --region us-east-1 --no-detect ` + + `--uid ${uid} --gid ${gid} --dir-mode 0777 --file-mode 0666 ` + + `-o allow_other ${BUCKET}:${SID} /home/user/work && echo MOUNT_OK` + ); + await sh(sbx, "mountpoint /home/user/work && echo IS_MOUNTPOINT || echo NOT_MOUNTPOINT"); + await sh(sbx, "echo 'hello from e2b geesefs' > /home/user/work/e2b-probe.txt && sync && ls -la /home/user/work && echo WRITE_OK"); + + const ok = mount.stdout.includes("MOUNT_OK"); + console.log(`\n=== RESULT: geesefs mount in E2B ${ok ? "SUCCEEDED" : "FAILED"} ===`); + console.log("Now check SeaweedFS for demo/smoketest/e2b-probe.txt to confirm the write landed."); +} finally { + await sbx.kill(); + console.log("sandbox killed"); +} diff --git a/sessions/demo/e2b-template/e2b.Dockerfile b/sessions/demo/e2b-template/e2b.Dockerfile new file mode 100644 index 0000000000..8d5cabd9c7 --- /dev/null +++ b/sessions/demo/e2b-template/e2b.Dockerfile @@ -0,0 +1,73 @@ +# E2B template: sandbox-agent + claude + codex + geesefs baked in. +# NOTE: `sandbox-agent install-agent` hangs in the E2B remote builder at the +# ACP-adapter step (registry resolution via cdn.agentclientprotocol.com stalls). +# Plain `npm install` works fine here, so we replicate install-agent's layout +# manually: native binary download (GCS/GitHub — works) + npm adapter + launcher. +FROM e2bdev/code-interpreter:latest + +USER root + +RUN apt-get update && apt-get install -y --no-install-recommends \ + bash ca-certificates curl git fuse procps sudo jq \ + && rm -rf /var/lib/apt/lists/* + +# The E2B base ships node 20, but pi (@earendil-works/pi-coding-agent) requires node +# >=22.19 — on node 20 its ACP adapter crashes ("stream was destroyed"). Install node 22. +RUN curl -fsSL https://deb.nodesource.com/setup_22.x | bash - \ + && apt-get install -y nodejs \ + && node --version + +RUN echo "user_allow_other" >> /etc/fuse.conf + +# rivet sandbox-agent server binary +RUN curl -fsSL https://releases.rivet.dev/sandbox-agent/0.4.x/install.sh | sh \ + && (command -v sandbox-agent || cp "$(find / -name sandbox-agent -type f 2>/dev/null | head -1)" /usr/local/bin/sandbox-agent) \ + && sandbox-agent --version + +# NOTE: E2B's builder does not reliably carry ENV into later RUN layers, so all +# paths are hardcoded. sandbox-agent looks under ~/.local/share/sandbox-agent/bin. + +# Claude: native CLI binary (GCS) + claude-agent-acp adapter (npm) + launcher +RUN mkdir -p /root/.local/share/sandbox-agent/bin && \ + CLAUDE_VER=$(curl -fsSL https://storage.googleapis.com/claude-code-dist-86c565f3-f756-42ad-8dfa-d59b1c096819/claude-code-releases/stable) && \ + curl -fsSL -o /root/.local/share/sandbox-agent/bin/claude "https://storage.googleapis.com/claude-code-dist-86c565f3-f756-42ad-8dfa-d59b1c096819/claude-code-releases/${CLAUDE_VER}/linux-x64/claude" && \ + chmod +x /root/.local/share/sandbox-agent/bin/claude +RUN mkdir -p /root/.local/share/sandbox-agent/bin/agent_processes/claude && \ + cd /root/.local/share/sandbox-agent/bin/agent_processes/claude && \ + npm install @agentclientprotocol/claude-agent-acp@^0.50.0 && \ + echo 'IyEvdXNyL2Jpbi9lbnYgc2gKc2V0IC1lCmV4ZWMgL3Jvb3QvLmxvY2FsL3NoYXJlL3NhbmRib3gtYWdlbnQvYmluL2FnZW50X3Byb2Nlc3Nlcy9jbGF1ZGUvbm9kZV9tb2R1bGVzLy5iaW4vY2xhdWRlLWFnZW50LWFjcCAiJEAiCg==' | base64 -d > /root/.local/share/sandbox-agent/bin/agent_processes/claude-acp && \ + chmod +x /root/.local/share/sandbox-agent/bin/agent_processes/claude-acp + +# Codex: native binary (GitHub) + codex-acp adapter (npm) + launcher +RUN curl -fsSL -o /tmp/codex.tgz "https://github.com/openai/codex/releases/latest/download/codex-x86_64-unknown-linux-musl.tar.gz" && \ + tar -xzf /tmp/codex.tgz -C /tmp && \ + mv "$(find /tmp -name 'codex-x86_64-unknown-linux-musl' -type f | head -1)" /root/.local/share/sandbox-agent/bin/codex && \ + chmod +x /root/.local/share/sandbox-agent/bin/codex && rm -f /tmp/codex.tgz +RUN mkdir -p /root/.local/share/sandbox-agent/bin/agent_processes/codex && \ + cd /root/.local/share/sandbox-agent/bin/agent_processes/codex && \ + npm install @agentclientprotocol/codex-acp@^1.0.0 && \ + echo 'IyEvdXNyL2Jpbi9lbnYgc2gKc2V0IC1lCmV4ZWMgL3Jvb3QvLmxvY2FsL3NoYXJlL3NhbmRib3gtYWdlbnQvYmluL2FnZW50X3Byb2Nlc3Nlcy9jb2RleC9ub2RlX21vZHVsZXMvLmJpbi9jb2RleC1hY3AgIiRAIgo=' | base64 -d > /root/.local/share/sandbox-agent/bin/agent_processes/codex-acp && \ + chmod +x /root/.local/share/sandbox-agent/bin/agent_processes/codex-acp + +# opencode: native x64 binary (anomalyco release) + launcher that execs `opencode acp`. +# E2B sandboxes are real x86_64, so the linux-x64 build is correct (no arch-fix needed). +RUN mkdir -p /root/.local/share/sandbox-agent/bin/agent_processes/opencode && \ + curl -fsSL -o /tmp/oc.tgz "https://github.com/anomalyco/opencode/releases/latest/download/opencode-linux-x64.tar.gz" && \ + rm -rf /tmp/ocx && mkdir -p /tmp/ocx && tar -xzf /tmp/oc.tgz -C /tmp/ocx && \ + install -m755 "$(find /tmp/ocx -name opencode -type f | head -1)" /root/.local/share/sandbox-agent/bin/agent_processes/opencode/opencode && \ + install -m755 "$(find /tmp/ocx -name opencode -type f | head -1)" /root/.local/share/sandbox-agent/bin/opencode && \ + rm -rf /tmp/oc.tgz /tmp/ocx && \ + echo 'IyEvdXNyL2Jpbi9lbnYgc2gKc2V0IC1lCmV4ZWMgL3Jvb3QvLmxvY2FsL3NoYXJlL3NhbmRib3gtYWdlbnQvYmluL2FnZW50X3Byb2Nlc3Nlcy9vcGVuY29kZS9vcGVuY29kZSBhY3AgIiRAIgo=' | base64 -d > /root/.local/share/sandbox-agent/bin/agent_processes/opencode-acp && \ + chmod +x /root/.local/share/sandbox-agent/bin/agent_processes/opencode-acp + +# pi: pi-acp adapter (npm) + the real pi CLI (global npm) + launcher +RUN mkdir -p /root/.local/share/sandbox-agent/bin/agent_processes/pi && \ + cd /root/.local/share/sandbox-agent/bin/agent_processes/pi && \ + npm install pi-acp@^0.0.31 && \ + npm install -g @earendil-works/pi-coding-agent@0.80.2 && \ + echo 'IyEvdXNyL2Jpbi9lbnYgc2gKc2V0IC1lCmV4ZWMgL3Jvb3QvLmxvY2FsL3NoYXJlL3NhbmRib3gtYWdlbnQvYmluL2FnZW50X3Byb2Nlc3Nlcy9waS9ub2RlX21vZHVsZXMvLmJpbi9waS1hY3AgIiRAIgo=' | base64 -d > /root/.local/share/sandbox-agent/bin/agent_processes/pi-acp && \ + chmod +x /root/.local/share/sandbox-agent/bin/agent_processes/pi-acp + +# geesefs static binary (linux-amd64; E2B sandboxes are x86_64) +COPY geesefs /usr/local/bin/geesefs +RUN chmod +x /usr/local/bin/geesefs diff --git a/sessions/demo/e2b-template/geesefs b/sessions/demo/e2b-template/geesefs new file mode 100755 index 0000000000..d141e4baa4 Binary files /dev/null and b/sessions/demo/e2b-template/geesefs differ diff --git a/sessions/demo/matrix_test.py b/sessions/demo/matrix_test.py new file mode 100644 index 0000000000..c40a32a897 --- /dev/null +++ b/sessions/demo/matrix_test.py @@ -0,0 +1,130 @@ +#!/usr/bin/env python3 +"""Full harness x sandbox matrix smoke. Each cell: invoke via FastAPI, the agent writes a +cell-unique file into its geesefs cwd, then verify durability in SeaweedFS host-side +(signed GET via the fastapi container). Prints a PASS/FAIL grid. + +Usage: python3 matrix_test.py [sandbox...] [--harness h1,h2] + python3 matrix_test.py # local daytona modal e2b x all 4 harnesses + python3 matrix_test.py local # just local + python3 matrix_test.py daytona --harness opencode,pi + +daytona requires Tier 3+ egress and a built snapshot (node sidecar/daytona_snapshot.js). +""" + +import json +import subprocess +import sys +import urllib.request + +API = "http://localhost:8000" +# valid (harness -> provider, model) per the discovered adapter vocab +MODEL = { + "claude": "sonnet", + "codex": "gpt-5.4", + "opencode": "anthropic/claude-sonnet-4-6", + "pi": "anthropic/claude-sonnet-4-6", +} +PROV = { + "claude": "anthropic", + "codex": "openai", + "opencode": "anthropic", + "pi": "anthropic", +} + +argv = [a for a in sys.argv[1:]] +harnesses = ["claude", "codex", "opencode", "pi"] + + +def _take_flag(name, default): + if name not in argv: + return default + i = argv.index(name) + if i + 1 >= len(argv): + sys.exit(f"{name} requires a value") + val = argv[i + 1] + del argv[i : i + 2] + return val + + +harnesses = _take_flag("--harness", ",".join(harnesses)).split(",") +REASONING = _take_flag("--reasoning", "none") +sandboxes = argv or ["local", "docker", "daytona", "modal", "e2b"] + + +def invoke(sandbox, harness, file, tag): + body = json.dumps( + { + "prompt": f"Create a file named {file} containing exactly: {tag} ok. Then stop.", + "sandbox": sandbox, + "harness": harness, + "provider": PROV[harness], + "model": MODEL[harness], + "reasoning": REASONING, + } + ).encode() + req = urllib.request.Request( + API + "/invoke", data=body, headers={"content-type": "application/json"} + ) + try: + with urllib.request.urlopen(req, timeout=320) as r: + o = json.loads(r.read()) + return o.get("session_id", ""), (o.get("stop_reason") or "no-stop") + except urllib.error.HTTPError as e: + detail = e.read().decode()[:120] + return "", f"HTTP{e.code}:{detail}" + except Exception as e: + return "", f"ERR:{str(e)[:100]}" + + +def durable(sid, file): + if not sid: + return False + code = f""" +import asyncio,aioboto3,os +async def m(): + s=aioboto3.Session() + async with s.client('s3',endpoint_url=os.environ['SEAWEEDFS_S3_URL'],aws_access_key_id=os.environ['SEAWEEDFS_S3_ACCESS_KEY'],aws_secret_access_key=os.environ['SEAWEEDFS_S3_SECRET_KEY'],region_name='us-east-1') as s3: + try: + await s3.get_object(Bucket=os.environ['SEAWEEDFS_S3_BUCKET'],Key='{sid}/{file}'); print('YES') + except Exception: print('NO') +asyncio.run(m()) +""" + out = subprocess.run( + ["docker", "compose", "exec", "-T", "fastapi", "python", "-c", code], + capture_output=True, + text=True, + cwd=".", + ) + return "YES" in out.stdout + + +results = {} +for sb in sandboxes: + for hn in harnesses: + tag = f"{sb}_{hn}" + file = f"proof_{tag}.txt" + print(f"── invoke {sb} × {hn} ──", flush=True) + sid, stop = invoke(sb, hn, file, tag) + ok = durable(sid, file) + results[tag] = (stop, ok) + print( + f" -> stop={stop} durable={'YES' if ok else 'NO'} sid={sid[:8]}", + flush=True, + ) + +print(f"\n========= MATRIX (durable agent write?) · reasoning={REASONING} =========") +hdr = "sandbox\\harness" +print(f"{hdr:<16}" + "".join(f"{h:<11}" for h in harnesses)) +for sb in sandboxes: + row = f"{sb:<16}" + for hn in harnesses: + stop, ok = results.get(f"{sb}_{hn}", ("", False)) + row += f"{'PASS' if ok else 'FAIL':<11}" + print(row) + +# detail lines for any failures +fails = {k: v for k, v in results.items() if not v[1]} +if fails: + print("\nfailures:") + for k, (stop, _) in fails.items(): + print(f" {k}: {stop}") diff --git a/sessions/demo/modal-smoketest/smoke.py b/sessions/demo/modal-smoketest/smoke.py new file mode 100644 index 0000000000..c5d049297c --- /dev/null +++ b/sessions/demo/modal-smoketest/smoke.py @@ -0,0 +1,67 @@ +"""Modal GATE test: does geesefs FUSE work in a Modal VM-runtime sandbox, and does a +write round-trip to SeaweedFS over the ngrok tunnel? If FUSE fails, we fall back to +CloudBucketMount (a separate test). Egress is unrestricted on Modal so the tunnel works. + +Run: MODAL_TOKEN_ID=.. MODAL_TOKEN_SECRET=.. TUNNEL=https://.. python smoke.py +""" + +import os +import modal + +TUNNEL = os.environ["TUNNEL"] +SID = "modal-smoketest" +GEESEFS = "https://github.com/yandex-cloud/geesefs/releases/latest/download/geesefs-linux-amd64" + +app = modal.App.lookup("rivet-demo-smoke", create_if_missing=True) + +img = ( + modal.Image.from_registry("debian:12-slim", add_python="3.11") + .apt_install("fuse", "ca-certificates", "curl") + .run_commands( + f"curl -fsSL -o /usr/local/bin/geesefs {GEESEFS} && chmod +x /usr/local/bin/geesefs" + ) +) + + +def run(sb, cmd, timeout=120): + p = sb.exec("bash", "-c", cmd, timeout=timeout) + out = p.stdout.read() + err = p.stderr.read() + print( + f"$ {cmd[:80]}\n {out.strip()[:300]}" + + (f"\n ERR: {err.strip()[:200]}" if err.strip() else "") + ) + return out + + +print("creating Modal VM-runtime sandbox...") +sb = modal.Sandbox.create( + "sleep", + "infinity", + app=app, + image=img, + timeout=600, + experimental_options={"vm_runtime": True}, +) +print("sandbox:", sb.object_id) +try: + run(sb, "ls -l /dev/fuse 2>&1 || echo NO_DEV_FUSE") + run(sb, "geesefs --version 2>&1 | head -1") + run(sb, "mkdir -p /root/work") + mount = run( + sb, + f"AWS_ACCESS_KEY_ID=demo AWS_SECRET_ACCESS_KEY=demosecret " + f"geesefs --endpoint {TUNNEL} --region us-east-1 --no-detect --fsync-on-close " + f"-o allow_other demo:{SID} /root/work && echo MOUNT_OK", + timeout=90, + ) + if "MOUNT_OK" in mount: + run( + sb, + "echo 'modal durable write' > /root/work/modal-probe.txt && cat /root/work/modal-probe.txt && echo WROTE", + timeout=90, + ) + print("\n=== check SeaweedFS for demo/modal-smoketest/modal-probe.txt ===") +finally: + sb.terminate() + print("terminated") diff --git a/sessions/demo/sandbox/Dockerfile b/sessions/demo/sandbox/Dockerfile new file mode 100644 index 0000000000..ee838e66ca --- /dev/null +++ b/sessions/demo/sandbox/Dockerfile @@ -0,0 +1,56 @@ +FROM node:22-bookworm-slim + +# Tools: curl/git for installs, fuse for geesefs, ca-certs for TLS to S3/Anthropic +RUN apt-get update && apt-get install -y --no-install-recommends \ + bash ca-certificates curl git fuse procps \ + && rm -rf /var/lib/apt/lists/* + +# Allow non-root + allow_other FUSE mounts (geesefs mounts under /work) +RUN echo "user_allow_other" >> /etc/fuse.conf + +# rivet sandbox-agent server binary +RUN curl -fsSL https://releases.rivet.dev/sandbox-agent/0.4.x/install.sh | sh \ + && (command -v sandbox-agent || cp "$(find / -name sandbox-agent -type f 2>/dev/null | head -1)" /usr/local/bin/sandbox-agent) \ + && sandbox-agent --version + +# Agent binaries + ACP adapters baked at build time, each isolated so one failure +# doesn't sink the others. claude + codex are known-good. +RUN sandbox-agent install-agent claude +RUN sandbox-agent install-agent codex +# opencode: rivet's installer fetches the linux-x64 Bun binary even on arm64 hosts, +# so on arm64 it lands a wrong-arch binary that SIGTRAPs under Rosetta. Install-agent +# (fail-soft for the verify crash), then overwrite the native binary with the correct +# arch build from the anomalyco release so `opencode acp` actually runs. +RUN sandbox-agent install-agent opencode || echo "opencode install-agent verify failed (fixing arch below)" +RUN set -e; \ + ARCH=$(dpkg --print-architecture); \ + case "$ARCH" in \ + arm64) OC=opencode-linux-arm64 ;; \ + amd64) OC=opencode-linux-x64 ;; \ + *) OC=opencode-linux-x64 ;; \ + esac; \ + rm -rf /tmp/ocfix && mkdir -p /tmp/ocfix; \ + curl -fsSL -o /tmp/ocfix/oc.tgz "https://github.com/anomalyco/opencode/releases/latest/download/${OC}.tar.gz"; \ + tar -xzf /tmp/ocfix/oc.tgz -C /tmp/ocfix; \ + OCBIN=$(find /tmp/ocfix -name opencode -type f | head -1); \ + install -m755 "$OCBIN" /root/.local/share/sandbox-agent/bin/opencode; \ + install -m755 "$OCBIN" /root/.local/share/sandbox-agent/bin/agent_processes/opencode/opencode; \ + rm -rf /tmp/ocfix; \ + /root/.local/share/sandbox-agent/bin/opencode --version +# pi: install-agent gives only the pi-acp adapter; the actual `pi` CLI is a separate +# npm package (earendil-works, headless, plain API key). +RUN sandbox-agent install-agent pi || echo "pi install-agent returned non-zero (continuing)" +RUN npm install -g @earendil-works/pi-coding-agent@0.80.2 + +# geesefs static binary (linux, arch matches build platform) +COPY bin/geesefs /usr/local/bin/geesefs +RUN chmod +x /usr/local/bin/geesefs + +COPY sandbox/entrypoint.sh /usr/local/bin/entrypoint.sh +RUN chmod +x /usr/local/bin/entrypoint.sh + +WORKDIR /work +EXPOSE 2468 + +# Entrypoint seeds codex auth.json, then serves (no token; bind all interfaces for the sidecar) +CMD ["/usr/local/bin/entrypoint.sh"] diff --git a/sessions/demo/sandbox/entrypoint.sh b/sessions/demo/sandbox/entrypoint.sh new file mode 100644 index 0000000000..d72378b1d5 --- /dev/null +++ b/sessions/demo/sandbox/entrypoint.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env bash +set -e + +# Codex's ACP adapter authenticates from ~/.codex/auth.json (API-key mode), +# not just OPENAI_API_KEY in env. Seed it so codex sessions don't require login. +if [ -n "${OPENAI_API_KEY:-}" ]; then + mkdir -p "$HOME/.codex" + printf '{"OPENAI_API_KEY":"%s"}' "$OPENAI_API_KEY" > "$HOME/.codex/auth.json" +fi + +# pi: trust projects by default so non-interactive RPC sessions don't block on a prompt. +mkdir -p "$HOME/.config/pi" +printf '{"defaultProjectTrust":"trusted"}' > "$HOME/.config/pi/settings.json" 2>/dev/null || true + +exec sandbox-agent server --no-token --host 0.0.0.0 --port 2468 diff --git a/sessions/demo/seaweedfs/s3.json b/sessions/demo/seaweedfs/s3.json new file mode 100644 index 0000000000..23f0aac141 --- /dev/null +++ b/sessions/demo/seaweedfs/s3.json @@ -0,0 +1,11 @@ +{ + "identities": [ + { + "name": "demo", + "credentials": [ + { "accessKey": "demo", "secretKey": "demosecret" } + ], + "actions": ["Admin", "Read", "Write", "List", "Tagging"] + } + ] +} diff --git a/sessions/demo/sidecar/Dockerfile b/sessions/demo/sidecar/Dockerfile new file mode 100644 index 0000000000..b5f6e8f637 --- /dev/null +++ b/sessions/demo/sidecar/Dockerfile @@ -0,0 +1,10 @@ +FROM node:22-bookworm-slim +WORKDIR /app +# python3 + modal SDK for the Modal provider bridge (Modal has no Node SDK) +RUN apt-get update && apt-get install -y --no-install-recommends python3 python3-pip \ + && pip3 install --break-system-packages --no-cache-dir modal \ + && rm -rf /var/lib/apt/lists/* +COPY package.json package-lock.json* ./ +RUN npm install --no-audit --no-fund +COPY server.js sandbox-provider.js run-lock.js session-persist.js provider-modal.js daytona_snapshot.js modal_bridge.py ./ +CMD ["node", "server.js"] diff --git a/sessions/demo/sidecar/daytona_snapshot.js b/sessions/demo/sidecar/daytona_snapshot.js new file mode 100644 index 0000000000..c24fde22dd --- /dev/null +++ b/sessions/demo/sidecar/daytona_snapshot.js @@ -0,0 +1,60 @@ +// Builds the Daytona snapshot (template-equivalent) used by the daytona case of +// sandbox-provider.js: sandbox-agent + claude + codex + opencode + pi + geesefs. Mirrors the +// E2B template (e2b-template/e2b.Dockerfile) — Daytona sandboxes are x86_64, so the +// linux-x64/amd64 binaries are correct. Run once: node daytona_snapshot.js +// +// Idempotent: if the snapshot already exists and --force isn't passed, it's a no-op. +import { Daytona, Image } from "@daytonaio/sdk"; + +const SNAPSHOT = process.env.DAYTONA_SNAPSHOT || "agenta-sandbox-agent"; +const SA = "/root/.local/share/sandbox-agent/bin"; +const GEESEFS = "https://github.com/yandex-cloud/geesefs/releases/latest/download/geesefs-linux-amd64"; + +// base64 launchers (identical to the E2B template) — exec the per-agent ACP adapter. +const L_CLAUDE = "IyEvdXNyL2Jpbi9lbnYgc2gKc2V0IC1lCmV4ZWMgL3Jvb3QvLmxvY2FsL3NoYXJlL3NhbmRib3gtYWdlbnQvYmluL2FnZW50X3Byb2Nlc3Nlcy9jbGF1ZGUvbm9kZV9tb2R1bGVzLy5iaW4vY2xhdWRlLWFnZW50LWFjcCAiJEAiCg=="; +const L_CODEX = "IyEvdXNyL2Jpbi9lbnYgc2gKc2V0IC1lCmV4ZWMgL3Jvb3QvLmxvY2FsL3NoYXJlL3NhbmRib3gtYWdlbnQvYmluL2FnZW50X3Byb2Nlc3Nlcy9jb2RleC9ub2RlX21vZHVsZXMvLmJpbi9jb2RleC1hY3AgIiRAIgo="; +const L_OPENCODE = "IyEvdXNyL2Jpbi9lbnYgc2gKc2V0IC1lCmV4ZWMgL3Jvb3QvLmxvY2FsL3NoYXJlL3NhbmRib3gtYWdlbnQvYmluL2FnZW50X3Byb2Nlc3Nlcy9vcGVuY29kZS9vcGVuY29kZSBhY3AgIiRAIgo="; +const L_PI = "IyEvdXNyL2Jpbi9lbnYgc2gKc2V0IC1lCmV4ZWMgL3Jvb3QvLmxvY2FsL3NoYXJlL3NhbmRib3gtYWdlbnQvYmluL2FnZW50X3Byb2Nlc3Nlcy9waS9ub2RlX21vZHVsZXMvLmJpbi9waS1hY3AgIiRAIgo="; + +const image = Image.base("debian:12-slim") + .runCommands( + "apt-get update && apt-get install -y --no-install-recommends bash ca-certificates curl git fuse procps sudo jq && rm -rf /var/lib/apt/lists/*", + // node 22 (pi needs >=22.19) + "curl -fsSL https://deb.nodesource.com/setup_22.x | bash - && apt-get install -y nodejs && node --version", + "echo user_allow_other >> /etc/fuse.conf", + // rivet sandbox-agent + "curl -fsSL https://releases.rivet.dev/sandbox-agent/0.4.x/install.sh | sh && (command -v sandbox-agent || cp \"$(find / -name sandbox-agent -type f 2>/dev/null | head -1)\" /usr/local/bin/sandbox-agent) && sandbox-agent --version", + // claude: native binary + adapter + launcher + `mkdir -p ${SA} && CLAUDE_VER=$(curl -fsSL https://storage.googleapis.com/claude-code-dist-86c565f3-f756-42ad-8dfa-d59b1c096819/claude-code-releases/stable) && curl -fsSL -o ${SA}/claude "https://storage.googleapis.com/claude-code-dist-86c565f3-f756-42ad-8dfa-d59b1c096819/claude-code-releases/$CLAUDE_VER/linux-x64/claude" && chmod +x ${SA}/claude`, + `mkdir -p ${SA}/agent_processes/claude && cd ${SA}/agent_processes/claude && npm install @agentclientprotocol/claude-agent-acp@^0.50.0 && echo '${L_CLAUDE}' | base64 -d > ${SA}/agent_processes/claude-acp && chmod +x ${SA}/agent_processes/claude-acp`, + // codex: native binary + adapter + launcher + `curl -fsSL -o /tmp/codex.tgz "https://github.com/openai/codex/releases/latest/download/codex-x86_64-unknown-linux-musl.tar.gz" && tar -xzf /tmp/codex.tgz -C /tmp && mv "$(find /tmp -name 'codex-x86_64-unknown-linux-musl' -type f | head -1)" ${SA}/codex && chmod +x ${SA}/codex && rm -f /tmp/codex.tgz`, + `mkdir -p ${SA}/agent_processes/codex && cd ${SA}/agent_processes/codex && npm install @agentclientprotocol/codex-acp@^1.0.0 && echo '${L_CODEX}' | base64 -d > ${SA}/agent_processes/codex-acp && chmod +x ${SA}/agent_processes/codex-acp`, + // opencode: native x64 binary + launcher + `mkdir -p ${SA}/agent_processes/opencode && curl -fsSL -o /tmp/oc.tgz "https://github.com/anomalyco/opencode/releases/latest/download/opencode-linux-x64.tar.gz" && rm -rf /tmp/ocx && mkdir -p /tmp/ocx && tar -xzf /tmp/oc.tgz -C /tmp/ocx && install -m755 "$(find /tmp/ocx -name opencode -type f | head -1)" ${SA}/agent_processes/opencode/opencode && install -m755 "$(find /tmp/ocx -name opencode -type f | head -1)" ${SA}/opencode && rm -rf /tmp/oc.tgz /tmp/ocx && echo '${L_OPENCODE}' | base64 -d > ${SA}/agent_processes/opencode-acp && chmod +x ${SA}/agent_processes/opencode-acp`, + // pi: adapter + real CLI + launcher + `mkdir -p ${SA}/agent_processes/pi && cd ${SA}/agent_processes/pi && npm install pi-acp@^0.0.31 && npm install -g @earendil-works/pi-coding-agent@0.80.2 && echo '${L_PI}' | base64 -d > ${SA}/agent_processes/pi-acp && chmod +x ${SA}/agent_processes/pi-acp`, + // geesefs + `curl -fsSL -o /usr/local/bin/geesefs ${GEESEFS} && chmod +x /usr/local/bin/geesefs`, + ) + .entrypoint(["sleep", "infinity"]); + +const daytona = new Daytona({ apiKey: process.env.DAYTONA_API_KEY }); +const force = process.argv.includes("--force"); + +const existing = await daytona.snapshot.get(SNAPSHOT).catch(() => null); +if (existing && !force) { + console.log(`snapshot '${SNAPSHOT}' already exists (state=${existing.state}); use --force to rebuild`); + process.exit(0); +} +if (existing && force) { + console.log(`deleting existing '${SNAPSHOT}'…`); + await daytona.snapshot.delete(existing).catch((e) => console.warn("delete:", e.message)); +} + +console.log(`building snapshot '${SNAPSHOT}' (this takes a few minutes)…`); +await daytona.snapshot.create( + { name: SNAPSHOT, image, resources: { cpu: 2, memory: 4, disk: 8 } }, + { onLogs: (l) => process.stdout.write(l), timeout: 1200 }, +); +console.log(`\nsnapshot '${SNAPSHOT}' ready.`); diff --git a/sessions/demo/sidecar/modal_bridge.py b/sessions/demo/sidecar/modal_bridge.py new file mode 100644 index 0000000000..79e9cd1214 --- /dev/null +++ b/sessions/demo/sidecar/modal_bridge.py @@ -0,0 +1,194 @@ +"""Modal provider bridge, called by provider-modal.js as a subprocess. + +Modal has no Node SDK, so the Node sidecar shells out to this. Commands (argv[1]): + up --sid S --endpoint URL [--sandbox-id ID] [--anthropic K] [--openai K] + provision-or-reconnect a Modal sandbox, mount geesefs() from the tunnel, + start sandbox-agent on :2468 (exposed via an encrypted tunnel), print JSON + {"sandbox_id","base_url","cwd"} on the LAST stdout line. + kill --sandbox-id ID terminate the sandbox (cwd stays durable in S3). + +Auth: reads ~/.modal.toml (modal token new) or MODAL_TOKEN_ID/SECRET from env. +The image (sandbox-agent + claude + codex + geesefs) is baked once and cached by Modal. +""" + +import argparse +import json +import sys +import time + +import modal + +AGENT_PORT = 2468 +APP_NAME = "rivet-demo-modal" +GEESEFS = "https://github.com/yandex-cloud/geesefs/releases/latest/download/geesefs-linux-amd64" + + +def log(*a): + print(*a, file=sys.stderr, flush=True) + + +# Image: sandbox-agent + claude + codex + geesefs, baked once and content-cached by Modal. +# fuse + ca-certificates for geesefs/TLS; node for sandbox-agent install. +image = ( + modal.Image.debian_slim(python_version="3.11") + .apt_install("curl", "fuse", "ca-certificates", "git", "procps") + .run_commands( + # node 22 (sandbox-agent installer expects a recent node) + "curl -fsSL https://deb.nodesource.com/setup_22.x | bash -", + "apt-get install -y nodejs", + # rivet sandbox-agent + "curl -fsSL https://releases.rivet.dev/sandbox-agent/0.4.x/install.sh | sh", + "cp $(find / -name sandbox-agent -type f 2>/dev/null | head -1) /usr/local/bin/sandbox-agent || true", + "sandbox-agent --version", + # agents (cloud image is real x64 -> install-agent's x64 binaries are correct) + "sandbox-agent install-agent claude", + "sandbox-agent install-agent codex", + # opencode: install-agent (fail-soft on its verify crash), then ensure the x64 + # native binary is in place at both launcher locations. On real-x64 cloud the + # default download is already correct; we just guard the verify step. + "sandbox-agent install-agent opencode || echo 'opencode verify failed (continuing)'", + "/root/.local/share/sandbox-agent/bin/opencode --version || echo 'opencode binary check skipped'", + # pi: install-agent gives only the pi-acp adapter; the real CLI is a separate npm pkg. + "sandbox-agent install-agent pi || echo 'pi install-agent non-zero (continuing)'", + "npm install -g @earendil-works/pi-coding-agent@0.80.2", + # geesefs + f"curl -fsSL -o /usr/local/bin/geesefs {GEESEFS} && chmod +x /usr/local/bin/geesefs", + "echo user_allow_other >> /etc/fuse.conf", + ) +) + + +def _app(): + return modal.App.lookup(APP_NAME, create_if_missing=True) + + +def _exec(sb, script, timeout=120): + # read the pipes BEFORE wait(): a command with large stdout (e.g. cat /tmp/sa.log) + # can fill the bounded pipe buffer and deadlock if we wait() first. + p = sb.exec("bash", "-c", script, timeout=timeout) + out, err = p.stdout.read(), p.stderr.read() + p.wait() + return p.returncode, out, err + + +def up(args): + app = _app() + sb = None + if args.sandbox_id: + try: + sb = modal.Sandbox.from_id(args.sandbox_id) + # poke it; from_id on a dead sandbox raises on first use + sb.exec("bash", "-c", "true").wait() + log(f"reconnected to {args.sandbox_id}") + except Exception as e: + log(f"reconnect failed ({e}); creating fresh") + sb = None + + if sb is None: + sb = modal.Sandbox.create( + "sleep", + "infinity", + app=app, + image=image, + timeout=3600, + encrypted_ports=[AGENT_PORT], + experimental_options={"vm_runtime": True}, # required for /dev/fuse + ) + log(f"created sandbox {sb.object_id}") + + cwd = "/root/work" + # codex auth.json (the ACP adapter authenticates from this file, not just env) + if args.openai: + _exec( + sb, + f"mkdir -p /root/.codex && printf '{{\"OPENAI_API_KEY\":\"%s\"}}' '{args.openai}' > /root/.codex/auth.json", + ) + # pi: trust projects so non-interactive RPC sessions don't block on a trust prompt + _exec( + sb, + 'mkdir -p /root/.config/pi && printf \'{"defaultProjectTrust":"trusted"}\' > /root/.config/pi/settings.json', + ) + + # mount geesefs if not already healthily mounted. A stale FUSE endpoint reports as a + # mountpoint but errors with "Transport endpoint is not connected" — treat as unmounted. + rc, out, _ = _exec( + sb, f"ls {cwd} >/dev/null 2>&1 && mountpoint -q {cwd} && echo yes || echo no" + ) + if "yes" not in out: + _exec(sb, f"fusermount -u {cwd} 2>/dev/null; umount -l {cwd} 2>/dev/null; true") + rc, out, err = _exec( + sb, + f"mkdir -p {cwd} && AWS_ACCESS_KEY_ID={args.s3_key} AWS_SECRET_ACCESS_KEY={args.s3_secret} " + f"geesefs --endpoint {args.endpoint} --region us-east-1 --no-detect --fsync-on-close " + f"-o allow_other {args.bucket}:{args.sid} {cwd} && echo MOUNT_OK", + timeout=90, + ) + if "MOUNT_OK" not in out: + raise RuntimeError(f"geesefs mount failed: {err or out}") + + # start sandbox-agent server in the background if not already serving + rc, out, _ = _exec( + sb, + f"curl -sf http://localhost:{AGENT_PORT}/v1/health >/dev/null && echo up || echo down", + ) + if "up" not in out: + env_exports = "" + if args.anthropic: + env_exports += f"ANTHROPIC_API_KEY='{args.anthropic}' " + if args.openai: + env_exports += f"OPENAI_API_KEY='{args.openai}' " + # detached; nohup so it outlives this exec + sb.exec( + "bash", + "-c", + f"{env_exports} nohup sandbox-agent server --no-token --host 0.0.0.0 --port {AGENT_PORT} " + f">/tmp/sa.log 2>&1 &", + ) + # poll health + for _ in range(40): + rc, out, _ = _exec( + sb, + f"curl -sf http://localhost:{AGENT_PORT}/v1/health >/dev/null && echo up || echo down", + ) + if "up" in out: + break + time.sleep(1) + else: + _, log_out, _ = _exec(sb, "cat /tmp/sa.log") + raise RuntimeError(f"sandbox-agent did not come up: {log_out}") + + base_url = sb.tunnels()[AGENT_PORT].url + print( + json.dumps({"sandbox_id": sb.object_id, "base_url": base_url, "cwd": cwd}), + flush=True, + ) + + +def kill(args): + sb = modal.Sandbox.from_id(args.sandbox_id) + sb.terminate() + print(json.dumps({"killed": args.sandbox_id}), flush=True) + + +def main(): + ap = argparse.ArgumentParser() + sub = ap.add_subparsers(dest="cmd", required=True) + u = sub.add_parser("up") + u.add_argument("--sid", required=True) + u.add_argument("--endpoint", required=True) + u.add_argument("--sandbox-id", dest="sandbox_id", default=None) + u.add_argument("--anthropic", default=None) + u.add_argument("--openai", default=None) + u.add_argument("--s3-key", dest="s3_key", default="demo") + u.add_argument("--s3-secret", dest="s3_secret", default="demosecret") + u.add_argument("--bucket", default="demo") + u.set_defaults(fn=up) + k = sub.add_parser("kill") + k.add_argument("--sandbox-id", dest="sandbox_id", required=True) + k.set_defaults(fn=kill) + args = ap.parse_args() + args.fn(args) + + +if __name__ == "__main__": + main() diff --git a/sessions/demo/sidecar/package-lock.json b/sessions/demo/sidecar/package-lock.json new file mode 100644 index 0000000000..d6b3dcff9f --- /dev/null +++ b/sessions/demo/sidecar/package-lock.json @@ -0,0 +1,4211 @@ +{ + "name": "demo-sidecar", + "version": "0.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "demo-sidecar", + "version": "0.0.0", + "dependencies": { + "@daytonaio/sdk": "^0.190.1", + "@e2b/code-interpreter": "^2.6.1", + "dockerode": "^5.0.0", + "express": "^4.21.2", + "get-port": "^7.2.0", + "ioredis": "^5.11.1", + "sandbox-agent": "0.4.x" + } + }, + "node_modules/@agentclientprotocol/sdk": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/@agentclientprotocol/sdk/-/sdk-0.16.1.tgz", + "integrity": "sha512-1ad+Sc/0sCtZGHthxxvgEUo5Wsbw16I+aF+YwdiLnPwkZG8KAGUEAPK6LM6Pf69lCyJPt1Aomk1d+8oE3C4ZEw==", + "license": "Apache-2.0", + "peerDependencies": { + "zod": "^3.25.0 || ^4.0.0" + } + }, + "node_modules/@aws-crypto/crc32": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/crc32/-/crc32-5.2.0.tgz", + "integrity": "sha512-nLbCWqQNgUiwwtFsen1AdzAtvuLRsQS8rYgMuxCrdKf9kOssamGLuPwyTY9wyYblNr9+1XM8v6zoDTPPSIeANg==", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-crypto/crc32c": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/crc32c/-/crc32c-5.2.0.tgz", + "integrity": "sha512-+iWb8qaHLYKrNvGRbiYRHSdKRWhto5XlZUEBwDjYNf+ly5SVYG6zEoYIdxvf5R3zyeP16w4PLBn3rH1xc74Rag==", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-crypto/sha1-browser": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha1-browser/-/sha1-browser-5.2.0.tgz", + "integrity": "sha512-OH6lveCFfcDjX4dbAvCFSYUjJZjDr/3XJ3xHtjn3Oj5b9RjojQo8npoLeA/bNwkOkrSQ0wgrHzXk4tDRxGKJeg==", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/supports-web-crypto": "^5.2.0", + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "@aws-sdk/util-locate-window": "^3.0.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-crypto/sha256-browser": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-browser/-/sha256-browser-5.2.0.tgz", + "integrity": "sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw==", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/sha256-js": "^5.2.0", + "@aws-crypto/supports-web-crypto": "^5.2.0", + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "@aws-sdk/util-locate-window": "^3.0.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-crypto/sha256-js": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-js/-/sha256-js-5.2.0.tgz", + "integrity": "sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA==", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-crypto/supports-web-crypto": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/supports-web-crypto/-/supports-web-crypto-5.2.0.tgz", + "integrity": "sha512-iAvUotm021kM33eCdNfwIN//F77/IADDSs58i+MDaOqFrVjZo9bAal0NK7HurRuWLLpF1iLX7gbWrjHjeo+YFg==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-crypto/util": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/util/-/util-5.2.0.tgz", + "integrity": "sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "^3.222.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-sdk/checksums": { + "version": "3.1000.8", + "resolved": "https://registry.npmjs.org/@aws-sdk/checksums/-/checksums-3.1000.8.tgz", + "integrity": "sha512-v0U9S7gBIme3OTgt1LdbAF4RpvavCc+4GK1+1xqAcqtbrHsEhjQo6R45LKcjhs/+WrRJij1Y0Gztw7QPAIeUfA==", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/crc32": "5.2.0", + "@aws-crypto/crc32c": "5.2.0", + "@aws-crypto/util": "5.2.0", + "@aws-sdk/core": "^3.974.23", + "@aws-sdk/types": "^3.973.13", + "@smithy/core": "^3.24.6", + "@smithy/types": "^4.14.3", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/client-s3": { + "version": "3.1075.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.1075.0.tgz", + "integrity": "sha512-h1A6nIl1YX6Y45enGsTK7ef3ZrOnBiQJ1qF5R2K/nMWfsu6A9mc2Y5T66nxerABzyjjyyvign3MrzafnFoQKmA==", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/sha1-browser": "5.2.0", + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "^3.974.23", + "@aws-sdk/credential-provider-node": "^3.972.58", + "@aws-sdk/middleware-flexible-checksums": "^3.974.33", + "@aws-sdk/middleware-sdk-s3": "^3.972.54", + "@aws-sdk/signature-v4-multi-region": "^3.996.35", + "@aws-sdk/types": "^3.973.13", + "@smithy/core": "^3.24.6", + "@smithy/fetch-http-handler": "^5.4.6", + "@smithy/node-http-handler": "^4.7.6", + "@smithy/types": "^4.14.3", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/core": { + "version": "3.974.23", + "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.974.23.tgz", + "integrity": "sha512-MiWR/uWjxjFXGzrE0Ghc5lWxUxzHsUWFhV+OX7M4cR9SrmrnZs6TXavnCWnzzdwJeFri34xQo81rvGNzK3c4BQ==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "^3.973.13", + "@aws-sdk/xml-builder": "^3.972.31", + "@aws/lambda-invoke-store": "^0.2.2", + "@smithy/core": "^3.24.6", + "@smithy/signature-v4": "^5.4.6", + "@smithy/types": "^4.14.3", + "bowser": "^2.11.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-env": { + "version": "3.972.49", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.972.49.tgz", + "integrity": "sha512-liB3yQNHCM9k/gu/w36XHMKPluT7HTlnGUhRbBGSISDQkcr/Sy1zsZabiuvQj8WG5yW573u9RehrBvvnIQ9OEQ==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "^3.974.23", + "@aws-sdk/types": "^3.973.13", + "@smithy/core": "^3.24.6", + "@smithy/types": "^4.14.3", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-http": { + "version": "3.972.51", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.972.51.tgz", + "integrity": "sha512-XET0H2oofciJ5lMRWNIvRjAP7Q3wv2XT+JtJJEdhPWUMwe3TvQ9qcxonpu7vXmNngncvFpi4E2It+Tamas/naA==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "^3.974.23", + "@aws-sdk/types": "^3.973.13", + "@smithy/core": "^3.24.6", + "@smithy/fetch-http-handler": "^5.4.6", + "@smithy/node-http-handler": "^4.7.6", + "@smithy/types": "^4.14.3", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-ini": { + "version": "3.972.56", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.972.56.tgz", + "integrity": "sha512-IAmc61hbgQiHht9U3x0tnRwz0lzdwOwD/i9voRgdJrKamF+JtmrBOsW9GwB7mfFonNWOWL4qARWYrF8veEMe3w==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "^3.974.23", + "@aws-sdk/credential-provider-env": "^3.972.49", + "@aws-sdk/credential-provider-http": "^3.972.51", + "@aws-sdk/credential-provider-login": "^3.972.55", + "@aws-sdk/credential-provider-process": "^3.972.49", + "@aws-sdk/credential-provider-sso": "^3.972.55", + "@aws-sdk/credential-provider-web-identity": "^3.972.55", + "@aws-sdk/nested-clients": "^3.997.23", + "@aws-sdk/types": "^3.973.13", + "@smithy/core": "^3.24.6", + "@smithy/credential-provider-imds": "^4.3.7", + "@smithy/types": "^4.14.3", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-login": { + "version": "3.972.55", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-login/-/credential-provider-login-3.972.55.tgz", + "integrity": "sha512-hBBkANo3cDn+h2qxxzER4a+J8JCO9o9Z/YYmU7iky6AcaarX5RRdRcHNC6SLdwY0vAXQygn6soUbDqPn3GghaA==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "^3.974.23", + "@aws-sdk/nested-clients": "^3.997.23", + "@aws-sdk/types": "^3.973.13", + "@smithy/core": "^3.24.6", + "@smithy/types": "^4.14.3", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-node": { + "version": "3.972.58", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.972.58.tgz", + "integrity": "sha512-OyCLVmSI7pZO8hxwNVX6pXhTVlJqRBTp+ijdEfJSUj0RyjHnF602OfAarOzGq6wkGodeFkYBt8MmJ6A6ycRgWw==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/credential-provider-env": "^3.972.49", + "@aws-sdk/credential-provider-http": "^3.972.51", + "@aws-sdk/credential-provider-ini": "^3.972.56", + "@aws-sdk/credential-provider-process": "^3.972.49", + "@aws-sdk/credential-provider-sso": "^3.972.55", + "@aws-sdk/credential-provider-web-identity": "^3.972.55", + "@aws-sdk/types": "^3.973.13", + "@smithy/core": "^3.24.6", + "@smithy/credential-provider-imds": "^4.3.7", + "@smithy/types": "^4.14.3", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-process": { + "version": "3.972.49", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.972.49.tgz", + "integrity": "sha512-C8h36lBuC/RnBSsjlO+dn6xZm3KbAl5vpJaVPAfQnMmz2/OISmKOc8XZcqMQgO2ADwBYNRMM6Kf3vz9G/TulMQ==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "^3.974.23", + "@aws-sdk/types": "^3.973.13", + "@smithy/core": "^3.24.6", + "@smithy/types": "^4.14.3", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-sso": { + "version": "3.972.55", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.972.55.tgz", + "integrity": "sha512-1FkOz74Ea5QGS9jtIoXp55T/IkSS3spv+nLTT07fRY/+T5xmEOqaYBVIaEmX4zTNvbV6g2lrtlaVKWEoNyJt3w==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "^3.974.23", + "@aws-sdk/nested-clients": "^3.997.23", + "@aws-sdk/token-providers": "3.1074.0", + "@aws-sdk/types": "^3.973.13", + "@smithy/core": "^3.24.6", + "@smithy/types": "^4.14.3", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-web-identity": { + "version": "3.972.55", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.972.55.tgz", + "integrity": "sha512-g2BoECD1q01kTPByi56+VLVvdWDzMkKIcr77qixpqH0okw2t0U5CoPv+6S8v/D1Y2Wa6QKKtn6XAtDzP+Kfpvg==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "^3.974.23", + "@aws-sdk/nested-clients": "^3.997.23", + "@aws-sdk/types": "^3.973.13", + "@smithy/core": "^3.24.6", + "@smithy/types": "^4.14.3", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/lib-storage": { + "version": "3.1075.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/lib-storage/-/lib-storage-3.1075.0.tgz", + "integrity": "sha512-Npdac3/Fv994iCdFFeqloPel+95Zv6dRiRUpfey6W/CqpB/QdnYP60U4YBhBgJj6V5020Pm3ad0HV4WzCE5hHQ==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/core": "^3.24.6", + "@smithy/types": "^4.14.3", + "buffer": "5.6.0", + "events": "3.3.0", + "stream-browserify": "3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "@aws-sdk/client-s3": "^3.1075.0" + } + }, + "node_modules/@aws-sdk/middleware-flexible-checksums": { + "version": "3.974.33", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.974.33.tgz", + "integrity": "sha512-qMgQSPemQq2/eW/e/0+SpY4kYR5L7dUgBiVdEc5bd+ztHNv07ZMYiI+sTiir3TgKndFfglSw/VFi7oZJ6bZ63g==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/checksums": "^3.1000.8", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/middleware-sdk-s3": { + "version": "3.972.54", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.972.54.tgz", + "integrity": "sha512-GDfDQ0gwLFRKN9gWIKcmVrHJ3e7XagnY7N1LLzMVNgnOnuY7f/ALgmy3CuBjosWD95T/Z6e+gs1IeWmLPkyLKQ==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "^3.974.23", + "@aws-sdk/signature-v4-multi-region": "^3.996.35", + "@aws-sdk/types": "^3.973.13", + "@smithy/core": "^3.24.6", + "@smithy/types": "^4.14.3", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/nested-clients": { + "version": "3.997.23", + "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.997.23.tgz", + "integrity": "sha512-gO93ZPsI2bxeFZD42f1/qjDw6FAZkNZcKRO94LIiT03fzOmcJ9e/tunxjVjA1Rl69ClmVJzz8H3G9CdKef10PA==", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "^3.974.23", + "@aws-sdk/signature-v4-multi-region": "^3.996.35", + "@aws-sdk/types": "^3.973.13", + "@smithy/core": "^3.24.6", + "@smithy/fetch-http-handler": "^5.4.6", + "@smithy/node-http-handler": "^4.7.6", + "@smithy/types": "^4.14.3", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/signature-v4-multi-region": { + "version": "3.996.35", + "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.996.35.tgz", + "integrity": "sha512-6L/VWs+Wch2stHemCGTmUNqKLMzURxQDK5boNG3Jn3kAOp71meDUuS5sbObpEvFxHDq0uWeSLFDNSYsjNt+Dlg==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "^3.973.13", + "@smithy/signature-v4": "^5.4.6", + "@smithy/types": "^4.14.3", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/token-providers": { + "version": "3.1074.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.1074.0.tgz", + "integrity": "sha512-pv80IzgGW4RnXWtft692chZOM9i6PhebVsLCcnaM4dBEPZva2fE6FXAHs76G7Rc7s3yGyX/68G0nZMrUy+Vmpg==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "^3.974.23", + "@aws-sdk/nested-clients": "^3.997.23", + "@aws-sdk/types": "^3.973.13", + "@smithy/core": "^3.24.6", + "@smithy/types": "^4.14.3", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/types": { + "version": "3.973.13", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.973.13.tgz", + "integrity": "sha512-pEHZqRkAlHfnfAU9tK+WpKv/gBNjGJrHMgA3A0iYRGyswBS2t0pfez+lWlwktb3Bqa0ovh7w/QJTFwp3fDxLNg==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.14.3", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/util-locate-window": { + "version": "3.965.8", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.965.8.tgz", + "integrity": "sha512-uUbMs1cBZPafD0ohUj6EwNf0fPZ534NvBxHox4hjX+0Rxq5paSYUem7+hi833pYrzrcnBATKIYpR02MDXT5M9g==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/xml-builder": { + "version": "3.972.31", + "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.972.31.tgz", + "integrity": "sha512-SzE4Pgyl+hDF+BuyuzxUSpwnuUu9lJuO1YGgteG89/4Qv0+2IQiVQqdbPV32IozLvXWQChPQcdkk/sKvb1QHiQ==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.14.3", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws/lambda-invoke-store": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/@aws/lambda-invoke-store/-/lambda-invoke-store-0.2.4.tgz", + "integrity": "sha512-iY8yvjE0y651BixKNPgmv1WrQc+GZ142sb0z4gYnChDDY2YqI4P/jsSopBWrKfAt7LOJAkOXt7rC/hms+WclQQ==", + "license": "Apache-2.0", + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@balena/dockerignore": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@balena/dockerignore/-/dockerignore-1.0.2.tgz", + "integrity": "sha512-wMue2Sy4GAVTk6Ic4tJVcnfdau+gx2EnG7S+uAEe+TWJFqE4YoWN4/H8MSLj4eYJKxGg26lZwboEniNiNwZQ6Q==", + "license": "Apache-2.0" + }, + "node_modules/@bufbuild/protobuf": { + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/@bufbuild/protobuf/-/protobuf-2.12.1.tgz", + "integrity": "sha512-BvAMfS6LrgZiryOAZ4pBYucu4wG/Ei/9o9DZ9akbREnMLbPJiom2i8b9C8IsKErQoiKqVhrerzt3kOT/RrzLHg==", + "license": "(Apache-2.0 AND BSD-3-Clause)" + }, + "node_modules/@connectrpc/connect": { + "version": "2.0.0-rc.3", + "resolved": "https://registry.npmjs.org/@connectrpc/connect/-/connect-2.0.0-rc.3.tgz", + "integrity": "sha512-ARBt64yEyKbanyRETTjcjJuHr2YXorzQo0etyS5+P6oSeW8xEuzajA9g+zDnMcj1hlX2dQE93foIWQGfpru7gQ==", + "license": "Apache-2.0", + "peerDependencies": { + "@bufbuild/protobuf": "^2.2.0" + } + }, + "node_modules/@connectrpc/connect-web": { + "version": "2.0.0-rc.3", + "resolved": "https://registry.npmjs.org/@connectrpc/connect-web/-/connect-web-2.0.0-rc.3.tgz", + "integrity": "sha512-w88P8Lsn5CCsA7MFRl2e6oLY4J/5toiNtJns/YJrlyQaWOy3RO8pDgkz+iIkG98RPMhj2thuBvsd3Cn4DKKCkw==", + "license": "Apache-2.0", + "peerDependencies": { + "@bufbuild/protobuf": "^2.2.0", + "@connectrpc/connect": "2.0.0-rc.3" + } + }, + "node_modules/@daytona/api-client": { + "version": "0.190.1", + "resolved": "https://registry.npmjs.org/@daytona/api-client/-/api-client-0.190.1.tgz", + "integrity": "sha512-69/J9B1YuJIVa4DT4/r5zSzy6vKpV7Cz2l6xZYhYyAjiLunqn7nlAxbDOXE08pmhuOK38C/8g/4SeBHdkARFQg==", + "license": "Apache-2.0", + "dependencies": { + "axios": "^1.6.1" + } + }, + "node_modules/@daytona/toolbox-api-client": { + "version": "0.190.1", + "resolved": "https://registry.npmjs.org/@daytona/toolbox-api-client/-/toolbox-api-client-0.190.1.tgz", + "integrity": "sha512-vObFluXvY7tJpU4en58TrZHdjueUDpTD7yZlDnYHypPUdGsTUdyWbAJUOSs0WyV9HHWBzwEzauOdif0e5Xytkg==", + "license": "Apache-2.0", + "dependencies": { + "axios": "^1.6.1" + } + }, + "node_modules/@daytonaio/sdk": { + "version": "0.190.1", + "resolved": "https://registry.npmjs.org/@daytonaio/sdk/-/sdk-0.190.1.tgz", + "integrity": "sha512-mLGLZWFVvwLfhFpdMQG1OvfskQL/04go+iXC81n1Xcnkd6qR/vhVLDuIakN0/dn55zIGjhW7f/8U4PozLSHeBg==", + "deprecated": "Moved to @daytona/sdk, same API, no breaking changes. Please update: npm uninstall @daytonaio/sdk && npm i @daytona/sdk", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/client-s3": "^3.787.0", + "@aws-sdk/lib-storage": "^3.798.0", + "@daytona/api-client": "0.190.1", + "@daytona/toolbox-api-client": "0.190.1", + "@iarna/toml": "^2.2.5", + "@opentelemetry/api": "^1.9.0", + "@opentelemetry/exporter-trace-otlp-http": "^0.217.0", + "@opentelemetry/instrumentation-http": "^0.217.0", + "@opentelemetry/otlp-exporter-base": "0.217.0", + "@opentelemetry/resources": "2.7.1", + "@opentelemetry/sdk-node": "^0.217.0", + "@opentelemetry/sdk-trace-base": "^2.7.1", + "@opentelemetry/semantic-conventions": "^1.40.0", + "axios": "^1.15.2", + "busboy": "^1.0.0", + "dotenv": "^17.0.1", + "expand-tilde": "^2.0.2", + "fast-glob": "^3.3.0", + "form-data": "^4.0.4", + "isomorphic-ws": "^5.0.0", + "pathe": "^2.0.3", + "shell-quote": "^1.8.2", + "tar": "^7.5.11" + } + }, + "node_modules/@e2b/code-interpreter": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/@e2b/code-interpreter/-/code-interpreter-2.6.1.tgz", + "integrity": "sha512-5sKJaw2w/XZNHq7NpcNm8cpGu3IHlwLjavRd6V5BsVQyyl+5zGnSWE+EvA6W1VHDbPXiSdm6pN8cREWAifdrJw==", + "license": "MIT", + "dependencies": { + "e2b": "^2.28.0" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/@grpc/grpc-js": { + "version": "1.14.4", + "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.14.4.tgz", + "integrity": "sha512-k9Dj3DV/itK9D06Y8f190Qgop7/Ui+D0njFV3LHMPwPT75DpXLQohE9Wmz0QElrJnzsjB7KPWiKJbOl7IPDArQ==", + "license": "Apache-2.0", + "dependencies": { + "@grpc/proto-loader": "^0.8.0", + "@js-sdsl/ordered-map": "^4.4.2" + }, + "engines": { + "node": ">=12.10.0" + } + }, + "node_modules/@grpc/proto-loader": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.8.1.tgz", + "integrity": "sha512-wtF6h+DY6M3YaDBPAmvuuA6jV8Sif9MjtOI5euKFWRgCDl5PeDpPsHR9u2l6St5ceY8AZgoNDww5+HvEsXFsGg==", + "license": "Apache-2.0", + "dependencies": { + "lodash.camelcase": "^4.3.0", + "long": "^5.0.0", + "protobufjs": "^7.5.5", + "yargs": "^17.7.2" + }, + "bin": { + "proto-loader-gen-types": "build/bin/proto-loader-gen-types.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@grpc/proto-loader/node_modules/protobufjs": { + "version": "7.6.4", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.6.4.tgz", + "integrity": "sha512-RJJPTTpvFfHcWLkIa2JFWK4XvtSzS0yEWDmunqHXli1h3JlkbcQZXDZdcWxv+JK3Xsl5/UFDPZ0iGm7DAengYw==", + "hasInstallScript": true, + "license": "BSD-3-Clause", + "dependencies": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.5", + "@protobufjs/eventemitter": "^1.1.1", + "@protobufjs/fetch": "^1.1.1", + "@protobufjs/float": "^1.0.2", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.1", + "@types/node": ">=13.7.0", + "long": "^5.3.2" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/@iarna/toml": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/@iarna/toml/-/toml-2.2.5.tgz", + "integrity": "sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg==", + "license": "ISC" + }, + "node_modules/@ioredis/commands": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@ioredis/commands/-/commands-1.10.0.tgz", + "integrity": "sha512-UmeW7z4LfctwoQ5wkhVzgq8tXkreED2xZGpX+Bg+zA+WJFZCT6c062AfCK/Dfk81xZnnwdhJCUMkitihRaoC2Q==", + "license": "MIT" + }, + "node_modules/@isaacs/cliui": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-9.0.0.tgz", + "integrity": "sha512-AokJm4tuBHillT+FpMtxQ60n8ObyXBatq7jD2/JA9dxbDDokKQm8KMht5ibGzLVU9IJDIKK4TPKgMHEYMn3lMg==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" + } + }, + "node_modules/@isaacs/fs-minipass": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", + "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==", + "license": "ISC", + "dependencies": { + "minipass": "^7.0.4" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@js-sdsl/ordered-map": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/@js-sdsl/ordered-map/-/ordered-map-4.4.2.tgz", + "integrity": "sha512-iUKgm52T8HOE/makSxjqoWhe95ZJA1/G1sYsGev2JDKUSS14KAgg1LHb+Ba+IPow0xflbnSkOsZcO08C7w1gYw==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/js-sdsl" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@opentelemetry/api": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.1.tgz", + "integrity": "sha512-gLyJlPHPZYdAk1JENA9LeHejZe1Ti77/pTeFm/nMXmQH/HFZlcS/O2XJB+L8fkbrNSqhdtlvjBVjxwUYanNH5Q==", + "license": "Apache-2.0", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@opentelemetry/api-logs": { + "version": "0.217.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.217.0.tgz", + "integrity": "sha512-Cdq0jW2lknrNfrAm92MyEAvpe2cRsKjdnQLHUL6xRA4IVUnsWx6P65E7NcUO0Y+L4w1Aee5iV8FvjSwd+lrs9A==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api": "^1.3.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@opentelemetry/configuration": { + "version": "0.217.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/configuration/-/configuration-0.217.0.tgz", + "integrity": "sha512-xCtrYOhBqdy6ZOMfe0Oa73ZKF+2LMhoOv4L5vmwAHVvOXUg+V3fvKuEIr9ZyD0Ow+vxllEjWO6PV1wd0DOtyvw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "2.7.1", + "yaml": "^2.0.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.9.0" + } + }, + "node_modules/@opentelemetry/context-async-hooks": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/context-async-hooks/-/context-async-hooks-2.7.1.tgz", + "integrity": "sha512-OPFBYuXEn1E4ja3Y6eeA7O+ZnLBNcXTV5Cgsn1VaqBZ6hC5FnpZPLBNme1LJY8ZtF4aOujPKFoeWN4ik487KuQ==", + "license": "Apache-2.0", + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/core": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-2.7.1.tgz", + "integrity": "sha512-QAqIj32AtK6+pEVNG7EOVxHdE06RP+FM5qpiEJ4RtDcFIqKUZHYhl7/7UY5efhwmwNAg7j8QbJVBLxMerc0+gw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/semantic-conventions": "^1.29.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/exporter-logs-otlp-grpc": { + "version": "0.217.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-logs-otlp-grpc/-/exporter-logs-otlp-grpc-0.217.0.tgz", + "integrity": "sha512-vC5S0Dc+noxD86CVtNu1+awCHPA5Kewi1Sg23ps+9lh4YifwsKXh3pe4XTNEKtUJiAcjpJ5dqStGakLbrSE+YQ==", + "license": "Apache-2.0", + "dependencies": { + "@grpc/grpc-js": "^1.14.3", + "@opentelemetry/core": "2.7.1", + "@opentelemetry/otlp-exporter-base": "0.217.0", + "@opentelemetry/otlp-grpc-exporter-base": "0.217.0", + "@opentelemetry/otlp-transformer": "0.217.0", + "@opentelemetry/sdk-logs": "0.217.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/exporter-logs-otlp-http": { + "version": "0.217.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-logs-otlp-http/-/exporter-logs-otlp-http-0.217.0.tgz", + "integrity": "sha512-KfLAdt1uilVE+3FxbgVnp2ZrzqbIawzcesnRoi+Kh9ckB5Ld5D8btUgoBvwTbdmuNx1j6b132Wsh72azq+pPNQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.217.0", + "@opentelemetry/core": "2.7.1", + "@opentelemetry/otlp-exporter-base": "0.217.0", + "@opentelemetry/otlp-transformer": "0.217.0", + "@opentelemetry/sdk-logs": "0.217.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/exporter-logs-otlp-proto": { + "version": "0.217.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-logs-otlp-proto/-/exporter-logs-otlp-proto-0.217.0.tgz", + "integrity": "sha512-Se0GG/ZO24mQTlQj7zprR4pNI0nKe4lPDPBsuJmi6508b9TlZEuUd3EfyuHk6oJxzL7fGyDFYAbxNigQvRP2ZQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.217.0", + "@opentelemetry/core": "2.7.1", + "@opentelemetry/otlp-exporter-base": "0.217.0", + "@opentelemetry/otlp-transformer": "0.217.0", + "@opentelemetry/resources": "2.7.1", + "@opentelemetry/sdk-logs": "0.217.0", + "@opentelemetry/sdk-trace-base": "2.7.1" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/exporter-logs-otlp-proto/node_modules/@opentelemetry/sdk-trace-base": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-2.7.1.tgz", + "integrity": "sha512-NAYIlsF8MPUsKqJMiDQJTMPOmlbawC1Iz/omMLygZ1C9am8fTKYjTaI+OZM+WTY3t3Glo0wnOg/6/pac6RGPPw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "2.7.1", + "@opentelemetry/resources": "2.7.1", + "@opentelemetry/semantic-conventions": "^1.29.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.3.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/exporter-metrics-otlp-grpc": { + "version": "0.217.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-metrics-otlp-grpc/-/exporter-metrics-otlp-grpc-0.217.0.tgz", + "integrity": "sha512-0GpJKnCoVaVA1rKBMVPHziznfOQlXgH72S9ktjBAF1AnAVPzX7vVEBGrhwiSxxHDAiefXk+J8znApsMb/K6Z3w==", + "license": "Apache-2.0", + "dependencies": { + "@grpc/grpc-js": "^1.14.3", + "@opentelemetry/core": "2.7.1", + "@opentelemetry/exporter-metrics-otlp-http": "0.217.0", + "@opentelemetry/otlp-exporter-base": "0.217.0", + "@opentelemetry/otlp-grpc-exporter-base": "0.217.0", + "@opentelemetry/otlp-transformer": "0.217.0", + "@opentelemetry/resources": "2.7.1", + "@opentelemetry/sdk-metrics": "2.7.1" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/exporter-metrics-otlp-http": { + "version": "0.217.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-metrics-otlp-http/-/exporter-metrics-otlp-http-0.217.0.tgz", + "integrity": "sha512-1zkMzzhiNJdVmLxuwkltqWGw4fOOam47bqRxmuQNjyKJe/9NmY5cIrZ4kiQV7sVGxoOgT0ZvGUfLcjvtpC/b9Q==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "2.7.1", + "@opentelemetry/otlp-exporter-base": "0.217.0", + "@opentelemetry/otlp-transformer": "0.217.0", + "@opentelemetry/resources": "2.7.1", + "@opentelemetry/sdk-metrics": "2.7.1" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/exporter-metrics-otlp-proto": { + "version": "0.217.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-metrics-otlp-proto/-/exporter-metrics-otlp-proto-0.217.0.tgz", + "integrity": "sha512-nfxt/KxVGFkjkO/M+58y1ugHu/dwPtxG4eYq0KApcQ7xk5CHzhdn+IuLZfDSvNDrJ3Uy5q++Fj/wbK7i8yryfQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "2.7.1", + "@opentelemetry/exporter-metrics-otlp-http": "0.217.0", + "@opentelemetry/otlp-exporter-base": "0.217.0", + "@opentelemetry/otlp-transformer": "0.217.0", + "@opentelemetry/resources": "2.7.1", + "@opentelemetry/sdk-metrics": "2.7.1" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/exporter-prometheus": { + "version": "0.217.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-prometheus/-/exporter-prometheus-0.217.0.tgz", + "integrity": "sha512-U9MCXxJu0sBCh5aEkylYRR4xVIL8D1CW6dGwvYXbfFr0qveSorfD0XJchCAWoW6QfAAIcY/yxjf4Dj8OgkHBPw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "2.7.1", + "@opentelemetry/resources": "2.7.1", + "@opentelemetry/sdk-metrics": "2.7.1", + "@opentelemetry/semantic-conventions": "^1.29.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/exporter-trace-otlp-grpc": { + "version": "0.217.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-trace-otlp-grpc/-/exporter-trace-otlp-grpc-0.217.0.tgz", + "integrity": "sha512-fPZs2fw7veLH3pEKu8vSepUa2fQpAE2P7al6qU10aH9GrEJJ8YaPgsd5xON7by5rbcEVS71FOU2aWyK6nzB7VQ==", + "license": "Apache-2.0", + "dependencies": { + "@grpc/grpc-js": "^1.14.3", + "@opentelemetry/core": "2.7.1", + "@opentelemetry/otlp-exporter-base": "0.217.0", + "@opentelemetry/otlp-grpc-exporter-base": "0.217.0", + "@opentelemetry/otlp-transformer": "0.217.0", + "@opentelemetry/resources": "2.7.1", + "@opentelemetry/sdk-trace-base": "2.7.1" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/exporter-trace-otlp-grpc/node_modules/@opentelemetry/sdk-trace-base": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-2.7.1.tgz", + "integrity": "sha512-NAYIlsF8MPUsKqJMiDQJTMPOmlbawC1Iz/omMLygZ1C9am8fTKYjTaI+OZM+WTY3t3Glo0wnOg/6/pac6RGPPw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "2.7.1", + "@opentelemetry/resources": "2.7.1", + "@opentelemetry/semantic-conventions": "^1.29.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.3.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/exporter-trace-otlp-http": { + "version": "0.217.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-trace-otlp-http/-/exporter-trace-otlp-http-0.217.0.tgz", + "integrity": "sha512-38YQoqtYjglz2GV94LGUN/djLvxtvGIQO68o6qAFPVshjmwSdX1F2i0c7vn3lEl1L5B/YqjB/bgKXaVx7KO+RQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "2.7.1", + "@opentelemetry/otlp-exporter-base": "0.217.0", + "@opentelemetry/otlp-transformer": "0.217.0", + "@opentelemetry/resources": "2.7.1", + "@opentelemetry/sdk-trace-base": "2.7.1" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/exporter-trace-otlp-http/node_modules/@opentelemetry/sdk-trace-base": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-2.7.1.tgz", + "integrity": "sha512-NAYIlsF8MPUsKqJMiDQJTMPOmlbawC1Iz/omMLygZ1C9am8fTKYjTaI+OZM+WTY3t3Glo0wnOg/6/pac6RGPPw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "2.7.1", + "@opentelemetry/resources": "2.7.1", + "@opentelemetry/semantic-conventions": "^1.29.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.3.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/exporter-trace-otlp-proto": { + "version": "0.217.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-trace-otlp-proto/-/exporter-trace-otlp-proto-0.217.0.tgz", + "integrity": "sha512-nPV8gKHUiSuTZpQcnZU3/pBlK7crSyEGpZuh5MtWySB0vv6NNG0QvvfKitQt+Fc2Mc6qfyU54KlZcurwoTbrVg==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "2.7.1", + "@opentelemetry/otlp-exporter-base": "0.217.0", + "@opentelemetry/otlp-transformer": "0.217.0", + "@opentelemetry/resources": "2.7.1", + "@opentelemetry/sdk-trace-base": "2.7.1" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/exporter-trace-otlp-proto/node_modules/@opentelemetry/sdk-trace-base": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-2.7.1.tgz", + "integrity": "sha512-NAYIlsF8MPUsKqJMiDQJTMPOmlbawC1Iz/omMLygZ1C9am8fTKYjTaI+OZM+WTY3t3Glo0wnOg/6/pac6RGPPw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "2.7.1", + "@opentelemetry/resources": "2.7.1", + "@opentelemetry/semantic-conventions": "^1.29.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.3.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/exporter-zipkin": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-zipkin/-/exporter-zipkin-2.7.1.tgz", + "integrity": "sha512-mfsD9bKAxcKrh5+y08TPodvClBO0CznBE3p79YAGnO81WI4LrdsGA65T53e4iTSbCalW4WaUpkbeJcbpyIUHfg==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "2.7.1", + "@opentelemetry/resources": "2.7.1", + "@opentelemetry/sdk-trace-base": "2.7.1", + "@opentelemetry/semantic-conventions": "^1.29.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.0.0" + } + }, + "node_modules/@opentelemetry/exporter-zipkin/node_modules/@opentelemetry/sdk-trace-base": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-2.7.1.tgz", + "integrity": "sha512-NAYIlsF8MPUsKqJMiDQJTMPOmlbawC1Iz/omMLygZ1C9am8fTKYjTaI+OZM+WTY3t3Glo0wnOg/6/pac6RGPPw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "2.7.1", + "@opentelemetry/resources": "2.7.1", + "@opentelemetry/semantic-conventions": "^1.29.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.3.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/instrumentation": { + "version": "0.217.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.217.0.tgz", + "integrity": "sha512-24ucQMjz7Y34Kw3trbxL2ZrssbtgWnR+Clpaa+YdeWuuyH3Cvk23Q03PcQvqiZrDvt8AmQmjgg9v6Y9PHoxG7w==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.217.0", + "import-in-the-middle": "^3.0.0", + "require-in-the-middle": "^8.0.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-http": { + "version": "0.217.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-http/-/instrumentation-http-0.217.0.tgz", + "integrity": "sha512-B88Y7k5A9a60pHUboFoeJlgVwXq2T0rsZKj6dTwzSMKSOsNXR4Jz5ovwprVn3kHLAZrkyLEjQtBJ34DYHs1U4Q==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "2.7.1", + "@opentelemetry/instrumentation": "0.217.0", + "@opentelemetry/semantic-conventions": "^1.29.0", + "forwarded-parse": "2.1.2" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/otlp-exporter-base": { + "version": "0.217.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-exporter-base/-/otlp-exporter-base-0.217.0.tgz", + "integrity": "sha512-eYfqnB3UhKu/5frhd1R6+FprKygbhkomuaceMXDyzxbfXB9tKgZOVmjaJ02CkLA6Tdzumxl+e2H+vo2a8jiMPQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "2.7.1", + "@opentelemetry/otlp-transformer": "0.217.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/otlp-grpc-exporter-base": { + "version": "0.217.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-grpc-exporter-base/-/otlp-grpc-exporter-base-0.217.0.tgz", + "integrity": "sha512-7RTAdZuOsCDnsyqTCG4+bDzrfnsWdzkRs7z0AVi/V3tEQx0oKeyc+OuRWYxnRsmaJXgxcmB8vb/lfxn58Dj6Ag==", + "license": "Apache-2.0", + "dependencies": { + "@grpc/grpc-js": "^1.14.3", + "@opentelemetry/core": "2.7.1", + "@opentelemetry/otlp-exporter-base": "0.217.0", + "@opentelemetry/otlp-transformer": "0.217.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/otlp-transformer": { + "version": "0.217.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-transformer/-/otlp-transformer-0.217.0.tgz", + "integrity": "sha512-MKK8UHKFUOGAvbZRWh90MhwHG+Fxm6OROBdjKPCF+HQobjuJ/Kuf8Chs8CR45X1aqotxrMj7OxTdsXe8sXuGVA==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.217.0", + "@opentelemetry/core": "2.7.1", + "@opentelemetry/resources": "2.7.1", + "@opentelemetry/sdk-logs": "0.217.0", + "@opentelemetry/sdk-metrics": "2.7.1", + "@opentelemetry/sdk-trace-base": "2.7.1", + "protobufjs": "8.0.1" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/otlp-transformer/node_modules/@opentelemetry/sdk-trace-base": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-2.7.1.tgz", + "integrity": "sha512-NAYIlsF8MPUsKqJMiDQJTMPOmlbawC1Iz/omMLygZ1C9am8fTKYjTaI+OZM+WTY3t3Glo0wnOg/6/pac6RGPPw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "2.7.1", + "@opentelemetry/resources": "2.7.1", + "@opentelemetry/semantic-conventions": "^1.29.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.3.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/propagator-b3": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/propagator-b3/-/propagator-b3-2.7.1.tgz", + "integrity": "sha512-RJid6E2CKyeGfKBzXKF21ejabGMHypFkPAh3qZ+NvI+SGjuIye79t3PmiqcDgtRzdKH6ynXzbfslQ8DfpRUg2A==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "2.7.1" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/propagator-jaeger": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/propagator-jaeger/-/propagator-jaeger-2.7.1.tgz", + "integrity": "sha512-KMjVBHzP4N60bOzxja76M1F1hZZ43lGPga5ix+mkv9+kk1nx9SbkxSvJsMbuVUxdPQmsPTqGShmhN8ulrMOg6Q==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "2.7.1" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/resources": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.7.1.tgz", + "integrity": "sha512-DeT6KKolmC4e/dRQvMQ/RwlnzhaqeiFOXY5ngoOPJ07GgVVKxZOg9EcrNZb5aTzUn+iCrJldAgOfQm1O/QfPAQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "2.7.1", + "@opentelemetry/semantic-conventions": "^1.29.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.3.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/sdk-logs": { + "version": "0.217.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-logs/-/sdk-logs-0.217.0.tgz", + "integrity": "sha512-BB+PcHItcZDL63dPMW+mJvwN9rk37wuIDjRxbVlg6pPDvDR/7GL7UJHbGsllgoggOoTimsKgENaWPoGch/oE1A==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.217.0", + "@opentelemetry/core": "2.7.1", + "@opentelemetry/resources": "2.7.1", + "@opentelemetry/semantic-conventions": "^1.29.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.4.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/sdk-metrics": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-metrics/-/sdk-metrics-2.7.1.tgz", + "integrity": "sha512-MpDJdkiFDs3Pm1RHO3KByuZbuBdJEXEAkiC0+yJdsZGVCdf1RpHR6n+LHDcS7ffmfrt5kVCzJSCfm4z2C7v0uQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "2.7.1", + "@opentelemetry/resources": "2.7.1" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.9.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/sdk-node": { + "version": "0.217.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-node/-/sdk-node-0.217.0.tgz", + "integrity": "sha512-K/60pSv42+NQiZKy1pAH18nYDkxltsDV4O3SJ233J0E9raU1ksyL9gsKuS8p30bYBb4AMPCfDuutHQaHYpcv0Q==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.217.0", + "@opentelemetry/configuration": "0.217.0", + "@opentelemetry/context-async-hooks": "2.7.1", + "@opentelemetry/core": "2.7.1", + "@opentelemetry/exporter-logs-otlp-grpc": "0.217.0", + "@opentelemetry/exporter-logs-otlp-http": "0.217.0", + "@opentelemetry/exporter-logs-otlp-proto": "0.217.0", + "@opentelemetry/exporter-metrics-otlp-grpc": "0.217.0", + "@opentelemetry/exporter-metrics-otlp-http": "0.217.0", + "@opentelemetry/exporter-metrics-otlp-proto": "0.217.0", + "@opentelemetry/exporter-prometheus": "0.217.0", + "@opentelemetry/exporter-trace-otlp-grpc": "0.217.0", + "@opentelemetry/exporter-trace-otlp-http": "0.217.0", + "@opentelemetry/exporter-trace-otlp-proto": "0.217.0", + "@opentelemetry/exporter-zipkin": "2.7.1", + "@opentelemetry/instrumentation": "0.217.0", + "@opentelemetry/otlp-exporter-base": "0.217.0", + "@opentelemetry/propagator-b3": "2.7.1", + "@opentelemetry/propagator-jaeger": "2.7.1", + "@opentelemetry/resources": "2.7.1", + "@opentelemetry/sdk-logs": "0.217.0", + "@opentelemetry/sdk-metrics": "2.7.1", + "@opentelemetry/sdk-trace-base": "2.7.1", + "@opentelemetry/sdk-trace-node": "2.7.1", + "@opentelemetry/semantic-conventions": "^1.29.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.3.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/sdk-node/node_modules/@opentelemetry/sdk-trace-base": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-2.7.1.tgz", + "integrity": "sha512-NAYIlsF8MPUsKqJMiDQJTMPOmlbawC1Iz/omMLygZ1C9am8fTKYjTaI+OZM+WTY3t3Glo0wnOg/6/pac6RGPPw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "2.7.1", + "@opentelemetry/resources": "2.7.1", + "@opentelemetry/semantic-conventions": "^1.29.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.3.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/sdk-trace-base": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-2.8.0.tgz", + "integrity": "sha512-mhU4jp+vW0mGbFRd+GeXHvmfA4aDqWjBjLC3pE5XMpLs0IE2ryYb019Ts2AQrOq67gaTF25D91+fgvEHDZEnuQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "2.8.0", + "@opentelemetry/resources": "2.8.0", + "@opentelemetry/semantic-conventions": "^1.29.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.3.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/sdk-trace-base/node_modules/@opentelemetry/core": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-2.8.0.tgz", + "integrity": "sha512-hd1Lfh8p545nNz+jq1Ejfz+Mn1hyLuxYn1YzTfFNrxr8urEWMNQLPf1Th8kjOH+HxwawCrtgBp8JpBUR4ZSgww==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/semantic-conventions": "^1.29.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/sdk-trace-base/node_modules/@opentelemetry/resources": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.8.0.tgz", + "integrity": "sha512-qmXQ27ilDbUK/vGMqwL8D4/rhn76C+sherM4wTbjlfknR8Nvfc/hCxjRJPhkzZzUsPiNg16SA31NxMabwttRjg==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "2.8.0", + "@opentelemetry/semantic-conventions": "^1.29.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.3.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/sdk-trace-node": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-node/-/sdk-trace-node-2.7.1.tgz", + "integrity": "sha512-pCpQxU68lV+I9s9svqMyVu5iHdDDUnqUpSxqwyCU8A9ejEsSnMPCbearwsUO4yk08ZJzAIUCFuReMdVQvHrdvg==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/context-async-hooks": "2.7.1", + "@opentelemetry/core": "2.7.1", + "@opentelemetry/sdk-trace-base": "2.7.1" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/sdk-trace-node/node_modules/@opentelemetry/sdk-trace-base": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-2.7.1.tgz", + "integrity": "sha512-NAYIlsF8MPUsKqJMiDQJTMPOmlbawC1Iz/omMLygZ1C9am8fTKYjTaI+OZM+WTY3t3Glo0wnOg/6/pac6RGPPw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "2.7.1", + "@opentelemetry/resources": "2.7.1", + "@opentelemetry/semantic-conventions": "^1.29.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.3.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/semantic-conventions": { + "version": "1.41.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.41.1.tgz", + "integrity": "sha512-/UhIkaZgPutTFmQ7RnIJGgDXZmtEJ7Dvi86xNTFWcnRxVRNk/aotsqDJYeEvDP+FSMB2SdW+pQzNMcWP0rwuNA==", + "license": "Apache-2.0", + "engines": { + "node": ">=14" + } + }, + "node_modules/@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/codegen": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.5.tgz", + "integrity": "sha512-zgXFLzW3Ap33e6d0Wlj4MGIm6Ce8O89n/apUaGNB/jx+hw+ruWEp7EwGUshdLKVRCxZW12fp9r40E1mQrf/34g==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/eventemitter": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.1.tgz", + "integrity": "sha512-vW1GmwMZNnL+gMRaovlh9yZX74kc+TTU3FObkkurpMaRtBfLP3ldjS9KQWlwZgraRE0+dheEEoAxdzcJQ8eXZg==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/fetch": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.1.tgz", + "integrity": "sha512-GpptLrs57adMSuHi3VNj0mAF8dwh36LMaYF6XyJ6JMWlVsc+t42tm1HSEDmOs3A8fC9yyeisgLhsTVQokOZ0zw==", + "license": "BSD-3-Clause", + "dependencies": { + "@protobufjs/aspromise": "^1.1.1" + } + }, + "node_modules/@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/inquire": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.2.tgz", + "integrity": "sha512-pa0vFRuws4wkvaXKK1uXZMAwAX4/t8ANaJo45iw/oQHNQ9q5xUzwgFmVJGXiga2BeN+zpX7Vf9vmsiIa2J+MUw==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/utf8": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.1.tgz", + "integrity": "sha512-oOAWABowe8EAbMyWKM0tYDKi8Yaox52D+HWZhAIJqQXbqe0xI/GV7FhLWqlEKreMkfDjshR5FKgi3mnle0h6Eg==", + "license": "BSD-3-Clause" + }, + "node_modules/@sandbox-agent/cli": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@sandbox-agent/cli/-/cli-0.4.2.tgz", + "integrity": "sha512-trO//ypJBSt5xkewuol9LOykvDgHwUXq8R+yQVS+0CmpN3lYUtewHkb+At9RVGRhDMmJZY2oasaXDnhfurQ33w==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@sandbox-agent/cli-shared": "0.4.2" + }, + "bin": { + "sandbox-agent": "bin/sandbox-agent" + }, + "optionalDependencies": { + "@sandbox-agent/cli-darwin-arm64": "0.4.2", + "@sandbox-agent/cli-darwin-x64": "0.4.2", + "@sandbox-agent/cli-linux-arm64": "0.4.2", + "@sandbox-agent/cli-linux-x64": "0.4.2", + "@sandbox-agent/cli-win32-x64": "0.4.2" + } + }, + "node_modules/@sandbox-agent/cli-darwin-arm64": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@sandbox-agent/cli-darwin-arm64/-/cli-darwin-arm64-0.4.2.tgz", + "integrity": "sha512-+L1O8SI7k/LLhyB4dG0ghmz1cJHa0WtVjuRTrEE2gw/5EbGLWopPBsCVCmQ7snrQ4fPwtaiZDhfExcEj1VI7aw==", + "cpu": [ + "arm64" + ], + "hasInstallScript": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@sandbox-agent/cli-darwin-x64": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@sandbox-agent/cli-darwin-x64/-/cli-darwin-x64-0.4.2.tgz", + "integrity": "sha512-dDg/EwWsdgVVbJiiCX1scSNRRA48u77SsC7Tuqrfzx4fIJMLuLiIcmEtXQyCBWysSyQNV2Cr+PYXXQfCb3xg8g==", + "cpu": [ + "x64" + ], + "hasInstallScript": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@sandbox-agent/cli-linux-arm64": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@sandbox-agent/cli-linux-arm64/-/cli-linux-arm64-0.4.2.tgz", + "integrity": "sha512-TGmTUexMoubmWQyTeaOJu0rDVl2h0Ifh1pZ0ceZy7u/6Eoqs2n46CbfQtasUxZJf10uxPgRyzEDhcdDrTYVQUA==", + "cpu": [ + "arm64" + ], + "hasInstallScript": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@sandbox-agent/cli-linux-x64": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@sandbox-agent/cli-linux-x64/-/cli-linux-x64-0.4.2.tgz", + "integrity": "sha512-H9Rbqq0DRkCHvakzefJUDrDa2y+vJjlYd5/tefzKbQ34locE13TGNygRLxdEVXpBECjK9wVdBwTVEphQNsOcjw==", + "cpu": [ + "x64" + ], + "hasInstallScript": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@sandbox-agent/cli-shared": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@sandbox-agent/cli-shared/-/cli-shared-0.4.2.tgz", + "integrity": "sha512-sjZXRkKeFXCSKR6hHzF2Af8CCRO3F3WFwVQJ22+sLTXJ2xskV8lkUE4egknQU9B5BC1Zumts/YiNCFQWG85awQ==", + "license": "Apache-2.0" + }, + "node_modules/@sandbox-agent/cli-win32-x64": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@sandbox-agent/cli-win32-x64/-/cli-win32-x64-0.4.2.tgz", + "integrity": "sha512-lZNfHWPwQe/VH51Yvrl/ATCUvBZ3a+c8mwovojhQcmZlv4QuUQPkuvxhPqHRh9AyBx78L5J/ha46es2doa34nQ==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@smithy/core": { + "version": "3.26.0", + "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.26.0.tgz", + "integrity": "sha512-mLUktFAn+Pa2agl1J7VgtYNFWCX8/b4GMJSK1hCu4YCvtBfM6F8Os3EP4ry+DFFlXOf3wyvlgXhuUdFoy52D3g==", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/crc32": "5.2.0", + "@smithy/types": "^4.15.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/credential-provider-imds": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-4.4.2.tgz", + "integrity": "sha512-18UMDMyrAbDcpmL1gLUA7ww0fRTcdCrSjSJOi2Sbld+tVjwD/pW+OAwjlScFLR7vvBnhZrIPQ7kVuTf1mnJLug==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/core": "^3.26.0", + "@smithy/types": "^4.15.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/fetch-http-handler": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-5.5.2.tgz", + "integrity": "sha512-Ei/UK/QMhq0rKaMqGPlOAkE2yS9DZeYmZdk1RAKc3vp3zxgleZHZyBLlZv8yLsxljX4svCRuMTD6u3LLIcU4Bg==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/core": "^3.26.0", + "@smithy/types": "^4.15.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/is-array-buffer": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz", + "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/node-http-handler": { + "version": "4.8.2", + "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.8.2.tgz", + "integrity": "sha512-wfl1uwrAqMH9/pi4kqBo5LBcFwrJLxuDLqL7p7qNcJIFcyZDUc6pzhYk4CYv+DP7fIUpQCZumwNnkhPKS52osQ==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/core": "^3.26.0", + "@smithy/types": "^4.15.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/signature-v4": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-5.5.2.tgz", + "integrity": "sha512-7xHpmPY4rt0IOmeAA8EfjgEH8isT+587TCdy9H6a7d4OMi5CQ0oEHhWllunvPu4j4Cq0vTFwdxXN/kABWPjdyA==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/core": "^3.26.0", + "@smithy/types": "^4.15.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/types": { + "version": "4.15.0", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.15.0.tgz", + "integrity": "sha512-Z5TAOxygoFvybJV3igo5SloFflSokHx2hu1eFA+DxDTcn+FtKxUSui+rbTRG1pAafMA888Z3MVvCWUuvCrTXjg==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-buffer-from": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz", + "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/is-array-buffer": "^2.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/util-utf8": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz", + "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/util-buffer-from": "^2.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@types/node": { + "version": "26.0.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-26.0.0.tgz", + "integrity": "sha512-vf2YFi1iY9lHGwNJMs01biZFbKJkrZR1T6/MlzjhJLPdntOHLhTrDSnSVcdtvjihi4VQNlrFRIxLsDBlQpAipA==", + "license": "MIT", + "dependencies": { + "undici-types": "~8.3.0" + } + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "license": "MIT", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "8.17.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.17.0.tgz", + "integrity": "sha512-xRQbDb9BnwDafYNn6Vwl839DYVjqXYb1XVGtWAZ1kcDc6iwAL4hg3B1dZlRiuENFeO2H53gFG3in621AdERVAg==", + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-import-attributes": { + "version": "1.9.5", + "resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz", + "integrity": "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==", + "license": "MIT", + "peerDependencies": { + "acorn": "^8" + } + }, + "node_modules/acp-http-client": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/acp-http-client/-/acp-http-client-0.4.2.tgz", + "integrity": "sha512-3wtPieF08YIU4vNXaoL5up/1D0if4i9IX3Ye5q/bwbcwg1BKsazIK/VNNfvN4ldbPjWul69IqIOpGRS3I0qo3Q==", + "license": "Apache-2.0", + "dependencies": { + "@agentclientprotocol/sdk": "^0.16.1" + } + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "license": "MIT", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/agent-base/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/agent-base/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", + "license": "MIT" + }, + "node_modules/asn1": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", + "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", + "license": "MIT", + "dependencies": { + "safer-buffer": "~2.1.0" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, + "node_modules/axios": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.18.1.tgz", + "integrity": "sha512-3nTvFlvpn9Zu/RkHUqtc7/+al4UpRW5az71ap5zccp6e8RAYEzhMTecX8Dz1wWDYrPpUoB1HAQEGEAEvUr7S9g==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.16.0", + "form-data": "^4.0.5", + "https-proxy-agent": "^5.0.1", + "proxy-from-env": "^2.1.0" + } + }, + "node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "license": "MIT", + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", + "license": "BSD-3-Clause", + "dependencies": { + "tweetnacl": "^0.14.3" + } + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "license": "MIT", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/body-parser": { + "version": "1.20.5", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.5.tgz", + "integrity": "sha512-3grm+/2tUOvu2cjJkvsIxrv/wVpfXQW4PsQHYm7yk4vfpu7Ekl6nEsYBoJUL6qDwZUx8wUhQ8tR2qz+ad9c9OA==", + "license": "MIT", + "dependencies": { + "bytes": "~3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "~1.2.0", + "http-errors": "~2.0.1", + "iconv-lite": "~0.4.24", + "on-finished": "~2.4.1", + "qs": "~6.15.1", + "raw-body": "~2.5.3", + "type-is": "~1.6.18", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/bowser": { + "version": "2.14.1", + "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.14.1.tgz", + "integrity": "sha512-tzPjzCxygAKWFOJP011oxFHs57HzIhOEracIgAePE4pqB3LikALKnSzUyU4MGs9/iCEUuHlAJTjTc5M+u7YEGg==", + "license": "MIT" + }, + "node_modules/brace-expansion": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz", + "integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==", + "license": "MIT", + "dependencies": { + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/buffer": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", + "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", + "license": "MIT", + "dependencies": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "node_modules/buildcheck": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/buildcheck/-/buildcheck-0.0.7.tgz", + "integrity": "sha512-lHblz4ahamxpTmnsk+MNTRWsjYKv965MwOrSJyeD588rR3Jcu7swE+0wN5F+PbL5cjgu/9ObkhfzEPuofEMwLA==", + "optional": true, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/busboy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", + "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "dependencies": { + "streamsearch": "^1.1.0" + }, + "engines": { + "node": ">=10.16.0" + } + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/chalk": { + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", + "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chownr": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", + "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" + } + }, + "node_modules/cjs-module-lexer": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-2.2.0.tgz", + "integrity": "sha512-4bHTS2YuzUvtoLjdy+98ykbNB5jS0+07EvFNXerqZQJ89F7DI6ET7OQo/HJuW6K0aVsKA9hj9/RVb2kQVOrPDQ==", + "license": "MIT" + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/cluster-key-slot": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.1.tgz", + "integrity": "sha512-rwHwUfXL40Chm1r08yrhU3qpUvdVlgkKNeyeGPOxnW8/SyVDvgRaed/Uz54AqWNaTCAThlj6QAs3TZcKI0xDEw==", + "license": "Apache-2.0", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/compare-versions": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-6.1.1.tgz", + "integrity": "sha512-4hm4VPpIecmlg59CHXnRDnqGplJFrbLG4aFEl5vl6cK1u76ws3LLvX7ikFnTDl5vo39sjWD6AaDPYodJp/NNHg==", + "license": "MIT" + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "license": "MIT", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.7.tgz", + "integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==", + "license": "MIT" + }, + "node_modules/cpu-features": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/cpu-features/-/cpu-features-0.0.10.tgz", + "integrity": "sha512-9IkYqtX3YHPCzoVg1Py+o9057a3i0fp7S530UWokCSaFVTc7CwXPRiOjRjBQQ18ZCNafx78YfnG+HALxtVmOGA==", + "hasInstallScript": true, + "optional": true, + "dependencies": { + "buildcheck": "~0.0.6", + "nan": "^2.19.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/denque": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", + "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==", + "license": "Apache-2.0", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "license": "MIT", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/docker-modem": { + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/docker-modem/-/docker-modem-5.0.7.tgz", + "integrity": "sha512-XJgGhoR/CLpqshm4d3L7rzH6t8NgDFUIIpztYlLHIApeJjMZKYJMz2zxPsYxnejq5h3ELYSw/RBsi3t5h7gNTA==", + "license": "Apache-2.0", + "dependencies": { + "debug": "^4.1.1", + "readable-stream": "^3.5.0", + "split-ca": "^1.0.1", + "ssh2": "^1.15.0" + }, + "engines": { + "node": ">= 8.0" + } + }, + "node_modules/docker-modem/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/docker-modem/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/dockerfile-ast": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/dockerfile-ast/-/dockerfile-ast-0.7.1.tgz", + "integrity": "sha512-oX/A4I0EhSkGqrFv0YuvPkBUSYp1XiY8O8zAKc8Djglx8ocz+JfOr8gP0ryRMC2myqvDLagmnZaU9ot1vG2ijw==", + "license": "MIT", + "dependencies": { + "vscode-languageserver-textdocument": "^1.0.8", + "vscode-languageserver-types": "^3.17.3" + }, + "engines": { + "node": "*" + } + }, + "node_modules/dockerode": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/dockerode/-/dockerode-5.0.0.tgz", + "integrity": "sha512-C52mvJ+7lcyhWNfrzVfFsbTrBfy/ezE9FGEYLpu17FUeBcCkxERk9nN7uDl/478ynDiQ4U+5DbQC2vENHkVEtQ==", + "license": "Apache-2.0", + "dependencies": { + "@balena/dockerignore": "^1.0.2", + "@grpc/grpc-js": "^1.11.1", + "@grpc/proto-loader": "^0.7.13", + "docker-modem": "^5.0.7", + "protobufjs": "^7.3.2", + "tar-fs": "^2.1.4" + }, + "engines": { + "node": ">= 14.17" + } + }, + "node_modules/dockerode/node_modules/@grpc/proto-loader": { + "version": "0.7.15", + "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.15.tgz", + "integrity": "sha512-tMXdRCfYVixjuFK+Hk0Q1s38gV9zDiDJfWL3h1rv4Qc39oILCu1TRTDt7+fGUI8K4G1Fj125Hx/ru3azECWTyQ==", + "license": "Apache-2.0", + "dependencies": { + "lodash.camelcase": "^4.3.0", + "long": "^5.0.0", + "protobufjs": "^7.2.5", + "yargs": "^17.7.2" + }, + "bin": { + "proto-loader-gen-types": "build/bin/proto-loader-gen-types.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/dockerode/node_modules/protobufjs": { + "version": "7.6.4", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.6.4.tgz", + "integrity": "sha512-RJJPTTpvFfHcWLkIa2JFWK4XvtSzS0yEWDmunqHXli1h3JlkbcQZXDZdcWxv+JK3Xsl5/UFDPZ0iGm7DAengYw==", + "hasInstallScript": true, + "license": "BSD-3-Clause", + "dependencies": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.5", + "@protobufjs/eventemitter": "^1.1.1", + "@protobufjs/fetch": "^1.1.1", + "@protobufjs/float": "^1.0.2", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.1", + "@types/node": ">=13.7.0", + "long": "^5.3.2" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/dotenv": { + "version": "17.4.2", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.4.2.tgz", + "integrity": "sha512-nI4U3TottKAcAD9LLud4Cb7b2QztQMUEfHbvhTH09bqXTxnSie8WnjPALV/WMCrJZ6UV/qHJ6L03OqO3LcdYZw==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/e2b": { + "version": "2.30.5", + "resolved": "https://registry.npmjs.org/e2b/-/e2b-2.30.5.tgz", + "integrity": "sha512-mw0tk5X3z+P8qr3z0+lNTHG2szfKtuBohIZVYqxw6LsKmPL49fEntLICeCfrenKlh7vQCcJRCnK3Bg0SwZS1HQ==", + "license": "MIT", + "dependencies": { + "@bufbuild/protobuf": "^2.6.2", + "@connectrpc/connect": "2.0.0-rc.3", + "@connectrpc/connect-web": "2.0.0-rc.3", + "chalk": "^5.3.0", + "compare-versions": "^6.1.0", + "dockerfile-ast": "^0.7.1", + "glob": "^11.1.0", + "openapi-fetch": "^0.14.1", + "platform": "^1.3.6", + "tar": "^7.5.16", + "undici": "^7.28.0" + }, + "engines": { + "node": ">=20.18.1" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "license": "MIT" + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", + "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", + "license": "MIT", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.2.tgz", + "integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "license": "MIT" + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "license": "MIT", + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/expand-tilde": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", + "integrity": "sha512-A5EmesHW6rfnZ9ysHQjPdJRni0SRar0tjtG5MNtm9n5TUvsYU8oozprtRD4AqHxcZWWlVuAmQo2nWKfN9oyjTw==", + "license": "MIT", + "dependencies": { + "homedir-polyfill": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/express": { + "version": "4.22.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.22.2.tgz", + "integrity": "sha512-IuL+Elrou2ZvCFHs18/CIzy2Nzvo25nZ1/D2eIZlz7c+QUayAcYoiM2BthCjs+EBHVpjYjcuLDAiCWgeIX3X1Q==", + "license": "MIT", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "~1.20.5", + "content-disposition": "~0.5.4", + "content-type": "~1.0.4", + "cookie": "~0.7.1", + "cookie-signature": "~1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "~1.3.1", + "fresh": "~0.5.2", + "http-errors": "~2.0.0", + "merge-descriptors": "1.0.3", + "methods": "~1.1.2", + "on-finished": "~2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "~0.1.12", + "proxy-addr": "~2.0.7", + "qs": "~6.15.1", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "~0.19.0", + "serve-static": "~1.16.2", + "setprototypeof": "1.2.0", + "statuses": "~2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fastq": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz", + "integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==", + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.2.tgz", + "integrity": "sha512-aA4RyPcd3badbdABGDuTXCMTtOneUCAYH/gxoYRTZlIJdF0YPWuGqiAsIrhNnnqdXGswYk6dGujem4w80UJFhg==", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "on-finished": "~2.4.1", + "parseurl": "~1.3.3", + "statuses": "~2.0.2", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/follow-redirects": { + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.0.tgz", + "integrity": "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/foreground-child": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/form-data": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.6.tgz", + "integrity": "sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.4", + "mime-types": "^2.1.35" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/forwarded-parse": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/forwarded-parse/-/forwarded-parse-2.1.2.tgz", + "integrity": "sha512-alTFZZQDKMporBH77856pXgzhEzaUVmLCDk+egLgIgHst3Tpndzz8MnKe+GzRJRfvVdn69HhpW7cmXzvtLvJAw==", + "license": "MIT" + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", + "license": "MIT" + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-port": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/get-port/-/get-port-7.2.0.tgz", + "integrity": "sha512-afP4W205ONCuMoPBqcR6PSXnzX35KTcJygfJfcp+QY+uwm3p20p1YczWXhlICIzGMCxYBQcySEcOgsJcrkyobg==", + "license": "MIT", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/glob": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-11.1.0.tgz", + "integrity": "sha512-vuNwKSaKiqm7g0THUBu2x7ckSs3XJLXE+2ssL7/MfTGPLLcrJQ/4Uq1CjPTtO5cCIiRxqvN6Twy1qOwhL0Xjcw==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "license": "BlueOak-1.0.0", + "dependencies": { + "foreground-child": "^3.3.1", + "jackspeak": "^4.1.1", + "minimatch": "^10.1.1", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^2.0.0" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz", + "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/homedir-polyfill": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", + "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", + "license": "MIT", + "dependencies": { + "parse-passwd": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/http-errors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", + "license": "MIT", + "dependencies": { + "depd": "~2.0.0", + "inherits": "~2.0.4", + "setprototypeof": "~1.2.0", + "statuses": "~2.0.2", + "toidentifier": "~1.0.1" + }, + "engines": { + "node": ">= 0.8" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "license": "MIT", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/https-proxy-agent/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/https-proxy-agent/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/import-in-the-middle": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-3.2.0.tgz", + "integrity": "sha512-vR2B6HKIhaBjcZr2bLpFiJ1VbzOlRQ7aby4/gw5WPIzToLjqpfWw3VJ4sk1uDchoOODEirvO2jyrSPtUSL5CrQ==", + "license": "Apache-2.0", + "dependencies": { + "acorn": "^8.15.0", + "acorn-import-attributes": "^1.9.5", + "cjs-module-lexer": "^2.2.0", + "module-details-from-path": "^1.0.4" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, + "node_modules/ioredis": { + "version": "5.11.1", + "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-5.11.1.tgz", + "integrity": "sha512-ehuGcf94bQXhfagULNXrJdfnWO38v070jxSx/qE87Kjzmu2fU7ro5EFAb+OPituLqgfyuQaym5DlrNydW2sJ9A==", + "license": "MIT", + "dependencies": { + "@ioredis/commands": "1.10.0", + "cluster-key-slot": "1.1.1", + "debug": "4.4.3", + "denque": "2.1.0", + "redis-errors": "1.2.0", + "redis-parser": "3.0.0", + "standard-as-callback": "2.1.0" + }, + "engines": { + "node": ">=12.22.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/ioredis" + } + }, + "node_modules/ioredis/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/ioredis/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "license": "ISC" + }, + "node_modules/isomorphic-ws": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-5.0.0.tgz", + "integrity": "sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw==", + "license": "MIT", + "peerDependencies": { + "ws": "*" + } + }, + "node_modules/jackspeak": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.2.3.tgz", + "integrity": "sha512-ykkVRwrYvFm1nb2AJfKKYPr0emF6IiXDYUaFx4Zn9ZuIH7MrzEZ3sD5RlqGXNRpHtvUHJyOnCEFxOlNDtGo7wg==", + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^9.0.0" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", + "license": "MIT" + }, + "node_modules/long": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz", + "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==", + "license": "Apache-2.0" + }, + "node_modules/lru-cache": { + "version": "11.5.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.5.1.tgz", + "integrity": "sha512-RPimw/7aMdv2oqRrxKwvZXcPfwBrn/JZ2xYcY9Hus/6LaS3VOAKVWKWgNLCFSiOm1ESXinjsDlidVU7JlnCN2A==", + "license": "BlueOak-1.0.0", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimatch": { + "version": "10.2.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", + "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", + "license": "BlueOak-1.0.0", + "dependencies": { + "brace-expansion": "^5.0.5" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minipass": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", + "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/minizlib": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.1.0.tgz", + "integrity": "sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==", + "license": "MIT", + "dependencies": { + "minipass": "^7.1.2" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", + "license": "MIT" + }, + "node_modules/module-details-from-path": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/module-details-from-path/-/module-details-from-path-1.0.4.tgz", + "integrity": "sha512-EGWKgxALGMgzvxYF1UyGTy0HXX/2vHLkw6+NvDKW2jypWbHpjQuj4UMcqQWXHERJhVGKikolT06G3bcKe4fi7w==", + "license": "MIT" + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/nan": { + "version": "2.27.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.27.0.tgz", + "integrity": "sha512-hC+0LidcL3XE4rp1C4H54KujgXKzbfyTngZTwBByQxsOxCEKZT0MPQ4hOKUH2jU1OYstqdDH4onyHPDzcV0XdQ==", + "license": "MIT", + "optional": true + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/openapi-fetch": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/openapi-fetch/-/openapi-fetch-0.14.1.tgz", + "integrity": "sha512-l7RarRHxlEZYjMLd/PR0slfMVse2/vvIAGm75/F7J6MlQ8/b9uUQmUF2kCPrQhJqMXSxmYWObVgeYXbFYzZR+A==", + "license": "MIT", + "dependencies": { + "openapi-typescript-helpers": "^0.0.15" + } + }, + "node_modules/openapi-typescript-helpers": { + "version": "0.0.15", + "resolved": "https://registry.npmjs.org/openapi-typescript-helpers/-/openapi-typescript-helpers-0.0.15.tgz", + "integrity": "sha512-opyTPaunsklCBpTK8JGef6mfPhLSnyy5a0IN9vKtx3+4aExf+KxEqYwIy3hqkedXIB97u357uLMJsOnm3GVjsw==", + "license": "MIT" + }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "license": "BlueOak-1.0.0" + }, + "node_modules/parse-passwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", + "integrity": "sha512-1Y1A//QUXEZK7YKz+rD9WydcE1+EuPr6ZBgKecAB8tmoW6UFv0NREVJe1p+jRxtThkcbbKkfwIbWJe/IeE6m2Q==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-scurry": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.2.tgz", + "integrity": "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==", + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^11.0.0", + "minipass": "^7.1.2" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-to-regexp": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.13.tgz", + "integrity": "sha512-A/AGNMFN3c8bOlvV9RreMdrv7jsmF9XIfDeCd87+I8RNg6s78BhJxMu69NEMHBSJFxKidViTEdruRwEk/WIKqA==", + "license": "MIT" + }, + "node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "license": "MIT" + }, + "node_modules/picomatch": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/platform": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/platform/-/platform-1.3.6.tgz", + "integrity": "sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg==", + "license": "MIT" + }, + "node_modules/protobufjs": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-8.0.1.tgz", + "integrity": "sha512-NWWCCscLjs+cOKF/s/XVNFRW7Yih0fdH+9brffR5NZCy8k42yRdl5KlWKMVXuI1vfCoy4o1z80XR/W/QUb3V3w==", + "hasInstallScript": true, + "license": "BSD-3-Clause", + "dependencies": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/node": ">=13.7.0", + "long": "^5.0.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "license": "MIT", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/proxy-from-env": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-2.1.0.tgz", + "integrity": "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/pump": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.4.tgz", + "integrity": "sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==", + "license": "MIT", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/qs": { + "version": "6.15.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.2.tgz", + "integrity": "sha512-Rzq0KEyX/w/tEybncDgdkZrJgVUsUMk3xjh3t5bv3S1HTAtg+uOYt72+ZfwiQwKdysThkTBdL/rTi6HDmX9Ddw==", + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.3.tgz", + "integrity": "sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==", + "license": "MIT", + "dependencies": { + "bytes": "~3.1.2", + "http-errors": "~2.0.1", + "iconv-lite": "~0.4.24", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/redis-errors": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz", + "integrity": "sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/redis-parser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-3.0.0.tgz", + "integrity": "sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==", + "license": "MIT", + "dependencies": { + "redis-errors": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-in-the-middle": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/require-in-the-middle/-/require-in-the-middle-8.0.1.tgz", + "integrity": "sha512-QT7FVMXfWOYFbeRBF6nu+I6tr2Tf3u0q8RIEjNob/heKY/nh7drD/k7eeMFmSQgnTtCzLDcCu/XEnpW2wk4xCQ==", + "license": "MIT", + "dependencies": { + "debug": "^4.3.5", + "module-details-from-path": "^1.0.3" + }, + "engines": { + "node": ">=9.3.0 || >=8.10.0 <9.0.0" + } + }, + "node_modules/require-in-the-middle/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/require-in-the-middle/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" + }, + "node_modules/sandbox-agent": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/sandbox-agent/-/sandbox-agent-0.4.2.tgz", + "integrity": "sha512-fH6WDQEaIrgiu93LxZcy+4Dx+t+/cslu+hzXImDyUlsaL6jV2jIv4fdxELkALlo7uzyEDVK9lmqs9qy65RHwBQ==", + "license": "Apache-2.0", + "dependencies": { + "@sandbox-agent/cli-shared": "0.4.2", + "acp-http-client": "0.4.2" + }, + "optionalDependencies": { + "@sandbox-agent/cli": "0.4.2" + }, + "peerDependencies": { + "@cloudflare/sandbox": ">=0.1.0", + "@daytonaio/sdk": ">=0.12.0", + "@e2b/code-interpreter": ">=1.0.0", + "@fly/sprites": ">=0.0.1", + "@vercel/sandbox": ">=0.1.0", + "computesdk": ">=0.1.0", + "dockerode": ">=4.0.0", + "get-port": ">=7.0.0", + "modal": ">=0.1.0" + }, + "peerDependenciesMeta": { + "@cloudflare/sandbox": { + "optional": true + }, + "@daytonaio/sdk": { + "optional": true + }, + "@e2b/code-interpreter": { + "optional": true + }, + "@fly/sprites": { + "optional": true + }, + "@vercel/sandbox": { + "optional": true + }, + "computesdk": { + "optional": true + }, + "dockerode": { + "optional": true + }, + "get-port": { + "optional": true + }, + "modal": { + "optional": true + } + } + }, + "node_modules/send": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.2.tgz", + "integrity": "sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "~0.5.2", + "http-errors": "~2.0.1", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "~2.4.1", + "range-parser": "~1.2.1", + "statuses": "~2.0.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/serve-static": { + "version": "1.16.3", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.3.tgz", + "integrity": "sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA==", + "license": "MIT", + "dependencies": { + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "~0.19.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "license": "ISC" + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/shell-quote": { + "version": "1.8.4", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.4.tgz", + "integrity": "sha512-VsC6n6vz1ihYYyZZwX7YZSF5l5x36ca17OC+a69h94YqB7X6XLwf+5MOgynYir2SLFUbl8gIYvBo8K8RoNQ6bQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.1.tgz", + "integrity": "sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.4", + "side-channel-list": "^1.0.1", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.1.tgz", + "integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/split-ca": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/split-ca/-/split-ca-1.0.1.tgz", + "integrity": "sha512-Q5thBSxp5t8WPTTJQS59LrGqOZqOsrhDGDVm8azCqIBjSBd7nd9o2PM+mDulQQkh8h//4U6hFZnc/mul8t5pWQ==", + "license": "ISC" + }, + "node_modules/ssh2": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/ssh2/-/ssh2-1.17.0.tgz", + "integrity": "sha512-wPldCk3asibAjQ/kziWQQt1Wh3PgDFpC0XpwclzKcdT1vql6KeYxf5LIt4nlFkUeR8WuphYMKqUA56X4rjbfgQ==", + "hasInstallScript": true, + "dependencies": { + "asn1": "^0.2.6", + "bcrypt-pbkdf": "^1.0.2" + }, + "engines": { + "node": ">=10.16.0" + }, + "optionalDependencies": { + "cpu-features": "~0.0.10", + "nan": "^2.23.0" + } + }, + "node_modules/standard-as-callback": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/standard-as-callback/-/standard-as-callback-2.1.0.tgz", + "integrity": "sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==", + "license": "MIT" + }, + "node_modules/statuses": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/stream-browserify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-3.0.0.tgz", + "integrity": "sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==", + "license": "MIT", + "dependencies": { + "inherits": "~2.0.4", + "readable-stream": "^3.5.0" + } + }, + "node_modules/streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tar": { + "version": "7.5.16", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.16.tgz", + "integrity": "sha512-56adEpPMouktRlBLXiaYFFzZ/3+JXa8P9n7WbR+ibIjtviN55mEaOkiysCnPnWm+7kkui1Dn8J9l+g6zV8731w==", + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/fs-minipass": "^4.0.0", + "chownr": "^3.0.0", + "minipass": "^7.1.2", + "minizlib": "^3.1.0", + "yallist": "^5.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/tar-fs": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.4.tgz", + "integrity": "sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ==", + "license": "MIT", + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/tar-fs/node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "license": "ISC" + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "license": "MIT", + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==", + "license": "Unlicense" + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "license": "MIT", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/undici": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.28.0.tgz", + "integrity": "sha512-cRZYrTDwWznlnRiPjggAGxZXanty6M8RV1ff8Wm4LWXBp7/IG8v5DnOm74DtUBp9OONpK75YlPnIjQqX0dBDtA==", + "license": "MIT", + "engines": { + "node": ">=20.18.1" + } + }, + "node_modules/undici-types": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-8.3.0.tgz", + "integrity": "sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ==", + "license": "MIT" + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "license": "MIT" + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "license": "MIT", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/vscode-languageserver-textdocument": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.12.tgz", + "integrity": "sha512-cxWNPesCnQCcMPeenjKKsOCKQZ/L6Tv19DTRIGuLWe32lyzWhihGVJ/rcckZXJxfdKCFvRLS3fpBIsV/ZGX4zA==", + "license": "MIT" + }, + "node_modules/vscode-languageserver-types": { + "version": "3.18.0", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.18.0.tgz", + "integrity": "sha512-8TsGPNMIMiiBdkORgRSvLjuiEIiAFtO+KssmYWxQ+uSVvlf7RjK8YKCOjPzZ+YA04jXEV7+7LvkSmHkhpNS99g==", + "license": "MIT" + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "license": "ISC" + }, + "node_modules/ws": { + "version": "8.21.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.21.0.tgz", + "integrity": "sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", + "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" + } + }, + "node_modules/yaml": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.9.0.tgz", + "integrity": "sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA==", + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14.6" + }, + "funding": { + "url": "https://github.com/sponsors/eemeli" + } + }, + "node_modules/yargs": { + "version": "17.7.3", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.3.tgz", + "integrity": "sha512-GZtjxm/J/4TSxuL3FNYjCmLktBTnIw/rVmKSIyKeYAZpmJB2ig9VauCC5xsa82GNKVKDAqpOn3KVzNt0zmrU0g==", + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/zod": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.4.3.tgz", + "integrity": "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==", + "license": "MIT", + "peer": true, + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + } + } +} diff --git a/sessions/demo/sidecar/package.json b/sessions/demo/sidecar/package.json new file mode 100644 index 0000000000..3e03ece028 --- /dev/null +++ b/sessions/demo/sidecar/package.json @@ -0,0 +1,18 @@ +{ + "name": "demo-sidecar", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "start": "node server.js" + }, + "dependencies": { + "@daytonaio/sdk": "^0.190.1", + "@e2b/code-interpreter": "^2.6.1", + "dockerode": "^5.0.0", + "express": "^4.21.2", + "get-port": "^7.2.0", + "ioredis": "^5.11.1", + "sandbox-agent": "0.4.x" + } +} diff --git a/sessions/demo/sidecar/provider-modal.js b/sessions/demo/sidecar/provider-modal.js new file mode 100644 index 0000000000..74c3d0754c --- /dev/null +++ b/sessions/demo/sidecar/provider-modal.js @@ -0,0 +1,79 @@ +// Modal provider path. Modal has no Node SDK, so we shell out to modal_bridge.py +// (uses the modal Python SDK) to provision/reconnect a sandbox, mount geesefs from the +// tunnel, start sandbox-agent on :2468 exposed via Modal's own encrypted tunnel, and +// print {sandbox_id, base_url, cwd}. The Node side then connect()s to that base_url. +// +// Auth: MODAL_TOKEN_ID/MODAL_TOKEN_SECRET in env (passed through to the python process). +import { spawn } from "node:child_process"; +import { SandboxAgent } from "sandbox-agent"; +import { makePersist } from "./session-persist.js"; + +const NGROK_API = process.env.NGROK_API_URL || "http://ngrok:4040/api/tunnels"; +const S3_KEY = process.env.SEAWEEDFS_S3_ACCESS_KEY || "demo"; +const S3_SECRET = process.env.SEAWEEDFS_S3_SECRET_KEY || "demosecret"; +const BUCKET = process.env.SEAWEEDFS_S3_BUCKET || "demo"; +const PYTHON = process.env.MODAL_PYTHON || "python3"; +const BRIDGE = new URL("./modal_bridge.py", import.meta.url).pathname; + +async function tunnelUrl() { + const r = await fetch(NGROK_API); + if (!r.ok) throw new Error(`ngrok api ${r.status} — is the tunnel up? (compose --profile remote up -d ngrok)`); + const d = await r.json(); + const t = (d.tunnels || []).find((x) => x.public_url?.startsWith("https")); + if (!t) throw new Error("no https ngrok tunnel found"); + return t.public_url; +} + +// Run the python bridge; resolve with the JSON object on its LAST stdout line. +function runBridge(argv) { + return new Promise((resolve, reject) => { + const p = spawn(PYTHON, [BRIDGE, ...argv], { + env: { ...process.env }, + }); + let out = "", err = ""; + p.stdout.on("data", (d) => (out += d)); + p.stderr.on("data", (d) => { err += d; process.stderr.write(`[modal] ${d}`); }); + p.on("error", reject); + p.on("close", (code) => { + if (code !== 0) return reject(new Error(`modal_bridge ${argv[0]} exit ${code}: ${err.slice(-600)}`)); + const lines = out.trim().split("\n").filter(Boolean); + try { + resolve(JSON.parse(lines[lines.length - 1])); + } catch (e) { + reject(new Error(`modal_bridge bad output: ${out.slice(-400)}`)); + } + }); + }); +} + +// Returns { session, sandboxId, cwd, flush } for the modal provider. +export async function modalSession({ sid, harness, sandboxId, mode, model, thoughtLevel, agentEnv }) { + const endpoint = await tunnelUrl(); + const argv = [ + "up", "--sid", sid, "--endpoint", endpoint, + "--s3-key", S3_KEY, "--s3-secret", S3_SECRET, "--bucket", BUCKET, + ]; + if (sandboxId) argv.push("--sandbox-id", sandboxId); + if (agentEnv.ANTHROPIC_API_KEY) argv.push("--anthropic", agentEnv.ANTHROPIC_API_KEY); + if (agentEnv.OPENAI_API_KEY) argv.push("--openai", agentEnv.OPENAI_API_KEY); + + const { sandbox_id, base_url, cwd } = await runBridge(argv); + const sdk = await SandboxAgent.connect({ baseUrl: base_url, persist: makePersist() }); + const init = { id: sid, agent: harness, cwd, mode }; + if (model) init.model = model; + if (thoughtLevel) init.thoughtLevel = thoughtLevel; + const session = await sdk.resumeOrCreateSession(init); + + return { + session, + client: sdk, // owns destroySession() — used by force-cancel to interrupt a live prompt + sandboxId: sandbox_id, + cwd, + // geesefs --fsync-on-close already lands each write; nothing extra to flush host-side. + flush: async () => {}, + }; +} + +export async function modalKill(sandboxId) { + await runBridge(["kill", "--sandbox-id", sandboxId]); +} diff --git a/sessions/demo/sidecar/run-lock.js b/sessions/demo/sidecar/run-lock.js new file mode 100644 index 0000000000..9e798ca8b6 --- /dev/null +++ b/sessions/demo/sidecar/run-lock.js @@ -0,0 +1,143 @@ +// Per-session concurrency control via TWO independent Redis locks with distinct meanings: +// +// alive:session: — "a run is executing server-side." Held for the whole /run, its +// watchdog refreshes the TTL while the run executes. Survives the +// client HTTP connection dropping (the sidecar keeps the prompt +// running). Governs cancel / take-over (force). +// attached:session: — "a client stream is currently connected and watching." Held while +// an /invoke->/run HTTP stream is connected; RELEASED the moment the +// server sees that client socket close (res 'close'), with the TTL as +// a backstop for hard crashes. Governs reattach. +// +// The two compose into the states we care about: +// alive=no, attached=no -> idle: a new run just runs. +// alive=yes, attached=yes -> running, someone is watching -> 409 (force = cancel+take-over). +// alive=yes, attached=no -> running but DETACHED (the driving tab left) -> reattachable. +// +// `force` is the general "do it anyway given the context" knob; cancel+take-over of an alive +// run is its first use. +// +// POC SIMPLIFICATIONS (would change for production): +// 1. Redis is used DIRECTLY from the sidecar — no FastAPI lock API, no separate lock service. +// Eventually the lock surface would likely be a first-class backend API. +// 2. Cancellation is IN-PROCESS: the holder's live Session object lives in THIS sidecar, so +// force-cancel just calls it locally. Works only because there is a SINGLE rivet sidecar +// instance; multiple would need a cancel channel (e.g. Redis pub/sub). +import Redis from "ioredis"; + +const TTL_MS = Number(process.env.RUN_LOCK_TTL_MS || 5 * 60 * 1000); // matches sandbox auto-stop +const REFRESH_MS = Math.floor(TTL_MS / 3); // watchdog heartbeat well under the TTL +// the attached lock tracks a live socket, so it expires fast if the holder dies without a +// clean close; refreshed often while connected. +const ATTACHED_TTL_MS = Number(process.env.ATTACHED_TTL_MS || 20_000); +const ATTACHED_REFRESH_MS = Math.floor(ATTACHED_TTL_MS / 3); +const CANCEL_TIMEOUT_MS = Number(process.env.RUN_LOCK_CANCEL_TIMEOUT_MS || 30_000); + +const redis = new Redis(process.env.REDIS_URL || "redis://redis:6379", { maxRetriesPerRequest: 3 }); +const aliveKey = (sid) => `alive:session:${sid}`; +const attachedKey = (sid) => `attached:session:${sid}`; + +// in-process registry of runs THIS sidecar owns: sid -> { token, cancel() } +const active = new Map(); + +// act only if we still hold the token (never touch someone else's lock) +const RELEASE_LUA = `if redis.call("get", KEYS[1]) == ARGV[1] then return redis.call("del", KEYS[1]) else return 0 end`; +const REFRESH_LUA = `if redis.call("get", KEYS[1]) == ARGV[1] then return redis.call("pexpire", KEYS[1], ARGV[2]) else return 0 end`; + +function randomToken() { + return `${Date.now().toString(36)}-${Math.floor(Math.random() * 1e9).toString(36)}`; +} + +async function trySet(key, token, ttl) { + return (await redis.set(key, token, "PX", ttl, "NX")) === "OK"; +} +async function releaseToken(key, token) { + try { await redis.eval(RELEASE_LUA, 1, key, token); } catch {} +} +// a self-refreshing hold on `key`; returns a stop() that clears the timer + releases the key. +function startRefresher(key, token, ttl, every) { + const iv = setInterval(() => { + redis.eval(REFRESH_LUA, 1, key, token, String(ttl)).catch(() => {}); + }, every); + if (iv.unref) iv.unref(); + return async () => { clearInterval(iv); await releaseToken(key, token); }; +} + +// Acquire the ALIVE lock for `sid`, handling the busy case per `force`. +// force=false: throw { code: "in_use" } if a run is live. +// force=true : cancel the current holder, wait up to CANCEL_TIMEOUT_MS to re-acquire; +// throw { code: "in_use" } if still live at the deadline (no auto-retry). +// Returns a handle: { token, setCancel(), attach(), detach(), release() }. +export async function acquire(sid, { force = false } = {}) { + const token = randomToken(); + if (await trySet(aliveKey(sid), token, TTL_MS)) return startHold(sid, token); + + if (!force) { + const e = new Error("session in use"); + e.code = "in_use"; + throw e; + } + + // force = STEER: cancel the local holder so ITS /run unwinds and releases `alive`, then poll + // to re-acquire. The cancel makes the holder's in-flight session.prompt() resolve (via + // destroySession) — that's what frees the lock; the poll just waits for that release to land. + const holder = active.get(sid); + if (holder) { + try { await holder.cancel(); } catch (e) { console.warn(`[steer ${sid}] cancel threw: ${e?.message?.slice(0, 80)}`); } + } + const deadline = Date.now() + CANCEL_TIMEOUT_MS; + while (Date.now() < deadline) { + if (await trySet(aliveKey(sid), token, TTL_MS)) return startHold(sid, token); + await new Promise((r) => setTimeout(r, 500)); + } + console.warn(`[steer ${sid}] TIMEOUT — holder never released alive`); + const e = new Error("session still in use after force-cancel timeout"); + e.code = "in_use"; + throw e; +} + +function startHold(sid, token) { + const stopAlive = startRefresher(aliveKey(sid), token, TTL_MS, REFRESH_MS); + let stopAttached = null; + const handle = { + token, + // the run registers how to cancel its live session here so a force-takeover can reach it + setCancel(fn) { active.set(sid, { token, cancel: fn }); }, + // mark this run as actively watched by a connected client stream (own token, own TTL). + async attach() { + const atok = randomToken(); + // take the attached lock; if someone else holds it, steal it (the alive lock is the real + // gate — attached is just "who is watching", and this run owns the alive lock). + await redis.set(attachedKey(sid), atok, "PX", ATTACHED_TTL_MS); + stopAttached = startRefresher(attachedKey(sid), atok, ATTACHED_TTL_MS, ATTACHED_REFRESH_MS); + }, + // client socket closed -> drop attached but KEEP live (the run keeps executing server-side). + async detach() { + if (stopAttached) { await stopAttached(); stopAttached = null; } + }, + async release() { + if (stopAttached) { await stopAttached(); stopAttached = null; } + if (active.get(sid)?.token === token) active.delete(sid); + await stopAlive(); + }, + }; + return handle; +} + +// CANCEL the alive run for `sid` WITHOUT taking it over (no re-prompt). Cancels the local +// holder's session; the holder's own /run unwinds and releases the alive lock in its finally. +// Returns whether a holder was found to cancel (false = nothing live in this sidecar). +export async function cancel(sid) { + const holder = active.get(sid); + if (!holder) return false; + try { await holder.cancel(); } catch {} + return true; +} + +// read-only snapshot of both locks for a session. +export async function status(sid) { + const [alive, attached] = await redis.mget(aliveKey(sid), attachedKey(sid)); + return { alive: alive !== null, attached: attached !== null }; +} + +export { CANCEL_TIMEOUT_MS }; diff --git a/sessions/demo/sidecar/sandbox-provider.js b/sessions/demo/sidecar/sandbox-provider.js new file mode 100644 index 0000000000..def869dba2 --- /dev/null +++ b/sessions/demo/sidecar/sandbox-provider.js @@ -0,0 +1,271 @@ +// Durability layer over the SandboxProvider interface from the rivet sandbox-agent SDK. +// +// A SandboxProvider implements the full sandbox lifecycle — create / reconnect / +// ensureServer / getUrl / destroy / kill — and `SandboxAgent.start({ sandbox })` drives all +// of it. withGeesefs() wraps a base provider and ADDS our geesefs-over-ngrok durable cwd +// (mount demo: over the tunnel + seed auth + start the credentialed agent server). One +// wrapper, reused across backends. `makeProvider(name, ctx)` returns the wrapped provider. +// +// Bases: daytona uses the SDK's built-in provider; e2b and docker use small custom bases +// here (the SDK's built-in e2b() calls a removed Sandbox.betaCreate, and its docker() owns +// the whole HostConfig so we can't add FUSE caps without clobbering the port mapping). +// +// Two backends are NOT here: local is the long-lived compose `sandbox` container (handled +// in server.js — geesefs talks to seaweedfs directly, creds already in its env); modal uses +// the dedicated Python bridge (provider-modal.js) since the Node modal SDK needs a +// separately-baked Modal image. + +const NGROK_API = process.env.NGROK_API_URL || "http://ngrok:4040/api/tunnels"; +const S3_ENDPOINT = process.env.SEAWEEDFS_S3_URL || "http://seaweedfs:8333"; +const S3_KEY = process.env.SEAWEEDFS_S3_ACCESS_KEY || "demo"; +const S3_SECRET = process.env.SEAWEEDFS_S3_SECRET_KEY || "demosecret"; +const BUCKET = process.env.SEAWEEDFS_S3_BUCKET || "demo"; +const AGENT_PORT = 2468; +const CWD = "/root/work"; + +// All baked images (daytona snapshot, e2b template, docker image) share one name. +const SNAPSHOT = process.env.DAYTONA_SNAPSHOT || "agenta-sandbox-agent"; +const E2B_TEMPLATE = process.env.E2B_TEMPLATE || "agenta-sandbox-agent"; +const DOCKER_IMAGE = process.env.SANDBOX_AGENT_IMAGE || "agenta-sandbox-agent:local"; + +async function tunnelUrl() { + const r = await fetch(NGROK_API); + if (!r.ok) throw new Error(`ngrok api ${r.status} — is the tunnel up? (compose --profile remote up -d ngrok)`); + const d = await r.json(); + const t = (d.tunnels || []).find((x) => x.public_url?.startsWith("https")); + if (!t) throw new Error("no https ngrok tunnel found"); + return t.public_url; +} + +// mount demo: at cwd if not already healthily mounted. A stale FUSE endpoint reports +// as a mountpoint but errors "Transport endpoint is not connected" — remount. +function geesefsScript(sid, cwd, endpoint) { + return [ + `if ls ${cwd} >/dev/null 2>&1 && mountpoint -q ${cwd}; then echo already; exit 0; fi`, + `fusermount -u ${cwd} 2>/dev/null; umount -l ${cwd} 2>/dev/null; mkdir -p ${cwd}`, + `AWS_ACCESS_KEY_ID=${S3_KEY} AWS_SECRET_ACCESS_KEY=${S3_SECRET} ` + + `geesefs --endpoint ${endpoint} --region us-east-1 --no-detect --fsync-on-close ` + + `-o allow_other ${BUCKET}:${sid} ${cwd} && echo MOUNT_OK`, + ].join("; "); +} + +function authScript(agentEnv) { + const lines = [`mkdir -p /root/.config/pi && printf '{"defaultProjectTrust":"trusted"}' > /root/.config/pi/settings.json`]; + if (agentEnv.OPENAI_API_KEY) + lines.push(`mkdir -p /root/.codex && printf '{"OPENAI_API_KEY":"%s"}' '${agentEnv.OPENAI_API_KEY}' > /root/.codex/auth.json`); + return lines.join("; "); +} + +// The built-in providers start the agent server with NO agent creds in its env (they only +// know about sandbox-agent, not which LLM key claude/codex need). Restart it once WITH the +// creds so prompts authenticate. Two hazards this avoids: +// - pkill -f 'sandbox-agent server' would also kill the agent that's RUNNING this command +// (our exec goes through the very server we'd be matching) → "signal: terminated". Kill +// by port owner via fuser instead, which won't match our shell. +// - the restarted server must outlive this command's shell → setsid + full detach. +// Written to a script + run via setsid so the parent exec can return immediately. +function restartServerWithCreds(agentEnv, port = AGENT_PORT) { + const env = Object.entries(agentEnv).map(([k, v]) => `${k}='${v}'`).join(" "); + return [ + `cat > /tmp/start-agent.sh <<'EOS'`, + `#!/bin/bash`, + `fuser -k ${port}/tcp 2>/dev/null; sleep 1`, + `${env} exec sandbox-agent server --no-token --host 0.0.0.0 --port ${port} >/tmp/sa.log 2>&1`, + `EOS`, + `chmod +x /tmp/start-agent.sh`, + `setsid /tmp/start-agent.sh /dev/null 2>&1 &`, + `for i in $(seq 1 30); do curl -sf http://localhost:${port}/v1/health >/dev/null && echo SRV_UP && exit 0; sleep 1; done; echo SRV_DOWN`, + ].join("\n"); +} + +// Wrap a base SandboxProvider with our durable cwd. `exec(sandboxId, cmd) -> stdout` is the +// backend-specific shell adapter. cwd is forced to CWD so resumeOrCreateSession lands in +// the mount regardless of the base provider's defaultCwd. +function withGeesefs(base, { sid, agentEnv, exec }) { + const mount = async (sandboxId) => { + const endpoint = await tunnelUrl(); + await exec(sandboxId, authScript(agentEnv)); + const out = await exec(sandboxId, geesefsScript(sid, CWD, endpoint)); + if (!/MOUNT_OK|already/.test(out)) throw new Error(`geesefs mount failed: ${out}`); + const srv = await exec(sandboxId, restartServerWithCreds(agentEnv)); + if (!/SRV_UP/.test(srv)) throw new Error(`agent server restart failed: ${srv}`); + }; + return { + ...base, + defaultCwd: CWD, + // SandboxAgent.start() calls create() on a fresh sandbox and reconnect() on an existing + // one, but only calls ensureServer() AFTER health failures. The base already starts the + // server, so health passes first try and ensureServer never fires — so we mount in + // create()/reconnect() (right after the sandbox exists), not ensureServer(). + async create() { + const id = await base.create(); + await mount(id); + return id; + }, + async reconnect(sandboxId) { + await base.reconnect?.(sandboxId); + await base.ensureServer?.(sandboxId); // resumed sandbox may need the server restarted + await mount(sandboxId); // and the geesefs cwd remounted + }, + }; +} + +// --- per-backend exec adapters: each backend hands us a different sandbox handle --- + +const daytonaExec = async (sandboxId, cmd) => { + const { Daytona } = await import("@daytonaio/sdk"); + const sbx = await new Daytona().get(sandboxId); + const r = await sbx.process.executeCommand(cmd, undefined, undefined, 90); + return String(r.result || ""); +}; + +const e2bExec = async (sandboxId, cmd) => { + const { Sandbox } = await import("@e2b/code-interpreter"); + const sbx = await Sandbox.connect(sandboxId, { timeoutMs: 300000 }); + // e2b runs commands as a non-root user; agents + geesefs live under /root → sudo. + const r = await sbx.commands.run(`sudo bash -c '${cmd.replace(/'/g, `'"'"'`)}'`, { timeoutMs: 120000 }); + return String(r.stdout || ""); +}; + +const dockerExec = async (sandboxId, cmd) => { + const Docker = (await import("dockerode")).default; + const container = new Docker({ socketPath: "/var/run/docker.sock" }).getContainer(sandboxId); + const e = await container.exec({ Cmd: ["bash", "-c", cmd], AttachStdout: true, AttachStderr: true }); + const stream = await e.start({}); + return await new Promise((resolve) => { + let out = ""; + stream.on("data", (d) => (out += d.toString("utf8"))); + stream.on("end", () => resolve(out)); + }); +}; + +// --- custom e2b base provider implementing the SDK's SandboxProvider interface. --- +// The SDK's built-in e2b() calls Sandbox.betaCreate, which doesn't exist in current +// @e2b/code-interpreter (sandbox-agent 0.4.2 references a removed API). Our template +// already bakes sandbox-agent + agents + geesefs, so we just create + start the server. +function e2bBase({ template, agentPort = AGENT_PORT } = {}) { + // e2b sandbox keep-alive (lifetime), NOT a command/execution cap: the sandbox expires + // this long after create/connect, each connect resetting it. 5 min idle = auto-stop, + // matching the UI live-TTL and daytona's autoStopInterval. (Per-command execution time is + // the separate timeoutMs on commands.run below, which stays large.) + const LIFETIME = 5 * 60 * 1000; + const connect = async (id) => (await import("@e2b/code-interpreter")).Sandbox.connect(id, { timeoutMs: LIFETIME }); + return { + name: "e2b", + defaultCwd: "/root/work", + // NOTE: create()/reconnect() deliberately DON'T start the agent server — withGeesefs + // starts the only server (with creds) after mounting, so there's no credential-less + // server to race with. ensureServer is a no-op for the same reason. + async create() { + const { Sandbox } = await import("@e2b/code-interpreter"); + const sbx = await Sandbox.create(template, { timeoutMs: LIFETIME }); + return sbx.sandboxId; + }, + async reconnect(id) { await connect(id); }, + async ensureServer() {}, + async getUrl(id) { return `https://${(await connect(id)).getHost(agentPort)}`; }, + async kill(id) { const { Sandbox } = await import("@e2b/code-interpreter"); await Sandbox.kill(id); }, + async destroy(id) { await this.kill(id); }, + }; +} + +// --- custom daytona base. The SDK's built-in daytona() starts a credential-less server in +// create() via executeCommand; our wrapper's restart can't reliably replace it because +// executeCommand runs as a child of that very server (killing it by port kills the exec +// shell mid-restart). So, like e2b/docker, this base does NOT start a server — withGeesefs +// starts the only one, with creds. --- +function daytonaBase({ snapshot, agentPort = AGENT_PORT } = {}) { + const newClient = async () => new ((await import("@daytonaio/sdk")).Daytona)(); + return { + name: "daytona", + defaultCwd: CWD, + async create() { + const client = await newClient(); + // auto-stop after 5 min idle (matches the UI live-TTL); resume restarts it. + const sbx = await client.create({ snapshot, autoStopInterval: 5 }); + return sbx.id; + }, + async reconnect(id) { + const client = await newClient(); + const sbx = await client.get(id); + if (sbx.state === "stopped") await client.start(sbx); + }, + async ensureServer() {}, + async getUrl(id) { + const sbx = await (await newClient()).get(id); + const p = await sbx.getSignedPreviewUrl(agentPort, 4 * 60 * 60); + return typeof p === "string" ? p : p.url; + }, + async destroy(id) { await (await (await newClient()).get(id)).delete(60); }, + async kill(id) { await this.destroy(id); }, + }; +} + +// --- custom docker base. The SDK's built-in docker() owns the whole HostConfig +// (PortBindings), so passing createContainerOptions to add FUSE caps would clobber the +// port mapping. We build the container ourselves with both. Like e2b, the server is +// started by withGeesefs (with creds), so create() doesn't start one. --- +function dockerBase({ image, agentPort = AGENT_PORT, host = "host.docker.internal" } = {}) { + const sock = "/var/run/docker.sock"; + const newClient = async () => new ((await import("dockerode")).default)({ socketPath: sock }); + return { + name: "docker", + defaultCwd: "/root/work", + async create() { + const Docker = (await import("dockerode")).default; + const getPort = (await import("get-port")).default; + const client = new Docker({ socketPath: sock }); + const hostPort = await getPort(); + const container = await client.createContainer({ + Image: image, + Entrypoint: ["sleep"], + Cmd: ["infinity"], + ExposedPorts: { [`${agentPort}/tcp`]: {} }, + HostConfig: { + AutoRemove: true, + PortBindings: { [`${agentPort}/tcp`]: [{ HostPort: String(hostPort) }] }, + Devices: [{ PathOnHost: "/dev/fuse", PathInContainer: "/dev/fuse", CgroupPermissions: "rwm" }], + CapAdd: ["SYS_ADMIN"], + SecurityOpt: ["apparmor:unconfined"], + }, + }); + await container.start(); + return container.id; + }, + async reconnect() {}, + async ensureServer() {}, + async getUrl(id) { + const client = await newClient(); + const info = await client.getContainer(id).inspect(); + const hp = info.NetworkSettings?.Ports?.[`${agentPort}/tcp`]?.[0]?.HostPort; + if (!hp) throw new Error(`docker: port ${agentPort} not published`); + return `http://${host}:${hp}`; + }, + async destroy(id) { + const client = await newClient(); + const c = client.getContainer(id); + try { await c.stop({ t: 5 }); } catch {} + try { await c.remove({ force: true }); } catch {} + }, + async kill(id) { await this.destroy(id); }, + }; +} + +// --- public factory: name -> wrapped provider ready for SandboxAgent.start() --- +export function makeProvider(name, { sid, agentEnv }) { + switch (name) { + case "daytona": + return withGeesefs(daytonaBase({ snapshot: SNAPSHOT }), { sid, agentEnv, exec: daytonaExec }); + case "e2b": + return withGeesefs(e2bBase({ template: E2B_TEMPLATE }), { sid, agentEnv, exec: e2bExec }); + case "docker": + return withGeesefs( + dockerBase({ image: DOCKER_IMAGE, agentPort: AGENT_PORT, host: process.env.DOCKER_HOST_IP || "host.docker.internal" }), + { sid, agentEnv, exec: dockerExec }, + ); + default: + throw new Error(`unknown sandbox provider: ${name}`); + } +} + +export { CWD, AGENT_PORT, S3_ENDPOINT }; diff --git a/sessions/demo/sidecar/server.js b/sessions/demo/sidecar/server.js new file mode 100644 index 0000000000..074ba71481 --- /dev/null +++ b/sessions/demo/sidecar/server.js @@ -0,0 +1,443 @@ +// Node sidecar: owns the sandbox-agent TS SDK; FastAPI calls this over HTTP. +// Responsibilities: +// - ensure a per-session geesefs mount (demo: -> /work/) inside the sandbox +// - create/resume an ACP "claude" session with cwd=/work/ +// - stream ACP events back to FastAPI as NDJSON (so it can persist them live) +// - flush geesefs write-back before returning +import express from "express"; +import { SandboxAgent } from "sandbox-agent"; +import { makePersist } from "./session-persist.js"; + +const AGENT_URL = process.env.SANDBOX_AGENT_URL || "http://sandbox:2468"; +const API_URL = process.env.API_URL || "http://fastapi:8000"; +const S3_ENDPOINT = process.env.SEAWEEDFS_S3_URL || "http://seaweedfs:8333"; +const S3_KEY = process.env.SEAWEEDFS_S3_ACCESS_KEY || "demo"; +const S3_SECRET = process.env.SEAWEEDFS_S3_SECRET_KEY || "demosecret"; +const BUCKET = process.env.SEAWEEDFS_S3_BUCKET || "demo"; +const PORT = 8080; + +// Survive a single run's network failure. An ACP request (e.g. a sandbox-agent call) can reject +// with a HeadersTimeout from deep inside the SDK's async machinery, where no try/catch of ours +// can reach it. Without these guards that one rejection crashes the WHOLE sidecar process (and +// `node --watch` then parks it until a file change), so every subsequent /invoke gets a +// ConnectError. Log and keep serving instead — the failed run is already lost, the server isn't. +process.on("unhandledRejection", (err) => { + console.error("[unhandledRejection]", String(err?.stack || err).slice(0, 300)); +}); +process.on("uncaughtException", (err) => { + console.error("[uncaughtException]", String(err?.stack || err).slice(0, 300)); +}); + +// PERSISTENCE PATH — producer-driven and 100% independent of any /invoke client. As rivet +// produces each transcript event we POST it to FastAPI's /events ingest, so the transcript is +// durable whether or not a browser is connected, attached, or watching. The NDJSON view stream +// is a SEPARATE, disposable concern (see emit() in /run). Best-effort: a persist failure must +// not break the run (the SDK's own replay store is a backstop). +// +// Events MUST persist in produced-order (the DB assigns a dense per-session seq at insert), so +// we serialize per session through a promise chain instead of firing POSTs concurrently. The +// caller does NOT await the chain — the run is never blocked on persistence — but the writes +// themselves land in order. +const PERSIST_DEBUG = process.env.PERSIST_DEBUG === "1"; +async function postEvent(sid, evt) { + // bounded retry: a transient ingest failure must not silently drop an event from the + // transcript (the durable record). Each event persists in produced-order via the chain. + let lastErr; + for (let attempt = 1; attempt <= 3; attempt++) { + try { + const r = await fetch(`${API_URL}/events`, { + method: "POST", + headers: { "content-type": "application/json" }, + body: JSON.stringify({ session_id: sid, ...evt }), + }); + if (!r.ok) throw new Error(`HTTP ${r.status}`); + if (PERSIST_DEBUG) console.log(`[persist ${sid}] ok su=${evt.session_update} idx=${evt.event_index} try=${attempt}`); + return; + } catch (e) { + lastErr = e; + await new Promise((res) => setTimeout(res, 100 * attempt)); + } + } + console.warn(`[persist ${sid}] DROPPED su=${evt.session_update} after retries: ${String(lastErr?.message).slice(0, 80)}`); +} + +const persistChains = new Map(); // sid -> tail Promise +function persistEvent(sid, evt) { + const tail = (persistChains.get(sid) || Promise.resolve()).then(() => postEvent(sid, evt)); + persistChains.set(sid, tail); + return tail; +} + +// Wait for all queued persists for a session to land. The run does NOT block on persistence +// mid-stream (so it stays responsive), but it MUST NOT report _done — or tear down a sandbox — +// until its own events are durable, or the last agent_message can be lost to the teardown race +// (notably on a force-takeover, whose cancel/recreate skews the timing). Drains then prunes. +async function drainPersist(sid) { + const tail = persistChains.get(sid); + if (!tail) return; + await tail; + if (persistChains.get(sid) === tail) persistChains.delete(sid); +} + +// Persist the remote sandbox id (for resume) independently of the view stream, so a detached +// run still records where it ran. null clears it (docker teardown). Best-effort. +async function persistSandboxId(sid, sandboxId) { + try { + await fetch(`${API_URL}/sessions/${sid}/sandbox-id`, { + method: "PUT", + headers: { "content-type": "application/json" }, + body: JSON.stringify({ sandbox_id: sandboxId }), + }); + } catch (e) { console.warn(`[persist-sbx ${sid}] ${e?.message?.slice(0, 80)}`); } +} + +// --- raw sandbox-agent REST helpers (process API: run shell inside the sandbox) --- +async function runInSandbox(script, env = {}) { + const res = await fetch(`${AGENT_URL}/v1/processes/run`, { + method: "POST", + headers: { "content-type": "application/json" }, + body: JSON.stringify({ + command: "bash", + args: ["-lc", script], + env, + waitForExit: true, + }), + }); + const text = await res.text(); + if (!res.ok) throw new Error(`runInSandbox failed (${res.status}): ${text}`); + const out = JSON.parse(text); + if (out.exitCode !== 0) + throw new Error(`runInSandbox exit ${out.exitCode}: ${out.stderr || out.stdout}`); + return out.stdout || ""; +} + +// geesefs mount is idempotent: skip if /work/ is already a mountpoint. +async function ensureMount(sid) { + const mnt = `/work/${sid}`; + const cmd = [ + `mkdir -p ${mnt}`, + `if mountpoint -q ${mnt}; then echo "already-mounted"; exit 0; fi`, + // path-style addressing = no --subdomain; --no-detect skips AWS autodetection + `geesefs --endpoint ${S3_ENDPOINT} --region us-east-1 --no-detect ` + + `-o allow_other ${BUCKET}:${sid} ${mnt}`, + `echo "mounted"`, + ].join(" && "); + const out = await runInSandbox(cmd, { + AWS_ACCESS_KEY_ID: S3_KEY, + AWS_SECRET_ACCESS_KEY: S3_SECRET, + }); + console.log(`[mount ${sid}] ${out.trim()}`); +} + +// Flush geesefs write-back cache to S3 before we consider the turn durable. +async function flushMount(sid) { + try { + await runInSandbox(`sync; sync`); + } catch (e) { + console.warn(`[flush ${sid}] ${e.message}`); + } +} + +// Unmount + remove the cwd dir (used on session delete). Best-effort, idempotent. +async function unmount(sid) { + const mnt = `/work/${sid}`; + await runInSandbox( + `fusermount -u ${mnt} 2>/dev/null || umount -l ${mnt} 2>/dev/null || true; ` + + `rmdir ${mnt} 2>/dev/null || true; echo unmounted` + ); + console.log(`[unmount ${sid}] done`); +} + +const app = express(); +app.use(express.json()); + +app.get("/health", (_req, res) => res.json({ ok: true })); + +// POST /unmount { session_id } — tear down the geesefs mount + cwd dir (on delete). +app.post("/unmount", async (req, res) => { + const sid = req.body?.session_id; + if (!sid) return res.status(400).json({ error: "session_id required" }); + try { + await unmount(sid); + res.json({ unmounted: sid }); + } catch (e) { + res.status(500).json({ error: String(e) }); + } +}); + +// POST /kill { sandbox, sandbox_id } — destroy a remote sandbox (cwd stays durable in S3). +app.post("/kill", async (req, res) => { + const { sandbox, sandbox_id } = req.body || {}; + if (!sandbox_id) return res.status(400).json({ error: "sandbox_id required" }); + try { + if (!["daytona", "e2b", "modal", "docker"].includes(sandbox)) + return res.status(400).json({ error: `kill not supported for sandbox '${sandbox}'` }); + if (sandbox === "modal") { + const { modalKill } = await import("./provider-modal.js"); + await modalKill(sandbox_id); + } else { + // the provider's own kill()/destroy() — no running agent needed to tear a sandbox down. + const { makeProvider } = await import("./sandbox-provider.js"); + const provider = makeProvider(sandbox, { sid: "kill", agentEnv: {} }); + await (provider.kill ?? provider.destroy).call(provider, sandbox_id); + } + res.json({ killed: sandbox_id }); + } catch (e) { + // idempotent: a sandbox that's already gone (cloud GC'd, container removed) IS the + // desired end state — report success so the caller clears the stale sandbox_id, instead + // of a 500 that leaves a dead-but-unkillable "live" badge in the UI. + const msg = String(e?.message || e); + if (/not\s*found|no such|does not exist|404|destroyed|terminated/i.test(msg)) { + console.warn(`[/kill ${sandbox}] sandbox already gone: ${msg.slice(0, 100)}`); + return res.json({ killed: sandbox_id, note: "already gone" }); + } + res.status(500).json({ error: msg }); + } +}); + +// Per-harness session mode. claude/codex have an auto-accept mode; opencode uses its +// default 'build' and pi has no modes — both rely on the onPermissionRequest backstop. +const HARNESS_MODE = { claude: "acceptEdits", codex: "agent-full-access", opencode: "build" }; + +// reasoning (none|low|medium|high) -> per-harness thoughtLevel. 'none' = pass nothing. +// claude/opencode accept low|medium|high; codex maps to its effort tiers; pi uses +// off|low|medium|high|xhigh thought levels. We forward the canonical token and let the +// adapter map/ignore; 'none' means we don't set a level at all. +function thoughtLevelFor(harness, reasoning) { + if (!reasoning || reasoning === "none") return undefined; + return reasoning; // low|medium|high pass through; adapters normalize +} + +// Auto-approve permission backstop (modes above usually skip prompts). +function autoApprove(session) { + session.onPermissionRequest?.((reqEvt) => { + const opts = reqEvt?.options || []; + const pick = + opts.find((o) => /allow.*always|always/i.test(o.kind || o.name || "")) || + opts.find((o) => /allow/i.test(o.kind || o.name || "")) || + opts.find((o) => !/reject|deny/i.test(o.kind || o.name || "")) || + opts[0]; + session.respondPermission?.(reqEvt.id, { optionId: pick?.optionId ?? pick?.id, allow: true }); + }); +} + +// On resume the SDK prepends the prior transcript to the live prompt as a synthetic text +// block (prefix below) so the agent has context. That injected block flows back as a client +// session/prompt event — if we persisted it, the NEXT resume would replay a transcript that +// already contains a replay, nesting (and doubling) the context every turn. Strip the +// injected block before storing so the transcript only ever holds the real user prompt. +const REPLAY_PREFIX = "Previous session history is replayed below as JSON-RPC envelopes."; +function stripReplay(payload) { + const prompt = payload?.params?.prompt; + if (payload?.method !== "session/prompt" || !Array.isArray(prompt)) return payload; + const cleaned = prompt.filter((p) => !(p?.type === "text" && p.text?.startsWith(REPLAY_PREFIX))); + if (cleaned.length === prompt.length) return payload; + return { ...payload, params: { ...payload.params, prompt: cleaned } }; +} + +// Stream a prompt's events to `write`, coalescing agent_message_chunks into agent_message. +// If `lock` is given, register a cancel fn so a force-takeover can interrupt this live prompt. +// The SDK forbids a manual "session/cancel" RPC; the supported interrupt is the owning +// client's destroySession(id), which sends the cancel internally and makes the in-flight +// prompt() resolve (stopReason "cancelled"). The stream then ends cleanly and the run's +// finally releases the lock. (The session is recreated on the next resume anyway.) +async function streamSession(session, prompt, emit, lock, client) { + autoApprove(session); + lock?.setCancel(async () => { + try { + await client.destroySession(session.id); + } catch (e) { console.warn(`[cancel] ${e?.message?.slice(0, 80)}`); } + }); + let buf = null; + const flushBuf = () => { + if (!buf) return; + emit({ + event_index: buf.evt.eventIndex, sender: buf.evt.sender, session_update: "agent_message", + payload: { method: "session/update", params: { + sessionId: buf.evt.payload?.params?.sessionId, + update: { sessionUpdate: "agent_message", messageId: buf.messageId, + content: { type: "text", text: buf.text } } } }, + }); + buf = null; + }; + const unsub = session.onEvent((evt) => { + const upd = evt.payload?.params?.update ?? evt.payload; + const su = upd?.sessionUpdate ?? null; + if (su === "agent_message_chunk") { + const mid = upd.messageId; + if (buf && buf.messageId !== mid) flushBuf(); + if (!buf) buf = { messageId: mid, text: "", evt }; + buf.text += upd.content?.text ?? ""; + return; + } + flushBuf(); + // The SDK sometimes emits a standalone (non-chunk) agent_message with EMPTY text as a + // turn artifact — the real text already arrived via chunks (flushed just above). Persisting + // the empty one would shadow the good message in the transcript, so drop empties. + if (su === "agent_message" && !((upd?.content?.text ?? "").length)) return; + emit({ event_index: evt.eventIndex, sender: evt.sender, session_update: su, payload: stripReplay(evt.payload) }); + }); + const result = await session.prompt( + Array.isArray(prompt) ? prompt : [{ type: "text", text: String(prompt) }] + ); + unsub?.(); + flushBuf(); + return result; +} + +// POST /run { session_id, prompt, sandbox, harness, provider, model, reasoning, sandbox_id? } +// Streams NDJSON: one line per ACP event, then a final {"_done": true, stop_reason, sandbox_id?}. +app.post("/run", async (req, res) => { + const { + session_id: sid, prompt, data, sandbox = "local", harness = "claude", + provider = "anthropic", model = null, reasoning = "none", sandbox_id, + force = false, + } = req.body; + if (!sid) return res.status(400).json({ error: "session_id required" }); + + // CONTROL PLANE: data === null = no work, intent only. The only control intent that reaches + // the sidecar is CANCEL: cancel the alive holder, run nothing. (ATTACH is FastAPI-only — it just + // holds `attached` + polls the transcript, never calls the sidecar.) Cancel always means + // "interrupt the holder", so `force` is implied here — no flag check needed. + if (data === null) { + const { cancel } = await import("./run-lock.js"); + const cancelled = await cancel(sid); // cancels the local holder; its /run unwinds + releases live + return res.json({ cancelled }); + } + + if (!prompt) return res.status(400).json({ error: "session_id and prompt required" }); + if (!["local", "daytona", "e2b", "modal", "docker"].includes(sandbox)) + return res.status(400).json({ error: `sandbox '${sandbox}' not supported yet` }); + + // ALIVE lock: one in-flight run per session. force=true cancels the current holder (graceful + // ACP cancel) and takes over; force=false replies 409 "in use" (no queue). Acquire BEFORE the + // NDJSON stream so 409 is a clean HTTP status, not a mid-stream frame. + const { acquire, status } = await import("./run-lock.js"); + let lock; + try { + lock = await acquire(sid, { force: !!force }); + } catch (e) { + if (e.code === "in_use") { + // Tell the caller WHICH kind of busy this is: a detached alive run is reattachable + // (the driving client left); an attached one is being watched -> force to take over. + const st = await status(sid); // { alive, attached } + return res.status(409).json({ + code: "in_use", + alive: st.alive, + attached: st.attached, + reattachable: st.alive && !st.attached, + }); + } + return res.status(500).json({ error: String(e?.message || e) }); + } + + res.setHeader("content-type", "application/x-ndjson"); + // NOTE: the sidecar owns only the ALIVE lock. The ATTACHED lock (is a BROWSER watching?) is + // owned by FastAPI, which sits at the browser boundary — a client leaving must NOT cancel + // this run, and the sidecar can't observe the browser anyway. A dropped FastAPI<->sidecar + // socket here just stops the (no-op) view writes; the run keeps executing to completion. + // + // Two independent sinks: + // view(obj) — push to the live NDJSON response (best-effort; no-op once the socket closes) + // emit(evt) — a TRANSCRIPT event: PERSIST it (durable, client-independent) AND view it + // Control frames (_done / _sandbox_id) use view() only: FastAPI consumes them from the live + // stream. _sandbox_id is persisted separately (persistSandboxId) so resume survives a detach. + const view = (obj) => { try { res.write(JSON.stringify(obj) + "\n"); } catch {} }; + const emit = (evt) => { persistEvent(sid, evt); view(evt); }; + const mode = HARNESS_MODE[harness]; // undefined for pi (no modes) + const thoughtLevel = thoughtLevelFor(harness, reasoning); + // model is keyed by provider; null/empty -> let the harness use its default model. + const sessionInit = { id: sid, agent: harness, mode }; + if (model) sessionInit.model = model; + if (thoughtLevel) sessionInit.thoughtLevel = thoughtLevel; + + try { + if (sandbox === "local") { + // local = the long-lived compose `sandbox` container; geesefs mounts to seaweedfs + // directly (no tunnel), creds already in the container env. Just connect + run. + await ensureMount(sid); + const sdk = await SandboxAgent.connect({ baseUrl: AGENT_URL, persist: makePersist() }); + const session = await sdk.resumeOrCreateSession({ ...sessionInit, cwd: `/work/${sid}` }); + const result = await streamSession(session, prompt, emit, lock, sdk); + await flushMount(sid); + await drainPersist(sid); // all events durable before _done + view({ _done: true, stop_reason: result?.stopReason ?? "end_turn" }); + } else if (sandbox === "modal") { + // modal stays on the dedicated Python-bridge provider (the Node modal SDK needs a + // separately-baked Modal image; the bridge already bakes one and works e2e). + const agentEnv = {}; + if (process.env.ANTHROPIC_API_KEY) agentEnv.ANTHROPIC_API_KEY = process.env.ANTHROPIC_API_KEY; + if (process.env.OPENAI_API_KEY) agentEnv.OPENAI_API_KEY = process.env.OPENAI_API_KEY; + const { modalSession } = await import("./provider-modal.js"); + const remote = await modalSession({ sid, harness, sandboxId: sandbox_id, mode, model, thoughtLevel, agentEnv }); + persistSandboxId(sid, remote.sandboxId); view({ _sandbox_id: remote.sandboxId }); + const result = await streamSession(remote.session, prompt, emit, lock, remote.client); + await remote.flush(); + await drainPersist(sid); + view({ _done: true, stop_reason: result?.stopReason ?? "end_turn", sandbox_id: remote.sandboxId }); + } else { + // daytona/e2b/docker: the SDK provider drives create/reconnect/getUrl/destroy; our + // withGeesefs wrapper adds the durable cwd (mount demo: over the tunnel + seed + // auth). SandboxAgent.start() runs the whole lifecycle from one provider object. + const { makeProvider, CWD } = await import("./sandbox-provider.js"); + const agentEnv = {}; + if (process.env.ANTHROPIC_API_KEY) agentEnv.ANTHROPIC_API_KEY = process.env.ANTHROPIC_API_KEY; + if (process.env.OPENAI_API_KEY) agentEnv.OPENAI_API_KEY = process.env.OPENAI_API_KEY; + const provider = makeProvider(sandbox, { sid, agentEnv }); + // Resume: reconnect to the recorded sandbox. If it's GONE (docker is AutoRemove, a + // cloud sandbox may have been GC'd), start() throws on reconnect/getUrl — fall back to + // a fresh sandbox, which remounts the same demo: prefix, so the durable cwd in + // SeaweedFS is preserved. This is the whole point of the geesefs layer. + let agent; + try { + agent = await SandboxAgent.start({ sandbox: provider, sandboxId: sandbox_id || undefined, persist: makePersist() }); + } catch (e) { + if (!sandbox_id) throw e; + console.warn(`[/run ${sandbox}] resume of ${sandbox_id} failed (${e?.message?.slice(0, 80)}); recreating`); + agent = await SandboxAgent.start({ sandbox: provider, persist: makePersist() }); + } + persistSandboxId(sid, agent.sandboxId); view({ _sandbox_id: agent.sandboxId }); // for resume + const session = await agent.resumeOrCreateSession({ ...sessionInit, cwd: CWD }); + const result = await streamSession(session, prompt, emit, lock, agent); + await drainPersist(sid); // events durable BEFORE any teardown (docker kills the container) + // docker is fresh-per-turn: the container runs `sleep infinity` so AutoRemove never + // fires on its own. Tear it down after the turn (cwd is durable in SeaweedFS; resume + // recreates + remounts). Cloud sandboxes are kept for fast resume. Sequence matters: + // flush geesefs, DISPOSE the agent (closes the ACP connection) so killing the container + // doesn't yank it out from under in-flight requests, THEN destroy. All best-effort — + // the work is already durable, so teardown errors must not fail the turn. + let finalSandboxId = agent.sandboxId; + if (sandbox === "docker") { + // geesefs mounts with --fsync-on-close, so the agent's writes are already durable on + // close (proven by the resume test). dispose() closes the ACP connection cleanly + // before we destroy the container, avoiding "other side closed" on in-flight requests. + try { await agent.dispose(); } catch {} + try { await agent.killSandbox(); } catch (e) { console.warn(`[/run docker] teardown: ${e?.message?.slice(0, 80)}`); } + finalSandboxId = null; + persistSandboxId(sid, null); view({ _sandbox_id: null }); // clear it + } + view({ _done: true, stop_reason: result?.stopReason ?? "end_turn", sandbox_id: finalSandboxId }); + } + res.end(); + } catch (err) { + console.error("[/run] error", err); + view({ _done: true, error: String(err?.stack || err) }); + res.end(); + } finally { + await lock.release(); // free the session for the next run (or the force-taker) + } +}); + +// GET /files?session_id=&path= -> proxy sandbox-agent fs listing (live view) +app.get("/files", async (req, res) => { + const { session_id: sid, path = "" } = req.query; + const abs = `/work/${sid}/${path}`.replace(/\/+$/, "") || `/work/${sid}`; + try { + const r = await fetch(`${AGENT_URL}/v1/fs/entries?path=${encodeURIComponent(abs)}`); + res.status(r.status).type("application/json").send(await r.text()); + } catch (e) { + res.status(502).json({ error: String(e) }); + } +}); + +app.listen(PORT, () => console.log(`sidecar listening on :${PORT}, agent=${AGENT_URL}`)); diff --git a/sessions/demo/sidecar/session-persist.js b/sessions/demo/sidecar/session-persist.js new file mode 100644 index 0000000000..d747e424d4 --- /dev/null +++ b/sessions/demo/sidecar/session-persist.js @@ -0,0 +1,61 @@ +// A sandbox-agent SessionPersistDriver backed by the FastAPI/Postgres store. +// +// WHY THIS EXISTS: the sidecar opens a FRESH SandboxAgent.connect()/start() on every /run. +// The SDK's default persist is in-memory, so across calls it has no record of a session and +// resumeOrCreateSession always CREATES a brand-new agent session — the coding agent starts +// each turn with no memory of the conversation (only the durable cwd carries over). Plugging +// in a durable persist driver lets the SDK actually RESUME the prior agent session and replay +// the transcript as context. +// +// The record (local-id -> agentSessionId, sessionInit, modes, ...) is small metadata that +// rides alongside the transcript; it lives in a session_state row. The EVENTS for replay are +// the transcript FastAPI already writes from the NDJSON stream — so insertEvent is a no-op +// here (we never double-write), and listEvents just reads that transcript back. +const API_URL = process.env.API_URL || "http://fastapi:8000"; + +async function api(method, path, body) { + const res = await fetch(`${API_URL}${path}`, { + method, + headers: body ? { "content-type": "application/json" } : undefined, + body: body ? JSON.stringify(body) : undefined, + }); + if (!res.ok) throw new Error(`persist ${method} ${path} -> ${res.status}: ${await res.text()}`); + return res.json(); +} + +export function makePersist() { + return { + async getSession(id) { + const { record } = await api("GET", `/sessions/${id}/state`); + return record ?? undefined; // SDK expects undefined (not null) when absent + }, + + async updateSession(record) { + await api("PUT", `/sessions/${record.id}/state`, record); + }, + + // The SDK only enumerates sessions for surfaces we don't use; an empty page is fine. + async listSessions() { + return { items: [] }; + }, + + // Events come from the transcript FastAPI already persists. Map our rows onto SessionEvent + // (the replay builder only reads createdAt/sender/payload; the rest is filled for shape). + async listEvents({ sessionId }) { + const { events } = await api("GET", `/sessions/${sessionId}/transcript`); + const items = events.map((e) => ({ + id: `${sessionId}:${e.seq}`, + eventIndex: e.event_index ?? e.seq, + sessionId, + createdAt: Date.parse(e.created_at) || 0, + connectionId: "", + sender: e.sender, + payload: e.payload, + })); + return { items }; // no pagination: the SDK slices to replayMaxEvents itself + }, + + // FastAPI already inserts every event as it streams off the wire — don't double-write. + async insertEvent() {}, + }; +}