@dynamicagents/plugins 0.12.0 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (132) hide show
  1. package/README.md +58 -77
  2. package/dist/browser/index.d.ts +0 -2
  3. package/dist/browser/index.js +21 -27
  4. package/dist/claude-code/cards.d.ts +55 -0
  5. package/dist/claude-code/cards.js +283 -0
  6. package/dist/claude-code/config.d.ts +28 -63
  7. package/dist/claude-code/config.js +0 -11
  8. package/dist/claude-code/egress.d.ts +8 -1
  9. package/dist/claude-code/egress.js +42 -4
  10. package/dist/claude-code/events.d.ts +106 -9
  11. package/dist/claude-code/events.js +201 -56
  12. package/dist/claude-code/github.d.ts +39 -0
  13. package/dist/claude-code/github.js +82 -0
  14. package/dist/claude-code/index.d.ts +16 -90
  15. package/dist/claude-code/index.js +14 -276
  16. package/dist/claude-code/model.d.ts +152 -0
  17. package/dist/claude-code/model.js +366 -0
  18. package/dist/claude-code/run.d.ts +230 -116
  19. package/dist/claude-code/run.js +380 -167
  20. package/dist/claude-code/session.d.ts +131 -0
  21. package/dist/claude-code/session.js +288 -0
  22. package/dist/claude-code/spec.d.ts +46 -0
  23. package/dist/claude-code/spec.js +83 -0
  24. package/dist/claude-code/verified.d.ts +15 -0
  25. package/dist/claude-code/verified.js +15 -0
  26. package/dist/computer/context.d.ts +1 -5
  27. package/dist/computer/context.js +7 -10
  28. package/dist/computer/file-lock.js +5 -4
  29. package/dist/computer/gate.d.ts +4 -4
  30. package/dist/computer/gate.js +5 -5
  31. package/dist/computer/index.d.ts +40 -258
  32. package/dist/computer/index.js +71 -324
  33. package/dist/computer/paths.d.ts +36 -16
  34. package/dist/computer/paths.js +42 -29
  35. package/dist/computer/proxy.d.ts +45 -0
  36. package/dist/computer/proxy.js +234 -0
  37. package/dist/computer/render.d.ts +1 -40
  38. package/dist/computer/render.js +2 -68
  39. package/dist/computer/tools-exec.js +12 -13
  40. package/dist/computer/tools-file.d.ts +9 -1
  41. package/dist/computer/tools-file.js +22 -82
  42. package/dist/computer/{tools-find.d.ts → tools-grep.d.ts} +1 -1
  43. package/dist/computer/tools-grep.js +129 -0
  44. package/dist/repo/checkout.d.ts +4 -5
  45. package/dist/repo/checkout.js +31 -8
  46. package/dist/repo/context.d.ts +35 -9
  47. package/dist/repo/context.js +101 -49
  48. package/dist/repo/index.d.ts +73 -28
  49. package/dist/repo/index.js +112 -96
  50. package/dist/repo/tools-checks.d.ts +3 -0
  51. package/dist/repo/tools-checks.js +112 -0
  52. package/dist/repo/tools-clone.js +1 -1
  53. package/dist/repo/tools-pr.d.ts +14 -0
  54. package/dist/repo/{tools-forge.js → tools-pr.js} +53 -36
  55. package/dist/repo/tools-review.d.ts +9 -0
  56. package/dist/repo/tools-review.js +67 -47
  57. package/dist/repo/tools-worktree.js +144 -60
  58. package/dist/repo/tools-worktrees.d.ts +12 -0
  59. package/dist/repo/tools-worktrees.js +48 -0
  60. package/dist/repo/url.d.ts +2 -2
  61. package/dist/repo/url.js +7 -7
  62. package/dist/scratch/index.d.ts +4 -4
  63. package/dist/scratch/index.js +12 -11
  64. package/dist/{computer → workspace}/advisory.d.ts +4 -4
  65. package/dist/{computer → workspace}/advisory.js +2 -2
  66. package/dist/{computer/host → workspace}/ca-trust.d.ts +8 -1
  67. package/dist/{computer/host → workspace}/ca-trust.js +12 -3
  68. package/dist/{computer/host → workspace}/container-deps.d.ts +4 -0
  69. package/dist/{computer/host → workspace}/container-deps.js +26 -1
  70. package/dist/{computer/host → workspace}/container-fault.d.ts +3 -3
  71. package/dist/{computer/host → workspace}/container-fault.js +23 -8
  72. package/dist/workspace/deps-snapshot.d.ts +110 -0
  73. package/dist/workspace/deps-snapshot.js +424 -0
  74. package/dist/workspace/exec.d.ts +94 -0
  75. package/dist/workspace/exec.js +153 -0
  76. package/dist/workspace/format.d.ts +36 -0
  77. package/dist/workspace/format.js +57 -0
  78. package/dist/{computer/host → workspace}/git-host.d.ts +21 -4
  79. package/dist/{computer/host → workspace}/git-host.js +72 -2
  80. package/dist/{computer/host → workspace}/git-identity.d.ts +1 -1
  81. package/dist/{computer/host → workspace}/git-identity.js +1 -1
  82. package/dist/workspace/index.d.ts +44 -47
  83. package/dist/workspace/index.js +52 -112
  84. package/dist/{computer/host → workspace}/install-job.d.ts +53 -4
  85. package/dist/{computer/host → workspace}/install-job.js +346 -178
  86. package/dist/{computer → workspace}/install.d.ts +17 -8
  87. package/dist/{computer → workspace}/install.js +24 -6
  88. package/dist/{computer/host/workspace.d.ts → workspace/object.d.ts} +125 -27
  89. package/dist/{computer/host/workspace.js → workspace/object.js} +341 -58
  90. package/dist/workspace/open.d.ts +95 -0
  91. package/dist/workspace/open.js +63 -0
  92. package/dist/workspace/read.d.ts +16 -0
  93. package/dist/workspace/read.js +22 -0
  94. package/dist/{computer → workspace}/shell.d.ts +5 -5
  95. package/dist/{computer → workspace}/shell.js +6 -6
  96. package/dist/{computer/host → workspace}/wake.d.ts +3 -1
  97. package/package.json +17 -37
  98. package/dist/arc-agi/analysis.d.ts +0 -322
  99. package/dist/arc-agi/analysis.js +0 -802
  100. package/dist/arc-agi/client.d.ts +0 -82
  101. package/dist/arc-agi/client.js +0 -113
  102. package/dist/arc-agi/game-tools.d.ts +0 -24
  103. package/dist/arc-agi/game-tools.js +0 -26
  104. package/dist/arc-agi/index.d.ts +0 -40
  105. package/dist/arc-agi/index.js +0 -175
  106. package/dist/arc-agi/main-agent.d.ts +0 -24
  107. package/dist/arc-agi/main-agent.js +0 -62
  108. package/dist/arc-agi/recipe.d.ts +0 -48
  109. package/dist/arc-agi/recipe.js +0 -97
  110. package/dist/arc-agi/scorecard.d.ts +0 -118
  111. package/dist/arc-agi/scorecard.js +0 -163
  112. package/dist/arc-agi/soul.d.ts +0 -29
  113. package/dist/arc-agi/soul.js +0 -79
  114. package/dist/arc-agi/store.d.ts +0 -153
  115. package/dist/arc-agi/store.js +0 -215
  116. package/dist/arc-agi/tools.d.ts +0 -36
  117. package/dist/arc-agi/tools.js +0 -574
  118. package/dist/arc-agi/types.d.ts +0 -211
  119. package/dist/arc-agi/types.js +0 -19
  120. package/dist/claude-code/recipe.d.ts +0 -53
  121. package/dist/claude-code/recipe.js +0 -100
  122. package/dist/computer/read.d.ts +0 -133
  123. package/dist/computer/read.js +0 -200
  124. package/dist/computer/tools-find.js +0 -216
  125. package/dist/recall/index.d.ts +0 -105
  126. package/dist/recall/index.js +0 -181
  127. package/dist/repo/tools-forge.d.ts +0 -4
  128. package/dist/triage/index.d.ts +0 -360
  129. package/dist/triage/index.js +0 -311
  130. /package/dist/{computer/host → workspace}/sync.d.ts +0 -0
  131. /package/dist/{computer/host → workspace}/sync.js +0 -0
  132. /package/dist/{computer/host → workspace}/wake.js +0 -0
@@ -0,0 +1,366 @@
1
+ var __addDisposableResource = (this && this.__addDisposableResource) || function (env, value, async) {
2
+ if (value !== null && value !== void 0) {
3
+ if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
4
+ var dispose, inner;
5
+ if (async) {
6
+ if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
7
+ dispose = value[Symbol.asyncDispose];
8
+ }
9
+ if (dispose === void 0) {
10
+ if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
11
+ dispose = value[Symbol.dispose];
12
+ if (async) inner = dispose;
13
+ }
14
+ if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
15
+ if (inner) dispose = function() { try { inner.call(this); } catch (e) { return Promise.reject(e); } };
16
+ env.stack.push({ value: value, dispose: dispose, async: async });
17
+ }
18
+ else if (async) {
19
+ env.stack.push({ async: true });
20
+ }
21
+ return value;
22
+ };
23
+ var __disposeResources = (this && this.__disposeResources) || (function (SuppressedError) {
24
+ return function (env) {
25
+ function fail(e) {
26
+ env.error = env.hasError ? new SuppressedError(e, env.error, "An error was suppressed during disposal.") : e;
27
+ env.hasError = true;
28
+ }
29
+ var r, s = 0;
30
+ function next() {
31
+ while (r = env.stack.pop()) {
32
+ try {
33
+ if (!r.async && s === 1) return s = 0, env.stack.push(r), Promise.resolve().then(next);
34
+ if (r.dispose) {
35
+ var result = r.dispose.call(r.value);
36
+ if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) { fail(e); return next(); });
37
+ }
38
+ else s |= 1;
39
+ }
40
+ catch (e) {
41
+ fail(e);
42
+ }
43
+ }
44
+ if (s === 1) return env.hasError ? Promise.reject(env.error) : Promise.resolve();
45
+ if (env.hasError) throw env.error;
46
+ }
47
+ return next();
48
+ };
49
+ })(typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
50
+ var e = new Error(message);
51
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
52
+ });
53
+ import { isPlatformTransientError } from "agents";
54
+ import { lostCard } from "./cards.js";
55
+ import { claudeCodeSession, requireCredentials } from "./session.js";
56
+ import { AttachGivenUpError, execIdFor, followUpExecIdFor } from "./run.js";
57
+ /** Zeroed: the session's tokens are the CLI's context, not this conversation's. */
58
+ const USAGE = {
59
+ inputTokens: {
60
+ total: 0,
61
+ noCache: 0,
62
+ cacheRead: 0,
63
+ cacheWrite: 0
64
+ },
65
+ outputTokens: { total: 0, text: 0, reasoning: 0 }
66
+ };
67
+ export function claudeCodeModel(options) {
68
+ requireCredentials(options.config);
69
+ const { storage, runId } = options;
70
+ const session = claudeCodeSession(options.config);
71
+ const key = (name) => `claude-code:${runId}:${name}`;
72
+ const KEYS = {
73
+ brief: key("brief"),
74
+ cursor: key("cursor"),
75
+ session: key("session"),
76
+ followUp: key("follow-up"),
77
+ followUpEnd: key("follow-up-end"),
78
+ report: key("report")
79
+ };
80
+ const run = async (call) => {
81
+ const env_1 = { stack: [], error: void 0, hasError: false };
82
+ try {
83
+ // The once-guarantee: a run that already reported says so again.
84
+ const reported = await storage.get(KEYS.report);
85
+ if (reported !== undefined)
86
+ return reported;
87
+ const signal = call.abortSignal;
88
+ // Opened again after a cut stream — see `drain`. Whichever is current is
89
+ // released when the run ends.
90
+ let workspace = await options.workspace();
91
+ const _release = __addDisposableResource(env_1, { [Symbol.dispose]: () => workspace[Symbol.dispose]() }, false);
92
+ /** The exec being drained, which leads each note's key. */
93
+ let current = "";
94
+ /**
95
+ * The handle already recorded, so one id is not announced twice over — and
96
+ * set only once the host has taken it, so a record that failed is tried
97
+ * again at the next checkpoint rather than given up on.
98
+ */
99
+ let announced = "";
100
+ /**
101
+ * Tell the host the session's handle, and never fail the run over it.
102
+ *
103
+ * Not on the note chain: a note is one line of a transcript, and this is the
104
+ * only way back to the conversation. It is awaited where it is called so a
105
+ * handle is recorded before whatever comes next can lose it.
106
+ */
107
+ const announce = async (record) => {
108
+ const sink = options.onSession;
109
+ if (!sink)
110
+ return;
111
+ try {
112
+ await sink(record);
113
+ announced = record.sessionId;
114
+ }
115
+ catch (err) {
116
+ console.warn("[claude-code] the session's handle was not recorded", {
117
+ runId,
118
+ sessionId: record.sessionId,
119
+ err: String(err)
120
+ });
121
+ }
122
+ };
123
+ /**
124
+ * Each note, filed as it is parsed, then the cursor behind it. Keyed on the
125
+ * exec as well as the position: the parent's transcript is one per task and
126
+ * dedupes on the key, so a run's notes must not collide with another run's
127
+ * — or with its own follow-up's, which counts from zero again.
128
+ */
129
+ const sinks = {
130
+ onProgress: (note) => options.note(`${current}:${note.key}`, note.text, note.detail),
131
+ // The drain offers a cursor the moment the session id appears, which is
132
+ // what makes this the earliest the handle can be recorded — seconds in,
133
+ // rather than at the end a killed session never reaches.
134
+ onCheckpoint: async (cursor) => {
135
+ await storage.put(KEYS.cursor, cursor);
136
+ if (cursor.sessionId && cursor.sessionId !== announced) {
137
+ await announce({ sessionId: cursor.sessionId });
138
+ }
139
+ },
140
+ ...(signal ? { signal } : {})
141
+ };
142
+ /**
143
+ * The session's end card, filed where the run gives up on a session it will
144
+ * never read to its end: a re-attach given up on, or a cancel that stops it.
145
+ * Without it the transcript shows a session that never ended, and a retry's
146
+ * start reads as more of it.
147
+ *
148
+ * Not on any other throw: a transient one is retried by re-entering this
149
+ * turn, which reads on from the stored cursor. Keyed on the exec, so a card
150
+ * filed twice is filed once.
151
+ */
152
+ const fileLost = async (execId, reason) => {
153
+ const card = lostCard(reason instanceof Error ? reason.message : String(reason));
154
+ await options
155
+ .note(`${execId}:lost`, card.text, card.detail)
156
+ .catch((err) => console.warn("[claude-code] a lost session's end was not filed", {
157
+ execId,
158
+ err: String(err)
159
+ }));
160
+ };
161
+ /**
162
+ * Drain one exec to its end, starting it or re-attaching from the cursor.
163
+ *
164
+ * **A cut stream is re-attached here, not failed.** The session is still
165
+ * running, and a failed run is stopped — the one outcome that loses it. The
166
+ * retry opens the workspace afresh, since the stub the stream came over may
167
+ * not survive the cut. Two attempts in a row that end in a cut with no
168
+ * checkpoint stored fail the run as before: a stream that breaks every time
169
+ * it opens is not a blip.
170
+ */
171
+ const drain = async (execId, begin) => {
172
+ current = execId;
173
+ let outcome;
174
+ let stalled = false;
175
+ while (!outcome) {
176
+ const cursor = await storage.get(KEYS.cursor);
177
+ try {
178
+ outcome =
179
+ cursor?.execId === execId
180
+ ? await session.resume(workspace.runtime, cursor, sinks)
181
+ : await begin(workspace.runtime);
182
+ }
183
+ catch (err) {
184
+ const after = await storage.get(KEYS.cursor);
185
+ const moved = after?.execId === execId &&
186
+ (cursor?.execId !== execId || after.seq > cursor.seq);
187
+ if (err instanceof AttachGivenUpError)
188
+ await fileLost(execId, err);
189
+ if (!isStreamCut(err) || signal?.aborted || (stalled && !moved))
190
+ throw err;
191
+ stalled = !moved;
192
+ console.warn("[claude-code] the session's stream was cut — re-attaching", {
193
+ execId,
194
+ err: String(err)
195
+ });
196
+ const fresh = await options.workspace();
197
+ workspace[Symbol.dispose]();
198
+ workspace = fresh;
199
+ }
200
+ }
201
+ await storage.put(KEYS.cursor, outcome.cursor);
202
+ if (!outcome.done) {
203
+ // Only the signal stops a drain short of the end: the turn was
204
+ // cancelled, so the session goes with it.
205
+ await session.stop(workspace.runtime, runId).catch((err) => console.warn("[claude-code] could not stop a cancelled session", {
206
+ runId,
207
+ err: String(err)
208
+ }));
209
+ const reason = signal?.reason ?? new Error("the session was stopped");
210
+ await fileLost(execId, reason);
211
+ throw reason;
212
+ }
213
+ return {
214
+ exitCode: outcome.exitCode,
215
+ ...(outcome.result ? { result: outcome.result } : {}),
216
+ ...(outcome.stderr ? { stderr: outcome.stderr } : {}),
217
+ ...(outcome.rateLimit ? { rateLimit: outcome.rateLimit } : {}),
218
+ ...(outcome.cursor.sessionId
219
+ ? { sessionId: outcome.cursor.sessionId }
220
+ : {})
221
+ };
222
+ };
223
+ let ended = await storage.get(KEYS.session);
224
+ if (!ended) {
225
+ let prompt = await storage.get(KEYS.brief);
226
+ if (prompt === undefined) {
227
+ const task = lastUserText(call.prompt);
228
+ prompt = options.brief ? await options.brief(task) : task;
229
+ await storage.put(KEYS.brief, prompt);
230
+ }
231
+ const brief = prompt;
232
+ ended = await drain(execIdFor(runId), (runtime) => session.start(runtime, runId, {
233
+ prompt: brief,
234
+ dir: options.dir,
235
+ ...(options.jsonSchema ? { jsonSchema: options.jsonSchema } : {}),
236
+ ...(options.permissionMode
237
+ ? { permissionMode: options.permissionMode }
238
+ : {}),
239
+ ...(options.resume ? { resume: options.resume } : {})
240
+ }, sinks));
241
+ await storage.put(KEYS.session, ended);
242
+ }
243
+ // After the end is stored, so a turn that dies here does not report an end
244
+ // the run has not kept — and outside the guard above, so a turn cut between
245
+ // storing the end and telling the host tells it on the next attempt. Telling
246
+ // it twice is harmless: its record is keyed on the id, see `SessionRecord`.
247
+ if (ended.sessionId)
248
+ await announce({ sessionId: ended.sessionId, end: ended });
249
+ let followUpEnd = await storage.get(KEYS.followUpEnd);
250
+ if (!followUpEnd && options.followUp) {
251
+ let asked = await storage.get(KEYS.followUp);
252
+ if (!asked) {
253
+ const prompt = await options.followUp(ended);
254
+ asked = prompt ? { prompt } : {};
255
+ await storage.put(KEYS.followUp, asked);
256
+ }
257
+ // The cursor's id as well as the result's: a session that was stopped
258
+ // before it reported still has a conversation worth one more turn.
259
+ const sessionId = ended.result?.sessionId ?? ended.sessionId;
260
+ if (asked.prompt && sessionId) {
261
+ const prompt = asked.prompt;
262
+ followUpEnd = await drain(followUpExecIdFor(runId), (runtime) => session.followUp(runtime, runId, {
263
+ sessionId,
264
+ prompt,
265
+ dir: options.dir,
266
+ ...(options.permissionMode
267
+ ? { permissionMode: options.permissionMode }
268
+ : {})
269
+ }, sinks));
270
+ await storage.put(KEYS.followUpEnd, followUpEnd);
271
+ }
272
+ }
273
+ const text = await options.report({
274
+ session: ended,
275
+ ...(followUpEnd ? { followUp: followUpEnd } : {})
276
+ });
277
+ await storage.put(KEYS.report, text);
278
+ return text;
279
+ }
280
+ catch (e_1) {
281
+ env_1.error = e_1;
282
+ env_1.hasError = true;
283
+ }
284
+ finally {
285
+ __disposeResources(env_1);
286
+ }
287
+ };
288
+ return {
289
+ specificationVersion: "v3",
290
+ provider: "claude-code",
291
+ modelId: options.config.model ?? "claude-code",
292
+ supportedUrls: {},
293
+ async doStream(call) {
294
+ // The stream is returned at once and the session runs inside it, so
295
+ // nothing waits on a promise for the length of a session.
296
+ const stream = new ReadableStream({
297
+ async start(controller) {
298
+ controller.enqueue({ type: "stream-start", warnings: [] });
299
+ try {
300
+ const text = await run(call);
301
+ controller.enqueue({ type: "text-start", id: "report" });
302
+ controller.enqueue({
303
+ type: "text-delta",
304
+ id: "report",
305
+ delta: text
306
+ });
307
+ controller.enqueue({ type: "text-end", id: "report" });
308
+ controller.enqueue({
309
+ type: "finish",
310
+ usage: USAGE,
311
+ finishReason: { unified: "stop", raw: undefined }
312
+ });
313
+ controller.close();
314
+ }
315
+ catch (err) {
316
+ controller.error(err);
317
+ }
318
+ }
319
+ });
320
+ return { stream };
321
+ },
322
+ async doGenerate(call) {
323
+ const text = await run(call);
324
+ return {
325
+ content: [{ type: "text", text }],
326
+ finishReason: { unified: "stop", raw: undefined },
327
+ usage: USAGE,
328
+ warnings: []
329
+ };
330
+ }
331
+ };
332
+ }
333
+ /**
334
+ * Whether a drain failed because the transport under a live session gave way.
335
+ *
336
+ * An exec's events reach the sub-agent as a stream over RPC, relayed by the
337
+ * workspace object from the container's own RPC session — so a drop anywhere on
338
+ * that path cuts the stream while the session runs on. Measured: a container's
339
+ * session dropped after 21 minutes and was attached again within a second, the
340
+ * process untouched. The message is workerd's for a stream whose far side went
341
+ * away, and it carries no code.
342
+ */
343
+ function isStreamCut(err) {
344
+ if (isPlatformTransientError(err))
345
+ return true;
346
+ for (let e = err; e instanceof Error; e = e.cause) {
347
+ if (e.message.includes("ReadableStream received over RPC disconnected"))
348
+ return true;
349
+ }
350
+ return false;
351
+ }
352
+ /**
353
+ * The task: the last user message's text. On a continued turn the prompt ends
354
+ * with the interrupted assistant message, so the last message is not it.
355
+ */
356
+ function lastUserText(prompt) {
357
+ for (let i = prompt.length - 1; i >= 0; i--) {
358
+ const message = prompt[i];
359
+ if (message.role !== "user")
360
+ continue;
361
+ return message.content
362
+ .map((part) => (part.type === "text" ? part.text : ""))
363
+ .join("");
364
+ }
365
+ throw new Error("claude-code: the run has no task — no user message");
366
+ }