@agentproto/adapter-claude-code-cloud 0.1.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/sessions-api.ts","../src/cli.ts","../src/meta-file.ts","../src/repo-source.ts","../src/acp-server.ts"],"names":["readFile","execFileAsync","promisify","execFile"],"mappings":"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","file":"chunk-LN5RJ5ZT.mjs","sourcesContent":["/**\n * Thin client for the undocumented Claude Code cloud sessions API\n * (AIP-66 Appendix A). Base https://api.anthropic.com; requests carry\n * `Authorization: Bearer <claude.ai OAuth access token>`,\n * `anthropic-version: 2023-06-01` and `x-organization-uuid`.\n *\n * The credential is the user's claude.ai login, owned by the claude CLI\n * (AIP-66 §8): this module never logs it, never persists it, and never\n * writes it anywhere — it lives only in request headers for the lifetime\n * of a call. Before a request, an expired token (or one expiring within\n * {@link EXPIRY_SKEW_MS}) triggers the injected login refresh, then the\n * source cache is invalidated and re-read. On 401 the same refresh +\n * invalidate + re-read happens once, then the call fails with a message\n * that tells the user how to log in.\n *\n * All network access goes through an injectable `fetch` so tests can drive\n * the client from fixtures — no live Anthropic call is ever made from here.\n */\n\nimport { execFile } from \"node:child_process\"\nimport { readFile } from \"node:fs/promises\"\nimport { homedir } from \"node:os\"\nimport { join } from \"node:path\"\nimport { promisify } from \"node:util\"\n\nconst execFileAsync = promisify(execFile)\n\n/** A claude.ai OAuth credential. `accessToken` is the bearer the API wants;\n * `orgUuid` is the `x-organization-uuid` header (from `~/.claude.json`'s\n * `.oauthAccount.organizationUuid`). `expiresAt` is the token's expiry in\n * epoch milliseconds (the keychain's `.claudeAiOauth.expiresAt`), when the\n * source knows it. NEVER logged or persisted. */\nexport interface CloudCredential {\n accessToken: string\n orgUuid?: string\n expiresAt?: number\n}\n\n/** A token expiring within this window is treated as expired: refresh it\n * before sending rather than racing a request against the expiry. */\nexport const EXPIRY_SKEW_MS = 5 * 60_000\n\n/** Where the host reads the vendor login from (AIP-66 §8). Implementations\n * must not cache a token across an explicit {@link CredentialSource.invalidate}\n * — a refresh or a 401 re-read has to be able to observe a fresh login. */\nexport interface CredentialSource {\n get(): Promise<CloudCredential>\n /** Drop any cached credential so the next {@link get} re-reads the\n * underlying store (the keychain may have been refreshed out-of-band). */\n invalidate(): void\n}\n\nconst KEYCHAIN_SERVICE = \"Claude Code-credentials\"\n\n/** macOS keychain credential: `security find-generic-password -s \"Claude\n * Code-credentials\" -w` returns JSON whose `.claudeAiOauth.accessToken` is\n * the bearer; the org uuid comes from `~/.claude.json`. `execFile` and the\n * file reader are injectable for tests; the token never leaves this module\n * except as a request header. */\nexport function keychainCredentialSource(\n deps: {\n execFileImpl?: (\n cmd: string,\n args: string[],\n ) => Promise<{ stdout: string }>\n readFileSyncImpl?: (path: string) => Promise<string>\n homedir?: () => string\n } = {},\n): CredentialSource {\n const execFileImpl =\n deps.execFileImpl ??\n (async (cmd: string, args: string[]) => {\n const { stdout } = await execFileAsync(cmd, args, {\n // `security` writes the secret to stdout only; maxBuffer covers a\n // long JSON blob. Never `echo` it anywhere else.\n maxBuffer: 1 << 20,\n })\n return { stdout }\n })\n const readFileSyncImpl =\n deps.readFileSyncImpl ??\n ((path: string) => readFile(path, \"utf8\"))\n const home = deps.homedir ?? homedir\n\n let cached: CloudCredential | null = null\n\n return {\n async get(): Promise<CloudCredential> {\n if (cached) return cached\n const { stdout } = await execFileImpl(\"security\", [\n \"find-generic-password\",\n \"-s\",\n KEYCHAIN_SERVICE,\n \"-w\",\n ])\n const keychain = JSON.parse(stdout) as {\n claudeAiOauth?: { accessToken?: string; expiresAt?: number }\n }\n const accessToken = keychain.claudeAiOauth?.accessToken\n if (!accessToken) {\n throw new Error(\n \"claude code cloud: no claudeAiOauth.accessToken in the Claude Code \" +\n \"keychain entry — run `claude auth login`\",\n )\n }\n let orgUuid: string | undefined\n try {\n const rc = JSON.parse(\n await readFileSyncImpl(join(home(), \".claude.json\")),\n ) as { oauthAccount?: { organizationUuid?: string } }\n orgUuid = rc.oauthAccount?.organizationUuid\n } catch {\n // org header is best-effort; some CLI versions work without it.\n }\n const expiresAt = keychain.claudeAiOauth?.expiresAt\n cached = {\n accessToken,\n ...(orgUuid ? { orgUuid } : {}),\n ...(typeof expiresAt === \"number\" ? { expiresAt } : {}),\n }\n return cached\n },\n invalidate() {\n cached = null\n },\n }\n}\n\n/** Env credential for hosts/tests that inject the login themselves:\n * CLAUDE_CLOUD_OAUTH_TOKEN (+ optional CLAUDE_CLOUD_ORG_UUID). */\nexport function envCredentialSource(\n env: Record<string, string | undefined> = process.env,\n): CredentialSource {\n return {\n async get(): Promise<CloudCredential> {\n const accessToken = env.CLAUDE_CLOUD_OAUTH_TOKEN\n if (!accessToken) {\n throw new Error(\n \"claude code cloud: CLAUDE_CLOUD_OAUTH_TOKEN is not set — run \" +\n \"`claude auth login` and use the keychain credential source, or \" +\n \"inject the token\",\n )\n }\n const orgUuid = env.CLAUDE_CLOUD_ORG_UUID\n return { accessToken, ...(orgUuid ? { orgUuid } : {}) }\n },\n invalidate() {\n // The env source has no cache: nothing to drop.\n },\n }\n}\n\n// ── wire shapes (observed 2026-10-14, CLI 2.1.296–2.1.299) ──────────────────\n\n/** One entry of GET /v1/code/sessions/{id}/events (newest first). The\n * `payload` is the Claude Code stream-json SDK message for `user` /\n * `assistant` / `result` events. */\nexport interface CloudSessionEvent {\n created_at: string\n event_id: string\n event_type: string\n /** A STRING of an integer, strictly increasing within the session. The\n * ordering key: parse with `Number()` (see {@link eventSequence}). */\n sequence_num: string\n /** Who produced the event — \"worker\" (the vendor's harness) or \"client\". */\n source?: string\n payload: unknown\n}\n\nexport interface CloudEventsPage {\n data: CloudSessionEvent[]\n /** The `sequence_num` of the OLDEST event on the page, present on the\n * first (newest) page. Pass back as `?cursor=<n>` to fetch the NEXT\n * OLDER page — the cursor pages BACKWARD in time, never forward. */\n resume_cursor?: string\n /** Alias for {@link resume_cursor}, seen on the first page only. */\n next_cursor?: string\n}\n\n/** Parse an event's `sequence_num` as a number, or null when absent /\n * non-numeric (such an event cannot be ordered and is skipped). */\nexport function eventSequence(event: CloudSessionEvent): number | null {\n const raw = event.sequence_num\n if (typeof raw !== \"string\" || raw.trim() === \"\") return null\n const n = Number(raw)\n return Number.isFinite(n) ? n : null\n}\n\n/** GET /v1/code/sessions/{id} — wrapped in `response_shape`. */\nexport interface CloudSessionState {\n id: string\n title: string\n status: string\n status_bucket?: string\n worker_status?: string\n connection_status?: string\n last_event_at?: string\n session_url?: string\n post_turn_summary?: string\n [key: string]: unknown\n}\n\nexport interface CloudGetSessionResponse {\n response_shape: CloudSessionState\n [key: string]: unknown\n}\n\n/** One entry of GET /v1/code/sessions — id is spelled `cse_<suffix>`, the\n * same suffix the CLI's `session_<suffix>` carries. */\nexport interface CloudSessionSummary {\n id: string\n title: string\n status: \"active\" | \"archived\" | string\n environment_kind?: \"anthropic_cloud\" | \"bridge\" | string\n config?: { model?: string; origin?: string; [key: string]: unknown }\n created_at?: string\n [key: string]: unknown\n}\n\nexport interface CloudListSessionsResponse {\n data: CloudSessionSummary[]\n resume_token?: string\n}\n\n/**\n * Normalize a session id to the API's own `cse_<suffix>` spelling. Accepts\n * `session_<suffix>` (what the CLI prints and `--cloud` takes) and\n * `cse_<suffix>` (what the API listing returns); rejects anything else so a\n * malformed id can never be interpolated into a request path.\n */\nexport function normalizeSessionId(id: string): string {\n const trimmed = id.trim()\n if (trimmed.startsWith(\"session_\")) return `cse_${trimmed.slice(\"session_\".length)}`\n if (trimmed.startsWith(\"cse_\")) return trimmed\n throw new Error(\n `claude code cloud: unrecognized session id ${JSON.stringify(id)} — ` +\n \"expected session_<id> or cse_<id>\",\n )\n}\n\n/** Normalize to the CLI's own `session_<suffix>` spelling (for `--cloud`,\n * `--teleport`). Same acceptance set as {@link normalizeSessionId}. */\nexport function toCliSessionId(id: string): string {\n const normalized = normalizeSessionId(id)\n return `session_${normalized.slice(\"cse_\".length)}`\n}\n\nexport interface SessionsApiOptions {\n /** Credential source; invalidated + re-read when the token is expiring or\n * a request comes back 401, then the call fails. */\n credentials: CredentialSource\n /** Refresh the vendor login before re-reading an expired credential and on\n * a 401 (e.g. cli.ts's refreshLogin). Omit to skip refreshing. */\n refreshLogin?: () => Promise<void>\n /** Injectable fetch — tests pass a fixture router; default is globalThis.fetch. */\n fetchImpl?: typeof fetch\n /** Override for proxies/mirrors; default https://api.anthropic.com. */\n baseUrl?: string\n}\n\nconst UNAUTHORIZED_HINT = \"run `claude auth login`\"\n\n/** True when the token is already expired or expires within the skew window\n * (or when the source reports no expiry, in which case we cannot know). */\nexport function isCredentialExpiring(\n credential: CloudCredential,\n now = Date.now(),\n): boolean {\n return (\n credential.expiresAt !== undefined &&\n credential.expiresAt - now <= EXPIRY_SKEW_MS\n )\n}\n\nexport class SessionsApi {\n readonly #credentials: CredentialSource\n readonly #refreshLogin?: () => Promise<void>\n readonly #fetch: typeof fetch\n readonly #baseUrl: string\n #credential: CloudCredential | null = null\n\n constructor(options: SessionsApiOptions) {\n this.#credentials = options.credentials\n this.#refreshLogin = options.refreshLogin\n this.#fetch = options.fetchImpl ?? globalThis.fetch.bind(globalThis)\n this.#baseUrl = (options.baseUrl ?? \"https://api.anthropic.com\").replace(/\\/$/, \"\")\n }\n\n /** GET /v1/code/sessions/{id} */\n async getSession(id: string): Promise<CloudGetSessionResponse> {\n return this.#request<CloudGetSessionResponse>(\n \"GET\",\n `/v1/code/sessions/${normalizeSessionId(id)}`,\n )\n }\n\n /**\n * GET /v1/code/sessions/{id}/events — newest first. With no `cursor` this\n * returns the NEWEST page; pass the page's `resume_cursor` (the oldest\n * event's `sequence_num`) as `cursor` to fetch the next OLDER page.\n */\n async listEvents(\n id: string,\n opts: { cursor?: string; limit?: number } = {},\n ): Promise<CloudEventsPage> {\n const params = new URLSearchParams()\n if (opts.cursor) params.set(\"cursor\", opts.cursor)\n if (opts.limit !== undefined) params.set(\"limit\", String(opts.limit))\n const qs = params.toString()\n return this.#request<CloudEventsPage>(\n \"GET\",\n `/v1/code/sessions/${normalizeSessionId(id)}/events${qs ? `?${qs}` : \"\"}`,\n )\n }\n\n /** GET /v1/code/sessions?limit=N */\n async listSessions(\n opts: { limit?: number } = {},\n ): Promise<CloudListSessionsResponse> {\n const qs = opts.limit !== undefined ? `?limit=${opts.limit}` : \"\"\n return this.#request<CloudListSessionsResponse>(\n \"GET\",\n `/v1/code/sessions${qs}`,\n )\n }\n\n async #credentialNow(): Promise<CloudCredential> {\n if (!this.#credential) this.#credential = await this.#credentials.get()\n return this.#credential\n }\n\n /** Refresh the login (when injected), drop the source cache, and re-read.\n * A refresh failure is surfaced to the caller — better a clear \"run\n * `claude auth login`\" than a request with a known-stale token. */\n async #refreshAndInvalidate(): Promise<void> {\n await this.#refreshLogin?.()\n this.#credentials.invalidate()\n this.#credential = null\n }\n\n /** The credential for the next request: refresh first when it is expired\n * or expiring. Without an injected refresh the check is a no-op. */\n async #freshCredential(): Promise<CloudCredential> {\n const credential = await this.#credentialNow()\n if (this.#refreshLogin && isCredentialExpiring(credential)) {\n await this.#refreshAndInvalidate()\n return this.#credentialNow()\n }\n return credential\n }\n\n async #request<T>(method: string, path: string, retriedAuth = false): Promise<T> {\n // On the retry the refresh already ran; read the source directly so a\n // still-stale-looking `expiresAt` cannot start a second refresh.\n const credential = retriedAuth\n ? await this.#credentialNow()\n : await this.#freshCredential()\n const headers: Record<string, string> = {\n authorization: `Bearer ${credential.accessToken}`,\n \"anthropic-version\": \"2023-06-01\",\n \"content-type\": \"application/json\",\n ...(credential.orgUuid ? { \"x-organization-uuid\": credential.orgUuid } : {}),\n }\n const res = await this.#fetch(`${this.#baseUrl}${path}`, { method, headers })\n if (res.status === 401 && !retriedAuth) {\n // The token may have been refreshed out-of-band: refresh the login,\n // drop the source cache and re-read exactly once, then fail closed\n // with the login hint.\n await this.#refreshAndInvalidate()\n return this.#request<T>(method, path, true)\n }\n if (res.status === 401) {\n throw new Error(`claude code cloud: unauthorized (401) — ${UNAUTHORIZED_HINT}`)\n }\n if (!res.ok) {\n throw new Error(\n `claude code cloud: ${method} ${path} failed: HTTP ${res.status}`,\n )\n }\n return (await res.json()) as T\n }\n}\n","/**\n * The vendor-client surface (AIP-66 Appendix A): start a Claude Code cloud\n * session under a PTY, send follow-ups headlessly, and preflight the\n * claude.ai login. The CLI is the only supported way to CREATE and PROMPT a\n * cloud session — the sessions API (sessions-api.ts) is observe-only.\n *\n * Every child process runs with ANTHROPIC_API_KEY and the Claude Code\n * gateway/redirect toggles deleted from its env (AIP-66 §8): a leftover\n * toggle or API key would make the CLI authenticate a different way and\n * refuse (or worse, re-route) the cloud call. The token the CLI reads from\n * the user's own login is never touched, logged or persisted here.\n *\n * The binary runner is injectable so tests can drive every path — auth\n * preflight, trust prompt, output parsing — from fixtures without a live\n * claude CLI or a real PTY.\n */\n\nimport { spawn } from \"node:child_process\"\nimport { tmpdir } from \"node:os\"\nimport { ANTHROPIC_CORE_SCRUB_ENV } from \"@agentproto/provider-presets\"\nimport { toCliSessionId } from \"./sessions-api.js\"\n\n// Cloud-provider redirect toggles scrubbed alongside ANTHROPIC_API_KEY —\n// byte-for-byte the same set the claude-code adapter scrubs for gateway\n// modes (adapters/claude-code/src/index.ts): a leftover Bedrock/Vertex/…\n// toggle in the child env would override the claude.ai login path. The\n// core ANTHROPIC_API_KEY entry comes from @agentproto/provider-presets, the\n// single source of truth for that fact.\nconst CLAUDE_CODE_CLOUD_TOGGLES: readonly string[] = [\n \"CLAUDE_CODE_USE_BEDROCK\",\n \"CLAUDE_CODE_USE_VERTEX\",\n \"CLAUDE_CODE_USE_FOUNDRY\",\n \"CLAUDE_CODE_USE_ANTHROPIC_AWS\",\n \"CLAUDE_CODE_USE_MANTLE\",\n \"CLAUDE_CODE_USE_GATEWAY\",\n]\n\n/** Env keys deleted from every claude child this adapter spawns (AIP-66 §8). */\nexport const CLAUDE_CODE_GATEWAY_ENV_UNSET: readonly string[] = [\n ...ANTHROPIC_CORE_SCRUB_ENV,\n ...CLAUDE_CODE_CLOUD_TOGGLES,\n]\n\n/** Copy `base` with every {@link CLAUDE_CODE_GATEWAY_ENV_UNSET} key deleted. */\nexport function cloudChildEnv(\n base: Record<string, string | undefined> = process.env,\n): Record<string, string> {\n const out: Record<string, string> = {}\n const drop = new Set(CLAUDE_CODE_GATEWAY_ENV_UNSET)\n for (const [key, value] of Object.entries(base)) {\n if (value === undefined || drop.has(key)) continue\n out[key] = value\n }\n return out\n}\n\n// ── TUI output normalization ────────────────────────────────────────────────\n\n/** Matches every terminal escape sequence the claude TUI emits: an OSC\n * (`\\x1b]…\\x07` or `\\x1b]…\\x1b\\\\`), a CSI (`\\x1b[…<final byte>`), or a lone\n * two-byte `\\x1b<char>`. Order matters — OSC and CSI are consumed before the\n * lone-ESC fallback can eat their introducer. */\nconst ANSI_ESCAPE_RE =\n /\\x1b\\][\\s\\S]*?(?:\\x07|\\x1b\\\\)|\\x1b\\[[0-9;?]*[ -/]*[@-~]|\\x1b./g\n\n/**\n * The one normalization every regex over live PTY output must run on. The\n * claude TUI draws text word-by-word, positioning each run with a\n * cursor-column escape (`\\x1b[12Gworkspace:`) instead of a space, so a raw\n * `Yes, I trust this folder` never appears literally and the old matcher\n * stalled until timeout. Here each escape sequence becomes one space, runs of\n * horizontal whitespace collapse to one space, and runs of blank lines\n * collapse to one newline — line boundaries are preserved so the\n * line-oriented `Created cloud session` / `--teleport` regexes below keep\n * working. Pure and exported so tests can target it directly and so no future\n * matcher can reintroduce the same class of bug.\n */\nexport function normalizePtyOutput(raw: string): string {\n return raw\n .replace(ANSI_ESCAPE_RE, \" \")\n .replace(/[^\\S\\n]+/g, \" \")\n .replace(/\\n[ \\t]*(?:\\n[ \\t]*)+/g, \"\\n\")\n .trim()\n}\n\n/** The trust prompt only ever appears INTERLEAVED with cursor escapes. */\nconst TRUST_PROMPT_RE = /Yes,\\s*I\\s*trust\\s*this\\s*folder/i\n\n/** Cap on {@link ptyOutputTail}: enough to see the stalled screen, short\n * enough that no incidental material can ride into a log. */\nconst PTY_TAIL_CHARS = 300\n\n/** ANSI-stripped tail (last ~300 chars) of raw PTY output, for diagnosing a\n * PTY stall from the thrown error alone. */\nexport function ptyOutputTail(raw: string, maxChars = PTY_TAIL_CHARS): string {\n const stripped = normalizePtyOutput(raw)\n return stripped.length > maxChars\n ? stripped.slice(stripped.length - maxChars)\n : stripped\n}\n\n// ── injectable runner ───────────────────────────────────────────────────────\n\nexport interface RunResult {\n code: number\n stdout: string\n stderr: string\n}\n\nexport interface RunOpts {\n cwd: string\n env: Record<string, string>\n timeoutMs?: number\n /** \"ignore\" detaches stdin so a non-interactive call can never TTY-block. */\n stdin?: \"ignore\"\n}\n\nexport interface PtyHandle {\n write(data: string): void\n result: Promise<{ code: number; output: string }>\n}\n\nexport interface PtyRunOpts extends RunOpts {\n onData?: (chunk: string) => void\n}\n\n/** What {@link startCloudSession} / {@link sendPrompt} drive. Tests inject a\n * fake; production uses {@link defaultCloudCliRunner}. */\nexport interface CloudCliRunner {\n run(cmd: string, args: string[], opts: RunOpts): Promise<RunResult>\n runPty(cmd: string, args: string[], opts: PtyRunOpts): PtyHandle\n}\n\nconst DEFAULT_RUN_TIMEOUT_MS = 60_000\n\n/** Options handed to a {@link PtySpawn} call (the node-pty fork options this\n * adapter actually sets). */\nexport interface PtySpawnOptions {\n name: string\n cols: number\n rows: number\n cwd: string\n env: Record<string, string>\n}\n\n/** The subset of node-pty's `IPty` surface this adapter drives. Structural, so\n * the real `IPty` satisfies it and a test can stand in a fake PTY. */\nexport interface PtyProcess {\n onData(cb: (chunk: string) => void): void\n onExit(cb: (event: { exitCode: number }) => void): void\n write(data: string): void\n kill(signal?: string): void\n}\n\n/** Spawns a PTY. Production is node-pty's `spawn`; tests inject a fake. */\nexport type PtySpawn = (\n cmd: string,\n args: string[],\n opts: PtySpawnOptions,\n) => PtyProcess\n\nexport interface CloudCliRunnerDeps {\n /** Test seam: override node-pty's `spawn` so the PTY paths can be driven\n * from fixtures without a real claude CLI or a native PTY. Production\n * leaves it unset and node-pty is lazily imported. */\n spawnPty?: PtySpawn\n}\n\n/** Real runner: child_process for headless calls, node-pty (optional dep)\n * for the TTY-required `claude --cloud` start. */\nexport function defaultCloudCliRunner(\n deps: CloudCliRunnerDeps = {},\n): CloudCliRunner {\n return {\n run(cmd, args, opts) {\n return new Promise<RunResult>((resolve, reject) => {\n const child = spawn(cmd, args, {\n cwd: opts.cwd,\n env: opts.env,\n stdio: [opts.stdin === \"ignore\" ? \"ignore\" : \"inherit\", \"pipe\", \"pipe\"],\n })\n let stdout = \"\"\n let stderr = \"\"\n const timer = setTimeout(() => {\n child.kill(\"SIGKILL\")\n reject(\n new Error(\n `claude code cloud: \\`${cmd} ${args.join(\" \")}\\` timed out after ` +\n `${opts.timeoutMs ?? DEFAULT_RUN_TIMEOUT_MS}ms`,\n ),\n )\n }, opts.timeoutMs ?? DEFAULT_RUN_TIMEOUT_MS)\n timer.unref?.()\n child.stdout?.on(\"data\", (d: Buffer) => (stdout += d.toString()))\n child.stderr?.on(\"data\", (d: Buffer) => (stderr += d.toString()))\n child.on(\"error\", (err) => {\n clearTimeout(timer)\n reject(err)\n })\n child.on(\"close\", (code) => {\n clearTimeout(timer)\n resolve({ code: code ?? -1, stdout, stderr })\n })\n })\n },\n runPty(cmd, args, opts) {\n let resolveResult!: (v: { code: number; output: string }) => void\n let rejectResult!: (err: unknown) => void\n const result = new Promise<{ code: number; output: string }>((res, rej) => {\n resolveResult = res\n rejectResult = rej\n })\n let proc: PtyProcess | null = null\n const pendingWrites: string[] = []\n const attach = (spawnFn: PtySpawn) => {\n const p = spawnFn(cmd, args, {\n name: \"xterm-256color\",\n cols: 120,\n rows: 40,\n cwd: opts.cwd,\n env: opts.env,\n })\n proc = p\n for (const data of pendingWrites) p.write(data)\n pendingWrites.length = 0\n let output = \"\"\n let answeredTrustPrompt = false\n p.onData((chunk: string) => {\n output += chunk\n opts.onData?.(chunk)\n // First run in a folder shows a trust prompt whose DEFAULT\n // highlighted option is \"No, exit\" — Down + Enter picks\n // \"Yes, I trust this folder\". The TUI renders it through cursor\n // escapes, so match on the normalized transcript. Answer at most\n // once.\n if (\n !answeredTrustPrompt &&\n TRUST_PROMPT_RE.test(normalizePtyOutput(output))\n ) {\n answeredTrustPrompt = true\n p.write(\"\\x1b[B\\r\")\n }\n })\n const timer = setTimeout(() => {\n try {\n p.kill(\"SIGKILL\")\n } catch {\n // already dead\n }\n rejectResult(\n new Error(\n `claude code cloud: \\`${cmd} ${args.join(\" \")}\\` timed out after ` +\n `${opts.timeoutMs ?? 120_000}ms under the PTY; last output: ` +\n `${ptyOutputTail(output)}`,\n ),\n )\n }, opts.timeoutMs ?? 120_000)\n timer.unref?.()\n p.onExit(({ exitCode }: { exitCode: number }) => {\n clearTimeout(timer)\n resolveResult({ code: exitCode, output })\n })\n }\n if (deps.spawnPty) {\n try {\n attach(deps.spawnPty)\n } catch (err) {\n rejectResult(err)\n }\n } else {\n // node-pty is an optional native dep (same policy as @agentproto/cli):\n // load it lazily and fail with an actionable message when absent.\n void import(\"node-pty\")\n .then(mod => {\n // node-pty is CJS — `import()` wraps it under `.default`.\n const pty =\n (mod as { default?: { spawn: PtySpawn } }).default ??\n (mod as unknown as { spawn: PtySpawn })\n if (typeof pty.spawn !== \"function\") throw new Error(\"node-pty has no spawn\")\n attach(pty.spawn)\n })\n .catch(err => {\n rejectResult(\n new Error(\n `claude code cloud: \\`claude --cloud\\` needs a real PTY and ` +\n `node-pty is not available (${err instanceof Error ? err.message : String(err)}) — ` +\n `install it (npm i node-pty) to use managed cloud sessions`,\n ),\n )\n })\n }\n return {\n write: (data: string) => {\n if (proc) proc.write(data)\n else pendingWrites.push(data)\n },\n result,\n }\n },\n }\n}\n\n// ── login refresh ───────────────────────────────────────────────────────────\n\nexport interface RefreshLoginOpts {\n runner?: CloudCliRunner\n env?: Record<string, string | undefined>\n /** Default os.tmpdir(): the refresh must not depend on any repo checkout. */\n cwd?: string\n /** Default 60s. */\n timeoutMs?: number\n}\n\n/**\n * Build the injectable login-refresh trigger. Running a trivial headless\n * prompt (`claude -p \"Reply OK\" --model haiku`) is what makes the claude CLI\n * re-mint and re-write the OAuth access token to the keychain (verified\n * live: `claude auth status` does NOT refresh it). stdin is detached, the\n * child runs from {@link os.tmpdir} with the same scrubbed env every other\n * claude child gets, and its stdout/stderr are never read or logged — they\n * can carry token-adjacent material and must not leak.\n *\n * Concurrent callers share one in-flight refresh (a single promise), so a\n * burst of requests around expiry runs the CLI at most once.\n */\nexport function createRefreshLogin(\n opts: RefreshLoginOpts = {},\n): () => Promise<void> {\n let inFlight: Promise<void> | null = null\n return () => {\n if (inFlight) return inFlight\n const run = (async () => {\n const runner = opts.runner ?? defaultCloudCliRunner()\n const env = cloudChildEnv(opts.env ?? process.env)\n let result: RunResult\n try {\n result = await runner.run(\n \"claude\",\n [\"-p\", \"Reply OK\", \"--model\", \"haiku\"],\n {\n cwd: opts.cwd ?? tmpdir(),\n env,\n stdin: \"ignore\",\n timeoutMs: opts.timeoutMs ?? 60_000,\n },\n )\n } catch (err) {\n throw new Error(\n \"claude code cloud: could not refresh the claude.ai login — is \" +\n `the claude CLI installed and on PATH? (${err instanceof Error ? err.message : String(err)})`,\n )\n }\n if (result.code !== 0) {\n // Never surface stdout/stderr: the refresh child may print\n // token-adjacent output that must not enter a log.\n throw new Error(\n \"claude code cloud: could not refresh the claude.ai login \" +\n `(exit ${result.code}) — run \\`claude auth login\\``,\n )\n }\n })()\n const wrapped = run.finally(() => {\n if (inFlight === wrapped) inFlight = null\n })\n inFlight = wrapped\n return wrapped\n }\n}\n\n// ── auth preflight ──────────────────────────────────────────────────────────\n\nexport interface AuthStatus {\n loggedIn: boolean\n authMethod?: string\n}\n\n/** Parse `claude auth status` JSON output. */\nexport function parseAuthStatus(stdout: string): AuthStatus {\n const trimmed = stdout.trim()\n const start = trimmed.indexOf(\"{\")\n const end = trimmed.lastIndexOf(\"}\")\n if (start === -1 || end === -1 || end < start) {\n throw new Error(\n \"claude code cloud: could not parse `claude auth status` output — \" +\n \"run `claude auth login`\",\n )\n }\n const parsed = JSON.parse(trimmed.slice(start, end + 1)) as {\n loggedIn?: boolean\n authMethod?: string\n }\n return { loggedIn: parsed.loggedIn === true, authMethod: parsed.authMethod }\n}\n\n/**\n * Refuse the spawn before any side effect when the claude CLI is missing,\n * not logged in, or authenticated by API key — cloud sessions require a\n * claude.ai sign-in (verified live: an ANTHROPIC_API_KEY env makes the CLI\n * refuse with \"Cloud sessions need a claude.ai sign-in\").\n */\nexport async function preflightAuth(\n runner: CloudCliRunner,\n opts: { cwd: string; env: Record<string, string> },\n): Promise<AuthStatus> {\n let result: RunResult\n try {\n result = await runner.run(\"claude\", [\"auth\", \"status\"], {\n cwd: opts.cwd,\n env: opts.env,\n timeoutMs: 15_000,\n stdin: \"ignore\",\n })\n } catch (err) {\n throw new Error(\n `claude code cloud: could not run \\`claude auth status\\` — is the ` +\n `claude CLI installed and on PATH? (${err instanceof Error ? err.message : String(err)})`,\n )\n }\n if (result.code !== 0 && !result.stdout.trim()) {\n throw new Error(\n \"claude code cloud: `claude auth status` failed — the claude CLI is \" +\n \"not usable; run `claude auth login`\",\n )\n }\n const status = parseAuthStatus(result.stdout)\n if (!status.loggedIn) {\n throw new Error(\n \"claude code cloud: not logged in — cloud sessions need a claude.ai \" +\n \"sign-in; run `claude auth login`\",\n )\n }\n if (status.authMethod === \"api_key\") {\n throw new Error(\n \"claude code cloud: authenticated by API key — cloud sessions need a \" +\n \"claude.ai sign-in; run `claude auth login`\",\n )\n }\n return status\n}\n\n// ── start / send ────────────────────────────────────────────────────────────\n\nexport interface StartedCloudSession {\n /** CLI-spelled id (`session_<id>`), ready for `--cloud` / `--teleport`. */\n sessionId: string\n url: string\n title?: string\n}\n\n/** Parse the `claude --cloud` start transcript: the id from the \"Resume\n * with:\" line (falling back to the View URL's path), the URL, and the\n * session title. Returns null when no session id can be found. */\nexport function parseCloudStartOutput(\n output: string,\n): StartedCloudSession | null {\n // The transcript may be the same escape-separated TUI output the trust\n // matcher sees — normalize first so these line regexes can't go dark the\n // way the trust prompt did.\n const transcript = normalizePtyOutput(output)\n let sessionId: string | undefined\n let url: string | undefined\n let title: string | undefined\n\n const resume = transcript.match(/Resume with:\\s*claude\\s+--teleport\\s+(session_[A-Za-z0-9_-]+)/)\n if (resume?.[1]) sessionId = resume[1]\n\n const view = transcript.match(/View:\\s*(https?:\\/\\/\\S+)/)\n if (view?.[1]) {\n url = view[1]\n if (!sessionId) {\n const fromUrl = url.match(/\\/session_([A-Za-z0-9_-]+)/)\n if (fromUrl?.[1]) sessionId = `session_${fromUrl[1]}`\n }\n }\n\n const created = transcript.match(/Created cloud session:\\s*(.+)/)\n if (created?.[1]) title = created[1].trim()\n\n if (!sessionId) return null\n return {\n sessionId,\n url: url ?? `https://claude.ai/code/${sessionId}`,\n ...(title ? { title } : {}),\n }\n}\n\nexport interface StartCloudSessionOpts {\n runner?: CloudCliRunner\n env?: Record<string, string | undefined>\n cwd: string\n /** Hard cap on the interactive start (PTY) — default 120s. */\n timeoutMs?: number\n /** Skip the auth preflight (tests only; production always preflights). */\n skipPreflight?: boolean\n}\n\n/**\n * Start a cloud session: `claude --cloud \"<prompt>\"` under a PTY (the CLI\n * requires a TTY here), answering the first-run folder-trust prompt, then\n * parse the printed session id / URL and exit. The vendor runs the first\n * turn; observe it via the sessions API.\n */\nexport async function startCloudSession(\n prompt: string,\n opts: StartCloudSessionOpts,\n): Promise<StartedCloudSession> {\n const runner = opts.runner ?? defaultCloudCliRunner()\n const env = cloudChildEnv(opts.env ?? process.env)\n if (!opts.skipPreflight) await preflightAuth(runner, { cwd: opts.cwd, env })\n\n const pty = runner.runPty(\"claude\", [\"--cloud\", prompt], {\n cwd: opts.cwd,\n env,\n timeoutMs: opts.timeoutMs ?? 120_000,\n })\n const { code, output } = await pty.result\n if (code !== 0) {\n throw new Error(\n `claude code cloud: \\`claude --cloud\\` exited ${code}: ` +\n `${output.trim().split(\"\\n\").slice(-5).join(\"\\n\").trim()}`,\n )\n }\n const started = parseCloudStartOutput(output)\n if (!started) {\n throw new Error(\n \"claude code cloud: could not parse a cloud session id from \" +\n \"`claude --cloud` output\",\n )\n }\n return started\n}\n\nexport interface SendPromptOpts {\n runner?: CloudCliRunner\n env?: Record<string, string | undefined>\n cwd: string\n timeoutMs?: number\n skipPreflight?: boolean\n}\n\n/**\n * Send a follow-up turn: `claude -p \"<text>\" --cloud <session id>` with\n * stdin detached (no TTY). Send-only by design — the CLI prints \"Sent to\n * cloud session.\" and never the reply; the reply is observed via the\n * sessions API. Accepts `session_`/`cse_` ids.\n */\nexport async function sendPrompt(\n sessionId: string,\n text: string,\n opts: SendPromptOpts,\n): Promise<{ stdout: string }> {\n const runner = opts.runner ?? defaultCloudCliRunner()\n const env = cloudChildEnv(opts.env ?? process.env)\n if (!opts.skipPreflight) await preflightAuth(runner, { cwd: opts.cwd, env })\n\n const result = await runner.run(\n \"claude\",\n [\"-p\", text, \"--cloud\", toCliSessionId(sessionId)],\n {\n cwd: opts.cwd,\n env,\n stdin: \"ignore\",\n timeoutMs: opts.timeoutMs ?? 60_000,\n },\n )\n if (result.code !== 0) {\n throw new Error(\n `claude code cloud: \\`claude -p --cloud\\` exited ${result.code}: ` +\n `${(result.stderr || result.stdout).trim().split(\"\\n\").slice(-5).join(\"\\n\").trim()}`,\n )\n }\n return { stdout: result.stdout }\n}\n","/**\n * AIP-66 §5/§8 — how this relay REPORTS the learned vendor session\n * identity to the host.\n *\n * The host (the runtime's `session-spawn.ts` + `cloud-vendors.ts`) hands\n * the relay the path of a file inside the session's isolated config dir via\n * `AGENTPROTO_CLOUD_SESSION_META_FILE`. Once the vendor has returned a\n * session id — after `claude --cloud` prints it, or when `session/load`\n * adopts the id persisted on `meta.cloud.sessionId` — the relay writes\n * exactly the three §5 fields `{ vendor, sessionId, url }` there, and the\n * host polls that file (`watchCloudSessionMeta`) to stamp\n * `meta.cloud = { vendor, sessionId, url }` onto the descriptor.\n *\n * ONLY those three fields are ever written: the vendor's OAuth credential\n * never enters this file, logs or events (AIP-66 §8). The write is\n * best-effort and atomic (temp file + rename), so a failed side-file write\n * can never sink the turn that learned the id — the host's poll simply\n * keeps watching.\n */\n\nimport { mkdir, readFile, rename, writeFile } from \"node:fs/promises\"\nimport { dirname } from \"node:path\"\n\n/** Env var carrying the absolute path of the meta file. Mirrors the\n * runtime's `CLOUD_SESSION_META_FILE_ENV` (cloud-vendors.ts) — the two\n * must stay byte-identical or the relay writes where nobody reads. */\nexport const CLOUD_SESSION_META_FILE_ENV = \"AGENTPROTO_CLOUD_SESSION_META_FILE\"\n\n/** The vendor slug this adapter relays to (AIP-66 §2 `CloudVendor.slug`,\n * registry entry `anthropic` → adapter `claude-code-cloud`). */\nexport const CLOUD_VENDOR_SLUG = \"anthropic\"\n\n/** The §5 mapping the relay reports. NEVER carries a credential. */\nexport interface CloudSessionMetaReport {\n vendor: string\n /** Vendor session id — CLI spelling (`session_<id>`). */\n sessionId: string\n /** Session URL when known (the start path prints it; a re-attach may\n * inherit it from the file already on disk). */\n url?: string\n}\n\n/** Read + parse a previously written meta file. Returns undefined for\n * absent/garbage — never throws (this is a side file, not a contract). */\nasync function readExisting(path: string): Promise<CloudSessionMetaReport | undefined> {\n try {\n const parsed: unknown = JSON.parse(await readFile(path, \"utf8\"))\n if (!parsed || typeof parsed !== \"object\" || Array.isArray(parsed)) return undefined\n const p = parsed as Record<string, unknown>\n if (typeof p[\"vendor\"] !== \"string\" || p[\"vendor\"].length === 0) return undefined\n if (typeof p[\"sessionId\"] !== \"string\" || p[\"sessionId\"].length === 0) return undefined\n return {\n vendor: p[\"vendor\"],\n sessionId: p[\"sessionId\"],\n ...(typeof p[\"url\"] === \"string\" && p[\"url\"].length > 0 ? { url: p[\"url\"] } : {}),\n }\n } catch {\n return undefined\n }\n}\n\n/**\n * Write `{ vendor, sessionId, url }` to the meta file the host named in\n * `AGENTPROTO_CLOUD_SESSION_META_FILE`. Returns the path written, or null\n * when the env var is unset or the write failed (best-effort: the host's\n * poll retries, and a cloud turn must never fail over a side file).\n *\n * A re-attach (`session/load`) carries no URL — when the id on disk matches\n * the one being reported, the existing `url` is preserved so the host's\n * later read keeps the full §5 mapping.\n */\nexport async function writeCloudSessionMeta(\n meta: CloudSessionMetaReport,\n opts: { env?: Record<string, string | undefined> } = {},\n): Promise<string | null> {\n const env = opts.env ?? process.env\n const path = env[CLOUD_SESSION_META_FILE_ENV]\n if (!path) return null\n try {\n const existing = await readExisting(path)\n const url =\n meta.url ??\n (existing?.sessionId === meta.sessionId ? existing.url : undefined)\n const payload = JSON.stringify({\n vendor: meta.vendor,\n sessionId: meta.sessionId,\n ...(url !== undefined ? { url } : {}),\n })\n await mkdir(dirname(path), { recursive: true })\n // Temp + rename: the host polls this file, and a torn read must never\n // be observed (parse failures would just stall the learn, but atomicity\n // costs nothing here).\n const tmp = `${path}.${process.pid}.tmp`\n await writeFile(tmp, payload, \"utf8\")\n await rename(tmp, path)\n return path\n } catch (err) {\n process.stderr.write(\n `[claude-code-cloud] could not write the cloud session meta file ` +\n `(${CLOUD_SESSION_META_FILE_ENV}): ${err instanceof Error ? err.message : String(err)}\\n`,\n )\n return null\n }\n}\n","/**\n * AIP-66 §3 (repo source): a managed cloud agent runs on a git remote and\n * ref — never on an uploaded working tree. The host MUST refuse the spawn\n * when `cwd` is not a git checkout with a remote, when the working tree is\n * dirty, or when HEAD is not reachable from the remote.\n *\n * Pure git-invocation logic with an injectable runner so tests can drive\n * every refusal from fixtures (no real repo required).\n */\n\nimport { execFile } from \"node:child_process\"\nimport { promisify } from \"node:util\"\n\nconst execFileAsync = promisify(execFile)\n\n/** Runs `git <args…>` in `cwd`; resolves with the exit code + streams. */\nexport type GitRunner = (\n args: string[],\n cwd: string,\n) => Promise<{ code: number; stdout: string; stderr: string }>\n\nexport const defaultGitRunner: GitRunner = async (args, cwd) => {\n try {\n const { stdout, stderr } = await execFileAsync(\"git\", args, { cwd })\n return { code: 0, stdout, stderr }\n } catch (err) {\n const e = err as { code?: number; stdout?: string; stderr?: string }\n return {\n code: typeof e.code === \"number\" ? e.code : 1,\n stdout: e.stdout ?? \"\",\n stderr: e.stderr ?? \"\",\n }\n }\n}\n\n/**\n * Refuse (throw) unless `cwd` is a clean git checkout whose HEAD is\n * contained in some `origin/*` ref. Each error names the failed condition —\n * the ACP server surfaces it as the `session/new` failure.\n */\nexport async function validateRepoSource(\n cwd: string,\n git: GitRunner = defaultGitRunner,\n): Promise<void> {\n const inside = await git([\"rev-parse\", \"--is-inside-work-tree\"], cwd)\n if (inside.code !== 0 || inside.stdout.trim() !== \"true\") {\n throw new Error(\n `claude code cloud: ${cwd} is not a git checkout — managed cloud ` +\n \"agents run on a git remote and ref (AIP-66 §3)\",\n )\n }\n\n const status = await git([\"status\", \"--porcelain\"], cwd)\n if (status.code !== 0) {\n throw new Error(\n `claude code cloud: could not read the working tree status in ${cwd} ` +\n `(${status.stderr.trim() || `git status exited ${status.code}`})`,\n )\n }\n if (status.stdout.trim().length > 0) {\n throw new Error(\n `claude code cloud: the working tree in ${cwd} is dirty — commit or ` +\n \"stash first; the vendor refuses to upload uncommitted files \" +\n \"(AIP-66 §3)\",\n )\n }\n\n const remote = await git([\"remote\", \"get-url\", \"origin\"], cwd)\n if (remote.code !== 0 || !remote.stdout.trim()) {\n throw new Error(\n `claude code cloud: ${cwd} has no origin remote — a managed cloud ` +\n \"agent runs on the repo's remote, not a local path (AIP-66 §3)\",\n )\n }\n\n const head = await git([\"rev-parse\", \"HEAD\"], cwd)\n if (head.code !== 0 || !head.stdout.trim()) {\n throw new Error(\n `claude code cloud: could not resolve HEAD in ${cwd} (${head.stderr.trim() || `git rev-parse HEAD exited ${head.code}`})`,\n )\n }\n\n // HEAD must be contained in some origin/* ref — i.e. pushed. An unpushed\n // commit (or a local-only branch) is refused; the vendor can only check\n // out what the remote actually has.\n const contains = await git([\"branch\", \"-r\", \"--contains\", \"HEAD\"], cwd)\n if (contains.code !== 0 || !contains.stdout.trim()) {\n throw new Error(\n `claude code cloud: HEAD in ${cwd} is not reachable from origin — ` +\n \"push the commit before starting a cloud session (AIP-66 §3)\",\n )\n }\n}\n","/**\n * The AIP-44 ACP server for Claude Code cloud sessions (AIP-66). This is\n * the binary the daemon spawns (`bin/claude-code-cloud-acp.mjs` → dist):\n * the vendor owns the machine and the harness, so this server does not run\n * any agent — it relays.\n *\n * - `session/new` validates the cwd as a pushed, clean git checkout\n * (AIP-66 §3) BEFORE any vendor side effect.\n * - first `session/prompt` → `claude --cloud \"<prompt>\"` (start), later\n * ones → `claude -p … --cloud <id>` (send-only).\n * - `session/load` RE-ATTACHES to the vendor session id the host\n * persisted on `meta.cloud.sessionId` (AIP-66 §5): the adopted id makes\n * the next prompt a `sendPrompt` — the relay never starts a replacement\n * vendor session.\n * - the learned identity (`{ vendor, sessionId, url }`) is reported to\n * the host through the meta file named by `AGENTPROTO_CLOUD_SESSION_META_FILE`\n * (meta-file.ts) — never a credential (AIP-66 §8).\n * - the turn is then observed via the sessions API: events are mapped\n * with @agentproto/adapter-claude-sdk's stream-json → ACP mappers\n * (the payloads ARE Claude Code stream-json SDK messages — reused, not\n * forked), and ONLY the vendor's own `result` event ends the prompt\n * (AIP-66 §6: never a timer, never silence). Transient read failures\n * (HTTP 5xx, network) are retried with backoff before the prompt fails.\n * - `result` carries `total_cost_usd` + `usage` → an ACP `usage_update`\n * (AIP-66 §7); a result without usage emits none — unmeasured, never\n * zero.\n * - `session/cancel` is unsupported: the vendor exposes no interrupt\n * verb, and AIP-66 §6 says a host without one reports it unsupported.\n */\n\nimport { Readable, Writable } from \"node:stream\"\nimport {\n AgentSideConnection,\n ndJsonStream,\n PROTOCOL_VERSION,\n type Agent,\n type CancelNotification,\n type InitializeRequest,\n type InitializeResponse,\n type LoadSessionRequest,\n type LoadSessionResponse,\n type NewSessionRequest,\n type NewSessionResponse,\n type PromptRequest,\n type PromptResponse,\n type SetSessionConfigOptionRequest,\n type SetSessionConfigOptionResponse,\n type SetSessionModeRequest,\n type SetSessionModeResponse,\n type SessionNotification,\n type SessionUpdate,\n type StopReason,\n} from \"@agentclientprotocol/sdk\"\nimport { promptText, sdkMessageToUpdates } from \"@agentproto/adapter-claude-sdk\"\nimport {\n createRefreshLogin,\n defaultCloudCliRunner,\n sendPrompt as defaultSendPrompt,\n startCloudSession as defaultStartCloudSession,\n type StartedCloudSession,\n} from \"./cli.js\"\nimport {\n SessionsApi,\n eventSequence,\n keychainCredentialSource,\n toCliSessionId,\n type CloudEventsPage,\n type CloudSessionEvent,\n type CredentialSource,\n} from \"./sessions-api.js\"\nimport { CLOUD_VENDOR_SLUG, writeCloudSessionMeta } from \"./meta-file.js\"\nimport { validateRepoSource } from \"./repo-source.js\"\n\n/**\n * The wire shape the cloud events API serves as `event.payload`: a Claude\n * Code stream-json SDK message. Derived from `sdkMessageToUpdates`'s\n * parameter so this package does not need a direct dependency on\n * `@anthropic-ai/claude-agent-sdk` (which would otherwise be a transitive\n * dep of `adapter-claude-sdk` and could break under strict pnpm or leak\n * into the emitted d.ts).\n */\ntype SDKMessage = Parameters<typeof sdkMessageToUpdates>[0]\n\n/** Poll cadence: 2s, backing off to 10s while the turn is still running. */\nexport const POLL_INITIAL_MS = 2_000\nexport const POLL_MAX_MS = 10_000\n\n/**\n * Budget of consecutive transient `listEvents` failures before the turn's\n * observation fails: the first four are retried with the poll backoff, the\n * fifth consecutive one fails the turn. The bound decides only when READING\n * events becomes impossible — a turn still ENDS solely on a vendor `result`\n * event (AIP-66 §6).\n */\nexport const MAX_LIST_EVENTS_FAILURES = 5\n\n/**\n * Cap on history pages walked BACKWARD within one observe tick. The API's\n * cursor pages backward in time (newest page first), so catching up after a\n * gap of more than one page (50 events) means following `resume_cursor`\n * toward older events. A single tick is bounded so a pathological cursor\n * cannot hold a poll open; 20 pages (1000 events) is far past any real gap.\n */\nexport const OBSERVE_PAGES_LIMIT = 20\n\n/** Node/network error codes a transient fetch failure can surface (walked\n * down the `cause` chain — undici wraps them under \"fetch failed\"). */\nconst NETWORK_ERROR_CODES =\n /^(ECONNABORTED|ECONNREFUSED|ECONNRESET|EHOSTUNREACH|ENETUNREACH|EAI_AGAIN|ENOTFOUND|EPIPE|ETIMEDOUT|UND_ERR)/\n\n/**\n * Worth retrying: an HTTP 5xx from the vendor API, or a network-level\n * failure. 4xx (auth, not-found, bad request) and payload/parse errors are\n * NOT transient — retrying them would just stall the turn.\n */\nexport function isTransientListEventsError(err: unknown): boolean {\n if (!(err instanceof Error)) return false\n if (/\\bHTTP 5\\d\\d\\b/.test(err.message)) return true\n if (/fetch failed|network error|socket hang up/i.test(err.message)) return true\n let cause: unknown = err\n for (let depth = 0; depth < 4 && cause; depth += 1) {\n const code = (cause as { code?: unknown }).code\n if (typeof code === \"string\" && NETWORK_ERROR_CODES.test(code)) return true\n cause = (cause as { cause?: unknown }).cause\n }\n return false\n}\n\n/** Read the ACP prompt's text content blocks. */\nexport { promptText }\n\n/** The observe surface the turn loop needs — satisfied by {@link SessionsApi}. */\nexport interface CloudEventsClient {\n listEvents(\n id: string,\n opts?: { cursor?: string; limit?: number },\n ): Promise<CloudEventsPage>\n}\n\n/** The start/send surface — satisfied by cli.ts's functions. */\nexport interface CloudCliDeps {\n startCloudSession(\n prompt: string,\n opts: { cwd: string },\n ): Promise<StartedCloudSession>\n sendPrompt(\n sessionId: string,\n text: string,\n opts: { cwd: string },\n ): Promise<{ stdout: string }>\n}\n\nexport interface ClaudeCloudAcpDeps {\n /** Events client. Default: real {@link SessionsApi} on the keychain login. */\n api?: CloudEventsClient\n /** Vendor CLI. Default: cli.ts's start/send against the real runner. */\n cli?: CloudCliDeps\n /** Repo-source validator (AIP-66 §3). Default: real git invocations. */\n validateRepo?: (cwd: string) => Promise<void>\n sleep?: (ms: number) => Promise<void>\n pollInitialMs?: number\n pollMaxMs?: number\n}\n\ninterface CloudSessionState {\n readonly id: string\n readonly cwd: string\n /** Vendor session id (`session_…`), set by the first prompt's start. */\n vendorSessionId: string | null\n vendorUrl: string | null\n /** Highest `sequence_num` already projected or seeded. The observe loop\n * projects only events with a greater seq, in ascending order — the\n * cursor itself is NOT tracked because it pages BACKWARD in time\n * (sessions-api.ts), so progress must key off the monotonic seq. */\n lastSeq: number\n /** The seq high-water recorded right before this turn's prompt was sent.\n * Only a vendor `result` with a seq ABOVE this ends the turn (AIP-66\n * §6) — an old result that predates the prompt never can. */\n turnBaseline: number\n promptInFlight: boolean\n}\n\nfunction defaultSleep(ms: number): Promise<void> {\n return new Promise(resolve => {\n const timer = setTimeout(resolve, ms)\n timer.unref?.()\n })\n}\n\nfunction defaultDeps(): Required<\n Pick<ClaudeCloudAcpDeps, \"api\" | \"cli\" | \"validateRepo\">\n> {\n const runner = defaultCloudCliRunner()\n const credentials: CredentialSource = keychainCredentialSource()\n // One login-refresh trigger per relay process: shared in-flight, so a\n // burst of requests around token expiry runs the CLI at most once. Both\n // the fresh-spawn and session/load paths reach the API through this client.\n const refreshLogin = createRefreshLogin({ runner, env: process.env })\n return {\n api: new SessionsApi({ credentials, refreshLogin }),\n cli: {\n startCloudSession: (prompt, opts) =>\n defaultStartCloudSession(prompt, {\n cwd: opts.cwd,\n runner,\n env: process.env,\n }),\n sendPrompt: (id, text, opts) =>\n defaultSendPrompt(id, text, {\n cwd: opts.cwd,\n runner,\n env: process.env,\n }),\n },\n validateRepo: (cwd: string) => validateRepoSource(cwd),\n }\n}\n\n/** Map a `result` event's payload to ACP updates. AIP-66 §7: usage is\n * reported only when the vendor's event carries it; absent usage is\n * UNMEASURED — never a fabricated zero. The shared mapper handles the\n * shape; we normalize the two fields it reads defensively (`modelUsage`,\n * `usage`). */\nexport function resultEventUpdates(payload: unknown): SessionUpdate[] {\n const p = (payload ?? {}) as {\n usage?: unknown\n total_cost_usd?: unknown\n modelUsage?: unknown\n }\n const hasUsage = p.usage != null || typeof p.total_cost_usd === \"number\"\n if (!hasUsage) return []\n const normalized = {\n ...p,\n type: \"result\",\n modelUsage: p.modelUsage ?? {},\n usage: p.usage ?? { input_tokens: 0, output_tokens: 0 },\n }\n return sdkMessageToUpdates(normalized as unknown as SDKMessage).filter(\n u => u.sessionUpdate === \"usage_update\",\n )\n}\n\n/** Stop reason from the `result` payload: an error (or any non-success\n * subtype) stops as `refusal` — ACP has no dedicated error stop. */\nexport function resultStopReason(payload: unknown): StopReason {\n const p = (payload ?? {}) as { is_error?: boolean; subtype?: string }\n if (p.is_error === true) return \"refusal\"\n if (p.subtype !== undefined && p.subtype !== \"success\") return \"refusal\"\n return \"end_turn\"\n}\n\nfunction errorResultText(payload: unknown): string | null {\n const p = (payload ?? {}) as { result?: unknown }\n if (typeof p.result === \"string\" && p.result.trim()) return p.result\n return null\n}\n\nexport class ClaudeCloudAcpAgent implements Agent {\n readonly #conn: AgentSideConnection\n readonly #api: CloudEventsClient\n readonly #cli: CloudCliDeps\n readonly #validateRepo: (cwd: string) => Promise<void>\n readonly #sleep: (ms: number) => Promise<void>\n readonly #pollInitialMs: number\n readonly #pollMaxMs: number\n readonly #sessions = new Map<string, CloudSessionState>()\n\n constructor(conn: AgentSideConnection, deps: ClaudeCloudAcpDeps = {}) {\n // Defaults are lazy: the real SessionsApi/keychain/runner only touch\n // the system when a turn actually runs — safe to construct always.\n const defaults = defaultDeps()\n this.#conn = conn\n this.#api = deps.api ?? defaults.api\n this.#cli = deps.cli ?? defaults.cli\n this.#validateRepo = deps.validateRepo ?? defaults.validateRepo\n this.#sleep = deps.sleep ?? defaultSleep\n this.#pollInitialMs = deps.pollInitialMs ?? POLL_INITIAL_MS\n this.#pollMaxMs = deps.pollMaxMs ?? POLL_MAX_MS\n }\n\n async initialize(_params: InitializeRequest): Promise<InitializeResponse> {\n return {\n protocolVersion: PROTOCOL_VERSION,\n agentCapabilities: {\n // Re-attach rides ACP `session/load` with the vendor session id the\n // host persisted on `meta.cloud.sessionId` (AIP-66 §5) — that call\n // ADOPTS the existing cloud session, it never starts a new one.\n loadSession: true,\n },\n }\n }\n\n async authenticate(): Promise<void> {\n // Auth is the user's claude.ai login, owned by the claude CLI —\n // preflighted per turn (see cli.ts). No ACP handshake.\n }\n\n async newSession(params: NewSessionRequest): Promise<NewSessionResponse> {\n // AIP-66 §4: mcpServers has no meaning for a vendor-owned harness —\n // refuse rather than silently drop (the host-level gate refuses the\n // whole spawn field set; this is the relay's own fail-closed backstop).\n if (params.mcpServers && params.mcpServers.length > 0) {\n throw new Error(\n \"claude code cloud: mcpServers is not supported for managed cloud \" +\n \"agents (AIP-66 §4) — the vendor owns the harness\",\n )\n }\n // AIP-66 §3 — refuse BEFORE any vendor side effect.\n await this.#validateRepo(params.cwd)\n const id = crypto.randomUUID()\n this.#sessions.set(id, {\n id,\n cwd: params.cwd,\n vendorSessionId: null,\n vendorUrl: null,\n lastSeq: 0,\n turnBaseline: 0,\n promptInFlight: false,\n })\n return { sessionId: id }\n }\n\n /**\n * AIP-66 §5 re-attach: ADOPT the vendor session id the host persisted on\n * `meta.cloud.sessionId` as this ACP session's vendor session. No vendor\n * side effect happens here — the next `session/prompt` goes through\n * `sendPrompt` (`claude -p … --cloud <id>`), never `startCloudSession`,\n * so a resumed relay can never replace the vendor's session with a new\n * one. The adopted id is also reported back to the host's meta file so a\n * re-attach against a fresh config dir still carries the §5 mapping.\n *\n * Fails closed on an id the vendor could never own (e.g. the ACP uuid of\n * a spawn whose vendor id was never learned): no session is started in\n * its place.\n */\n async loadSession(params: LoadSessionRequest): Promise<LoadSessionResponse> {\n // Same §4 backstop as session/new — resume passes the host's persisted\n // mcpServers (empty for a cloud spawn; a non-empty list still means\n // \"silently drop the field\", which §4 forbids).\n if (params.mcpServers && params.mcpServers.length > 0) {\n throw new Error(\n \"claude code cloud: mcpServers is not supported for managed cloud \" +\n \"agents (AIP-66 §4) — the vendor owns the harness\",\n )\n }\n // Reject a malformed session id BEFORE the repo check: the id is what\n // identifies the session to re-attach, so a bad one is reported first\n // (AIP-66 §5) rather than masked by an unrelated repo-source failure.\n let vendorSessionId: string\n try {\n // Accepts the vendor's own spellings (`session_<id>` / `cse_<id>`)\n // and normalizes to the CLI's; anything else (an unlearned ACP uuid)\n // is rejected here rather than handed to the vendor below.\n vendorSessionId = toCliSessionId(params.sessionId)\n } catch {\n throw new Error(\n `claude code cloud: session/load needs the vendor session id, got ` +\n `${JSON.stringify(params.sessionId)} — expected session_<id> or ` +\n `cse_<id> (AIP-66 §5). That id was never learned onto ` +\n \"meta.cloud.sessionId, so there is no vendor session to re-attach \" +\n \"to — and this relay will not start a replacement.\",\n )\n }\n // AIP-66 §3 — refuse BEFORE any vendor side effect: a re-attach runs\n // code from this cwd on the vendor's machine too.\n await this.#validateRepo(params.cwd)\n // Keyed BY THE VENDOR ID: the ACP client registers the loaded session\n // under the id it passed in, so `session/prompt` (and our own\n // `session/update` notifications) address this state by that id.\n const session: CloudSessionState = {\n id: vendorSessionId,\n cwd: params.cwd,\n vendorSessionId,\n vendorUrl: null,\n lastSeq: 0,\n turnBaseline: 0,\n promptInFlight: false,\n }\n this.#sessions.set(vendorSessionId, session)\n // The vendor's history is already there: seed `lastSeq` at the newest\n // existing seq so the first post-attach prompt is ended ONLY by ITS own\n // `result` (AIP-66 §6) — without this, the previous turn's `result`,\n // still in the newest events page, could end the new turn on arrival.\n await this.#seedHistory(session, vendorSessionId)\n // Report the adopted identity (meta-file.ts) — the host re-persists\n // `meta.cloud = { vendor, sessionId, url? }` from it.\n await writeCloudSessionMeta({ vendor: CLOUD_VENDOR_SLUG, sessionId: vendorSessionId })\n // The ACP client keys the loaded session on the id IT sent (the vendor\n // id) — `LoadSessionResponse` carries no id of its own.\n return {}\n }\n\n /** Seed `lastSeq` from the vendor's newest events page. Best effort: a\n * failed seed degrades to (at worst) an early end on an older `result` —\n * it must never turn a re-attach into a failed load, which AIP-66 §5\n * forbids replacing with a fresh start anyway.\n *\n * ONE newest-page GET with no cursor: it returns the newest page (newest\n * first), so its max `sequence_num` is the history high-water. No\n * backward paging is needed — `lastSeq` only has to be high enough that\n * the first post-attach poll projects nothing already in the history. */\n async #seedHistory(session: CloudSessionState, vendorSessionId: string): Promise<void> {\n try {\n session.lastSeq = await this.#highWaterSeq(vendorSessionId)\n } catch (err) {\n process.stderr.write(\n `[claude-code-cloud] session/load: could not seed the vendor's ` +\n `existing event high-water (${err instanceof Error ? err.message : String(err)})\\n`,\n )\n }\n }\n\n /** Max `sequence_num` on the session's newest events page (0 when the\n * page is empty). One newest-page GET, no cursor. */\n async #highWaterSeq(vendorSessionId: string): Promise<number> {\n const res = await this.#api.listEvents(vendorSessionId, {})\n let max = 0\n for (const event of res.data ?? []) {\n const seq = eventSequence(event)\n if (seq !== null && seq > max) max = seq\n }\n return max\n }\n\n /**\n * Read every event newer than `lastSeq`, in ascending seq order, walking\n * the API's cursor BACKWARD as far as needed. The API serves the NEWEST\n * page with no cursor and pages toward OLDER events via `?cursor=<n>`\n * (sessions-api.ts), so catching up across a >1-page gap means following\n * `resume_cursor` and collecting the seqs above `lastSeq` until a page\n * reaches already-projected history. Capped at {@link OBSERVE_PAGES_LIMIT}\n * pages per call.\n */\n async #collectNewEvents(\n vendorSessionId: string,\n lastSeq: number,\n ): Promise<Array<{ seq: number; event: CloudSessionEvent }>> {\n const collected: Array<{ seq: number; event: CloudSessionEvent }> = []\n let cursor: string | undefined\n for (let page = 0; page < OBSERVE_PAGES_LIMIT; page += 1) {\n const res: CloudEventsPage = await this.#api.listEvents(\n vendorSessionId,\n cursor ? { cursor } : {},\n )\n const events = res.data ?? []\n let oldest: number | null = null\n for (const event of events) {\n const seq = eventSequence(event)\n if (seq === null) continue // unorderable — skip\n if (oldest === null || seq < oldest) oldest = seq\n if (seq > lastSeq) collected.push({ seq, event })\n }\n // Stop once this page reaches already-projected history (its oldest\n // seq is at or below lastSeq + 1 — nothing at or below lastSeq is\n // needed), or the vendor offers no further cursor.\n if (events.length === 0 || oldest === null || oldest <= lastSeq + 1) break\n const next = res.resume_cursor ?? res.next_cursor\n if (!next || next === cursor) break\n cursor = next\n }\n collected.sort((a, b) => a.seq - b.seq)\n return collected\n }\n\n async prompt(params: PromptRequest): Promise<PromptResponse> {\n const session = this.#sessions.get(params.sessionId)\n if (!session) throw new Error(`unknown session ${params.sessionId}`)\n if (session.promptInFlight) {\n // session/cancel is unsupported (no vendor interrupt verb), so a\n // second concurrent turn cannot be honoured honestly.\n throw new Error(\n \"claude code cloud: a turn is already in flight — session/cancel is \" +\n \"unsupported (AIP-66 §6)\",\n )\n }\n session.promptInFlight = true\n try {\n const text = promptText(params)\n if (!session.vendorSessionId) {\n const started = await this.#cli.startCloudSession(text, {\n cwd: session.cwd,\n })\n session.vendorSessionId = started.sessionId\n session.vendorUrl = started.url\n // Report the learned §5 identity to the host (meta-file.ts) — the\n // ONLY three fields written are vendor/sessionId/url; the vendor's\n // OAuth credential never enters this file (AIP-66 §8).\n await writeCloudSessionMeta({\n vendor: CLOUD_VENDOR_SLUG,\n sessionId: started.sessionId,\n url: started.url,\n })\n // Surface the session URL (AIP-66 security considerations: the user\n // must be able to inspect what the vendor is running).\n await this.#conn.sessionUpdate({\n sessionId: session.id,\n update: {\n sessionUpdate: \"agent_message_chunk\",\n content: {\n type: \"text\",\n text: `[claude-code-cloud] ${started.title ? `${started.title} — ` : \"\"}${started.url}`,\n },\n },\n })\n // A brand-new session has no prior events: the turn's baseline is 0.\n session.turnBaseline = 0\n } else {\n // Follow-up (or a re-attach via session/load): record the seq\n // high-water BEFORE sending, so only a `result` written after this\n // point can end the turn. Reading it after the send would race the\n // new turn's own events into the baseline and hang the turn.\n session.turnBaseline = await this.#highWaterSeq(session.vendorSessionId)\n await this.#cli.sendPrompt(session.vendorSessionId, text, {\n cwd: session.cwd,\n })\n }\n return await this.#observeTurn(session)\n } finally {\n session.promptInFlight = false\n }\n }\n\n /** Read events until a NEW `result` event ends the turn (AIP-66 §6). */\n async #observeTurn(session: CloudSessionState): Promise<PromptResponse> {\n const vendorId = session.vendorSessionId\n if (!vendorId) throw new Error(\"claude code cloud: no vendor session\")\n let delay = this.#pollInitialMs\n let failures = 0\n for (;;) {\n let fresh: Array<{ seq: number; event: CloudSessionEvent }>\n try {\n // Collect everything newer than lastSeq, ascending — the API pages\n // backward, so #collectNewEvents walks older pages as needed.\n fresh = await this.#collectNewEvents(vendorId, session.lastSeq)\n } catch (err) {\n // A transient read failure (HTTP 5xx, network) says nothing about the\n // turn — retry with the poll backoff, up to MAX_LIST_EVENTS_FAILURES\n // consecutive failures. Non-transient errors and an exhausted budget\n // fail the prompt; only a vendor `result` ever ENDS the turn.\n if (\n !isTransientListEventsError(err) ||\n failures + 1 >= MAX_LIST_EVENTS_FAILURES\n ) {\n throw err\n }\n failures += 1\n await this.#sleep(delay)\n delay = Math.min(delay * 2, this.#pollMaxMs)\n continue\n }\n failures = 0\n let stopReason: StopReason | null = null\n for (const { seq, event } of fresh) {\n session.lastSeq = Math.max(session.lastSeq, seq)\n if (event.event_type === \"result\") {\n if (resultStopReason(event.payload) === \"refusal\") {\n const errText = errorResultText(event.payload)\n if (errText) {\n await this.#send(session.id, {\n sessionUpdate: \"agent_message_chunk\",\n content: { type: \"text\", text: errText },\n })\n }\n }\n for (const update of resultEventUpdates(event.payload)) {\n await this.#send(session.id, update)\n }\n // Only a result written AFTER this turn's prompt ends it: an old\n // result at or below the baseline is ignored (AIP-66 §6).\n if (seq > session.turnBaseline) {\n stopReason = resultStopReason(event.payload)\n }\n } else if (event.event_type === \"user\") {\n // Follow-up turns: the vendor echoes the user's own prompt back as\n // a `user` event — the host already rendered that prompt, so it is\n // NEVER replayed as a chunk. Only `tool_result` blocks project\n // (tool_call_update); every other user payload is dropped here.\n for (const update of sdkMessageToUpdates(\n event.payload as unknown as SDKMessage,\n )) {\n if (update.sessionUpdate === \"agent_message_chunk\") continue\n await this.#send(session.id, update)\n }\n } else if (event.event_type === \"assistant\") {\n // Payloads ARE stream-json SDK messages — reuse the claude-sdk\n // adapter's mappers (assistant text → agent_message_chunk,\n // tool_use → tool_call).\n for (const update of sdkMessageToUpdates(\n event.payload as unknown as SDKMessage,\n )) {\n await this.#send(session.id, update)\n }\n }\n // system / env_manager_log / rate_limit_event / … carry no ACP\n // projection; advancing lastSeq past them still marks them seen.\n }\n if (stopReason) return { stopReason }\n await this.#sleep(delay)\n delay = Math.min(delay * 2, this.#pollMaxMs)\n }\n }\n\n async #send(sessionId: string, update: SessionUpdate): Promise<void> {\n await this.#conn.sessionUpdate({ sessionId, update } as SessionNotification)\n }\n\n /** Unsupported: the vendor exposes no interrupt verb (AIP-66 §6). Throwing\n * reports it — the in-flight poll loop is NOT aborted (we cannot stop the\n * cloud turn; lying \"cancelled\" would violate §6's end-on-vendor-event\n * rule). */\n async cancel(_params: CancelNotification): Promise<void> {\n throw new Error(\n \"claude code cloud: session/cancel is unsupported — the vendor \" +\n \"exposes no interrupt verb for cloud sessions (AIP-66 §6)\",\n )\n }\n\n /** No runtime-configurable options (no model menu — the vendor picks the\n * model). Empty set so a host that tries to set one doesn't error. */\n async setSessionConfigOption(\n _params: SetSessionConfigOptionRequest,\n ): Promise<SetSessionConfigOptionResponse> {\n return { configOptions: [] }\n }\n\n /** No agent-specific modes; accept and ignore. */\n async setSessionMode(\n _params: SetSessionModeRequest,\n ): Promise<SetSessionModeResponse> {\n return {}\n }\n}\n\n/** Boot the ACP server over stdio — what bin/claude-code-cloud-acp.mjs runs. */\nexport function runAcpOverStdio(deps: ClaudeCloudAcpDeps = {}): AgentSideConnection {\n const toClient = Writable.toWeb(process.stdout) as WritableStream<Uint8Array>\n const fromClient = Readable.toWeb(\n process.stdin,\n ) as unknown as ReadableStream<Uint8Array>\n const stream = ndJsonStream(toClient, fromClient)\n return new AgentSideConnection(\n conn => new ClaudeCloudAcpAgent(conn, deps),\n stream,\n )\n}\n\n/** Entry point for bin/claude-code-cloud-acp.mjs. */\nexport function main(): void {\n runAcpOverStdio()\n}\n"]}
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { AgentCliHandle, AgentCliRuntime } from '@agentproto/driver-agent-cli';
2
2
  export { AgentCliHandle, AgentCliRuntime } from '@agentproto/driver-agent-cli';
3
- import { Agent, AgentSideConnection, InitializeRequest, InitializeResponse, NewSessionRequest, NewSessionResponse, PromptRequest, PromptResponse, CancelNotification, SetSessionConfigOptionRequest, SetSessionConfigOptionResponse, SetSessionModeRequest, SetSessionModeResponse, SessionUpdate, StopReason } from '@agentclientprotocol/sdk';
3
+ import { Agent, AgentSideConnection, InitializeRequest, InitializeResponse, NewSessionRequest, NewSessionResponse, LoadSessionRequest, LoadSessionResponse, PromptRequest, PromptResponse, CancelNotification, SetSessionConfigOptionRequest, SetSessionConfigOptionResponse, SetSessionModeRequest, SetSessionModeResponse, SessionUpdate, StopReason } from '@agentclientprotocol/sdk';
4
4
 
5
5
  /**
6
6
  * The vendor-client surface (AIP-66 Appendix A): start a Claude Code cloud
@@ -22,6 +22,22 @@ import { Agent, AgentSideConnection, InitializeRequest, InitializeResponse, NewS
22
22
  declare const CLAUDE_CODE_GATEWAY_ENV_UNSET: readonly string[];
23
23
  /** Copy `base` with every {@link CLAUDE_CODE_GATEWAY_ENV_UNSET} key deleted. */
24
24
  declare function cloudChildEnv(base?: Record<string, string | undefined>): Record<string, string>;
25
+ /**
26
+ * The one normalization every regex over live PTY output must run on. The
27
+ * claude TUI draws text word-by-word, positioning each run with a
28
+ * cursor-column escape (`\x1b[12Gworkspace:`) instead of a space, so a raw
29
+ * `Yes, I trust this folder` never appears literally and the old matcher
30
+ * stalled until timeout. Here each escape sequence becomes one space, runs of
31
+ * horizontal whitespace collapse to one space, and runs of blank lines
32
+ * collapse to one newline — line boundaries are preserved so the
33
+ * line-oriented `Created cloud session` / `--teleport` regexes below keep
34
+ * working. Pure and exported so tests can target it directly and so no future
35
+ * matcher can reintroduce the same class of bug.
36
+ */
37
+ declare function normalizePtyOutput(raw: string): string;
38
+ /** ANSI-stripped tail (last ~300 chars) of raw PTY output, for diagnosing a
39
+ * PTY stall from the thrown error alone. */
40
+ declare function ptyOutputTail(raw: string, maxChars?: number): string;
25
41
  interface RunResult {
26
42
  code: number;
27
43
  stdout: string;
@@ -50,9 +66,57 @@ interface CloudCliRunner {
50
66
  run(cmd: string, args: string[], opts: RunOpts): Promise<RunResult>;
51
67
  runPty(cmd: string, args: string[], opts: PtyRunOpts): PtyHandle;
52
68
  }
69
+ /** Options handed to a {@link PtySpawn} call (the node-pty fork options this
70
+ * adapter actually sets). */
71
+ interface PtySpawnOptions {
72
+ name: string;
73
+ cols: number;
74
+ rows: number;
75
+ cwd: string;
76
+ env: Record<string, string>;
77
+ }
78
+ /** The subset of node-pty's `IPty` surface this adapter drives. Structural, so
79
+ * the real `IPty` satisfies it and a test can stand in a fake PTY. */
80
+ interface PtyProcess {
81
+ onData(cb: (chunk: string) => void): void;
82
+ onExit(cb: (event: {
83
+ exitCode: number;
84
+ }) => void): void;
85
+ write(data: string): void;
86
+ kill(signal?: string): void;
87
+ }
88
+ /** Spawns a PTY. Production is node-pty's `spawn`; tests inject a fake. */
89
+ type PtySpawn = (cmd: string, args: string[], opts: PtySpawnOptions) => PtyProcess;
90
+ interface CloudCliRunnerDeps {
91
+ /** Test seam: override node-pty's `spawn` so the PTY paths can be driven
92
+ * from fixtures without a real claude CLI or a native PTY. Production
93
+ * leaves it unset and node-pty is lazily imported. */
94
+ spawnPty?: PtySpawn;
95
+ }
53
96
  /** Real runner: child_process for headless calls, node-pty (optional dep)
54
97
  * for the TTY-required `claude --cloud` start. */
55
- declare function defaultCloudCliRunner(): CloudCliRunner;
98
+ declare function defaultCloudCliRunner(deps?: CloudCliRunnerDeps): CloudCliRunner;
99
+ interface RefreshLoginOpts {
100
+ runner?: CloudCliRunner;
101
+ env?: Record<string, string | undefined>;
102
+ /** Default os.tmpdir(): the refresh must not depend on any repo checkout. */
103
+ cwd?: string;
104
+ /** Default 60s. */
105
+ timeoutMs?: number;
106
+ }
107
+ /**
108
+ * Build the injectable login-refresh trigger. Running a trivial headless
109
+ * prompt (`claude -p "Reply OK" --model haiku`) is what makes the claude CLI
110
+ * re-mint and re-write the OAuth access token to the keychain (verified
111
+ * live: `claude auth status` does NOT refresh it). stdin is detached, the
112
+ * child runs from {@link os.tmpdir} with the same scrubbed env every other
113
+ * claude child gets, and its stdout/stderr are never read or logged — they
114
+ * can carry token-adjacent material and must not leak.
115
+ *
116
+ * Concurrent callers share one in-flight refresh (a single promise), so a
117
+ * burst of requests around expiry runs the CLI at most once.
118
+ */
119
+ declare function createRefreshLogin(opts?: RefreshLoginOpts): () => Promise<void>;
56
120
  interface AuthStatus {
57
121
  loggedIn: boolean;
58
122
  authMethod?: string;
@@ -121,25 +185,36 @@ declare function sendPrompt(sessionId: string, text: string, opts: SendPromptOpt
121
185
  * The credential is the user's claude.ai login, owned by the claude CLI
122
186
  * (AIP-66 §8): this module never logs it, never persists it, and never
123
187
  * writes it anywhere — it lives only in request headers for the lifetime
124
- * of a call. On 401 the credential source is re-read exactly once (the
125
- * token may have been refreshed since process start), then the call fails
126
- * with a message that tells the user how to log in.
188
+ * of a call. Before a request, an expired token (or one expiring within
189
+ * {@link EXPIRY_SKEW_MS}) triggers the injected login refresh, then the
190
+ * source cache is invalidated and re-read. On 401 the same refresh +
191
+ * invalidate + re-read happens once, then the call fails with a message
192
+ * that tells the user how to log in.
127
193
  *
128
194
  * All network access goes through an injectable `fetch` so tests can drive
129
195
  * the client from fixtures — no live Anthropic call is ever made from here.
130
196
  */
131
197
  /** A claude.ai OAuth credential. `accessToken` is the bearer the API wants;
132
198
  * `orgUuid` is the `x-organization-uuid` header (from `~/.claude.json`'s
133
- * `.oauthAccount.organizationUuid`). NEVER logged or persisted. */
199
+ * `.oauthAccount.organizationUuid`). `expiresAt` is the token's expiry in
200
+ * epoch milliseconds (the keychain's `.claudeAiOauth.expiresAt`), when the
201
+ * source knows it. NEVER logged or persisted. */
134
202
  interface CloudCredential {
135
203
  accessToken: string;
136
204
  orgUuid?: string;
205
+ expiresAt?: number;
137
206
  }
207
+ /** A token expiring within this window is treated as expired: refresh it
208
+ * before sending rather than racing a request against the expiry. */
209
+ declare const EXPIRY_SKEW_MS: number;
138
210
  /** Where the host reads the vendor login from (AIP-66 §8). Implementations
139
- * must not cache a token across an explicit invalidate() — a 401 re-read
140
- * has to be able to observe a refreshed login. */
211
+ * must not cache a token across an explicit {@link CredentialSource.invalidate}
212
+ * — a refresh or a 401 re-read has to be able to observe a fresh login. */
141
213
  interface CredentialSource {
142
214
  get(): Promise<CloudCredential>;
215
+ /** Drop any cached credential so the next {@link get} re-reads the
216
+ * underlying store (the keychain may have been refreshed out-of-band). */
217
+ invalidate(): void;
143
218
  }
144
219
  /** macOS keychain credential: `security find-generic-password -s "Claude
145
220
  * Code-credentials" -w` returns JSON whose `.claudeAiOauth.accessToken` is
@@ -163,12 +238,21 @@ interface CloudSessionEvent {
163
238
  created_at: string;
164
239
  event_id: string;
165
240
  event_type: string;
241
+ /** A STRING of an integer, strictly increasing within the session. The
242
+ * ordering key: parse with `Number()` (see {@link eventSequence}). */
243
+ sequence_num: string;
244
+ /** Who produced the event — "worker" (the vendor's harness) or "client". */
245
+ source?: string;
166
246
  payload: unknown;
167
247
  }
168
248
  interface CloudEventsPage {
169
249
  data: CloudSessionEvent[];
170
- /** Pass back as `cursor` on the next poll to resume after this page. */
250
+ /** The `sequence_num` of the OLDEST event on the page, present on the
251
+ * first (newest) page. Pass back as `?cursor=<n>` to fetch the NEXT
252
+ * OLDER page — the cursor pages BACKWARD in time, never forward. */
171
253
  resume_cursor?: string;
254
+ /** Alias for {@link resume_cursor}, seen on the first page only. */
255
+ next_cursor?: string;
172
256
  }
173
257
  /** GET /v1/code/sessions/{id} — wrapped in `response_shape`. */
174
258
  interface CloudSessionState {
@@ -217,21 +301,29 @@ declare function normalizeSessionId(id: string): string;
217
301
  * `--teleport`). Same acceptance set as {@link normalizeSessionId}. */
218
302
  declare function toCliSessionId(id: string): string;
219
303
  interface SessionsApiOptions {
220
- /** Credential source; re-read once on a 401, then the call fails. */
304
+ /** Credential source; invalidated + re-read when the token is expiring or
305
+ * a request comes back 401, then the call fails. */
221
306
  credentials: CredentialSource;
307
+ /** Refresh the vendor login before re-reading an expired credential and on
308
+ * a 401 (e.g. cli.ts's refreshLogin). Omit to skip refreshing. */
309
+ refreshLogin?: () => Promise<void>;
222
310
  /** Injectable fetch — tests pass a fixture router; default is globalThis.fetch. */
223
311
  fetchImpl?: typeof fetch;
224
312
  /** Override for proxies/mirrors; default https://api.anthropic.com. */
225
313
  baseUrl?: string;
226
314
  }
315
+ /** True when the token is already expired or expires within the skew window
316
+ * (or when the source reports no expiry, in which case we cannot know). */
317
+ declare function isCredentialExpiring(credential: CloudCredential, now?: number): boolean;
227
318
  declare class SessionsApi {
228
319
  #private;
229
320
  constructor(options: SessionsApiOptions);
230
321
  /** GET /v1/code/sessions/{id} */
231
322
  getSession(id: string): Promise<CloudGetSessionResponse>;
232
323
  /**
233
- * GET /v1/code/sessions/{id}/events — newest first. Pass the previous
234
- * page's `resume_cursor` as `cursor` to resume after it.
324
+ * GET /v1/code/sessions/{id}/events — newest first. With no `cursor` this
325
+ * returns the NEWEST page; pass the page's `resume_cursor` (the oldest
326
+ * event's `sequence_num`) as `cursor` to fetch the next OLDER page.
235
327
  */
236
328
  listEvents(id: string, opts?: {
237
329
  cursor?: string;
@@ -253,6 +345,13 @@ declare class SessionsApi {
253
345
  * (AIP-66 §3) BEFORE any vendor side effect.
254
346
  * - first `session/prompt` → `claude --cloud "<prompt>"` (start), later
255
347
  * ones → `claude -p … --cloud <id>` (send-only).
348
+ * - `session/load` RE-ATTACHES to the vendor session id the host
349
+ * persisted on `meta.cloud.sessionId` (AIP-66 §5): the adopted id makes
350
+ * the next prompt a `sendPrompt` — the relay never starts a replacement
351
+ * vendor session.
352
+ * - the learned identity (`{ vendor, sessionId, url }`) is reported to
353
+ * the host through the meta file named by `AGENTPROTO_CLOUD_SESSION_META_FILE`
354
+ * (meta-file.ts) — never a credential (AIP-66 §8).
256
355
  * - the turn is then observed via the sessions API: events are mapped
257
356
  * with @agentproto/adapter-claude-sdk's stream-json → ACP mappers
258
357
  * (the payloads ARE Claude Code stream-json SDK messages — reused, not
@@ -313,6 +412,20 @@ declare class ClaudeCloudAcpAgent implements Agent {
313
412
  initialize(_params: InitializeRequest): Promise<InitializeResponse>;
314
413
  authenticate(): Promise<void>;
315
414
  newSession(params: NewSessionRequest): Promise<NewSessionResponse>;
415
+ /**
416
+ * AIP-66 §5 re-attach: ADOPT the vendor session id the host persisted on
417
+ * `meta.cloud.sessionId` as this ACP session's vendor session. No vendor
418
+ * side effect happens here — the next `session/prompt` goes through
419
+ * `sendPrompt` (`claude -p … --cloud <id>`), never `startCloudSession`,
420
+ * so a resumed relay can never replace the vendor's session with a new
421
+ * one. The adopted id is also reported back to the host's meta file so a
422
+ * re-attach against a fresh config dir still carries the §5 mapping.
423
+ *
424
+ * Fails closed on an id the vendor could never own (e.g. the ACP uuid of
425
+ * a spawn whose vendor id was never learned): no session is started in
426
+ * its place.
427
+ */
428
+ loadSession(params: LoadSessionRequest): Promise<LoadSessionResponse>;
316
429
  prompt(params: PromptRequest): Promise<PromptResponse>;
317
430
  /** Unsupported: the vendor exposes no interrupt verb (AIP-66 §6). Throwing
318
431
  * reports it — the in-flight poll loop is NOT aborted (we cannot stop the
@@ -328,6 +441,55 @@ declare class ClaudeCloudAcpAgent implements Agent {
328
441
  /** Boot the ACP server over stdio — what bin/claude-code-cloud-acp.mjs runs. */
329
442
  declare function runAcpOverStdio(deps?: ClaudeCloudAcpDeps): AgentSideConnection;
330
443
 
444
+ /**
445
+ * AIP-66 §5/§8 — how this relay REPORTS the learned vendor session
446
+ * identity to the host.
447
+ *
448
+ * The host (the runtime's `session-spawn.ts` + `cloud-vendors.ts`) hands
449
+ * the relay the path of a file inside the session's isolated config dir via
450
+ * `AGENTPROTO_CLOUD_SESSION_META_FILE`. Once the vendor has returned a
451
+ * session id — after `claude --cloud` prints it, or when `session/load`
452
+ * adopts the id persisted on `meta.cloud.sessionId` — the relay writes
453
+ * exactly the three §5 fields `{ vendor, sessionId, url }` there, and the
454
+ * host polls that file (`watchCloudSessionMeta`) to stamp
455
+ * `meta.cloud = { vendor, sessionId, url }` onto the descriptor.
456
+ *
457
+ * ONLY those three fields are ever written: the vendor's OAuth credential
458
+ * never enters this file, logs or events (AIP-66 §8). The write is
459
+ * best-effort and atomic (temp file + rename), so a failed side-file write
460
+ * can never sink the turn that learned the id — the host's poll simply
461
+ * keeps watching.
462
+ */
463
+ /** Env var carrying the absolute path of the meta file. Mirrors the
464
+ * runtime's `CLOUD_SESSION_META_FILE_ENV` (cloud-vendors.ts) — the two
465
+ * must stay byte-identical or the relay writes where nobody reads. */
466
+ declare const CLOUD_SESSION_META_FILE_ENV = "AGENTPROTO_CLOUD_SESSION_META_FILE";
467
+ /** The vendor slug this adapter relays to (AIP-66 §2 `CloudVendor.slug`,
468
+ * registry entry `anthropic` → adapter `claude-code-cloud`). */
469
+ declare const CLOUD_VENDOR_SLUG = "anthropic";
470
+ /** The §5 mapping the relay reports. NEVER carries a credential. */
471
+ interface CloudSessionMetaReport {
472
+ vendor: string;
473
+ /** Vendor session id — CLI spelling (`session_<id>`). */
474
+ sessionId: string;
475
+ /** Session URL when known (the start path prints it; a re-attach may
476
+ * inherit it from the file already on disk). */
477
+ url?: string;
478
+ }
479
+ /**
480
+ * Write `{ vendor, sessionId, url }` to the meta file the host named in
481
+ * `AGENTPROTO_CLOUD_SESSION_META_FILE`. Returns the path written, or null
482
+ * when the env var is unset or the write failed (best-effort: the host's
483
+ * poll retries, and a cloud turn must never fail over a side file).
484
+ *
485
+ * A re-attach (`session/load`) carries no URL — when the id on disk matches
486
+ * the one being reported, the existing `url` is preserved so the host's
487
+ * later read keeps the full §5 mapping.
488
+ */
489
+ declare function writeCloudSessionMeta(meta: CloudSessionMetaReport, opts?: {
490
+ env?: Record<string, string | undefined>;
491
+ }): Promise<string | null>;
492
+
331
493
  /**
332
494
  * AIP-66 §3 (repo source): a managed cloud agent runs on a git remote and
333
495
  * ref — never on an uploaded working tree. The host MUST refuse the spawn
@@ -371,4 +533,4 @@ declare const CLOUD_REFUSED_SPAWN_FIELDS: readonly ["sandbox", "worktree", "comm
371
533
  declare const claudeCodeCloud: AgentCliHandle;
372
534
  declare function claudeCodeCloudRuntime(): AgentCliRuntime;
373
535
 
374
- export { type AuthStatus, CLAUDE_CODE_GATEWAY_ENV_UNSET, CLOUD_REFUSED_SPAWN_FIELDS, ClaudeCloudAcpAgent, type ClaudeCloudAcpDeps, type CloudCliDeps, type CloudCliRunner, type CloudCredential, type CloudEventsClient, type CloudEventsPage, type CloudGetSessionResponse, type CloudSessionEvent, type CloudSessionState, type CloudSessionSummary, type CredentialSource, type GitRunner, POLL_INITIAL_MS, POLL_MAX_MS, type RunOpts, type RunResult, SessionsApi, type SessionsApiOptions, type StartedCloudSession, claudeCodeCloud, claudeCodeCloudRuntime, cloudChildEnv, defaultCloudCliRunner, defaultGitRunner, envCredentialSource, keychainCredentialSource, normalizeSessionId, parseAuthStatus, parseCloudStartOutput, preflightAuth, resultEventUpdates, resultStopReason, runAcpOverStdio, sendPrompt, startCloudSession, toCliSessionId, validateRepoSource };
536
+ export { type AuthStatus, CLAUDE_CODE_GATEWAY_ENV_UNSET, CLOUD_REFUSED_SPAWN_FIELDS, CLOUD_SESSION_META_FILE_ENV, CLOUD_VENDOR_SLUG, ClaudeCloudAcpAgent, type ClaudeCloudAcpDeps, type CloudCliDeps, type CloudCliRunner, type CloudCliRunnerDeps, type CloudCredential, type CloudEventsClient, type CloudEventsPage, type CloudGetSessionResponse, type CloudSessionEvent, type CloudSessionMetaReport, type CloudSessionState, type CloudSessionSummary, type CredentialSource, EXPIRY_SKEW_MS, type GitRunner, POLL_INITIAL_MS, POLL_MAX_MS, type PtyProcess, type PtySpawn, type PtySpawnOptions, type RefreshLoginOpts, type RunOpts, type RunResult, SessionsApi, type SessionsApiOptions, type StartedCloudSession, claudeCodeCloud, claudeCodeCloudRuntime, cloudChildEnv, createRefreshLogin, defaultCloudCliRunner, defaultGitRunner, envCredentialSource, isCredentialExpiring, keychainCredentialSource, normalizePtyOutput, normalizeSessionId, parseAuthStatus, parseCloudStartOutput, preflightAuth, ptyOutputTail, resultEventUpdates, resultStopReason, runAcpOverStdio, sendPrompt, startCloudSession, toCliSessionId, validateRepoSource, writeCloudSessionMeta };
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- export { CLAUDE_CODE_GATEWAY_ENV_UNSET, ClaudeCloudAcpAgent, POLL_INITIAL_MS, POLL_MAX_MS, SessionsApi, cloudChildEnv, defaultCloudCliRunner, defaultGitRunner, envCredentialSource, keychainCredentialSource, normalizeSessionId, parseAuthStatus, parseCloudStartOutput, preflightAuth, resultEventUpdates, resultStopReason, runAcpOverStdio, sendPrompt, startCloudSession, toCliSessionId, validateRepoSource } from './chunk-KA4G4O2X.mjs';
1
+ export { CLAUDE_CODE_GATEWAY_ENV_UNSET, CLOUD_SESSION_META_FILE_ENV, CLOUD_VENDOR_SLUG, ClaudeCloudAcpAgent, EXPIRY_SKEW_MS, POLL_INITIAL_MS, POLL_MAX_MS, SessionsApi, cloudChildEnv, createRefreshLogin, defaultCloudCliRunner, defaultGitRunner, envCredentialSource, isCredentialExpiring, keychainCredentialSource, normalizePtyOutput, normalizeSessionId, parseAuthStatus, parseCloudStartOutput, preflightAuth, ptyOutputTail, resultEventUpdates, resultStopReason, runAcpOverStdio, sendPrompt, startCloudSession, toCliSessionId, validateRepoSource, writeCloudSessionMeta } from './chunk-LN5RJ5ZT.mjs';
2
2
  import { fileURLToPath } from 'url';
3
3
  import { defineAgentCli, createAgentCliRuntime } from '@agentproto/driver-agent-cli';
4
4
 
@@ -78,8 +78,9 @@ var claudeCodeCloud = defineAgentCli({
78
78
  sub_agents: false,
79
79
  file_io: true,
80
80
  multimodal: false,
81
- // Re-attach is via the persisted vendor session id (AIP-66 §5), not an
82
- // ACP session/load replay.
81
+ // Re-attach is via the persisted vendor session id (AIP-66 §5): the
82
+ // host hands it back as ACP `session/load`, which ADOPTS it — the next
83
+ // prompt is a send to that same vendor session, never a new start.
83
84
  resumable: true,
84
85
  // Send-only prompting: the CLI never returns the reply on the prompt
85
86
  // path; the reply is observed via the sessions API.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;AA4BA,IAAM,MAAA,GAAS,aAAA;AAAA,EACb,IAAI,GAAA,CAAI,kCAAA,EAAoC,MAAA,CAAA,IAAA,CAAY,GAAG;AAC7D,CAAA;AAMO,IAAM,0BAAA,GAA6B;AAAA,EACxC,SAAA;AAAA,EACA,UAAA;AAAA,EACA,gBAAA;AAAA,EACA,YAAA;AAAA,EACA,aAAA;AAAA,EACA,SAAA;AAAA,EACA,SAAA;AAAA,EACA,UAAA;AAAA,EACA;AACF;AAEO,IAAM,kBAAkC,cAAA,CAAe;AAAA,EAC5D,IAAA,EAAM,mBAAA;AAAA,EACN,EAAA,EAAI,mBAAA;AAAA,EACJ,WAAA,EACE,ohBAAA;AAAA,EAQF,OAAA,EAAS,OAAA;AAAA,EACT,GAAA,EAAK,MAAA;AAAA,EACL,QAAA,EAAU,CAAC,MAAM,CAAA;AAAA,EACjB,OAAA,EAAS;AAAA,IACP;AAAA,MACE,MAAA,EAAQ,KAAA;AAAA,MACR,OAAA,EAAS,uCAAA;AAAA,MACT,MAAA,EAAQ;AAAA;AACV,GACF;AAAA;AAAA;AAAA;AAAA,EAIA,aAAA,EAAe;AAAA,IACb,GAAA,EAAK,kBAAA;AAAA,IACL,KAAA,EAAO,sBAAA;AAAA,IACP,KAAA,EAAO,WAAA;AAAA,IACP,UAAA,EAAY;AAAA,GACd;AAAA;AAAA;AAAA;AAAA;AAAA,EAKA,IAAA,EAAM;AAAA,IACJ,GAAA,EAAK,wBAAA;AAAA,IACL,KAAA,EAAO;AAAA,MACL,GAAA,EAAK,mBAAA;AAAA,MACL,WAAA,EAAa;AAAA;AACf,GACF;AAAA;AAAA,EAEA,OAAA,EACE,kLAAA;AAAA,EAGF,QAAA,EAAU,KAAA;AAAA,EACV,GAAA,EAAK,wBAAA;AAAA,EACL,OAAA,EAAS;AAAA;AAAA;AAAA,IAGP,IAAA,EAAM,YAAA;AAAA,IACN,eAAA,EAAiB,IAAA;AAAA,IACjB,iBAAA,EAAmB;AAAA,GACrB;AAAA;AAAA;AAAA;AAAA;AAAA,EAKA,YAAA,EAAc;AAAA;AAAA,IAEZ,SAAA,EAAW,IAAA;AAAA;AAAA;AAAA,IAGX,UAAA,EAAY,IAAA;AAAA,IACZ,UAAA,EAAY,KAAA;AAAA,IACZ,OAAA,EAAS,IAAA;AAAA,IACT,UAAA,EAAY,KAAA;AAAA;AAAA;AAAA,IAGZ,SAAA,EAAW,IAAA;AAAA;AAAA;AAAA,IAGX,aAAA,EAAe;AAAA,GACjB;AAAA,EACA,IAAA,EAAM;AAAA,IACJ,aAAA;AAAA,IACA,WAAA;AAAA,IACA,OAAA;AAAA,IACA,QAAA;AAAA,IACA,KAAA;AAAA,IACA,eAAA;AAAA,IACA;AAAA,GACF;AAAA,EACA,QAAA,EAAU;AAAA,IACR,GAAA,EAAK,EAAA;AAAA;AAAA,IAEL,OAAA,EAAS,aAAA;AAAA,IACT,KAAA,EAAO;AAAA,MACL,MAAA,EAAQ;AAAA,KACV;AAAA;AAAA,IAEA,kBAAA,EAAoB,CAAC,GAAG,0BAA0B;AAAA;AAEtD,CAAC;AAEM,SAAS,sBAAA,GAA0C;AACxD,EAAA,OAAO,sBAAsB,eAAe,CAAA;AAC9C","file":"index.mjs","sourcesContent":["/**\n * @agentproto/adapter-claude-code-cloud — AIP-66 managed cloud agent adapter\n * for Anthropic Claude Code cloud sessions.\n *\n * Unlike `@agentproto/adapter-claude-code` (local harness, host machine),\n * this adapter relays a session the VENDOR hosts end to end: the vendor\n * boots the machine, runs Claude Code in it, and exposes the session\n * through `claude --cloud` / `claude -p --cloud` plus the undocumented\n * Claude Code sessions API. No agentproto daemon runs inside; the host\n * controls neither the machine nor the harness — so this manifest is\n * deliberately smaller and refuses the spawn fields that could never take\n * effect (AIP-66 §4).\n *\n * import { claudeCodeCloud } from \"@agentproto/adapter-claude-code-cloud\"\n */\n\nimport { fileURLToPath } from \"node:url\"\nimport {\n createAgentCliRuntime,\n defineAgentCli,\n type AgentCliHandle,\n type AgentCliRuntime,\n} from \"@agentproto/driver-agent-cli\"\n\n// Self-locating: the built handle spawns `node <this-pkg>/bin/…\n// claude-code-cloud-acp.mjs`. From dist/index.mjs the bin sits one level up,\n// so the same build works whether the daemon resolves this package from\n// node_modules or a user runs the published bin directly.\nconst acpBin = fileURLToPath(\n new URL(\"../bin/claude-code-cloud-acp.mjs\", import.meta.url),\n)\n\n// AIP-66 §4 refused spawn fields — no meaning for a vendor-owned harness, so\n// the host MUST refuse a cloud spawn that sets any of them rather than\n// ignore them. Documented here (and in CLAUDE-CODE-CLOUD.md) so the runtime\n// gate and users share one list.\nexport const CLOUD_REFUSED_SPAWN_FIELDS = [\n \"sandbox\",\n \"worktree\",\n \"commandSandbox\",\n \"mcpServers\",\n \"daemonMount\",\n \"bundles\",\n \"browser\",\n \"appServe\",\n \"inference\",\n] as const\n\nexport const claudeCodeCloud: AgentCliHandle = defineAgentCli({\n name: \"claude-code-cloud\",\n id: \"claude-code-cloud\",\n description:\n \"AIP-66 managed cloud agent adapter for Anthropic Claude Code cloud \" +\n \"sessions. The vendor owns the machine and the harness: starts via \" +\n \"`claude --cloud` (TTY), prompts via `claude -p --cloud <id>`, observes \" +\n \"via the Claude Code sessions API, projected onto stdio ACP. Refuses \" +\n \"the AIP-66 §4 spawn fields (sandbox, worktree, commandSandbox, \" +\n \"mcpServers, daemonMount, bundles, browser, appServe, inference) — the \" +\n \"vendor can never apply them. Requires a claude.ai sign-in (API-key \" +\n \"auth is refused) and a clean, pushed git checkout.\",\n version: \"0.1.0\",\n bin: \"node\",\n bin_args: [acpBin],\n install: [\n {\n method: \"npm\",\n package: \"@agentproto/adapter-claude-code-cloud\",\n global: true,\n },\n ],\n // Presence probe against the vendor client this adapter relays to — the\n // pinned floor is the oldest CLI observed to support `--cloud` / the\n // sessions API (AIP-66 Appendix A: 2.1.296–2.1.299).\n version_check: {\n cmd: \"claude --version\",\n parse: \"(\\\\d+\\\\.\\\\d+\\\\.\\\\d+)\",\n range: \">=2.1.296\",\n timeout_ms: 15_000,\n },\n // Auth is the user's OWN claude.ai login inside the claude CLI (keychain\n // on macOS) — never an injected env credential (AIP-66 §8). No `state.env`\n // because an API-key env would be scrubbed, not consumed; the preflight\n // refuses an api_key-authenticated CLI outright.\n auth: {\n ref: \"./CLAUDE-CODE-CLOUD.md\",\n login: {\n cmd: \"claude auth login\",\n interactive: true,\n },\n },\n // The machine is the vendor's; there is no host-side sandbox to describe.\n sandbox:\n \"Managed cloud (AIP-66): the vendor boots the machine and runs Claude \" +\n \"Code on it. No agentproto daemon runs inside; the session URL is \" +\n \"surfaced so the user can inspect what ran.\",\n protocol: \"acp\",\n acp: \"./CLAUDE-CODE-CLOUD.md\",\n session: {\n // One agentproto session = one vendor cloud session (AIP-66 §5);\n // follow-up turns send to the same vendor session.\n mode: \"persistent\",\n idle_timeout_ms: 1_800_000,\n context_carryover: true,\n },\n // NO `models` menu: the vendor picks and bills the model inside its own\n // harness; the host has no model to select or route (AIP-66 §4 — `model`\n // is only meaningful when the vendor client accepts it, and this CLI's\n // cloud path exposes no model flag).\n capabilities: {\n // Turns stream back as ACP updates while the vendor runs them.\n streaming: true,\n // The vendor harness's own tools (Read/Edit/Bash/…) surface as ACP\n // tool_call / tool_call_update updates from the session's events.\n tool_calls: true,\n sub_agents: false,\n file_io: true,\n multimodal: false,\n // Re-attach is via the persisted vendor session id (AIP-66 §5), not an\n // ACP session/load replay.\n resumable: true,\n // Send-only prompting: the CLI never returns the reply on the prompt\n // path; the reply is observed via the sessions API.\n bidirectional: false,\n },\n tags: [\n \"claude-code\",\n \"anthropic\",\n \"cloud\",\n \"aip-66\",\n \"acp\",\n \"agent-runtime\",\n \"coding\",\n ],\n metadata: {\n aip: 66,\n // The harness the vendor runs (AIP-66 §2 CloudVendor.harnesses).\n harness: \"claude-code\",\n cloud: {\n vendor: \"anthropic\",\n },\n // AIP-66 §4 refused spawn fields, machine-readable for the host gate.\n refusedSpawnFields: [...CLOUD_REFUSED_SPAWN_FIELDS],\n },\n})\n\nexport function claudeCodeCloudRuntime(): AgentCliRuntime {\n return createAgentCliRuntime(claudeCodeCloud)\n}\n\nexport {\n ClaudeCloudAcpAgent,\n runAcpOverStdio,\n resultEventUpdates,\n resultStopReason,\n POLL_INITIAL_MS,\n POLL_MAX_MS,\n type ClaudeCloudAcpDeps,\n type CloudCliDeps,\n type CloudEventsClient,\n} from \"./acp-server.js\"\nexport {\n cloudChildEnv,\n defaultCloudCliRunner,\n parseAuthStatus,\n parseCloudStartOutput,\n preflightAuth,\n sendPrompt,\n startCloudSession,\n CLAUDE_CODE_GATEWAY_ENV_UNSET,\n type AuthStatus,\n type CloudCliRunner,\n type RunOpts,\n type RunResult,\n type StartedCloudSession,\n} from \"./cli.js\"\nexport {\n SessionsApi,\n envCredentialSource,\n keychainCredentialSource,\n normalizeSessionId,\n toCliSessionId,\n type CloudCredential,\n type CloudEventsPage,\n type CloudGetSessionResponse,\n type CloudSessionEvent,\n type CloudSessionState,\n type CloudSessionSummary,\n type CredentialSource,\n type SessionsApiOptions,\n} from \"./sessions-api.js\"\nexport {\n validateRepoSource,\n defaultGitRunner,\n type GitRunner,\n} from \"./repo-source.js\"\nexport type { AgentCliHandle, AgentCliRuntime }\n"]}
1
+ {"version":3,"sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;AA4BA,IAAM,MAAA,GAAS,aAAA;AAAA,EACb,IAAI,GAAA,CAAI,kCAAA,EAAoC,MAAA,CAAA,IAAA,CAAY,GAAG;AAC7D,CAAA;AAMO,IAAM,0BAAA,GAA6B;AAAA,EACxC,SAAA;AAAA,EACA,UAAA;AAAA,EACA,gBAAA;AAAA,EACA,YAAA;AAAA,EACA,aAAA;AAAA,EACA,SAAA;AAAA,EACA,SAAA;AAAA,EACA,UAAA;AAAA,EACA;AACF;AAEO,IAAM,kBAAkC,cAAA,CAAe;AAAA,EAC5D,IAAA,EAAM,mBAAA;AAAA,EACN,EAAA,EAAI,mBAAA;AAAA,EACJ,WAAA,EACE,ohBAAA;AAAA,EAQF,OAAA,EAAS,OAAA;AAAA,EACT,GAAA,EAAK,MAAA;AAAA,EACL,QAAA,EAAU,CAAC,MAAM,CAAA;AAAA,EACjB,OAAA,EAAS;AAAA,IACP;AAAA,MACE,MAAA,EAAQ,KAAA;AAAA,MACR,OAAA,EAAS,uCAAA;AAAA,MACT,MAAA,EAAQ;AAAA;AACV,GACF;AAAA;AAAA;AAAA;AAAA,EAIA,aAAA,EAAe;AAAA,IACb,GAAA,EAAK,kBAAA;AAAA,IACL,KAAA,EAAO,sBAAA;AAAA,IACP,KAAA,EAAO,WAAA;AAAA,IACP,UAAA,EAAY;AAAA,GACd;AAAA;AAAA;AAAA;AAAA;AAAA,EAKA,IAAA,EAAM;AAAA,IACJ,GAAA,EAAK,wBAAA;AAAA,IACL,KAAA,EAAO;AAAA,MACL,GAAA,EAAK,mBAAA;AAAA,MACL,WAAA,EAAa;AAAA;AACf,GACF;AAAA;AAAA,EAEA,OAAA,EACE,kLAAA;AAAA,EAGF,QAAA,EAAU,KAAA;AAAA,EACV,GAAA,EAAK,wBAAA;AAAA,EACL,OAAA,EAAS;AAAA;AAAA;AAAA,IAGP,IAAA,EAAM,YAAA;AAAA,IACN,eAAA,EAAiB,IAAA;AAAA,IACjB,iBAAA,EAAmB;AAAA,GACrB;AAAA;AAAA;AAAA;AAAA;AAAA,EAKA,YAAA,EAAc;AAAA;AAAA,IAEZ,SAAA,EAAW,IAAA;AAAA;AAAA;AAAA,IAGX,UAAA,EAAY,IAAA;AAAA,IACZ,UAAA,EAAY,KAAA;AAAA,IACZ,OAAA,EAAS,IAAA;AAAA,IACT,UAAA,EAAY,KAAA;AAAA;AAAA;AAAA;AAAA,IAIZ,SAAA,EAAW,IAAA;AAAA;AAAA;AAAA,IAGX,aAAA,EAAe;AAAA,GACjB;AAAA,EACA,IAAA,EAAM;AAAA,IACJ,aAAA;AAAA,IACA,WAAA;AAAA,IACA,OAAA;AAAA,IACA,QAAA;AAAA,IACA,KAAA;AAAA,IACA,eAAA;AAAA,IACA;AAAA,GACF;AAAA,EACA,QAAA,EAAU;AAAA,IACR,GAAA,EAAK,EAAA;AAAA;AAAA,IAEL,OAAA,EAAS,aAAA;AAAA,IACT,KAAA,EAAO;AAAA,MACL,MAAA,EAAQ;AAAA,KACV;AAAA;AAAA,IAEA,kBAAA,EAAoB,CAAC,GAAG,0BAA0B;AAAA;AAEtD,CAAC;AAEM,SAAS,sBAAA,GAA0C;AACxD,EAAA,OAAO,sBAAsB,eAAe,CAAA;AAC9C","file":"index.mjs","sourcesContent":["/**\n * @agentproto/adapter-claude-code-cloud — AIP-66 managed cloud agent adapter\n * for Anthropic Claude Code cloud sessions.\n *\n * Unlike `@agentproto/adapter-claude-code` (local harness, host machine),\n * this adapter relays a session the VENDOR hosts end to end: the vendor\n * boots the machine, runs Claude Code in it, and exposes the session\n * through `claude --cloud` / `claude -p --cloud` plus the undocumented\n * Claude Code sessions API. No agentproto daemon runs inside; the host\n * controls neither the machine nor the harness — so this manifest is\n * deliberately smaller and refuses the spawn fields that could never take\n * effect (AIP-66 §4).\n *\n * import { claudeCodeCloud } from \"@agentproto/adapter-claude-code-cloud\"\n */\n\nimport { fileURLToPath } from \"node:url\"\nimport {\n createAgentCliRuntime,\n defineAgentCli,\n type AgentCliHandle,\n type AgentCliRuntime,\n} from \"@agentproto/driver-agent-cli\"\n\n// Self-locating: the built handle spawns `node <this-pkg>/bin/…\n// claude-code-cloud-acp.mjs`. From dist/index.mjs the bin sits one level up,\n// so the same build works whether the daemon resolves this package from\n// node_modules or a user runs the published bin directly.\nconst acpBin = fileURLToPath(\n new URL(\"../bin/claude-code-cloud-acp.mjs\", import.meta.url),\n)\n\n// AIP-66 §4 refused spawn fields — no meaning for a vendor-owned harness, so\n// the host MUST refuse a cloud spawn that sets any of them rather than\n// ignore them. Documented here (and in CLAUDE-CODE-CLOUD.md) so the runtime\n// gate and users share one list.\nexport const CLOUD_REFUSED_SPAWN_FIELDS = [\n \"sandbox\",\n \"worktree\",\n \"commandSandbox\",\n \"mcpServers\",\n \"daemonMount\",\n \"bundles\",\n \"browser\",\n \"appServe\",\n \"inference\",\n] as const\n\nexport const claudeCodeCloud: AgentCliHandle = defineAgentCli({\n name: \"claude-code-cloud\",\n id: \"claude-code-cloud\",\n description:\n \"AIP-66 managed cloud agent adapter for Anthropic Claude Code cloud \" +\n \"sessions. The vendor owns the machine and the harness: starts via \" +\n \"`claude --cloud` (TTY), prompts via `claude -p --cloud <id>`, observes \" +\n \"via the Claude Code sessions API, projected onto stdio ACP. Refuses \" +\n \"the AIP-66 §4 spawn fields (sandbox, worktree, commandSandbox, \" +\n \"mcpServers, daemonMount, bundles, browser, appServe, inference) — the \" +\n \"vendor can never apply them. Requires a claude.ai sign-in (API-key \" +\n \"auth is refused) and a clean, pushed git checkout.\",\n version: \"0.1.0\",\n bin: \"node\",\n bin_args: [acpBin],\n install: [\n {\n method: \"npm\",\n package: \"@agentproto/adapter-claude-code-cloud\",\n global: true,\n },\n ],\n // Presence probe against the vendor client this adapter relays to — the\n // pinned floor is the oldest CLI observed to support `--cloud` / the\n // sessions API (AIP-66 Appendix A: 2.1.296–2.1.299).\n version_check: {\n cmd: \"claude --version\",\n parse: \"(\\\\d+\\\\.\\\\d+\\\\.\\\\d+)\",\n range: \">=2.1.296\",\n timeout_ms: 15_000,\n },\n // Auth is the user's OWN claude.ai login inside the claude CLI (keychain\n // on macOS) — never an injected env credential (AIP-66 §8). No `state.env`\n // because an API-key env would be scrubbed, not consumed; the preflight\n // refuses an api_key-authenticated CLI outright.\n auth: {\n ref: \"./CLAUDE-CODE-CLOUD.md\",\n login: {\n cmd: \"claude auth login\",\n interactive: true,\n },\n },\n // The machine is the vendor's; there is no host-side sandbox to describe.\n sandbox:\n \"Managed cloud (AIP-66): the vendor boots the machine and runs Claude \" +\n \"Code on it. No agentproto daemon runs inside; the session URL is \" +\n \"surfaced so the user can inspect what ran.\",\n protocol: \"acp\",\n acp: \"./CLAUDE-CODE-CLOUD.md\",\n session: {\n // One agentproto session = one vendor cloud session (AIP-66 §5);\n // follow-up turns send to the same vendor session.\n mode: \"persistent\",\n idle_timeout_ms: 1_800_000,\n context_carryover: true,\n },\n // NO `models` menu: the vendor picks and bills the model inside its own\n // harness; the host has no model to select or route (AIP-66 §4 — `model`\n // is only meaningful when the vendor client accepts it, and this CLI's\n // cloud path exposes no model flag).\n capabilities: {\n // Turns stream back as ACP updates while the vendor runs them.\n streaming: true,\n // The vendor harness's own tools (Read/Edit/Bash/…) surface as ACP\n // tool_call / tool_call_update updates from the session's events.\n tool_calls: true,\n sub_agents: false,\n file_io: true,\n multimodal: false,\n // Re-attach is via the persisted vendor session id (AIP-66 §5): the\n // host hands it back as ACP `session/load`, which ADOPTS it — the next\n // prompt is a send to that same vendor session, never a new start.\n resumable: true,\n // Send-only prompting: the CLI never returns the reply on the prompt\n // path; the reply is observed via the sessions API.\n bidirectional: false,\n },\n tags: [\n \"claude-code\",\n \"anthropic\",\n \"cloud\",\n \"aip-66\",\n \"acp\",\n \"agent-runtime\",\n \"coding\",\n ],\n metadata: {\n aip: 66,\n // The harness the vendor runs (AIP-66 §2 CloudVendor.harnesses).\n harness: \"claude-code\",\n cloud: {\n vendor: \"anthropic\",\n },\n // AIP-66 §4 refused spawn fields, machine-readable for the host gate.\n refusedSpawnFields: [...CLOUD_REFUSED_SPAWN_FIELDS],\n },\n})\n\nexport function claudeCodeCloudRuntime(): AgentCliRuntime {\n return createAgentCliRuntime(claudeCodeCloud)\n}\n\nexport {\n ClaudeCloudAcpAgent,\n runAcpOverStdio,\n resultEventUpdates,\n resultStopReason,\n POLL_INITIAL_MS,\n POLL_MAX_MS,\n type ClaudeCloudAcpDeps,\n type CloudCliDeps,\n type CloudEventsClient,\n} from \"./acp-server.js\"\nexport {\n CLOUD_SESSION_META_FILE_ENV,\n CLOUD_VENDOR_SLUG,\n writeCloudSessionMeta,\n type CloudSessionMetaReport,\n} from \"./meta-file.js\"\nexport {\n cloudChildEnv,\n createRefreshLogin,\n defaultCloudCliRunner,\n normalizePtyOutput,\n parseAuthStatus,\n parseCloudStartOutput,\n preflightAuth,\n ptyOutputTail,\n sendPrompt,\n startCloudSession,\n CLAUDE_CODE_GATEWAY_ENV_UNSET,\n type AuthStatus,\n type CloudCliRunner,\n type CloudCliRunnerDeps,\n type PtyProcess,\n type PtySpawn,\n type PtySpawnOptions,\n type RefreshLoginOpts,\n type RunOpts,\n type RunResult,\n type StartedCloudSession,\n} from \"./cli.js\"\nexport {\n SessionsApi,\n EXPIRY_SKEW_MS,\n envCredentialSource,\n isCredentialExpiring,\n keychainCredentialSource,\n normalizeSessionId,\n toCliSessionId,\n type CloudCredential,\n type CloudEventsPage,\n type CloudGetSessionResponse,\n type CloudSessionEvent,\n type CloudSessionState,\n type CloudSessionSummary,\n type CredentialSource,\n type SessionsApiOptions,\n} from \"./sessions-api.js\"\nexport {\n validateRepoSource,\n defaultGitRunner,\n type GitRunner,\n} from \"./repo-source.js\"\nexport type { AgentCliHandle, AgentCliRuntime }\n"]}