@agentproto/adapter-claude-code-cloud 0.0.0-stage → 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.
@@ -0,0 +1,454 @@
1
+ import { AgentCliHandle, AgentCliRuntime } from '@agentproto/driver-agent-cli';
2
+ export { AgentCliHandle, AgentCliRuntime } from '@agentproto/driver-agent-cli';
3
+ import { Agent, AgentSideConnection, InitializeRequest, InitializeResponse, NewSessionRequest, NewSessionResponse, LoadSessionRequest, LoadSessionResponse, PromptRequest, PromptResponse, CancelNotification, SetSessionConfigOptionRequest, SetSessionConfigOptionResponse, SetSessionModeRequest, SetSessionModeResponse, SessionUpdate, StopReason } from '@agentclientprotocol/sdk';
4
+
5
+ /**
6
+ * The vendor-client surface (AIP-66 Appendix A): start a Claude Code cloud
7
+ * session under a PTY, send follow-ups headlessly, and preflight the
8
+ * claude.ai login. The CLI is the only supported way to CREATE and PROMPT a
9
+ * cloud session — the sessions API (sessions-api.ts) is observe-only.
10
+ *
11
+ * Every child process runs with ANTHROPIC_API_KEY and the Claude Code
12
+ * gateway/redirect toggles deleted from its env (AIP-66 §8): a leftover
13
+ * toggle or API key would make the CLI authenticate a different way and
14
+ * refuse (or worse, re-route) the cloud call. The token the CLI reads from
15
+ * the user's own login is never touched, logged or persisted here.
16
+ *
17
+ * The binary runner is injectable so tests can drive every path — auth
18
+ * preflight, trust prompt, output parsing — from fixtures without a live
19
+ * claude CLI or a real PTY.
20
+ */
21
+ /** Env keys deleted from every claude child this adapter spawns (AIP-66 §8). */
22
+ declare const CLAUDE_CODE_GATEWAY_ENV_UNSET: readonly string[];
23
+ /** Copy `base` with every {@link CLAUDE_CODE_GATEWAY_ENV_UNSET} key deleted. */
24
+ declare function cloudChildEnv(base?: Record<string, string | undefined>): Record<string, string>;
25
+ interface RunResult {
26
+ code: number;
27
+ stdout: string;
28
+ stderr: string;
29
+ }
30
+ interface RunOpts {
31
+ cwd: string;
32
+ env: Record<string, string>;
33
+ timeoutMs?: number;
34
+ /** "ignore" detaches stdin so a non-interactive call can never TTY-block. */
35
+ stdin?: "ignore";
36
+ }
37
+ interface PtyHandle {
38
+ write(data: string): void;
39
+ result: Promise<{
40
+ code: number;
41
+ output: string;
42
+ }>;
43
+ }
44
+ interface PtyRunOpts extends RunOpts {
45
+ onData?: (chunk: string) => void;
46
+ }
47
+ /** What {@link startCloudSession} / {@link sendPrompt} drive. Tests inject a
48
+ * fake; production uses {@link defaultCloudCliRunner}. */
49
+ interface CloudCliRunner {
50
+ run(cmd: string, args: string[], opts: RunOpts): Promise<RunResult>;
51
+ runPty(cmd: string, args: string[], opts: PtyRunOpts): PtyHandle;
52
+ }
53
+ /** Real runner: child_process for headless calls, node-pty (optional dep)
54
+ * for the TTY-required `claude --cloud` start. */
55
+ declare function defaultCloudCliRunner(): CloudCliRunner;
56
+ interface AuthStatus {
57
+ loggedIn: boolean;
58
+ authMethod?: string;
59
+ }
60
+ /** Parse `claude auth status` JSON output. */
61
+ declare function parseAuthStatus(stdout: string): AuthStatus;
62
+ /**
63
+ * Refuse the spawn before any side effect when the claude CLI is missing,
64
+ * not logged in, or authenticated by API key — cloud sessions require a
65
+ * claude.ai sign-in (verified live: an ANTHROPIC_API_KEY env makes the CLI
66
+ * refuse with "Cloud sessions need a claude.ai sign-in").
67
+ */
68
+ declare function preflightAuth(runner: CloudCliRunner, opts: {
69
+ cwd: string;
70
+ env: Record<string, string>;
71
+ }): Promise<AuthStatus>;
72
+ interface StartedCloudSession {
73
+ /** CLI-spelled id (`session_<id>`), ready for `--cloud` / `--teleport`. */
74
+ sessionId: string;
75
+ url: string;
76
+ title?: string;
77
+ }
78
+ /** Parse the `claude --cloud` start transcript: the id from the "Resume
79
+ * with:" line (falling back to the View URL's path), the URL, and the
80
+ * session title. Returns null when no session id can be found. */
81
+ declare function parseCloudStartOutput(output: string): StartedCloudSession | null;
82
+ interface StartCloudSessionOpts {
83
+ runner?: CloudCliRunner;
84
+ env?: Record<string, string | undefined>;
85
+ cwd: string;
86
+ /** Hard cap on the interactive start (PTY) — default 120s. */
87
+ timeoutMs?: number;
88
+ /** Skip the auth preflight (tests only; production always preflights). */
89
+ skipPreflight?: boolean;
90
+ }
91
+ /**
92
+ * Start a cloud session: `claude --cloud "<prompt>"` under a PTY (the CLI
93
+ * requires a TTY here), answering the first-run folder-trust prompt, then
94
+ * parse the printed session id / URL and exit. The vendor runs the first
95
+ * turn; observe it via the sessions API.
96
+ */
97
+ declare function startCloudSession(prompt: string, opts: StartCloudSessionOpts): Promise<StartedCloudSession>;
98
+ interface SendPromptOpts {
99
+ runner?: CloudCliRunner;
100
+ env?: Record<string, string | undefined>;
101
+ cwd: string;
102
+ timeoutMs?: number;
103
+ skipPreflight?: boolean;
104
+ }
105
+ /**
106
+ * Send a follow-up turn: `claude -p "<text>" --cloud <session id>` with
107
+ * stdin detached (no TTY). Send-only by design — the CLI prints "Sent to
108
+ * cloud session." and never the reply; the reply is observed via the
109
+ * sessions API. Accepts `session_`/`cse_` ids.
110
+ */
111
+ declare function sendPrompt(sessionId: string, text: string, opts: SendPromptOpts): Promise<{
112
+ stdout: string;
113
+ }>;
114
+
115
+ /**
116
+ * Thin client for the undocumented Claude Code cloud sessions API
117
+ * (AIP-66 Appendix A). Base https://api.anthropic.com; requests carry
118
+ * `Authorization: Bearer <claude.ai OAuth access token>`,
119
+ * `anthropic-version: 2023-06-01` and `x-organization-uuid`.
120
+ *
121
+ * The credential is the user's claude.ai login, owned by the claude CLI
122
+ * (AIP-66 §8): this module never logs it, never persists it, and never
123
+ * writes it anywhere — it lives only in request headers for the lifetime
124
+ * of a call. On 401 the credential source is re-read exactly once (the
125
+ * token may have been refreshed since process start), then the call fails
126
+ * with a message that tells the user how to log in.
127
+ *
128
+ * All network access goes through an injectable `fetch` so tests can drive
129
+ * the client from fixtures — no live Anthropic call is ever made from here.
130
+ */
131
+ /** A claude.ai OAuth credential. `accessToken` is the bearer the API wants;
132
+ * `orgUuid` is the `x-organization-uuid` header (from `~/.claude.json`'s
133
+ * `.oauthAccount.organizationUuid`). NEVER logged or persisted. */
134
+ interface CloudCredential {
135
+ accessToken: string;
136
+ orgUuid?: string;
137
+ }
138
+ /** Where the host reads the vendor login from (AIP-66 §8). Implementations
139
+ * must not cache a token across an explicit invalidate() — a 401 re-read
140
+ * has to be able to observe a refreshed login. */
141
+ interface CredentialSource {
142
+ get(): Promise<CloudCredential>;
143
+ }
144
+ /** macOS keychain credential: `security find-generic-password -s "Claude
145
+ * Code-credentials" -w` returns JSON whose `.claudeAiOauth.accessToken` is
146
+ * the bearer; the org uuid comes from `~/.claude.json`. `execFile` and the
147
+ * file reader are injectable for tests; the token never leaves this module
148
+ * except as a request header. */
149
+ declare function keychainCredentialSource(deps?: {
150
+ execFileImpl?: (cmd: string, args: string[]) => Promise<{
151
+ stdout: string;
152
+ }>;
153
+ readFileSyncImpl?: (path: string) => Promise<string>;
154
+ homedir?: () => string;
155
+ }): CredentialSource;
156
+ /** Env credential for hosts/tests that inject the login themselves:
157
+ * CLAUDE_CLOUD_OAUTH_TOKEN (+ optional CLAUDE_CLOUD_ORG_UUID). */
158
+ declare function envCredentialSource(env?: Record<string, string | undefined>): CredentialSource;
159
+ /** One entry of GET /v1/code/sessions/{id}/events (newest first). The
160
+ * `payload` is the Claude Code stream-json SDK message for `user` /
161
+ * `assistant` / `result` events. */
162
+ interface CloudSessionEvent {
163
+ created_at: string;
164
+ event_id: string;
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;
171
+ payload: unknown;
172
+ }
173
+ interface CloudEventsPage {
174
+ data: CloudSessionEvent[];
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. */
178
+ resume_cursor?: string;
179
+ /** Alias for {@link resume_cursor}, seen on the first page only. */
180
+ next_cursor?: string;
181
+ }
182
+ /** GET /v1/code/sessions/{id} — wrapped in `response_shape`. */
183
+ interface CloudSessionState {
184
+ id: string;
185
+ title: string;
186
+ status: string;
187
+ status_bucket?: string;
188
+ worker_status?: string;
189
+ connection_status?: string;
190
+ last_event_at?: string;
191
+ session_url?: string;
192
+ post_turn_summary?: string;
193
+ [key: string]: unknown;
194
+ }
195
+ interface CloudGetSessionResponse {
196
+ response_shape: CloudSessionState;
197
+ [key: string]: unknown;
198
+ }
199
+ /** One entry of GET /v1/code/sessions — id is spelled `cse_<suffix>`, the
200
+ * same suffix the CLI's `session_<suffix>` carries. */
201
+ interface CloudSessionSummary {
202
+ id: string;
203
+ title: string;
204
+ status: "active" | "archived" | string;
205
+ environment_kind?: "anthropic_cloud" | "bridge" | string;
206
+ config?: {
207
+ model?: string;
208
+ origin?: string;
209
+ [key: string]: unknown;
210
+ };
211
+ created_at?: string;
212
+ [key: string]: unknown;
213
+ }
214
+ interface CloudListSessionsResponse {
215
+ data: CloudSessionSummary[];
216
+ resume_token?: string;
217
+ }
218
+ /**
219
+ * Normalize a session id to the API's own `cse_<suffix>` spelling. Accepts
220
+ * `session_<suffix>` (what the CLI prints and `--cloud` takes) and
221
+ * `cse_<suffix>` (what the API listing returns); rejects anything else so a
222
+ * malformed id can never be interpolated into a request path.
223
+ */
224
+ declare function normalizeSessionId(id: string): string;
225
+ /** Normalize to the CLI's own `session_<suffix>` spelling (for `--cloud`,
226
+ * `--teleport`). Same acceptance set as {@link normalizeSessionId}. */
227
+ declare function toCliSessionId(id: string): string;
228
+ interface SessionsApiOptions {
229
+ /** Credential source; re-read once on a 401, then the call fails. */
230
+ credentials: CredentialSource;
231
+ /** Injectable fetch — tests pass a fixture router; default is globalThis.fetch. */
232
+ fetchImpl?: typeof fetch;
233
+ /** Override for proxies/mirrors; default https://api.anthropic.com. */
234
+ baseUrl?: string;
235
+ }
236
+ declare class SessionsApi {
237
+ #private;
238
+ constructor(options: SessionsApiOptions);
239
+ /** GET /v1/code/sessions/{id} */
240
+ getSession(id: string): Promise<CloudGetSessionResponse>;
241
+ /**
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.
245
+ */
246
+ listEvents(id: string, opts?: {
247
+ cursor?: string;
248
+ limit?: number;
249
+ }): Promise<CloudEventsPage>;
250
+ /** GET /v1/code/sessions?limit=N */
251
+ listSessions(opts?: {
252
+ limit?: number;
253
+ }): Promise<CloudListSessionsResponse>;
254
+ }
255
+
256
+ /**
257
+ * The AIP-44 ACP server for Claude Code cloud sessions (AIP-66). This is
258
+ * the binary the daemon spawns (`bin/claude-code-cloud-acp.mjs` → dist):
259
+ * the vendor owns the machine and the harness, so this server does not run
260
+ * any agent — it relays.
261
+ *
262
+ * - `session/new` validates the cwd as a pushed, clean git checkout
263
+ * (AIP-66 §3) BEFORE any vendor side effect.
264
+ * - first `session/prompt` → `claude --cloud "<prompt>"` (start), later
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).
273
+ * - the turn is then observed via the sessions API: events are mapped
274
+ * with @agentproto/adapter-claude-sdk's stream-json → ACP mappers
275
+ * (the payloads ARE Claude Code stream-json SDK messages — reused, not
276
+ * forked), and ONLY the vendor's own `result` event ends the prompt
277
+ * (AIP-66 §6: never a timer, never silence). Transient read failures
278
+ * (HTTP 5xx, network) are retried with backoff before the prompt fails.
279
+ * - `result` carries `total_cost_usd` + `usage` → an ACP `usage_update`
280
+ * (AIP-66 §7); a result without usage emits none — unmeasured, never
281
+ * zero.
282
+ * - `session/cancel` is unsupported: the vendor exposes no interrupt
283
+ * verb, and AIP-66 §6 says a host without one reports it unsupported.
284
+ */
285
+
286
+ /** Poll cadence: 2s, backing off to 10s while the turn is still running. */
287
+ declare const POLL_INITIAL_MS = 2000;
288
+ declare const POLL_MAX_MS = 10000;
289
+ /** The observe surface the turn loop needs — satisfied by {@link SessionsApi}. */
290
+ interface CloudEventsClient {
291
+ listEvents(id: string, opts?: {
292
+ cursor?: string;
293
+ limit?: number;
294
+ }): Promise<CloudEventsPage>;
295
+ }
296
+ /** The start/send surface — satisfied by cli.ts's functions. */
297
+ interface CloudCliDeps {
298
+ startCloudSession(prompt: string, opts: {
299
+ cwd: string;
300
+ }): Promise<StartedCloudSession>;
301
+ sendPrompt(sessionId: string, text: string, opts: {
302
+ cwd: string;
303
+ }): Promise<{
304
+ stdout: string;
305
+ }>;
306
+ }
307
+ interface ClaudeCloudAcpDeps {
308
+ /** Events client. Default: real {@link SessionsApi} on the keychain login. */
309
+ api?: CloudEventsClient;
310
+ /** Vendor CLI. Default: cli.ts's start/send against the real runner. */
311
+ cli?: CloudCliDeps;
312
+ /** Repo-source validator (AIP-66 §3). Default: real git invocations. */
313
+ validateRepo?: (cwd: string) => Promise<void>;
314
+ sleep?: (ms: number) => Promise<void>;
315
+ pollInitialMs?: number;
316
+ pollMaxMs?: number;
317
+ }
318
+ /** Map a `result` event's payload to ACP updates. AIP-66 §7: usage is
319
+ * reported only when the vendor's event carries it; absent usage is
320
+ * UNMEASURED — never a fabricated zero. The shared mapper handles the
321
+ * shape; we normalize the two fields it reads defensively (`modelUsage`,
322
+ * `usage`). */
323
+ declare function resultEventUpdates(payload: unknown): SessionUpdate[];
324
+ /** Stop reason from the `result` payload: an error (or any non-success
325
+ * subtype) stops as `refusal` — ACP has no dedicated error stop. */
326
+ declare function resultStopReason(payload: unknown): StopReason;
327
+ declare class ClaudeCloudAcpAgent implements Agent {
328
+ #private;
329
+ constructor(conn: AgentSideConnection, deps?: ClaudeCloudAcpDeps);
330
+ initialize(_params: InitializeRequest): Promise<InitializeResponse>;
331
+ authenticate(): Promise<void>;
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>;
347
+ prompt(params: PromptRequest): Promise<PromptResponse>;
348
+ /** Unsupported: the vendor exposes no interrupt verb (AIP-66 §6). Throwing
349
+ * reports it — the in-flight poll loop is NOT aborted (we cannot stop the
350
+ * cloud turn; lying "cancelled" would violate §6's end-on-vendor-event
351
+ * rule). */
352
+ cancel(_params: CancelNotification): Promise<void>;
353
+ /** No runtime-configurable options (no model menu — the vendor picks the
354
+ * model). Empty set so a host that tries to set one doesn't error. */
355
+ setSessionConfigOption(_params: SetSessionConfigOptionRequest): Promise<SetSessionConfigOptionResponse>;
356
+ /** No agent-specific modes; accept and ignore. */
357
+ setSessionMode(_params: SetSessionModeRequest): Promise<SetSessionModeResponse>;
358
+ }
359
+ /** Boot the ACP server over stdio — what bin/claude-code-cloud-acp.mjs runs. */
360
+ declare function runAcpOverStdio(deps?: ClaudeCloudAcpDeps): AgentSideConnection;
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
+
411
+ /**
412
+ * AIP-66 §3 (repo source): a managed cloud agent runs on a git remote and
413
+ * ref — never on an uploaded working tree. The host MUST refuse the spawn
414
+ * when `cwd` is not a git checkout with a remote, when the working tree is
415
+ * dirty, or when HEAD is not reachable from the remote.
416
+ *
417
+ * Pure git-invocation logic with an injectable runner so tests can drive
418
+ * every refusal from fixtures (no real repo required).
419
+ */
420
+ /** Runs `git <args…>` in `cwd`; resolves with the exit code + streams. */
421
+ type GitRunner = (args: string[], cwd: string) => Promise<{
422
+ code: number;
423
+ stdout: string;
424
+ stderr: string;
425
+ }>;
426
+ declare const defaultGitRunner: GitRunner;
427
+ /**
428
+ * Refuse (throw) unless `cwd` is a clean git checkout whose HEAD is
429
+ * contained in some `origin/*` ref. Each error names the failed condition —
430
+ * the ACP server surfaces it as the `session/new` failure.
431
+ */
432
+ declare function validateRepoSource(cwd: string, git?: GitRunner): Promise<void>;
433
+
434
+ /**
435
+ * @agentproto/adapter-claude-code-cloud — AIP-66 managed cloud agent adapter
436
+ * for Anthropic Claude Code cloud sessions.
437
+ *
438
+ * Unlike `@agentproto/adapter-claude-code` (local harness, host machine),
439
+ * this adapter relays a session the VENDOR hosts end to end: the vendor
440
+ * boots the machine, runs Claude Code in it, and exposes the session
441
+ * through `claude --cloud` / `claude -p --cloud` plus the undocumented
442
+ * Claude Code sessions API. No agentproto daemon runs inside; the host
443
+ * controls neither the machine nor the harness — so this manifest is
444
+ * deliberately smaller and refuses the spawn fields that could never take
445
+ * effect (AIP-66 §4).
446
+ *
447
+ * import { claudeCodeCloud } from "@agentproto/adapter-claude-code-cloud"
448
+ */
449
+
450
+ declare const CLOUD_REFUSED_SPAWN_FIELDS: readonly ["sandbox", "worktree", "commandSandbox", "mcpServers", "daemonMount", "bundles", "browser", "appServe", "inference"];
451
+ declare const claudeCodeCloud: AgentCliHandle;
452
+ declare function claudeCodeCloudRuntime(): AgentCliRuntime;
453
+
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 ADDED
@@ -0,0 +1,115 @@
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
+ import { fileURLToPath } from 'url';
3
+ import { defineAgentCli, createAgentCliRuntime } from '@agentproto/driver-agent-cli';
4
+
5
+ /**
6
+ * @agentproto/adapter-claude-code-cloud v0.1.0
7
+ * AIP-66 managed cloud agent adapter: Claude Code cloud sessions behind ACP.
8
+ */
9
+ var acpBin = fileURLToPath(
10
+ new URL("../bin/claude-code-cloud-acp.mjs", import.meta.url)
11
+ );
12
+ var CLOUD_REFUSED_SPAWN_FIELDS = [
13
+ "sandbox",
14
+ "worktree",
15
+ "commandSandbox",
16
+ "mcpServers",
17
+ "daemonMount",
18
+ "bundles",
19
+ "browser",
20
+ "appServe",
21
+ "inference"
22
+ ];
23
+ var claudeCodeCloud = defineAgentCli({
24
+ name: "claude-code-cloud",
25
+ id: "claude-code-cloud",
26
+ description: "AIP-66 managed cloud agent adapter for Anthropic Claude Code cloud sessions. The vendor owns the machine and the harness: starts via `claude --cloud` (TTY), prompts via `claude -p --cloud <id>`, observes via the Claude Code sessions API, projected onto stdio ACP. Refuses the AIP-66 \xA74 spawn fields (sandbox, worktree, commandSandbox, mcpServers, daemonMount, bundles, browser, appServe, inference) \u2014 the vendor can never apply them. Requires a claude.ai sign-in (API-key auth is refused) and a clean, pushed git checkout.",
27
+ version: "0.1.0",
28
+ bin: "node",
29
+ bin_args: [acpBin],
30
+ install: [
31
+ {
32
+ method: "npm",
33
+ package: "@agentproto/adapter-claude-code-cloud",
34
+ global: true
35
+ }
36
+ ],
37
+ // Presence probe against the vendor client this adapter relays to — the
38
+ // pinned floor is the oldest CLI observed to support `--cloud` / the
39
+ // sessions API (AIP-66 Appendix A: 2.1.296–2.1.299).
40
+ version_check: {
41
+ cmd: "claude --version",
42
+ parse: "(\\d+\\.\\d+\\.\\d+)",
43
+ range: ">=2.1.296",
44
+ timeout_ms: 15e3
45
+ },
46
+ // Auth is the user's OWN claude.ai login inside the claude CLI (keychain
47
+ // on macOS) — never an injected env credential (AIP-66 §8). No `state.env`
48
+ // because an API-key env would be scrubbed, not consumed; the preflight
49
+ // refuses an api_key-authenticated CLI outright.
50
+ auth: {
51
+ ref: "./CLAUDE-CODE-CLOUD.md",
52
+ login: {
53
+ cmd: "claude auth login",
54
+ interactive: true
55
+ }
56
+ },
57
+ // The machine is the vendor's; there is no host-side sandbox to describe.
58
+ sandbox: "Managed cloud (AIP-66): the vendor boots the machine and runs Claude Code on it. No agentproto daemon runs inside; the session URL is surfaced so the user can inspect what ran.",
59
+ protocol: "acp",
60
+ acp: "./CLAUDE-CODE-CLOUD.md",
61
+ session: {
62
+ // One agentproto session = one vendor cloud session (AIP-66 §5);
63
+ // follow-up turns send to the same vendor session.
64
+ mode: "persistent",
65
+ idle_timeout_ms: 18e5,
66
+ context_carryover: true
67
+ },
68
+ // NO `models` menu: the vendor picks and bills the model inside its own
69
+ // harness; the host has no model to select or route (AIP-66 §4 — `model`
70
+ // is only meaningful when the vendor client accepts it, and this CLI's
71
+ // cloud path exposes no model flag).
72
+ capabilities: {
73
+ // Turns stream back as ACP updates while the vendor runs them.
74
+ streaming: true,
75
+ // The vendor harness's own tools (Read/Edit/Bash/…) surface as ACP
76
+ // tool_call / tool_call_update updates from the session's events.
77
+ tool_calls: true,
78
+ sub_agents: false,
79
+ file_io: true,
80
+ multimodal: false,
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.
84
+ resumable: true,
85
+ // Send-only prompting: the CLI never returns the reply on the prompt
86
+ // path; the reply is observed via the sessions API.
87
+ bidirectional: false
88
+ },
89
+ tags: [
90
+ "claude-code",
91
+ "anthropic",
92
+ "cloud",
93
+ "aip-66",
94
+ "acp",
95
+ "agent-runtime",
96
+ "coding"
97
+ ],
98
+ metadata: {
99
+ aip: 66,
100
+ // The harness the vendor runs (AIP-66 §2 CloudVendor.harnesses).
101
+ harness: "claude-code",
102
+ cloud: {
103
+ vendor: "anthropic"
104
+ },
105
+ // AIP-66 §4 refused spawn fields, machine-readable for the host gate.
106
+ refusedSpawnFields: [...CLOUD_REFUSED_SPAWN_FIELDS]
107
+ }
108
+ });
109
+ function claudeCodeCloudRuntime() {
110
+ return createAgentCliRuntime(claudeCodeCloud);
111
+ }
112
+
113
+ export { CLOUD_REFUSED_SPAWN_FIELDS, claudeCodeCloud, claudeCodeCloudRuntime };
114
+ //# sourceMappingURL=index.mjs.map
115
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;AA4BA,IAAM,MAAA,GAAS,aAAA;AAAA,EACb,IAAI,GAAA,CAAI,kCAAA,EAAoC,MAAA,CAAA,IAAA,CAAY,GAAG;AAC7D,CAAA;AAMO,IAAM,0BAAA,GAA6B;AAAA,EACxC,SAAA;AAAA,EACA,UAAA;AAAA,EACA,gBAAA;AAAA,EACA,YAAA;AAAA,EACA,aAAA;AAAA,EACA,SAAA;AAAA,EACA,SAAA;AAAA,EACA,UAAA;AAAA,EACA;AACF;AAEO,IAAM,kBAAkC,cAAA,CAAe;AAAA,EAC5D,IAAA,EAAM,mBAAA;AAAA,EACN,EAAA,EAAI,mBAAA;AAAA,EACJ,WAAA,EACE,ohBAAA;AAAA,EAQF,OAAA,EAAS,OAAA;AAAA,EACT,GAAA,EAAK,MAAA;AAAA,EACL,QAAA,EAAU,CAAC,MAAM,CAAA;AAAA,EACjB,OAAA,EAAS;AAAA,IACP;AAAA,MACE,MAAA,EAAQ,KAAA;AAAA,MACR,OAAA,EAAS,uCAAA;AAAA,MACT,MAAA,EAAQ;AAAA;AACV,GACF;AAAA;AAAA;AAAA;AAAA,EAIA,aAAA,EAAe;AAAA,IACb,GAAA,EAAK,kBAAA;AAAA,IACL,KAAA,EAAO,sBAAA;AAAA,IACP,KAAA,EAAO,WAAA;AAAA,IACP,UAAA,EAAY;AAAA,GACd;AAAA;AAAA;AAAA;AAAA;AAAA,EAKA,IAAA,EAAM;AAAA,IACJ,GAAA,EAAK,wBAAA;AAAA,IACL,KAAA,EAAO;AAAA,MACL,GAAA,EAAK,mBAAA;AAAA,MACL,WAAA,EAAa;AAAA;AACf,GACF;AAAA;AAAA,EAEA,OAAA,EACE,kLAAA;AAAA,EAGF,QAAA,EAAU,KAAA;AAAA,EACV,GAAA,EAAK,wBAAA;AAAA,EACL,OAAA,EAAS;AAAA;AAAA;AAAA,IAGP,IAAA,EAAM,YAAA;AAAA,IACN,eAAA,EAAiB,IAAA;AAAA,IACjB,iBAAA,EAAmB;AAAA,GACrB;AAAA;AAAA;AAAA;AAAA;AAAA,EAKA,YAAA,EAAc;AAAA;AAAA,IAEZ,SAAA,EAAW,IAAA;AAAA;AAAA;AAAA,IAGX,UAAA,EAAY,IAAA;AAAA,IACZ,UAAA,EAAY,KAAA;AAAA,IACZ,OAAA,EAAS,IAAA;AAAA,IACT,UAAA,EAAY,KAAA;AAAA;AAAA;AAAA;AAAA,IAIZ,SAAA,EAAW,IAAA;AAAA;AAAA;AAAA,IAGX,aAAA,EAAe;AAAA,GACjB;AAAA,EACA,IAAA,EAAM;AAAA,IACJ,aAAA;AAAA,IACA,WAAA;AAAA,IACA,OAAA;AAAA,IACA,QAAA;AAAA,IACA,KAAA;AAAA,IACA,eAAA;AAAA,IACA;AAAA,GACF;AAAA,EACA,QAAA,EAAU;AAAA,IACR,GAAA,EAAK,EAAA;AAAA;AAAA,IAEL,OAAA,EAAS,aAAA;AAAA,IACT,KAAA,EAAO;AAAA,MACL,MAAA,EAAQ;AAAA,KACV;AAAA;AAAA,IAEA,kBAAA,EAAoB,CAAC,GAAG,0BAA0B;AAAA;AAEtD,CAAC;AAEM,SAAS,sBAAA,GAA0C;AACxD,EAAA,OAAO,sBAAsB,eAAe,CAAA;AAC9C","file":"index.mjs","sourcesContent":["/**\n * @agentproto/adapter-claude-code-cloud — AIP-66 managed cloud agent adapter\n * for Anthropic Claude Code cloud sessions.\n *\n * Unlike `@agentproto/adapter-claude-code` (local harness, host machine),\n * this adapter relays a session the VENDOR hosts end to end: the vendor\n * boots the machine, runs Claude Code in it, and exposes the session\n * through `claude --cloud` / `claude -p --cloud` plus the undocumented\n * Claude Code sessions API. No agentproto daemon runs inside; the host\n * controls neither the machine nor the harness — so this manifest is\n * deliberately smaller and refuses the spawn fields that could never take\n * effect (AIP-66 §4).\n *\n * import { claudeCodeCloud } from \"@agentproto/adapter-claude-code-cloud\"\n */\n\nimport { fileURLToPath } from \"node:url\"\nimport {\n createAgentCliRuntime,\n defineAgentCli,\n type AgentCliHandle,\n type AgentCliRuntime,\n} from \"@agentproto/driver-agent-cli\"\n\n// Self-locating: the built handle spawns `node <this-pkg>/bin/…\n// claude-code-cloud-acp.mjs`. From dist/index.mjs the bin sits one level up,\n// so the same build works whether the daemon resolves this package from\n// node_modules or a user runs the published bin directly.\nconst acpBin = fileURLToPath(\n new URL(\"../bin/claude-code-cloud-acp.mjs\", import.meta.url),\n)\n\n// AIP-66 §4 refused spawn fields — no meaning for a vendor-owned harness, so\n// the host MUST refuse a cloud spawn that sets any of them rather than\n// ignore them. Documented here (and in CLAUDE-CODE-CLOUD.md) so the runtime\n// gate and users share one list.\nexport const CLOUD_REFUSED_SPAWN_FIELDS = [\n \"sandbox\",\n \"worktree\",\n \"commandSandbox\",\n \"mcpServers\",\n \"daemonMount\",\n \"bundles\",\n \"browser\",\n \"appServe\",\n \"inference\",\n] as const\n\nexport const claudeCodeCloud: AgentCliHandle = defineAgentCli({\n name: \"claude-code-cloud\",\n id: \"claude-code-cloud\",\n description:\n \"AIP-66 managed cloud agent adapter for Anthropic Claude Code cloud \" +\n \"sessions. The vendor owns the machine and the harness: starts via \" +\n \"`claude --cloud` (TTY), prompts via `claude -p --cloud <id>`, observes \" +\n \"via the Claude Code sessions API, projected onto stdio ACP. Refuses \" +\n \"the AIP-66 §4 spawn fields (sandbox, worktree, commandSandbox, \" +\n \"mcpServers, daemonMount, bundles, browser, appServe, inference) — the \" +\n \"vendor can never apply them. Requires a claude.ai sign-in (API-key \" +\n \"auth is refused) and a clean, pushed git checkout.\",\n version: \"0.1.0\",\n bin: \"node\",\n bin_args: [acpBin],\n install: [\n {\n method: \"npm\",\n package: \"@agentproto/adapter-claude-code-cloud\",\n global: true,\n },\n ],\n // Presence probe against the vendor client this adapter relays to — the\n // pinned floor is the oldest CLI observed to support `--cloud` / the\n // sessions API (AIP-66 Appendix A: 2.1.296–2.1.299).\n version_check: {\n cmd: \"claude --version\",\n parse: \"(\\\\d+\\\\.\\\\d+\\\\.\\\\d+)\",\n range: \">=2.1.296\",\n timeout_ms: 15_000,\n },\n // Auth is the user's OWN claude.ai login inside the claude CLI (keychain\n // on macOS) — never an injected env credential (AIP-66 §8). No `state.env`\n // because an API-key env would be scrubbed, not consumed; the preflight\n // refuses an api_key-authenticated CLI outright.\n auth: {\n ref: \"./CLAUDE-CODE-CLOUD.md\",\n login: {\n cmd: \"claude auth login\",\n interactive: true,\n },\n },\n // The machine is the vendor's; there is no host-side sandbox to describe.\n sandbox:\n \"Managed cloud (AIP-66): the vendor boots the machine and runs Claude \" +\n \"Code on it. No agentproto daemon runs inside; the session URL is \" +\n \"surfaced so the user can inspect what ran.\",\n protocol: \"acp\",\n acp: \"./CLAUDE-CODE-CLOUD.md\",\n session: {\n // One agentproto session = one vendor cloud session (AIP-66 §5);\n // follow-up turns send to the same vendor session.\n mode: \"persistent\",\n idle_timeout_ms: 1_800_000,\n context_carryover: true,\n },\n // NO `models` menu: the vendor picks and bills the model inside its own\n // harness; the host has no model to select or route (AIP-66 §4 — `model`\n // is only meaningful when the vendor client accepts it, and this CLI's\n // cloud path exposes no model flag).\n capabilities: {\n // Turns stream back as ACP updates while the vendor runs them.\n streaming: true,\n // The vendor harness's own tools (Read/Edit/Bash/…) surface as ACP\n // tool_call / tool_call_update updates from the session's events.\n tool_calls: true,\n sub_agents: false,\n file_io: true,\n multimodal: false,\n // Re-attach is via the persisted vendor session id (AIP-66 §5): the\n // host hands it back as ACP `session/load`, which ADOPTS it — the next\n // prompt is a send to that same vendor session, never a new start.\n resumable: true,\n // Send-only prompting: the CLI never returns the reply on the prompt\n // path; the reply is observed via the sessions API.\n bidirectional: false,\n },\n tags: [\n \"claude-code\",\n \"anthropic\",\n \"cloud\",\n \"aip-66\",\n \"acp\",\n \"agent-runtime\",\n \"coding\",\n ],\n metadata: {\n aip: 66,\n // The harness the vendor runs (AIP-66 §2 CloudVendor.harnesses).\n harness: \"claude-code\",\n cloud: {\n vendor: \"anthropic\",\n },\n // AIP-66 §4 refused spawn fields, machine-readable for the host gate.\n refusedSpawnFields: [...CLOUD_REFUSED_SPAWN_FIELDS],\n },\n})\n\nexport function claudeCodeCloudRuntime(): AgentCliRuntime {\n return createAgentCliRuntime(claudeCodeCloud)\n}\n\nexport {\n ClaudeCloudAcpAgent,\n runAcpOverStdio,\n resultEventUpdates,\n resultStopReason,\n POLL_INITIAL_MS,\n POLL_MAX_MS,\n type ClaudeCloudAcpDeps,\n type CloudCliDeps,\n type CloudEventsClient,\n} from \"./acp-server.js\"\nexport {\n CLOUD_SESSION_META_FILE_ENV,\n CLOUD_VENDOR_SLUG,\n writeCloudSessionMeta,\n type CloudSessionMetaReport,\n} from \"./meta-file.js\"\nexport {\n cloudChildEnv,\n defaultCloudCliRunner,\n parseAuthStatus,\n parseCloudStartOutput,\n preflightAuth,\n sendPrompt,\n startCloudSession,\n CLAUDE_CODE_GATEWAY_ENV_UNSET,\n type AuthStatus,\n type CloudCliRunner,\n type RunOpts,\n type RunResult,\n type StartedCloudSession,\n} from \"./cli.js\"\nexport {\n SessionsApi,\n envCredentialSource,\n keychainCredentialSource,\n normalizeSessionId,\n toCliSessionId,\n type CloudCredential,\n type CloudEventsPage,\n type CloudGetSessionResponse,\n type CloudSessionEvent,\n type CloudSessionState,\n type CloudSessionSummary,\n type CredentialSource,\n type SessionsApiOptions,\n} from \"./sessions-api.js\"\nexport {\n validateRepoSource,\n defaultGitRunner,\n type GitRunner,\n} from \"./repo-source.js\"\nexport type { AgentCliHandle, AgentCliRuntime }\n"]}
package/package.json CHANGED
@@ -1,6 +1,74 @@
1
1
  {
2
2
  "name": "@agentproto/adapter-claude-code-cloud",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
3
+ "version": "0.2.0",
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
+ "keywords": [
6
+ "agentproto",
7
+ "aip-44",
8
+ "aip-45",
9
+ "aip-66",
10
+ "claude-code",
11
+ "anthropic",
12
+ "cloud",
13
+ "acp",
14
+ "agent-cli",
15
+ "adapter"
16
+ ],
17
+ "homepage": "https://agentproto.sh/docs/aip-45",
18
+ "repository": {
19
+ "type": "git",
20
+ "url": "https://github.com/agentproto/ts",
21
+ "directory": "adapters/claude-code-cloud"
22
+ },
23
+ "license": "Apache-2.0",
24
+ "type": "module",
25
+ "main": "dist/index.mjs",
26
+ "module": "dist/index.mjs",
27
+ "types": "dist/index.d.ts",
28
+ "bin": {
29
+ "agentproto-claude-code-cloud-acp": "./bin/claude-code-cloud-acp.mjs"
30
+ },
31
+ "exports": {
32
+ ".": {
33
+ "types": "./dist/index.d.ts",
34
+ "import": "./dist/index.mjs",
35
+ "default": "./dist/index.mjs"
36
+ },
37
+ "./CLAUDE-CODE-CLOUD.md": "./CLAUDE-CODE-CLOUD.md",
38
+ "./package.json": "./package.json"
39
+ },
40
+ "files": [
41
+ "dist",
42
+ "bin",
43
+ "CLAUDE-CODE-CLOUD.md",
44
+ "README.md",
45
+ "LICENSE"
46
+ ],
47
+ "publishConfig": {
48
+ "access": "public"
49
+ },
50
+ "dependencies": {
51
+ "@agentclientprotocol/sdk": "^0.21.1",
52
+ "@agentproto/adapter-claude-sdk": "0.7.24",
53
+ "@agentproto/driver-agent-cli": "2.13.0",
54
+ "@agentproto/provider-presets": "0.7.0"
55
+ },
56
+ "optionalDependencies": {
57
+ "node-pty": "^1.1.0"
58
+ },
59
+ "devDependencies": {
60
+ "@types/node": "^25.9.5",
61
+ "tsup": "^8.5.1",
62
+ "typescript": "^5.9.3",
63
+ "vitest": "^3.2.7",
64
+ "@agentproto/tooling": "0.1.0"
65
+ },
66
+ "scripts": {
67
+ "dev": "tsup --watch",
68
+ "build": "tsup",
69
+ "clean": "rm -rf dist",
70
+ "check-types": "tsc --noEmit",
71
+ "test": "vitest run --passWithNoTests",
72
+ "test:watch": "vitest"
73
+ }
6
74
  }