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

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.
@@ -41,6 +41,34 @@ a timer or on poll silence. Stop reason: `end_turn` for a success result,
41
41
  failures (HTTP 5xx, network) are retried with the poll backoff — a read
42
42
  failure never ends a turn — until 5 consecutive ones fail the prompt.
43
43
 
44
+ ## Event paging & ordering (Appendix)
45
+
46
+ `GET /v1/code/sessions/{id}/events` does NOT page forward. Observed
47
+ 2026-10-14 against the live API:
48
+
49
+ - **No `cursor` → the NEWEST page**, up to 50 events, newest first.
50
+ - **`resume_cursor`** (alias `next_cursor`, present on the first/no-cursor
51
+ page only) is the `sequence_num` of the OLDEST event on that page. Passing
52
+ it back as `?cursor=<n>` returns the next **OLDER** page — the cursor
53
+ pages **BACKWARD in time**, not forward. (Real example: the newest page
54
+ held seq 60..11 with `next_cursor` `"11"`; `?cursor=11` returned seq
55
+ 10..1 with `resume_cursor` `"1"`.)
56
+ - **`sequence_num`** is a STRING of an integer, strictly increasing within a
57
+ session, and is the ordering key. Parse with `Number()`; skip an event
58
+ whose `sequence_num` is not finite. Every event also carries `event_id`,
59
+ `event_type`, `payload` (the stream-json message), `source`
60
+ (`"worker"`/`"client"`) and `created_at`.
61
+
62
+ The relay therefore tracks progress by `sequence_num`, not by cursor: it
63
+ keeps a per-session `lastSeq` (the highest seq projected or seeded), polls
64
+ the newest page each tick, walks `cursor` backward only as far as needed to
65
+ reach `lastSeq` (capped at 20 pages/tick), then projects the new events in
66
+ ASCENDING seq order. `session/load` seeds `lastSeq` from ONE newest-page GET
67
+ (its max seq is the history high-water — no backward paging needed). Before
68
+ each prompt the relay records the current high-water seq; only a `result`
69
+ with a seq ABOVE that baseline can end the turn, so a prior turn's result
70
+ never ends a new one.
71
+
44
72
  ## Usage telemetry
45
73
 
46
74
  When the `result` event carries `total_cost_usd` and/or `usage`, it is
@@ -56,6 +84,44 @@ and kept for every later turn; the host is expected to persist it on the
56
84
  session descriptor (`meta.cloud = { vendor, sessionId, url }`) and re-attach
57
85
  rather than start a new vendor session after a restart.
58
86
 
87
+ ## Re-attach (AIP-66 §5)
88
+
89
+ The vendor id only exists AFTER the first prompt reaches the vendor, so the
90
+ handoff from relay to host is a side file plus a poll, and the re-attach
91
+ itself rides the ordinary ACP `session/load` resume path:
92
+
93
+ - **Meta-file handoff.** At spawn the host sets
94
+ `AGENTPROTO_CLOUD_SESSION_META_FILE` to a path inside the session's
95
+ isolated config dir. Whenever the relay learns the vendor id — after
96
+ `claude --cloud` prints it, or when `session/load` adopts an id handed
97
+ back by the host — it writes exactly the three §5 fields
98
+ `{ vendor, sessionId, url }` there (`src/meta-file.ts`, atomic
99
+ temp-file + rename, best-effort: a failed write never sinks the turn,
100
+ and a re-attach preserves an existing `url` for the same id). The file
101
+ is the ONLY channel: no credential, keychain material, or bearer token
102
+ ever enters it, the descriptor's `meta.cloud`, logs or events (AIP-66
103
+ §8) — it is byte-scoped to those three fields.
104
+ - **The host's watch.** The runtime polls that file every 2s (timers
105
+ unref'd, NO fixed timeout) and stamps the learned mapping onto the
106
+ session's `meta.cloud` the moment it appears; the watch stops on learn
107
+ or when the session ends.
108
+ - **`session/load`.** A restart or re-attach hands the relay the vendor id
109
+ persisted on `meta.cloud.sessionId` through the standard ACP
110
+ `session/load`. The relay validates it against the repo source first
111
+ (an id that isn't `session_`/`cse_`, or whose repo no longer matches,
112
+ fails closed), ADOPTS it — never starting a replacement vendor session —
113
+ pre-marks the vendor's existing events so only the next turn's own
114
+ `result` can end it, and resumes through `sendPrompt`
115
+ (`claude -p --cloud <id>`).
116
+ - **The resume fallback.** The spawn-time watch dies with a daemon
117
+ restart, so every resume point first reads `meta.cloud.sessionId`; when
118
+ the descriptor never learned one, the runtime falls back to reading the
119
+ relay's meta file inside the row's own config dir
120
+ (`cloudSessionMetaFilePath`) and stamps the found mapping back onto the
121
+ descriptor before resuming. Only when both sources are empty does the
122
+ resume fall back to the ordinary ACP uuid, which fails closed at the
123
+ vendor.
124
+
59
125
  ## Repo source (AIP-66 §3)
60
126
 
61
127
  The cloud runs the user's REPO from its git remote — never an uploaded
@@ -1,3 +1,3 @@
1
- export { ClaudeCloudAcpAgent, MAX_LIST_EVENTS_FAILURES, POLL_INITIAL_MS, POLL_MAX_MS, SEEN_EVENT_IDS_LIMIT, isTransientListEventsError, main, promptText, resultEventUpdates, resultStopReason, runAcpOverStdio } from './chunk-KA4G4O2X.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-RSQRK7X6.mjs';
2
2
  //# sourceMappingURL=acp-server.mjs.map
3
3
  //# sourceMappingURL=acp-server.mjs.map
@@ -4,9 +4,9 @@ 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
6
  import { ANTHROPIC_CORE_SCRUB_ENV } from '@agentproto/provider-presets';
7
- import { readFile } from 'fs/promises';
7
+ import { readFile, mkdir, writeFile, rename } from 'fs/promises';
8
8
  import { homedir } from 'os';
9
- import { join } from 'path';
9
+ import { join, dirname } from 'path';
10
10
  import { promisify } from 'util';
11
11
 
12
12
  /**
@@ -71,6 +71,12 @@ function envCredentialSource(env = process.env) {
71
71
  }
72
72
  };
73
73
  }
74
+ function eventSequence(event) {
75
+ const raw = event.sequence_num;
76
+ if (typeof raw !== "string" || raw.trim() === "") return null;
77
+ const n = Number(raw);
78
+ return Number.isFinite(n) ? n : null;
79
+ }
74
80
  function normalizeSessionId(id) {
75
81
  const trimmed = id.trim();
76
82
  if (trimmed.startsWith("session_")) return `cse_${trimmed.slice("session_".length)}`;
@@ -102,8 +108,9 @@ var SessionsApi = class {
102
108
  );
103
109
  }
104
110
  /**
105
- * GET /v1/code/sessions/{id}/events — newest first. Pass the previous
106
- * page's `resume_cursor` as `cursor` to resume after it.
111
+ * GET /v1/code/sessions/{id}/events — newest first. With no `cursor` this
112
+ * returns the NEWEST page; pass the page's `resume_cursor` (the oldest
113
+ * event's `sequence_num`) as `cursor` to fetch the next OLDER page.
107
114
  */
108
115
  async listEvents(id, opts = {}) {
109
116
  const params = new URLSearchParams();
@@ -383,6 +390,49 @@ async function sendPrompt(sessionId, text, opts) {
383
390
  }
384
391
  return { stdout: result.stdout };
385
392
  }
393
+ var CLOUD_SESSION_META_FILE_ENV = "AGENTPROTO_CLOUD_SESSION_META_FILE";
394
+ var CLOUD_VENDOR_SLUG = "anthropic";
395
+ async function readExisting(path) {
396
+ try {
397
+ const parsed = JSON.parse(await readFile(path, "utf8"));
398
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return void 0;
399
+ const p = parsed;
400
+ if (typeof p["vendor"] !== "string" || p["vendor"].length === 0) return void 0;
401
+ if (typeof p["sessionId"] !== "string" || p["sessionId"].length === 0) return void 0;
402
+ return {
403
+ vendor: p["vendor"],
404
+ sessionId: p["sessionId"],
405
+ ...typeof p["url"] === "string" && p["url"].length > 0 ? { url: p["url"] } : {}
406
+ };
407
+ } catch {
408
+ return void 0;
409
+ }
410
+ }
411
+ async function writeCloudSessionMeta(meta, opts = {}) {
412
+ const env = opts.env ?? process.env;
413
+ const path = env[CLOUD_SESSION_META_FILE_ENV];
414
+ if (!path) return null;
415
+ try {
416
+ const existing = await readExisting(path);
417
+ const url = meta.url ?? (existing?.sessionId === meta.sessionId ? existing.url : void 0);
418
+ const payload = JSON.stringify({
419
+ vendor: meta.vendor,
420
+ sessionId: meta.sessionId,
421
+ ...url !== void 0 ? { url } : {}
422
+ });
423
+ await mkdir(dirname(path), { recursive: true });
424
+ const tmp = `${path}.${process.pid}.tmp`;
425
+ await writeFile(tmp, payload, "utf8");
426
+ await rename(tmp, path);
427
+ return path;
428
+ } catch (err) {
429
+ process.stderr.write(
430
+ `[claude-code-cloud] could not write the cloud session meta file (${CLOUD_SESSION_META_FILE_ENV}): ${err instanceof Error ? err.message : String(err)}
431
+ `
432
+ );
433
+ return null;
434
+ }
435
+ }
386
436
  var execFileAsync2 = promisify(execFile);
387
437
  var defaultGitRunner = async (args, cwd) => {
388
438
  try {
@@ -439,6 +489,7 @@ async function validateRepoSource(cwd, git = defaultGitRunner) {
439
489
  var POLL_INITIAL_MS = 2e3;
440
490
  var POLL_MAX_MS = 1e4;
441
491
  var MAX_LIST_EVENTS_FAILURES = 5;
492
+ var OBSERVE_PAGES_LIMIT = 20;
442
493
  var NETWORK_ERROR_CODES = /^(ECONNABORTED|ECONNREFUSED|ECONNRESET|EHOSTUNREACH|ENETUNREACH|EAI_AGAIN|ENOTFOUND|EPIPE|ETIMEDOUT|UND_ERR)/;
443
494
  function isTransientListEventsError(err) {
444
495
  if (!(err instanceof Error)) return false;
@@ -452,16 +503,6 @@ function isTransientListEventsError(err) {
452
503
  }
453
504
  return false;
454
505
  }
455
- var SEEN_EVENT_IDS_LIMIT = 500;
456
- function rememberSeenEventId(session, id) {
457
- const seen = session.seenEventIds;
458
- seen.add(id);
459
- while (seen.size > SEEN_EVENT_IDS_LIMIT) {
460
- const oldest = seen.values().next();
461
- if (oldest.done) break;
462
- seen.delete(oldest.value);
463
- }
464
- }
465
506
  function defaultSleep(ms) {
466
507
  return new Promise((resolve) => {
467
508
  const timer = setTimeout(resolve, ms);
@@ -536,9 +577,10 @@ var ClaudeCloudAcpAgent = class {
536
577
  return {
537
578
  protocolVersion: PROTOCOL_VERSION,
538
579
  agentCapabilities: {
539
- // Sessions live in the vendor's cloud; re-attach is via the vendor
540
- // id, not an ACP session/load replay (AIP-66 §5).
541
- loadSession: false
580
+ // Re-attach rides ACP `session/load` with the vendor session id the
581
+ // host persisted on `meta.cloud.sessionId` (AIP-66 §5) — that call
582
+ // ADOPTS the existing cloud session, it never starts a new one.
583
+ loadSession: true
542
584
  }
543
585
  };
544
586
  }
@@ -557,12 +599,117 @@ var ClaudeCloudAcpAgent = class {
557
599
  cwd: params.cwd,
558
600
  vendorSessionId: null,
559
601
  vendorUrl: null,
560
- pollCursor: null,
561
- seenEventIds: /* @__PURE__ */ new Set(),
602
+ lastSeq: 0,
603
+ turnBaseline: 0,
562
604
  promptInFlight: false
563
605
  });
564
606
  return { sessionId: id };
565
607
  }
608
+ /**
609
+ * AIP-66 §5 re-attach: ADOPT the vendor session id the host persisted on
610
+ * `meta.cloud.sessionId` as this ACP session's vendor session. No vendor
611
+ * side effect happens here — the next `session/prompt` goes through
612
+ * `sendPrompt` (`claude -p … --cloud <id>`), never `startCloudSession`,
613
+ * so a resumed relay can never replace the vendor's session with a new
614
+ * one. The adopted id is also reported back to the host's meta file so a
615
+ * re-attach against a fresh config dir still carries the §5 mapping.
616
+ *
617
+ * Fails closed on an id the vendor could never own (e.g. the ACP uuid of
618
+ * a spawn whose vendor id was never learned): no session is started in
619
+ * its place.
620
+ */
621
+ async loadSession(params) {
622
+ if (params.mcpServers && params.mcpServers.length > 0) {
623
+ throw new Error(
624
+ "claude code cloud: mcpServers is not supported for managed cloud agents (AIP-66 \xA74) \u2014 the vendor owns the harness"
625
+ );
626
+ }
627
+ let vendorSessionId;
628
+ try {
629
+ vendorSessionId = toCliSessionId(params.sessionId);
630
+ } catch {
631
+ throw new Error(
632
+ `claude code cloud: session/load needs the vendor session id, got ${JSON.stringify(params.sessionId)} \u2014 expected session_<id> or cse_<id> (AIP-66 \xA75). That id was never learned onto meta.cloud.sessionId, so there is no vendor session to re-attach to \u2014 and this relay will not start a replacement.`
633
+ );
634
+ }
635
+ await this.#validateRepo(params.cwd);
636
+ const session = {
637
+ id: vendorSessionId,
638
+ cwd: params.cwd,
639
+ vendorSessionId,
640
+ vendorUrl: null,
641
+ lastSeq: 0,
642
+ turnBaseline: 0,
643
+ promptInFlight: false
644
+ };
645
+ this.#sessions.set(vendorSessionId, session);
646
+ await this.#seedHistory(session, vendorSessionId);
647
+ await writeCloudSessionMeta({ vendor: CLOUD_VENDOR_SLUG, sessionId: vendorSessionId });
648
+ return {};
649
+ }
650
+ /** Seed `lastSeq` from the vendor's newest events page. Best effort: a
651
+ * failed seed degrades to (at worst) an early end on an older `result` —
652
+ * it must never turn a re-attach into a failed load, which AIP-66 §5
653
+ * forbids replacing with a fresh start anyway.
654
+ *
655
+ * ONE newest-page GET with no cursor: it returns the newest page (newest
656
+ * first), so its max `sequence_num` is the history high-water. No
657
+ * backward paging is needed — `lastSeq` only has to be high enough that
658
+ * the first post-attach poll projects nothing already in the history. */
659
+ async #seedHistory(session, vendorSessionId) {
660
+ try {
661
+ session.lastSeq = await this.#highWaterSeq(vendorSessionId);
662
+ } catch (err) {
663
+ process.stderr.write(
664
+ `[claude-code-cloud] session/load: could not seed the vendor's existing event high-water (${err instanceof Error ? err.message : String(err)})
665
+ `
666
+ );
667
+ }
668
+ }
669
+ /** Max `sequence_num` on the session's newest events page (0 when the
670
+ * page is empty). One newest-page GET, no cursor. */
671
+ async #highWaterSeq(vendorSessionId) {
672
+ const res = await this.#api.listEvents(vendorSessionId, {});
673
+ let max = 0;
674
+ for (const event of res.data ?? []) {
675
+ const seq = eventSequence(event);
676
+ if (seq !== null && seq > max) max = seq;
677
+ }
678
+ return max;
679
+ }
680
+ /**
681
+ * Read every event newer than `lastSeq`, in ascending seq order, walking
682
+ * the API's cursor BACKWARD as far as needed. The API serves the NEWEST
683
+ * page with no cursor and pages toward OLDER events via `?cursor=<n>`
684
+ * (sessions-api.ts), so catching up across a >1-page gap means following
685
+ * `resume_cursor` and collecting the seqs above `lastSeq` until a page
686
+ * reaches already-projected history. Capped at {@link OBSERVE_PAGES_LIMIT}
687
+ * pages per call.
688
+ */
689
+ async #collectNewEvents(vendorSessionId, lastSeq) {
690
+ const collected = [];
691
+ let cursor;
692
+ for (let page = 0; page < OBSERVE_PAGES_LIMIT; page += 1) {
693
+ const res = await this.#api.listEvents(
694
+ vendorSessionId,
695
+ cursor ? { cursor } : {}
696
+ );
697
+ const events = res.data ?? [];
698
+ let oldest = null;
699
+ for (const event of events) {
700
+ const seq = eventSequence(event);
701
+ if (seq === null) continue;
702
+ if (oldest === null || seq < oldest) oldest = seq;
703
+ if (seq > lastSeq) collected.push({ seq, event });
704
+ }
705
+ if (events.length === 0 || oldest === null || oldest <= lastSeq + 1) break;
706
+ const next = res.resume_cursor ?? res.next_cursor;
707
+ if (!next || next === cursor) break;
708
+ cursor = next;
709
+ }
710
+ collected.sort((a, b) => a.seq - b.seq);
711
+ return collected;
712
+ }
566
713
  async prompt(params) {
567
714
  const session = this.#sessions.get(params.sessionId);
568
715
  if (!session) throw new Error(`unknown session ${params.sessionId}`);
@@ -580,6 +727,11 @@ var ClaudeCloudAcpAgent = class {
580
727
  });
581
728
  session.vendorSessionId = started.sessionId;
582
729
  session.vendorUrl = started.url;
730
+ await writeCloudSessionMeta({
731
+ vendor: CLOUD_VENDOR_SLUG,
732
+ sessionId: started.sessionId,
733
+ url: started.url
734
+ });
583
735
  await this.#conn.sessionUpdate({
584
736
  sessionId: session.id,
585
737
  update: {
@@ -590,7 +742,9 @@ var ClaudeCloudAcpAgent = class {
590
742
  }
591
743
  }
592
744
  });
745
+ session.turnBaseline = 0;
593
746
  } else {
747
+ session.turnBaseline = await this.#highWaterSeq(session.vendorSessionId);
594
748
  await this.#cli.sendPrompt(session.vendorSessionId, text, {
595
749
  cwd: session.cwd
596
750
  });
@@ -607,12 +761,9 @@ var ClaudeCloudAcpAgent = class {
607
761
  let delay = this.#pollInitialMs;
608
762
  let failures = 0;
609
763
  for (; ; ) {
610
- let page;
764
+ let fresh;
611
765
  try {
612
- page = await this.#api.listEvents(
613
- vendorId,
614
- session.pollCursor ? { cursor: session.pollCursor } : {}
615
- );
766
+ fresh = await this.#collectNewEvents(vendorId, session.lastSeq);
616
767
  } catch (err) {
617
768
  if (!isTransientListEventsError(err) || failures + 1 >= MAX_LIST_EVENTS_FAILURES) {
618
769
  throw err;
@@ -623,16 +774,9 @@ var ClaudeCloudAcpAgent = class {
623
774
  continue;
624
775
  }
625
776
  failures = 0;
626
- if (page.resume_cursor) session.pollCursor = page.resume_cursor;
627
- const fresh = (page.data ?? []).filter((event) => !session.seenEventIds.has(event.event_id)).sort((a, b) => {
628
- if (a.created_at !== b.created_at) {
629
- return a.created_at < b.created_at ? -1 : 1;
630
- }
631
- return a.event_id < b.event_id ? -1 : 1;
632
- });
633
777
  let stopReason = null;
634
- for (const event of fresh) {
635
- rememberSeenEventId(session, event.event_id);
778
+ for (const { seq, event } of fresh) {
779
+ session.lastSeq = Math.max(session.lastSeq, seq);
636
780
  if (event.event_type === "result") {
637
781
  if (resultStopReason(event.payload) === "refusal") {
638
782
  const errText = errorResultText(event.payload);
@@ -646,7 +790,9 @@ var ClaudeCloudAcpAgent = class {
646
790
  for (const update of resultEventUpdates(event.payload)) {
647
791
  await this.#send(session.id, update);
648
792
  }
649
- stopReason = resultStopReason(event.payload);
793
+ if (seq > session.turnBaseline) {
794
+ stopReason = resultStopReason(event.payload);
795
+ }
650
796
  } else if (event.event_type === "user") {
651
797
  for (const update of sdkMessageToUpdates(
652
798
  event.payload
@@ -704,6 +850,6 @@ function main() {
704
850
  runAcpOverStdio();
705
851
  }
706
852
 
707
- export { CLAUDE_CODE_GATEWAY_ENV_UNSET, ClaudeCloudAcpAgent, MAX_LIST_EVENTS_FAILURES, POLL_INITIAL_MS, POLL_MAX_MS, SEEN_EVENT_IDS_LIMIT, SessionsApi, cloudChildEnv, defaultCloudCliRunner, defaultGitRunner, envCredentialSource, isTransientListEventsError, keychainCredentialSource, main, normalizeSessionId, parseAuthStatus, parseCloudStartOutput, preflightAuth, resultEventUpdates, resultStopReason, runAcpOverStdio, sendPrompt, startCloudSession, toCliSessionId, validateRepoSource };
708
- //# sourceMappingURL=chunk-KA4G4O2X.mjs.map
709
- //# sourceMappingURL=chunk-KA4G4O2X.mjs.map
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
@@ -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-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"]}
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { AgentCliHandle, AgentCliRuntime } from '@agentproto/driver-agent-cli';
2
2
  export { AgentCliHandle, AgentCliRuntime } from '@agentproto/driver-agent-cli';
3
- import { Agent, AgentSideConnection, InitializeRequest, InitializeResponse, NewSessionRequest, NewSessionResponse, PromptRequest, PromptResponse, CancelNotification, SetSessionConfigOptionRequest, SetSessionConfigOptionResponse, SetSessionModeRequest, SetSessionModeResponse, SessionUpdate, StopReason } from '@agentclientprotocol/sdk';
3
+ import { Agent, AgentSideConnection, InitializeRequest, InitializeResponse, NewSessionRequest, NewSessionResponse, LoadSessionRequest, LoadSessionResponse, PromptRequest, PromptResponse, CancelNotification, SetSessionConfigOptionRequest, SetSessionConfigOptionResponse, SetSessionModeRequest, SetSessionModeResponse, SessionUpdate, StopReason } from '@agentclientprotocol/sdk';
4
4
 
5
5
  /**
6
6
  * The vendor-client surface (AIP-66 Appendix A): start a Claude Code cloud
@@ -163,12 +163,21 @@ interface CloudSessionEvent {
163
163
  created_at: string;
164
164
  event_id: string;
165
165
  event_type: string;
166
+ /** A STRING of an integer, strictly increasing within the session. The
167
+ * ordering key: parse with `Number()` (see {@link eventSequence}). */
168
+ sequence_num: string;
169
+ /** Who produced the event — "worker" (the vendor's harness) or "client". */
170
+ source?: string;
166
171
  payload: unknown;
167
172
  }
168
173
  interface CloudEventsPage {
169
174
  data: CloudSessionEvent[];
170
- /** Pass back as `cursor` on the next poll to resume after this page. */
175
+ /** The `sequence_num` of the OLDEST event on the page, present on the
176
+ * first (newest) page. Pass back as `?cursor=<n>` to fetch the NEXT
177
+ * OLDER page — the cursor pages BACKWARD in time, never forward. */
171
178
  resume_cursor?: string;
179
+ /** Alias for {@link resume_cursor}, seen on the first page only. */
180
+ next_cursor?: string;
172
181
  }
173
182
  /** GET /v1/code/sessions/{id} — wrapped in `response_shape`. */
174
183
  interface CloudSessionState {
@@ -230,8 +239,9 @@ declare class SessionsApi {
230
239
  /** GET /v1/code/sessions/{id} */
231
240
  getSession(id: string): Promise<CloudGetSessionResponse>;
232
241
  /**
233
- * GET /v1/code/sessions/{id}/events — newest first. Pass the previous
234
- * page's `resume_cursor` as `cursor` to resume after it.
242
+ * GET /v1/code/sessions/{id}/events — newest first. With no `cursor` this
243
+ * returns the NEWEST page; pass the page's `resume_cursor` (the oldest
244
+ * event's `sequence_num`) as `cursor` to fetch the next OLDER page.
235
245
  */
236
246
  listEvents(id: string, opts?: {
237
247
  cursor?: string;
@@ -253,6 +263,13 @@ declare class SessionsApi {
253
263
  * (AIP-66 §3) BEFORE any vendor side effect.
254
264
  * - first `session/prompt` → `claude --cloud "<prompt>"` (start), later
255
265
  * ones → `claude -p … --cloud <id>` (send-only).
266
+ * - `session/load` RE-ATTACHES to the vendor session id the host
267
+ * persisted on `meta.cloud.sessionId` (AIP-66 §5): the adopted id makes
268
+ * the next prompt a `sendPrompt` — the relay never starts a replacement
269
+ * vendor session.
270
+ * - the learned identity (`{ vendor, sessionId, url }`) is reported to
271
+ * the host through the meta file named by `AGENTPROTO_CLOUD_SESSION_META_FILE`
272
+ * (meta-file.ts) — never a credential (AIP-66 §8).
256
273
  * - the turn is then observed via the sessions API: events are mapped
257
274
  * with @agentproto/adapter-claude-sdk's stream-json → ACP mappers
258
275
  * (the payloads ARE Claude Code stream-json SDK messages — reused, not
@@ -313,6 +330,20 @@ declare class ClaudeCloudAcpAgent implements Agent {
313
330
  initialize(_params: InitializeRequest): Promise<InitializeResponse>;
314
331
  authenticate(): Promise<void>;
315
332
  newSession(params: NewSessionRequest): Promise<NewSessionResponse>;
333
+ /**
334
+ * AIP-66 §5 re-attach: ADOPT the vendor session id the host persisted on
335
+ * `meta.cloud.sessionId` as this ACP session's vendor session. No vendor
336
+ * side effect happens here — the next `session/prompt` goes through
337
+ * `sendPrompt` (`claude -p … --cloud <id>`), never `startCloudSession`,
338
+ * so a resumed relay can never replace the vendor's session with a new
339
+ * one. The adopted id is also reported back to the host's meta file so a
340
+ * re-attach against a fresh config dir still carries the §5 mapping.
341
+ *
342
+ * Fails closed on an id the vendor could never own (e.g. the ACP uuid of
343
+ * a spawn whose vendor id was never learned): no session is started in
344
+ * its place.
345
+ */
346
+ loadSession(params: LoadSessionRequest): Promise<LoadSessionResponse>;
316
347
  prompt(params: PromptRequest): Promise<PromptResponse>;
317
348
  /** Unsupported: the vendor exposes no interrupt verb (AIP-66 §6). Throwing
318
349
  * reports it — the in-flight poll loop is NOT aborted (we cannot stop the
@@ -328,6 +359,55 @@ declare class ClaudeCloudAcpAgent implements Agent {
328
359
  /** Boot the ACP server over stdio — what bin/claude-code-cloud-acp.mjs runs. */
329
360
  declare function runAcpOverStdio(deps?: ClaudeCloudAcpDeps): AgentSideConnection;
330
361
 
362
+ /**
363
+ * AIP-66 §5/§8 — how this relay REPORTS the learned vendor session
364
+ * identity to the host.
365
+ *
366
+ * The host (the runtime's `session-spawn.ts` + `cloud-vendors.ts`) hands
367
+ * the relay the path of a file inside the session's isolated config dir via
368
+ * `AGENTPROTO_CLOUD_SESSION_META_FILE`. Once the vendor has returned a
369
+ * session id — after `claude --cloud` prints it, or when `session/load`
370
+ * adopts the id persisted on `meta.cloud.sessionId` — the relay writes
371
+ * exactly the three §5 fields `{ vendor, sessionId, url }` there, and the
372
+ * host polls that file (`watchCloudSessionMeta`) to stamp
373
+ * `meta.cloud = { vendor, sessionId, url }` onto the descriptor.
374
+ *
375
+ * ONLY those three fields are ever written: the vendor's OAuth credential
376
+ * never enters this file, logs or events (AIP-66 §8). The write is
377
+ * best-effort and atomic (temp file + rename), so a failed side-file write
378
+ * can never sink the turn that learned the id — the host's poll simply
379
+ * keeps watching.
380
+ */
381
+ /** Env var carrying the absolute path of the meta file. Mirrors the
382
+ * runtime's `CLOUD_SESSION_META_FILE_ENV` (cloud-vendors.ts) — the two
383
+ * must stay byte-identical or the relay writes where nobody reads. */
384
+ declare const CLOUD_SESSION_META_FILE_ENV = "AGENTPROTO_CLOUD_SESSION_META_FILE";
385
+ /** The vendor slug this adapter relays to (AIP-66 §2 `CloudVendor.slug`,
386
+ * registry entry `anthropic` → adapter `claude-code-cloud`). */
387
+ declare const CLOUD_VENDOR_SLUG = "anthropic";
388
+ /** The §5 mapping the relay reports. NEVER carries a credential. */
389
+ interface CloudSessionMetaReport {
390
+ vendor: string;
391
+ /** Vendor session id — CLI spelling (`session_<id>`). */
392
+ sessionId: string;
393
+ /** Session URL when known (the start path prints it; a re-attach may
394
+ * inherit it from the file already on disk). */
395
+ url?: string;
396
+ }
397
+ /**
398
+ * Write `{ vendor, sessionId, url }` to the meta file the host named in
399
+ * `AGENTPROTO_CLOUD_SESSION_META_FILE`. Returns the path written, or null
400
+ * when the env var is unset or the write failed (best-effort: the host's
401
+ * poll retries, and a cloud turn must never fail over a side file).
402
+ *
403
+ * A re-attach (`session/load`) carries no URL — when the id on disk matches
404
+ * the one being reported, the existing `url` is preserved so the host's
405
+ * later read keeps the full §5 mapping.
406
+ */
407
+ declare function writeCloudSessionMeta(meta: CloudSessionMetaReport, opts?: {
408
+ env?: Record<string, string | undefined>;
409
+ }): Promise<string | null>;
410
+
331
411
  /**
332
412
  * AIP-66 §3 (repo source): a managed cloud agent runs on a git remote and
333
413
  * ref — never on an uploaded working tree. The host MUST refuse the spawn
@@ -371,4 +451,4 @@ declare const CLOUD_REFUSED_SPAWN_FIELDS: readonly ["sandbox", "worktree", "comm
371
451
  declare const claudeCodeCloud: AgentCliHandle;
372
452
  declare function claudeCodeCloudRuntime(): AgentCliRuntime;
373
453
 
374
- export { type AuthStatus, CLAUDE_CODE_GATEWAY_ENV_UNSET, CLOUD_REFUSED_SPAWN_FIELDS, ClaudeCloudAcpAgent, type ClaudeCloudAcpDeps, type CloudCliDeps, type CloudCliRunner, type CloudCredential, type CloudEventsClient, type CloudEventsPage, type CloudGetSessionResponse, type CloudSessionEvent, type CloudSessionState, type CloudSessionSummary, type CredentialSource, type GitRunner, POLL_INITIAL_MS, POLL_MAX_MS, type RunOpts, type RunResult, SessionsApi, type SessionsApiOptions, type StartedCloudSession, claudeCodeCloud, claudeCodeCloudRuntime, cloudChildEnv, defaultCloudCliRunner, defaultGitRunner, envCredentialSource, keychainCredentialSource, normalizeSessionId, parseAuthStatus, parseCloudStartOutput, preflightAuth, resultEventUpdates, resultStopReason, runAcpOverStdio, sendPrompt, startCloudSession, toCliSessionId, validateRepoSource };
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 };
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- export { CLAUDE_CODE_GATEWAY_ENV_UNSET, ClaudeCloudAcpAgent, POLL_INITIAL_MS, POLL_MAX_MS, SessionsApi, cloudChildEnv, defaultCloudCliRunner, defaultGitRunner, envCredentialSource, keychainCredentialSource, normalizeSessionId, parseAuthStatus, parseCloudStartOutput, preflightAuth, resultEventUpdates, resultStopReason, runAcpOverStdio, sendPrompt, startCloudSession, toCliSessionId, validateRepoSource } from './chunk-KA4G4O2X.mjs';
1
+ export { CLAUDE_CODE_GATEWAY_ENV_UNSET, CLOUD_SESSION_META_FILE_ENV, CLOUD_VENDOR_SLUG, ClaudeCloudAcpAgent, 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';
2
2
  import { fileURLToPath } from 'url';
3
3
  import { defineAgentCli, createAgentCliRuntime } from '@agentproto/driver-agent-cli';
4
4
 
@@ -78,8 +78,9 @@ var claudeCodeCloud = defineAgentCli({
78
78
  sub_agents: false,
79
79
  file_io: true,
80
80
  multimodal: false,
81
- // Re-attach is via the persisted vendor session id (AIP-66 §5), not an
82
- // ACP session/load replay.
81
+ // Re-attach is via the persisted vendor session id (AIP-66 §5): the
82
+ // host hands it back as ACP `session/load`, which ADOPTS it — the next
83
+ // prompt is a send to that same vendor session, never a new start.
83
84
  resumable: true,
84
85
  // Send-only prompting: the CLI never returns the reply on the prompt
85
86
  // path; the reply is observed via the sessions API.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;AA4BA,IAAM,MAAA,GAAS,aAAA;AAAA,EACb,IAAI,GAAA,CAAI,kCAAA,EAAoC,MAAA,CAAA,IAAA,CAAY,GAAG;AAC7D,CAAA;AAMO,IAAM,0BAAA,GAA6B;AAAA,EACxC,SAAA;AAAA,EACA,UAAA;AAAA,EACA,gBAAA;AAAA,EACA,YAAA;AAAA,EACA,aAAA;AAAA,EACA,SAAA;AAAA,EACA,SAAA;AAAA,EACA,UAAA;AAAA,EACA;AACF;AAEO,IAAM,kBAAkC,cAAA,CAAe;AAAA,EAC5D,IAAA,EAAM,mBAAA;AAAA,EACN,EAAA,EAAI,mBAAA;AAAA,EACJ,WAAA,EACE,ohBAAA;AAAA,EAQF,OAAA,EAAS,OAAA;AAAA,EACT,GAAA,EAAK,MAAA;AAAA,EACL,QAAA,EAAU,CAAC,MAAM,CAAA;AAAA,EACjB,OAAA,EAAS;AAAA,IACP;AAAA,MACE,MAAA,EAAQ,KAAA;AAAA,MACR,OAAA,EAAS,uCAAA;AAAA,MACT,MAAA,EAAQ;AAAA;AACV,GACF;AAAA;AAAA;AAAA;AAAA,EAIA,aAAA,EAAe;AAAA,IACb,GAAA,EAAK,kBAAA;AAAA,IACL,KAAA,EAAO,sBAAA;AAAA,IACP,KAAA,EAAO,WAAA;AAAA,IACP,UAAA,EAAY;AAAA,GACd;AAAA;AAAA;AAAA;AAAA;AAAA,EAKA,IAAA,EAAM;AAAA,IACJ,GAAA,EAAK,wBAAA;AAAA,IACL,KAAA,EAAO;AAAA,MACL,GAAA,EAAK,mBAAA;AAAA,MACL,WAAA,EAAa;AAAA;AACf,GACF;AAAA;AAAA,EAEA,OAAA,EACE,kLAAA;AAAA,EAGF,QAAA,EAAU,KAAA;AAAA,EACV,GAAA,EAAK,wBAAA;AAAA,EACL,OAAA,EAAS;AAAA;AAAA;AAAA,IAGP,IAAA,EAAM,YAAA;AAAA,IACN,eAAA,EAAiB,IAAA;AAAA,IACjB,iBAAA,EAAmB;AAAA,GACrB;AAAA;AAAA;AAAA;AAAA;AAAA,EAKA,YAAA,EAAc;AAAA;AAAA,IAEZ,SAAA,EAAW,IAAA;AAAA;AAAA;AAAA,IAGX,UAAA,EAAY,IAAA;AAAA,IACZ,UAAA,EAAY,KAAA;AAAA,IACZ,OAAA,EAAS,IAAA;AAAA,IACT,UAAA,EAAY,KAAA;AAAA;AAAA;AAAA,IAGZ,SAAA,EAAW,IAAA;AAAA;AAAA;AAAA,IAGX,aAAA,EAAe;AAAA,GACjB;AAAA,EACA,IAAA,EAAM;AAAA,IACJ,aAAA;AAAA,IACA,WAAA;AAAA,IACA,OAAA;AAAA,IACA,QAAA;AAAA,IACA,KAAA;AAAA,IACA,eAAA;AAAA,IACA;AAAA,GACF;AAAA,EACA,QAAA,EAAU;AAAA,IACR,GAAA,EAAK,EAAA;AAAA;AAAA,IAEL,OAAA,EAAS,aAAA;AAAA,IACT,KAAA,EAAO;AAAA,MACL,MAAA,EAAQ;AAAA,KACV;AAAA;AAAA,IAEA,kBAAA,EAAoB,CAAC,GAAG,0BAA0B;AAAA;AAEtD,CAAC;AAEM,SAAS,sBAAA,GAA0C;AACxD,EAAA,OAAO,sBAAsB,eAAe,CAAA;AAC9C","file":"index.mjs","sourcesContent":["/**\n * @agentproto/adapter-claude-code-cloud — AIP-66 managed cloud agent adapter\n * for Anthropic Claude Code cloud sessions.\n *\n * Unlike `@agentproto/adapter-claude-code` (local harness, host machine),\n * this adapter relays a session the VENDOR hosts end to end: the vendor\n * boots the machine, runs Claude Code in it, and exposes the session\n * through `claude --cloud` / `claude -p --cloud` plus the undocumented\n * Claude Code sessions API. No agentproto daemon runs inside; the host\n * controls neither the machine nor the harness — so this manifest is\n * deliberately smaller and refuses the spawn fields that could never take\n * effect (AIP-66 §4).\n *\n * import { claudeCodeCloud } from \"@agentproto/adapter-claude-code-cloud\"\n */\n\nimport { fileURLToPath } from \"node:url\"\nimport {\n createAgentCliRuntime,\n defineAgentCli,\n type AgentCliHandle,\n type AgentCliRuntime,\n} from \"@agentproto/driver-agent-cli\"\n\n// Self-locating: the built handle spawns `node <this-pkg>/bin/…\n// claude-code-cloud-acp.mjs`. From dist/index.mjs the bin sits one level up,\n// so the same build works whether the daemon resolves this package from\n// node_modules or a user runs the published bin directly.\nconst acpBin = fileURLToPath(\n new URL(\"../bin/claude-code-cloud-acp.mjs\", import.meta.url),\n)\n\n// AIP-66 §4 refused spawn fields — no meaning for a vendor-owned harness, so\n// the host MUST refuse a cloud spawn that sets any of them rather than\n// ignore them. Documented here (and in CLAUDE-CODE-CLOUD.md) so the runtime\n// gate and users share one list.\nexport const CLOUD_REFUSED_SPAWN_FIELDS = [\n \"sandbox\",\n \"worktree\",\n \"commandSandbox\",\n \"mcpServers\",\n \"daemonMount\",\n \"bundles\",\n \"browser\",\n \"appServe\",\n \"inference\",\n] as const\n\nexport const claudeCodeCloud: AgentCliHandle = defineAgentCli({\n name: \"claude-code-cloud\",\n id: \"claude-code-cloud\",\n description:\n \"AIP-66 managed cloud agent adapter for Anthropic Claude Code cloud \" +\n \"sessions. The vendor owns the machine and the harness: starts via \" +\n \"`claude --cloud` (TTY), prompts via `claude -p --cloud <id>`, observes \" +\n \"via the Claude Code sessions API, projected onto stdio ACP. Refuses \" +\n \"the AIP-66 §4 spawn fields (sandbox, worktree, commandSandbox, \" +\n \"mcpServers, daemonMount, bundles, browser, appServe, inference) — the \" +\n \"vendor can never apply them. Requires a claude.ai sign-in (API-key \" +\n \"auth is refused) and a clean, pushed git checkout.\",\n version: \"0.1.0\",\n bin: \"node\",\n bin_args: [acpBin],\n install: [\n {\n method: \"npm\",\n package: \"@agentproto/adapter-claude-code-cloud\",\n global: true,\n },\n ],\n // Presence probe against the vendor client this adapter relays to — the\n // pinned floor is the oldest CLI observed to support `--cloud` / the\n // sessions API (AIP-66 Appendix A: 2.1.296–2.1.299).\n version_check: {\n cmd: \"claude --version\",\n parse: \"(\\\\d+\\\\.\\\\d+\\\\.\\\\d+)\",\n range: \">=2.1.296\",\n timeout_ms: 15_000,\n },\n // Auth is the user's OWN claude.ai login inside the claude CLI (keychain\n // on macOS) — never an injected env credential (AIP-66 §8). No `state.env`\n // because an API-key env would be scrubbed, not consumed; the preflight\n // refuses an api_key-authenticated CLI outright.\n auth: {\n ref: \"./CLAUDE-CODE-CLOUD.md\",\n login: {\n cmd: \"claude auth login\",\n interactive: true,\n },\n },\n // The machine is the vendor's; there is no host-side sandbox to describe.\n sandbox:\n \"Managed cloud (AIP-66): the vendor boots the machine and runs Claude \" +\n \"Code on it. No agentproto daemon runs inside; the session URL is \" +\n \"surfaced so the user can inspect what ran.\",\n protocol: \"acp\",\n acp: \"./CLAUDE-CODE-CLOUD.md\",\n session: {\n // One agentproto session = one vendor cloud session (AIP-66 §5);\n // follow-up turns send to the same vendor session.\n mode: \"persistent\",\n idle_timeout_ms: 1_800_000,\n context_carryover: true,\n },\n // NO `models` menu: the vendor picks and bills the model inside its own\n // harness; the host has no model to select or route (AIP-66 §4 — `model`\n // is only meaningful when the vendor client accepts it, and this CLI's\n // cloud path exposes no model flag).\n capabilities: {\n // Turns stream back as ACP updates while the vendor runs them.\n streaming: true,\n // The vendor harness's own tools (Read/Edit/Bash/…) surface as ACP\n // tool_call / tool_call_update updates from the session's events.\n tool_calls: true,\n sub_agents: false,\n file_io: true,\n multimodal: false,\n // Re-attach is via the persisted vendor session id (AIP-66 §5), not an\n // ACP session/load replay.\n resumable: true,\n // Send-only prompting: the CLI never returns the reply on the prompt\n // path; the reply is observed via the sessions API.\n bidirectional: false,\n },\n tags: [\n \"claude-code\",\n \"anthropic\",\n \"cloud\",\n \"aip-66\",\n \"acp\",\n \"agent-runtime\",\n \"coding\",\n ],\n metadata: {\n aip: 66,\n // The harness the vendor runs (AIP-66 §2 CloudVendor.harnesses).\n harness: \"claude-code\",\n cloud: {\n vendor: \"anthropic\",\n },\n // AIP-66 §4 refused spawn fields, machine-readable for the host gate.\n refusedSpawnFields: [...CLOUD_REFUSED_SPAWN_FIELDS],\n },\n})\n\nexport function claudeCodeCloudRuntime(): AgentCliRuntime {\n return createAgentCliRuntime(claudeCodeCloud)\n}\n\nexport {\n ClaudeCloudAcpAgent,\n runAcpOverStdio,\n resultEventUpdates,\n resultStopReason,\n POLL_INITIAL_MS,\n POLL_MAX_MS,\n type ClaudeCloudAcpDeps,\n type CloudCliDeps,\n type CloudEventsClient,\n} from \"./acp-server.js\"\nexport {\n cloudChildEnv,\n defaultCloudCliRunner,\n parseAuthStatus,\n parseCloudStartOutput,\n preflightAuth,\n sendPrompt,\n startCloudSession,\n CLAUDE_CODE_GATEWAY_ENV_UNSET,\n type AuthStatus,\n type CloudCliRunner,\n type RunOpts,\n type RunResult,\n type StartedCloudSession,\n} from \"./cli.js\"\nexport {\n SessionsApi,\n envCredentialSource,\n keychainCredentialSource,\n normalizeSessionId,\n toCliSessionId,\n type CloudCredential,\n type CloudEventsPage,\n type CloudGetSessionResponse,\n type CloudSessionEvent,\n type CloudSessionState,\n type CloudSessionSummary,\n type CredentialSource,\n type SessionsApiOptions,\n} from \"./sessions-api.js\"\nexport {\n validateRepoSource,\n defaultGitRunner,\n type GitRunner,\n} from \"./repo-source.js\"\nexport type { AgentCliHandle, AgentCliRuntime }\n"]}
1
+ {"version":3,"sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;AA4BA,IAAM,MAAA,GAAS,aAAA;AAAA,EACb,IAAI,GAAA,CAAI,kCAAA,EAAoC,MAAA,CAAA,IAAA,CAAY,GAAG;AAC7D,CAAA;AAMO,IAAM,0BAAA,GAA6B;AAAA,EACxC,SAAA;AAAA,EACA,UAAA;AAAA,EACA,gBAAA;AAAA,EACA,YAAA;AAAA,EACA,aAAA;AAAA,EACA,SAAA;AAAA,EACA,SAAA;AAAA,EACA,UAAA;AAAA,EACA;AACF;AAEO,IAAM,kBAAkC,cAAA,CAAe;AAAA,EAC5D,IAAA,EAAM,mBAAA;AAAA,EACN,EAAA,EAAI,mBAAA;AAAA,EACJ,WAAA,EACE,ohBAAA;AAAA,EAQF,OAAA,EAAS,OAAA;AAAA,EACT,GAAA,EAAK,MAAA;AAAA,EACL,QAAA,EAAU,CAAC,MAAM,CAAA;AAAA,EACjB,OAAA,EAAS;AAAA,IACP;AAAA,MACE,MAAA,EAAQ,KAAA;AAAA,MACR,OAAA,EAAS,uCAAA;AAAA,MACT,MAAA,EAAQ;AAAA;AACV,GACF;AAAA;AAAA;AAAA;AAAA,EAIA,aAAA,EAAe;AAAA,IACb,GAAA,EAAK,kBAAA;AAAA,IACL,KAAA,EAAO,sBAAA;AAAA,IACP,KAAA,EAAO,WAAA;AAAA,IACP,UAAA,EAAY;AAAA,GACd;AAAA;AAAA;AAAA;AAAA;AAAA,EAKA,IAAA,EAAM;AAAA,IACJ,GAAA,EAAK,wBAAA;AAAA,IACL,KAAA,EAAO;AAAA,MACL,GAAA,EAAK,mBAAA;AAAA,MACL,WAAA,EAAa;AAAA;AACf,GACF;AAAA;AAAA,EAEA,OAAA,EACE,kLAAA;AAAA,EAGF,QAAA,EAAU,KAAA;AAAA,EACV,GAAA,EAAK,wBAAA;AAAA,EACL,OAAA,EAAS;AAAA;AAAA;AAAA,IAGP,IAAA,EAAM,YAAA;AAAA,IACN,eAAA,EAAiB,IAAA;AAAA,IACjB,iBAAA,EAAmB;AAAA,GACrB;AAAA;AAAA;AAAA;AAAA;AAAA,EAKA,YAAA,EAAc;AAAA;AAAA,IAEZ,SAAA,EAAW,IAAA;AAAA;AAAA;AAAA,IAGX,UAAA,EAAY,IAAA;AAAA,IACZ,UAAA,EAAY,KAAA;AAAA,IACZ,OAAA,EAAS,IAAA;AAAA,IACT,UAAA,EAAY,KAAA;AAAA;AAAA;AAAA;AAAA,IAIZ,SAAA,EAAW,IAAA;AAAA;AAAA;AAAA,IAGX,aAAA,EAAe;AAAA,GACjB;AAAA,EACA,IAAA,EAAM;AAAA,IACJ,aAAA;AAAA,IACA,WAAA;AAAA,IACA,OAAA;AAAA,IACA,QAAA;AAAA,IACA,KAAA;AAAA,IACA,eAAA;AAAA,IACA;AAAA,GACF;AAAA,EACA,QAAA,EAAU;AAAA,IACR,GAAA,EAAK,EAAA;AAAA;AAAA,IAEL,OAAA,EAAS,aAAA;AAAA,IACT,KAAA,EAAO;AAAA,MACL,MAAA,EAAQ;AAAA,KACV;AAAA;AAAA,IAEA,kBAAA,EAAoB,CAAC,GAAG,0BAA0B;AAAA;AAEtD,CAAC;AAEM,SAAS,sBAAA,GAA0C;AACxD,EAAA,OAAO,sBAAsB,eAAe,CAAA;AAC9C","file":"index.mjs","sourcesContent":["/**\n * @agentproto/adapter-claude-code-cloud — AIP-66 managed cloud agent adapter\n * for Anthropic Claude Code cloud sessions.\n *\n * Unlike `@agentproto/adapter-claude-code` (local harness, host machine),\n * this adapter relays a session the VENDOR hosts end to end: the vendor\n * boots the machine, runs Claude Code in it, and exposes the session\n * through `claude --cloud` / `claude -p --cloud` plus the undocumented\n * Claude Code sessions API. No agentproto daemon runs inside; the host\n * controls neither the machine nor the harness — so this manifest is\n * deliberately smaller and refuses the spawn fields that could never take\n * effect (AIP-66 §4).\n *\n * import { claudeCodeCloud } from \"@agentproto/adapter-claude-code-cloud\"\n */\n\nimport { fileURLToPath } from \"node:url\"\nimport {\n createAgentCliRuntime,\n defineAgentCli,\n type AgentCliHandle,\n type AgentCliRuntime,\n} from \"@agentproto/driver-agent-cli\"\n\n// Self-locating: the built handle spawns `node <this-pkg>/bin/…\n// claude-code-cloud-acp.mjs`. From dist/index.mjs the bin sits one level up,\n// so the same build works whether the daemon resolves this package from\n// node_modules or a user runs the published bin directly.\nconst acpBin = fileURLToPath(\n new URL(\"../bin/claude-code-cloud-acp.mjs\", import.meta.url),\n)\n\n// AIP-66 §4 refused spawn fields — no meaning for a vendor-owned harness, so\n// the host MUST refuse a cloud spawn that sets any of them rather than\n// ignore them. Documented here (and in CLAUDE-CODE-CLOUD.md) so the runtime\n// gate and users share one list.\nexport const CLOUD_REFUSED_SPAWN_FIELDS = [\n \"sandbox\",\n \"worktree\",\n \"commandSandbox\",\n \"mcpServers\",\n \"daemonMount\",\n \"bundles\",\n \"browser\",\n \"appServe\",\n \"inference\",\n] as const\n\nexport const claudeCodeCloud: AgentCliHandle = defineAgentCli({\n name: \"claude-code-cloud\",\n id: \"claude-code-cloud\",\n description:\n \"AIP-66 managed cloud agent adapter for Anthropic Claude Code cloud \" +\n \"sessions. The vendor owns the machine and the harness: starts via \" +\n \"`claude --cloud` (TTY), prompts via `claude -p --cloud <id>`, observes \" +\n \"via the Claude Code sessions API, projected onto stdio ACP. Refuses \" +\n \"the AIP-66 §4 spawn fields (sandbox, worktree, commandSandbox, \" +\n \"mcpServers, daemonMount, bundles, browser, appServe, inference) — the \" +\n \"vendor can never apply them. Requires a claude.ai sign-in (API-key \" +\n \"auth is refused) and a clean, pushed git checkout.\",\n version: \"0.1.0\",\n bin: \"node\",\n bin_args: [acpBin],\n install: [\n {\n method: \"npm\",\n package: \"@agentproto/adapter-claude-code-cloud\",\n global: true,\n },\n ],\n // Presence probe against the vendor client this adapter relays to — the\n // pinned floor is the oldest CLI observed to support `--cloud` / the\n // sessions API (AIP-66 Appendix A: 2.1.296–2.1.299).\n version_check: {\n cmd: \"claude --version\",\n parse: \"(\\\\d+\\\\.\\\\d+\\\\.\\\\d+)\",\n range: \">=2.1.296\",\n timeout_ms: 15_000,\n },\n // Auth is the user's OWN claude.ai login inside the claude CLI (keychain\n // on macOS) — never an injected env credential (AIP-66 §8). No `state.env`\n // because an API-key env would be scrubbed, not consumed; the preflight\n // refuses an api_key-authenticated CLI outright.\n auth: {\n ref: \"./CLAUDE-CODE-CLOUD.md\",\n login: {\n cmd: \"claude auth login\",\n interactive: true,\n },\n },\n // The machine is the vendor's; there is no host-side sandbox to describe.\n sandbox:\n \"Managed cloud (AIP-66): the vendor boots the machine and runs Claude \" +\n \"Code on it. No agentproto daemon runs inside; the session URL is \" +\n \"surfaced so the user can inspect what ran.\",\n protocol: \"acp\",\n acp: \"./CLAUDE-CODE-CLOUD.md\",\n session: {\n // One agentproto session = one vendor cloud session (AIP-66 §5);\n // follow-up turns send to the same vendor session.\n mode: \"persistent\",\n idle_timeout_ms: 1_800_000,\n context_carryover: true,\n },\n // NO `models` menu: the vendor picks and bills the model inside its own\n // harness; the host has no model to select or route (AIP-66 §4 — `model`\n // is only meaningful when the vendor client accepts it, and this CLI's\n // cloud path exposes no model flag).\n capabilities: {\n // Turns stream back as ACP updates while the vendor runs them.\n streaming: true,\n // The vendor harness's own tools (Read/Edit/Bash/…) surface as ACP\n // tool_call / tool_call_update updates from the session's events.\n tool_calls: true,\n sub_agents: false,\n file_io: true,\n multimodal: false,\n // Re-attach is via the persisted vendor session id (AIP-66 §5): the\n // host hands it back as ACP `session/load`, which ADOPTS it — the next\n // prompt is a send to that same vendor session, never a new start.\n resumable: true,\n // Send-only prompting: the CLI never returns the reply on the prompt\n // path; the reply is observed via the sessions API.\n bidirectional: false,\n },\n tags: [\n \"claude-code\",\n \"anthropic\",\n \"cloud\",\n \"aip-66\",\n \"acp\",\n \"agent-runtime\",\n \"coding\",\n ],\n metadata: {\n aip: 66,\n // The harness the vendor runs (AIP-66 §2 CloudVendor.harnesses).\n harness: \"claude-code\",\n cloud: {\n vendor: \"anthropic\",\n },\n // AIP-66 §4 refused spawn fields, machine-readable for the host gate.\n refusedSpawnFields: [...CLOUD_REFUSED_SPAWN_FIELDS],\n },\n})\n\nexport function claudeCodeCloudRuntime(): AgentCliRuntime {\n return createAgentCliRuntime(claudeCodeCloud)\n}\n\nexport {\n ClaudeCloudAcpAgent,\n runAcpOverStdio,\n resultEventUpdates,\n resultStopReason,\n POLL_INITIAL_MS,\n POLL_MAX_MS,\n type ClaudeCloudAcpDeps,\n type CloudCliDeps,\n type CloudEventsClient,\n} from \"./acp-server.js\"\nexport {\n CLOUD_SESSION_META_FILE_ENV,\n CLOUD_VENDOR_SLUG,\n writeCloudSessionMeta,\n type CloudSessionMetaReport,\n} from \"./meta-file.js\"\nexport {\n cloudChildEnv,\n 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"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentproto/adapter-claude-code-cloud",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
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",
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/sessions-api.ts","../src/cli.ts","../src/repo-source.ts","../src/acp-server.ts"],"names":["execFileAsync","promisify","execFile"],"mappings":"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","file":"chunk-KA4G4O2X.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 payload: unknown\n}\n\nexport interface CloudEventsPage {\n data: CloudSessionEvent[]\n /** Pass back as `cursor` on the next poll to resume after this page. */\n resume_cursor?: string\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. Pass the previous\n * page's `resume_cursor` as `cursor` to resume after it.\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 §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 * - 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 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 keychainCredentialSource,\n type CloudEventsPage,\n type CredentialSource,\n} from \"./sessions-api.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/** 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 /** Events page cursor across polls; null until the API hands one back. */\n pollCursor: string | null\n /** Event ids already projected this turn (and previous turns) — the\n * newest-first first page overlaps turns, so dedup is mandatory. Bounded:\n * ids are remembered in projection order (oldest first) and the OLDEST\n * are evicted past {@link SEEN_EVENT_IDS_LIMIT}, so the set cannot grow\n * for the life of the session. */\n readonly seenEventIds: Set<string>\n promptInFlight: boolean\n}\n\n/**\n * Cap on remembered event ids per session. Dedup spans turns (an old\n * `result` must not end a new turn), but the session may live indefinitely —\n * so the set is bounded, evicting in insertion order: those ids were\n * projected on the earliest polls, behind the pagination cursor the API\n * serves forward from.\n */\nexport const SEEN_EVENT_IDS_LIMIT = 500\n\n/** Record a projected event id, evicting the oldest past the cap. */\nfunction rememberSeenEventId(session: CloudSessionState, id: string): void {\n const seen = session.seenEventIds\n seen.add(id)\n while (seen.size > SEEN_EVENT_IDS_LIMIT) {\n const oldest = seen.values().next()\n if (oldest.done) break\n seen.delete(oldest.value)\n }\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 // Sessions live in the vendor's cloud; re-attach is via the vendor\n // id, not an ACP session/load replay (AIP-66 §5).\n loadSession: false,\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 pollCursor: null,\n seenEventIds: new Set(),\n promptInFlight: false,\n })\n return { sessionId: id }\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 // 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 } else {\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 page: CloudEventsPage\n try {\n page = await this.#api.listEvents(\n vendorId,\n session.pollCursor ? { cursor: session.pollCursor } : {},\n )\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 if (page.resume_cursor) session.pollCursor = page.resume_cursor\n const fresh = (page.data ?? [])\n .filter(event => !session.seenEventIds.has(event.event_id))\n .sort((a, b) => {\n if (a.created_at !== b.created_at) {\n return a.created_at < b.created_at ? -1 : 1\n }\n return a.event_id < b.event_id ? -1 : 1\n })\n let stopReason: StopReason | null = null\n for (const event of fresh) {\n rememberSeenEventId(session, event.event_id)\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 stopReason = resultStopReason(event.payload)\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; they still consume a seen-id above.\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"]}