@dynamicagents/plugins 0.11.1 → 0.13.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 (134) hide show
  1. package/README.md +59 -79
  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 +53 -0
  5. package/dist/claude-code/cards.js +272 -0
  6. package/dist/claude-code/config.d.ts +73 -31
  7. package/dist/claude-code/config.js +0 -2
  8. package/dist/claude-code/credentials.d.ts +21 -9
  9. package/dist/claude-code/credentials.js +43 -9
  10. package/dist/claude-code/egress.d.ts +15 -14
  11. package/dist/claude-code/egress.js +51 -14
  12. package/dist/claude-code/events.d.ts +153 -9
  13. package/dist/claude-code/events.js +289 -58
  14. package/dist/claude-code/github.d.ts +39 -0
  15. package/dist/claude-code/github.js +82 -0
  16. package/dist/claude-code/index.d.ts +24 -80
  17. package/dist/claude-code/index.js +19 -234
  18. package/dist/claude-code/model.d.ts +152 -0
  19. package/dist/claude-code/model.js +342 -0
  20. package/dist/claude-code/run.d.ts +283 -92
  21. package/dist/claude-code/run.js +620 -114
  22. package/dist/claude-code/session.d.ts +131 -0
  23. package/dist/claude-code/session.js +285 -0
  24. package/dist/claude-code/spec.d.ts +46 -0
  25. package/dist/claude-code/spec.js +83 -0
  26. package/dist/claude-code/verified.d.ts +15 -0
  27. package/dist/claude-code/verified.js +15 -0
  28. package/dist/computer/context.d.ts +19 -0
  29. package/dist/computer/context.js +222 -0
  30. package/dist/computer/file-lock.d.ts +5 -0
  31. package/dist/computer/file-lock.js +40 -0
  32. package/dist/computer/gate.d.ts +12 -12
  33. package/dist/computer/gate.js +12 -12
  34. package/dist/computer/index.d.ts +57 -255
  35. package/dist/computer/index.js +98 -1039
  36. package/dist/computer/paths.d.ts +47 -22
  37. package/dist/computer/paths.js +64 -49
  38. package/dist/computer/proxy.d.ts +45 -0
  39. package/dist/computer/proxy.js +234 -0
  40. package/dist/computer/render.d.ts +27 -38
  41. package/dist/computer/render.js +32 -65
  42. package/dist/computer/tools-exec.d.ts +3 -0
  43. package/dist/computer/tools-exec.js +268 -0
  44. package/dist/computer/tools-file.d.ts +12 -0
  45. package/dist/computer/tools-file.js +64 -0
  46. package/dist/computer/tools-grep.d.ts +3 -0
  47. package/dist/computer/tools-grep.js +129 -0
  48. package/dist/repo/checkout.d.ts +35 -6
  49. package/dist/repo/checkout.js +64 -6
  50. package/dist/repo/context.d.ts +135 -0
  51. package/dist/repo/context.js +582 -0
  52. package/dist/repo/index.d.ts +79 -57
  53. package/dist/repo/index.js +118 -1112
  54. package/dist/repo/tools-checks.d.ts +3 -0
  55. package/dist/repo/tools-checks.js +112 -0
  56. package/dist/repo/tools-clone.d.ts +4 -0
  57. package/dist/repo/tools-clone.js +192 -0
  58. package/dist/repo/tools-pr.d.ts +14 -0
  59. package/dist/repo/tools-pr.js +196 -0
  60. package/dist/repo/tools-review.d.ts +12 -0
  61. package/dist/repo/tools-review.js +393 -0
  62. package/dist/repo/tools-worktree.d.ts +4 -0
  63. package/dist/repo/tools-worktree.js +305 -0
  64. package/dist/repo/tools-worktrees.d.ts +12 -0
  65. package/dist/repo/tools-worktrees.js +48 -0
  66. package/dist/repo/url.d.ts +2 -2
  67. package/dist/repo/url.js +7 -7
  68. package/dist/scratch/index.d.ts +4 -4
  69. package/dist/scratch/index.js +12 -11
  70. package/dist/{computer → workspace}/advisory.d.ts +33 -20
  71. package/dist/{computer → workspace}/advisory.js +32 -7
  72. package/dist/workspace/ca-trust.d.ts +95 -0
  73. package/dist/workspace/ca-trust.js +312 -0
  74. package/dist/workspace/container-deps.d.ts +54 -0
  75. package/dist/workspace/container-deps.js +224 -0
  76. package/dist/workspace/container-fault.d.ts +38 -0
  77. package/dist/workspace/container-fault.js +73 -0
  78. package/dist/workspace/exec.d.ts +94 -0
  79. package/dist/workspace/exec.js +153 -0
  80. package/dist/workspace/format.d.ts +36 -0
  81. package/dist/workspace/format.js +57 -0
  82. package/dist/workspace/git-host.d.ts +79 -0
  83. package/dist/workspace/git-host.js +226 -0
  84. package/dist/workspace/git-identity.d.ts +57 -0
  85. package/dist/workspace/git-identity.js +147 -0
  86. package/dist/workspace/index.d.ts +43 -47
  87. package/dist/workspace/index.js +52 -112
  88. package/dist/workspace/install-job.d.ts +121 -0
  89. package/dist/workspace/install-job.js +866 -0
  90. package/dist/{computer → workspace}/install.d.ts +15 -19
  91. package/dist/{computer → workspace}/install.js +8 -11
  92. package/dist/workspace/object.d.ts +502 -0
  93. package/dist/workspace/object.js +1427 -0
  94. package/dist/workspace/open.d.ts +95 -0
  95. package/dist/workspace/open.js +63 -0
  96. package/dist/workspace/read.d.ts +16 -0
  97. package/dist/workspace/read.js +22 -0
  98. package/dist/workspace/shell.d.ts +45 -0
  99. package/dist/workspace/shell.js +80 -0
  100. package/dist/workspace/sync.d.ts +111 -0
  101. package/dist/workspace/sync.js +124 -0
  102. package/dist/workspace/wake.d.ts +19 -0
  103. package/dist/workspace/wake.js +10 -0
  104. package/package.json +28 -42
  105. package/dist/arc-agi/analysis.d.ts +0 -336
  106. package/dist/arc-agi/analysis.js +0 -829
  107. package/dist/arc-agi/client.d.ts +0 -82
  108. package/dist/arc-agi/client.js +0 -113
  109. package/dist/arc-agi/game-tools.d.ts +0 -25
  110. package/dist/arc-agi/game-tools.js +0 -26
  111. package/dist/arc-agi/index.d.ts +0 -42
  112. package/dist/arc-agi/index.js +0 -175
  113. package/dist/arc-agi/main-agent.d.ts +0 -27
  114. package/dist/arc-agi/main-agent.js +0 -65
  115. package/dist/arc-agi/recipe.d.ts +0 -51
  116. package/dist/arc-agi/recipe.js +0 -100
  117. package/dist/arc-agi/scorecard.d.ts +0 -118
  118. package/dist/arc-agi/scorecard.js +0 -163
  119. package/dist/arc-agi/soul.d.ts +0 -40
  120. package/dist/arc-agi/soul.js +0 -90
  121. package/dist/arc-agi/store.d.ts +0 -154
  122. package/dist/arc-agi/store.js +0 -216
  123. package/dist/arc-agi/tools.d.ts +0 -36
  124. package/dist/arc-agi/tools.js +0 -576
  125. package/dist/arc-agi/types.d.ts +0 -212
  126. package/dist/arc-agi/types.js +0 -19
  127. package/dist/claude-code/recipe.d.ts +0 -53
  128. package/dist/claude-code/recipe.js +0 -100
  129. package/dist/computer/read.d.ts +0 -137
  130. package/dist/computer/read.js +0 -203
  131. package/dist/recall/index.d.ts +0 -99
  132. package/dist/recall/index.js +0 -171
  133. package/dist/triage/index.d.ts +0 -355
  134. package/dist/triage/index.js +0 -302
@@ -1,9 +1,5 @@
1
- import type { AgentPlugin } from "@dynamicagents/core";
2
- import type { CredentialStore, Lead } from "./credentials.js";
3
- import { type DrainCursor, type DrainOutcome, type SessionRuntime } from "./run.js";
4
- import { type ClaudeCodeConfig } from "./config.js";
5
1
  /**
6
- * `@dynamicagents/plugins/claude-code` — subtasks that run the Claude Code CLI.
2
+ * `@dynamicagents/plugins/claude-code` — sub-agents that run the Claude Code CLI.
7
3
  *
8
4
  * ## Why this exists
9
5
  *
@@ -16,11 +12,12 @@ import { type ClaudeCodeConfig } from "./config.js";
16
12
  *
17
13
  * ## What it contributes, and what it does not
18
14
  *
19
- * It declares **one subtask type and no tool families**. That is unusual here
20
- * and it is the whole shape of the thing: Claude Code brings its own tools, its
21
- * own loop and its own context management, so there is nothing for core's
22
- * resumable runner to drive. The host's subagent overrides `executeChunk` and
23
- * 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.
24
21
  *
25
22
  * ## The credential never enters the container
26
23
  *
@@ -36,10 +33,9 @@ import { type ClaudeCodeConfig } from "./config.js";
36
33
  *
37
34
  * ## The 5-hour and weekly limits are routed around, not predicted
38
35
  *
39
- * 0.5.0 had a budget gate: an estimate of spend in dollars, and a refusal to
40
- * start work over a cap. 0.6.0 deletes it. The estimate was a guess about a
41
- * bucket nobody can read, and it only moved when a run *ended* — so it was never
42
- * a cap on spend, only a gate on starting.
36
+ * **No budget gate, and one must not come back.** An estimate of spend is a
37
+ * guess about a bucket nobody can read, and it only moves when a run *ends* — so
38
+ * it caps nothing, it only refuses to start.
43
39
  *
44
40
  * The gateway sees Anthropic's actual response, which is the one place the
45
41
  * bucket announces itself. So the credential is a **pool**: the first usable
@@ -56,72 +52,20 @@ import { type ClaudeCodeConfig } from "./config.js";
56
52
  * policy is `{ mode: "http-gateway" }` and which supplies a
57
53
  * {@link CredentialStore}. See the README.
58
54
  */
59
- /**
60
- * Bind a config to a workspace runtime: start, drain, stop.
61
- *
62
- * The three calls a host's `executeChunk` needs and nothing else. State lives in
63
- * the {@link DrainCursor} the caller persists between chunks, so this holds none
64
- * and a fresh isolate picks up exactly where the last one stopped.
65
- */
66
- export declare function claudeCodeSession(config: ClaudeCodeConfig): {
67
- /**
68
- * Spawn a session for one subtask and drain its first window.
69
- *
70
- * `subtaskId` namespaces the exec id. Subtasks are a concurrent fan-out, so
71
- * two sessions in one workspace under one id would spawn over each other —
72
- * see {@link execIdFor}.
73
- */
74
- start(runtime: SessionRuntime, subtaskId: string | number, prompt: string, dir: string): Promise<DrainOutcome>;
75
- /** Re-attach to a running session and drain one more window. */
76
- resume(runtime: SessionRuntime, cursor: DrainCursor): Promise<DrainOutcome>;
77
- /** Stop a session — `SIGTERM`, so its own process tree goes with it. */
78
- stop(runtime: SessionRuntime, subtaskId: string | number): Promise<void>;
79
- /**
80
- * Is any credential usable right now, and if not, when?
81
- *
82
- * The same question {@link egress} answers per request, asked ahead of time
83
- * so a host can decline to start a session it cannot pay for. That is not a
84
- * micro-optimisation: an invocation carries an 18.7-27k-token cached prefix
85
- * before it does anything, so starting one and letting the gateway refuse
86
- * its first model call costs a container start and that prefix to learn what
87
- * this returns for free — and reports it as a failed run rather than as a
88
- * rate limit with a time on it.
89
- *
90
- * Reads only. Nothing here marks anything spent.
91
- */
92
- credentials: (store: CredentialStore) => Promise<Lead>;
93
- /**
94
- * The `Fetcher` the workspace object installs as its egress policy.
95
- *
96
- * `store` is an **argument rather than a config field**, and that is the
97
- * point: the credential pool's state belongs to whichever object has
98
- * storage, and this same config object is also held by the parent's plugin
99
- * list and by the subagent facet, neither of which has any. Making it a
100
- * field would force both of them to invent one.
101
- */
102
- egress: (store: CredentialStore) => {
103
- fetch(input: RequestInfo | URL, init?: RequestInit): Promise<Response>;
104
- connect(address: SocketAddress | string, options?: SocketOptions): Socket;
105
- };
106
- };
107
- export type ClaudeCodeSession = ReturnType<typeof claudeCodeSession>;
108
- /**
109
- * The plugin.
110
- *
111
- * `subtaskType` and nothing else: no `toolFamilies`, because Claude Code's tools
112
- * are its own, and no `capability` on the plugin, because a plugin declaring a
113
- * subtask type puts its capability block on the **type** — declaring both makes
114
- * the main agent read the same advice twice per round.
115
- */
116
- export declare function claudeCode(config: ClaudeCodeConfig): AgentPlugin;
55
+ export { claudeCodeModel } from "./model.js";
56
+ export type { ClaudeCodeModelOptions, SessionEnd, SessionOutcome, SessionRecord, SessionWorkspace } from "./model.js";
57
+ export { claudeCodeSession } from "./session.js";
58
+ export type { ClaudeCodeSession, ResumeSession, StartSession } from "./session.js";
59
+ export { CLAUDE_CODE_AGENT, CLAUDE_CODE_WRITE_INPUT, type ClaudeCodeInput } from "./spec.js";
117
60
  export { ANTHROPIC_HOST, claudeCodeEgress } from "./egress.js";
61
+ export { VERIFIED_CLAUDE_CODE_VERSION } from "./verified.js";
118
62
  export type { EgressConfig } from "./egress.js";
119
- export { credentialPool, readRefusal } from "./credentials.js";
63
+ export { GITHUB_HOSTS, GITHUB_TOKEN_PLACEHOLDER } from "./github.js";
64
+ export { credentialPool, readRefusal, readRateLimitEvent } from "./credentials.js";
120
65
  export type { CredentialPool, CredentialPoolConfig, CredentialState, CredentialStore, Lead, Refusal } from "./credentials.js";
121
- export { buildLaunch, CLAUDE_EXEC_PREFIX, CREDENTIAL_PLACEHOLDER, execIdFor, freshCursor } from "./run.js";
122
- export type { DrainCursor, DrainOutcome, Launch, LaunchOptions, SessionRuntime } from "./run.js";
123
- export { parseStream, toProgress } from "./events.js";
124
- export type { ClaudeCodeEvent, ClaudeCodeResult, ClaudeCodeUsage } from "./events.js";
125
- export { CLAUDE_CODE_CAPABILITY, CLAUDE_CODE_RECIPE, CLAUDE_CODE_SPEC, CLAUDE_CODE_TYPE, WORKSPACE_RUNTIME_KEY } from "./recipe.js";
126
- export { DEFAULT_PERMISSION_MODE, DEFAULT_TIMEOUT_MS, DEFAULT_WINDOW_MS } from "./config.js";
127
- export type { ClaudeCodeConfig, PermissionMode } from "./config.js";
66
+ export { buildLaunch, CLAUDE_EXEC_PREFIX, CREDENTIAL_PLACEHOLDER, execIdFor, followUpExecIdFor, freshCursor } from "./run.js";
67
+ export type { DrainCursor, DrainOptions, DrainOutcome, Launch, LaunchOptions, SessionRuntime } from "./run.js";
68
+ export { parseStream, toProgress, RATE_LIMIT_OK } from "./events.js";
69
+ export type { ClaudeCodeEvent, ClaudeCodeResult, ClaudeCodeUsage, RateLimitInfo } from "./events.js";
70
+ export { DEFAULT_PERMISSION_MODE, DEFAULT_TIMEOUT_MS } from "./config.js";
71
+ export type { ClaudeCodeConfig, EffortLevel, PermissionMode } from "./config.js";
@@ -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, 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
  *
@@ -90,10 +33,9 @@ import { CLAUDE_CODE_SPEC, CLAUDE_CODE_TYPE, WORKSPACE_RUNTIME_KEY } from "./rec
90
33
  *
91
34
  * ## The 5-hour and weekly limits are routed around, not predicted
92
35
  *
93
- * 0.5.0 had a budget gate: an estimate of spend in dollars, and a refusal to
94
- * start work over a cap. 0.6.0 deletes it. The estimate was a guess about a
95
- * bucket nobody can read, and it only moved when a run *ended* — so it was never
96
- * a cap on spend, only a gate on starting.
36
+ * **No budget gate, and one must not come back.** An estimate of spend is a
37
+ * guess about a bucket nobody can read, and it only moves when a run *ends* — so
38
+ * it caps nothing, it only refuses to start.
97
39
  *
98
40
  * The gateway sees Anthropic's actual response, which is the one place the
99
41
  * bucket announces itself. So the credential is a **pool**: the first usable
@@ -110,170 +52,13 @@ import { CLAUDE_CODE_SPEC, CLAUDE_CODE_TYPE, WORKSPACE_RUNTIME_KEY } from "./rec
110
52
  * policy is `{ mode: "http-gateway" }` and which supplies a
111
53
  * {@link CredentialStore}. See the README.
112
54
  */
113
- /**
114
- * Bind a config to a workspace runtime: start, drain, stop.
115
- *
116
- * The three calls a host's `executeChunk` needs and nothing else. State lives in
117
- * the {@link DrainCursor} the caller persists between chunks, so this holds none
118
- * and a fresh isolate picks up exactly where the last one stopped.
119
- */
120
- export function claudeCodeSession(config) {
121
- const windowMs = config.windowMs ?? DEFAULT_WINDOW_MS;
122
- const timeoutMs = config.timeoutMs ?? DEFAULT_TIMEOUT_MS;
123
- const launch = (prompt, dir) => ({
124
- prompt,
125
- dir,
126
- ...(config.model ? { model: config.model } : {}),
127
- ...(config.maxTurns === undefined ? {} : { maxTurns: config.maxTurns }),
128
- ...(config.maxSubagentDepth === undefined
129
- ? {}
130
- : { maxSubagentDepth: config.maxSubagentDepth }),
131
- ...(config.maxConcurrentSubagents === undefined
132
- ? {}
133
- : { maxConcurrentSubagents: config.maxConcurrentSubagents }),
134
- // Forwarded only when set, so `buildLaunch` owns the default in one place
135
- // rather than this line resolving it and the flag being written twice.
136
- ...(config.permissionMode ? { permissionMode: config.permissionMode } : {}),
137
- ...(config.env ? { env: config.env } : {})
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) {
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), { windowMs });
158
- }
159
- catch (e_1) {
160
- env_1.error = e_1;
161
- env_1.hasError = true;
162
- }
163
- finally {
164
- __disposeResources(env_1);
165
- }
166
- },
167
- /** Re-attach to a running session and drain one more window. */
168
- async resume(runtime, cursor) {
169
- const env_2 = { stack: [], error: void 0, hasError: false };
170
- try {
171
- const handle = __addDisposableResource(env_2, await attachRun(runtime, cursor), false);
172
- return await drainRun(handle, cursor, { windowMs });
173
- }
174
- catch (e_2) {
175
- env_2.error = e_2;
176
- env_2.hasError = true;
177
- }
178
- finally {
179
- __disposeResources(env_2);
180
- }
181
- },
182
- /** Stop a session — `SIGTERM`, so its own process tree goes with it. */
183
- async stop(runtime, subtaskId) {
184
- await killRun(runtime, execIdFor(subtaskId));
185
- },
186
- /**
187
- * Is any credential usable right now, and if not, when?
188
- *
189
- * The same question {@link egress} answers per request, asked ahead of time
190
- * so a host can decline to start a session it cannot pay for. That is not a
191
- * micro-optimisation: an invocation carries an 18.7-27k-token cached prefix
192
- * before it does anything, so starting one and letting the gateway refuse
193
- * its first model call costs a container start and that prefix to learn what
194
- * this returns for free — and reports it as a failed run rather than as a
195
- * rate limit with a time on it.
196
- *
197
- * Reads only. Nothing here marks anything spent.
198
- */
199
- credentials: (store) => credentialPool({ credentials: config.credentials, store }).lead(),
200
- /**
201
- * The `Fetcher` the workspace object installs as its egress policy.
202
- *
203
- * `store` is an **argument rather than a config field**, and that is the
204
- * point: the credential pool's state belongs to whichever object has
205
- * storage, and this same config object is also held by the parent's plugin
206
- * list and by the subagent facet, neither of which has any. Making it a
207
- * field would force both of them to invent one.
208
- */
209
- egress: (store) => claudeCodeEgress({
210
- credentials: config.credentials,
211
- store,
212
- // Forwarded only when set. Defaulting it to `[]` here would turn "the
213
- // host said nothing" into "Anthropic only", which is the one reading
214
- // the three-way semantics exist to keep distinct.
215
- ...(config.restrictToHosts === undefined
216
- ? {}
217
- : { restrictToHosts: config.restrictToHosts }),
218
- label: CLAUDE_CODE_TYPE
219
- })
220
- };
221
- }
222
- /**
223
- * The plugin.
224
- *
225
- * `subtaskType` and nothing else: no `toolFamilies`, because Claude Code's tools
226
- * are its own, and no `capability` on the plugin, because a plugin declaring a
227
- * subtask type puts its capability block on the **type** — declaring both makes
228
- * the main agent read the same advice twice per round.
229
- */
230
- export function claudeCode(config) {
231
- // Read once at construction so a deployment that forgot the secret fails at DO
232
- // start with a sentence naming this plugin, rather than at the first model
233
- // call inside a subtask somebody is waiting on. The thunk is still what the
234
- // gateway calls per request, so a rotation is picked up.
235
- if (config.credentials().filter(Boolean).length === 0) {
236
- throw new Error("claude-code: no credentials. Set at least one `claude setup-token` " +
237
- "credential and pass it as " +
238
- "`credentials: () => [env.CLAUDE_CODE_OAUTH_TOKEN_1]`.");
239
- }
240
- return definePlugin({
241
- key: "claude-code",
242
- contractVersion: PLUGIN_CONTRACT_VERSION,
243
- subtaskType: CLAUDE_CODE_SPEC,
244
- /**
245
- * Hand each subtask the workspace its parent is working in.
246
- *
247
- * This runs on the **parent** — core dispatches `resolveRuntime` to the
248
- * plugin that declared the subtask type, which is this one — so
249
- * `workspaceName()` resolves here and would throw in the facet, where
250
- * `callerKey()` is deliberately unavailable. Whatever this returns arrives
251
- * at `executeChunk` as its `runtime` argument, and the host reads the name
252
- * back out with {@link WORKSPACE_RUNTIME_KEY}.
253
- *
254
- * Without it a delegated session has no way to address the Durable Object
255
- * holding the checkout it was told to work in — and it cannot be a subtask
256
- * param instead, because those are rendered to the delegating model and a
257
- * model-authored workspace name would let it name somebody else's.
258
- */
259
- // Annotated rather than inferred: without it TypeScript narrows the
260
- // plugin's runtime generic to this one key, which then fails to accept a
261
- // plain `SubtaskRuntime` anywhere else.
262
- resolveRuntime: async () => ({
263
- [WORKSPACE_RUNTIME_KEY]: config.workspaceName()
264
- })
265
- // **No `requires.secrets`, and it is not an omission.** It named
266
- // `CLAUDE_CODE_OAUTH_TOKEN` while there was exactly one credential with a
267
- // name this package could know. The pool's entries are host-named — a
268
- // deployment may call them anything and may have three — so there is no
269
- // name left to declare. The property `requires` bought is kept by the
270
- // `credentials()` check above, which is strictly better: it fails at DO
271
- // start on the *value* being absent rather than on a name being unset.
272
- });
273
- }
55
+ export { claudeCodeModel } from "./model.js";
56
+ export { claudeCodeSession } from "./session.js";
57
+ export { CLAUDE_CODE_AGENT, CLAUDE_CODE_WRITE_INPUT } from "./spec.js";
274
58
  export { ANTHROPIC_HOST, claudeCodeEgress } from "./egress.js";
275
- export { credentialPool, readRefusal } from "./credentials.js";
276
- export { buildLaunch, CLAUDE_EXEC_PREFIX, CREDENTIAL_PLACEHOLDER, execIdFor, freshCursor } from "./run.js";
277
- export { parseStream, toProgress } from "./events.js";
278
- export { CLAUDE_CODE_CAPABILITY, CLAUDE_CODE_RECIPE, CLAUDE_CODE_SPEC, CLAUDE_CODE_TYPE, WORKSPACE_RUNTIME_KEY } from "./recipe.js";
279
- export { DEFAULT_PERMISSION_MODE, DEFAULT_TIMEOUT_MS, DEFAULT_WINDOW_MS } from "./config.js";
59
+ export { VERIFIED_CLAUDE_CODE_VERSION } from "./verified.js";
60
+ export { GITHUB_HOSTS, GITHUB_TOKEN_PLACEHOLDER } from "./github.js";
61
+ export { credentialPool, readRefusal, readRateLimitEvent } from "./credentials.js";
62
+ export { buildLaunch, CLAUDE_EXEC_PREFIX, CREDENTIAL_PLACEHOLDER, execIdFor, followUpExecIdFor, freshCursor } from "./run.js";
63
+ export { parseStream, toProgress, RATE_LIMIT_OK } from "./events.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 {};