@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.
- package/README.md +58 -77
- package/dist/browser/index.d.ts +0 -2
- package/dist/browser/index.js +21 -27
- package/dist/claude-code/cards.d.ts +53 -0
- package/dist/claude-code/cards.js +272 -0
- package/dist/claude-code/config.d.ts +28 -63
- package/dist/claude-code/config.js +0 -11
- package/dist/claude-code/egress.d.ts +8 -1
- package/dist/claude-code/egress.js +42 -4
- package/dist/claude-code/events.d.ts +106 -9
- package/dist/claude-code/events.js +201 -56
- package/dist/claude-code/github.d.ts +39 -0
- package/dist/claude-code/github.js +82 -0
- package/dist/claude-code/index.d.ts +16 -90
- package/dist/claude-code/index.js +14 -276
- package/dist/claude-code/model.d.ts +152 -0
- package/dist/claude-code/model.js +342 -0
- package/dist/claude-code/run.d.ts +209 -112
- package/dist/claude-code/run.js +339 -138
- package/dist/claude-code/session.d.ts +131 -0
- package/dist/claude-code/session.js +285 -0
- package/dist/claude-code/spec.d.ts +46 -0
- package/dist/claude-code/spec.js +83 -0
- package/dist/claude-code/verified.d.ts +15 -0
- package/dist/claude-code/verified.js +15 -0
- package/dist/computer/context.d.ts +1 -5
- package/dist/computer/context.js +7 -10
- package/dist/computer/file-lock.js +5 -4
- package/dist/computer/gate.d.ts +4 -4
- package/dist/computer/gate.js +5 -5
- package/dist/computer/index.d.ts +40 -258
- package/dist/computer/index.js +71 -324
- package/dist/computer/paths.d.ts +36 -16
- package/dist/computer/paths.js +42 -29
- package/dist/computer/proxy.d.ts +45 -0
- package/dist/computer/proxy.js +234 -0
- package/dist/computer/render.d.ts +1 -40
- package/dist/computer/render.js +2 -68
- package/dist/computer/tools-exec.js +12 -13
- package/dist/computer/tools-file.d.ts +9 -1
- package/dist/computer/tools-file.js +22 -82
- package/dist/computer/{tools-find.d.ts → tools-grep.d.ts} +1 -1
- package/dist/computer/tools-grep.js +129 -0
- package/dist/repo/checkout.d.ts +4 -5
- package/dist/repo/checkout.js +31 -8
- package/dist/repo/context.d.ts +35 -9
- package/dist/repo/context.js +101 -49
- package/dist/repo/index.d.ts +73 -28
- package/dist/repo/index.js +112 -96
- package/dist/repo/tools-checks.d.ts +3 -0
- package/dist/repo/tools-checks.js +112 -0
- package/dist/repo/tools-clone.js +1 -1
- package/dist/repo/tools-pr.d.ts +14 -0
- package/dist/repo/{tools-forge.js → tools-pr.js} +53 -36
- package/dist/repo/tools-review.d.ts +9 -0
- package/dist/repo/tools-review.js +67 -47
- package/dist/repo/tools-worktree.js +144 -60
- package/dist/repo/tools-worktrees.d.ts +12 -0
- package/dist/repo/tools-worktrees.js +48 -0
- package/dist/repo/url.d.ts +2 -2
- package/dist/repo/url.js +7 -7
- package/dist/scratch/index.d.ts +4 -4
- package/dist/scratch/index.js +12 -11
- package/dist/{computer → workspace}/advisory.d.ts +4 -4
- package/dist/{computer → workspace}/advisory.js +2 -2
- package/dist/{computer/host → workspace}/ca-trust.d.ts +8 -1
- package/dist/{computer/host → workspace}/ca-trust.js +12 -3
- package/dist/{computer/host → workspace}/container-fault.d.ts +3 -3
- package/dist/{computer/host → workspace}/container-fault.js +23 -8
- package/dist/workspace/exec.d.ts +94 -0
- package/dist/workspace/exec.js +153 -0
- package/dist/workspace/format.d.ts +36 -0
- package/dist/workspace/format.js +57 -0
- package/dist/{computer/host → workspace}/git-host.d.ts +21 -4
- package/dist/{computer/host → workspace}/git-host.js +72 -2
- package/dist/{computer/host → workspace}/git-identity.d.ts +1 -1
- package/dist/{computer/host → workspace}/git-identity.js +1 -1
- package/dist/workspace/index.d.ts +43 -47
- package/dist/workspace/index.js +52 -112
- package/dist/{computer/host → workspace}/install-job.d.ts +4 -4
- package/dist/{computer/host → workspace}/install-job.js +276 -176
- package/dist/{computer → workspace}/install.d.ts +8 -8
- package/dist/{computer → workspace}/install.js +3 -3
- package/dist/{computer/host/workspace.d.ts → workspace/object.d.ts} +105 -27
- package/dist/{computer/host/workspace.js → workspace/object.js} +217 -48
- package/dist/workspace/open.d.ts +95 -0
- package/dist/workspace/open.js +63 -0
- package/dist/workspace/read.d.ts +16 -0
- package/dist/workspace/read.js +22 -0
- package/dist/{computer → workspace}/shell.d.ts +5 -5
- package/dist/{computer → workspace}/shell.js +6 -6
- package/dist/{computer/host → workspace}/wake.d.ts +1 -1
- package/package.json +16 -36
- package/dist/arc-agi/analysis.d.ts +0 -322
- package/dist/arc-agi/analysis.js +0 -802
- package/dist/arc-agi/client.d.ts +0 -82
- package/dist/arc-agi/client.js +0 -113
- package/dist/arc-agi/game-tools.d.ts +0 -24
- package/dist/arc-agi/game-tools.js +0 -26
- package/dist/arc-agi/index.d.ts +0 -40
- package/dist/arc-agi/index.js +0 -175
- package/dist/arc-agi/main-agent.d.ts +0 -24
- package/dist/arc-agi/main-agent.js +0 -62
- package/dist/arc-agi/recipe.d.ts +0 -48
- package/dist/arc-agi/recipe.js +0 -97
- package/dist/arc-agi/scorecard.d.ts +0 -118
- package/dist/arc-agi/scorecard.js +0 -163
- package/dist/arc-agi/soul.d.ts +0 -29
- package/dist/arc-agi/soul.js +0 -79
- package/dist/arc-agi/store.d.ts +0 -153
- package/dist/arc-agi/store.js +0 -215
- package/dist/arc-agi/tools.d.ts +0 -36
- package/dist/arc-agi/tools.js +0 -574
- package/dist/arc-agi/types.d.ts +0 -211
- package/dist/arc-agi/types.js +0 -19
- package/dist/claude-code/recipe.d.ts +0 -53
- package/dist/claude-code/recipe.js +0 -100
- package/dist/computer/read.d.ts +0 -133
- package/dist/computer/read.js +0 -200
- package/dist/computer/tools-find.js +0 -216
- package/dist/recall/index.d.ts +0 -105
- package/dist/recall/index.js +0 -181
- package/dist/repo/tools-forge.d.ts +0 -4
- package/dist/triage/index.d.ts +0 -360
- package/dist/triage/index.js +0 -311
- /package/dist/{computer/host → workspace}/container-deps.d.ts +0 -0
- /package/dist/{computer/host → workspace}/container-deps.js +0 -0
- /package/dist/{computer/host → workspace}/sync.d.ts +0 -0
- /package/dist/{computer/host → workspace}/sync.js +0 -0
- /package/dist/{computer/host → workspace}/wake.js +0 -0
package/dist/arc-agi/client.d.ts
DELETED
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
import { type CookieJar, type FrameResponse, type GameInfo, type ScorecardSummary } from "./types.js";
|
|
2
|
-
/**
|
|
3
|
-
* Typed client for the ARC-AGI-3 REST API.
|
|
4
|
-
*
|
|
5
|
-
* Two Workers-specific concerns are handled explicitly, because `fetch` in a
|
|
6
|
-
* Worker manages neither:
|
|
7
|
-
*
|
|
8
|
-
* - **Session affinity**: the API pins a game session to a load-balancer via
|
|
9
|
-
* `AWSALB*` cookies returned on RESET/ACTION responses; they MUST be echoed on
|
|
10
|
-
* every subsequent request. The jar is passed in and returned as plain data
|
|
11
|
-
* (not a stateful client), so it checkpoints into the workspace and survives
|
|
12
|
-
* isolate eviction between chunks.
|
|
13
|
-
* - **Rate limiting**: 600 RPM → 429; we honor `Retry-After` with bounded
|
|
14
|
-
* exponential backoff. Exhausted retries and 5xx throw (transient — the
|
|
15
|
-
* Workflow step retries and the runner resumes from its checkpoint); a 401
|
|
16
|
-
* throws a tagged deterministic error (bad key — a terminal failure).
|
|
17
|
-
* - **Cancellation**: a client built with a `signal` stops at it — the `fetch` and
|
|
18
|
-
* the backoff between retries alike. `Retry-After` is honoured up to
|
|
19
|
-
* {@link MAX_RETRY_AFTER_MS} and no further: the header is the server's to set,
|
|
20
|
-
* and an uncapped one parks a tool for as long as the server likes.
|
|
21
|
-
*/
|
|
22
|
-
export interface ArcClient {
|
|
23
|
-
listGames(cookies: CookieJar): Promise<{
|
|
24
|
-
games: GameInfo[];
|
|
25
|
-
cookies: CookieJar;
|
|
26
|
-
}>;
|
|
27
|
-
openScorecard(cookies: CookieJar): Promise<{
|
|
28
|
-
cardId: string;
|
|
29
|
-
cookies: CookieJar;
|
|
30
|
-
}>;
|
|
31
|
-
/**
|
|
32
|
-
* The whole card, with one `environments` entry per game played on it.
|
|
33
|
-
* Readable while the card is still open, which is what lets a result be
|
|
34
|
-
* reported without anything closing a card.
|
|
35
|
-
*/
|
|
36
|
-
getScorecard(cardId: string, cookies: CookieJar): Promise<{
|
|
37
|
-
summary: ScorecardSummary;
|
|
38
|
-
cookies: CookieJar;
|
|
39
|
-
}>;
|
|
40
|
-
reset(input: {
|
|
41
|
-
gameId: string;
|
|
42
|
-
cardId: string;
|
|
43
|
-
guid?: string;
|
|
44
|
-
}, cookies: CookieJar): Promise<{
|
|
45
|
-
frame: FrameResponse;
|
|
46
|
-
cookies: CookieJar;
|
|
47
|
-
}>;
|
|
48
|
-
act(input: {
|
|
49
|
-
action: number;
|
|
50
|
-
gameId: string;
|
|
51
|
-
guid: string;
|
|
52
|
-
x?: number;
|
|
53
|
-
y?: number;
|
|
54
|
-
note?: string;
|
|
55
|
-
}, cookies: CookieJar): Promise<{
|
|
56
|
-
frame: FrameResponse;
|
|
57
|
-
cookies: CookieJar;
|
|
58
|
-
}>;
|
|
59
|
-
}
|
|
60
|
-
/**
|
|
61
|
-
* The longest a `Retry-After` is waited out. A minute covers the API's own
|
|
62
|
-
* per-minute rate window; past that the header is either hostile or describing an
|
|
63
|
-
* outage, and a retry loop is the wrong place to sit through either.
|
|
64
|
-
*/
|
|
65
|
-
export declare const MAX_RETRY_AFTER_MS = 60000;
|
|
66
|
-
/** Message prefix of the deterministic (non-retryable) auth error. */
|
|
67
|
-
export declare const ARC_AUTH_ERROR = "arc-client: unauthorized";
|
|
68
|
-
export interface ArcClientOptions {
|
|
69
|
-
fetchFn?: typeof fetch;
|
|
70
|
-
/** Injected for tests; defaults to a real timed sleep. */
|
|
71
|
-
sleep?: (ms: number) => Promise<void>;
|
|
72
|
-
/** Max attempts per request before a 429/5xx becomes a thrown transient fault. */
|
|
73
|
-
maxAttempts?: number;
|
|
74
|
-
/**
|
|
75
|
-
* Stops every request this client makes, and every wait between them. Taken at
|
|
76
|
-
* construction, so a client lives no longer than the signal it stops on: a tool
|
|
77
|
-
* builds one per call, from that call's signal — see
|
|
78
|
-
* {@link file://./tools.ts buildArcGameTools}.
|
|
79
|
-
*/
|
|
80
|
-
signal?: AbortSignal;
|
|
81
|
-
}
|
|
82
|
-
export declare function makeArcClient(apiKey: string, options?: ArcClientOptions): ArcClient;
|
package/dist/arc-agi/client.js
DELETED
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
import { withAbort } from "@dynamicagents/core";
|
|
2
|
-
import { ARC_BASE_URL } from "./types.js";
|
|
3
|
-
/**
|
|
4
|
-
* The longest a `Retry-After` is waited out. A minute covers the API's own
|
|
5
|
-
* per-minute rate window; past that the header is either hostile or describing an
|
|
6
|
-
* outage, and a retry loop is the wrong place to sit through either.
|
|
7
|
-
*/
|
|
8
|
-
export const MAX_RETRY_AFTER_MS = 60_000;
|
|
9
|
-
/** Message prefix of the deterministic (non-retryable) auth error. */
|
|
10
|
-
export const ARC_AUTH_ERROR = "arc-client: unauthorized";
|
|
11
|
-
const realSleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
12
|
-
/** Merge `set-cookie` headers from a response into the jar (name=value pairs). */
|
|
13
|
-
function mergeCookies(jar, res) {
|
|
14
|
-
const next = { ...jar };
|
|
15
|
-
for (const raw of res.headers.getSetCookie()) {
|
|
16
|
-
const pair = raw.split(";", 1)[0];
|
|
17
|
-
const eq = pair.indexOf("=");
|
|
18
|
-
if (eq <= 0)
|
|
19
|
-
continue;
|
|
20
|
-
next[pair.slice(0, eq).trim()] = pair.slice(eq + 1).trim();
|
|
21
|
-
}
|
|
22
|
-
return next;
|
|
23
|
-
}
|
|
24
|
-
/** Serialize the jar to a `Cookie` request header, or undefined when empty. */
|
|
25
|
-
function cookieHeader(jar) {
|
|
26
|
-
const parts = Object.entries(jar).map(([k, v]) => `${k}=${v}`);
|
|
27
|
-
return parts.length === 0 ? undefined : parts.join("; ");
|
|
28
|
-
}
|
|
29
|
-
export function makeArcClient(apiKey, options = {}) {
|
|
30
|
-
const doFetch = options.fetchFn ?? fetch;
|
|
31
|
-
const sleep = options.sleep ?? realSleep;
|
|
32
|
-
const maxAttempts = options.maxAttempts ?? 4;
|
|
33
|
-
const signal = options.signal;
|
|
34
|
-
async function request(path, init, cookies) {
|
|
35
|
-
const headers = {
|
|
36
|
-
"X-API-Key": apiKey,
|
|
37
|
-
accept: "application/json"
|
|
38
|
-
};
|
|
39
|
-
if (init.body !== undefined)
|
|
40
|
-
headers["content-type"] = "application/json";
|
|
41
|
-
const cookie = cookieHeader(cookies);
|
|
42
|
-
if (cookie)
|
|
43
|
-
headers["cookie"] = cookie;
|
|
44
|
-
let attempt = 0;
|
|
45
|
-
for (;;) {
|
|
46
|
-
attempt++;
|
|
47
|
-
const res = await doFetch(`${ARC_BASE_URL}${path}`, {
|
|
48
|
-
method: init.method,
|
|
49
|
-
headers,
|
|
50
|
-
body: init.body === undefined ? undefined : JSON.stringify(init.body),
|
|
51
|
-
...(signal ? { signal } : {})
|
|
52
|
-
});
|
|
53
|
-
if (res.ok) {
|
|
54
|
-
const nextCookies = mergeCookies(cookies, res);
|
|
55
|
-
const data = (await res.json());
|
|
56
|
-
return { data, cookies: nextCookies };
|
|
57
|
-
}
|
|
58
|
-
if (res.status === 401 || res.status === 403) {
|
|
59
|
-
throw new Error(`${ARC_AUTH_ERROR} (HTTP ${res.status})`);
|
|
60
|
-
}
|
|
61
|
-
// 429 / 5xx: retry with backoff, honoring Retry-After when present.
|
|
62
|
-
const retryable = res.status === 429 || res.status >= 500;
|
|
63
|
-
if (!retryable || attempt >= maxAttempts) {
|
|
64
|
-
throw new Error(`arc-client: ${init.method} ${path} failed (HTTP ${res.status})`);
|
|
65
|
-
}
|
|
66
|
-
const retryAfter = Number(res.headers.get("retry-after"));
|
|
67
|
-
const backoffMs = Number.isFinite(retryAfter) && retryAfter > 0
|
|
68
|
-
? Math.min(retryAfter * 1000, MAX_RETRY_AFTER_MS)
|
|
69
|
-
: Math.min(1000 * 2 ** (attempt - 1), 8000);
|
|
70
|
-
// The wait between attempts is the longest thing this loop does, so it is
|
|
71
|
-
// the part a cancel most needs to reach.
|
|
72
|
-
await withAbort(signal, sleep(backoffMs));
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
return {
|
|
76
|
-
async listGames(cookies) {
|
|
77
|
-
const { data, cookies: next } = await request("/api/games", { method: "GET" }, cookies);
|
|
78
|
-
return { games: data, cookies: next };
|
|
79
|
-
},
|
|
80
|
-
async openScorecard(cookies) {
|
|
81
|
-
const { data, cookies: next } = await request("/api/scorecard/open", { method: "POST", body: {} }, cookies);
|
|
82
|
-
return { cardId: data.card_id, cookies: next };
|
|
83
|
-
},
|
|
84
|
-
async getScorecard(cardId, cookies) {
|
|
85
|
-
const { data, cookies: next } = await request(`/api/scorecard/${encodeURIComponent(cardId)}`, { method: "GET" }, cookies);
|
|
86
|
-
return { summary: data, cookies: next };
|
|
87
|
-
},
|
|
88
|
-
async reset(input, cookies) {
|
|
89
|
-
const body = {
|
|
90
|
-
game_id: input.gameId,
|
|
91
|
-
card_id: input.cardId
|
|
92
|
-
};
|
|
93
|
-
if (input.guid !== undefined)
|
|
94
|
-
body.guid = input.guid;
|
|
95
|
-
const { data, cookies: next } = await request("/api/cmd/RESET", { method: "POST", body }, cookies);
|
|
96
|
-
return { frame: data, cookies: next };
|
|
97
|
-
},
|
|
98
|
-
async act(input, cookies) {
|
|
99
|
-
const body = {
|
|
100
|
-
game_id: input.gameId,
|
|
101
|
-
guid: input.guid
|
|
102
|
-
};
|
|
103
|
-
if (input.action === 6) {
|
|
104
|
-
body.x = input.x;
|
|
105
|
-
body.y = input.y;
|
|
106
|
-
}
|
|
107
|
-
if (input.note !== undefined)
|
|
108
|
-
body.reasoning = { text: input.note };
|
|
109
|
-
const { data, cookies: next } = await request(`/api/cmd/ACTION${input.action}`, { method: "POST", body }, cookies);
|
|
110
|
-
return { frame: data, cookies: next };
|
|
111
|
-
}
|
|
112
|
-
};
|
|
113
|
-
}
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { type ToolSet } from "ai";
|
|
2
|
-
import type { ArcClient } from "./client.js";
|
|
3
|
-
/**
|
|
4
|
-
* The **main agent's** ARC tool: the game catalogue, and nothing else.
|
|
5
|
-
*
|
|
6
|
-
* **No scorecard lifecycle here.** The API retires an idle card itself, so a
|
|
7
|
-
* card opened, named and closed by the model is a lifecycle modelled twice with
|
|
8
|
-
* every play depending on the model's bookkeeping. The card is leased by the
|
|
9
|
-
* recipe (see {@link file://./scorecard.ts}) and never named here, so the only
|
|
10
|
-
* thing the main agent needs from ARC is the exact game id to delegate with.
|
|
11
|
-
*
|
|
12
|
-
* Handlers are exported separately from the `tool()` wiring so they unit-test
|
|
13
|
-
* without an LLM, and the client is closed over so it is never model input.
|
|
14
|
-
*/
|
|
15
|
-
export interface ArcGamesDeps {
|
|
16
|
-
client: ArcClient;
|
|
17
|
-
}
|
|
18
|
-
/** One line per game: id, title, and how it is played. */
|
|
19
|
-
export declare function renderGames(games: {
|
|
20
|
-
game_id: string;
|
|
21
|
-
title?: string;
|
|
22
|
-
tags?: string[];
|
|
23
|
-
}[]): string;
|
|
24
|
-
export declare function buildArcGamesTools(deps: ArcGamesDeps): ToolSet;
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { tool } from "ai";
|
|
2
|
-
import { z } from "zod";
|
|
3
|
-
/** One line per game: id, title, and how it is played. */
|
|
4
|
-
export function renderGames(games) {
|
|
5
|
-
if (games.length === 0)
|
|
6
|
-
return "(the API listed no games)";
|
|
7
|
-
return games
|
|
8
|
-
.map((g) => {
|
|
9
|
-
const title = g.title ? ` (${g.title})` : "";
|
|
10
|
-
const tags = g.tags?.length ? ` [${g.tags.join(", ")}]` : "";
|
|
11
|
-
return `- ${g.game_id}${title}${tags}`;
|
|
12
|
-
})
|
|
13
|
-
.join("\n");
|
|
14
|
-
}
|
|
15
|
-
export function buildArcGamesTools(deps) {
|
|
16
|
-
return {
|
|
17
|
-
arc_list_games: tool({
|
|
18
|
-
description: "List the ARC-AGI-3 games available to play, with their exact game ids and tags describing how each is played. Use this to find the full game id before delegating a play.",
|
|
19
|
-
inputSchema: z.object({}),
|
|
20
|
-
execute: async () => {
|
|
21
|
-
const { games } = await deps.client.listGames({});
|
|
22
|
-
return renderGames(games);
|
|
23
|
-
}
|
|
24
|
-
})
|
|
25
|
-
};
|
|
26
|
-
}
|
package/dist/arc-agi/index.d.ts
DELETED
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import type { AgentPlugin } from "@dynamicagents/core";
|
|
2
|
-
import { ARC_GAME_TYPE } from "./recipe.js";
|
|
3
|
-
import { type ScorecardStore } from "./scorecard.js";
|
|
4
|
-
import { ARC_GAME_FAMILY } from "./tools.js";
|
|
5
|
-
import type { ArcRuntime } from "./types.js";
|
|
6
|
-
/**
|
|
7
|
-
* `@dynamicagents/plugins/arc-agi` — play ARC-AGI-3 games.
|
|
8
|
-
*
|
|
9
|
-
* The stress test for the whole plugin contract, and the reason `resolveRuntime`,
|
|
10
|
-
* the lease hooks and `enrichResult` exist on it: every one of them is a piece of
|
|
11
|
-
* ARC-specific policy that would otherwise sit in an agent's Durable Object,
|
|
12
|
-
* which has no other reason to know what a scorecard is.
|
|
13
|
-
*
|
|
14
|
-
* The line that keeps it honest: the *only* thing the agent knows is that it
|
|
15
|
-
* installed a plugin. Nothing in a loop, a workflow, or a DO names a card, a
|
|
16
|
-
* guid, or a game.
|
|
17
|
-
*/
|
|
18
|
-
/** Everything this plugin needs from its host. */
|
|
19
|
-
export interface ArcAgiConfig {
|
|
20
|
-
/** `ARC_API_KEY` — a secret the host must set. */
|
|
21
|
-
apiKey: string;
|
|
22
|
-
/**
|
|
23
|
-
* The Durable Object's storage, for the `arc_scorecards` ledger.
|
|
24
|
-
*
|
|
25
|
-
* `DurableObjectStorage` rather than the `SqlStorage` that `ensureTables`
|
|
26
|
-
* receives, because the query side builds a drizzle handle over it. The host
|
|
27
|
-
* has it as `this.ctx.storage`.
|
|
28
|
-
*/
|
|
29
|
-
storage: DurableObjectStorage;
|
|
30
|
-
/**
|
|
31
|
-
* Test override: an in-memory {@link ScorecardStore}. Supplying this skips the
|
|
32
|
-
* table entirely, which is what lets the policy specs run with no SQLite.
|
|
33
|
-
*/
|
|
34
|
-
store?: ScorecardStore;
|
|
35
|
-
}
|
|
36
|
-
export declare function arcAgi(config: ArcAgiConfig): AgentPlugin<ArcRuntime>;
|
|
37
|
-
export { ARC_GAME_FAMILY, ARC_GAME_TYPE };
|
|
38
|
-
export type { ArcRuntime, ScorecardStore };
|
|
39
|
-
export { arcScorecardStore, makeScorecardStore } from "./store.js";
|
|
40
|
-
export { ARC_GAME_RECIPE, ARC_GAME_SPEC } from "./recipe.js";
|
package/dist/arc-agi/index.js
DELETED
|
@@ -1,175 +0,0 @@
|
|
|
1
|
-
import { definePlugin } from "@dynamicagents/core";
|
|
2
|
-
import { makeArcClient } from "./client.js";
|
|
3
|
-
import { buildArcGamesTools } from "./game-tools.js";
|
|
4
|
-
import { ARC_GAME_SPEC, ARC_GAME_TYPE } from "./recipe.js";
|
|
5
|
-
import { gameScoreReport, resolvePlayOn, resolveScorecard } from "./scorecard.js";
|
|
6
|
-
import { arcScorecardStore, makeScorecardStore } from "./store.js";
|
|
7
|
-
import { ARC_GAME_FAMILY, buildArcGameTools } from "./tools.js";
|
|
8
|
-
export function arcAgi(config) {
|
|
9
|
-
const { apiKey, storage } = config;
|
|
10
|
-
// Built once per DO instance, like the plugin itself. `makeScorecardStore`
|
|
11
|
-
// only constructs a drizzle handle — it issues no query until something asks —
|
|
12
|
-
// so this is safe before `AgentDB` has run the store's DDL.
|
|
13
|
-
let store = config.store;
|
|
14
|
-
const deps = () => ({
|
|
15
|
-
store: (store ??= makeScorecardStore(storage)),
|
|
16
|
-
client: makeArcClient(apiKey)
|
|
17
|
-
});
|
|
18
|
-
/**
|
|
19
|
-
* In-flight leases, collapsed so concurrent branches share one call.
|
|
20
|
-
*
|
|
21
|
-
* The plugin is built once per DO instance, so this closure is per-instance
|
|
22
|
-
* scope — held by the thing that cares about a card rather than by the agent
|
|
23
|
-
* that merely hosts it.
|
|
24
|
-
*
|
|
25
|
-
* Load-bearing, not an optimization. All of a round's ready Subtasks execute
|
|
26
|
-
* concurrently, and opening a card is a `fetch`, which opens the DO's input
|
|
27
|
-
* gate — so without this, two branches starting together each find no live
|
|
28
|
-
* card and each open one. It matters more for a play: RESET is also a `fetch`,
|
|
29
|
-
* so two Subtasks for one game would each find no recorded guid and each open
|
|
30
|
-
* a play. The store settles that race anyway (first guid written wins), but
|
|
31
|
-
* only after a wasted run is already recorded on the card, so collapsing is
|
|
32
|
-
* what keeps the card's history honest rather than merely cheap.
|
|
33
|
-
*/
|
|
34
|
-
let leasingCard;
|
|
35
|
-
const leasingPlays = new Map();
|
|
36
|
-
/**
|
|
37
|
-
* The card each execution *first* resolved onto, so a later chunk's lease can
|
|
38
|
-
* be recognised as a different one. See {@link ArcAgiConfig} and the note on
|
|
39
|
-
* `enrichResult`.
|
|
40
|
-
*
|
|
41
|
-
* In memory, and that is the honest limit: an isolate evicted between the
|
|
42
|
-
* final chunk and the result loses the entry and simply cannot tell. That is
|
|
43
|
-
* no worse than not tracking at all, and the common case — the parent
|
|
44
|
-
* resolving the last chunk and then handling its result — keeps it warm.
|
|
45
|
-
*/
|
|
46
|
-
const firstCard = new Map();
|
|
47
|
-
const executionKey = (taskId, subtaskId) => `${taskId}:${subtaskId}`;
|
|
48
|
-
const leaseScorecard = () => (leasingCard ??= resolveScorecard(deps()).finally(() => {
|
|
49
|
-
leasingCard = undefined;
|
|
50
|
-
}));
|
|
51
|
-
const leasePlay = (gameId) => {
|
|
52
|
-
const inFlight = leasingPlays.get(gameId);
|
|
53
|
-
if (inFlight)
|
|
54
|
-
return inFlight;
|
|
55
|
-
// Keyed per game: different games legitimately open different plays on the
|
|
56
|
-
// same card — but they must all be on *the same card*, so the play resolves
|
|
57
|
-
// onto the collapsed lease rather than looking one up for itself. Calling
|
|
58
|
-
// `resolvePlay` here instead would re-enter `resolveScorecard` per game and
|
|
59
|
-
// undo the collapse entirely: two games starting together would each find
|
|
60
|
-
// an empty ledger and each open a card.
|
|
61
|
-
const pending = leaseScorecard()
|
|
62
|
-
.then((card) => resolvePlayOn(deps(), card, gameId))
|
|
63
|
-
.finally(() => {
|
|
64
|
-
leasingPlays.delete(gameId);
|
|
65
|
-
});
|
|
66
|
-
leasingPlays.set(gameId, pending);
|
|
67
|
-
return pending;
|
|
68
|
-
};
|
|
69
|
-
return definePlugin({
|
|
70
|
-
key: "arc-agi",
|
|
71
|
-
subtaskType: ARC_GAME_SPEC,
|
|
72
|
-
toolFamilies: {
|
|
73
|
-
[ARC_GAME_FAMILY]: (ctx) => buildArcGameTools(apiKey, ctx)
|
|
74
|
-
},
|
|
75
|
-
/**
|
|
76
|
-
* The **game catalogue only**. Playing is a subagent's job, and the card it
|
|
77
|
-
* plays on is leased below and never reaches a model — so the only thing the
|
|
78
|
-
* main agent needs from ARC is the exact id to delegate a play with.
|
|
79
|
-
*/
|
|
80
|
-
mainAgentTools: () => buildArcGamesTools({ client: makeArcClient(apiKey) }),
|
|
81
|
-
// No `capability` here: it is on the subtask type, with the delegation
|
|
82
|
-
// guidance it has to agree with. See `ARC_GAME_SPEC`.
|
|
83
|
-
/**
|
|
84
|
-
* Resolve the session state an execution needs and no model can supply: the
|
|
85
|
-
* card, and the play on it.
|
|
86
|
-
*
|
|
87
|
-
* Neither is a decision. Which card is live is a fact about the clock, and a
|
|
88
|
-
* guid is mintable only by RESET — a call a subagent must never make, since a
|
|
89
|
-
* second RESET is a second run on the card that discards whatever the first
|
|
90
|
-
* reached. Both are settled here and handed down.
|
|
91
|
-
*
|
|
92
|
-
* Called once per **chunk**, not once per run, and the repetition is
|
|
93
|
-
* load-bearing twice over: each call restarts the card's reuse clock (which
|
|
94
|
-
* keeps a long play's card alive), and each call re-resolves the same guid
|
|
95
|
-
* from the store rather than opening anything.
|
|
96
|
-
*/
|
|
97
|
-
async resolveRuntime(ctx) {
|
|
98
|
-
const gameId = ctx.params.game_id;
|
|
99
|
-
// A Subtask whose params never validated still reaches here. Resolve the
|
|
100
|
-
// card alone and let the recipe's own validation report the missing game,
|
|
101
|
-
// rather than RESETting on it and turning a clean failure into an API error.
|
|
102
|
-
const resolved = gameId
|
|
103
|
-
? await leasePlay(gameId)
|
|
104
|
-
: await leaseScorecard();
|
|
105
|
-
// Remember the first card only. A later chunk that lands on a different
|
|
106
|
-
// one has rolled over, and the play it names is not the play running.
|
|
107
|
-
const key = executionKey(ctx.taskId, ctx.subtaskId);
|
|
108
|
-
if (!firstCard.has(key))
|
|
109
|
-
firstCard.set(key, resolved.cardId);
|
|
110
|
-
return resolved;
|
|
111
|
-
},
|
|
112
|
-
/**
|
|
113
|
-
* Append what only the parent can know to a completed execution's report:
|
|
114
|
-
* the score.
|
|
115
|
-
*
|
|
116
|
-
* Nothing closes a scorecard any more, so the score is *read* from the card
|
|
117
|
-
* once the play that earned it is done — which only this side can do, since
|
|
118
|
-
* it alone knows the leased card and holds the jar pinned to it. The score
|
|
119
|
-
* lands as an extra text part, and result parts are joined on delivery, so it
|
|
120
|
-
* reaches the user and any dependent Subtask with no other change.
|
|
121
|
-
*
|
|
122
|
-
* Never fails the execution: a play that succeeded is not retroactively
|
|
123
|
-
* broken by a rate-limited score read, so `gameScoreReport` swallows its own
|
|
124
|
-
* errors and a null leaves the report as the child wrote it. Safe to repeat
|
|
125
|
-
* on a Workflow step replay — the read is a GET.
|
|
126
|
-
*/
|
|
127
|
-
async enrichResult(ctx, result) {
|
|
128
|
-
const gameId = ctx.request.params.game_id;
|
|
129
|
-
const cardId = ctx.runtime.cardId;
|
|
130
|
-
const key = executionKey(ctx.request.taskId, ctx.request.subtaskId);
|
|
131
|
-
const opened = firstCard.get(key);
|
|
132
|
-
firstCard.delete(key);
|
|
133
|
-
if (result.status !== "completed" || !cardId || !gameId)
|
|
134
|
-
return result;
|
|
135
|
-
// A rollover means this runtime names a card the play never ran on, so
|
|
136
|
-
// its score belongs to something else. The tool family keeps playing the
|
|
137
|
-
// session it already has when the lease diverges — deliberately, because
|
|
138
|
-
// joining the new play would throw away every level the real one reached
|
|
139
|
-
// — so the report is right and only the score would be wrong.
|
|
140
|
-
//
|
|
141
|
-
// Nothing here can recover the real one: the parent cannot read the
|
|
142
|
-
// child's workspace, which is the only place the play it actually ran is
|
|
143
|
-
// recorded. And a rollover means over 14 minutes passed between two
|
|
144
|
-
// chunks, so the old card is idle-closed and unreachable anyway. What is
|
|
145
|
-
// fixable is the lie — an empty RESET on the fresh card renders as a
|
|
146
|
-
// perfectly plausible "score 0, 0 levels", which reads as a play that
|
|
147
|
-
// achieved nothing rather than as a score that could not be read. Omit it
|
|
148
|
-
// instead; the main agent is told to report an absent score as
|
|
149
|
-
// unavailable.
|
|
150
|
-
if (opened !== undefined && opened !== cardId) {
|
|
151
|
-
console.warn("[arc-agi] scorecard rolled over mid-execution", {
|
|
152
|
-
gameId,
|
|
153
|
-
played: opened,
|
|
154
|
-
leased: cardId
|
|
155
|
-
});
|
|
156
|
-
return result;
|
|
157
|
-
}
|
|
158
|
-
const score = await gameScoreReport(deps(), cardId, gameId);
|
|
159
|
-
if (!score)
|
|
160
|
-
return result;
|
|
161
|
-
return {
|
|
162
|
-
...result,
|
|
163
|
-
resultParts: [...result.resultParts, { kind: "text", text: score }]
|
|
164
|
-
};
|
|
165
|
-
},
|
|
166
|
-
// No `onAbort`. There is deliberately nothing to release: the ARC API
|
|
167
|
-
// auto-closes an idle card, so an abandoned play needs no cleanup at all.
|
|
168
|
-
// Declaring an empty hook would imply otherwise.
|
|
169
|
-
store: arcScorecardStore,
|
|
170
|
-
requires: { secrets: ["ARC_API_KEY"] }
|
|
171
|
-
});
|
|
172
|
-
}
|
|
173
|
-
export { ARC_GAME_FAMILY, ARC_GAME_TYPE };
|
|
174
|
-
export { arcScorecardStore, makeScorecardStore } from "./store.js";
|
|
175
|
-
export { ARC_GAME_RECIPE, ARC_GAME_SPEC } from "./recipe.js";
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import type { DelegationNames } from "@dynamicagents/core";
|
|
2
|
-
/**
|
|
3
|
-
* Everything the **main agent** is told about ARC-AGI-3 — the counterpart to
|
|
4
|
-
* {@link file://./soul.ts}, which is what the *subagent* playing a game is told.
|
|
5
|
-
*
|
|
6
|
-
* **The capability block and the delegation guidance stay in this one file.** A
|
|
7
|
-
* main agent's system prompt is soul plus round contract concatenated, so split
|
|
8
|
-
* across two files they are two statements of the same advice with no reason to
|
|
9
|
-
* agree — and the way they disagree is one telling the model to delegate a
|
|
10
|
-
* subtask per game while the other allows exactly one.
|
|
11
|
-
*/
|
|
12
|
-
/**
|
|
13
|
-
* The capability block: what the agent can do, and what to do with a result that
|
|
14
|
-
* comes back. Deliberately names no scorecard tool and no `card_id` — the card is
|
|
15
|
-
* leased by the recipe per chunk and is not this model's to manage, so naming one
|
|
16
|
-
* would only invite a call to a tool that does not exist.
|
|
17
|
-
*/
|
|
18
|
-
export declare const ARC_CAPABILITY: string;
|
|
19
|
-
/**
|
|
20
|
-
* The delegation guidance: how to build the `delegate` payload for a play. What
|
|
21
|
-
* the capability block already says is not repeated here, and neither is the
|
|
22
|
-
* params schema — the `delegate` tool description renders that from the type.
|
|
23
|
-
*/
|
|
24
|
-
export declare function arcDelegationGuidance(names: DelegationNames): string;
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Everything the **main agent** is told about ARC-AGI-3 — the counterpart to
|
|
3
|
-
* {@link file://./soul.ts}, which is what the *subagent* playing a game is told.
|
|
4
|
-
*
|
|
5
|
-
* **The capability block and the delegation guidance stay in this one file.** A
|
|
6
|
-
* main agent's system prompt is soul plus round contract concatenated, so split
|
|
7
|
-
* across two files they are two statements of the same advice with no reason to
|
|
8
|
-
* agree — and the way they disagree is one telling the model to delegate a
|
|
9
|
-
* subtask per game while the other allows exactly one.
|
|
10
|
-
*/
|
|
11
|
-
/**
|
|
12
|
-
* The capability block: what the agent can do, and what to do with a result that
|
|
13
|
-
* comes back. Deliberately names no scorecard tool and no `card_id` — the card is
|
|
14
|
-
* leased by the recipe per chunk and is not this model's to manage, so naming one
|
|
15
|
-
* would only invite a call to a tool that does not exist.
|
|
16
|
-
*/
|
|
17
|
-
export const ARC_CAPABILITY = [
|
|
18
|
-
"You can run ARC-AGI-3 games, played for you by subagents:",
|
|
19
|
-
"- `arc_list_games` shows the available games with their exact ids and tags describing how each is played.",
|
|
20
|
-
"- To have a game played, delegate a subtask of type `arc-game` with param `game_id` (an exact id from `arc_list_games`). That is the whole contract — there is no scorecard for you to open, choose, or close.",
|
|
21
|
-
"- To have several games played, delegate one `arc-game` subtask per game; they run concurrently.",
|
|
22
|
-
"- Each play's report ends with that game's score, read from the scorecard once the play finishes. Report that score rather than inventing one — and if a report carries no score line, say the score was unavailable.",
|
|
23
|
-
"- A play's report also carries what it learned: the mechanics it confirmed, what it never got to test, and where the level's pieces are. That is the only record of it — the subagent keeps nothing between plays. Record what generalizes (mechanics, geography, what failed and why) so the next play starts from it, and keep it separate from what is merely suspected. Spent scorecard ids and other one-off residue are not worth keeping."
|
|
24
|
-
].join("\n");
|
|
25
|
-
/**
|
|
26
|
-
* The delegation guidance: how to build the `delegate` payload for a play. What
|
|
27
|
-
* the capability block already says is not repeated here, and neither is the
|
|
28
|
-
* params schema — the `delegate` tool description renders that from the type.
|
|
29
|
-
*/
|
|
30
|
-
export function arcDelegationGuidance(names) {
|
|
31
|
-
return `## Playing an ARC-AGI-3 game
|
|
32
|
-
|
|
33
|
-
When the user asks for a game to be played (e.g. "play game ls20"), you can
|
|
34
|
-
delegate in parallel subtasks of "type": "arc-game" per game they named.
|
|
35
|
-
|
|
36
|
-
Each of those subtasks carries "params": { "game_id": "<id>" }, an exact id from
|
|
37
|
-
\`arc_list_games\`. The param is what starts the play, and the "prompt" is never a
|
|
38
|
-
substitute for it. Restate the request in the "prompt" as well (e.g. "Play the
|
|
39
|
-
ARC-AGI-3 game ls20."), so the subagent knows what it was asked for.
|
|
40
|
-
|
|
41
|
-
If the request does not name a game, or names it loosely — call \`arc_list_games\`
|
|
42
|
-
first and delegate the id associated with "ls20". Never invent an id or pass through
|
|
43
|
-
the user's wording as one. If nothing in the list matches well enough to choose,
|
|
44
|
-
ask the user which game they mean with \`${names.finalReplyTool}\` rather than guessing.
|
|
45
|
-
|
|
46
|
-
### What to put in the prompt
|
|
47
|
-
|
|
48
|
-
Give it the goal, and give it what earlier plays actually established — labeled as
|
|
49
|
-
what it is. Write "an earlier play observed …" for something a play reported seeing,
|
|
50
|
-
and "we suspect …" for a hypothesis, so it can tell what to verify from what to use.
|
|
51
|
-
A route or a map you pass down is a guess about a level nobody has finished; stated
|
|
52
|
-
as fact, it gets followed off a cliff.
|
|
53
|
-
|
|
54
|
-
Do **not** state mechanics of the tools or the budget: how many actions it has, how
|
|
55
|
-
many moves fit in one call, how many turns it may spend. It is told all of that
|
|
56
|
-
directly, it is told correctly, and a number you supply that disagrees will be
|
|
57
|
-
believed over the truth — a play once stopped early because its prompt said it had
|
|
58
|
-
"20 actions total" when 20 was its turn budget.
|
|
59
|
-
|
|
60
|
-
These subtasks take several minutes — acknowledge in your "reply" that you have started playing
|
|
61
|
-
and will report back, without promising a time.`;
|
|
62
|
-
}
|
package/dist/arc-agi/recipe.d.ts
DELETED
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
import type { ResolvedRecipe, SubtaskTypeSpec } from "@dynamicagents/core";
|
|
2
|
-
/** Semantic Subtask type the decomposer emits for a "play this game" request. */
|
|
3
|
-
export declare const ARC_GAME_TYPE = "arc-game";
|
|
4
|
-
/**
|
|
5
|
-
* Recipe for playing an ARC-AGI-3 game. Names no model, so it runs on whatever
|
|
6
|
-
* pair its host agent is configured with; what distinguishes it is its tool
|
|
7
|
-
* family, its soul, its context discipline, and
|
|
8
|
-
* a turn budget twice the baseline — a play is a long sequence of cheap decisions,
|
|
9
|
-
* and 20 turns bought roughly ten game actions once inspection was paid for.
|
|
10
|
-
*
|
|
11
|
-
* **Budget the turns, never the chunks.** A turn here is a reasoning model plus
|
|
12
|
-
* an ARC HTTP round trip, nothing like the sub-ten-second turn a chunk count is
|
|
13
|
-
* implicitly sized against: 1,000 turns sliced 25 to a chunk is 40 chunks on
|
|
14
|
-
* paper and 70-100 in a real run, which blows the per-branch cap and *fails* a
|
|
15
|
-
* play after hours rather than asking it to report. Time and turns are both
|
|
16
|
-
* enforced directly, and a play ends through the graceful summary — a terminal
|
|
17
|
-
* report with the metrics footer.
|
|
18
|
-
*
|
|
19
|
-
* - `historyWindow` bounds context, and it is the model's *only* memory: with no
|
|
20
|
-
* workspace tools (see below) a plan that scrolls out of it is gone. Note it
|
|
21
|
-
* counts *assistant messages* — one per tool call, not one per game action —
|
|
22
|
-
* so a play spends it several times faster than the number suggests.
|
|
23
|
-
* - `reportMetrics` appends the turns/model-calls/wall-clock footer the user
|
|
24
|
-
* asked to see.
|
|
25
|
-
*
|
|
26
|
-
* Tool family: `arc-game` alone (act/inspect against the ARC REST API, session
|
|
27
|
-
* state kept in the workspace), code-validated by
|
|
28
|
-
* `validateRecipe`/`buildRecipeTools`.
|
|
29
|
-
*
|
|
30
|
-
* **No `workspace` family, despite the small history window.** Across two logged
|
|
31
|
-
* plays `ws_read` was never called and the three `ws_write` calls were a
|
|
32
|
-
* scratchpad for arithmetic — a note costing a turn apiece, which `arc_act`'s
|
|
33
|
-
* `note` field carries for free and keeps in the model's own history. The
|
|
34
|
-
* session file is unaffected: the family reaches the workspace through the
|
|
35
|
-
* `ToolFamilyContext` core hands it, not through tools the model can see.
|
|
36
|
-
*/
|
|
37
|
-
export declare const ARC_GAME_RECIPE: ResolvedRecipe;
|
|
38
|
-
/**
|
|
39
|
-
* The arc-game type. Its one param is an id the model quotes back from a tool
|
|
40
|
-
* result it already saw, so the contract is checkable before anything runs: a
|
|
41
|
-
* play with no game cannot succeed, and refusing it here costs no model call.
|
|
42
|
-
*
|
|
43
|
-
* There is deliberately no `card_id`. Which scorecard a play runs on is not a
|
|
44
|
-
* choice — the API auto-closes an idle card, so the live card is whichever one
|
|
45
|
-
* was used recently — and the parent leases it per chunk (see
|
|
46
|
-
* {@link file://./scorecard.ts}), handing it to the execution as runtime state.
|
|
47
|
-
*/
|
|
48
|
-
export declare const ARC_GAME_SPEC: SubtaskTypeSpec;
|