@dynamicagents/plugins 0.12.0 → 0.13.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 (130) 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 +53 -0
  5. package/dist/claude-code/cards.js +272 -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 +342 -0
  18. package/dist/claude-code/run.d.ts +209 -112
  19. package/dist/claude-code/run.js +339 -138
  20. package/dist/claude-code/session.d.ts +131 -0
  21. package/dist/claude-code/session.js +285 -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-fault.d.ts +3 -3
  69. package/dist/{computer/host → workspace}/container-fault.js +23 -8
  70. package/dist/workspace/exec.d.ts +94 -0
  71. package/dist/workspace/exec.js +153 -0
  72. package/dist/workspace/format.d.ts +36 -0
  73. package/dist/workspace/format.js +57 -0
  74. package/dist/{computer/host → workspace}/git-host.d.ts +21 -4
  75. package/dist/{computer/host → workspace}/git-host.js +72 -2
  76. package/dist/{computer/host → workspace}/git-identity.d.ts +1 -1
  77. package/dist/{computer/host → workspace}/git-identity.js +1 -1
  78. package/dist/workspace/index.d.ts +43 -47
  79. package/dist/workspace/index.js +52 -112
  80. package/dist/{computer/host → workspace}/install-job.d.ts +4 -4
  81. package/dist/{computer/host → workspace}/install-job.js +276 -176
  82. package/dist/{computer → workspace}/install.d.ts +8 -8
  83. package/dist/{computer → workspace}/install.js +3 -3
  84. package/dist/{computer/host/workspace.d.ts → workspace/object.d.ts} +105 -27
  85. package/dist/{computer/host/workspace.js → workspace/object.js} +217 -48
  86. package/dist/workspace/open.d.ts +95 -0
  87. package/dist/workspace/open.js +63 -0
  88. package/dist/workspace/read.d.ts +16 -0
  89. package/dist/workspace/read.js +22 -0
  90. package/dist/{computer → workspace}/shell.d.ts +5 -5
  91. package/dist/{computer → workspace}/shell.js +6 -6
  92. package/dist/{computer/host → workspace}/wake.d.ts +1 -1
  93. package/package.json +16 -36
  94. package/dist/arc-agi/analysis.d.ts +0 -322
  95. package/dist/arc-agi/analysis.js +0 -802
  96. package/dist/arc-agi/client.d.ts +0 -82
  97. package/dist/arc-agi/client.js +0 -113
  98. package/dist/arc-agi/game-tools.d.ts +0 -24
  99. package/dist/arc-agi/game-tools.js +0 -26
  100. package/dist/arc-agi/index.d.ts +0 -40
  101. package/dist/arc-agi/index.js +0 -175
  102. package/dist/arc-agi/main-agent.d.ts +0 -24
  103. package/dist/arc-agi/main-agent.js +0 -62
  104. package/dist/arc-agi/recipe.d.ts +0 -48
  105. package/dist/arc-agi/recipe.js +0 -97
  106. package/dist/arc-agi/scorecard.d.ts +0 -118
  107. package/dist/arc-agi/scorecard.js +0 -163
  108. package/dist/arc-agi/soul.d.ts +0 -29
  109. package/dist/arc-agi/soul.js +0 -79
  110. package/dist/arc-agi/store.d.ts +0 -153
  111. package/dist/arc-agi/store.js +0 -215
  112. package/dist/arc-agi/tools.d.ts +0 -36
  113. package/dist/arc-agi/tools.js +0 -574
  114. package/dist/arc-agi/types.d.ts +0 -211
  115. package/dist/arc-agi/types.js +0 -19
  116. package/dist/claude-code/recipe.d.ts +0 -53
  117. package/dist/claude-code/recipe.js +0 -100
  118. package/dist/computer/read.d.ts +0 -133
  119. package/dist/computer/read.js +0 -200
  120. package/dist/computer/tools-find.js +0 -216
  121. package/dist/recall/index.d.ts +0 -105
  122. package/dist/recall/index.js +0 -181
  123. package/dist/repo/tools-forge.d.ts +0 -4
  124. package/dist/triage/index.d.ts +0 -360
  125. package/dist/triage/index.js +0 -311
  126. /package/dist/{computer/host → workspace}/container-deps.d.ts +0 -0
  127. /package/dist/{computer/host → workspace}/container-deps.js +0 -0
  128. /package/dist/{computer/host → workspace}/sync.d.ts +0 -0
  129. /package/dist/{computer/host → workspace}/sync.js +0 -0
  130. /package/dist/{computer/host → workspace}/wake.js +0 -0
@@ -1,97 +0,0 @@
1
- import { z } from "zod";
2
- import { ARC_GAME_SOUL } from "./soul.js";
3
- import { ARC_CAPABILITY, arcDelegationGuidance } from "./main-agent.js";
4
- /** Semantic Subtask type the decomposer emits for a "play this game" request. */
5
- export const ARC_GAME_TYPE = "arc-game";
6
- /**
7
- * Recipe for playing an ARC-AGI-3 game. Names no model, so it runs on whatever
8
- * pair its host agent is configured with; what distinguishes it is its tool
9
- * family, its soul, its context discipline, and
10
- * a turn budget twice the baseline — a play is a long sequence of cheap decisions,
11
- * and 20 turns bought roughly ten game actions once inspection was paid for.
12
- *
13
- * **Budget the turns, never the chunks.** A turn here is a reasoning model plus
14
- * an ARC HTTP round trip, nothing like the sub-ten-second turn a chunk count is
15
- * implicitly sized against: 1,000 turns sliced 25 to a chunk is 40 chunks on
16
- * paper and 70-100 in a real run, which blows the per-branch cap and *fails* a
17
- * play after hours rather than asking it to report. Time and turns are both
18
- * enforced directly, and a play ends through the graceful summary — a terminal
19
- * report with the metrics footer.
20
- *
21
- * - `historyWindow` bounds context, and it is the model's *only* memory: with no
22
- * workspace tools (see below) a plan that scrolls out of it is gone. Note it
23
- * counts *assistant messages* — one per tool call, not one per game action —
24
- * so a play spends it several times faster than the number suggests.
25
- * - `reportMetrics` appends the turns/model-calls/wall-clock footer the user
26
- * asked to see.
27
- *
28
- * Tool family: `arc-game` alone (act/inspect against the ARC REST API, session
29
- * state kept in the workspace), code-validated by
30
- * `validateRecipe`/`buildRecipeTools`.
31
- *
32
- * **No `workspace` family, despite the small history window.** Across two logged
33
- * plays `ws_read` was never called and the three `ws_write` calls were a
34
- * scratchpad for arithmetic — a note costing a turn apiece, which `arc_act`'s
35
- * `note` field carries for free and keeps in the model's own history. The
36
- * session file is unaffected: the family reaches the workspace through the
37
- * `ToolFamilyContext` core hands it, not through tools the model can see.
38
- */
39
- export const ARC_GAME_RECIPE = {
40
- key: ARC_GAME_TYPE,
41
- version: 1,
42
- // A recipe states no model, and `ResolvedRecipe` has no field to state one
43
- // with. Every recipe runs on the agent's own configured pair, which
44
- // `validateRecipe` stamps onto the `ValidatedRecipe` a runner consumes.
45
- soul: ARC_GAME_SOUL,
46
- toolFamilies: ["arc-game"],
47
- enabled: true,
48
- // Twice the baseline turns, and the largest number that keeps
49
- // `MAX_CHUNKS_PER_BRANCH` unreachable: a yielding chunk always advanced at least
50
- // one turn, so a run takes at most `maxTurns` chunks and the cap is 40. Asserted
51
- // in `test/agent/subtasks/subtask-types.spec.ts` — raising this past 39 is a
52
- // platform change, not a recipe one.
53
- //
54
- // `maxWallMs` deliberately stays at the 30-minute baseline. Measured turns run
55
- // ~15s but reach 165s, so time may well end a play before turn 39 does; both
56
- // ceilings end it the same way, through the graceful summary, so the cost of
57
- // guessing wrong here is a shorter play rather than lost work.
58
- limits: { maxTurns: 39 },
59
- // Counts assistant messages (tool calls), so an inspect + act cycle spends two
60
- // or three of these per game action; 12 left the model unable to see more than a
61
- // couple of moves back, which it answered by re-inspecting.
62
- //
63
- // Lowered from 32 because `elideToolOutputs` changed what a slot *costs*, not
64
- // how many there are: a turn that has aged past the detail window now carries
65
- // its reasoning and its `note` but not the board render that was nearly all of
66
- // its tokens. 32 was the compensation for losing the workspace tools, and the
67
- // thing it was compensating for — reach — is unaffected by the elision.
68
- historyWindow: 24,
69
- reportMetrics: true
70
- };
71
- /**
72
- * The arc-game type. Its one param is an id the model quotes back from a tool
73
- * result it already saw, so the contract is checkable before anything runs: a
74
- * play with no game cannot succeed, and refusing it here costs no model call.
75
- *
76
- * There is deliberately no `card_id`. Which scorecard a play runs on is not a
77
- * choice — the API auto-closes an idle card, so the live card is whichever one
78
- * was used recently — and the parent leases it per chunk (see
79
- * {@link file://./scorecard.ts}), handing it to the execution as runtime state.
80
- */
81
- export const ARC_GAME_SPEC = {
82
- key: ARC_GAME_TYPE,
83
- description: "Play one ARC-AGI-3 game.",
84
- params: z.object({
85
- game_id: z.string().min(1).describe("An exact game id from arc_list_games")
86
- }),
87
- paramsHelp: "requires param `game_id` (an exact id from `arc_list_games`)",
88
- // Everything the main agent is told about ARC is declared here, never written
89
- // inside a runtime — see {@link file://./main-agent.ts}. Both blocks live on
90
- // the *type* rather than on the plugin, because a plugin that declares a
91
- // subtask type has two places it could put a capability block and they are
92
- // rendered by different call sites: setting both makes the main agent read the
93
- // same advice twice per round, which is the exact drift these fields ended.
94
- capability: ARC_CAPABILITY,
95
- delegationGuidance: arcDelegationGuidance,
96
- recipe: ARC_GAME_RECIPE
97
- };
@@ -1,118 +0,0 @@
1
- import type { ArcClient } from "./client.js";
2
- import type { CookieJar, FrameResponse, Scorecard, ScorecardSummary } from "./types.js";
3
- /**
4
- * The `arc-game` recipe's scorecard policy: which card a play runs on, and what
5
- * that play scored.
6
- *
7
- * Neither is a model's decision any more. The ARC API auto-closes a card after
8
- * ~15 minutes idle, which makes the whole open/close lifecycle the *server's* —
9
- * so the only judgement left is arithmetic: a card used recently is still alive
10
- * and every concurrent play should share it; an older one is gone and a new card
11
- * has to be opened. That is {@link resolveScorecard}, run by the parent once per
12
- * durable chunk (a subagent facet has no DB, so it cannot own this).
13
- *
14
- * Because nothing closes a card, the score is *read* rather than returned:
15
- * `GET /api/scorecard/{card_id}` works on an open card, and
16
- * {@link gameScoreReport} appends the finished game's entry to its play's report.
17
- *
18
- * Handlers are exported separately from any tool wiring so they unit-test without
19
- * an LLM, and {@link ScorecardStore} is a narrow interface (`AgentDB.scorecards`
20
- * satisfies it structurally) so tests can pass an in-memory fake.
21
- */
22
- /**
23
- * How long a card stays reusable. Deliberately a minute short of the API's ~15
24
- * minute idle auto-close: the clock is bumped per durable chunk, and a chunk is
25
- * capped at `CHUNK_SOFT_MS` (4 minutes), so the margin only has to cover the gap
26
- * between two bumps — not a whole play.
27
- */
28
- export declare const SCORECARD_REUSE_MS: number;
29
- /** The slice of `AgentDB.scorecards` the scorecard policy needs. */
30
- export interface ScorecardStore {
31
- findRecent(since: number): Scorecard | null;
32
- get(cardId: string): Scorecard | null;
33
- open(cardId: string, cookies: CookieJar): Scorecard;
34
- setGuid(cardId: string, gameId: string, guid: string): void;
35
- touch(cardId: string): void;
36
- }
37
- export interface ArcScorecardDeps {
38
- store: ScorecardStore;
39
- client: ArcClient;
40
- }
41
- /** The resolved card a play runs on: its id, and the jar the API pinned to it. */
42
- export interface ResolvedScorecard {
43
- cardId: string;
44
- cookies: CookieJar;
45
- }
46
- /**
47
- * Lease a scorecard for a play: reuse the most recently used live card, or open a
48
- * new one. Either way the card's clock is restarted, so a play that keeps calling
49
- * this (once per chunk) keeps its own card alive for as long as it runs.
50
- *
51
- * `now` is injected so the window is testable at its boundary.
52
- */
53
- export declare function resolveScorecard(deps: ArcScorecardDeps, now?: number): Promise<ResolvedScorecard>;
54
- /** A play a subagent can join: the card, and the ARC session handle on it. */
55
- export interface ResolvedPlay extends ResolvedScorecard {
56
- /** The ARC play handle. Every ACTION is addressed to it. */
57
- guid: string;
58
- /**
59
- * The opening frame — present **only** on the call that minted the guid, and
60
- * absent on every later resolution of the same play. There is no ARC endpoint
61
- * that reads a board back, so this is the one chance to hand one over; a
62
- * subagent that joins later learns the board from its first ACTION instead.
63
- */
64
- frame?: FrameResponse;
65
- }
66
- /**
67
- * Resolve the play a Subtask runs: the leased card, plus the guid for this game
68
- * on it — reusing the recorded one, or RESETting **once** to mint it.
69
- *
70
- * This is the only RESET in the system. A guid is mintable only by RESET, and a
71
- * second RESET is a second run on the card: separately scored, with whatever the
72
- * first play reached left behind. Pinning one guid per (card, game) in the store
73
- * is what makes a re-dispatched Subtask, a lost workspace, or a later chunk
74
- * rejoin the play in progress instead of quietly starting another — so a
75
- * GAME_OVER stays the result this card recorded for this game.
76
- */
77
- export declare function resolvePlay(deps: ArcScorecardDeps, gameId: string, now?: number): Promise<ResolvedPlay>;
78
- /**
79
- * {@link resolvePlay} on a card the caller has **already** leased.
80
- *
81
- * Split out because resolving the card inside is a race the caller may have
82
- * gone to trouble to avoid: a host that collapses concurrent scorecard leases
83
- * onto one call (as the plugin does) would have that work bypassed entirely if
84
- * every play re-resolved its own card. Two plays for *different* games starting
85
- * together would then each find an empty ledger and each open a card, which is
86
- * exactly the shared-card behaviour the collapse exists to produce.
87
- */
88
- export declare function resolvePlayOn(deps: ArcScorecardDeps, card: ResolvedScorecard, gameId: string): Promise<ResolvedPlay>;
89
- /**
90
- * Exactly what a game's report may be built from — deliberately narrower than
91
- * {@link ScorecardSummary}, which also carries card-wide totals. Narrowing it
92
- * here makes quoting one of those totals as a game's own result a type error
93
- * rather than a judgement call, which is the mistake this guards.
94
- */
95
- export type GameScoreSource = Pick<ScorecardSummary, "card_id" | "environments">;
96
- /**
97
- * What one game scored on a card: its aggregate, then a line per play.
98
- *
99
- * Reads **only** the game's own `environments` entry. Every top-level field of
100
- * the response (`score`, `total_actions`, `total_levels_completed`, …) covers the
101
- * whole card, and since concurrent plays share a card by design, quoting one as
102
- * this game's result would be a straightforward mislabeling — verified against
103
- * the live API, where a card with two games reported both games' actions at the
104
- * top level.
105
- */
106
- export declare function renderGameScore(summary: GameScoreSource, gameId: string): string;
107
- /**
108
- * The finished play's score, as a line to append to its report — or null if it
109
- * cannot be read.
110
- *
111
- * Best-effort by contract: this runs *after* a play has already succeeded, so a
112
- * rate-limited or malformed score response must cost the run nothing. Every
113
- * failure is logged and swallowed.
114
- *
115
- * Reads with the card's stored jar rather than the play's: the play's jar drifted
116
- * across chunks, while the stored one is the session the API pinned the card to.
117
- */
118
- export declare function gameScoreReport(deps: ArcScorecardDeps, cardId: string, gameId: string): Promise<string | null>;
@@ -1,163 +0,0 @@
1
- import { z } from "zod";
2
- /**
3
- * The `arc-game` recipe's scorecard policy: which card a play runs on, and what
4
- * that play scored.
5
- *
6
- * Neither is a model's decision any more. The ARC API auto-closes a card after
7
- * ~15 minutes idle, which makes the whole open/close lifecycle the *server's* —
8
- * so the only judgement left is arithmetic: a card used recently is still alive
9
- * and every concurrent play should share it; an older one is gone and a new card
10
- * has to be opened. That is {@link resolveScorecard}, run by the parent once per
11
- * durable chunk (a subagent facet has no DB, so it cannot own this).
12
- *
13
- * Because nothing closes a card, the score is *read* rather than returned:
14
- * `GET /api/scorecard/{card_id}` works on an open card, and
15
- * {@link gameScoreReport} appends the finished game's entry to its play's report.
16
- *
17
- * Handlers are exported separately from any tool wiring so they unit-test without
18
- * an LLM, and {@link ScorecardStore} is a narrow interface (`AgentDB.scorecards`
19
- * satisfies it structurally) so tests can pass an in-memory fake.
20
- */
21
- /**
22
- * How long a card stays reusable. Deliberately a minute short of the API's ~15
23
- * minute idle auto-close: the clock is bumped per durable chunk, and a chunk is
24
- * capped at `CHUNK_SOFT_MS` (4 minutes), so the margin only has to cover the gap
25
- * between two bumps — not a whole play.
26
- */
27
- export const SCORECARD_REUSE_MS = 14 * 60_000;
28
- /**
29
- * Lease a scorecard for a play: reuse the most recently used live card, or open a
30
- * new one. Either way the card's clock is restarted, so a play that keeps calling
31
- * this (once per chunk) keeps its own card alive for as long as it runs.
32
- *
33
- * `now` is injected so the window is testable at its boundary.
34
- */
35
- export async function resolveScorecard(deps, now = Date.now()) {
36
- const recent = deps.store.findRecent(now - SCORECARD_REUSE_MS);
37
- if (recent) {
38
- deps.store.touch(recent.cardId);
39
- return { cardId: recent.cardId, cookies: recent.cookies };
40
- }
41
- const { cardId, cookies } = await deps.client.openScorecard({});
42
- deps.store.open(cardId, cookies);
43
- return { cardId, cookies };
44
- }
45
- /**
46
- * Resolve the play a Subtask runs: the leased card, plus the guid for this game
47
- * on it — reusing the recorded one, or RESETting **once** to mint it.
48
- *
49
- * This is the only RESET in the system. A guid is mintable only by RESET, and a
50
- * second RESET is a second run on the card: separately scored, with whatever the
51
- * first play reached left behind. Pinning one guid per (card, game) in the store
52
- * is what makes a re-dispatched Subtask, a lost workspace, or a later chunk
53
- * rejoin the play in progress instead of quietly starting another — so a
54
- * GAME_OVER stays the result this card recorded for this game.
55
- */
56
- export async function resolvePlay(deps, gameId, now = Date.now()) {
57
- return resolvePlayOn(deps, await resolveScorecard(deps, now), gameId);
58
- }
59
- /**
60
- * {@link resolvePlay} on a card the caller has **already** leased.
61
- *
62
- * Split out because resolving the card inside is a race the caller may have
63
- * gone to trouble to avoid: a host that collapses concurrent scorecard leases
64
- * onto one call (as the plugin does) would have that work bypassed entirely if
65
- * every play re-resolved its own card. Two plays for *different* games starting
66
- * together would then each find an empty ledger and each open a card, which is
67
- * exactly the shared-card behaviour the collapse exists to produce.
68
- */
69
- export async function resolvePlayOn(deps, card, gameId) {
70
- const { cardId, cookies } = card;
71
- const recorded = deps.store.get(cardId)?.guids[gameId];
72
- if (recorded !== undefined)
73
- return { cardId, cookies, guid: recorded };
74
- const { frame, cookies: next } = await deps.client.reset({ gameId, cardId }, cookies);
75
- deps.store.setGuid(cardId, gameId, frame.guid);
76
- // `setGuid` keeps the first guid written, so losing a race to a concurrent
77
- // resolution means this RESET opened a play nobody will join. Hand back the
78
- // guid that won — and not this frame, which belongs to the abandoned play.
79
- const winner = deps.store.get(cardId)?.guids[gameId] ?? frame.guid;
80
- return winner === frame.guid
81
- ? { cardId, cookies: next, guid: frame.guid, frame }
82
- : { cardId, cookies: next, guid: winner };
83
- }
84
- /**
85
- * Loose on purpose: a field the API adds tomorrow must not turn a real result
86
- * into a parse error. The fields asserted here are the ones
87
- * {@link renderGameScore} actually renders.
88
- */
89
- const runSchema = z.looseObject({
90
- guid: z.string(),
91
- actions: z.number(),
92
- completed: z.boolean(),
93
- levels_completed: z.number(),
94
- resets: z.number(),
95
- score: z.number(),
96
- state: z.enum(["NOT_STARTED", "NOT_FINISHED", "WIN", "GAME_OVER"])
97
- });
98
- const environmentSchema = z.looseObject({
99
- id: z.string(),
100
- actions: z.number(),
101
- completed: z.boolean(),
102
- level_count: z.number(),
103
- levels_completed: z.number(),
104
- resets: z.number(),
105
- score: z.number(),
106
- runs: z.array(runSchema)
107
- });
108
- const summarySchema = z.looseObject({
109
- card_id: z.string(),
110
- environments: z.array(environmentSchema)
111
- });
112
- /**
113
- * What one game scored on a card: its aggregate, then a line per play.
114
- *
115
- * Reads **only** the game's own `environments` entry. Every top-level field of
116
- * the response (`score`, `total_actions`, `total_levels_completed`, …) covers the
117
- * whole card, and since concurrent plays share a card by design, quoting one as
118
- * this game's result would be a straightforward mislabeling — verified against
119
- * the live API, where a card with two games reported both games' actions at the
120
- * top level.
121
- */
122
- export function renderGameScore(summary, gameId) {
123
- // Match by id rather than taking the sole entry on trust: a mislabeled result
124
- // is worse than none.
125
- const env = summary.environments.find((e) => e.id === gameId);
126
- if (!env || env.runs.length === 0) {
127
- return `Scorecard ${summary.card_id} recorded no plays of ${gameId}.`;
128
- }
129
- const header = `Score for ${gameId} on scorecard ${summary.card_id}: ` +
130
- `${env.score} — ${env.levels_completed}/${env.level_count} levels, ` +
131
- `${env.actions} actions across ${env.runs.length} play(s)` +
132
- (env.completed ? " (completed)" : "") +
133
- ".";
134
- const plays = env.runs.map((run, index) => `- play ${index + 1}: ${run.state}, ${run.levels_completed} level(s), ` +
135
- `${run.actions} actions, score ${run.score}`);
136
- return `${header}\n${plays.join("\n")}`;
137
- }
138
- /**
139
- * The finished play's score, as a line to append to its report — or null if it
140
- * cannot be read.
141
- *
142
- * Best-effort by contract: this runs *after* a play has already succeeded, so a
143
- * rate-limited or malformed score response must cost the run nothing. Every
144
- * failure is logged and swallowed.
145
- *
146
- * Reads with the card's stored jar rather than the play's: the play's jar drifted
147
- * across chunks, while the stored one is the session the API pinned the card to.
148
- */
149
- export async function gameScoreReport(deps, cardId, gameId) {
150
- try {
151
- const card = deps.store.get(cardId);
152
- const { summary } = await deps.client.getScorecard(cardId, card?.cookies ?? {});
153
- return renderGameScore(summarySchema.parse(summary), gameId);
154
- }
155
- catch (err) {
156
- console.warn("[arc-game] scorecard read failed", {
157
- cardId,
158
- gameId,
159
- err: String(err)
160
- });
161
- return null;
162
- }
163
- }
@@ -1,29 +0,0 @@
1
- /**
2
- * The soul (system prompt) for the ARC-AGI-3 game-playing recipe. The domain
3
- * mechanics (sessions, cookies, frame analysis) live entirely in the `arc-game`
4
- * tool family; this prompt only tells the model how to play.
5
- *
6
- * It plays on a scorecard the parent leased for it. The game is a declared
7
- * Subtask param and the card is resolved runtime state, so the tools close over
8
- * both and the model never names, chooses, or copies either id.
9
- *
10
- * Sections written against logged failures rather than a theory of good play,
11
- * and the constraints they carry:
12
- *
13
- * - **Reading a step's result** names each register separately — refused,
14
- * nothing moved, changed but did not travel — because `nothing moved` is a
15
- * movement game's vocabulary and a click game moves nothing ever. The wording
16
- * here is paired with the rendering in {@link file://./analysis.ts}: teach a
17
- * register the prompt does not name, or name one the renderer never emits, and
18
- * the model reads every click as refused.
19
- * - **Where the views stand** is ordered by measurement, not by cost intuition:
20
- * `shapes` for the map, `grid` for exact cells, `region` for fine detail only.
21
- * The full grid of a real board is 35 collapsed lines, so `grid` is not the
22
- * expensive last resort it reads as; rank it as one and the model maps a
23
- * maze through `region` peepholes rather than reading the board whole.
24
- * - **Batching** requires a route to be walked against those bands before it is
25
- * sent. That check is here rather than in the tool because it is a judgement
26
- * about the game's rules — what blocks what — and a tool making it would be
27
- * guessing on the model's behalf.
28
- */
29
- export declare const ARC_GAME_SOUL: string;
@@ -1,79 +0,0 @@
1
- /**
2
- * The soul (system prompt) for the ARC-AGI-3 game-playing recipe. The domain
3
- * mechanics (sessions, cookies, frame analysis) live entirely in the `arc-game`
4
- * tool family; this prompt only tells the model how to play.
5
- *
6
- * It plays on a scorecard the parent leased for it. The game is a declared
7
- * Subtask param and the card is resolved runtime state, so the tools close over
8
- * both and the model never names, chooses, or copies either id.
9
- *
10
- * Sections written against logged failures rather than a theory of good play,
11
- * and the constraints they carry:
12
- *
13
- * - **Reading a step's result** names each register separately — refused,
14
- * nothing moved, changed but did not travel — because `nothing moved` is a
15
- * movement game's vocabulary and a click game moves nothing ever. The wording
16
- * here is paired with the rendering in {@link file://./analysis.ts}: teach a
17
- * register the prompt does not name, or name one the renderer never emits, and
18
- * the model reads every click as refused.
19
- * - **Where the views stand** is ordered by measurement, not by cost intuition:
20
- * `shapes` for the map, `grid` for exact cells, `region` for fine detail only.
21
- * The full grid of a real board is 35 collapsed lines, so `grid` is not the
22
- * expensive last resort it reads as; rank it as one and the model maps a
23
- * maze through `region` peepholes rather than reading the board whole.
24
- * - **Batching** requires a route to be walked against those bands before it is
25
- * sent. That check is here rather than in the tool because it is a judgement
26
- * about the game's rules — what blocks what — and a tool making it would be
27
- * guessing on the model's behalf.
28
- */
29
- export const ARC_GAME_SOUL = [
30
- "You are playing an ARC-AGI-3 game: a visual-reasoning puzzle on a 64×64 grid of colored cells. You discover the game's hidden rules by acting and observing, and progress through levels toward a win.",
31
- "",
32
- "# How to play",
33
- "1. Your game is already running — there is nothing to start. Which game you play, and on which scorecard, were decided before you began. Start with `arc_inspect` (`shapes` view) to see where everything is, or go straight to `arc_act` if you already know what to try. Either way the reply tells you the current level, the game state, and which actions are legal right now (`available_actions`). If `arc_inspect` says no board has arrived yet, the play was opened before you joined it: your first `arc_act` step is also how the board reaches you, so spend it on a direction you wanted to try anyway rather than on a probe.",
34
- "2. Call `arc_act` with the `steps` you want to take, in order. Actions: 1=up, 2=down, 3=left, 4=right, 5=interact/select, 6=click at an (x,y) coordinate (x and y are required for action 6 only), 7=undo.",
35
- "3. `arc_act` reports each step separately, in the register that step calls for: which shapes moved, from where to where and how far; which changed color where they stood, appeared, or vanished; `0 cells changed (no effect at all)` when the game refused the action outright; and `nothing moved` when objects stayed put while a counter or a bar ticked, which in a game you steer is a wall. Read `no shape travelled, but the board changed` as what it says — that action did something, and what it did is on the same line. After a batch you also get the net travel per shape, counted in moves rather than cells, and how many steps changed nothing at all. Trust those lines over your own arithmetic: where the report says you are is where you are.",
36
- "4. When you need to see the board itself, call `arc_inspect`. `shapes` is your map and the view to reach for: it lists every colored region with the rows and columns it occupies, and for the big sparse ones — walls, floors, frames, anything that is mostly holes — it gives the columns that color occupies in each band of rows, because a bounding box round a maze says nothing. `grid` is the whole board, one character per cell with a legend; it is not the expensive option it sounds like, since bands of identical rows collapse into one line, and it is the right call when you need exact cells. `region` is a labeled close-up around a point — use it to read fine detail, not to map a board a row band at a time. `histogram` is the color counts. Inspecting costs no game action, but it costs a turn out of your budget — and repeating a view of a board that has not changed tells you nothing, so the tool will say so instead of drawing it again. Inspect to answer a question you actually have; otherwise act.",
37
- "",
38
- "# Colors",
39
- "Results name colors rather than numbering them. Some are deliberately close relatives: magenta and magenta-light, blue and blue-light, neutral and neutral-light. Treat those as distinct colors that a game may well use as a pair. `white` is the usual background. In the `grid` view each cell is one character and the legend tells you which color it stands for — the `b` in the grid and the `yellow` in a diff can be the same color.",
40
- "A color that spreads thinly over a large area is described by the rows and columns it actually occupies rather than by one box: `too sparse for a box, so by row:` followed by a line per band of rows. Read those lines as the same kind of fact as a box, at the resolution you need to walk through it. The percentage in front of them is how much of that box the color really fills — a low one is your warning that the rest of the box is something else.",
41
- "",
42
- "# Batching actions",
43
- "`steps` accepts up to 8 actions. Batch the whole path you mean to walk — a batch is one turn where eight single steps are eight, and turns are the budget you will actually run out of. What a batch reports back is per step, so you lose no information by sending several at once: you see which of them moved something and which did not.",
44
- "- Send ONE step when you are still working out what an action even does, and the result will teach you. Send the whole route once you know the mechanics.",
45
- "- A batch runs to the end whatever happens: a step that hits a wall does not stop the ones after it, and each of them still costs an action. So batch a route you have reason to believe in, and read the idle steps and the net travel afterwards to find out where your belief was wrong.",
46
- "- Walk the route against the board before you send it. You know where you are and how far one action moves you, so every step of a planned batch lands on a row range and a column range — and the `shapes` view already told you, band by band, which color occupies those rows and columns. Check the destination of each step against that before you commit to it. Nothing will stop you sending a step into a wall, and the walls are not going to be mentioned unless you look them up.",
47
- "- A batch does stop early if an action is not available or the play ends; steps it did not send are listed as `not sent`, so trust that list rather than assuming all your steps ran.",
48
- "- Every step is a real move, and the game scores you against a human baseline number of actions. Actions spent on a guess that turns out wrong cost you score, whether you spent them one at a time or eight at once.",
49
- "",
50
- "# Strategy",
51
- "- Start by exploring: try single actions and watch what changes, to learn the mechanics before committing to a plan.",
52
- "- `available_actions` is the game's own declaration of what is legal — a keyboard-only game will never offer click, however long you wait. Do not spend actions probing for actions it has not offered; work with what it lists.",
53
- "- Look for structure: repeated shapes, symmetry, color regions, objects that move or transform when you act. Watch what moves *besides* the thing you are steering — a shape that travels with you, against you, or only when you act is a mechanic, and every moved shape is named in the result.",
54
- "- A step that did nothing is a real clue, not a failure: a wall, an edge, or a rule stopped that action. Two `nothing moved` or `0 cells changed` in the same direction means that direction is closed, and a third will be too. But judge that per game: in a game played by clicking, nothing was ever going to travel, so the useful distinction is between clicks that changed the board and clicks that changed not one cell.",
55
- "- If `levels_completed` goes up, your approach is working — keep going. If nothing changes across several tries, change tactics.",
56
- "- Undo (action 7) is cheap when a move looks like a mistake and undo is available.",
57
- "- You get ONE play, and it is the play you were handed — not one you can open. There is no restart: a WIN or a GAME_OVER is final, and it is the result your scorecard records for this game. So treat every action as spent for good — think before you act rather than counting on another attempt, and when the play ends, report what happened instead of trying to undo it.",
58
- "",
59
- "# The scorecard is not yours",
60
- "A scorecard was chosen for you, and you may be sharing it with other games being played right now. You have no tool to open, close, choose, or score a card — do not claim a score, and do not treat reaching WIN or GAME_OVER as something you must clean up. Your game's score is read from the card and appended to your report after you finish.",
61
- "",
62
- "# What you were told, and what you have seen",
63
- "Your task may hand you knowledge from an earlier play: a route, a map, what the colors mean. Treat it as a well-informed guess, not as fact. It came from a play that did not finish this level — that is why you are here — and levels get harder by adding elements nobody has seen yet, so a route that worked before can be wrong in ways whoever wrote it could not know. Check it against your own first result before you spend a batch on it, and when it turns out wrong, say so in your report: that correction is worth more to the next play than the route was.",
64
- "Your own results outrank everything else. If the board contradicts what you were told, or contradicts what you worked out three turns ago, the board is right.",
65
- "",
66
- "# Memory discipline (important)",
67
- "You do NOT keep your full history in view — only your most recent turns, and you have no file store: there is nowhere to write a note but into the play itself. Use `arc_act`'s `note` field for that. It costs no turn and no action, it rides along with a move you were making anyway, and it stays in your history where you can read it back. Put in it what you would otherwise forget: the rule you just confirmed, the route you are walking and which step of it you are on, what you have already ruled out.",
68
- "You also get your bearings back for free: after any gap in your turns, your next tool result opens by restating where you are — level, state, legal actions, and where every shape sits. So never spend a turn on `arc_inspect` just to re-orient after losing track. Inspect when you want a view you do not have — a close-up, the color counts, the full grid.",
69
- "",
70
- "# Finishing",
71
- "Your work ends when you have nothing useful left to try, or when your budget is exhausted. Your final report is the only thing that survives this play, and the next one will be planned from it — so write it as a handover, in plain text, with these parts:",
72
- "- **Outcome**: which game, the final state (report a GAME_OVER plainly — it is a real outcome, not a failure to hide), and how many levels you completed.",
73
- '- **Confirmed mechanics**: one line each, with the observation that confirmed it — "`right` moved the orange 5×5 five columns; walls report `nothing moved`". Only things a tool result actually showed you.',
74
- "- **Still unknown**: what you suspect but never tested, named as untested. A hypothesis you ran out of turns before checking belongs here, never among the mechanics.",
75
- "- **Where things are**: the geography of the level you reached, taken from your most recent view of it and not from memory.",
76
- "- **What to try next**, and what not to repeat.",
77
- "Two rules for the whole report. Give positions only from your latest view of the board — not from where you believed you were — and if you are stating something you inferred rather than watched happen, say that you inferred it. A confident wrong fact costs the next play more than an admitted gap does.",
78
- "Runtime metrics (turns taken, model calls, wall-clock time) and your game's score are appended automatically — do not invent either, and do not report a scorecard score yourself."
79
- ].join("\n");
@@ -1,153 +0,0 @@
1
- import type { PluginStore } from "@dynamicagents/core";
2
- import type { ScorecardStore } from "./scorecard.js";
3
- /**
4
- * The `arc_scorecards` table — cards this agent opened, as a **recency ledger**
5
- * rather than a lifecycle.
6
- *
7
- * The ARC API auto-closes a card after ~15 minutes idle, so nothing here ever
8
- * closes one and there is no open/closed state worth keeping: a card used
9
- * recently is live, an older one is gone. `last_used_at` is that clock, bumped
10
- * every time a play resolves onto the card, and the only column anything queries
11
- * by — see `resolveScorecard` in {@link file://./scorecard.ts}.
12
- *
13
- * ## Why the DDL is hand-written and the queries are not
14
- *
15
- * A plugin must never run drizzle's durable-sqlite **migrator**: it keeps one
16
- * flat integer journal and one global `__drizzle_migrations` table, which two
17
- * independently-versioned packages cannot share: two agents consuming the same
18
- * module fork that journal at the first index they disagree on. And
19
- * `drizzle-kit generate` diffs against a snapshot in a single output directory,
20
- * so a plugin shipping from its own repo cannot produce a correct diff at all.
21
- *
22
- * None of that touches the **query builder**, which is a typed wrapper over the
23
- * same `DurableObjectStorage` holding no journal and no connection state. So the
24
- * split is: `CREATE TABLE IF NOT EXISTS` by hand in {@link arcScorecardStore},
25
- * every read and write through drizzle below. A second handle alongside core's
26
- * `AgentDB` is safe — neither carries state the other can disturb.
27
- *
28
- * The table is prefixed `arc_` because a plugin's tables share one SQLite
29
- * database with core's and with every other installed plugin's. An unprefixed
30
- * `scorecards` is a name a second plugin could plausibly want.
31
- */
32
- export declare const arcScorecards: import("drizzle-orm/sqlite-core").SQLiteTableWithColumns<{
33
- name: "arc_scorecards";
34
- schema: undefined;
35
- columns: {
36
- cardId: import("drizzle-orm/sqlite-core").SQLiteColumn<{
37
- name: "card_id";
38
- tableName: "arc_scorecards";
39
- dataType: "string";
40
- columnType: "SQLiteText";
41
- data: string;
42
- driverParam: string;
43
- notNull: true;
44
- hasDefault: false;
45
- isPrimaryKey: true;
46
- isAutoincrement: false;
47
- hasRuntimeDefault: false;
48
- enumValues: [string, ...string[]];
49
- baseColumn: never;
50
- identity: undefined;
51
- generated: undefined;
52
- }, {}, {
53
- length: number | undefined;
54
- }>;
55
- cookiesJson: import("drizzle-orm/sqlite-core").SQLiteColumn<{
56
- name: "cookies_json";
57
- tableName: "arc_scorecards";
58
- dataType: "string";
59
- columnType: "SQLiteText";
60
- data: string;
61
- driverParam: string;
62
- notNull: true;
63
- hasDefault: true;
64
- isPrimaryKey: false;
65
- isAutoincrement: false;
66
- hasRuntimeDefault: false;
67
- enumValues: [string, ...string[]];
68
- baseColumn: never;
69
- identity: undefined;
70
- generated: undefined;
71
- }, {}, {
72
- length: number | undefined;
73
- }>;
74
- guidsJson: import("drizzle-orm/sqlite-core").SQLiteColumn<{
75
- name: "guids_json";
76
- tableName: "arc_scorecards";
77
- dataType: "string";
78
- columnType: "SQLiteText";
79
- data: string;
80
- driverParam: string;
81
- notNull: true;
82
- hasDefault: true;
83
- isPrimaryKey: false;
84
- isAutoincrement: false;
85
- hasRuntimeDefault: false;
86
- enumValues: [string, ...string[]];
87
- baseColumn: never;
88
- identity: undefined;
89
- generated: undefined;
90
- }, {}, {
91
- length: number | undefined;
92
- }>;
93
- openedAt: import("drizzle-orm/sqlite-core").SQLiteColumn<{
94
- name: "opened_at";
95
- tableName: "arc_scorecards";
96
- dataType: "number";
97
- columnType: "SQLiteInteger";
98
- data: number;
99
- driverParam: number;
100
- notNull: true;
101
- hasDefault: false;
102
- isPrimaryKey: false;
103
- isAutoincrement: false;
104
- hasRuntimeDefault: false;
105
- enumValues: undefined;
106
- baseColumn: never;
107
- identity: undefined;
108
- generated: undefined;
109
- }, {}, {}>;
110
- lastUsedAt: import("drizzle-orm/sqlite-core").SQLiteColumn<{
111
- name: "last_used_at";
112
- tableName: "arc_scorecards";
113
- dataType: "number";
114
- columnType: "SQLiteInteger";
115
- data: number;
116
- driverParam: number;
117
- notNull: true;
118
- hasDefault: false;
119
- isPrimaryKey: false;
120
- isAutoincrement: false;
121
- hasRuntimeDefault: false;
122
- enumValues: undefined;
123
- baseColumn: never;
124
- identity: undefined;
125
- generated: undefined;
126
- }, {}, {}>;
127
- };
128
- dialect: "sqlite";
129
- }>;
130
- /** How long a scorecard row is kept before a maintenance sweep removes it. */
131
- export declare const SCORECARD_RETENTION_MS: number;
132
- /**
133
- * This plugin's `PluginStore` — the DDL half, handed to `new AgentDB(storage,
134
- * { stores })` by the host through `runtime.stores`.
135
- *
136
- * `version` bumps whenever {@link PluginStore.ensureTables} needs to do
137
- * something it did not do before; `from` is the version last recorded on disk,
138
- * so an upgrade path branches on it without re-running earlier DDL.
139
- */
140
- export declare const arcScorecardStore: PluginStore;
141
- /** Everything the scorecard policy needs, plus the sweep the ledger needs. */
142
- export interface ArcScorecardStore extends ScorecardStore {
143
- /** Delete cards older than {@link SCORECARD_RETENTION_MS}. */
144
- cleanup(): void;
145
- }
146
- /**
147
- * Query methods for `arc_scorecards`, over the plugin's **own** drizzle handle.
148
- *
149
- * durable-sqlite is synchronous, so these return plain values. The narrow
150
- * {@link ScorecardStore} port is what `resolveScorecard`/`resolvePlay` consume,
151
- * so a spec can pass an in-memory fake and never touch SQLite at all.
152
- */
153
- export declare function makeScorecardStore(storage: DurableObjectStorage): ArcScorecardStore;