@dynamicagents/plugins 0.14.0 → 0.15.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 +14 -14
- package/dist/claude-code/cards.d.ts +2 -0
- package/dist/claude-code/cards.js +11 -0
- package/dist/claude-code/config.d.ts +10 -83
- package/dist/claude-code/config.js +0 -2
- package/dist/claude-code/credentials.d.ts +32 -50
- package/dist/claude-code/credentials.js +115 -74
- package/dist/claude-code/daemon/index.d.ts +24 -0
- package/dist/claude-code/daemon/index.js +203 -0
- package/dist/claude-code/egress.d.ts +35 -117
- package/dist/claude-code/egress.js +80 -325
- package/dist/claude-code/events.d.ts +14 -17
- package/dist/claude-code/events.js +19 -15
- package/dist/claude-code/harness-wire.d.ts +45 -0
- package/dist/claude-code/harness-wire.js +47 -0
- package/dist/claude-code/index.d.ts +19 -29
- package/dist/claude-code/index.js +17 -25
- package/dist/claude-code/language-model.d.ts +19 -0
- package/dist/claude-code/language-model.js +71 -0
- package/dist/claude-code/model.d.ts +77 -70
- package/dist/claude-code/model.js +327 -327
- package/dist/claude-code/placeholder.d.ts +12 -0
- package/dist/claude-code/placeholder.js +12 -0
- package/dist/claude-code/spec.d.ts +4 -4
- package/dist/claude-code/spec.js +4 -4
- package/dist/computer/client.d.ts +88 -0
- package/dist/computer/client.js +6 -0
- package/dist/computer/context.d.ts +7 -7
- package/dist/computer/context.js +14 -18
- package/dist/computer/gate.d.ts +4 -23
- package/dist/computer/gate.js +1 -37
- package/dist/computer/index.d.ts +44 -43
- package/dist/computer/index.js +29 -50
- package/dist/computer/paths.d.ts +5 -27
- package/dist/computer/paths.js +7 -30
- package/dist/computer/proxy.d.ts +17 -31
- package/dist/computer/proxy.js +9 -44
- package/dist/computer/render.d.ts +3 -40
- package/dist/computer/render.js +3 -36
- package/dist/computer/sandbox.d.ts +55 -0
- package/dist/computer/sandbox.js +236 -0
- package/dist/computer/shell.d.ts +36 -0
- package/dist/computer/shell.js +41 -0
- package/dist/computer/tools-exec.js +3 -9
- package/dist/computer/tools-file.d.ts +1 -1
- package/dist/computer/tools-file.js +1 -1
- package/dist/{repo → repo-github}/checkout.d.ts +3 -4
- package/dist/{repo → repo-github}/checkout.js +3 -4
- package/dist/{repo → repo-github}/context.d.ts +14 -32
- package/dist/{repo → repo-github}/context.js +46 -81
- package/dist/{repo → repo-github}/index.d.ts +30 -13
- package/dist/{repo → repo-github}/index.js +25 -6
- package/dist/repo-github/mcp.d.ts +95 -0
- package/dist/repo-github/mcp.js +107 -0
- package/dist/repo-github/sandbox-egress.d.ts +68 -0
- package/dist/repo-github/sandbox-egress.js +272 -0
- package/dist/repo-github/sandbox-git.d.ts +30 -0
- package/dist/repo-github/sandbox-git.js +113 -0
- package/dist/{repo → repo-github}/tools-checks.js +43 -4
- package/dist/{repo → repo-github}/tools-clone.js +2 -21
- package/dist/{repo → repo-github}/tools-pr.d.ts +0 -1
- package/dist/{repo → repo-github}/tools-pr.js +85 -20
- package/dist/{repo → repo-github}/tools-review.d.ts +6 -0
- package/dist/{repo → repo-github}/tools-review.js +62 -176
- package/dist/{repo → repo-github}/url.d.ts +11 -0
- package/dist/{repo → repo-github}/url.js +12 -1
- package/dist/{workspace → sandbox}/advisory.d.ts +16 -35
- package/dist/{workspace → sandbox}/advisory.js +2 -29
- package/dist/sandbox/agent-exec.d.ts +31 -0
- package/dist/sandbox/agent-exec.js +62 -0
- package/dist/sandbox/ca-trust.d.ts +9 -0
- package/dist/sandbox/ca-trust.js +21 -0
- package/dist/sandbox/constants.d.ts +22 -0
- package/dist/sandbox/constants.js +22 -0
- package/dist/sandbox/daemon/composite.d.ts +9 -0
- package/dist/sandbox/daemon/composite.js +35 -0
- package/dist/sandbox/daemon/index.d.ts +47 -0
- package/dist/sandbox/daemon/index.js +116 -0
- package/dist/sandbox/egress.d.ts +81 -0
- package/dist/sandbox/egress.js +109 -0
- package/dist/sandbox/exec.d.ts +57 -0
- package/dist/sandbox/exec.js +52 -0
- package/dist/sandbox/format.d.ts +2 -0
- package/dist/sandbox/format.js +7 -0
- package/dist/sandbox/header.d.ts +50 -0
- package/dist/sandbox/header.js +94 -0
- package/dist/sandbox/index.d.ts +17 -0
- package/dist/sandbox/index.js +17 -0
- package/dist/{workspace/install.d.ts → sandbox/install-plan.d.ts} +2 -2
- package/dist/{workspace/install.js → sandbox/install-plan.js} +2 -2
- package/dist/sandbox/name.d.ts +27 -0
- package/dist/sandbox/name.js +32 -0
- package/dist/sandbox/object.d.ts +244 -0
- package/dist/sandbox/object.js +1139 -0
- package/dist/scratch/index.d.ts +1 -9
- package/dist/scratch/index.js +2 -18
- package/package.json +22 -18
- package/dist/claude-code/github.d.ts +0 -39
- package/dist/claude-code/github.js +0 -82
- package/dist/claude-code/run.d.ts +0 -491
- package/dist/claude-code/run.js +0 -913
- package/dist/claude-code/session.d.ts +0 -131
- package/dist/claude-code/session.js +0 -288
- package/dist/workspace/ca-trust.d.ts +0 -95
- package/dist/workspace/ca-trust.js +0 -312
- package/dist/workspace/container-deps.d.ts +0 -58
- package/dist/workspace/container-deps.js +0 -249
- package/dist/workspace/container-fault.d.ts +0 -38
- package/dist/workspace/container-fault.js +0 -73
- package/dist/workspace/deps-snapshot.d.ts +0 -110
- package/dist/workspace/deps-snapshot.js +0 -424
- package/dist/workspace/exec.d.ts +0 -94
- package/dist/workspace/exec.js +0 -153
- package/dist/workspace/format.d.ts +0 -36
- package/dist/workspace/format.js +0 -57
- package/dist/workspace/git-host.d.ts +0 -79
- package/dist/workspace/git-host.js +0 -226
- package/dist/workspace/git-identity.d.ts +0 -57
- package/dist/workspace/git-identity.js +0 -147
- package/dist/workspace/index.d.ts +0 -50
- package/dist/workspace/index.js +0 -58
- package/dist/workspace/install-job.d.ts +0 -170
- package/dist/workspace/install-job.js +0 -934
- package/dist/workspace/object.d.ts +0 -522
- package/dist/workspace/object.js +0 -1541
- package/dist/workspace/open.d.ts +0 -95
- package/dist/workspace/open.js +0 -63
- package/dist/workspace/read.d.ts +0 -16
- package/dist/workspace/read.js +0 -22
- package/dist/workspace/shell.d.ts +0 -45
- package/dist/workspace/shell.js +0 -80
- package/dist/workspace/sync.d.ts +0 -111
- package/dist/workspace/sync.js +0 -124
- package/dist/workspace/wake.d.ts +0 -21
- package/dist/workspace/wake.js +0 -10
- /package/dist/{repo → repo-github}/tools-checks.d.ts +0 -0
- /package/dist/{repo → repo-github}/tools-clone.d.ts +0 -0
- /package/dist/{repo → repo-github}/tools-worktree.d.ts +0 -0
- /package/dist/{repo → repo-github}/tools-worktree.js +0 -0
- /package/dist/{repo → repo-github}/tools-worktrees.d.ts +0 -0
- /package/dist/{repo → repo-github}/tools-worktrees.js +0 -0
package/dist/workspace/open.d.ts
DELETED
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
import type { WorkspaceClient, WorkspaceStub } from "@cloudflare/computer";
|
|
2
|
-
import type { WorkspaceAdvisory } from "./advisory.js";
|
|
3
|
-
/**
|
|
4
|
-
* Reaching a workspace: which one a call names, and the two ways to open it.
|
|
5
|
-
*
|
|
6
|
-
* A leaf, so the object, `/computer`'s tools and its proxy in
|
|
7
|
-
* `../computer/proxy.ts` can import it without
|
|
8
|
-
* going through the barrel that re-exports them.
|
|
9
|
-
*/
|
|
10
|
-
/**
|
|
11
|
-
* Where a parent puts the workspace name so its sub-agents reach the same one.
|
|
12
|
-
*
|
|
13
|
-
* A sub-agent cannot compute this itself. The name is derived from the caller
|
|
14
|
-
* and the repository, and the checkout it should work in is one its parent
|
|
15
|
-
* chose — so a sub-agent that named its own would land beside the parent's
|
|
16
|
-
* checkout, in a workspace with nothing in it.
|
|
17
|
-
*
|
|
18
|
-
* A spec's `prepare` runs on the parent, where the name resolves, and its
|
|
19
|
-
* return value reaches the sub-agent's plugins as `runtime()`. That is the
|
|
20
|
-
* channel core built for exactly this, and it is emphatically *not* the
|
|
21
|
-
* sub-agent's input, which the parent's model writes — a workspace name there
|
|
22
|
-
* would be model-authored, and a model naming another caller's workspace would
|
|
23
|
-
* get that caller's files.
|
|
24
|
-
*/
|
|
25
|
-
export declare const WORKSPACE_RUNTIME_KEY = "workspaceName";
|
|
26
|
-
/**
|
|
27
|
-
* Read a parent-resolved workspace name off a sub-agent's `runtime()`.
|
|
28
|
-
*
|
|
29
|
-
* Returns `undefined` rather than throwing on anything unexpected: a parent has
|
|
30
|
-
* no runtime at all, and falling back to the configured thunk is right there.
|
|
31
|
-
*/
|
|
32
|
-
export declare function workspaceNameFromRuntime(runtime: unknown): string | undefined;
|
|
33
|
-
/**
|
|
34
|
-
* The Durable Object the workspace lives in, as this plugin needs to see it.
|
|
35
|
-
*
|
|
36
|
-
* Structural rather than imported: the class is the host's — it owns the
|
|
37
|
-
* container binding, the alarm and the install job — and a plugin that imported
|
|
38
|
-
* it would stop a second host from bringing its own. `__getWorkspaceStub` is the
|
|
39
|
-
* one method `getWorkspace()` calls across the boundary, and it is what
|
|
40
|
-
* `withWorkspace` installs (or what a host that constructs `Workspace` itself
|
|
41
|
-
* reimplements, which is the same three lines).
|
|
42
|
-
*/
|
|
43
|
-
export interface WorkspaceHost extends Rpc.DurableObjectBranded {
|
|
44
|
-
__getWorkspaceStub(): Promise<WorkspaceStub>;
|
|
45
|
-
/**
|
|
46
|
-
* The same workspace for filesystem-only work, which the host must serve
|
|
47
|
-
* **without starting a container**.
|
|
48
|
-
*
|
|
49
|
-
* The filesystem is the Durable Object's own SQLite, while the first command
|
|
50
|
-
* in a fresh container waits for the whole tree to be pushed into it — so a
|
|
51
|
-
* file tool served the other way waits minutes for a local `readdir`. See
|
|
52
|
-
* `WorkspaceObjectBase.__getWorkspaceFsStub` in `./object.ts`.
|
|
53
|
-
*
|
|
54
|
-
* Required rather than optional, for the reason {@link advisories} gives. A
|
|
55
|
-
* host with nothing to distinguish returns its own `__getWorkspaceStub()`.
|
|
56
|
-
*/
|
|
57
|
-
__getWorkspaceFsStub(): Promise<WorkspaceStub>;
|
|
58
|
-
/**
|
|
59
|
-
* Everything currently true about the workspace that a caller must not assume
|
|
60
|
-
* away — see {@link file://./advisory.ts}. An empty array is the good case.
|
|
61
|
-
*
|
|
62
|
-
* Required rather than optional, and not only because Workers RPC types an
|
|
63
|
-
* optional method as a union nothing can call. A host with nothing to report
|
|
64
|
-
* returns `[]` in one line; a host that forgot to expose it gets a compile
|
|
65
|
-
* error instead of a `bash` that silently runs against a half-built
|
|
66
|
-
* `node_modules`, or against a workspace whose writes are being dropped.
|
|
67
|
-
*
|
|
68
|
-
* `deriveAdvisories` builds the array from what the host already knows, so
|
|
69
|
-
* implementing this is gathering what the host has rather than writing policy.
|
|
70
|
-
*/
|
|
71
|
-
advisories(): Promise<readonly WorkspaceAdvisory[]>;
|
|
72
|
-
}
|
|
73
|
-
/**
|
|
74
|
-
* Open the workspace behind a Durable Object stub.
|
|
75
|
-
*
|
|
76
|
-
* The cast is unavoidable, and narrow enough to be worth isolating here rather
|
|
77
|
-
* than repeating. `getWorkspace` wants a handle whose `__getWorkspaceStub()`
|
|
78
|
-
* resolves to a `WorkspaceStub` — the concrete class, private fields and all.
|
|
79
|
-
* Across a Durable Object boundary Workers RPC hands back a structural
|
|
80
|
-
* `Stub<WorkspaceStub>`, which forwards every method faithfully but carries none
|
|
81
|
-
* of the class's private brand: runtime-compatible, type-incompatible. This is
|
|
82
|
-
* the only place in the plugin that gap is crossed.
|
|
83
|
-
*/
|
|
84
|
-
export declare function openWorkspace(host: DurableObjectStub<WorkspaceHost>): Promise<WorkspaceClient>;
|
|
85
|
-
/**
|
|
86
|
-
* The same workspace, opened for filesystem work alone.
|
|
87
|
-
*
|
|
88
|
-
* `getWorkspace` calls exactly one method on what it is handed, so the host is
|
|
89
|
-
* wrapped in an object answering it from the other side of the seam — see
|
|
90
|
-
* {@link WorkspaceHost.__getWorkspaceFsStub}. Everything past that is identical.
|
|
91
|
-
*
|
|
92
|
-
* **Only the file tools take this.** `bash` and `workspaceExec` need the
|
|
93
|
-
* container started and its CA installed, so they open it the other way.
|
|
94
|
-
*/
|
|
95
|
-
export declare function openWorkspaceFs(host: DurableObjectStub<WorkspaceHost>): Promise<WorkspaceClient>;
|
package/dist/workspace/open.js
DELETED
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
import { getWorkspace } from "@cloudflare/computer";
|
|
2
|
-
/**
|
|
3
|
-
* Reaching a workspace: which one a call names, and the two ways to open it.
|
|
4
|
-
*
|
|
5
|
-
* A leaf, so the object, `/computer`'s tools and its proxy in
|
|
6
|
-
* `../computer/proxy.ts` can import it without
|
|
7
|
-
* going through the barrel that re-exports them.
|
|
8
|
-
*/
|
|
9
|
-
/**
|
|
10
|
-
* Where a parent puts the workspace name so its sub-agents reach the same one.
|
|
11
|
-
*
|
|
12
|
-
* A sub-agent cannot compute this itself. The name is derived from the caller
|
|
13
|
-
* and the repository, and the checkout it should work in is one its parent
|
|
14
|
-
* chose — so a sub-agent that named its own would land beside the parent's
|
|
15
|
-
* checkout, in a workspace with nothing in it.
|
|
16
|
-
*
|
|
17
|
-
* A spec's `prepare` runs on the parent, where the name resolves, and its
|
|
18
|
-
* return value reaches the sub-agent's plugins as `runtime()`. That is the
|
|
19
|
-
* channel core built for exactly this, and it is emphatically *not* the
|
|
20
|
-
* sub-agent's input, which the parent's model writes — a workspace name there
|
|
21
|
-
* would be model-authored, and a model naming another caller's workspace would
|
|
22
|
-
* get that caller's files.
|
|
23
|
-
*/
|
|
24
|
-
export const WORKSPACE_RUNTIME_KEY = "workspaceName";
|
|
25
|
-
/**
|
|
26
|
-
* Read a parent-resolved workspace name off a sub-agent's `runtime()`.
|
|
27
|
-
*
|
|
28
|
-
* Returns `undefined` rather than throwing on anything unexpected: a parent has
|
|
29
|
-
* no runtime at all, and falling back to the configured thunk is right there.
|
|
30
|
-
*/
|
|
31
|
-
export function workspaceNameFromRuntime(runtime) {
|
|
32
|
-
const value = runtime?.[WORKSPACE_RUNTIME_KEY];
|
|
33
|
-
return typeof value === "string" && value.length > 0 ? value : undefined;
|
|
34
|
-
}
|
|
35
|
-
/**
|
|
36
|
-
* Open the workspace behind a Durable Object stub.
|
|
37
|
-
*
|
|
38
|
-
* The cast is unavoidable, and narrow enough to be worth isolating here rather
|
|
39
|
-
* than repeating. `getWorkspace` wants a handle whose `__getWorkspaceStub()`
|
|
40
|
-
* resolves to a `WorkspaceStub` — the concrete class, private fields and all.
|
|
41
|
-
* Across a Durable Object boundary Workers RPC hands back a structural
|
|
42
|
-
* `Stub<WorkspaceStub>`, which forwards every method faithfully but carries none
|
|
43
|
-
* of the class's private brand: runtime-compatible, type-incompatible. This is
|
|
44
|
-
* the only place in the plugin that gap is crossed.
|
|
45
|
-
*/
|
|
46
|
-
export function openWorkspace(host) {
|
|
47
|
-
return getWorkspace(host);
|
|
48
|
-
}
|
|
49
|
-
/**
|
|
50
|
-
* The same workspace, opened for filesystem work alone.
|
|
51
|
-
*
|
|
52
|
-
* `getWorkspace` calls exactly one method on what it is handed, so the host is
|
|
53
|
-
* wrapped in an object answering it from the other side of the seam — see
|
|
54
|
-
* {@link WorkspaceHost.__getWorkspaceFsStub}. Everything past that is identical.
|
|
55
|
-
*
|
|
56
|
-
* **Only the file tools take this.** `bash` and `workspaceExec` need the
|
|
57
|
-
* container started and its CA installed, so they open it the other way.
|
|
58
|
-
*/
|
|
59
|
-
export function openWorkspaceFs(host) {
|
|
60
|
-
return getWorkspace({
|
|
61
|
-
__getWorkspaceStub: () => host.__getWorkspaceFsStub()
|
|
62
|
-
});
|
|
63
|
-
}
|
package/dist/workspace/read.d.ts
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import type { WorkspaceClient } from "@cloudflare/computer";
|
|
2
|
-
/**
|
|
3
|
-
* Does this path exist?
|
|
4
|
-
*
|
|
5
|
-
* `getWorkspace()` types `fs` as the in-process `WorkspaceFilesystem`, but the
|
|
6
|
-
* value on the far side of a Durable Object boundary is a
|
|
7
|
-
* `WorkspaceFilesystemStub`, which carries a few methods the local class does
|
|
8
|
-
* not — `exists` among them. So the fast path is asked for rather than cast to,
|
|
9
|
-
* and `stat` is the fallback for a host that hands back a local workspace.
|
|
10
|
-
*
|
|
11
|
-
* The fallback treats *any* `stat` failure as absence, which is the honest
|
|
12
|
-
* reading for a tool whose entire answer is a boolean: there is no error channel
|
|
13
|
-
* to distinguish "missing" from "unreadable", and the caller's next move — look
|
|
14
|
-
* somewhere else — is the same either way.
|
|
15
|
-
*/
|
|
16
|
-
export declare function pathExists(fs: WorkspaceClient["fs"], path: string): Promise<boolean>;
|
package/dist/workspace/read.js
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Does this path exist?
|
|
3
|
-
*
|
|
4
|
-
* `getWorkspace()` types `fs` as the in-process `WorkspaceFilesystem`, but the
|
|
5
|
-
* value on the far side of a Durable Object boundary is a
|
|
6
|
-
* `WorkspaceFilesystemStub`, which carries a few methods the local class does
|
|
7
|
-
* not — `exists` among them. So the fast path is asked for rather than cast to,
|
|
8
|
-
* and `stat` is the fallback for a host that hands back a local workspace.
|
|
9
|
-
*
|
|
10
|
-
* The fallback treats *any* `stat` failure as absence, which is the honest
|
|
11
|
-
* reading for a tool whose entire answer is a boolean: there is no error channel
|
|
12
|
-
* to distinguish "missing" from "unreadable", and the caller's next move — look
|
|
13
|
-
* somewhere else — is the same either way.
|
|
14
|
-
*/
|
|
15
|
-
export async function pathExists(fs, path) {
|
|
16
|
-
// Called as a method, never through `.call`: on an RPC stub `.call` is read as
|
|
17
|
-
// a remote method, and the stub it would pass as `this` cannot be serialised.
|
|
18
|
-
const remote = fs;
|
|
19
|
-
if (typeof remote.exists === "function")
|
|
20
|
-
return remote.exists(path);
|
|
21
|
-
return fs.stat(path).then(() => true, () => false);
|
|
22
|
-
}
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Run a command under {@link file://./exec.ts WorkspaceClientConfig.shell} with its
|
|
3
|
-
* two output streams left as they are, or hand it back untouched when no shell
|
|
4
|
-
* is configured.
|
|
5
|
-
*
|
|
6
|
-
* This is the variant for a caller that **reads the result in code**: `stdout` is
|
|
7
|
-
* a data channel it compares or parses, and `stderr` is a separate diagnostic.
|
|
8
|
-
* {@link file://./exec.ts workspaceExec} is that caller, on behalf of
|
|
9
|
-
* `@dynamicagents/plugins/repo`, which asks git questions like
|
|
10
|
-
* `symbolic-ref --short refs/remotes/origin/HEAD` and `rev-list --count` and
|
|
11
|
-
* needs the answer alone.
|
|
12
|
-
*
|
|
13
|
-
* Two functions rather than one with a flag, because the difference is a change
|
|
14
|
-
* to the *output contract* and a boolean hides it at the call site. Merging the
|
|
15
|
-
* streams here would give every `/repo` git command an empty `stderr` and a
|
|
16
|
-
* `stdout` that is a transcript rather than an answer — which fails silently,
|
|
17
|
-
* since the commands `/repo` parses are quiet ones and a single `warning:` is
|
|
18
|
-
* enough to skip the empty-branch guard.
|
|
19
|
-
*/
|
|
20
|
-
export declare function withShell(command: string, shell: string | undefined): string;
|
|
21
|
-
/**
|
|
22
|
-
* Run a command under {@link file://./exec.ts WorkspaceClientConfig.shell} with its
|
|
23
|
-
* two output streams merged into one transcript, in the order they were
|
|
24
|
-
* written.
|
|
25
|
-
*
|
|
26
|
-
* This is the variant for a caller whose consumer is **a model reading output**.
|
|
27
|
-
* `bash` is that caller. A project's check is a chain — `wrangler types &&
|
|
28
|
-
* prettier && eslint && tsc` — and *which tool spoke last* is how you know which
|
|
29
|
-
* one failed. A stdout block and a separate stderr block destroy that ordering,
|
|
30
|
-
* and a model that wants it back re-runs the whole gate as
|
|
31
|
-
* `npm run check > /tmp/out 2>&1; cat /tmp/out`. This is that workaround, done
|
|
32
|
-
* once, for free.
|
|
33
|
-
*
|
|
34
|
-
* The redirect binds to the wrapper process, so it applies to everything the
|
|
35
|
-
* command writes however deeply nested — and there is no inner brace group or
|
|
36
|
-
* subshell to mis-parse a command that already contains `&&`, quotes or redirects
|
|
37
|
-
* of its own.
|
|
38
|
-
*
|
|
39
|
-
* With no shell configured there is no wrapper process to redirect, so the
|
|
40
|
-
* command goes to the runtime untouched and the two streams arrive separate.
|
|
41
|
-
* That is not a gap: {@link file://../computer/render.ts renderResult} renders them as a
|
|
42
|
-
* labelled `--- stderr ---` block for exactly this case. The transcript is the
|
|
43
|
-
* better answer, not the only supported one.
|
|
44
|
-
*/
|
|
45
|
-
export declare function withShellTranscript(command: string, shell: string | undefined): string;
|
package/dist/workspace/shell.js
DELETED
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
import { shellQuote } from "@cloudflare/computer";
|
|
2
|
-
/** How a command reaches the shell, and what its two output streams do there. */
|
|
3
|
-
/**
|
|
4
|
-
* The shell wrapper both variants share, minus the choice they differ on.
|
|
5
|
-
*
|
|
6
|
-
* One quoted argument, not string concatenation: the command is model-authored
|
|
7
|
-
* and routinely contains quotes of its own (`git commit -m "…"`), so anything
|
|
8
|
-
* less than `shellQuote` re-parses the model's quoting and mangles it.
|
|
9
|
-
*
|
|
10
|
-
* ## Why `-o pipefail`
|
|
11
|
-
*
|
|
12
|
-
* Without it a pipeline's exit status is its **last** stage's, so
|
|
13
|
-
* `npm run check | tail -100` reports `exit 0` for a gate that failed outright —
|
|
14
|
-
* and models pipe into `tail` constantly. A tool that reports success for a
|
|
15
|
-
* failed build is worse than one that reports nothing. It also costs a re-run
|
|
16
|
-
* every time: a model that cannot trust a piped exit code runs the whole thing
|
|
17
|
-
* again unpiped to get one.
|
|
18
|
-
*
|
|
19
|
-
* The trade is worth stating. `pipefail` surfaces SIGPIPE too, so
|
|
20
|
-
* `ls big-dir | head -1` reports 141 rather than 0 — noisy, but *visible*, where
|
|
21
|
-
* the alternative is a failing gate that looks clean. The tool description tells
|
|
22
|
-
* the model not to pipe into `head`/`tail` at all, since output is already
|
|
23
|
-
* truncated with both ends kept.
|
|
24
|
-
*
|
|
25
|
-
* Requires a shell that implements it — `bash`, `zsh`, `ksh`, not `sh`/dash. A
|
|
26
|
-
* host setting {@link file://./exec.ts WorkspaceClientConfig.shell} is choosing that
|
|
27
|
-
* shell explicitly.
|
|
28
|
-
*/
|
|
29
|
-
function wrapped(command, shell) {
|
|
30
|
-
return `${shell} -o pipefail -c ${shellQuote(command)}`;
|
|
31
|
-
}
|
|
32
|
-
/**
|
|
33
|
-
* Run a command under {@link file://./exec.ts WorkspaceClientConfig.shell} with its
|
|
34
|
-
* two output streams left as they are, or hand it back untouched when no shell
|
|
35
|
-
* is configured.
|
|
36
|
-
*
|
|
37
|
-
* This is the variant for a caller that **reads the result in code**: `stdout` is
|
|
38
|
-
* a data channel it compares or parses, and `stderr` is a separate diagnostic.
|
|
39
|
-
* {@link file://./exec.ts workspaceExec} is that caller, on behalf of
|
|
40
|
-
* `@dynamicagents/plugins/repo`, which asks git questions like
|
|
41
|
-
* `symbolic-ref --short refs/remotes/origin/HEAD` and `rev-list --count` and
|
|
42
|
-
* needs the answer alone.
|
|
43
|
-
*
|
|
44
|
-
* Two functions rather than one with a flag, because the difference is a change
|
|
45
|
-
* to the *output contract* and a boolean hides it at the call site. Merging the
|
|
46
|
-
* streams here would give every `/repo` git command an empty `stderr` and a
|
|
47
|
-
* `stdout` that is a transcript rather than an answer — which fails silently,
|
|
48
|
-
* since the commands `/repo` parses are quiet ones and a single `warning:` is
|
|
49
|
-
* enough to skip the empty-branch guard.
|
|
50
|
-
*/
|
|
51
|
-
export function withShell(command, shell) {
|
|
52
|
-
return shell ? wrapped(command, shell) : command;
|
|
53
|
-
}
|
|
54
|
-
/**
|
|
55
|
-
* Run a command under {@link file://./exec.ts WorkspaceClientConfig.shell} with its
|
|
56
|
-
* two output streams merged into one transcript, in the order they were
|
|
57
|
-
* written.
|
|
58
|
-
*
|
|
59
|
-
* This is the variant for a caller whose consumer is **a model reading output**.
|
|
60
|
-
* `bash` is that caller. A project's check is a chain — `wrangler types &&
|
|
61
|
-
* prettier && eslint && tsc` — and *which tool spoke last* is how you know which
|
|
62
|
-
* one failed. A stdout block and a separate stderr block destroy that ordering,
|
|
63
|
-
* and a model that wants it back re-runs the whole gate as
|
|
64
|
-
* `npm run check > /tmp/out 2>&1; cat /tmp/out`. This is that workaround, done
|
|
65
|
-
* once, for free.
|
|
66
|
-
*
|
|
67
|
-
* The redirect binds to the wrapper process, so it applies to everything the
|
|
68
|
-
* command writes however deeply nested — and there is no inner brace group or
|
|
69
|
-
* subshell to mis-parse a command that already contains `&&`, quotes or redirects
|
|
70
|
-
* of its own.
|
|
71
|
-
*
|
|
72
|
-
* With no shell configured there is no wrapper process to redirect, so the
|
|
73
|
-
* command goes to the runtime untouched and the two streams arrive separate.
|
|
74
|
-
* That is not a gap: {@link file://../computer/render.ts renderResult} renders them as a
|
|
75
|
-
* labelled `--- stderr ---` block for exactly this case. The transcript is the
|
|
76
|
-
* better answer, not the only supported one.
|
|
77
|
-
*/
|
|
78
|
-
export function withShellTranscript(command, shell) {
|
|
79
|
-
return shell ? `${wrapped(command, shell)} 2>&1` : command;
|
|
80
|
-
}
|
package/dist/workspace/sync.d.ts
DELETED
|
@@ -1,111 +0,0 @@
|
|
|
1
|
-
import type { Workspace } from "@cloudflare/computer";
|
|
2
|
-
import type { Deadline } from "@dynamicagents/core/alarm";
|
|
3
|
-
/**
|
|
4
|
-
* The host's half of syncing: moving what the container wrote into the object.
|
|
5
|
-
*
|
|
6
|
-
* ## Why the host has a half at all
|
|
7
|
-
*
|
|
8
|
-
* Every command is bracketed by a sync — a push before it runs, a pull after it
|
|
9
|
-
* exits — and the pull is what carries its writes back into this object's
|
|
10
|
-
* SQLite. That pull can fail while the command itself succeeds: a transport that
|
|
11
|
-
* dropped, a container replaced underneath it. The library reports that on the
|
|
12
|
-
* command's result and schedules nothing of its own afterwards. What it does
|
|
13
|
-
* keep is the cursor, so a later `pull()` resumes the same operation rather than
|
|
14
|
-
* starting one.
|
|
15
|
-
*
|
|
16
|
-
* That later `pull()` is this. Without it the workspace silently lags the
|
|
17
|
-
* container: the file tools read a tree missing the last command's work, and git
|
|
18
|
-
* — which runs on this side — would commit and push it that way.
|
|
19
|
-
*/
|
|
20
|
-
/**
|
|
21
|
-
* How long one drain spends moving blocks before it comes back.
|
|
22
|
-
*
|
|
23
|
-
* The alarm is shared. Every other reason a workspace wakes is queued behind
|
|
24
|
-
* whatever the alarm is doing, so a drain that ran to completion in one
|
|
25
|
-
* invocation would hold the object for as long as the pull takes. A minute
|
|
26
|
-
* finishes an ordinary pull outright and keeps a large one from starving the
|
|
27
|
-
* install watchdog.
|
|
28
|
-
*/
|
|
29
|
-
export declare const SYNC_DRAIN_BUDGET_MS = 60000;
|
|
30
|
-
/** How soon a drain that is making progress comes back for the next block. */
|
|
31
|
-
export declare const SYNC_DRAIN_RESUME_MS = 1000;
|
|
32
|
-
/**
|
|
33
|
-
* The ceiling on the wait after a pull that failed.
|
|
34
|
-
*
|
|
35
|
-
* A failure is not a slow success: whatever broke — a container that stopped
|
|
36
|
-
* answering, a transport that will not open — is usually still broken a second
|
|
37
|
-
* later, and coming back at the resume interval would be an alarm and an error
|
|
38
|
-
* line every second for as long as the workspace stays up. Backing off turns
|
|
39
|
-
* that into a handful of attempts an hour, which is the rate a recoverable
|
|
40
|
-
* fault actually clears at.
|
|
41
|
-
*
|
|
42
|
-
* Bounded rather than abandoned, because the cursor is durable and the cost of
|
|
43
|
-
* one more attempt is one round trip: a container that comes back should be
|
|
44
|
-
* drained without anyone asking.
|
|
45
|
-
*/
|
|
46
|
-
export declare const SYNC_DRAIN_MAX_BACKOFF_MS: number;
|
|
47
|
-
/** How long to wait before a retry, after this many consecutive failures. */
|
|
48
|
-
export declare function syncRetryDelayMs(attempt: number): number;
|
|
49
|
-
/**
|
|
50
|
-
* What one drain achieved.
|
|
51
|
-
*
|
|
52
|
-
* `incomplete` and `failed` are separated because they want opposite responses.
|
|
53
|
-
* `incomplete` is a healthy drain that ran out of budget with the cursor moved,
|
|
54
|
-
* and the right answer is to come straight back. `failed` is a pull that threw
|
|
55
|
-
* with nothing to show for it, and coming straight back would spin against
|
|
56
|
-
* whatever is broken — see {@link syncRetryDelayMs}.
|
|
57
|
-
*
|
|
58
|
-
* `unavailable` is not a failure either: it is the answer when there is no
|
|
59
|
-
* container to pull from, which also means there is nothing outstanding that
|
|
60
|
-
* could still be recovered. Kept distinct from `complete` so a caller deciding
|
|
61
|
-
* whether to act on the workspace — a git push, say — can tell "nothing to move"
|
|
62
|
-
* from "nothing reachable".
|
|
63
|
-
*/
|
|
64
|
-
export type DrainOutcome = "complete" | "incomplete" | "failed" | "unavailable";
|
|
65
|
-
/**
|
|
66
|
-
* What a schedule waiting on a pull carries: how many times it has failed in a
|
|
67
|
-
* row. Both the drain's own deadline and the container-idle deferral that waits
|
|
68
|
-
* for one hold it, since both have to back off against the same fault.
|
|
69
|
-
*/
|
|
70
|
-
export interface SyncDrainIntent {
|
|
71
|
-
attempt: number;
|
|
72
|
-
}
|
|
73
|
-
export interface WorkspaceSyncDeps {
|
|
74
|
-
workspace: () => Workspace;
|
|
75
|
-
/** Whether a container is up. A drain must never start one — see {@link drain}. */
|
|
76
|
-
containerRunning: () => boolean;
|
|
77
|
-
/** Where the next block is scheduled. */
|
|
78
|
-
deadline: () => Deadline<SyncDrainIntent | undefined>;
|
|
79
|
-
tag: () => string;
|
|
80
|
-
id: () => string;
|
|
81
|
-
}
|
|
82
|
-
export declare class WorkspaceSync {
|
|
83
|
-
private readonly deps;
|
|
84
|
-
constructor(deps: WorkspaceSyncDeps);
|
|
85
|
-
/**
|
|
86
|
-
* Come back shortly and move what is still outstanding.
|
|
87
|
-
*
|
|
88
|
-
* A deadline rather than an immediate drain, because the caller is usually
|
|
89
|
-
* holding something that should not wait on a pull — an install's drain, or a
|
|
90
|
-
* request. `set` replaces whatever stood before, so arming twice is one
|
|
91
|
-
* schedule rather than two.
|
|
92
|
-
*/
|
|
93
|
-
arm(attempt?: number): Promise<void>;
|
|
94
|
-
/**
|
|
95
|
-
* Move what the container has written into this object's storage.
|
|
96
|
-
*
|
|
97
|
-
* One block per `next()`, under a budget rather than to completion, because
|
|
98
|
-
* the iterator is disposable by design: the durable state is the cursor the
|
|
99
|
-
* block just committed, so stopping is a normal thing to do and a recreated
|
|
100
|
-
* iterable picks up where this one stopped.
|
|
101
|
-
*
|
|
102
|
-
* **Never starts a container.** Opening a backend handle would launch one, and
|
|
103
|
-
* a pull against a replacement finds an empty filesystem rather than the
|
|
104
|
-
* writes it was after — the library fences that to the runtime that ran the
|
|
105
|
-
* command, but launching a container to discover so is pure cost. A stopped
|
|
106
|
-
* container also means there is nothing left to pull: whatever it held that
|
|
107
|
-
* never arrived is gone, which is why a drain runs *before* an idle deadline
|
|
108
|
-
* stops one.
|
|
109
|
-
*/
|
|
110
|
-
drain(budgetMs: number): Promise<DrainOutcome>;
|
|
111
|
-
}
|
package/dist/workspace/sync.js
DELETED
|
@@ -1,124 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The host's half of syncing: moving what the container wrote into the object.
|
|
3
|
-
*
|
|
4
|
-
* ## Why the host has a half at all
|
|
5
|
-
*
|
|
6
|
-
* Every command is bracketed by a sync — a push before it runs, a pull after it
|
|
7
|
-
* exits — and the pull is what carries its writes back into this object's
|
|
8
|
-
* SQLite. That pull can fail while the command itself succeeds: a transport that
|
|
9
|
-
* dropped, a container replaced underneath it. The library reports that on the
|
|
10
|
-
* command's result and schedules nothing of its own afterwards. What it does
|
|
11
|
-
* keep is the cursor, so a later `pull()` resumes the same operation rather than
|
|
12
|
-
* starting one.
|
|
13
|
-
*
|
|
14
|
-
* That later `pull()` is this. Without it the workspace silently lags the
|
|
15
|
-
* container: the file tools read a tree missing the last command's work, and git
|
|
16
|
-
* — which runs on this side — would commit and push it that way.
|
|
17
|
-
*/
|
|
18
|
-
/**
|
|
19
|
-
* How long one drain spends moving blocks before it comes back.
|
|
20
|
-
*
|
|
21
|
-
* The alarm is shared. Every other reason a workspace wakes is queued behind
|
|
22
|
-
* whatever the alarm is doing, so a drain that ran to completion in one
|
|
23
|
-
* invocation would hold the object for as long as the pull takes. A minute
|
|
24
|
-
* finishes an ordinary pull outright and keeps a large one from starving the
|
|
25
|
-
* install watchdog.
|
|
26
|
-
*/
|
|
27
|
-
export const SYNC_DRAIN_BUDGET_MS = 60_000;
|
|
28
|
-
/** How soon a drain that is making progress comes back for the next block. */
|
|
29
|
-
export const SYNC_DRAIN_RESUME_MS = 1_000;
|
|
30
|
-
/**
|
|
31
|
-
* The ceiling on the wait after a pull that failed.
|
|
32
|
-
*
|
|
33
|
-
* A failure is not a slow success: whatever broke — a container that stopped
|
|
34
|
-
* answering, a transport that will not open — is usually still broken a second
|
|
35
|
-
* later, and coming back at the resume interval would be an alarm and an error
|
|
36
|
-
* line every second for as long as the workspace stays up. Backing off turns
|
|
37
|
-
* that into a handful of attempts an hour, which is the rate a recoverable
|
|
38
|
-
* fault actually clears at.
|
|
39
|
-
*
|
|
40
|
-
* Bounded rather than abandoned, because the cursor is durable and the cost of
|
|
41
|
-
* one more attempt is one round trip: a container that comes back should be
|
|
42
|
-
* drained without anyone asking.
|
|
43
|
-
*/
|
|
44
|
-
export const SYNC_DRAIN_MAX_BACKOFF_MS = 5 * 60_000;
|
|
45
|
-
/** How long to wait before a retry, after this many consecutive failures. */
|
|
46
|
-
export function syncRetryDelayMs(attempt) {
|
|
47
|
-
return Math.min(SYNC_DRAIN_RESUME_MS * 2 ** Math.max(0, attempt), SYNC_DRAIN_MAX_BACKOFF_MS);
|
|
48
|
-
}
|
|
49
|
-
export class WorkspaceSync {
|
|
50
|
-
deps;
|
|
51
|
-
constructor(deps) {
|
|
52
|
-
this.deps = deps;
|
|
53
|
-
}
|
|
54
|
-
/**
|
|
55
|
-
* Come back shortly and move what is still outstanding.
|
|
56
|
-
*
|
|
57
|
-
* A deadline rather than an immediate drain, because the caller is usually
|
|
58
|
-
* holding something that should not wait on a pull — an install's drain, or a
|
|
59
|
-
* request. `set` replaces whatever stood before, so arming twice is one
|
|
60
|
-
* schedule rather than two.
|
|
61
|
-
*/
|
|
62
|
-
async arm(attempt = 0) {
|
|
63
|
-
await this.deps
|
|
64
|
-
.deadline()
|
|
65
|
-
.set(new Date(Date.now() + syncRetryDelayMs(attempt)), { attempt });
|
|
66
|
-
}
|
|
67
|
-
/**
|
|
68
|
-
* Move what the container has written into this object's storage.
|
|
69
|
-
*
|
|
70
|
-
* One block per `next()`, under a budget rather than to completion, because
|
|
71
|
-
* the iterator is disposable by design: the durable state is the cursor the
|
|
72
|
-
* block just committed, so stopping is a normal thing to do and a recreated
|
|
73
|
-
* iterable picks up where this one stopped.
|
|
74
|
-
*
|
|
75
|
-
* **Never starts a container.** Opening a backend handle would launch one, and
|
|
76
|
-
* a pull against a replacement finds an empty filesystem rather than the
|
|
77
|
-
* writes it was after — the library fences that to the runtime that ran the
|
|
78
|
-
* command, but launching a container to discover so is pure cost. A stopped
|
|
79
|
-
* container also means there is nothing left to pull: whatever it held that
|
|
80
|
-
* never arrived is gone, which is why a drain runs *before* an idle deadline
|
|
81
|
-
* stops one.
|
|
82
|
-
*/
|
|
83
|
-
async drain(budgetMs) {
|
|
84
|
-
if (!this.deps.containerRunning())
|
|
85
|
-
return "unavailable";
|
|
86
|
-
const stopAt = Date.now() + budgetMs;
|
|
87
|
-
let blocks = 0;
|
|
88
|
-
let entries = 0;
|
|
89
|
-
try {
|
|
90
|
-
for await (const progress of this.deps.workspace().pull()) {
|
|
91
|
-
blocks += 1;
|
|
92
|
-
entries += progress.entries;
|
|
93
|
-
if (progress.complete) {
|
|
94
|
-
// Silent for the ordinary case — one empty block, which is what a
|
|
95
|
-
// workspace with nothing outstanding returns on every check.
|
|
96
|
-
if (blocks > 1 || entries > 0) {
|
|
97
|
-
console.info(`[${this.deps.tag()}] pull drained`, {
|
|
98
|
-
id: this.deps.id(),
|
|
99
|
-
blocks,
|
|
100
|
-
entries
|
|
101
|
-
});
|
|
102
|
-
}
|
|
103
|
-
return "complete";
|
|
104
|
-
}
|
|
105
|
-
if (Date.now() >= stopAt)
|
|
106
|
-
return "incomplete";
|
|
107
|
-
}
|
|
108
|
-
// The iterable ended without a block claiming completion, which is what a
|
|
109
|
-
// backend with nothing to sync returns. Nothing is outstanding either way.
|
|
110
|
-
return "complete";
|
|
111
|
-
}
|
|
112
|
-
catch (err) {
|
|
113
|
-
// Left outstanding rather than retried here: the cursor is durable, so the
|
|
114
|
-
// next drain resumes whatever this one committed before it threw.
|
|
115
|
-
console.error(`[${this.deps.tag()}] a pull could not be drained`, {
|
|
116
|
-
id: this.deps.id(),
|
|
117
|
-
blocks,
|
|
118
|
-
entries,
|
|
119
|
-
err: String(err)
|
|
120
|
-
});
|
|
121
|
-
return "failed";
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
}
|
package/dist/workspace/wake.d.ts
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* What a workspace object wakes for, as one map.
|
|
3
|
-
*
|
|
4
|
-
* Its own module because the object that registers these callbacks and the
|
|
5
|
-
* `JobLifecycle` in `./install-job.ts` that schedules some of them by name both type
|
|
6
|
-
* against it, and neither should own it. A name that exists in one and not the
|
|
7
|
-
* other is then a compile error rather than a schedule that is rejected at
|
|
8
|
-
* runtime.
|
|
9
|
-
*/
|
|
10
|
-
import type { SyncDrainIntent } from "./sync.js";
|
|
11
|
-
export type WorkspaceWakeHandlers = {
|
|
12
|
-
installRun: () => Promise<void>;
|
|
13
|
-
installWatch: () => Promise<void>;
|
|
14
|
-
idleReclaim: () => Promise<void>;
|
|
15
|
-
/** Start a cold container before a command needs it — see `./object.ts`. */
|
|
16
|
-
containerWarm: () => Promise<void>;
|
|
17
|
-
/** Snapshot a container that just installed — see `./deps-snapshot.ts`. */
|
|
18
|
-
depsSnapshot: () => Promise<void>;
|
|
19
|
-
containerIdle: (payload?: SyncDrainIntent) => Promise<void>;
|
|
20
|
-
syncRetry: (payload?: SyncDrainIntent) => Promise<void>;
|
|
21
|
-
};
|
package/dist/workspace/wake.js
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* What a workspace object wakes for, as one map.
|
|
3
|
-
*
|
|
4
|
-
* Its own module because the object that registers these callbacks and the
|
|
5
|
-
* `JobLifecycle` in `./install-job.ts` that schedules some of them by name both type
|
|
6
|
-
* against it, and neither should own it. A name that exists in one and not the
|
|
7
|
-
* other is then a compile error rather than a schedule that is rejected at
|
|
8
|
-
* runtime.
|
|
9
|
-
*/
|
|
10
|
-
export {};
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|