@agentproto/adapter-claude-code-cloud 0.2.0 → 0.2.2

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.
@@ -12,7 +12,7 @@ relays the vendor's own client + sessions API onto ACP.
12
12
 
13
13
  | Method | Behaviour |
14
14
  | ---------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
15
- | `initialize` | Returns `PROTOCOL_VERSION` + `agentCapabilities.loadSession=false` (re-attach is via the persisted vendor session id, AIP-66 §5). |
15
+ | `initialize` | Returns `PROTOCOL_VERSION` + `agentCapabilities.loadSession=true` (`session/load` adopts the persisted vendor session id, AIP-66 §5). |
16
16
  | `authenticate` | No-op. Auth is the user's claude.ai login inside the claude CLI (keychain); preflighted per turn (`claude auth status` — api_key auth and not-logged-in are refused). |
17
17
  | `session/new` | Validates `cwd` per AIP-66 §3 BEFORE any vendor side effect: a git checkout, clean working tree, an `origin` remote, and a HEAD contained in some `origin/*` ref. Refuses `mcpServers` (AIP-66 §4). |
18
18
  | `session/prompt` | First prompt → `claude --cloud "<prompt>"` under a PTY (start; answers the first-run folder-trust prompt), later prompts → `claude -p "<text>" --cloud <session id>` (send-only). Then polls `GET /v1/code/sessions/{id}/events` (2s, backing off to 10s) until a NEW `result` event arrives. |
package/README.md CHANGED
@@ -25,8 +25,12 @@ zero — AIP-66 §7).
25
25
  from the `Claude Code-credentials` keychain entry (org uuid from
26
26
  `~/.claude.json`), or `CLAUDE_CLOUD_OAUTH_TOKEN` when injected. A CLI
27
27
  authenticated by API key, or not logged in, is refused with a pointer to
28
- `claude auth login`. The token is only ever used as a request header — never
29
- logged or persisted (AIP-66 §8).
28
+ `claude auth login`. When the token is expired (or within five minutes of
29
+ expiry) or the API answers 401, the adapter runs `claude -p "Reply OK"
30
+ --model haiku` once to let the CLI re-mint it, drops its cached credential,
31
+ and retries — a still-failing call reports `run \`claude auth login\``. The
32
+ token is only ever used as a request header — never logged or persisted
33
+ (AIP-66 §8).
30
34
  - **A clean, pushed git checkout as the session cwd.** The cloud runs the repo
31
35
  from its git remote, never an uploaded working tree, so `session/new`
32
36
  refuses (AIP-66 §3) a non-git cwd, a dirty working tree, a missing `origin`
@@ -1,3 +1,3 @@
1
- export { ClaudeCloudAcpAgent, MAX_LIST_EVENTS_FAILURES, OBSERVE_PAGES_LIMIT, POLL_INITIAL_MS, POLL_MAX_MS, isTransientListEventsError, main, promptText, resultEventUpdates, resultStopReason, runAcpOverStdio } from './chunk-RSQRK7X6.mjs';
1
+ export { ClaudeCloudAcpAgent, MAX_LIST_EVENTS_FAILURES, OBSERVE_PAGES_LIMIT, POLL_INITIAL_MS, POLL_MAX_MS, isTransientListEventsError, main, promptText, resultEventUpdates, resultStopReason, runAcpOverStdio } from './chunk-LN5RJ5ZT.mjs';
2
2
  //# sourceMappingURL=acp-server.mjs.map
3
3
  //# sourceMappingURL=acp-server.mjs.map
@@ -3,9 +3,9 @@ import { PROTOCOL_VERSION, ndJsonStream, AgentSideConnection } from '@agentclien
3
3
  import { sdkMessageToUpdates, promptText } from '@agentproto/adapter-claude-sdk';
4
4
  export { promptText } from '@agentproto/adapter-claude-sdk';
5
5
  import { execFile, spawn } from 'child_process';
6
+ import { homedir, tmpdir } from 'os';
6
7
  import { ANTHROPIC_CORE_SCRUB_ENV } from '@agentproto/provider-presets';
7
8
  import { readFile, mkdir, writeFile, rename } from 'fs/promises';
8
- import { homedir } from 'os';
9
9
  import { join, dirname } from 'path';
10
10
  import { promisify } from 'util';
11
11
 
@@ -15,6 +15,7 @@ import { promisify } from 'util';
15
15
  */
16
16
 
17
17
  var execFileAsync = promisify(execFile);
18
+ var EXPIRY_SKEW_MS = 5 * 6e4;
18
19
  var KEYCHAIN_SERVICE = "Claude Code-credentials";
19
20
  function keychainCredentialSource(deps = {}) {
20
21
  const execFileImpl = deps.execFileImpl ?? (async (cmd, args) => {
@@ -52,8 +53,16 @@ function keychainCredentialSource(deps = {}) {
52
53
  orgUuid = rc.oauthAccount?.organizationUuid;
53
54
  } catch {
54
55
  }
55
- cached = { accessToken, ...orgUuid ? { orgUuid } : {} };
56
+ const expiresAt = keychain.claudeAiOauth?.expiresAt;
57
+ cached = {
58
+ accessToken,
59
+ ...orgUuid ? { orgUuid } : {},
60
+ ...typeof expiresAt === "number" ? { expiresAt } : {}
61
+ };
56
62
  return cached;
63
+ },
64
+ invalidate() {
65
+ cached = null;
57
66
  }
58
67
  };
59
68
  }
@@ -68,6 +77,8 @@ function envCredentialSource(env = process.env) {
68
77
  }
69
78
  const orgUuid = env.CLAUDE_CLOUD_ORG_UUID;
70
79
  return { accessToken, ...orgUuid ? { orgUuid } : {} };
80
+ },
81
+ invalidate() {
71
82
  }
72
83
  };
73
84
  }
@@ -90,13 +101,18 @@ function toCliSessionId(id) {
90
101
  return `session_${normalized.slice("cse_".length)}`;
91
102
  }
92
103
  var UNAUTHORIZED_HINT = "run `claude auth login`";
104
+ function isCredentialExpiring(credential, now = Date.now()) {
105
+ return credential.expiresAt !== void 0 && credential.expiresAt - now <= EXPIRY_SKEW_MS;
106
+ }
93
107
  var SessionsApi = class {
94
108
  #credentials;
109
+ #refreshLogin;
95
110
  #fetch;
96
111
  #baseUrl;
97
112
  #credential = null;
98
113
  constructor(options) {
99
114
  this.#credentials = options.credentials;
115
+ this.#refreshLogin = options.refreshLogin;
100
116
  this.#fetch = options.fetchImpl ?? globalThis.fetch.bind(globalThis);
101
117
  this.#baseUrl = (options.baseUrl ?? "https://api.anthropic.com").replace(/\/$/, "");
102
118
  }
@@ -134,8 +150,26 @@ var SessionsApi = class {
134
150
  if (!this.#credential) this.#credential = await this.#credentials.get();
135
151
  return this.#credential;
136
152
  }
137
- async #request(method, path, retriedAuth = false) {
153
+ /** Refresh the login (when injected), drop the source cache, and re-read.
154
+ * A refresh failure is surfaced to the caller — better a clear "run
155
+ * `claude auth login`" than a request with a known-stale token. */
156
+ async #refreshAndInvalidate() {
157
+ await this.#refreshLogin?.();
158
+ this.#credentials.invalidate();
159
+ this.#credential = null;
160
+ }
161
+ /** The credential for the next request: refresh first when it is expired
162
+ * or expiring. Without an injected refresh the check is a no-op. */
163
+ async #freshCredential() {
138
164
  const credential = await this.#credentialNow();
165
+ if (this.#refreshLogin && isCredentialExpiring(credential)) {
166
+ await this.#refreshAndInvalidate();
167
+ return this.#credentialNow();
168
+ }
169
+ return credential;
170
+ }
171
+ async #request(method, path, retriedAuth = false) {
172
+ const credential = retriedAuth ? await this.#credentialNow() : await this.#freshCredential();
139
173
  const headers = {
140
174
  authorization: `Bearer ${credential.accessToken}`,
141
175
  "anthropic-version": "2023-06-01",
@@ -144,7 +178,7 @@ var SessionsApi = class {
144
178
  };
145
179
  const res = await this.#fetch(`${this.#baseUrl}${path}`, { method, headers });
146
180
  if (res.status === 401 && !retriedAuth) {
147
- this.#credential = null;
181
+ await this.#refreshAndInvalidate();
148
182
  return this.#request(method, path, true);
149
183
  }
150
184
  if (res.status === 401) {
@@ -181,8 +215,18 @@ function cloudChildEnv(base = process.env) {
181
215
  }
182
216
  return out;
183
217
  }
218
+ var ANSI_ESCAPE_RE = /\x1b\][\s\S]*?(?:\x07|\x1b\\)|\x1b\[[0-9;?]*[ -/]*[@-~]|\x1b./g;
219
+ function normalizePtyOutput(raw) {
220
+ return raw.replace(ANSI_ESCAPE_RE, " ").replace(/[^\S\n]+/g, " ").replace(/\n[ \t]*(?:\n[ \t]*)+/g, "\n").trim();
221
+ }
222
+ var TRUST_PROMPT_RE = /Yes,\s*I\s*trust\s*this\s*folder/i;
223
+ var PTY_TAIL_CHARS = 300;
224
+ function ptyOutputTail(raw, maxChars = PTY_TAIL_CHARS) {
225
+ const stripped = normalizePtyOutput(raw);
226
+ return stripped.length > maxChars ? stripped.slice(stripped.length - maxChars) : stripped;
227
+ }
184
228
  var DEFAULT_RUN_TIMEOUT_MS = 6e4;
185
- function defaultCloudCliRunner() {
229
+ function defaultCloudCliRunner(deps = {}) {
186
230
  return {
187
231
  run(cmd, args, opts) {
188
232
  return new Promise((resolve, reject) => {
@@ -223,10 +267,8 @@ function defaultCloudCliRunner() {
223
267
  });
224
268
  let proc = null;
225
269
  const pendingWrites = [];
226
- void import('node-pty').then((mod) => {
227
- const pty = mod.default ?? mod;
228
- if (typeof pty.spawn !== "function") throw new Error("node-pty has no spawn");
229
- const p = pty.spawn(cmd, args, {
270
+ const attach = (spawnFn) => {
271
+ const p = spawnFn(cmd, args, {
230
272
  name: "xterm-256color",
231
273
  cols: 120,
232
274
  rows: 40,
@@ -241,7 +283,7 @@ function defaultCloudCliRunner() {
241
283
  p.onData((chunk) => {
242
284
  output += chunk;
243
285
  opts.onData?.(chunk);
244
- if (!answeredTrustPrompt && /Yes, I trust this folder/.test(output)) {
286
+ if (!answeredTrustPrompt && TRUST_PROMPT_RE.test(normalizePtyOutput(output))) {
245
287
  answeredTrustPrompt = true;
246
288
  p.write("\x1B[B\r");
247
289
  }
@@ -253,7 +295,7 @@ function defaultCloudCliRunner() {
253
295
  }
254
296
  rejectResult(
255
297
  new Error(
256
- `claude code cloud: \`${cmd} ${args.join(" ")}\` timed out after ${opts.timeoutMs ?? 12e4}ms under the PTY`
298
+ `claude code cloud: \`${cmd} ${args.join(" ")}\` timed out after ${opts.timeoutMs ?? 12e4}ms under the PTY; last output: ${ptyOutputTail(output)}`
257
299
  )
258
300
  );
259
301
  }, opts.timeoutMs ?? 12e4);
@@ -262,13 +304,26 @@ function defaultCloudCliRunner() {
262
304
  clearTimeout(timer);
263
305
  resolveResult({ code: exitCode, output });
264
306
  });
265
- }).catch((err) => {
266
- rejectResult(
267
- new Error(
268
- `claude code cloud: \`claude --cloud\` needs a real PTY and node-pty is not available (${err instanceof Error ? err.message : String(err)}) \u2014 install it (npm i node-pty) to use managed cloud sessions`
269
- )
270
- );
271
- });
307
+ };
308
+ if (deps.spawnPty) {
309
+ try {
310
+ attach(deps.spawnPty);
311
+ } catch (err) {
312
+ rejectResult(err);
313
+ }
314
+ } else {
315
+ void import('node-pty').then((mod) => {
316
+ const pty = mod.default ?? mod;
317
+ if (typeof pty.spawn !== "function") throw new Error("node-pty has no spawn");
318
+ attach(pty.spawn);
319
+ }).catch((err) => {
320
+ rejectResult(
321
+ new Error(
322
+ `claude code cloud: \`claude --cloud\` needs a real PTY and node-pty is not available (${err instanceof Error ? err.message : String(err)}) \u2014 install it (npm i node-pty) to use managed cloud sessions`
323
+ )
324
+ );
325
+ });
326
+ }
272
327
  return {
273
328
  write: (data) => {
274
329
  if (proc) proc.write(data);
@@ -279,6 +334,43 @@ function defaultCloudCliRunner() {
279
334
  }
280
335
  };
281
336
  }
337
+ function createRefreshLogin(opts = {}) {
338
+ let inFlight = null;
339
+ return () => {
340
+ if (inFlight) return inFlight;
341
+ const run = (async () => {
342
+ const runner = opts.runner ?? defaultCloudCliRunner();
343
+ const env = cloudChildEnv(opts.env ?? process.env);
344
+ let result;
345
+ try {
346
+ result = await runner.run(
347
+ "claude",
348
+ ["-p", "Reply OK", "--model", "haiku"],
349
+ {
350
+ cwd: opts.cwd ?? tmpdir(),
351
+ env,
352
+ stdin: "ignore",
353
+ timeoutMs: opts.timeoutMs ?? 6e4
354
+ }
355
+ );
356
+ } catch (err) {
357
+ throw new Error(
358
+ `claude code cloud: could not refresh the claude.ai login \u2014 is the claude CLI installed and on PATH? (${err instanceof Error ? err.message : String(err)})`
359
+ );
360
+ }
361
+ if (result.code !== 0) {
362
+ throw new Error(
363
+ `claude code cloud: could not refresh the claude.ai login (exit ${result.code}) \u2014 run \`claude auth login\``
364
+ );
365
+ }
366
+ })();
367
+ const wrapped = run.finally(() => {
368
+ if (inFlight === wrapped) inFlight = null;
369
+ });
370
+ inFlight = wrapped;
371
+ return wrapped;
372
+ };
373
+ }
282
374
  function parseAuthStatus(stdout) {
283
375
  const trimmed = stdout.trim();
284
376
  const start = trimmed.indexOf("{");
@@ -324,12 +416,13 @@ async function preflightAuth(runner, opts) {
324
416
  return status;
325
417
  }
326
418
  function parseCloudStartOutput(output) {
419
+ const transcript = normalizePtyOutput(output);
327
420
  let sessionId;
328
421
  let url;
329
422
  let title;
330
- const resume = output.match(/Resume with:\s*claude\s+--teleport\s+(session_[A-Za-z0-9_-]+)/);
423
+ const resume = transcript.match(/Resume with:\s*claude\s+--teleport\s+(session_[A-Za-z0-9_-]+)/);
331
424
  if (resume?.[1]) sessionId = resume[1];
332
- const view = output.match(/View:\s*(https?:\/\/\S+)/);
425
+ const view = transcript.match(/View:\s*(https?:\/\/\S+)/);
333
426
  if (view?.[1]) {
334
427
  url = view[1];
335
428
  if (!sessionId) {
@@ -337,7 +430,7 @@ function parseCloudStartOutput(output) {
337
430
  if (fromUrl?.[1]) sessionId = `session_${fromUrl[1]}`;
338
431
  }
339
432
  }
340
- const created = output.match(/Created cloud session:\s*(.+)/);
433
+ const created = transcript.match(/Created cloud session:\s*(.+)/);
341
434
  if (created?.[1]) title = created[1].trim();
342
435
  if (!sessionId) return null;
343
436
  return {
@@ -512,8 +605,9 @@ function defaultSleep(ms) {
512
605
  function defaultDeps() {
513
606
  const runner = defaultCloudCliRunner();
514
607
  const credentials = keychainCredentialSource();
608
+ const refreshLogin = createRefreshLogin({ runner, env: process.env });
515
609
  return {
516
- api: new SessionsApi({ credentials }),
610
+ api: new SessionsApi({ credentials, refreshLogin }),
517
611
  cli: {
518
612
  startCloudSession: (prompt, opts) => startCloudSession(prompt, {
519
613
  cwd: opts.cwd,
@@ -850,6 +944,6 @@ function main() {
850
944
  runAcpOverStdio();
851
945
  }
852
946
 
853
- export { CLAUDE_CODE_GATEWAY_ENV_UNSET, CLOUD_SESSION_META_FILE_ENV, CLOUD_VENDOR_SLUG, ClaudeCloudAcpAgent, MAX_LIST_EVENTS_FAILURES, OBSERVE_PAGES_LIMIT, POLL_INITIAL_MS, POLL_MAX_MS, SessionsApi, cloudChildEnv, defaultCloudCliRunner, defaultGitRunner, envCredentialSource, isTransientListEventsError, keychainCredentialSource, main, normalizeSessionId, parseAuthStatus, parseCloudStartOutput, preflightAuth, resultEventUpdates, resultStopReason, runAcpOverStdio, sendPrompt, startCloudSession, toCliSessionId, validateRepoSource, writeCloudSessionMeta };
854
- //# sourceMappingURL=chunk-RSQRK7X6.mjs.map
855
- //# sourceMappingURL=chunk-RSQRK7X6.mjs.map
947
+ export { CLAUDE_CODE_GATEWAY_ENV_UNSET, CLOUD_SESSION_META_FILE_ENV, CLOUD_VENDOR_SLUG, ClaudeCloudAcpAgent, EXPIRY_SKEW_MS, MAX_LIST_EVENTS_FAILURES, OBSERVE_PAGES_LIMIT, POLL_INITIAL_MS, POLL_MAX_MS, SessionsApi, cloudChildEnv, createRefreshLogin, defaultCloudCliRunner, defaultGitRunner, envCredentialSource, isCredentialExpiring, isTransientListEventsError, keychainCredentialSource, main, normalizePtyOutput, normalizeSessionId, parseAuthStatus, parseCloudStartOutput, preflightAuth, ptyOutputTail, resultEventUpdates, resultStopReason, runAcpOverStdio, sendPrompt, startCloudSession, toCliSessionId, validateRepoSource, writeCloudSessionMeta };
948
+ //# sourceMappingURL=chunk-LN5RJ5ZT.mjs.map
949
+ //# sourceMappingURL=chunk-LN5RJ5ZT.mjs.map
@@ -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
@@ -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
@@ -226,13 +301,20 @@ declare function normalizeSessionId(id: string): string;
226
301
  * `--teleport`). Same acceptance set as {@link normalizeSessionId}. */
227
302
  declare function toCliSessionId(id: string): string;
228
303
  interface SessionsApiOptions {
229
- /** 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. */
230
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>;
231
310
  /** Injectable fetch — tests pass a fixture router; default is globalThis.fetch. */
232
311
  fetchImpl?: typeof fetch;
233
312
  /** Override for proxies/mirrors; default https://api.anthropic.com. */
234
313
  baseUrl?: string;
235
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;
236
318
  declare class SessionsApi {
237
319
  #private;
238
320
  constructor(options: SessionsApiOptions);
@@ -451,4 +533,4 @@ declare const CLOUD_REFUSED_SPAWN_FIELDS: readonly ["sandbox", "worktree", "comm
451
533
  declare const claudeCodeCloud: AgentCliHandle;
452
534
  declare function claudeCodeCloudRuntime(): AgentCliRuntime;
453
535
 
454
- 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 CloudCredential, type CloudEventsClient, type CloudEventsPage, type CloudGetSessionResponse, type CloudSessionEvent, type CloudSessionMetaReport, 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, writeCloudSessionMeta };
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, CLOUD_SESSION_META_FILE_ENV, CLOUD_VENDOR_SLUG, ClaudeCloudAcpAgent, POLL_INITIAL_MS, POLL_MAX_MS, SessionsApi, cloudChildEnv, defaultCloudCliRunner, defaultGitRunner, envCredentialSource, keychainCredentialSource, normalizeSessionId, parseAuthStatus, parseCloudStartOutput, preflightAuth, resultEventUpdates, resultStopReason, runAcpOverStdio, sendPrompt, startCloudSession, toCliSessionId, validateRepoSource, writeCloudSessionMeta } from './chunk-RSQRK7X6.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
 
@@ -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;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 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"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentproto/adapter-claude-code-cloud",
3
- "version": "0.2.0",
3
+ "version": "0.2.2",
4
4
  "description": "@agentproto/adapter-claude-code-cloud — AIP-66 managed-cloud-agent adapter for Anthropic Claude Code cloud sessions. Relays `claude --cloud` / `claude -p --cloud` and the undocumented Claude Code sessions API behind an AIP-44 ACP server; the vendor owns the machine and the harness, no agentproto daemon runs inside.",
5
5
  "keywords": [
6
6
  "agentproto",
@@ -49,8 +49,8 @@
49
49
  },
50
50
  "dependencies": {
51
51
  "@agentclientprotocol/sdk": "^0.21.1",
52
- "@agentproto/adapter-claude-sdk": "0.7.24",
53
- "@agentproto/driver-agent-cli": "2.13.0",
52
+ "@agentproto/adapter-claude-sdk": "0.7.26",
53
+ "@agentproto/driver-agent-cli": "2.13.1",
54
54
  "@agentproto/provider-presets": "0.7.0"
55
55
  },
56
56
  "optionalDependencies": {
@@ -1 +0,0 @@
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-RSQRK7X6.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. On 401 the credential source is re-read exactly once (the\n * token may have been refreshed since process start), then the call fails\n * with a message 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`). NEVER logged or persisted. */\nexport interface CloudCredential {\n accessToken: string\n orgUuid?: string\n}\n\n/** Where the host reads the vendor login from (AIP-66 §8). Implementations\n * must not cache a token across an explicit invalidate() — a 401 re-read\n * has to be able to observe a refreshed login. */\nexport interface CredentialSource {\n get(): Promise<CloudCredential>\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 }\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 cached = { accessToken, ...(orgUuid ? { orgUuid } : {}) }\n return cached\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 }\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; re-read once on a 401, then the call fails. */\n credentials: CredentialSource\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\nexport class SessionsApi {\n readonly #credentials: CredentialSource\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.#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 async #request<T>(method: string, path: string, retriedAuth = false): Promise<T> {\n const credential = await this.#credentialNow()\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 since we read it — re-read the\n // source exactly once, then fail closed with the login hint.\n this.#credential = null\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 { 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// ── 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/** Real runner: child_process for headless calls, node-pty (optional dep)\n * for the TTY-required `claude --cloud` start. */\nexport function defaultCloudCliRunner(): 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: import(\"node-pty\").IPty | null = null\n const pendingWrites: string[] = []\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 = (mod as { default?: { spawn: typeof import(\"node-pty\").spawn } }).default ?? (mod as unknown as { spawn: typeof import(\"node-pty\").spawn })\n if (typeof pty.spawn !== \"function\") throw new Error(\"node-pty has no spawn\")\n const p = pty.spawn(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\". Answer at most once.\n if (!answeredTrustPrompt && /Yes, I trust this folder/.test(output)) {\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`,\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 .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 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// ── 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 let sessionId: string | undefined\n let url: string | undefined\n let title: string | undefined\n\n const resume = output.match(/Resume with:\\s*claude\\s+--teleport\\s+(session_[A-Za-z0-9_-]+)/)\n if (resume?.[1]) sessionId = resume[1]\n\n const view = output.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 = output.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 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 return {\n api: new SessionsApi({ credentials }),\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"]}