@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.
- package/README.md +58 -77
- package/dist/browser/index.d.ts +0 -2
- package/dist/browser/index.js +21 -27
- package/dist/claude-code/cards.d.ts +55 -0
- package/dist/claude-code/cards.js +283 -0
- package/dist/claude-code/config.d.ts +28 -63
- package/dist/claude-code/config.js +0 -11
- package/dist/claude-code/egress.d.ts +8 -1
- package/dist/claude-code/egress.js +42 -4
- package/dist/claude-code/events.d.ts +106 -9
- package/dist/claude-code/events.js +201 -56
- package/dist/claude-code/github.d.ts +39 -0
- package/dist/claude-code/github.js +82 -0
- package/dist/claude-code/index.d.ts +16 -90
- package/dist/claude-code/index.js +14 -276
- package/dist/claude-code/model.d.ts +152 -0
- package/dist/claude-code/model.js +366 -0
- package/dist/claude-code/run.d.ts +230 -116
- package/dist/claude-code/run.js +380 -167
- package/dist/claude-code/session.d.ts +131 -0
- package/dist/claude-code/session.js +288 -0
- package/dist/claude-code/spec.d.ts +46 -0
- package/dist/claude-code/spec.js +83 -0
- package/dist/claude-code/verified.d.ts +15 -0
- package/dist/claude-code/verified.js +15 -0
- package/dist/computer/context.d.ts +1 -5
- package/dist/computer/context.js +7 -10
- package/dist/computer/file-lock.js +5 -4
- package/dist/computer/gate.d.ts +4 -4
- package/dist/computer/gate.js +5 -5
- package/dist/computer/index.d.ts +40 -258
- package/dist/computer/index.js +71 -324
- package/dist/computer/paths.d.ts +36 -16
- package/dist/computer/paths.js +42 -29
- package/dist/computer/proxy.d.ts +45 -0
- package/dist/computer/proxy.js +234 -0
- package/dist/computer/render.d.ts +1 -40
- package/dist/computer/render.js +2 -68
- package/dist/computer/tools-exec.js +12 -13
- package/dist/computer/tools-file.d.ts +9 -1
- package/dist/computer/tools-file.js +22 -82
- package/dist/computer/{tools-find.d.ts → tools-grep.d.ts} +1 -1
- package/dist/computer/tools-grep.js +129 -0
- package/dist/repo/checkout.d.ts +4 -5
- package/dist/repo/checkout.js +31 -8
- package/dist/repo/context.d.ts +35 -9
- package/dist/repo/context.js +101 -49
- package/dist/repo/index.d.ts +73 -28
- package/dist/repo/index.js +112 -96
- package/dist/repo/tools-checks.d.ts +3 -0
- package/dist/repo/tools-checks.js +112 -0
- package/dist/repo/tools-clone.js +1 -1
- package/dist/repo/tools-pr.d.ts +14 -0
- package/dist/repo/{tools-forge.js → tools-pr.js} +53 -36
- package/dist/repo/tools-review.d.ts +9 -0
- package/dist/repo/tools-review.js +67 -47
- package/dist/repo/tools-worktree.js +144 -60
- package/dist/repo/tools-worktrees.d.ts +12 -0
- package/dist/repo/tools-worktrees.js +48 -0
- package/dist/repo/url.d.ts +2 -2
- package/dist/repo/url.js +7 -7
- package/dist/scratch/index.d.ts +4 -4
- package/dist/scratch/index.js +12 -11
- package/dist/{computer → workspace}/advisory.d.ts +4 -4
- package/dist/{computer → workspace}/advisory.js +2 -2
- package/dist/{computer/host → workspace}/ca-trust.d.ts +8 -1
- package/dist/{computer/host → workspace}/ca-trust.js +12 -3
- package/dist/{computer/host → workspace}/container-deps.d.ts +4 -0
- package/dist/{computer/host → workspace}/container-deps.js +26 -1
- package/dist/{computer/host → workspace}/container-fault.d.ts +3 -3
- package/dist/{computer/host → workspace}/container-fault.js +23 -8
- package/dist/workspace/deps-snapshot.d.ts +110 -0
- package/dist/workspace/deps-snapshot.js +424 -0
- package/dist/workspace/exec.d.ts +94 -0
- package/dist/workspace/exec.js +153 -0
- package/dist/workspace/format.d.ts +36 -0
- package/dist/workspace/format.js +57 -0
- package/dist/{computer/host → workspace}/git-host.d.ts +21 -4
- package/dist/{computer/host → workspace}/git-host.js +72 -2
- package/dist/{computer/host → workspace}/git-identity.d.ts +1 -1
- package/dist/{computer/host → workspace}/git-identity.js +1 -1
- package/dist/workspace/index.d.ts +44 -47
- package/dist/workspace/index.js +52 -112
- package/dist/{computer/host → workspace}/install-job.d.ts +53 -4
- package/dist/{computer/host → workspace}/install-job.js +346 -178
- package/dist/{computer → workspace}/install.d.ts +17 -8
- package/dist/{computer → workspace}/install.js +24 -6
- package/dist/{computer/host/workspace.d.ts → workspace/object.d.ts} +125 -27
- package/dist/{computer/host/workspace.js → workspace/object.js} +341 -58
- package/dist/workspace/open.d.ts +95 -0
- package/dist/workspace/open.js +63 -0
- package/dist/workspace/read.d.ts +16 -0
- package/dist/workspace/read.js +22 -0
- package/dist/{computer → workspace}/shell.d.ts +5 -5
- package/dist/{computer → workspace}/shell.js +6 -6
- package/dist/{computer/host → workspace}/wake.d.ts +3 -1
- package/package.json +17 -37
- package/dist/arc-agi/analysis.d.ts +0 -322
- package/dist/arc-agi/analysis.js +0 -802
- package/dist/arc-agi/client.d.ts +0 -82
- package/dist/arc-agi/client.js +0 -113
- package/dist/arc-agi/game-tools.d.ts +0 -24
- package/dist/arc-agi/game-tools.js +0 -26
- package/dist/arc-agi/index.d.ts +0 -40
- package/dist/arc-agi/index.js +0 -175
- package/dist/arc-agi/main-agent.d.ts +0 -24
- package/dist/arc-agi/main-agent.js +0 -62
- package/dist/arc-agi/recipe.d.ts +0 -48
- package/dist/arc-agi/recipe.js +0 -97
- package/dist/arc-agi/scorecard.d.ts +0 -118
- package/dist/arc-agi/scorecard.js +0 -163
- package/dist/arc-agi/soul.d.ts +0 -29
- package/dist/arc-agi/soul.js +0 -79
- package/dist/arc-agi/store.d.ts +0 -153
- package/dist/arc-agi/store.js +0 -215
- package/dist/arc-agi/tools.d.ts +0 -36
- package/dist/arc-agi/tools.js +0 -574
- package/dist/arc-agi/types.d.ts +0 -211
- package/dist/arc-agi/types.js +0 -19
- package/dist/claude-code/recipe.d.ts +0 -53
- package/dist/claude-code/recipe.js +0 -100
- package/dist/computer/read.d.ts +0 -133
- package/dist/computer/read.js +0 -200
- package/dist/computer/tools-find.js +0 -216
- package/dist/recall/index.d.ts +0 -105
- package/dist/recall/index.js +0 -181
- package/dist/repo/tools-forge.d.ts +0 -4
- package/dist/triage/index.d.ts +0 -360
- package/dist/triage/index.js +0 -311
- /package/dist/{computer/host → workspace}/sync.d.ts +0 -0
- /package/dist/{computer/host → workspace}/sync.js +0 -0
- /package/dist/{computer/host → workspace}/wake.js +0 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Everything one
|
|
2
|
+
* Everything one deployment of this plugin tunes, in one shape.
|
|
3
3
|
*
|
|
4
4
|
* Config at instantiation rather than an `env` argument, for the reason the
|
|
5
5
|
* whole package works this way: `Env` is the ambient interface `wrangler types`
|
|
@@ -14,8 +14,16 @@
|
|
|
14
14
|
* the exact failure this option exists to end. The CLI validates the value too,
|
|
15
15
|
* but it does so by exiting 1 with a message on stderr, and stderr reaches an
|
|
16
16
|
* operator far less reliably than a type error reaches a developer.
|
|
17
|
+
*
|
|
18
|
+
* Two of these are worth knowing about before picking one. `default` is not
|
|
19
|
+
* among the choices the pinned CLI documents, and is accepted and echoed back as
|
|
20
|
+
* `permissionMode: "default"` anyway — so it stays. `manual` is the reverse: the
|
|
21
|
+
* CLI documents it and no session here has been run under it, so it is spellable
|
|
22
|
+
* rather than recommended, and whatever it prompts for the headless path denies.
|
|
23
|
+
* See {@link ClaudeCodeConfig.permissionMode} for why the default is the
|
|
24
|
+
* permissive one.
|
|
17
25
|
*/
|
|
18
|
-
export type PermissionMode = "default" | "acceptEdits" | "bypassPermissions" | "plan" | "dontAsk" | "auto";
|
|
26
|
+
export type PermissionMode = "default" | "acceptEdits" | "bypassPermissions" | "plan" | "dontAsk" | "manual" | "auto";
|
|
19
27
|
/**
|
|
20
28
|
* What a session runs under when a deployment says nothing.
|
|
21
29
|
*
|
|
@@ -61,18 +69,6 @@ export interface ClaudeCodeConfig {
|
|
|
61
69
|
* refused with the reset time.
|
|
62
70
|
*/
|
|
63
71
|
credentials: () => readonly string[];
|
|
64
|
-
/**
|
|
65
|
-
* Which workspace this agent's sessions run in.
|
|
66
|
-
*
|
|
67
|
-
* Resolved on the **parent**, where the verified caller is known: core
|
|
68
|
-
* dispatches `resolveRuntime` to the plugin that declared the subtask type,
|
|
69
|
-
* which is this one, and the value it writes is how the subagent facet learns
|
|
70
|
-
* which Durable Object holds its checkout. A facet cannot work this out for
|
|
71
|
-
* itself — `callerKey()` throws there by design — and it is deliberately not a
|
|
72
|
-
* subtask param, because a model-authored workspace name would let a model
|
|
73
|
-
* name somebody else's.
|
|
74
|
-
*/
|
|
75
|
-
workspaceName: () => string;
|
|
76
72
|
/** Which model the session runs. Unset, Claude Code picks its own default. */
|
|
77
73
|
model?: string;
|
|
78
74
|
/**
|
|
@@ -84,9 +80,9 @@ export interface ClaudeCodeConfig {
|
|
|
84
80
|
* holds, not just how well one thinks. The README's Costs section carries the
|
|
85
81
|
* multiples and the sizing they imply.
|
|
86
82
|
*
|
|
87
|
-
* Not to be confused with the
|
|
88
|
-
*
|
|
89
|
-
*
|
|
83
|
+
* Not to be confused with the agent's own reasoning effort, which belongs to
|
|
84
|
+
* a different model on the Worker side. This one reaches only the CLI in the
|
|
85
|
+
* container.
|
|
90
86
|
*/
|
|
91
87
|
effort?: EffortLevel;
|
|
92
88
|
/**
|
|
@@ -94,8 +90,8 @@ export interface ClaudeCodeConfig {
|
|
|
94
90
|
*
|
|
95
91
|
* Advisory, and the distinction is the reason there is no turn ceiling beside
|
|
96
92
|
* them — see the README on what this package deliberately does not do. That
|
|
97
|
-
* tree is invisible to
|
|
98
|
-
* these say; {@link timeoutMs} is the ceiling that actually holds, because the
|
|
93
|
+
* tree is invisible to the agent running the session, so it multiplies
|
|
94
|
+
* whatever these say; {@link timeoutMs} is the ceiling that actually holds, because the
|
|
99
95
|
* container runtime enforces it.
|
|
100
96
|
*/
|
|
101
97
|
maxSubagentDepth?: number;
|
|
@@ -127,6 +123,9 @@ export interface ClaudeCodeConfig {
|
|
|
127
123
|
*
|
|
128
124
|
* See {@link file://./run.ts buildLaunch} for the root guard this mode trips,
|
|
129
125
|
* which is the other half of making it work.
|
|
126
|
+
*
|
|
127
|
+
* A run may set its own, over this one: a planning run's is `plan` — see
|
|
128
|
+
* {@link file://./model.ts ClaudeCodeModelOptions.permissionMode}.
|
|
130
129
|
*/
|
|
131
130
|
permissionMode?: PermissionMode;
|
|
132
131
|
/**
|
|
@@ -137,43 +136,20 @@ export interface ClaudeCodeConfig {
|
|
|
137
136
|
* {@link file://./egress.ts EgressConfig.restrictToHosts} for the full table
|
|
138
137
|
* and for why open is the default.
|
|
139
138
|
*
|
|
140
|
-
*
|
|
141
|
-
*
|
|
142
|
-
* forge token stays on the Worker side.
|
|
139
|
+
* A restriction that leaves out `github.com` and `api.github.com` leaves out
|
|
140
|
+
* {@link githubToken} with them.
|
|
143
141
|
*/
|
|
144
142
|
restrictToHosts?: readonly string[];
|
|
145
143
|
/**
|
|
146
|
-
*
|
|
147
|
-
*
|
|
148
|
-
*
|
|
149
|
-
*
|
|
150
|
-
* session
|
|
151
|
-
*
|
|
152
|
-
*
|
|
153
|
-
* there is no in-flight turn to overrun, which is what sizes the recipe
|
|
154
|
-
* path's budget.
|
|
155
|
-
*
|
|
156
|
-
* What prices the headroom instead is the post-exit filesystem pull, which is
|
|
157
|
-
* deliberately unbounded because it carries whatever the session wrote,
|
|
158
|
-
* dependency trees included, and can outlast the window. So no value here can
|
|
159
|
-
* guarantee the chunk fits inside the step timeout: what is left over is
|
|
160
|
-
* sized for an *expected* pull, plus the sub-second unwind of yielding and
|
|
161
|
-
* the step's own bookkeeping, and a large enough pull overruns it whatever
|
|
162
|
-
* this is set to. See {@link file://./run.ts DrainOptions.windowMs}.
|
|
163
|
-
*
|
|
164
|
-
* **Overrunning is the cheaper failure, which is why the default is
|
|
165
|
-
* generous.** The step is killed and retried; the filesystem sync resumes
|
|
166
|
-
* from the blocks it has already committed rather than starting over, and the
|
|
167
|
-
* retry re-attaches to the session from the cursor — so an overrun costs a
|
|
168
|
-
* retry and some replayed notes, never a session's edits. An undersized
|
|
169
|
-
* window costs a chunk boundary on *every* session instead — a checkpoint, a
|
|
170
|
-
* fresh step, a re-hydrated subagent and a re-attach that replays the tail —
|
|
171
|
-
* paid whether or not the pull was ever going to be large.
|
|
172
|
-
*
|
|
173
|
-
* It must also be long enough that a session does not exhaust its branch's
|
|
174
|
-
* chunk allowance while it is still thinking.
|
|
144
|
+
* GitHub as the deployment's account, for a session that pushes its branch,
|
|
145
|
+
* opens its pull request and answers its review. Read per request, on the
|
|
146
|
+
* Worker side.
|
|
147
|
+
*
|
|
148
|
+
* The session gets a placeholder as `GH_TOKEN` and as git's credential, and
|
|
149
|
+
* the egress gateway swaps in this token for GitHub's hosts only — see
|
|
150
|
+
* {@link file://./github.ts}. Unset, `gh` and git reach GitHub anonymously.
|
|
175
151
|
*/
|
|
176
|
-
|
|
152
|
+
githubToken?: () => string | undefined;
|
|
177
153
|
/**
|
|
178
154
|
* Ceiling on the whole session, enforced by the container runtime.
|
|
179
155
|
*
|
|
@@ -202,16 +178,5 @@ export interface ClaudeCodeConfig {
|
|
|
202
178
|
email: string;
|
|
203
179
|
};
|
|
204
180
|
}
|
|
205
|
-
/**
|
|
206
|
-
* Twenty minutes against a 30-minute step timeout, which leaves ~10 minutes for
|
|
207
|
-
* the sub-second unwind of yielding the window and for the post-exit filesystem
|
|
208
|
-
* pull. An expected pull fits there; a pull that carries an install's
|
|
209
|
-
* dependency tree may not, and nothing here promises it will — that pull is
|
|
210
|
-
* unbounded by design. Sized for the expected case deliberately: the pull that
|
|
211
|
-
* overruns is retried and resumes, while a shorter window would buy that back
|
|
212
|
-
* by paying for extra chunk boundaries on every session. See
|
|
213
|
-
* {@link ClaudeCodeConfig.windowMs}.
|
|
214
|
-
*/
|
|
215
|
-
export declare const DEFAULT_WINDOW_MS: number;
|
|
216
181
|
/** Fifteen minutes, well under the coder workspace's 20-minute idle timer. */
|
|
217
182
|
export declare const DEFAULT_TIMEOUT_MS: number;
|
|
@@ -7,16 +7,5 @@
|
|
|
7
7
|
* {@link ClaudeCodeConfig.permissionMode}.
|
|
8
8
|
*/
|
|
9
9
|
export const DEFAULT_PERMISSION_MODE = "bypassPermissions";
|
|
10
|
-
/**
|
|
11
|
-
* Twenty minutes against a 30-minute step timeout, which leaves ~10 minutes for
|
|
12
|
-
* the sub-second unwind of yielding the window and for the post-exit filesystem
|
|
13
|
-
* pull. An expected pull fits there; a pull that carries an install's
|
|
14
|
-
* dependency tree may not, and nothing here promises it will — that pull is
|
|
15
|
-
* unbounded by design. Sized for the expected case deliberately: the pull that
|
|
16
|
-
* overruns is retried and resumes, while a shorter window would buy that back
|
|
17
|
-
* by paying for extra chunk boundaries on every session. See
|
|
18
|
-
* {@link ClaudeCodeConfig.windowMs}.
|
|
19
|
-
*/
|
|
20
|
-
export const DEFAULT_WINDOW_MS = 20 * 60_000;
|
|
21
10
|
/** Fifteen minutes, well under the coder workspace's 20-minute idle timer. */
|
|
22
11
|
export const DEFAULT_TIMEOUT_MS = 15 * 60_000;
|
|
@@ -22,7 +22,8 @@ import { type CredentialStore } from "./credentials.js";
|
|
|
22
22
|
* with a placeholder; the swap happens here. A `postinstall` script in a
|
|
23
23
|
* cloned repository can read every environment variable the container has and
|
|
24
24
|
* still learn nothing — which is the repository's standing rule ("hand it the
|
|
25
|
-
* action, not the credential") applied to a process nobody can constrain.
|
|
25
|
+
* action, not the credential") applied to a process nobody can constrain. A
|
|
26
|
+
* GitHub token, when configured, is held the same way — see `./github.ts`.
|
|
26
27
|
* 2. **Any restriction that is applied is total.** Not a policy the container
|
|
27
28
|
* cooperates with; the only route out. Restriction is **off by default** —
|
|
28
29
|
* see {@link EgressConfig.restrictToHosts} for why.
|
|
@@ -103,6 +104,12 @@ export interface EgressConfig {
|
|
|
103
104
|
* restriction, the first time a host serves user-controlled subdomains.
|
|
104
105
|
*/
|
|
105
106
|
restrictToHosts?: readonly string[];
|
|
107
|
+
/**
|
|
108
|
+
* The GitHub token to swap for its placeholder, read per request. It reaches
|
|
109
|
+
* {@link GITHUB_HOSTS} and nowhere else. Unset, GitHub is reached
|
|
110
|
+
* anonymously like any other host. See `./github.ts`.
|
|
111
|
+
*/
|
|
112
|
+
githubToken?: () => string | undefined;
|
|
106
113
|
/** Named in log lines so one Worker's several gateways stay tellable apart. */
|
|
107
114
|
label?: string;
|
|
108
115
|
now?: () => number;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { credentialPool, readRefusal } from "./credentials.js";
|
|
2
|
+
import { GITHUB_HOSTS, githubAuthorization, githubError, presentsPlaceholder } from "./github.js";
|
|
2
3
|
/**
|
|
3
4
|
* `@dynamicagents/plugins/claude-code` — the container's only way out.
|
|
4
5
|
*
|
|
@@ -22,7 +23,8 @@ import { credentialPool, readRefusal } from "./credentials.js";
|
|
|
22
23
|
* with a placeholder; the swap happens here. A `postinstall` script in a
|
|
23
24
|
* cloned repository can read every environment variable the container has and
|
|
24
25
|
* still learn nothing — which is the repository's standing rule ("hand it the
|
|
25
|
-
* action, not the credential") applied to a process nobody can constrain.
|
|
26
|
+
* action, not the credential") applied to a process nobody can constrain. A
|
|
27
|
+
* GitHub token, when configured, is held the same way — see `./github.ts`.
|
|
26
28
|
* 2. **Any restriction that is applied is total.** Not a policy the container
|
|
27
29
|
* cooperates with; the only route out. Restriction is **off by default** —
|
|
28
30
|
* see {@link EgressConfig.restrictToHosts} for why.
|
|
@@ -57,9 +59,9 @@ export const ANTHROPIC_HOST = "api.anthropic.com";
|
|
|
57
59
|
* Bouncing a request back into it is never a legitimate fetch, so it is refused
|
|
58
60
|
* before any policy is consulted.
|
|
59
61
|
*
|
|
60
|
-
* A workspace that overrides `egressHost` on its `
|
|
61
|
-
*
|
|
62
|
-
*
|
|
62
|
+
* A workspace that overrides `egressHost` on its `ContainerBackend` should add
|
|
63
|
+
* that name here; the default is what the backend uses when nothing says
|
|
64
|
+
* otherwise.
|
|
63
65
|
*/
|
|
64
66
|
const NEVER_ALLOWED = new Set([
|
|
65
67
|
"computer.internal",
|
|
@@ -206,6 +208,9 @@ export function claudeCodeEgress(config) {
|
|
|
206
208
|
});
|
|
207
209
|
return apiError("permission_error", `${host} is outside this workspace's egress host restriction`, 403);
|
|
208
210
|
}
|
|
211
|
+
if (config.githubToken && GITHUB_HOSTS.has(host)) {
|
|
212
|
+
return await toGitHub(request, url, config.githubToken);
|
|
213
|
+
}
|
|
209
214
|
const headers = new Headers(request.headers);
|
|
210
215
|
if (host !== ANTHROPIC_HOST) {
|
|
211
216
|
// The placeholder must not leave the boundary either. It is worthless to
|
|
@@ -263,6 +268,39 @@ export function claudeCodeEgress(config) {
|
|
|
263
268
|
}
|
|
264
269
|
return await rotate(request, response, lead.id, lead.index);
|
|
265
270
|
};
|
|
271
|
+
/**
|
|
272
|
+
* A request to GitHub: anonymous unless it presents the placeholder,
|
|
273
|
+
* which is swapped for the real token over https only.
|
|
274
|
+
*
|
|
275
|
+
* `redirect: "manual"`, so the token rides only the request it was swapped
|
|
276
|
+
* into: a redirect goes back to the client, whose next request crosses this
|
|
277
|
+
* gateway again and is judged on its own host.
|
|
278
|
+
*/
|
|
279
|
+
const toGitHub = async (request, url, githubToken) => {
|
|
280
|
+
const headers = new Headers(request.headers);
|
|
281
|
+
const presented = presentsPlaceholder(headers.get("authorization"));
|
|
282
|
+
for (const name of CREDENTIAL_HEADERS)
|
|
283
|
+
headers.delete(name);
|
|
284
|
+
if (!presented) {
|
|
285
|
+
return await fetch(new Request(url, new Request(request, { headers })));
|
|
286
|
+
}
|
|
287
|
+
if (url.protocol !== "https:") {
|
|
288
|
+
console.warn(`[${tag}] refused a plaintext request to GitHub`, {
|
|
289
|
+
host: url.hostname,
|
|
290
|
+
method: request.method
|
|
291
|
+
});
|
|
292
|
+
return githubError(`${url.hostname} is reachable over https only; a credential is never ` +
|
|
293
|
+
"attached to a plaintext request", 403);
|
|
294
|
+
}
|
|
295
|
+
const token = githubToken();
|
|
296
|
+
if (!token) {
|
|
297
|
+
console.error(`[${tag}] a session asked for GitHub with no token set`);
|
|
298
|
+
return githubError("no GitHub token is configured for this deployment, so nothing can " +
|
|
299
|
+
"be done as its account", 401);
|
|
300
|
+
}
|
|
301
|
+
headers.set("authorization", githubAuthorization(presented, token));
|
|
302
|
+
return await fetch(new Request(url, new Request(request, { headers, redirect: "manual" })));
|
|
303
|
+
};
|
|
266
304
|
/**
|
|
267
305
|
* Read a refusal, move the lead if it earned one, and shape what the client
|
|
268
306
|
* sees so its own retry lands on the new credential.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { NoteData } from "@dynamicagents/core/subagent";
|
|
2
2
|
/** What a `result` line carries, of the fields anything here reads. */
|
|
3
3
|
export interface ClaudeCodeResult {
|
|
4
4
|
/** `success`, or one of the `error_*` subtypes. */
|
|
@@ -16,6 +16,23 @@ export interface ClaudeCodeResult {
|
|
|
16
16
|
/** How many inner subagents the run spawned — advisory, for the logs. */
|
|
17
17
|
subagentsSpawned?: number;
|
|
18
18
|
permissionDenials: number;
|
|
19
|
+
/**
|
|
20
|
+
* The answer of a session launched with a JSON Schema: the input of its
|
|
21
|
+
* `StructuredOutput` call, which `text` then holds as a JSON string. Absent
|
|
22
|
+
* for any other session, and for one that never made the call.
|
|
23
|
+
*/
|
|
24
|
+
structured?: unknown;
|
|
25
|
+
/**
|
|
26
|
+
* What the CLI says went wrong, when it reports an error rather than an
|
|
27
|
+
* answer.
|
|
28
|
+
*
|
|
29
|
+
* The only account there is of a refused resume: a `--resume` naming a
|
|
30
|
+
* conversation the config directory does not hold ends in a `result` line with
|
|
31
|
+
* no `text` at all, and `No conversation found with session ID: …` here. A
|
|
32
|
+
* caller that reports such a run as a failed session rather than as "not
|
|
33
|
+
* resumable" is reporting the one thing it was handed to say.
|
|
34
|
+
*/
|
|
35
|
+
errors?: string[];
|
|
19
36
|
}
|
|
20
37
|
/**
|
|
21
38
|
* Token counts, flattened.
|
|
@@ -63,6 +80,8 @@ export type ClaudeCodeEvent = {
|
|
|
63
80
|
kind: "init";
|
|
64
81
|
sessionId: string;
|
|
65
82
|
model?: string;
|
|
83
|
+
cwd?: string;
|
|
84
|
+
permissionMode?: string;
|
|
66
85
|
}
|
|
67
86
|
/**
|
|
68
87
|
* The subscription bucket, as the client sees it. Carried rather than acted
|
|
@@ -72,10 +91,44 @@ export type ClaudeCodeEvent = {
|
|
|
72
91
|
| {
|
|
73
92
|
kind: "rateLimit";
|
|
74
93
|
info: RateLimitInfo;
|
|
75
|
-
}
|
|
76
|
-
|
|
94
|
+
}
|
|
95
|
+
/** One `text` block of an assistant message, verbatim — it is markdown. */
|
|
96
|
+
| {
|
|
97
|
+
kind: "text";
|
|
77
98
|
text: string;
|
|
78
|
-
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* One `thinking` block, as how long it took — never what it said. A block can
|
|
102
|
+
* run to thousands of tokens of private reasoning; a reader is told that the
|
|
103
|
+
* model thought, and for how long, the way the CLI itself says it.
|
|
104
|
+
*
|
|
105
|
+
* `durationMs` is measured, never inferred: see
|
|
106
|
+
* {@link ParsedStream.thinkingFrom} for where it starts, and it is absent
|
|
107
|
+
* whenever that cannot be trusted. `messageId` is the API message the block
|
|
108
|
+
* belongs to — a message can carry more than one.
|
|
109
|
+
*/
|
|
110
|
+
| {
|
|
111
|
+
kind: "thinking";
|
|
112
|
+
messageId?: string;
|
|
113
|
+
durationMs?: number;
|
|
114
|
+
} | {
|
|
115
|
+
kind: "toolUse";
|
|
116
|
+
id: string;
|
|
117
|
+
name: string;
|
|
118
|
+
input: unknown;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* One `tool_result` block of a `user` line: a tool's answer going back to
|
|
122
|
+
* the model. `structured` is the line's `tool_use_result` — the tool's own
|
|
123
|
+
* record of what it did, richer than the text the model reads — and is read
|
|
124
|
+
* only when the line carries a single result, since it is not per block.
|
|
125
|
+
*/
|
|
126
|
+
| {
|
|
127
|
+
kind: "toolResult";
|
|
128
|
+
id: string;
|
|
129
|
+
isError: boolean;
|
|
130
|
+
content: string;
|
|
131
|
+
structured?: unknown;
|
|
79
132
|
} | {
|
|
80
133
|
kind: "retry";
|
|
81
134
|
detail: string;
|
|
@@ -124,7 +177,46 @@ export interface ParsedStream {
|
|
|
124
177
|
sample?: string;
|
|
125
178
|
/** Lines dropped for carrying `parent_tool_use_id`. See {@link parseStream}. */
|
|
126
179
|
nested: number;
|
|
180
|
+
/**
|
|
181
|
+
* When the pending thinking block began streaming, on the caller's clock:
|
|
182
|
+
* the `now` of the read that brought its first `system/thinking_tokens`
|
|
183
|
+
* line.
|
|
184
|
+
*
|
|
185
|
+
* That line is the one sign on the stream that thinking is under way. The
|
|
186
|
+
* CLI prints it as the block's text arrives, so it comes after everything
|
|
187
|
+
* that is not thinking: request setup, the wait for a first token, an API
|
|
188
|
+
* retry's back-off, a compaction. The line before a block — the tool result
|
|
189
|
+
* it answers — comes before all of those, and timing from it is how a minute
|
|
190
|
+
* of retries reads as a minute of thought. The token line carries no time of
|
|
191
|
+
* its own, which is why the caller's clock stamps it.
|
|
192
|
+
*
|
|
193
|
+
* Cleared by every line that carries a `timestamp`, so a start belongs to
|
|
194
|
+
* the block that follows the last message and never to work before it. Handed
|
|
195
|
+
* back with `carry`, for the same reason, and kept on the caller's cursor.
|
|
196
|
+
*/
|
|
197
|
+
thinkingFrom?: number;
|
|
198
|
+
}
|
|
199
|
+
/** What {@link parseStream} times a thinking block against. */
|
|
200
|
+
export interface ParseClock {
|
|
201
|
+
/** When this read arrived, in epoch milliseconds. */
|
|
202
|
+
now: number;
|
|
203
|
+
/** {@link ParsedStream.thinkingFrom} from the previous read. */
|
|
204
|
+
thinkingFrom?: number;
|
|
127
205
|
}
|
|
206
|
+
/**
|
|
207
|
+
* How far a thinking line's arrival may be from its own `timestamp` for the
|
|
208
|
+
* block to be timed.
|
|
209
|
+
*
|
|
210
|
+
* Both ends of a block are timed by when they arrive, which is only the truth
|
|
211
|
+
* while the drain reads live. A drain that re-attached after a cut is handed
|
|
212
|
+
* what was printed meanwhile in one burst, and its arrival times are the
|
|
213
|
+
* replay's — so a block whose line arrived far from when the CLI stamped it
|
|
214
|
+
* reads "Thought", with no time. Locally a line arrives 5–31 ms after its
|
|
215
|
+
* stamp; a re-attach has been measured at about a second. A container clock
|
|
216
|
+
* this far from the Worker's degrades every block to no time, rather than to a
|
|
217
|
+
* wrong one.
|
|
218
|
+
*/
|
|
219
|
+
export declare const LIVE_SLACK_MS = 5000;
|
|
128
220
|
/**
|
|
129
221
|
* Parse whatever has arrived so far into complete events plus a carry.
|
|
130
222
|
*
|
|
@@ -138,8 +230,12 @@ export interface ParsedStream {
|
|
|
138
230
|
* the filter.
|
|
139
231
|
*
|
|
140
232
|
* `result` and `init` are never nested and are read unconditionally.
|
|
233
|
+
*
|
|
234
|
+
* `clock` is when this read arrived, and the pending thinking block's start
|
|
235
|
+
* from the previous read — see {@link ParsedStream.thinkingFrom}. Without it no
|
|
236
|
+
* block is timed.
|
|
141
237
|
*/
|
|
142
|
-
export declare function parseStream(buffer: string): ParsedStream;
|
|
238
|
+
export declare function parseStream(buffer: string, clock?: ParseClock): ParsedStream;
|
|
143
239
|
/**
|
|
144
240
|
* The status a healthy bucket reports, and the only one ever observed.
|
|
145
241
|
*
|
|
@@ -152,18 +248,19 @@ export declare function parseStream(buffer: string): ParsedStream;
|
|
|
152
248
|
*/
|
|
153
249
|
export declare const RATE_LIMIT_OK = "allowed";
|
|
154
250
|
/**
|
|
155
|
-
* Turn events into progress notes the parent
|
|
251
|
+
* Turn events into progress notes for the parent's transcript.
|
|
156
252
|
*
|
|
157
253
|
* **`from` is the number of notes already emitted for this run, and the key is
|
|
158
254
|
* derived from it.** Not from the note's content, not from a clock, and not from
|
|
159
255
|
* the Claude Code `uuid` — from position alone.
|
|
160
256
|
*
|
|
161
|
-
* The reason is replay. A
|
|
162
|
-
*
|
|
257
|
+
* The reason is replay. A drain that dies mid-stream is resumed from the last
|
|
258
|
+
* stored sequence, whatever arrived after it is read again, and the same
|
|
259
|
+
* assistant turn is parsed twice. A
|
|
163
260
|
* content-derived key would make two identical notes collide *by luck* (and two
|
|
164
261
|
* genuinely repeated notes — "Running tests" twice — collide wrongly). A
|
|
165
262
|
* clock-derived key would never collide, so every replay would re-post
|
|
166
263
|
* everything. Position is the only choice that dedupes exactly the events that
|
|
167
264
|
* are the same event.
|
|
168
265
|
*/
|
|
169
|
-
export declare function toProgress(events: readonly ClaudeCodeEvent[], from: number):
|
|
266
|
+
export declare function toProgress(events: readonly ClaudeCodeEvent[], from: number): NoteData[];
|