@dynamicagents/plugins 0.13.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.
Files changed (141) hide show
  1. package/README.md +14 -14
  2. package/dist/claude-code/cards.d.ts +4 -0
  3. package/dist/claude-code/cards.js +22 -0
  4. package/dist/claude-code/config.d.ts +10 -83
  5. package/dist/claude-code/config.js +0 -2
  6. package/dist/claude-code/credentials.d.ts +32 -50
  7. package/dist/claude-code/credentials.js +115 -74
  8. package/dist/claude-code/daemon/index.d.ts +24 -0
  9. package/dist/claude-code/daemon/index.js +203 -0
  10. package/dist/claude-code/egress.d.ts +35 -117
  11. package/dist/claude-code/egress.js +80 -325
  12. package/dist/claude-code/events.d.ts +14 -17
  13. package/dist/claude-code/events.js +19 -15
  14. package/dist/claude-code/harness-wire.d.ts +45 -0
  15. package/dist/claude-code/harness-wire.js +47 -0
  16. package/dist/claude-code/index.d.ts +19 -29
  17. package/dist/claude-code/index.js +17 -25
  18. package/dist/claude-code/language-model.d.ts +19 -0
  19. package/dist/claude-code/language-model.js +71 -0
  20. package/dist/claude-code/model.d.ts +77 -70
  21. package/dist/claude-code/model.js +328 -304
  22. package/dist/claude-code/placeholder.d.ts +12 -0
  23. package/dist/claude-code/placeholder.js +12 -0
  24. package/dist/claude-code/spec.d.ts +4 -4
  25. package/dist/claude-code/spec.js +4 -4
  26. package/dist/claude-code/verified.d.ts +1 -1
  27. package/dist/claude-code/verified.js +1 -1
  28. package/dist/computer/client.d.ts +88 -0
  29. package/dist/computer/client.js +6 -0
  30. package/dist/computer/context.d.ts +7 -7
  31. package/dist/computer/context.js +14 -18
  32. package/dist/computer/gate.d.ts +4 -23
  33. package/dist/computer/gate.js +1 -37
  34. package/dist/computer/index.d.ts +44 -43
  35. package/dist/computer/index.js +29 -50
  36. package/dist/computer/paths.d.ts +5 -27
  37. package/dist/computer/paths.js +7 -30
  38. package/dist/computer/proxy.d.ts +17 -31
  39. package/dist/computer/proxy.js +9 -44
  40. package/dist/computer/render.d.ts +3 -40
  41. package/dist/computer/render.js +3 -36
  42. package/dist/computer/sandbox.d.ts +55 -0
  43. package/dist/computer/sandbox.js +236 -0
  44. package/dist/computer/shell.d.ts +36 -0
  45. package/dist/computer/shell.js +41 -0
  46. package/dist/computer/tools-exec.js +3 -9
  47. package/dist/computer/tools-file.d.ts +1 -1
  48. package/dist/computer/tools-file.js +1 -1
  49. package/dist/{repo → repo-github}/checkout.d.ts +3 -4
  50. package/dist/{repo → repo-github}/checkout.js +3 -4
  51. package/dist/{repo → repo-github}/context.d.ts +14 -32
  52. package/dist/{repo → repo-github}/context.js +46 -81
  53. package/dist/{repo → repo-github}/index.d.ts +30 -13
  54. package/dist/{repo → repo-github}/index.js +25 -6
  55. package/dist/repo-github/mcp.d.ts +95 -0
  56. package/dist/repo-github/mcp.js +107 -0
  57. package/dist/repo-github/sandbox-egress.d.ts +68 -0
  58. package/dist/repo-github/sandbox-egress.js +272 -0
  59. package/dist/repo-github/sandbox-git.d.ts +30 -0
  60. package/dist/repo-github/sandbox-git.js +113 -0
  61. package/dist/{repo → repo-github}/tools-checks.js +43 -4
  62. package/dist/{repo → repo-github}/tools-clone.js +2 -21
  63. package/dist/{repo → repo-github}/tools-pr.d.ts +0 -1
  64. package/dist/{repo → repo-github}/tools-pr.js +85 -20
  65. package/dist/{repo → repo-github}/tools-review.d.ts +6 -0
  66. package/dist/{repo → repo-github}/tools-review.js +62 -176
  67. package/dist/{repo → repo-github}/url.d.ts +11 -0
  68. package/dist/{repo → repo-github}/url.js +12 -1
  69. package/dist/{workspace → sandbox}/advisory.d.ts +16 -35
  70. package/dist/{workspace → sandbox}/advisory.js +2 -29
  71. package/dist/sandbox/agent-exec.d.ts +31 -0
  72. package/dist/sandbox/agent-exec.js +62 -0
  73. package/dist/sandbox/ca-trust.d.ts +9 -0
  74. package/dist/sandbox/ca-trust.js +21 -0
  75. package/dist/sandbox/constants.d.ts +22 -0
  76. package/dist/sandbox/constants.js +22 -0
  77. package/dist/sandbox/daemon/composite.d.ts +9 -0
  78. package/dist/sandbox/daemon/composite.js +35 -0
  79. package/dist/sandbox/daemon/index.d.ts +47 -0
  80. package/dist/sandbox/daemon/index.js +116 -0
  81. package/dist/sandbox/egress.d.ts +81 -0
  82. package/dist/sandbox/egress.js +109 -0
  83. package/dist/sandbox/exec.d.ts +57 -0
  84. package/dist/sandbox/exec.js +52 -0
  85. package/dist/sandbox/format.d.ts +2 -0
  86. package/dist/sandbox/format.js +7 -0
  87. package/dist/sandbox/header.d.ts +50 -0
  88. package/dist/sandbox/header.js +94 -0
  89. package/dist/sandbox/index.d.ts +17 -0
  90. package/dist/sandbox/index.js +17 -0
  91. package/dist/{workspace/install.d.ts → sandbox/install-plan.d.ts} +10 -1
  92. package/dist/{workspace/install.js → sandbox/install-plan.js} +22 -4
  93. package/dist/sandbox/name.d.ts +27 -0
  94. package/dist/sandbox/name.js +32 -0
  95. package/dist/sandbox/object.d.ts +244 -0
  96. package/dist/sandbox/object.js +1139 -0
  97. package/dist/scratch/index.d.ts +1 -9
  98. package/dist/scratch/index.js +2 -18
  99. package/package.json +26 -22
  100. package/dist/claude-code/github.d.ts +0 -39
  101. package/dist/claude-code/github.js +0 -82
  102. package/dist/claude-code/run.d.ts +0 -474
  103. package/dist/claude-code/run.js +0 -901
  104. package/dist/claude-code/session.d.ts +0 -131
  105. package/dist/claude-code/session.js +0 -285
  106. package/dist/workspace/ca-trust.d.ts +0 -95
  107. package/dist/workspace/ca-trust.js +0 -312
  108. package/dist/workspace/container-deps.d.ts +0 -54
  109. package/dist/workspace/container-deps.js +0 -224
  110. package/dist/workspace/container-fault.d.ts +0 -38
  111. package/dist/workspace/container-fault.js +0 -73
  112. package/dist/workspace/exec.d.ts +0 -94
  113. package/dist/workspace/exec.js +0 -153
  114. package/dist/workspace/format.d.ts +0 -36
  115. package/dist/workspace/format.js +0 -57
  116. package/dist/workspace/git-host.d.ts +0 -79
  117. package/dist/workspace/git-host.js +0 -226
  118. package/dist/workspace/git-identity.d.ts +0 -57
  119. package/dist/workspace/git-identity.js +0 -147
  120. package/dist/workspace/index.d.ts +0 -49
  121. package/dist/workspace/index.js +0 -58
  122. package/dist/workspace/install-job.d.ts +0 -121
  123. package/dist/workspace/install-job.js +0 -866
  124. package/dist/workspace/object.d.ts +0 -502
  125. package/dist/workspace/object.js +0 -1427
  126. package/dist/workspace/open.d.ts +0 -95
  127. package/dist/workspace/open.js +0 -63
  128. package/dist/workspace/read.d.ts +0 -16
  129. package/dist/workspace/read.js +0 -22
  130. package/dist/workspace/shell.d.ts +0 -45
  131. package/dist/workspace/shell.js +0 -80
  132. package/dist/workspace/sync.d.ts +0 -111
  133. package/dist/workspace/sync.js +0 -124
  134. package/dist/workspace/wake.d.ts +0 -19
  135. package/dist/workspace/wake.js +0 -10
  136. /package/dist/{repo → repo-github}/tools-checks.d.ts +0 -0
  137. /package/dist/{repo → repo-github}/tools-clone.d.ts +0 -0
  138. /package/dist/{repo → repo-github}/tools-worktree.d.ts +0 -0
  139. /package/dist/{repo → repo-github}/tools-worktree.js +0 -0
  140. /package/dist/{repo → repo-github}/tools-worktrees.d.ts +0 -0
  141. /package/dist/{repo → repo-github}/tools-worktrees.js +0 -0
@@ -1,226 +0,0 @@
1
- /**
2
- * What the container's own `git init` would write, over isomorphic-git's.
3
- *
4
- * isomorphic-git's `init` writes `core.*` for a filesystem without symlinks or
5
- * an executable bit that ignores case, and the container's git obeys it. With
6
- * `symlinks = false`, a command there that rewrites the tree — starter puts a
7
- * worktree on its branch with `checkout -f` — writes each link as a file holding
8
- * its target, and `status` calls that clean. With `filemode = false`, a script
9
- * made executable is committed as 100644. The store models all three.
10
- */
11
- const CONTAINER_CORE_CONFIG = {
12
- "core.symlinks": true,
13
- "core.filemode": true,
14
- "core.ignorecase": false
15
- };
16
- export class WorkspaceGitHost {
17
- deps;
18
- constructor(deps) {
19
- this.deps = deps;
20
- }
21
- /**
22
- * Each operation takes `url` explicitly rather than a remote name: resolving
23
- * `origin` would read `.git/config`, a workspace file a co-installed shell
24
- * tool can write.
25
- */
26
- async clone(req) {
27
- return this.#run(req.allowedHosts, async (git, onAuth) => {
28
- // Spelled out rather than `git.clone`, and the reason is the credential.
29
- //
30
- // `clone` is the one network operation the client does not give an
31
- // `onAuth` callback — it authenticates only through a `headers` option,
32
- // which means attaching the token to the very first request to a URL the
33
- // *model* chose. Composing the same work out of `fetch` puts every
34
- // credentialed request on this side of `onAuth` instead, where the host is
35
- // checked at the moment the token would be handed over. The cost is four
36
- // calls instead of one; `clone` is these four.
37
- await git.init({ dir: req.dir });
38
- // Straight after `init`, so a clone that fails part-way leaves nothing
39
- // behind that the container's git would misread.
40
- for (const [path, value] of Object.entries(CONTAINER_CORE_CONFIG))
41
- await git.configSet({ dir: req.dir, path, value });
42
- await git.remoteAdd({
43
- dir: req.dir,
44
- name: "origin",
45
- url: req.url,
46
- force: true
47
- });
48
- const fetched = await git.fetch({
49
- url: req.url,
50
- dir: req.dir,
51
- onAuth,
52
- // Omission is passed through as omission, because the tool the model
53
- // reads says so: `repo_clone` describes `depth` as "omit for full
54
- // history; needed if you must rebase", and `/repo` deliberately leaves
55
- // the key off when it is unset. Defaulting to 1 here made every such
56
- // clone shallow, so the one thing the model was told to omit it for —
57
- // rebasing — failed on a repository it had asked for in full.
58
- ...(req.depth === undefined ? {} : { depth: req.depth }),
59
- singleBranch: true,
60
- tags: false,
61
- ...(req.branch ? { ref: req.branch } : {})
62
- });
63
- const landed = req.branch ?? fetched.defaultBranch?.replace(/^refs\/heads\//, "");
64
- if (!landed)
65
- throw new Error(`cloned ${req.url} but the remote named no default branch to check out`);
66
- await git.checkout({ dir: req.dir, ref: landed });
67
- // What a real `git clone` writes and the container's git will look for:
68
- // without it the branch tracks nothing, and an agent reaching for a bare
69
- // `git status` in the shell sees a branch with no upstream.
70
- await git.configSet({
71
- dir: req.dir,
72
- path: `branch.${landed}.remote`,
73
- value: "origin"
74
- });
75
- await git.configSet({
76
- dir: req.dir,
77
- path: `branch.${landed}.merge`,
78
- value: `refs/heads/${landed}`
79
- });
80
- return landed;
81
- });
82
- }
83
- async fetch(req) {
84
- return this.#run(req.allowedHosts, async (git, onAuth) => {
85
- const result = await git.fetch({
86
- url: req.url,
87
- dir: req.dir,
88
- onAuth,
89
- prune: true,
90
- tags: false,
91
- singleBranch: false,
92
- // Every branch is fetched, but isomorphic-git still resolves one ref
93
- // against the remote's list, and left to itself it picks the current
94
- // branch's upstream. A checkout left on a branch whose pull request
95
- // merged — and whose remote branch went with it — then fails every
96
- // fetch with `Could not find refs/heads/<branch>`. The remote's HEAD
97
- // is always listed.
98
- remoteRef: "HEAD",
99
- ...(req.depth ? { depth: req.depth } : {})
100
- });
101
- return `fetched ${req.url} (default branch ${result.defaultBranch ?? "unknown"})`;
102
- });
103
- }
104
- /**
105
- * `remote.origin.url` from the local store, or `undefined` where there is no
106
- * checkout or no origin. Reads only, and needs no credential.
107
- */
108
- async origin(dir) {
109
- try {
110
- const url = await this.deps
111
- .git()
112
- .configGet({ dir, path: "remote.origin.url" });
113
- return typeof url === "string" && url ? url : undefined;
114
- }
115
- catch {
116
- return undefined;
117
- }
118
- }
119
- async push(req) {
120
- return this.#run(req.allowedHosts, async (git, onAuth) => {
121
- const result = await git.push({
122
- url: req.url,
123
- dir: req.dir,
124
- ref: req.branch,
125
- remoteRef: req.branch,
126
- onAuth
127
- // No `force`, ever, and not a knob: `/repo` refuses anything but a plain
128
- // branch name precisely so that a push cannot be turned into a force
129
- // push, and this is the other end of that promise.
130
- });
131
- // isomorphic-git reports a rejected push in the *result* rather than by
132
- // throwing — a non-fast-forward comes back `ok: false` with the reason on
133
- // the ref. Reading only the absence of an exception would report every
134
- // rejected push as a success, in the one plugin whose entire theme is that
135
- // a failed command is not a completed operation.
136
- if (!result.ok) {
137
- const perRef = Object.entries(result.refs)
138
- .filter(([, status]) => !status.ok)
139
- .map(([ref, status]) => `${ref}: ${status.error ?? "rejected"}`)
140
- .join("; ");
141
- // `||`, not `??`, on the second rung: `perRef` is a joined string, so
142
- // "no failing ref carried a reason" is `""` rather than nullish — and
143
- // `??` would hand that through as the error message. A rejected push
144
- // reporting a blank reason is the one outcome worse than a generic one.
145
- throw new Error(result.error ?? (perRef || "the remote rejected the push"));
146
- }
147
- return `pushed ${req.branch} to ${req.url}`;
148
- });
149
- }
150
- /**
151
- * The shared body: entry-point bookkeeping, the credential, and the translation
152
- * back into something that survives RPC.
153
- *
154
- * A thrown `GitError` loses its prototype crossing a Durable Object boundary,
155
- * so `instanceof` on the far side is not available and the caller would be left
156
- * pattern-matching a string. The `code` is lifted here, while the error is
157
- * still itself, and travels as data.
158
- */
159
- async #run(allowedHosts, body) {
160
- // Bound to the credential rather than checked before the call, which is
161
- // strictly stronger: this is the moment the token would be handed over, and
162
- // it sees the URL git actually authenticated against — including one it
163
- // reached by redirect. A host nobody allowed gets no credential and the
164
- // request fails unauthenticated, rather than the token being offered to it
165
- // and *then* the mistake being noticed.
166
- const onAuth = (url) => {
167
- let host;
168
- try {
169
- const parsed = new URL(url);
170
- if (parsed.protocol !== "https:")
171
- return {};
172
- host = parsed.hostname;
173
- }
174
- catch {
175
- return {};
176
- }
177
- if (!allowedHosts.includes(host)) {
178
- console.warn(`[${this.deps.tag()}] refused to authenticate to a host`, {
179
- host
180
- });
181
- return {};
182
- }
183
- return { username: "x-access-token", password: this.deps.token() };
184
- };
185
- try {
186
- return { ok: true, detail: await body(this.deps.git(), onAuth) };
187
- }
188
- catch (err) {
189
- const code = err?.code;
190
- const message = describeGitError(err);
191
- console.error(`[${this.deps.tag()}] git failed`, { code, message });
192
- return {
193
- ok: false,
194
- ...(typeof code === "string" ? { code } : {}),
195
- message
196
- };
197
- }
198
- }
199
- }
200
- /**
201
- * A git error's message with the chain of causes behind it.
202
- *
203
- * `@cloudflare/computer/git` wraps isomorphic-git's errors, and classifies some
204
- * by a heuristic: any failure whose message mentions `.git` beside a missing
205
- * path or a ref it could not find is reported as "not a git repository" — a
206
- * sentence that is wrong about a checkout that plainly is one, and names
207
- * neither the file nor the ref. What actually failed is only on `cause`, which
208
- * a Durable Object boundary does not carry, so it is folded into the message
209
- * here while the error is still itself.
210
- */
211
- export function describeGitError(err) {
212
- const parts = [];
213
- const seen = new Set();
214
- let at = err;
215
- for (let depth = 0; at !== undefined && at !== null && depth < 4; depth++) {
216
- const e = at;
217
- const text = typeof e.message === "string" ? e.message : String(at);
218
- if (!seen.has(text)) {
219
- seen.add(text);
220
- const name = typeof e.name === "string" ? e.name : "";
221
- parts.push(name && depth > 0 ? `${name}: ${text}` : text);
222
- }
223
- at = e.cause;
224
- }
225
- return parts.join(" ← ");
226
- }
@@ -1,57 +0,0 @@
1
- import type { Workspace } from "@cloudflare/computer";
2
- /**
3
- * The identity a commit made in this container carries when nothing nearer
4
- * answers for it.
5
- *
6
- * `/repo` configures the checkouts it clones and names the identity on every
7
- * commit it makes — see {@link file://../repo/checkout.ts writeGitIdentity}.
8
- * Neither reaches a repository the container made for itself: a submodule
9
- * checked out by a bootstrap, a `git init`, a second clone from the shell. Those
10
- * have no identity at all, and git refuses to commit without one — so whatever
11
- * is driving the shell has to invent a name to get past the refusal, and that
12
- * invention is what ends up in the history.
13
- *
14
- * This is the layer underneath, so there is nothing to invent: every repository
15
- * in the container starts out attributed to the deployment.
16
- *
17
- * **System scope, not global.** `--global` writes `$HOME/.gitconfig`, and a
18
- * command run through the runtime cannot count on `HOME` being set to anything
19
- * in particular — nor is the identity a property of one user of the container.
20
- * `--system` is also the *lowest* precedence git has, which is the right place
21
- * for it: a checkout's own config still wins, and so does the environment
22
- * `/repo` and the session's launch put on a commit.
23
- */
24
- /** Written to `/etc/gitconfig`; the values arrive as variables, never inline. */
25
- export declare const GIT_IDENTITY_COMMAND: string;
26
- export interface ContainerGitIdentityDeps {
27
- workspace: () => Workspace;
28
- author: () => {
29
- name: string;
30
- email: string;
31
- };
32
- /** Log prefix and object id, for the one line an operator can see. */
33
- tag: () => string;
34
- id: () => string;
35
- }
36
- /**
37
- * The write above, once per container.
38
- *
39
- * In memory, with {@link file://./ca-trust.ts}'s lifetime and for its reason: it
40
- * describes one container, and an isolate that lost it re-runs an idempotent
41
- * command.
42
- */
43
- export declare class ContainerGitIdentity {
44
- #private;
45
- private readonly deps;
46
- constructor(deps: ContainerGitIdentityDeps);
47
- forget(): void;
48
- /**
49
- * Configure this container if it has not been configured yet.
50
- *
51
- * **Never throws**, like the CA install and unlike the dependency setup. What
52
- * a failure costs is an attribution, and every later commit says plainly that
53
- * it has no identity to use — where a throw here would fail a workspace that
54
- * is otherwise entirely usable.
55
- */
56
- ensure(): Promise<void>;
57
- }
@@ -1,147 +0,0 @@
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
- /**
54
- * The identity a commit made in this container carries when nothing nearer
55
- * answers for it.
56
- *
57
- * `/repo` configures the checkouts it clones and names the identity on every
58
- * commit it makes — see {@link file://../repo/checkout.ts writeGitIdentity}.
59
- * Neither reaches a repository the container made for itself: a submodule
60
- * checked out by a bootstrap, a `git init`, a second clone from the shell. Those
61
- * have no identity at all, and git refuses to commit without one — so whatever
62
- * is driving the shell has to invent a name to get past the refusal, and that
63
- * invention is what ends up in the history.
64
- *
65
- * This is the layer underneath, so there is nothing to invent: every repository
66
- * in the container starts out attributed to the deployment.
67
- *
68
- * **System scope, not global.** `--global` writes `$HOME/.gitconfig`, and a
69
- * command run through the runtime cannot count on `HOME` being set to anything
70
- * in particular — nor is the identity a property of one user of the container.
71
- * `--system` is also the *lowest* precedence git has, which is the right place
72
- * for it: a checkout's own config still wins, and so does the environment
73
- * `/repo` and the session's launch put on a commit.
74
- */
75
- /** Written to `/etc/gitconfig`; the values arrive as variables, never inline. */
76
- export const GIT_IDENTITY_COMMAND = [
77
- 'git config --system user.name "$GIT_NAME"',
78
- 'git config --system user.email "$GIT_EMAIL"',
79
- "echo IDENTITY OK"
80
- ].join(" && ");
81
- /** How long the write may take before it is not going to happen. */
82
- const IDENTITY_TIMEOUT_MS = 30_000;
83
- /**
84
- * The write above, once per container.
85
- *
86
- * In memory, with {@link file://./ca-trust.ts}'s lifetime and for its reason: it
87
- * describes one container, and an isolate that lost it re-runs an idempotent
88
- * command.
89
- */
90
- export class ContainerGitIdentity {
91
- deps;
92
- #done = false;
93
- constructor(deps) {
94
- this.deps = deps;
95
- }
96
- forget() {
97
- this.#done = false;
98
- }
99
- /**
100
- * Configure this container if it has not been configured yet.
101
- *
102
- * **Never throws**, like the CA install and unlike the dependency setup. What
103
- * a failure costs is an attribution, and every later commit says plainly that
104
- * it has no identity to use — where a throw here would fail a workspace that
105
- * is otherwise entirely usable.
106
- */
107
- async ensure() {
108
- if (this.#done)
109
- return;
110
- const author = this.deps.author();
111
- try {
112
- const env_1 = { stack: [], error: void 0, hasError: false };
113
- try {
114
- const handle = __addDisposableResource(env_1, await this.deps
115
- .workspace()
116
- .runtime.exec(GIT_IDENTITY_COMMAND, {
117
- cwd: "/",
118
- encoding: "utf8",
119
- timeoutMs: IDENTITY_TIMEOUT_MS,
120
- env: { GIT_NAME: author.name, GIT_EMAIL: author.email }
121
- }), false);
122
- const result = await handle.result();
123
- const output = `${result.stdout ?? ""}${result.stderr ?? ""}`;
124
- this.#done = result.exitCode === 0 && output.includes("IDENTITY OK");
125
- if (this.#done)
126
- return;
127
- console.warn(`[${this.deps.tag()}] could not set the container's git identity`, {
128
- id: this.deps.id(),
129
- output: output.trim()
130
- });
131
- }
132
- catch (e_1) {
133
- env_1.error = e_1;
134
- env_1.hasError = true;
135
- }
136
- finally {
137
- __disposeResources(env_1);
138
- }
139
- }
140
- catch (err) {
141
- console.warn(`[${this.deps.tag()}] could not set the container's git identity`, {
142
- id: this.deps.id(),
143
- err: String(err)
144
- });
145
- }
146
- }
147
- }
@@ -1,49 +0,0 @@
1
- /**
2
- * `@dynamicagents/plugins/workspace` — the Durable Object a container workspace
3
- * lives in, and the client side every other plugin reaches it through.
4
- *
5
- * The filesystem **is** a Durable Object's SQLite, mounted into the container
6
- * over FUSE by `computerd`. Commands see a normal `/workspace`; the Worker reads
7
- * the same tree over RPC; and when the container is replaced the tree is pushed
8
- * back into the new one — so a checkout outlives the container that held it.
9
- *
10
- * `WorkspaceObjectBase` is the object: container backend, egress, CA trust,
11
- * credentialed git, the dependency install, the sync drain and idle reclaim. A
12
- * host subclasses it and answers a short config. Everything else here is what
13
- * reaches it from outside: `openWorkspace`, `workspaceExec`, and the advisory
14
- * vocabulary it reports its state in.
15
- *
16
- * `@dynamicagents/plugins/computer` is the agent's tools over it; `/repo` and
17
- * `/scratch` take `workspaceExec` injected.
18
- *
19
- * Requires the Workers **Paid** plan (containers) and a Durable Object binding
20
- * whose class extends `WorkspaceObjectBase` — see the README for the wrangler
21
- * block.
22
- */
23
- /** How a repository installs its dependencies — the mechanical half. */
24
- export { DEFAULT_INSTALL_PLAN, installFingerprint, resolveInstallCommand, type InstallPlan, type InstallProbe, type InstallResolution, type InstallRule, type InstallState } from "./install.js";
25
- /**
26
- * The workspace-advisory vocabulary, which a host needs all of: the type to
27
- * return over RPC, `deriveAdvisories` to build it from what it already knows,
28
- * and `sessionAdvisory` for a host driving a whole session rather than one
29
- * command. `shapeOf` and `renderAdvisory` are exported for the specs that hold
30
- * their exhaustiveness — a host has no reason to call either, since calling them
31
- * would mean writing policy or wording that has one home already.
32
- */
33
- export { deriveAdvisories, renderAdvisory, sessionAdvisory, shapeOf, type AdvisoryAudience, type AdvisoryInput, type AdvisoryShape, type WorkspaceAdvisory } from "./advisory.js";
34
- export { pathExists } from "./read.js";
35
- export { cancelledNote, truncateOutput } from "./format.js";
36
- export { openWorkspace, openWorkspaceFs, workspaceNameFromRuntime, WORKSPACE_RUNTIME_KEY, type WorkspaceHost } from "./open.js";
37
- export { withShell, withShellTranscript } from "./shell.js";
38
- export { workspaceExec, DEFAULT_CWD, DEFAULT_TIMEOUT_MS, type WorkspaceClientConfig } from "./exec.js";
39
- /**
40
- * The object itself. The modules below import the client-side leaves beside
41
- * them, never this barrel: a cycle through a module that builds a class at
42
- * import time is a base that evaluates `undefined`.
43
- */
44
- export { WorkspaceObjectBase, IDLE_RECLAIM_MS, WORKSPACE_DIR, workspaceName, type WorkspaceObjectConfig, type WorkspaceGitConfig } from "./object.js";
45
- export { InstallJob, type InstallJobDeps } from "./install-job.js";
46
- export { WorkspaceSync, SYNC_DRAIN_BUDGET_MS, SYNC_DRAIN_RESUME_MS, SYNC_DRAIN_MAX_BACKOFF_MS, syncRetryDelayMs, type DrainOutcome, type SyncDrainIntent, type WorkspaceSyncDeps } from "./sync.js";
47
- export { ContainerTrust, TRUST_CA_COMMAND, type ContainerTrustDeps } from "./ca-trust.js";
48
- export { WorkspaceGitHost, type GitHostDeps } from "./git-host.js";
49
- export type { WorkspaceWakeHandlers } from "./wake.js";
@@ -1,58 +0,0 @@
1
- /**
2
- * `@dynamicagents/plugins/workspace` — the Durable Object a container workspace
3
- * lives in, and the client side every other plugin reaches it through.
4
- *
5
- * The filesystem **is** a Durable Object's SQLite, mounted into the container
6
- * over FUSE by `computerd`. Commands see a normal `/workspace`; the Worker reads
7
- * the same tree over RPC; and when the container is replaced the tree is pushed
8
- * back into the new one — so a checkout outlives the container that held it.
9
- *
10
- * `WorkspaceObjectBase` is the object: container backend, egress, CA trust,
11
- * credentialed git, the dependency install, the sync drain and idle reclaim. A
12
- * host subclasses it and answers a short config. Everything else here is what
13
- * reaches it from outside: `openWorkspace`, `workspaceExec`, and the advisory
14
- * vocabulary it reports its state in.
15
- *
16
- * `@dynamicagents/plugins/computer` is the agent's tools over it; `/repo` and
17
- * `/scratch` take `workspaceExec` injected.
18
- *
19
- * Requires the Workers **Paid** plan (containers) and a Durable Object binding
20
- * whose class extends `WorkspaceObjectBase` — see the README for the wrangler
21
- * block.
22
- */
23
- /** How a repository installs its dependencies — the mechanical half. */
24
- export { DEFAULT_INSTALL_PLAN, installFingerprint, resolveInstallCommand } from "./install.js";
25
- /**
26
- * The workspace-advisory vocabulary, which a host needs all of: the type to
27
- * return over RPC, `deriveAdvisories` to build it from what it already knows,
28
- * and `sessionAdvisory` for a host driving a whole session rather than one
29
- * command. `shapeOf` and `renderAdvisory` are exported for the specs that hold
30
- * their exhaustiveness — a host has no reason to call either, since calling them
31
- * would mean writing policy or wording that has one home already.
32
- */
33
- export { deriveAdvisories, renderAdvisory, sessionAdvisory, shapeOf } from "./advisory.js";
34
- // A host implementing `InstallProbe` needs exactly this, and hand-rolling it
35
- // loses the fast path: across a Durable Object boundary `fs` is a stub carrying
36
- // `exists`, which a `stat`-only probe never asks for.
37
- export { pathExists } from "./read.js";
38
- export { cancelledNote, truncateOutput } from "./format.js";
39
- export { openWorkspace, openWorkspaceFs, workspaceNameFromRuntime, WORKSPACE_RUNTIME_KEY } from "./open.js";
40
- export { withShell, withShellTranscript } from "./shell.js";
41
- export { workspaceExec, DEFAULT_CWD, DEFAULT_TIMEOUT_MS } from "./exec.js";
42
- /**
43
- * The object itself. The modules below import the client-side leaves beside
44
- * them, never this barrel: a cycle through a module that builds a class at
45
- * import time is a base that evaluates `undefined`.
46
- */
47
- export { WorkspaceObjectBase, IDLE_RECLAIM_MS, WORKSPACE_DIR, workspaceName } from "./object.js";
48
- // The dependency install, exported because a host that wants to report on one —
49
- // or a spec that drives it — needs the type, not because anything but
50
- // `./object.ts` constructs it.
51
- export { InstallJob } from "./install-job.js";
52
- // The pull the library owns no alarm for. Its constants are exported because a
53
- // host deferring to a drain has to back off at the same rate this does.
54
- export { WorkspaceSync, SYNC_DRAIN_BUDGET_MS, SYNC_DRAIN_RESUME_MS, SYNC_DRAIN_MAX_BACKOFF_MS, syncRetryDelayMs } from "./sync.js";
55
- // `TRUST_CA_COMMAND` is exported so a host can assert what its image will be
56
- // asked to run — see the file for why this cannot live in an entrypoint.
57
- export { ContainerTrust, TRUST_CA_COMMAND } from "./ca-trust.js";
58
- export { WorkspaceGitHost } from "./git-host.js";
@@ -1,121 +0,0 @@
1
- import { type Workspace } from "@cloudflare/computer";
2
- import type { Scheduler } from "@dynamicagents/core/alarm";
3
- import { type InstallPlan, type InstallState } from "./install.js";
4
- import type { WorkspaceWakeHandlers } from "./wake.js";
5
- export interface InstallJobDeps {
6
- storage: DurableObjectStorage;
7
- scheduler: Scheduler<WorkspaceWakeHandlers>;
8
- workspace: () => Workspace;
9
- /** How this deployment installs dependencies for this agent's checkouts. */
10
- plan: () => InstallPlan;
11
- /** How long an install may run before it is killed. */
12
- timeoutMs: () => number;
13
- /** Set only when the workspace is over its ceiling. */
14
- headroom: () => {
15
- bytes: number;
16
- capBytes: number;
17
- } | undefined;
18
- /** The object's own entry-point bookkeeping, which an install still owes. */
19
- touch: () => Promise<void>;
20
- ready: () => Promise<void>;
21
- /** Hand a drain to the invocation, for the caller that can hold one. */
22
- waitUntil: (promise: Promise<unknown>) => void;
23
- /** A container was replaced, so nothing believed about it still holds. */
24
- containerGone: () => Promise<void>;
25
- tag: () => string;
26
- id: () => string;
27
- }
28
- export declare class InstallJob {
29
- #private;
30
- private readonly deps;
31
- constructor(deps: InstallJobDeps);
32
- /**
33
- * Start a dependency install the moment we can see one will be needed.
34
- *
35
- * The signal is {@link CONTAINER_TREE_KEY}: a local read, true only while the
36
- * container that ran the install is the one running.
37
- *
38
- * Armed as soon as a container is up or a command is about to start one,
39
- * because the model's first minute is README-reading and `git status` — an
40
- * install armed there runs *through* that minute, where one armed on the first
41
- * `npm` command charges its full time to that command.
42
- *
43
- * It writes `running` before anything is running: the alarm has not fired yet,
44
- * and a `done` record would let an `npm` command through against a tree that
45
- * is not there. That also makes this self-limiting — the next call sees
46
- * `running` and stops.
47
- */
48
- armIfTreeMissing(): Promise<void>;
49
- /** Where the last install ran, for the container setup's marker read. */
50
- dir(): Promise<string | undefined>;
51
- /** The container went away, and its tree with it. */
52
- containerGone(): Promise<void>;
53
- /**
54
- * Check the record against the marker a new isolate's setup read.
55
- *
56
- * The record can outlive its container in an isolate that did not watch it
57
- * exit; the marker cannot.
58
- */
59
- reconcile(marker: string | null): Promise<void>;
60
- /**
61
- * The record exactly as the job wrote it, with no staleness bound applied.
62
- *
63
- * {@link state} is what almost everything wants. This is for the one caller
64
- * that must not repair anything on the way past: the container-idle handler,
65
- * which only needs to know whether something is running before it destroys the
66
- * container underneath it.
67
- */
68
- read(): Promise<InstallState>;
69
- /**
70
- * Start installing this checkout's dependencies, and return without waiting.
71
- *
72
- * Called from `repo_clone` through the repo plugin's `afterCheckout` hook, so
73
- * it runs inside a model turn and must not block on the install — 225 seconds
74
- * for slack-gatekeeper, against a turn that is cut at fifteen minutes.
75
- *
76
- * That caller is a model turn, which lives long enough to hold the drain handed
77
- * to `ctx.waitUntil` below. **A short-lived caller cannot**, which is why an
78
- * install the alarm drives is awaited inside that alarm rather than calling
79
- * this.
80
- */
81
- start(req: {
82
- dir: string;
83
- repo?: string;
84
- }): Promise<InstallState>;
85
- /**
86
- * Whether this container holds a finished tree, asked only when it qualifies a
87
- * `deps-broken` advisory (see `deriveAdvisories`).
88
- */
89
- treePresentIfItMatters(install: InstallState): Promise<boolean>;
90
- /**
91
- * The install record itself, with its staleness bound and re-attach applied.
92
- *
93
- * Split from {@link advisories} so `startInstall` can consult the record
94
- * without going through the `node_modules` probe, which needs a container and
95
- * has nothing to say about whether an install may start.
96
- *
97
- * Re-attaches on the way past. An isolate reset leaves the record saying
98
- * `running` with nothing draining it, and without this the state would say
99
- * `running` forever while the command had long since finished.
100
- */
101
- state(): Promise<InstallState>;
102
- /**
103
- * When a reinstall was queued, if one is waiting to run.
104
- *
105
- * Read by {@link file://./advisory.ts deriveAdvisories}, which is the only
106
- * caller that needs it: a `failed` record with a repair already queued is a
107
- * transient condition wearing a permanent record's clothes.
108
- */
109
- reinstallArmedAt(): Promise<number | undefined>;
110
- /**
111
- * The armed reinstall came due.
112
- *
113
- * `clearArmed` first and unconditionally: this handler runs for minutes, and
114
- * the stamp left in place is what a second arming would recognise as its own.
115
- * The reservation in `#beginInstall` would catch a double, but the cheaper
116
- * answer is not to schedule one.
117
- */
118
- onRun(): Promise<void>;
119
- /** The watchdog: an install still running that nobody is draining. */
120
- onWatch(): Promise<void>;
121
- }