@dynamicagents/plugins 0.12.0 → 0.14.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.
Files changed (132) hide show
  1. package/README.md +58 -77
  2. package/dist/browser/index.d.ts +0 -2
  3. package/dist/browser/index.js +21 -27
  4. package/dist/claude-code/cards.d.ts +55 -0
  5. package/dist/claude-code/cards.js +283 -0
  6. package/dist/claude-code/config.d.ts +28 -63
  7. package/dist/claude-code/config.js +0 -11
  8. package/dist/claude-code/egress.d.ts +8 -1
  9. package/dist/claude-code/egress.js +42 -4
  10. package/dist/claude-code/events.d.ts +106 -9
  11. package/dist/claude-code/events.js +201 -56
  12. package/dist/claude-code/github.d.ts +39 -0
  13. package/dist/claude-code/github.js +82 -0
  14. package/dist/claude-code/index.d.ts +16 -90
  15. package/dist/claude-code/index.js +14 -276
  16. package/dist/claude-code/model.d.ts +152 -0
  17. package/dist/claude-code/model.js +366 -0
  18. package/dist/claude-code/run.d.ts +230 -116
  19. package/dist/claude-code/run.js +380 -167
  20. package/dist/claude-code/session.d.ts +131 -0
  21. package/dist/claude-code/session.js +288 -0
  22. package/dist/claude-code/spec.d.ts +46 -0
  23. package/dist/claude-code/spec.js +83 -0
  24. package/dist/claude-code/verified.d.ts +15 -0
  25. package/dist/claude-code/verified.js +15 -0
  26. package/dist/computer/context.d.ts +1 -5
  27. package/dist/computer/context.js +7 -10
  28. package/dist/computer/file-lock.js +5 -4
  29. package/dist/computer/gate.d.ts +4 -4
  30. package/dist/computer/gate.js +5 -5
  31. package/dist/computer/index.d.ts +40 -258
  32. package/dist/computer/index.js +71 -324
  33. package/dist/computer/paths.d.ts +36 -16
  34. package/dist/computer/paths.js +42 -29
  35. package/dist/computer/proxy.d.ts +45 -0
  36. package/dist/computer/proxy.js +234 -0
  37. package/dist/computer/render.d.ts +1 -40
  38. package/dist/computer/render.js +2 -68
  39. package/dist/computer/tools-exec.js +12 -13
  40. package/dist/computer/tools-file.d.ts +9 -1
  41. package/dist/computer/tools-file.js +22 -82
  42. package/dist/computer/{tools-find.d.ts → tools-grep.d.ts} +1 -1
  43. package/dist/computer/tools-grep.js +129 -0
  44. package/dist/repo/checkout.d.ts +4 -5
  45. package/dist/repo/checkout.js +31 -8
  46. package/dist/repo/context.d.ts +35 -9
  47. package/dist/repo/context.js +101 -49
  48. package/dist/repo/index.d.ts +73 -28
  49. package/dist/repo/index.js +112 -96
  50. package/dist/repo/tools-checks.d.ts +3 -0
  51. package/dist/repo/tools-checks.js +112 -0
  52. package/dist/repo/tools-clone.js +1 -1
  53. package/dist/repo/tools-pr.d.ts +14 -0
  54. package/dist/repo/{tools-forge.js → tools-pr.js} +53 -36
  55. package/dist/repo/tools-review.d.ts +9 -0
  56. package/dist/repo/tools-review.js +67 -47
  57. package/dist/repo/tools-worktree.js +144 -60
  58. package/dist/repo/tools-worktrees.d.ts +12 -0
  59. package/dist/repo/tools-worktrees.js +48 -0
  60. package/dist/repo/url.d.ts +2 -2
  61. package/dist/repo/url.js +7 -7
  62. package/dist/scratch/index.d.ts +4 -4
  63. package/dist/scratch/index.js +12 -11
  64. package/dist/{computer → workspace}/advisory.d.ts +4 -4
  65. package/dist/{computer → workspace}/advisory.js +2 -2
  66. package/dist/{computer/host → workspace}/ca-trust.d.ts +8 -1
  67. package/dist/{computer/host → workspace}/ca-trust.js +12 -3
  68. package/dist/{computer/host → workspace}/container-deps.d.ts +4 -0
  69. package/dist/{computer/host → workspace}/container-deps.js +26 -1
  70. package/dist/{computer/host → workspace}/container-fault.d.ts +3 -3
  71. package/dist/{computer/host → workspace}/container-fault.js +23 -8
  72. package/dist/workspace/deps-snapshot.d.ts +110 -0
  73. package/dist/workspace/deps-snapshot.js +424 -0
  74. package/dist/workspace/exec.d.ts +94 -0
  75. package/dist/workspace/exec.js +153 -0
  76. package/dist/workspace/format.d.ts +36 -0
  77. package/dist/workspace/format.js +57 -0
  78. package/dist/{computer/host → workspace}/git-host.d.ts +21 -4
  79. package/dist/{computer/host → workspace}/git-host.js +72 -2
  80. package/dist/{computer/host → workspace}/git-identity.d.ts +1 -1
  81. package/dist/{computer/host → workspace}/git-identity.js +1 -1
  82. package/dist/workspace/index.d.ts +44 -47
  83. package/dist/workspace/index.js +52 -112
  84. package/dist/{computer/host → workspace}/install-job.d.ts +53 -4
  85. package/dist/{computer/host → workspace}/install-job.js +346 -178
  86. package/dist/{computer → workspace}/install.d.ts +17 -8
  87. package/dist/{computer → workspace}/install.js +24 -6
  88. package/dist/{computer/host/workspace.d.ts → workspace/object.d.ts} +125 -27
  89. package/dist/{computer/host/workspace.js → workspace/object.js} +341 -58
  90. package/dist/workspace/open.d.ts +95 -0
  91. package/dist/workspace/open.js +63 -0
  92. package/dist/workspace/read.d.ts +16 -0
  93. package/dist/workspace/read.js +22 -0
  94. package/dist/{computer → workspace}/shell.d.ts +5 -5
  95. package/dist/{computer → workspace}/shell.js +6 -6
  96. package/dist/{computer/host → workspace}/wake.d.ts +3 -1
  97. package/package.json +17 -37
  98. package/dist/arc-agi/analysis.d.ts +0 -322
  99. package/dist/arc-agi/analysis.js +0 -802
  100. package/dist/arc-agi/client.d.ts +0 -82
  101. package/dist/arc-agi/client.js +0 -113
  102. package/dist/arc-agi/game-tools.d.ts +0 -24
  103. package/dist/arc-agi/game-tools.js +0 -26
  104. package/dist/arc-agi/index.d.ts +0 -40
  105. package/dist/arc-agi/index.js +0 -175
  106. package/dist/arc-agi/main-agent.d.ts +0 -24
  107. package/dist/arc-agi/main-agent.js +0 -62
  108. package/dist/arc-agi/recipe.d.ts +0 -48
  109. package/dist/arc-agi/recipe.js +0 -97
  110. package/dist/arc-agi/scorecard.d.ts +0 -118
  111. package/dist/arc-agi/scorecard.js +0 -163
  112. package/dist/arc-agi/soul.d.ts +0 -29
  113. package/dist/arc-agi/soul.js +0 -79
  114. package/dist/arc-agi/store.d.ts +0 -153
  115. package/dist/arc-agi/store.js +0 -215
  116. package/dist/arc-agi/tools.d.ts +0 -36
  117. package/dist/arc-agi/tools.js +0 -574
  118. package/dist/arc-agi/types.d.ts +0 -211
  119. package/dist/arc-agi/types.js +0 -19
  120. package/dist/claude-code/recipe.d.ts +0 -53
  121. package/dist/claude-code/recipe.js +0 -100
  122. package/dist/computer/read.d.ts +0 -133
  123. package/dist/computer/read.js +0 -200
  124. package/dist/computer/tools-find.js +0 -216
  125. package/dist/recall/index.d.ts +0 -105
  126. package/dist/recall/index.js +0 -181
  127. package/dist/repo/tools-forge.d.ts +0 -4
  128. package/dist/triage/index.d.ts +0 -360
  129. package/dist/triage/index.js +0 -311
  130. /package/dist/{computer/host → workspace}/sync.d.ts +0 -0
  131. /package/dist/{computer/host → workspace}/sync.js +0 -0
  132. /package/dist/{computer/host → workspace}/wake.js +0 -0
@@ -1,63 +1,5 @@
1
- var __addDisposableResource = (this && this.__addDisposableResource) || function (env, value, async) {
2
- if (value !== null && value !== void 0) {
3
- if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
4
- var dispose, inner;
5
- if (async) {
6
- if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
7
- dispose = value[Symbol.asyncDispose];
8
- }
9
- if (dispose === void 0) {
10
- if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
11
- dispose = value[Symbol.dispose];
12
- if (async) inner = dispose;
13
- }
14
- if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
15
- if (inner) dispose = function() { try { inner.call(this); } catch (e) { return Promise.reject(e); } };
16
- env.stack.push({ value: value, dispose: dispose, async: async });
17
- }
18
- else if (async) {
19
- env.stack.push({ async: true });
20
- }
21
- return value;
22
- };
23
- var __disposeResources = (this && this.__disposeResources) || (function (SuppressedError) {
24
- return function (env) {
25
- function fail(e) {
26
- env.error = env.hasError ? new SuppressedError(e, env.error, "An error was suppressed during disposal.") : e;
27
- env.hasError = true;
28
- }
29
- var r, s = 0;
30
- function next() {
31
- while (r = env.stack.pop()) {
32
- try {
33
- if (!r.async && s === 1) return s = 0, env.stack.push(r), Promise.resolve().then(next);
34
- if (r.dispose) {
35
- var result = r.dispose.call(r.value);
36
- if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) { fail(e); return next(); });
37
- }
38
- else s |= 1;
39
- }
40
- catch (e) {
41
- fail(e);
42
- }
43
- }
44
- if (s === 1) return env.hasError ? Promise.reject(env.error) : Promise.resolve();
45
- if (env.hasError) throw env.error;
46
- }
47
- return next();
48
- };
49
- })(typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
50
- var e = new Error(message);
51
- return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
52
- });
53
- import { definePlugin, PLUGIN_CONTRACT_VERSION } from "@dynamicagents/core";
54
- import { claudeCodeEgress } from "./egress.js";
55
- import { credentialPool } from "./credentials.js";
56
- import { attachRun, drainRun, execIdFor, freshCursor, isExecLost, killRun, startRun } from "./run.js";
57
- import { DEFAULT_TIMEOUT_MS, DEFAULT_WINDOW_MS } from "./config.js";
58
- import { CLAUDE_CODE_SPEC, CLAUDE_CODE_TYPE, WORKSPACE_RUNTIME_KEY } from "./recipe.js";
59
1
  /**
60
- * `@dynamicagents/plugins/claude-code` — subtasks that run the Claude Code CLI.
2
+ * `@dynamicagents/plugins/claude-code` — sub-agents that run the Claude Code CLI.
61
3
  *
62
4
  * ## Why this exists
63
5
  *
@@ -70,11 +12,12 @@ import { CLAUDE_CODE_SPEC, CLAUDE_CODE_TYPE, WORKSPACE_RUNTIME_KEY } from "./rec
70
12
  *
71
13
  * ## What it contributes, and what it does not
72
14
  *
73
- * It declares **one subtask type and no tool families**. That is unusual here
74
- * and it is the whole shape of the thing: Claude Code brings its own tools, its
75
- * own loop and its own context management, so there is nothing for core's
76
- * resumable runner to drive. The host's subagent overrides `executeChunk` and
77
- * calls {@link claudeCodeSession} instead.
15
+ * **A writer's sub-agent spec, a model, and no plugin.** Claude Code brings its own
16
+ * tools, its own loop and its own context management, so there is nothing for
17
+ * an agent loop to drive: the session *is* the sub-agent's model —
18
+ * {@link claudeCodeModel} — and Think's recovery drives that. A host binds
19
+ * {@link CLAUDE_CODE_AGENT} to a `SubAgent` class whose `getModel()` returns
20
+ * one, and adds the `prepare` and `settle` that claim and release a workspace.
78
21
  *
79
22
  * ## The credential never enters the container
80
23
  *
@@ -109,218 +52,13 @@ import { CLAUDE_CODE_SPEC, CLAUDE_CODE_TYPE, WORKSPACE_RUNTIME_KEY } from "./rec
109
52
  * policy is `{ mode: "http-gateway" }` and which supplies a
110
53
  * {@link CredentialStore}. See the README.
111
54
  */
112
- /**
113
- * Bind a config to a workspace runtime: start, drain, stop.
114
- *
115
- * The three calls a host's `executeChunk` needs and nothing else. State lives in
116
- * the {@link DrainCursor} the caller persists between chunks, so this holds none
117
- * and a fresh isolate picks up exactly where the last one stopped.
118
- */
119
- export function claudeCodeSession(config) {
120
- const windowMs = config.windowMs ?? DEFAULT_WINDOW_MS;
121
- const timeoutMs = config.timeoutMs ?? DEFAULT_TIMEOUT_MS;
122
- const launch = (prompt, dir) => ({
123
- prompt,
124
- dir,
125
- ...(config.model ? { model: config.model } : {}),
126
- ...(config.effort ? { effort: config.effort } : {}),
127
- ...(config.maxSubagentDepth === undefined
128
- ? {}
129
- : { maxSubagentDepth: config.maxSubagentDepth }),
130
- ...(config.maxConcurrentSubagents === undefined
131
- ? {}
132
- : { maxConcurrentSubagents: config.maxConcurrentSubagents }),
133
- // Forwarded only when set, so `buildLaunch` owns the default in one place
134
- // rather than this line resolving it and the flag being written twice.
135
- ...(config.permissionMode ? { permissionMode: config.permissionMode } : {}),
136
- ...(config.env ? { env: config.env } : {}),
137
- ...(config.author ? { author: config.author } : {})
138
- });
139
- return {
140
- /**
141
- * Spawn a session for one subtask and drain its first window.
142
- *
143
- * `subtaskId` namespaces the exec id. Subtasks are a concurrent fan-out, so
144
- * two sessions in one workspace under one id would spawn over each other —
145
- * see {@link execIdFor}.
146
- */
147
- async start(runtime, subtaskId, prompt, dir, sinks = {}) {
148
- const env_1 = { stack: [], error: void 0, hasError: false };
149
- try {
150
- const execId = execIdFor(subtaskId);
151
- // `using`, so the attachment is released even when the drain throws.
152
- const handle = __addDisposableResource(env_1, await startRun(runtime, {
153
- ...launch(prompt, dir),
154
- execId,
155
- timeoutMs
156
- }), false);
157
- return await drainRun(handle, freshCursor(execId), {
158
- windowMs,
159
- ...sinks
160
- });
161
- }
162
- catch (e_1) {
163
- env_1.error = e_1;
164
- env_1.hasError = true;
165
- }
166
- finally {
167
- __disposeResources(env_1);
168
- }
169
- },
170
- /**
171
- * Re-attach to a running session and drain one more window.
172
- *
173
- * **A session whose container was replaced is reported, not thrown.** The
174
- * attachment is the first thing to notice a replacement, and the caller is a
175
- * chunk loop with a cursor it will happily keep presenting: a throw here
176
- * retries the same dead id until the chunk allowance runs out, and the run
177
- * ends on a stack trace that names neither the session nor the cause. A
178
- * terminal outcome ends it at the first attempt instead, with the exit code
179
- * the runtime uses for a killed process and an explanation on `stderr`,
180
- * which is exactly the channel a session that died without a result line
181
- * already reports through.
182
- *
183
- * **What it must not say is that starting over is safe.** A session is an
184
- * agent: by the time its container went, it may have written files that
185
- * reached the workspace, committed, pushed, or called something outside
186
- * altogether. None of that is visible from here — only that the attachment
187
- * is gone — so the honest report is what is known plus where to look, and
188
- * the decision belongs to whoever can read the durable state.
189
- */
190
- async resume(runtime, cursor, sinks = {}) {
191
- const env_2 = { stack: [], error: void 0, hasError: false };
192
- try {
193
- let handle;
194
- try {
195
- handle = await attachRun(runtime, cursor);
196
- }
197
- catch (err) {
198
- if (!isExecLost(err))
199
- throw err;
200
- console.warn("[claude-code] the session's container was replaced", {
201
- execId: cursor.execId,
202
- err: String(err)
203
- });
204
- return {
205
- done: true,
206
- cursor,
207
- progress: [],
208
- exitCode: -1,
209
- stderr: "the container holding this session was replaced, so the session " +
210
- "was lost before it finished and cannot be re-attached. What it had " +
211
- "already written to the workspace is still there, and anything it " +
212
- "did outside the workspace — a commit, a push, a request — has " +
213
- "already happened. Check the workspace and the branch before " +
214
- "starting this subtask again, since a rerun repeats from the " +
215
- "beginning."
216
- };
217
- }
218
- const session = __addDisposableResource(env_2, handle, false);
219
- return await drainRun(session, cursor, { windowMs, ...sinks });
220
- }
221
- catch (e_2) {
222
- env_2.error = e_2;
223
- env_2.hasError = true;
224
- }
225
- finally {
226
- __disposeResources(env_2);
227
- }
228
- },
229
- /** Stop a session — `SIGTERM`, so its own process tree goes with it. */
230
- async stop(runtime, subtaskId) {
231
- await killRun(runtime, execIdFor(subtaskId));
232
- },
233
- /**
234
- * Is any credential usable right now, and if not, when?
235
- *
236
- * The same question {@link egress} answers per request, asked ahead of time
237
- * so a host can decline to start a session it cannot pay for. That is not a
238
- * micro-optimisation: an invocation carries an 18.7-27k-token cached prefix
239
- * before it does anything, so starting one and letting the gateway refuse
240
- * its first model call costs a container start and that prefix to learn what
241
- * this returns for free — and reports it as a failed run rather than as a
242
- * rate limit with a time on it.
243
- *
244
- * Reads only. Nothing here marks anything spent.
245
- */
246
- credentials: (store) => credentialPool({ credentials: config.credentials, store }).lead(),
247
- /**
248
- * The `Fetcher` the workspace object installs as its egress policy.
249
- *
250
- * `store` is an **argument rather than a config field**, and that is the
251
- * point: the credential pool's state belongs to whichever object has
252
- * storage, and this same config object is also held by the parent's plugin
253
- * list and by the subagent facet, neither of which has any. Making it a
254
- * field would force both of them to invent one.
255
- */
256
- egress: (store) => claudeCodeEgress({
257
- credentials: config.credentials,
258
- store,
259
- // Forwarded only when set. Defaulting it to `[]` here would turn "the
260
- // host said nothing" into "Anthropic only", which is the one reading
261
- // the three-way semantics exist to keep distinct.
262
- ...(config.restrictToHosts === undefined
263
- ? {}
264
- : { restrictToHosts: config.restrictToHosts }),
265
- label: CLAUDE_CODE_TYPE
266
- })
267
- };
268
- }
269
- /**
270
- * The plugin.
271
- *
272
- * `subtaskType` and nothing else: no `toolFamilies`, because Claude Code's tools
273
- * are its own, and no `capability` on the plugin, because a plugin declaring a
274
- * subtask type puts its capability block on the **type** — declaring both makes
275
- * the main agent read the same advice twice per round.
276
- */
277
- export function claudeCode(config) {
278
- // Read once at construction so a deployment that forgot the secret fails at DO
279
- // start with a sentence naming this plugin, rather than at the first model
280
- // call inside a subtask somebody is waiting on. The thunk is still what the
281
- // gateway calls per request, so a rotation is picked up.
282
- if (config.credentials().filter(Boolean).length === 0) {
283
- throw new Error("claude-code: no credentials. Set at least one `claude setup-token` " +
284
- "credential and pass it as " +
285
- "`credentials: () => [env.CLAUDE_CODE_OAUTH_TOKEN_1]`.");
286
- }
287
- return definePlugin({
288
- key: "claude-code",
289
- contractVersion: PLUGIN_CONTRACT_VERSION,
290
- subtaskType: CLAUDE_CODE_SPEC,
291
- /**
292
- * Hand each subtask the workspace its parent is working in.
293
- *
294
- * This runs on the **parent** — core dispatches `resolveRuntime` to the
295
- * plugin that declared the subtask type, which is this one — so
296
- * `workspaceName()` resolves here and would throw in the facet, where
297
- * `callerKey()` is deliberately unavailable. Whatever this returns arrives
298
- * at `executeChunk` as its `runtime` argument, and the host reads the name
299
- * back out with {@link WORKSPACE_RUNTIME_KEY}.
300
- *
301
- * Without it a delegated session has no way to address the Durable Object
302
- * holding the checkout it was told to work in — and it cannot be a subtask
303
- * param instead, because those are rendered to the delegating model and a
304
- * model-authored workspace name would let it name somebody else's.
305
- */
306
- // Annotated rather than inferred: without it TypeScript narrows the
307
- // plugin's runtime generic to this one key, which then fails to accept a
308
- // plain `SubtaskRuntime` anywhere else.
309
- resolveRuntime: async () => ({
310
- [WORKSPACE_RUNTIME_KEY]: config.workspaceName()
311
- })
312
- // **No `requires.secrets`, and it is not an omission.** It named
313
- // `CLAUDE_CODE_OAUTH_TOKEN` while there was exactly one credential with a
314
- // name this package could know. The pool's entries are host-named — a
315
- // deployment may call them anything and may have three — so there is no
316
- // name left to declare. The property `requires` bought is kept by the
317
- // `credentials()` check above, which is strictly better: it fails at DO
318
- // start on the *value* being absent rather than on a name being unset.
319
- });
320
- }
55
+ export { claudeCodeModel } from "./model.js";
56
+ export { claudeCodeSession } from "./session.js";
57
+ export { CLAUDE_CODE_AGENT, CLAUDE_CODE_WRITE_INPUT } from "./spec.js";
321
58
  export { ANTHROPIC_HOST, claudeCodeEgress } from "./egress.js";
59
+ export { VERIFIED_CLAUDE_CODE_VERSION } from "./verified.js";
60
+ export { GITHUB_HOSTS, GITHUB_TOKEN_PLACEHOLDER } from "./github.js";
322
61
  export { credentialPool, readRefusal, readRateLimitEvent } from "./credentials.js";
323
- export { buildLaunch, CLAUDE_EXEC_PREFIX, CREDENTIAL_PLACEHOLDER, execIdFor, freshCursor } from "./run.js";
62
+ export { buildLaunch, CLAUDE_EXEC_PREFIX, CREDENTIAL_PLACEHOLDER, execIdFor, followUpExecIdFor, freshCursor } from "./run.js";
324
63
  export { parseStream, toProgress, RATE_LIMIT_OK } from "./events.js";
325
- export { CLAUDE_CODE_CAPABILITY, CLAUDE_CODE_RECIPE, CLAUDE_CODE_SPEC, CLAUDE_CODE_TYPE, WORKSPACE_RUNTIME_KEY } from "./recipe.js";
326
- export { DEFAULT_PERMISSION_MODE, DEFAULT_TIMEOUT_MS, DEFAULT_WINDOW_MS } from "./config.js";
64
+ export { DEFAULT_PERMISSION_MODE, DEFAULT_TIMEOUT_MS } from "./config.js";
@@ -0,0 +1,152 @@
1
+ import type { LanguageModel } from "ai";
2
+ import type { ArtifactEntryDetail } from "@dynamicagents/core/artifacts";
3
+ import type { ClaudeCodeConfig, PermissionMode } from "./config.js";
4
+ import type { ClaudeCodeResult, RateLimitInfo } from "./events.js";
5
+ import { type SessionRuntime } from "./run.js";
6
+ /**
7
+ * A Claude Code session as a sub-agent's **model**.
8
+ *
9
+ * Claude Code brings its own tools, its own loop and its own context, so there
10
+ * is nothing for Think to drive but the one call that runs it — and making that
11
+ * call the model is what puts the session under Think's recovery. A turn cut by
12
+ * an eviction or a deploy is continued; the continuation calls `doStream`
13
+ * again, and every step below it has already taken is stored, so it resumes
14
+ * where it was: the session is re-attached from its cursor, and a report
15
+ * already made is emitted again rather than made again.
16
+ *
17
+ * ## The report is the only text
18
+ *
19
+ * A run's result is what its assistant messages say, so narration streamed as
20
+ * text would become the result and bury the report. What the session says as
21
+ * it works goes to the parent as notes instead, through `note`. Nothing else is
22
+ * streamed at all: Think's stall watchdog is off, so a silent stream is not cut.
23
+ */
24
+ /** The provider interface this implements, read off `ai` rather than imported. */
25
+ type LanguageModelV3 = Extract<LanguageModel, {
26
+ specificationVersion: "v3";
27
+ }>;
28
+ /** How one exec of a session ended. */
29
+ export interface SessionEnd {
30
+ exitCode: number;
31
+ /** Absent when the process died without ever emitting a `result` line. */
32
+ result?: ClaudeCodeResult;
33
+ /** Bounded, and only when there is no `result` to explain the exit. */
34
+ stderr?: string;
35
+ /** The subscription bucket as the client last reported it, if it did. */
36
+ rateLimit?: RateLimitInfo;
37
+ /**
38
+ * The Claude Code session id, from the `init` line by way of the drain's
39
+ * cursor — see {@link file://./run.ts DrainCursor.sessionId}.
40
+ *
41
+ * Here as well as on `result` because the sessions worth continuing are often
42
+ * the ones with no result: a session ended by its time limit, a cancel or a
43
+ * container rollout reports none, and this is then the only handle to the
44
+ * conversation it got half-way through.
45
+ */
46
+ sessionId?: string;
47
+ }
48
+ /**
49
+ * A session's handle, as the host is told it.
50
+ *
51
+ * Told **twice**: once with the id alone, as soon as the session's `init` line
52
+ * names it, and once with the session's end. The first call is what makes a
53
+ * session that is about to be killed resumable at all; the second says how the
54
+ * conversation it left stands.
55
+ *
56
+ * So a host keys its record on `sessionId` and keeps an `end` once it has one: a
57
+ * recovered turn can report the same id again without an end, and a record that
58
+ * let that erase the end would forget how the session finished.
59
+ */
60
+ export interface SessionRecord {
61
+ sessionId: string;
62
+ /** Absent on the first call; the session's end on the second. */
63
+ end?: SessionEnd;
64
+ }
65
+ /** What a run amounted to, handed to `report`. */
66
+ export interface SessionOutcome {
67
+ /** The session's own end. */
68
+ session: SessionEnd;
69
+ /** The follow-up's end, when `followUp` asked for one. */
70
+ followUp?: SessionEnd;
71
+ }
72
+ /** The container a session runs in, released when the call that opened it ends. */
73
+ export interface SessionWorkspace extends Disposable {
74
+ readonly runtime: SessionRuntime;
75
+ }
76
+ export interface ClaudeCodeModelOptions {
77
+ config: ClaudeCodeConfig;
78
+ /**
79
+ * Opens the run's container — the workspace the run's `runtime()` names.
80
+ * Called again to re-attach after a cut stream, so each call should reach the
81
+ * object through a new stub rather than one held from the last.
82
+ */
83
+ workspace: () => Promise<SessionWorkspace>;
84
+ /** The sub-agent's own storage, where every step's outcome is kept. */
85
+ storage: DurableObjectStorage;
86
+ /** The sub-agent's name, which is the run's id. The exec ids derive from it. */
87
+ runId: string;
88
+ /** The checkout. */
89
+ dir: string;
90
+ /**
91
+ * A JSON Schema the session's answer must match. Its `result` then carries
92
+ * the answer as `structured`, for `report` to read.
93
+ */
94
+ jsonSchema?: Record<string, unknown>;
95
+ /**
96
+ * This run's mode, over {@link file://./config.ts ClaudeCodeConfig.permissionMode}.
97
+ *
98
+ * A planning run is a writing session under `plan` with a `jsonSchema`: it
99
+ * reads, edits nothing, and answers through `StructuredOutput` rather than an
100
+ * approval nobody is there to give. Carrying the plan out is a later run that
101
+ * resumes it with `fork` under the config's mode — the CLI takes a new
102
+ * `--permission-mode` on `--resume` — so the plan's own conversation stays
103
+ * whole for an edit.
104
+ */
105
+ permissionMode?: PermissionMode;
106
+ /**
107
+ * A Claude Code conversation for this run to continue instead of starting one
108
+ * — see {@link file://./session.ts StartSession.resume}.
109
+ *
110
+ * Resolved by the host, in `prepare`, against whatever it recorded through
111
+ * {@link ClaudeCodeModelOptions.onSession}: which conversations exist in a
112
+ * workspace, and which of them a caller may continue, are the host's
113
+ * questions. The run's prompt is then the next user turn — its `brief` hook
114
+ * is the place to say what changed and nothing the session already holds.
115
+ */
116
+ resume?: {
117
+ sessionId: string;
118
+ fork?: boolean;
119
+ };
120
+ /**
121
+ * Files one note on the parent's transcript: the sub-agent's `note`. A tool
122
+ * call, its result and the session's own start and end arrive with a card —
123
+ * see {@link file://./cards.ts Card}.
124
+ */
125
+ note: (key: string, text: string, detail?: ArtifactEntryDetail) => Promise<void>;
126
+ /**
127
+ * The session's handle, as soon as there is one and again when the session
128
+ * ends — see {@link SessionRecord}.
129
+ *
130
+ * Best-effort, like `note`: a throw is logged and the run goes on. Recording a
131
+ * handle is what makes a later run able to continue this conversation, and
132
+ * losing that is not worth losing the session over.
133
+ */
134
+ onSession?: (record: SessionRecord) => Promise<void>;
135
+ /**
136
+ * The session's prompt, from the task the parent sent. Defaults to the task.
137
+ *
138
+ * Runs once per run, before the session starts, and its answer is kept. A
139
+ * throw fails the run with its message — how a host refuses a run it cannot
140
+ * pay for, or has nothing to work in.
141
+ */
142
+ brief?: (task: string) => Promise<string>;
143
+ /**
144
+ * One more turn for a session that ended, or `undefined`. Asked once; its
145
+ * answer is kept, so a resumed run does not ask again.
146
+ */
147
+ followUp?: (session: SessionEnd) => Promise<string | undefined>;
148
+ /** The text the parent receives. Run once, and kept. */
149
+ report: (outcome: SessionOutcome) => Promise<string>;
150
+ }
151
+ export declare function claudeCodeModel(options: ClaudeCodeModelOptions): LanguageModelV3;
152
+ export {};