@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
@@ -1,211 +0,0 @@
1
- /**
2
- * ARC-AGI-3 REST API + session types. The API plays a visual-reasoning game on a
3
- * 64×64 grid of color values 0–15; see https://docs.arcprize.org.
4
- *
5
- * Two lifecycles meet here, and neither belongs to a model:
6
- *
7
- * - The **scorecard** is a container that aggregates many plays. The API opens
8
- * one on request and auto-closes it after ~15 minutes idle, so nothing here
9
- * ever closes one: the parent leases the most recently used card and records it
10
- * in its DO SQLite (`db.scorecards`) purely to know how fresh it is.
11
- * - A **play** is one RESET→ACTION* run inside a scorecard, driven by a subagent.
12
- * All state that must survive across durable chunks (cookies, guid, frames,
13
- * metrics) lives in the workspace as {@link ArcSession}, written by the tool
14
- * family. A subagent is handed a resolved card; it never opens or chooses one.
15
- */
16
- /** Game lifecycle state as the API reports it. */
17
- export type GameState = "NOT_STARTED" | "NOT_FINISHED" | "WIN" | "GAME_OVER";
18
- /** Base URL of the ARC-AGI-3 API. */
19
- export declare const ARC_BASE_URL = "https://three.arcprize.org";
20
- /**
21
- * One game as `GET /api/games` lists it. Ids look like `ls20-016295f7601e`.
22
- * `tags` describes how it is played (`click`, `keyboard`, `keyboard_click`) and
23
- * `baseline_actions` is the per-level human baseline — both are shown to the
24
- * main agent so it can brief a play sensibly.
25
- */
26
- export interface GameInfo {
27
- game_id: string;
28
- title?: string;
29
- tags?: string[];
30
- baseline_actions?: number[];
31
- }
32
- /** A frame response from RESET / ACTION*. `frame` is one or more 64×64 grids. */
33
- export interface FrameResponse {
34
- game_id: string;
35
- guid: string;
36
- frame: number[][][];
37
- state: GameState;
38
- levels_completed: number;
39
- win_levels?: number;
40
- available_actions: number[];
41
- score?: number;
42
- }
43
- /** One RESET→terminal run of a game, as the scorecard reports it. */
44
- export interface ScorecardRun {
45
- guid: string;
46
- actions: number;
47
- completed: boolean;
48
- levels_completed: number;
49
- resets: number;
50
- score: number;
51
- state: GameState;
52
- /** Actions spent on each level of this run. */
53
- level_actions?: number[];
54
- /** The human baseline each level is scored against. */
55
- level_baseline_actions?: number[];
56
- level_scores?: number[];
57
- }
58
- /**
59
- * One game's aggregate within a scorecard — every run played against it.
60
- *
61
- * This is the **only** game-scoped part of the response: every top-level field of
62
- * {@link ScorecardSummary} covers the whole card. Since several games share one
63
- * card by design, reporting a card-level total as a game's own is a real
64
- * mislabeling — so the renderer reads nothing but this entry.
65
- */
66
- export interface ScorecardEnvironment {
67
- id: string;
68
- actions: number;
69
- completed: boolean;
70
- level_count: number;
71
- levels_completed: number;
72
- resets: number;
73
- score: number;
74
- runs: ScorecardRun[];
75
- }
76
- /** Per-tag rollup (`click`, `keyboard`, …) across the scorecard's games. */
77
- export interface ScorecardTagScore {
78
- id: string;
79
- actions: number;
80
- levels_completed: number;
81
- number_of_environments: number;
82
- number_of_levels: number;
83
- score: number;
84
- }
85
- /**
86
- * A whole scorecard as `GET /api/scorecard/{card_id}` reports it: one
87
- * `environments` entry per game played, one `runs` entry per RESET within it.
88
- *
89
- * This is a **read**, not a terminal event — it works while the card is still
90
- * open, which is what lets a result be reported without anything ever closing a
91
- * card. (It is the same shape the retired close call returned, which is why it
92
- * carries a real per-game `score`.)
93
- *
94
- * The narrower `GET /api/scorecard/{card_id}/{game_id}` is deliberately *not*
95
- * used: it reports no score at all, and its top-level totals are card-wide
96
- * despite the game filter — verified against the live API.
97
- */
98
- export interface ScorecardSummary {
99
- card_id: string;
100
- score: number;
101
- total_actions: number;
102
- total_environments: number;
103
- total_environments_completed: number;
104
- total_levels: number;
105
- total_levels_completed: number;
106
- environments: ScorecardEnvironment[];
107
- tags?: string[];
108
- tags_scores?: ScorecardTagScore[];
109
- }
110
- /**
111
- * One scorecard as the agent's DO SQLite records it (see `db/schema.ts`).
112
- *
113
- * There is no status: the API auto-closes an idle card, so liveness is inferred
114
- * from {@link lastUsedAt} rather than tracked. A card is a lease, not an object
115
- * with a lifecycle.
116
- */
117
- export interface Scorecard {
118
- cardId: string;
119
- /**
120
- * The jar `POST /api/scorecard/open` returned. The API pins the card to that
121
- * session — every later RESET, ACTION, and scorecard read must echo these
122
- * cookies, from whichever agent makes the call — so it is stored with the card,
123
- * not held by whoever happened to open it.
124
- */
125
- cookies: CookieJar;
126
- /**
127
- * `{ [gameId]: guid }` — the play this card has already opened per game, so a
128
- * game resolving onto it a second time rejoins that play instead of RESETting
129
- * a new one. See `resolvePlay` in `recipes/arc-game/scorecard.ts`.
130
- */
131
- guids: Record<string, string>;
132
- openedAt: number;
133
- /** Last time a play resolved onto this card; the reuse clock. */
134
- lastUsedAt: number;
135
- }
136
- /** Session-affinity cookie jar (AWSALB*), echoed on every request of a session. */
137
- export type CookieJar = Record<string, string>;
138
- /**
139
- * Durable play session, persisted to the workspace at {@link ARC_SESSION_PATH}.
140
- * The single grid we render/diff is the LAST grid of the frame array (the current
141
- * board).
142
- *
143
- * One session file is one play, and one execution gets exactly one: the RESET
144
- * that creates this file is implicit and fires once, so reaching WIN or GAME_OVER
145
- * is a terminal result to report on this card, not a state the model can reset
146
- * out of. Its presence on disk is what makes that guarantee — every later tool
147
- * call loads it instead of starting.
148
- */
149
- export interface ArcSession {
150
- /**
151
- * The scorecard this play belongs to, recorded from the lease the parent
152
- * resolved at the opening RESET. Kept rather than re-read each chunk: if the
153
- * lease rolls over onto a new card mid-execution, this play's runs still belong
154
- * to the card that recorded them.
155
- */
156
- cardId: string;
157
- gameId: string;
158
- guid: string;
159
- cookies: CookieJar;
160
- winLevels: number;
161
- levelsCompleted: number;
162
- state: GameState;
163
- availableActions: number[];
164
- /** Count of actions actually sent to the API (game moves) in this play. */
165
- actionsSent: number;
166
- /** Levels at which we have emitted a level-up progress note. */
167
- levelsReported: number[];
168
- /**
169
- * The current board as bare hex rows (`serializeGrid`), not `number[][]`.
170
- *
171
- * The workspace pretty-prints its JSON, so a nested numeric array serializes to
172
- * one integer per line — ~38 KB for a 64×64 board. Since the session is written
173
- * twice per action (write-ahead intent, then the recorded result) and one
174
- * `arc_act` call may carry several actions, that adds up to hundreds of KB of
175
- * SQLite per tool call. Hex rows are ~4 KB.
176
- */
177
- lastGridHex: string | null;
178
- /** Write-ahead intent: set before an action is sent, cleared after it returns. */
179
- pendingAction: {
180
- action: number;
181
- x?: number;
182
- y?: number;
183
- } | null;
184
- }
185
- /** Workspace path for the durable ARC session. */
186
- export declare const ARC_SESSION_PATH = "arc/session.json";
187
- /**
188
- * This plugin's slice of a Subtask's runtime bag — what the parent resolves for
189
- * an execution and no model could supply.
190
- *
191
- * Core's `SubtaskRuntime` is an open `Record<string, unknown>`, and this slice is
192
- * why: declared in core's own delegation types instead, core would import a
193
- * domain's vocabulary and every unrelated agent would carry it in its bundle.
194
- * The plugin that writes this slice is the plugin that reads it, so narrow it
195
- * with `runtimeAs<ArcRuntime>` at the boundary and keep the cast's blast radius
196
- * to this one module.
197
- */
198
- export type ArcRuntime = {
199
- /** The scorecard leased for this chunk. */
200
- cardId?: string;
201
- /** The session jar the ARC API pinned that card to. */
202
- cookies?: CookieJar;
203
- /** The play to join. Mintable only by RESET, which only the parent performs. */
204
- guid?: string;
205
- /**
206
- * The opening frame — present **only** on the chunk that minted the guid.
207
- * There is no ARC endpoint that reads a board back, so this is the one chance
208
- * to hand one over; a later chunk learns the board from its first ACTION.
209
- */
210
- frame?: FrameResponse;
211
- };
@@ -1,19 +0,0 @@
1
- /**
2
- * ARC-AGI-3 REST API + session types. The API plays a visual-reasoning game on a
3
- * 64×64 grid of color values 0–15; see https://docs.arcprize.org.
4
- *
5
- * Two lifecycles meet here, and neither belongs to a model:
6
- *
7
- * - The **scorecard** is a container that aggregates many plays. The API opens
8
- * one on request and auto-closes it after ~15 minutes idle, so nothing here
9
- * ever closes one: the parent leases the most recently used card and records it
10
- * in its DO SQLite (`db.scorecards`) purely to know how fresh it is.
11
- * - A **play** is one RESET→ACTION* run inside a scorecard, driven by a subagent.
12
- * All state that must survive across durable chunks (cookies, guid, frames,
13
- * metrics) lives in the workspace as {@link ArcSession}, written by the tool
14
- * family. A subagent is handed a resolved card; it never opens or chooses one.
15
- */
16
- /** Base URL of the ARC-AGI-3 API. */
17
- export const ARC_BASE_URL = "https://three.arcprize.org";
18
- /** Workspace path for the durable ARC session. */
19
- export const ARC_SESSION_PATH = "arc/session.json";
@@ -1,53 +0,0 @@
1
- import type { ResolvedRecipe, SubtaskTypeSpec } from "@dynamicagents/core";
2
- /** The Subtask type a "make this change" request decomposes into. */
3
- export declare const CLAUDE_CODE_TYPE = "claude-code";
4
- /**
5
- * The key this plugin writes the workspace name under, for the facet to read
6
- * back off `SubtaskRuntime`.
7
- *
8
- * **Deliberately a second declaration of `/computer`'s `WORKSPACE_RUNTIME_KEY`,
9
- * not an import of it.** Importing one string constant across the subpath
10
- * boundary would merge two realms `verify:exports` keeps apart, and pull the
11
- * whole computer plugin into the graph of every agent that installs this one.
12
- *
13
- * The two must stay equal, because a host that installs both on its subagent
14
- * gets them working off one runtime value — so `index.spec.ts` imports both and
15
- * asserts it, which is where a cross-realm import costs nothing.
16
- */
17
- export declare const WORKSPACE_RUNTIME_KEY = "workspaceName";
18
- /**
19
- * The recipe a Claude Code session runs under — and most of it is inert, which
20
- * is worth saying plainly rather than letting a reader assume otherwise.
21
- *
22
- * Every other recipe in this package configures core's resumable model/tool
23
- * loop: `soul` is the system prompt, `toolFamilies` names what the model may
24
- * call, `historyWindow` bounds its context. **None of that applies here.** The
25
- * host's subagent overrides `executeChunk` and never calls `runResumableChunk`
26
- * at all — the loop, the tools, the context management and the system prompt are
27
- * Claude Code's, inside the container.
28
- *
29
- * So the fields below exist because {@link ResolvedRecipe} requires them and
30
- * `validateRecipe` checks them on the parent, not because anything reads them at
31
- * runtime. They are set to the most honest values available:
32
- *
33
- * - `toolFamilies: []` — this plugin registers none. Claude Code brings its own
34
- * tools and they are not core's to name.
35
- * - `soul` — required and never defaulted, so it says what this recipe *is*.
36
- * Nothing sends it to a model.
37
- * - `limits.maxTurns` — the budget core would meter if it were driving. It is
38
- * not, so what actually bounds a session is `timeoutMs`, enforced by the
39
- * container runtime. Set to 1 to say so: one Dynamic Agents "turn" is one
40
- * whole Claude Code session.
41
- */
42
- export declare const CLAUDE_CODE_RECIPE: ResolvedRecipe;
43
- /**
44
- * What the main agent is told it can hand off.
45
- *
46
- * Sized deliberately. An invocation carries an 18.7-27k token cached prefix
47
- * before it does anything — a ten-call burst billed twenty raw input tokens
48
- * against 187,130 cache reads — so a session has to be worth starting. The
49
- * guidance says that in the terms the delegating model can act on: one coherent
50
- * change, not one file edit.
51
- */
52
- export declare const CLAUDE_CODE_CAPABILITY: string;
53
- export declare const CLAUDE_CODE_SPEC: SubtaskTypeSpec;
@@ -1,100 +0,0 @@
1
- /** The Subtask type a "make this change" request decomposes into. */
2
- export const CLAUDE_CODE_TYPE = "claude-code";
3
- /**
4
- * The key this plugin writes the workspace name under, for the facet to read
5
- * back off `SubtaskRuntime`.
6
- *
7
- * **Deliberately a second declaration of `/computer`'s `WORKSPACE_RUNTIME_KEY`,
8
- * not an import of it.** Importing one string constant across the subpath
9
- * boundary would merge two realms `verify:exports` keeps apart, and pull the
10
- * whole computer plugin into the graph of every agent that installs this one.
11
- *
12
- * The two must stay equal, because a host that installs both on its subagent
13
- * gets them working off one runtime value — so `index.spec.ts` imports both and
14
- * asserts it, which is where a cross-realm import costs nothing.
15
- */
16
- export const WORKSPACE_RUNTIME_KEY = "workspaceName";
17
- /**
18
- * The recipe a Claude Code session runs under — and most of it is inert, which
19
- * is worth saying plainly rather than letting a reader assume otherwise.
20
- *
21
- * Every other recipe in this package configures core's resumable model/tool
22
- * loop: `soul` is the system prompt, `toolFamilies` names what the model may
23
- * call, `historyWindow` bounds its context. **None of that applies here.** The
24
- * host's subagent overrides `executeChunk` and never calls `runResumableChunk`
25
- * at all — the loop, the tools, the context management and the system prompt are
26
- * Claude Code's, inside the container.
27
- *
28
- * So the fields below exist because {@link ResolvedRecipe} requires them and
29
- * `validateRecipe` checks them on the parent, not because anything reads them at
30
- * runtime. They are set to the most honest values available:
31
- *
32
- * - `toolFamilies: []` — this plugin registers none. Claude Code brings its own
33
- * tools and they are not core's to name.
34
- * - `soul` — required and never defaulted, so it says what this recipe *is*.
35
- * Nothing sends it to a model.
36
- * - `limits.maxTurns` — the budget core would meter if it were driving. It is
37
- * not, so what actually bounds a session is `timeoutMs`, enforced by the
38
- * container runtime. Set to 1 to say so: one Dynamic Agents "turn" is one
39
- * whole Claude Code session.
40
- */
41
- export const CLAUDE_CODE_RECIPE = {
42
- key: CLAUDE_CODE_TYPE,
43
- version: 1,
44
- soul: [
45
- "This recipe does not drive a model loop.",
46
- "",
47
- "A subtask of this type runs the Claude Code CLI inside the agent's",
48
- "workspace container, against the durable working tree. The system prompt, the",
49
- "tool loop and the context management all belong to that process. Nothing",
50
- "reads this text — it exists because a recipe must declare a soul, and a",
51
- "placeholder that looked like a prompt would invite someone to tune it."
52
- ].join("\n"),
53
- toolFamilies: [],
54
- enabled: true,
55
- limits: { maxTurns: 1 },
56
- historyWindow: 1,
57
- reportMetrics: false
58
- };
59
- /**
60
- * What the main agent is told it can hand off.
61
- *
62
- * Sized deliberately. An invocation carries an 18.7-27k token cached prefix
63
- * before it does anything — a ten-call burst billed twenty raw input tokens
64
- * against 187,130 cache reads — so a session has to be worth starting. The
65
- * guidance says that in the terms the delegating model can act on: one coherent
66
- * change, not one file edit.
67
- */
68
- export const CLAUDE_CODE_CAPABILITY = [
69
- "## Writing code",
70
- "",
71
- "You can hand a coding task to a Claude Code session running in your",
72
- "workspace container, in whatever you have open there — a repository you",
73
- "checked out, or a scratchpad. It has its own tools — it reads, edits, runs the",
74
- "test suite and iterates — and it reports back what it did.",
75
- "",
76
- "Give it **one coherent change**, described the way you would describe it to",
77
- "an engineer: what should be true when it is done, and how to tell. It is",
78
- "expensive to start and cheap to let run, so 'add the endpoint, its tests and",
79
- "wire it up' is one subtask, not three. A session that is only asked to edit",
80
- "a single line costs about what a substantial one costs.",
81
- "",
82
- "It cannot ask you anything mid-run. Anything it would need to ask, decide",
83
- "first — or ask the user yourself before delegating."
84
- ].join("\n");
85
- export const CLAUDE_CODE_SPEC = {
86
- key: CLAUDE_CODE_TYPE,
87
- description: "Run a coding task in the workspace with a Claude Code session — a checked-out repository, or a scratchpad.",
88
- /**
89
- * No params, and that is a decision rather than an omission.
90
- *
91
- * *Which* repository is not the delegating model's to choose: the workspace is
92
- * one Durable Object, one container and one checkout, keyed by caller and
93
- * repository, and the parent already tracks which one is active. Letting a
94
- * model name a repository here would let it name somebody else's — the same
95
- * reasoning that keeps `workspaceName` out of model input in `/computer`.
96
- */
97
- params: null,
98
- capability: CLAUDE_CODE_CAPABILITY,
99
- recipe: CLAUDE_CODE_RECIPE
100
- };
@@ -1,133 +0,0 @@
1
- import type { WorkspaceClient } from "@cloudflare/computer";
2
- /**
3
- * Reading the workspace without pulling more of it across the boundary than the
4
- * model will be shown.
5
- *
6
- * The obvious version of each function here reads everything and throws most of
7
- * it away, which is the wrong shape against a Durable Object's 128 MB. So the
8
- * budget is applied at the source, and the offsets handed back are the *source's*
9
- * rather than the rendered subset's — which is what makes the next page exact
10
- * instead of a guess.
11
- */
12
- /**
13
- * Read a file without pulling more of it across the boundary than the model will
14
- * be shown.
15
- *
16
- * `readFile(path, "utf8")` materialises the whole file in the isolate before
17
- * `truncateOutput` throws most of it away. Harmless on a source file, and the
18
- * wrong shape against a Durable Object's 128 MB — `sb_read` is one model decision
19
- * away from a lockfile, a bundle or a captured build log. The read is
20
- * range-addressable, so the budget is enforced at the source.
21
- *
22
- * Two reads rather than one, because the budget is spent from both ends for the
23
- * reason {@link truncateOutput} documents — the first error is at the top of a
24
- * file and the summary is at the bottom.
25
- *
26
- * ## The one place the budget is spent in bytes
27
- *
28
- * `maxChars` is a character ceiling everywhere else — see
29
- * {@link ComputerConfig.maxOutputChars} — and here it is spent against
30
- * `byteOffset`/`byteLength`, which are the only units the transport has, and the
31
- * only ones that bound what crosses it. Safe in the direction that matters: a
32
- * UTF-8 byte is never more than one UTF-16 code unit, so *N* bytes decode to at
33
- * most *N* characters. Reading the character budget as bytes therefore always
34
- * honours the ceiling, and errs low on a file that is mostly non-ASCII — a CJK
35
- * source file is cut at about a third of the characters it could have shown. The
36
- * alternative is a second round trip on every read, to recover a bound the
37
- * marker already announces.
38
- *
39
- * ## Why `stat` first
40
- *
41
- * Sizing off the returned string instead would be wrong in a way that hides
42
- * itself. `byteLength` counts bytes and `String.length` counts UTF-16 code units,
43
- * so a file of two-byte characters comes back *under* a character budget while
44
- * still being over the byte budget — and the read would look complete with half
45
- * the file missing and no marker saying so. One extra round trip buys the
46
- * distinction.
47
- *
48
- * A slice boundary can land mid-codepoint, which the decoder resolves to a single
49
- * replacement character. That is one glyph of noise at a cut that already
50
- * announces itself as a cut.
51
- */
52
- export declare function readBounded(fs: WorkspaceClient["fs"], path: string, maxChars: number): Promise<string>;
53
- /**
54
- * A byte window the model asked for, with its coordinates stated.
55
- *
56
- * No middle-out here, deliberately: {@link readBounded} guesses at what matters when
57
- * nobody said, but an explicit `offset` *is* the model saying. Trimming the middle
58
- * of a region it chose would defeat the request and, worse, make the next offset
59
- * unknowable.
60
- *
61
- * The window line is what makes paging work at all — the model needs to know where
62
- * it landed and how much is left to compute the next `offset`.
63
- */
64
- export declare function readWindow(fs: WorkspaceClient["fs"], path: string, offset: number, length: number, maxChars: number): Promise<string>;
65
- /**
66
- * Fetch a page, drop what is off-limits, and keep the source offsets that make the
67
- * *next* page exact.
68
- *
69
- * The subtle part is why `rawIndex` exists at all. `offset` counts items at the
70
- * source; the caller renders a filtered, budget-trimmed subset of them. So the
71
- * obvious `nextOffset = offset + shown` is wrong — it silently skips or repeats
72
- * whenever anything was dropped, which is precisely when a skipped directory is
73
- * involved. Keeping each survivor's source index means the next page starts exactly
74
- * after the last one the model actually saw.
75
- *
76
- * Retries because a skipped directory can outnumber a whole page on its own — a
77
- * dependency tree runs to tens of thousands of files — so one fetch can come back
78
- * entirely excluded. `maxRounds` is the caller's: a retry re-reads and re-scans
79
- * every file the last one looked at. For a walk the store can prune instead, see
80
- * `sb_ls`, which passes exclusions to `find` and needs none of this.
81
- *
82
- * Deliberately no slicing to `want`: the caller needs the extra item to know a next
83
- * page exists, and its index to say where.
84
- */
85
- export declare function collectVisible<T>(fetch: (offset: number, limit: number) => Promise<T[]>, pathOf: (item: T) => string, skip: (path: string) => boolean, want: number, offset: number, maxRounds: number): Promise<{
86
- items: T[];
87
- /** Source offset of `items[i]`. */
88
- rawIndex: number[];
89
- /** Source offset just past everything examined. */
90
- rawEnd: number;
91
- /** The source ran out; there is no next page. */
92
- exhausted: boolean;
93
- /** Rounds ran out while excluded paths still dominated. */
94
- crowded: boolean;
95
- }>;
96
- /** What a page of a collected listing owes the caller once it knows how much fit. */
97
- interface VisiblePage {
98
- rawIndex: number[];
99
- rawEnd: number;
100
- exhausted: boolean;
101
- crowded: boolean;
102
- }
103
- /**
104
- * The "there is more, here is where" line, with an offset that is actually correct.
105
- *
106
- * `rawIndex[shown]` rather than `offset + shown`: the first item the model did *not*
107
- * see, at its source coordinate. Anything else drifts by however many entries the
108
- * skip filter removed, and drifts silently — the next page would repeat or skip
109
- * with nothing to indicate it had.
110
- *
111
- * Narrowing is still offered, and still first-class, because it is cheaper than
112
- * paging: `offset` does not skip the walk, it only discards its early results. It is
113
- * offered as the better option rather than the only one, which is the thing the
114
- * previous wording got wrong — "narrow it" is no answer at all when the model wants
115
- * the next page of a list it is working through.
116
- */
117
- export declare function listingNote(page: VisiblePage, shown: number, noun: string, narrower: string): string;
118
- /**
119
- * Does this path exist?
120
- *
121
- * `getWorkspace()` types `fs` as the in-process `WorkspaceFilesystem`, but the
122
- * value on the far side of a Durable Object boundary is a
123
- * `WorkspaceFilesystemStub`, which carries a few methods the local class does
124
- * not — `exists` among them. So the fast path is asked for rather than cast to,
125
- * and `stat` is the fallback for a host that hands back a local workspace.
126
- *
127
- * The fallback treats *any* `stat` failure as absence, which is the honest
128
- * reading for a tool whose entire answer is a boolean: there is no error channel
129
- * to distinguish "missing" from "unreadable", and the caller's next move — look
130
- * somewhere else — is the same either way.
131
- */
132
- export declare function pathExists(fs: WorkspaceClient["fs"], path: string): Promise<boolean>;
133
- export {};