@a-dray/aglib 0.1.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/LICENSE +21 -0
- package/README.md +172 -0
- package/dist/agent.d.ts +158 -0
- package/dist/agent.js +2 -0
- package/dist/agent.js.map +1 -0
- package/dist/content.d.ts +45 -0
- package/dist/content.js +11 -0
- package/dist/content.js.map +1 -0
- package/dist/harness/adapters/acp/index.d.ts +92 -0
- package/dist/harness/adapters/acp/index.js +479 -0
- package/dist/harness/adapters/acp/index.js.map +1 -0
- package/dist/harness/adapters/acp/rpc.d.ts +23 -0
- package/dist/harness/adapters/acp/rpc.js +103 -0
- package/dist/harness/adapters/acp/rpc.js.map +1 -0
- package/dist/harness/adapters/native/compaction.d.ts +16 -0
- package/dist/harness/adapters/native/compaction.js +55 -0
- package/dist/harness/adapters/native/compaction.js.map +1 -0
- package/dist/harness/adapters/native/index.d.ts +2 -0
- package/dist/harness/adapters/native/index.js +2 -0
- package/dist/harness/adapters/native/index.js.map +1 -0
- package/dist/harness/adapters/native/loop.d.ts +25 -0
- package/dist/harness/adapters/native/loop.js +153 -0
- package/dist/harness/adapters/native/loop.js.map +1 -0
- package/dist/harness/harness.d.ts +129 -0
- package/dist/harness/harness.js +2 -0
- package/dist/harness/harness.js.map +1 -0
- package/dist/harness/index.d.ts +3 -0
- package/dist/harness/index.js +2 -0
- package/dist/harness/index.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -0
- package/dist/json.d.ts +4 -0
- package/dist/json.js +2 -0
- package/dist/json.js.map +1 -0
- package/dist/model/adapters/anthropic/index.d.ts +34 -0
- package/dist/model/adapters/anthropic/index.js +271 -0
- package/dist/model/adapters/anthropic/index.js.map +1 -0
- package/dist/model/adapters/fake/index.d.ts +27 -0
- package/dist/model/adapters/fake/index.js +37 -0
- package/dist/model/adapters/fake/index.js.map +1 -0
- package/dist/model/adapters/openai-compatible/index.d.ts +29 -0
- package/dist/model/adapters/openai-compatible/index.js +226 -0
- package/dist/model/adapters/openai-compatible/index.js.map +1 -0
- package/dist/model/conformance.d.ts +210 -0
- package/dist/model/conformance.js +427 -0
- package/dist/model/conformance.js.map +1 -0
- package/dist/model/index.d.ts +2 -0
- package/dist/model/index.js +2 -0
- package/dist/model/index.js.map +1 -0
- package/dist/model/model.d.ts +85 -0
- package/dist/model/model.js +8 -0
- package/dist/model/model.js.map +1 -0
- package/dist/result.d.ts +23 -0
- package/dist/result.js +3 -0
- package/dist/result.js.map +1 -0
- package/dist/run.d.ts +10 -0
- package/dist/run.js +477 -0
- package/dist/run.js.map +1 -0
- package/dist/sandbox/adapters/docker.d.ts +22 -0
- package/dist/sandbox/adapters/docker.js +443 -0
- package/dist/sandbox/adapters/docker.js.map +1 -0
- package/dist/sandbox/adapters/local.d.ts +11 -0
- package/dist/sandbox/adapters/local.js +284 -0
- package/dist/sandbox/adapters/local.js.map +1 -0
- package/dist/sandbox/conformance.d.ts +73 -0
- package/dist/sandbox/conformance.js +309 -0
- package/dist/sandbox/conformance.js.map +1 -0
- package/dist/sandbox/index.d.ts +1 -0
- package/dist/sandbox/index.js +2 -0
- package/dist/sandbox/index.js.map +1 -0
- package/dist/sandbox/sandbox.d.ts +172 -0
- package/dist/sandbox/sandbox.js +2 -0
- package/dist/sandbox/sandbox.js.map +1 -0
- package/dist/session/entry.d.ts +196 -0
- package/dist/session/entry.js +2 -0
- package/dist/session/entry.js.map +1 -0
- package/dist/session/index.d.ts +2 -0
- package/dist/session/index.js +2 -0
- package/dist/session/index.js.map +1 -0
- package/dist/session/log.d.ts +20 -0
- package/dist/session/log.js +24 -0
- package/dist/session/log.js.map +1 -0
- package/dist/session/messages.d.ts +42 -0
- package/dist/session/messages.js +99 -0
- package/dist/session/messages.js.map +1 -0
- package/dist/store/adapters/sqlite.d.ts +20 -0
- package/dist/store/adapters/sqlite.js +365 -0
- package/dist/store/adapters/sqlite.js.map +1 -0
- package/dist/store/conformance.d.ts +66 -0
- package/dist/store/conformance.js +580 -0
- package/dist/store/conformance.js.map +1 -0
- package/dist/store/index.d.ts +1 -0
- package/dist/store/index.js +2 -0
- package/dist/store/index.js.map +1 -0
- package/dist/store/store.d.ts +244 -0
- package/dist/store/store.js +2 -0
- package/dist/store/store.js.map +1 -0
- package/dist/tools/execute.d.ts +24 -0
- package/dist/tools/execute.js +105 -0
- package/dist/tools/execute.js.map +1 -0
- package/dist/tools/index.d.ts +2 -0
- package/dist/tools/index.js +2 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/tool.d.ts +106 -0
- package/dist/tools/tool.js +34 -0
- package/dist/tools/tool.js.map +1 -0
- package/package.json +119 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"conformance.js","sourceRoot":"","sources":["../../src/store/conformance.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * What any implementation of the store port must do.\n *\n * The port is seven methods and two mechanisms, and the mechanisms are the part\n * that goes wrong. `expectedSeq` is correctness and the claim is exclusion; one\n * does not imply the other; and the failure from confusing them is not a\n * rejected write but a log a provider will not accept, discovered in\n * production. Every store written from the interface alone re-derives those\n * rules, and a store that gets them subtly wrong looks exactly like one that\n * does not until two workers meet.\n *\n * So the contract is executable. These cases say what the interface means —\n * that a claim does not consume, that a queue survives a lost race, that an\n * open activation renews by writing rather than by having started, that a\n * delivery id outlives the queue — and an adapter runs them rather than reading\n * them.\n *\n * Inert on purpose. Each case is a name and a function that throws, so the\n * suite drags no test framework into the package and an adapter runs it under\n * whichever one it already has:\n *\n * ```ts\n * for (const item of defineStoreConformance({ open })) test(item.name, item.run);\n * ```\n */\nimport type { Runnable, Store, StoreChange } from \"./store.js\";\nimport type { Delivery, Entry, Stored } from \"../session/entry.js\";\nimport type { Failure, Result } from \"../result.js\";\n\n/** One case: a name, and a function that throws when the contract is broken. */\nexport interface ConformanceCase {\n name: string;\n run(): Promise<void>;\n}\n\nexport interface StoreUnderTest {\n /**\n * A store with no sessions in it, whose claim lapses after `claimMs`.\n *\n * Called once per case, so nothing leaks between them. The window is the\n * suite's because two cases turn on a claim expiring, and waiting out a\n * production default would take ten minutes.\n */\n open(input: { claimMs: number }): Promise<Store> | Store;\n /** Release whatever `open` provisioned. `Store.close` is called first. */\n release?(store: Store): Promise<void> | void;\n /**\n * How far this store's change feed reaches.\n *\n * Declared rather than inferred from the method being there, so a store that\n * has a push channel and never wired it up fails here instead of quietly\n * costing every worker built on it a poll — and so that \"reach is the store's\n * own to state\" has somewhere to be stated and held to.\n *\n * `\"process\"` wakes watchers on this instance: the HTTP surface writes and\n * the worker beside it hears, which is most deployments. `\"deployment\"` wakes\n * a watcher on another connection too, and owes a `peer` to prove it.\n */\n changes: \"none\" | \"process\" | \"deployment\";\n /**\n * A second store on the same data, for a feed claiming `\"deployment\"`. Not\n * `open`, which is entitled to start from nothing.\n */\n peer?(input: { claimMs: number }): Promise<Store> | Store;\n}\n\n/**\n * Short enough that a case can wait a claim out, long enough that two calls in\n * a row are inside one — a store reached over a socket takes real time, and a\n * window measured in tens of milliseconds tests the scheduler rather than the\n * contract.\n */\nconst CLAIM_MS = 500;\nconst LAPSE_MS = CLAIM_MS + 150;\n\n/**\n * A readable name for a session or a run, and a real id for the store.\n *\n * The cases read better with `parent` and `child` than with two UUIDs, and a\n * store reads them as what the port says they are. Memoised for the whole run\n * rather than per case, which costs nothing: every case gets its own store.\n */\nconst named = new Map<string, string>();\nconst id = (name: string): string => {\n const known = named.get(name);\n if (known) return known;\n const minted = crypto.randomUUID();\n named.set(name, minted);\n return minted;\n};\n\nconst agent = { id: \"conformance\", version: \"1\" };\n\nconst said = (input: string, runId = id(\"r\")): Entry => ({ type: \"run.started\", runId, input });\nconst ended = (runId = id(\"r\")): Entry => ({ type: \"run.finished\", runId, outcome: \"completed\" });\nconst wrote = (content: string, runId = id(\"r\")): Entry => ({ type: \"assistant\", runId, content });\n\nconst wait = (ms: number) => new Promise<void>((resolve) => { setTimeout(resolve, ms); });\n\nfunction fail(what: string): never {\n throw new Error(`store conformance: ${what}`);\n}\n\nfunction holds(condition: boolean, what: string): asserts condition {\n if (!condition) fail(what);\n}\n\nfunction same(actual: unknown, expected: unknown): boolean {\n if (actual === expected) return true;\n if (Array.isArray(actual) && Array.isArray(expected)) {\n return actual.length === expected.length && actual.every((item, at) => same(item, expected[at]));\n }\n if (typeof actual !== \"object\" || typeof expected !== \"object\" || !actual || !expected) return false;\n const left = Object.keys(actual as object).sort();\n const right = Object.keys(expected as object).sort();\n return same(left, right)\n && left.every((key) => same((actual as Record<string, unknown>)[key], (expected as Record<string, unknown>)[key]));\n}\n\nfunction equals(actual: unknown, expected: unknown, what: string): void {\n if (!same(actual, expected)) {\n fail(`${what} — expected ${JSON.stringify(expected)}, got ${JSON.stringify(actual)}`);\n }\n}\n\n/** Unwraps a `Result` the case expects to have succeeded. */\nfunction got<T>(result: Result<T, Failure>, what: string): T {\n if (!result.ok) fail(`${what} — ${result.error.code}: ${result.error.message}`);\n return result.value;\n}\n\nexport function defineStoreConformance(subject: StoreUnderTest): readonly ConformanceCase[] {\n const cases: ConformanceCase[] = [];\n\n const define = (name: string, body: (store: Store) => Promise<void>): void => {\n cases.push({\n name,\n async run() {\n const store = await subject.open({ claimMs: CLAIM_MS });\n try {\n await body(store);\n } finally {\n await store.close();\n await subject.release?.(store);\n }\n },\n });\n };\n\n /** An empty session — no entries, nothing owed — under an optional application key. */\n const created = async (store: Store, sessionId: string, key?: string): Promise<void> => {\n got(await store.create({ sessionId, agent, ...(key ? { key } : {}) }), `create ${sessionId}`);\n };\n\n const entriesOf = async (store: Store, sessionId: string): Promise<readonly Stored[]> =>\n got(await store.read({ sessionId }), `read ${sessionId}`).entries;\n\n const claim = async (store: Store): Promise<Runnable | undefined> =>\n got(await store.next({}), \"next\");\n\n const interrupted = async (store: Store): Promise<Runnable | undefined> =>\n got(await store.interrupted({}), \"interrupted\");\n\n // ---- The log ------------------------------------------------------------\n\n define(\"entries come back in order, and a cursor returns only what is new\", async (store) => {\n await created(store, id(\"s\"));\n const written = got(\n await store.append({ sessionId: id(\"s\"), expectedSeq: 0, entries: [said(\"one\"), said(\"two\")] }), \"append\");\n equals(written.seq, 2, \"the append reports the position it left the session at\");\n\n const all = got(await store.read({ sessionId: id(\"s\") }), \"read\");\n equals(all.entries.map((entry) => entry.seq), [1, 2], \"positions are 1 and 2\");\n equals(all.seq, 2, \"the session is at 2\");\n holds(all.entries.every((entry) => typeof entry.at === \"string\" && !Number.isNaN(Date.parse(entry.at))),\n \"every stored entry carries an ISO 8601 commit time\");\n\n const after = got(await store.read({ sessionId: id(\"s\"), afterSeq: 1 }), \"read after 1\");\n equals(after.entries.map((entry) => entry.seq), [2], \"a cursor returns only what is new\");\n equals(after.seq, 2, \"a cursor read still reports the session's real position\");\n });\n\n define(\"a session that was never created is not-found rather than empty\", async (store) => {\n const read = await store.read({ sessionId: id(\"nobody\") });\n holds(!read.ok, \"reading an unknown session fails\");\n equals(read.error.code, \"not-found\", \"the code says not-found\");\n });\n\n define(\"entries survive the round trip whole\", async (store) => {\n await created(store, id(\"s\"));\n const rich: Entry = {\n type: \"assistant\", runId: id(\"r\"),\n content: [{ type: \"text\", text: \"here\" }, { type: \"opaque\", provider: \"acme\", data: { keep: [1, null, \"x\"] } }],\n calls: [{ callId: \"c1\", name: \"look\", arguments: \"{\\\"at\\\":1}\" }],\n usage: { inputTokens: 10, outputTokens: 2 },\n generation: { model: \"m\", startedAt: \"2026-01-01T00:00:00.000Z\", endedAt: \"2026-01-01T00:00:01.000Z\" },\n };\n got(await store.append({ sessionId: id(\"s\"), expectedSeq: 0, entries: [rich] }), \"append\");\n const [stored] = await entriesOf(store, id(\"s\"));\n holds(stored !== undefined, \"the entry was stored\");\n const { seq, at, ...body } = stored;\n equals(body, rich, \"the entry comes back exactly as it went in\");\n });\n\n define(\"a session carries the agent and the metadata it was created with\", async (store) => {\n got(await store.create({ sessionId: id(\"s\"), agent, key: \"tenant\", metadata: { model: \"one\" } }), \"create\");\n got(await store.append({ sessionId: id(\"s\"), expectedSeq: 0, entries: [said(\"go\")] }), \"append\");\n\n const read = got(await store.read({ sessionId: id(\"s\") }), \"read\");\n equals(read.agent, agent, \"a read says whose session this is\");\n equals(read.metadata, { model: \"one\" }, \"and hands back what create was given, uninterpreted\");\n\n // A summary carries the same facts because a listing is how an application\n // finds a session it has no id for — one that had to read each row to learn\n // its agent or position would be a listing in name only.\n const [summary] = got(await store.list({ key: \"tenant\" }), \"list\");\n holds(summary !== undefined, \"the session is listed under its key\");\n equals(summary.agent, agent, \"a summary says whose session it is\");\n equals(summary.seq, 1, \"and where its log has got to\");\n equals(summary.metadata, { model: \"one\" }, \"and carries the metadata without a second read\");\n });\n\n // ---- Compare-and-swap ---------------------------------------------------\n\n define(\"a write from a stale position is refused and told the real one\", async (store) => {\n await created(store, id(\"s\"));\n got(await store.append({ sessionId: id(\"s\"), expectedSeq: 0, entries: [said(\"one\")] }), \"append\");\n\n const stale = await store.append({ sessionId: id(\"s\"), expectedSeq: 0, entries: [said(\"two\")] });\n holds(!stale.ok, \"a stale write is refused\");\n equals(stale.error.code, \"conflict\", \"the code says conflict\");\n equals((stale.error as { actualSeq?: number }).actualSeq, 1, \"the refusal carries the real position\");\n equals((await entriesOf(store, id(\"s\"))).length, 1, \"nothing of the refused write survives\");\n });\n\n define(\"an append to a session that is not there is not-found\", async (store) => {\n const missing = await store.append({ sessionId: id(\"nobody\"), expectedSeq: 0, entries: [said(\"one\")] });\n holds(!missing.ok, \"appending to an unknown session fails\");\n equals(missing.error.code, \"not-found\", \"the code says not-found\");\n });\n\n define(\"metadata merges rather than replacing\", async (store) => {\n await created(store, id(\"s\"));\n got(await store.append({ sessionId: id(\"s\"), expectedSeq: 0, entries: [], metadata: { model: \"one\", tenant: \"acme\" } }), \"first merge\");\n got(await store.append({ sessionId: id(\"s\"), expectedSeq: 0, entries: [], metadata: { model: \"two\" } }), \"second merge\");\n equals(got(await store.read({ sessionId: id(\"s\") }), \"read\").metadata, { model: \"two\", tenant: \"acme\" },\n \"the key that was not written keeps its value\");\n });\n\n // ---- Delivery, atomically ----------------------------------------------\n\n define(\"a delivery to another session commits with the sender's own entries\", async (store) => {\n await created(store, id(\"parent\"));\n await created(store, id(\"child\"), \"parent\");\n got(await store.append({\n sessionId: id(\"parent\"), expectedSeq: 0, entries: [said(\"spawn a child\")],\n enqueue: [{ sessionId: id(\"child\"), input: \"do the thing\", from: { kind: \"session\", id: id(\"parent\") } }],\n }), \"append with a delivery\");\n\n const runnable = await claim(store);\n holds(runnable?.sessionId === id(\"child\"), \"the recipient is runnable\");\n // The fields the port names, not the object. A store is entitled to hand\n // back a delivery with its default priority materialised — the caller sent\n // none and `next` is what none means — and comparing whole objects called\n // that a difference.\n equals(runnable.pending.length, 1, \"one delivery is waiting\");\n const [waiting] = runnable.pending;\n equals(waiting?.sessionId, id(\"child\"), \"addressed to the recipient\");\n equals(waiting?.input, \"do the thing\", \"carrying what was sent\");\n equals(waiting?.from?.kind, \"session\", \"sent by a session\");\n equals(waiting?.from?.id, id(\"parent\"), \"and which one\");\n equals(runnable.seq, 0, \"the recipient's position is its own, not the sender's\");\n });\n\n define(\"a rejected append delivers nothing\", async (store) => {\n await created(store, id(\"sender\"));\n await created(store, id(\"target\"));\n got(await store.append({ sessionId: id(\"sender\"), expectedSeq: 0, entries: [said(\"one\")] }), \"append\");\n\n const stale = await store.append({\n sessionId: id(\"sender\"), expectedSeq: 0, entries: [said(\"two\")],\n enqueue: [{ sessionId: id(\"target\"), input: \"never sent\" }],\n });\n holds(!stale.ok, \"the stale write is refused\");\n equals(got(await store.read({ sessionId: id(\"target\") }), \"read target\").pending, [],\n \"the recipient received nothing\");\n });\n\n define(\"a delivery to a session that is not there fails and commits nothing\", async (store) => {\n await created(store, id(\"sender\"));\n const missing = await store.append({\n sessionId: id(\"sender\"), expectedSeq: 0, entries: [said(\"one\")],\n enqueue: [{ sessionId: id(\"nobody\"), input: \"into the void\" }],\n });\n holds(!missing.ok, \"a delivery to an unknown session fails\");\n equals(missing.error.code, \"not-found\", \"the code says not-found\");\n equals((await entriesOf(store, id(\"sender\"))).length, 0, \"the sender's own entries went with it\");\n });\n\n // ---- The queue and the claim -------------------------------------------\n\n define(\"next claims without consuming: the queue survives until an append commits it\", async (store) => {\n await created(store, id(\"s\"));\n got(await store.append({\n sessionId: id(\"s\"), expectedSeq: 0, entries: [], enqueue: [{ sessionId: id(\"s\"), input: \"read me\" }],\n }), \"enqueue\");\n\n const claimed = await claim(store);\n holds(claimed?.sessionId === id(\"s\"), \"the session is claimed\");\n equals(got(await store.read({ sessionId: id(\"s\") }), \"read\").pending.length, 1,\n \"reading the queue did not empty it\");\n\n got(await store.append({\n sessionId: id(\"s\"), expectedSeq: claimed.seq, entries: [said(\"read me\")], takePending: 1,\n }), \"commit the delivery as an entry\");\n equals(got(await store.read({ sessionId: id(\"s\") }), \"read\").pending, [],\n \"the write that recorded it is what removed it\");\n });\n\n define(\"an append that loses its position destroys no messages\", async (store) => {\n await created(store, id(\"s\"));\n got(await store.append({\n sessionId: id(\"s\"), expectedSeq: 0, entries: [], enqueue: [{ sessionId: id(\"s\"), input: \"read me\" }],\n }), \"enqueue\");\n const claimed = await claim(store);\n holds(claimed !== undefined, \"the session is claimed\");\n\n // Somebody else advances the session while this worker holds the queue.\n got(await store.append({ sessionId: id(\"s\"), expectedSeq: claimed.seq, entries: [wrote(\"elsewhere\")] }), \"other writer\");\n\n const lost = await store.append({\n sessionId: id(\"s\"), expectedSeq: claimed.seq, entries: [said(\"read me\")], takePending: 1,\n });\n holds(!lost.ok, \"the loser is refused\");\n equals(got(await store.read({ sessionId: id(\"s\") }), \"read\").pending.length, 1,\n \"the messages it was carrying are where it found them\");\n });\n\n define(\"takePending removes what was committed and nothing that arrived since\", async (store) => {\n await created(store, id(\"s\"));\n got(await store.append({\n sessionId: id(\"s\"), expectedSeq: 0, entries: [],\n enqueue: [{ sessionId: id(\"s\"), input: \"first\" }, { sessionId: id(\"s\"), input: \"second\" }],\n }), \"enqueue two\");\n const claimed = await claim(store);\n holds(claimed?.pending.length === 2, \"both are reported\");\n\n got(await store.append({\n sessionId: id(\"s\"), expectedSeq: claimed.seq, entries: [], enqueue: [{ sessionId: id(\"s\"), input: \"third\" }],\n }), \"a third arrives while the activation runs\");\n got(await store.append({\n sessionId: id(\"s\"), expectedSeq: claimed.seq, entries: [said(\"first\"), said(\"second\")], takePending: 2,\n }), \"commit the two that were taken\");\n\n equals(got(await store.read({ sessionId: id(\"s\") }), \"read\").pending.map((one: Delivery) => one.input), [\"third\"],\n \"what arrived since is behind them and survives\");\n });\n\n define(\"a session is claimed while it runs and released when the run finishes\", async (store) => {\n await created(store, id(\"s\"));\n got(await store.append({\n sessionId: id(\"s\"), expectedSeq: 0, entries: [], enqueue: [{ sessionId: id(\"s\"), input: \"go\" }],\n }), \"enqueue\");\n\n const claimed = await claim(store);\n holds(claimed !== undefined, \"the session is claimed\");\n got(await store.append({\n sessionId: id(\"s\"), expectedSeq: claimed.seq, entries: [said(\"go\")], takePending: 1,\n }), \"open the activation\");\n got(await store.append({\n sessionId: id(\"s\"), expectedSeq: claimed.seq + 1, entries: [], enqueue: [{ sessionId: id(\"s\"), input: \"and again\" }],\n }), \"a message arrives mid-activation\");\n\n equals(await claim(store), undefined, \"a second activation of a running session is not offered\");\n\n got(await store.append({ sessionId: id(\"s\"), expectedSeq: claimed.seq + 1, entries: [ended()] }), \"finish the run\");\n const again = await claim(store);\n holds(again?.sessionId === id(\"s\"), \"the finished session is offered with what arrived while it ran\");\n });\n\n define(\"an open activation holds its claim by writing, not by having started\", async (store) => {\n await created(store, id(\"s\"));\n got(await store.append({\n sessionId: id(\"s\"), expectedSeq: 0, entries: [], enqueue: [{ sessionId: id(\"s\"), input: \"go\" }],\n }), \"enqueue\");\n const claimed = await claim(store);\n holds(claimed !== undefined, \"the session is claimed\");\n got(await store.append({\n sessionId: id(\"s\"), expectedSeq: claimed.seq, entries: [said(\"go\")], takePending: 1,\n }), \"open the activation\");\n got(await store.append({\n sessionId: id(\"s\"), expectedSeq: claimed.seq + 1, entries: [], enqueue: [{ sessionId: id(\"s\"), input: \"more\" }],\n }), \"a message arrives mid-activation\");\n\n // A turn longer than the claim window. Every write the activation makes\n // renews it, or a second worker is handed a session that is still running —\n // and a compare-and-swap can refuse a write, not un-run a tool call.\n await wait(LAPSE_MS);\n got(await store.append({\n sessionId: id(\"s\"), expectedSeq: claimed.seq + 1, entries: [wrote(\"still working\")],\n }), \"the activation writes again\");\n equals(await claim(store), undefined, \"the running session is still not offered\");\n });\n\n define(\"a claim lapses, so a worker that died does not strand its session\", async (store) => {\n await created(store, id(\"s\"));\n got(await store.append({\n sessionId: id(\"s\"), expectedSeq: 0, entries: [], enqueue: [{ sessionId: id(\"s\"), input: \"go\" }],\n }), \"enqueue\");\n holds((await claim(store)) !== undefined, \"the session is claimed\");\n equals(await claim(store), undefined, \"and held\");\n\n await wait(LAPSE_MS);\n const again = await claim(store);\n holds(again?.sessionId === id(\"s\"), \"the lapsed claim releases the session\");\n equals(again.pending.length, 1, \"with the messages still on it\");\n });\n\n define(\"next takes the oldest waiting session, and does not read priority\", async (store) => {\n await created(store, id(\"first\"));\n await created(store, id(\"second\"));\n got(await store.append({\n sessionId: id(\"first\"), expectedSeq: 0, entries: [], enqueue: [{ sessionId: id(\"first\"), input: \"older\" }],\n }), \"enqueue to first\");\n await wait(15);\n got(await store.append({\n sessionId: id(\"second\"), expectedSeq: 0, entries: [],\n enqueue: [{ sessionId: id(\"second\"), input: \"urgent\", priority: \"interrupt\" }],\n }), \"enqueue to second\");\n\n // Where a message lands in a running activation says nothing about which\n // session a worker picks up next. An application that needs urgent work\n // scheduled first orders its own workers.\n equals((await claim(store))?.sessionId, id(\"first\"), \"the oldest goes first\");\n const urgent = await claim(store);\n equals(urgent?.sessionId, id(\"second\"), \"then the newer one\");\n // Recorded and reported, though nothing here acted on it: the mode is the\n // harness's to honour, and it cannot honour what the store dropped.\n equals(urgent?.pending[0]?.priority, \"interrupt\", \"the place the sender asked for reaches the reader\");\n });\n\n // ---- Delivery identity --------------------------------------------------\n\n define(\"a delivery already waiting under the same id does not arrive twice\", async (store) => {\n await created(store, id(\"s\"));\n for (let attempt = 0; attempt < 2; attempt += 1) {\n got(await store.append({\n sessionId: id(\"s\"), expectedSeq: 0, entries: [],\n enqueue: [{ sessionId: id(\"s\"), input: \"once\", id: \"d1\" }],\n }), `send ${attempt}`);\n }\n equals(got(await store.read({ sessionId: id(\"s\") }), \"read\").pending.length, 1, \"the retry collapsed into one\");\n });\n\n define(\"a delivery id is remembered after its first copy has been read\", async (store) => {\n await created(store, id(\"s\"));\n got(await store.append({\n sessionId: id(\"s\"), expectedSeq: 0, entries: [], enqueue: [{ sessionId: id(\"s\"), input: \"once\", id: \"d1\" }],\n }), \"first send\");\n const claimed = await claim(store);\n holds(claimed !== undefined, \"the session is claimed\");\n got(await store.append({\n sessionId: id(\"s\"), expectedSeq: claimed.seq, entries: [said(\"once\")], takePending: 1,\n }), \"read it\");\n\n got(await store.append({\n sessionId: id(\"s\"), expectedSeq: claimed.seq + 1, entries: [],\n enqueue: [{ sessionId: id(\"s\"), input: \"once\", id: \"d1\" }],\n }), \"the same delivery again\");\n equals(got(await store.read({ sessionId: id(\"s\") }), \"read\").pending, [],\n \"an id is not forgotten the moment the queue drains\");\n });\n\n define(\"two senders numbering their messages from one do not suppress each other\", async (store) => {\n await created(store, id(\"one\"));\n await created(store, id(\"two\"));\n await created(store, id(\"target\"));\n got(await store.append({\n sessionId: id(\"one\"), expectedSeq: 0, entries: [],\n enqueue: [{ sessionId: id(\"target\"), input: \"from one\", from: { kind: \"session\", id: id(\"one\") }, id: \"1\" }],\n }), \"sender one\");\n got(await store.append({\n sessionId: id(\"two\"), expectedSeq: 0, entries: [],\n enqueue: [{ sessionId: id(\"target\"), input: \"from two\", from: { kind: \"session\", id: id(\"two\") }, id: \"1\" }],\n }), \"sender two\");\n equals(got(await store.read({ sessionId: id(\"target\") }), \"read\").pending.length, 2,\n \"an id is the sender's own, so two of them are two deliveries\");\n });\n\n // ---- Listing ------------------------------------------------------------\n\n define(\"listing is by the application's opaque key, newest first\", async (store) => {\n await created(store, id(\"a\"), \"tenant-1\");\n await wait(15);\n await created(store, id(\"b\"), \"tenant-1\");\n await created(store, id(\"c\"), \"tenant-2\");\n\n const mine = got(await store.list({ key: \"tenant-1\" }), \"list\");\n equals(mine.map((row) => row.sessionId), [id(\"b\"), id(\"a\")], \"only that key, newest first\");\n equals(mine[0]?.key, \"tenant-1\", \"the key comes back as it was given\");\n equals(got(await store.list({}), \"list all\").length, 3, \"listing without a key sees every session\");\n });\n\n define(\"a listing page does not step over the sessions sharing its boundary\", async (store) => {\n // Written in one tick on purpose: without the id in the cursor, a page\n // boundary is an instant and every row sharing it is skipped.\n // `id(...)` shadowed by a loop variable is how a raw label reached a store\n // that keeps session ids as UUIDs, so these are named rather than reused.\n for (const label of [\"a\", \"b\", \"c\"]) await created(store, id(label), \"tenant\");\n const first = got(await store.list({ key: \"tenant\", limit: 1 }), \"first page\");\n holds(first.length === 1, \"one row\");\n const cursor = `${first[0]!.updatedAt}|${first[0]!.sessionId}`;\n const rest = got(await store.list({ key: \"tenant\", before: cursor }), \"second page\");\n equals(rest.length, 2, \"the remaining two are on the next page\");\n holds(!rest.some((row) => row.sessionId === first[0]!.sessionId), \"and the first is not repeated\");\n });\n\n // ---- Resumption ---------------------------------------------------------\n\n define(\"an interrupted activation is found once its claim lapses, and next cannot see it\", async (store) => {\n await created(store, id(\"s\"));\n got(await store.append({\n sessionId: id(\"s\"), expectedSeq: 0, entries: [], enqueue: [{ sessionId: id(\"s\"), input: \"go\" }],\n }), \"enqueue\");\n const claimed = await claim(store);\n holds(claimed !== undefined, \"the session is claimed\");\n // The commit that opened the run took the queue with it. This is the state\n // a killed worker leaves: an open activation and nothing owed.\n got(await store.append({\n sessionId: id(\"s\"), expectedSeq: claimed.seq, entries: [said(\"go\")], takePending: 1,\n }), \"open the activation\");\n\n equals(await claim(store), undefined, \"next has nothing: the session is running and nothing waits\");\n equals(await interrupted(store), undefined, \"and while the claim holds, nothing is handed back either\");\n\n await wait(LAPSE_MS);\n equals(await claim(store), undefined, \"still nothing has been asked for\");\n const found = await interrupted(store);\n holds(found?.sessionId === id(\"s\"), \"the interrupted activation is found\");\n equals(found.seq, claimed.seq + 1, \"at the position its last commit left it\");\n equals(found.pending, [], \"with nothing waiting, by construction\");\n });\n\n define(\"interrupted claims what it hands out\", async (store) => {\n await created(store, id(\"s\"));\n got(await store.append({ sessionId: id(\"s\"), expectedSeq: 0, entries: [said(\"go\")] }), \"open the activation\");\n await wait(LAPSE_MS);\n holds((await interrupted(store))?.sessionId === id(\"s\"), \"the first caller takes it\");\n equals(await interrupted(store), undefined, \"a second is not handed the same work\");\n });\n\n define(\"a session that finished is neither runnable nor interrupted\", async (store) => {\n await created(store, id(\"s\"));\n got(await store.append({ sessionId: id(\"s\"), expectedSeq: 0, entries: [said(\"go\"), ended()] }), \"a whole run\");\n await wait(LAPSE_MS);\n equals(await claim(store), undefined, \"nothing is owed\");\n equals(await interrupted(store), undefined, \"and nothing was left half-done\");\n });\n\n define(\"a session with input waiting belongs to next, not to interrupted\", async (store) => {\n await created(store, id(\"s\"));\n got(await store.append({\n sessionId: id(\"s\"), expectedSeq: 0, entries: [said(\"go\")],\n enqueue: [{ sessionId: id(\"s\"), input: \"and this too\" }],\n }), \"an open activation with a message waiting\");\n await wait(LAPSE_MS);\n equals(await interrupted(store), undefined, \"interrupted leaves it alone\");\n equals((await claim(store))?.sessionId, id(\"s\"), \"next takes it, with what it is owed\");\n });\n\n define(\"a claim carries the session's metadata, from either question\", async (store) => {\n // The claim is passed whole to the activation that follows, and metadata is\n // how an application configured this session — which model, whose tenant,\n // which sandbox. A claim without it is a claim the worker has to re-read.\n got(await store.create({ sessionId: id(\"owed\"), agent, metadata: { model: \"one\" } }), \"create owed\");\n got(await store.create({ sessionId: id(\"open\"), agent, metadata: { model: \"two\" } }), \"create open\");\n got(await store.append({\n sessionId: id(\"owed\"), expectedSeq: 0, entries: [], enqueue: [{ sessionId: id(\"owed\"), input: \"go\" }],\n }), \"enqueue to the one that is owed input\");\n got(await store.append({ sessionId: id(\"open\"), expectedSeq: 0, entries: [said(\"go\")] }), \"open the other\");\n\n const claimed = await claim(store);\n holds(claimed?.sessionId === id(\"owed\"), \"next takes the session with input\");\n equals(claimed.metadata, { model: \"one\" }, \"and hands back that session's metadata\");\n\n await wait(LAPSE_MS);\n const found = await interrupted(store);\n holds(found?.sessionId === id(\"open\"), \"interrupted takes the open one\");\n equals(found.metadata, { model: \"two\" }, \"and hands back the same thing\");\n });\n\n define(\"a claim lapses while a session is only spoken to, never worked\", async (store) => {\n // The trap: a store that renewed on any append at all let a message *to* a\n // session renew the claim of the worker that was meant to read it. A dead\n // worker's session then stayed invisible to `next` — the claim never\n // lapsed — and to `interrupted`, whose queue was not empty. The messages\n // stayed there for ever.\n await created(store, id(\"s\"));\n got(await store.append({\n sessionId: id(\"s\"), expectedSeq: 0, entries: [], enqueue: [{ sessionId: id(\"s\"), input: \"go\" }],\n }), \"enqueue\");\n const claimed = await claim(store);\n holds(claimed !== undefined, \"the session is claimed\");\n got(await store.append({\n sessionId: id(\"s\"), expectedSeq: claimed.seq, entries: [said(\"go\")], takePending: 1,\n }), \"open the activation\");\n\n // The worker dies here. Somebody keeps talking to the session, right up to\n // the moment of asking — so a store that renews on any write at all still\n // holds a fresh claim, and one that renews only on work does not.\n for (let sent = 0; sent < 4; sent += 1) {\n await wait(CLAIM_MS / 2);\n got(await store.append({\n sessionId: id(\"s\"), expectedSeq: claimed.seq + 1, entries: [],\n enqueue: [{ sessionId: id(\"s\"), input: `and ${sent}` }],\n }), `a later message ${sent}`);\n }\n\n const again = await claim(store);\n holds(again?.sessionId === id(\"s\"), \"the session is offered again once its own writes stop\");\n equals(again.pending.length, 4, \"with everything that arrived while nobody was reading\");\n });\n\n define(\"taking more deliveries than are queued is refused, not clamped\", async (store) => {\n // Silently dropping messages nothing recorded is the one loss this design\n // exists to prevent, and a caller's off-by-one reaches it.\n await created(store, id(\"s\"));\n got(await store.append({\n sessionId: id(\"s\"), expectedSeq: 0, entries: [],\n enqueue: [{ sessionId: id(\"s\"), input: \"one\" }, { sessionId: id(\"s\"), input: \"two\" }],\n }), \"enqueue two\");\n const over = await store.append({\n sessionId: id(\"s\"), expectedSeq: 0, entries: [said(\"one\")], takePending: 9,\n });\n holds(!over.ok, \"a count larger than the queue is refused\");\n equals(got(await store.read({ sessionId: id(\"s\") }), \"read\").pending.length, 2,\n \"and the messages are still there\");\n });\n\n // ---- Being told to look again -------------------------------------------\n\n if (subject.changes === \"none\") {\n define(\"a store with no push channel says so by not offering one\", async (store) => {\n holds(store.watch === undefined, \"a store declaring no feed must not carry a `watch` that never fires\");\n });\n return cases;\n }\n\n /** The next wake matching `want`, or a failure naming what never arrived. */\n const woken = (store: Store, want: (change: StoreChange) => boolean, what: string): Promise<StoreChange> => {\n holds(store.watch !== undefined, \"a store declaring a feed must offer `watch`\");\n return new Promise<StoreChange>((resolve, reject) => {\n const timer = setTimeout(() => { off(); reject(new Error(`store conformance: no wake for ${what}`)); }, 4_000);\n const off = store.watch!((change) => {\n if (!want(change)) return;\n clearTimeout(timer);\n off();\n resolve(change);\n });\n });\n };\n\n define(\"a change committed through this store wakes a watcher on this store\", async (store) => {\n await created(store, id(\"s\"));\n // Not a hypothetical: an implementation skipped its own notification to\n // avoid an echo, and since the surface that writes and the worker that\n // reads were one process, a delivery woke nobody at all.\n const wake = woken(store, (change) => change.sessionId === id(\"s\"), \"an append on the same store\");\n got(await store.append({ sessionId: id(\"s\"), expectedSeq: 0, entries: [said(\"one\")] }), \"append\");\n await wake;\n });\n\n define(\"a wake means the change is already readable\", async (store) => {\n await created(store, id(\"s\"));\n const wake = woken(store, (change) => change.sessionId === id(\"s\"), \"an append\");\n got(await store.append({ sessionId: id(\"s\"), expectedSeq: 0, entries: [said(\"one\")] }), \"append\");\n await wake;\n // Looking after a wake finds at least what woke it. A notification sent\n // before the commit is worse than none: the look finds nothing, and nothing\n // ever tells it again.\n equals((await entriesOf(store, id(\"s\"))).length, 1, \"the entry that caused the wake is there\");\n });\n\n define(\"a delivery says the session it landed on is runnable\", async (store) => {\n await created(store, id(\"sender\"));\n await created(store, id(\"target\"));\n const wake = woken(store, (change) => change.sessionId === id(\"target\"), \"a delivery to another session\");\n got(await store.append({\n sessionId: id(\"sender\"), expectedSeq: 0, entries: [said(\"go\")],\n enqueue: [{ sessionId: id(\"target\"), input: \"do the thing\" }],\n }), \"append with a delivery\");\n equals((await wake).runnable, true, \"the recipient now has work owed to it\");\n });\n\n if (subject.changes === \"deployment\") {\n cases.push({\n name: \"a change on one connection wakes a watcher on another\",\n async run() {\n // The reach a database store exists for. One that only hears itself is\n // a real feed and a useful one, but a worker in another process is then\n // carried entirely by its heartbeat — which is the difference between a\n // message arriving in milliseconds and in half a minute.\n holds(subject.peer !== undefined, \"a feed claiming deployment reach owes a peer to prove it\");\n const store = await subject.open({ claimMs: CLAIM_MS });\n const other = await subject.peer!({ claimMs: CLAIM_MS });\n try {\n await created(store, id(\"s\"));\n const wake = woken(other, (change) => change.sessionId === id(\"s\"), \"a write on another connection\");\n // Registering `LISTEN` is itself a round trip; the heartbeat is what\n // covers a change that lands before it completes.\n await wait(400);\n got(await store.append({\n sessionId: id(\"s\"), expectedSeq: 0, entries: [], enqueue: [{ sessionId: id(\"s\"), input: \"wake up\" }],\n }), \"a delivery from the other connection\");\n equals((await wake).runnable, true, \"the far watcher hears that work is owed\");\n } finally {\n await other.close();\n await store.close();\n await subject.release?.(store);\n }\n },\n });\n }\n\n define(\"unsubscribing stops the wakes\", async (store) => {\n await created(store, id(\"s\"));\n let seen = 0;\n const off = store.watch!(() => { seen += 1; });\n off();\n off(); // idempotent: releasing twice is what releasing asked for\n got(await store.append({ sessionId: id(\"s\"), expectedSeq: 0, entries: [said(\"one\")] }), \"append\");\n await wait(200);\n equals(seen, 0, \"a watcher that let go is not called again\");\n });\n\n return cases;\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export type { AgentRef, Delivery, Runnable, SessionRead, SessionSummary, Store, StoreChange, StoreConflict, StoreError, } from "./store.js";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/store/index.ts"],"names":[],"mappings":"","sourcesContent":["export type {\n AgentRef, Delivery, Runnable, SessionRead, SessionSummary,\n Store, StoreChange, StoreConflict, StoreError,\n} from \"./store.js\";\n"]}
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
import type { Delivery, Entry, Stored } from "../session/entry.js";
|
|
2
|
+
import type { Failure, Result } from "../result.js";
|
|
3
|
+
import type { JsonValue } from "../json.js";
|
|
4
|
+
export interface AgentRef {
|
|
5
|
+
id: string;
|
|
6
|
+
version: string;
|
|
7
|
+
}
|
|
8
|
+
export interface StoreError extends Failure {
|
|
9
|
+
code: "unavailable" | "not-found" | "conflict" | "failed";
|
|
10
|
+
}
|
|
11
|
+
/** Someone else advanced this session first. Retry means re-read and re-decide, not re-send. */
|
|
12
|
+
export interface StoreConflict extends StoreError {
|
|
13
|
+
code: "conflict";
|
|
14
|
+
actualSeq: number;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* A session id and a run id are UUIDs.
|
|
18
|
+
*
|
|
19
|
+
* `runAgent` mints both with `crypto.randomUUID()` and the library never
|
|
20
|
+
* produces anything else, so the only place another shape could enter is a
|
|
21
|
+
* caller-supplied `sessionId` — and stating it is what lets a store keep them
|
|
22
|
+
* in a `uuid` column, which is not a detail: it is sixteen bytes and index
|
|
23
|
+
* locality on the hottest table a deployment has. Left unstated, a store that
|
|
24
|
+
* did so was narrowing a contract nobody had written down.
|
|
25
|
+
*
|
|
26
|
+
* An application's own naming goes in `key`, which exists for exactly that and
|
|
27
|
+
* is opaque here.
|
|
28
|
+
*/
|
|
29
|
+
export interface SessionRead {
|
|
30
|
+
sessionId: string;
|
|
31
|
+
agent: AgentRef;
|
|
32
|
+
seq: number;
|
|
33
|
+
metadata: JsonValue;
|
|
34
|
+
entries: readonly Stored[];
|
|
35
|
+
/** Undelivered input. Visible to any process, which is how a delivery to a busy session is noticed. */
|
|
36
|
+
pending: readonly Delivery[];
|
|
37
|
+
}
|
|
38
|
+
export interface SessionSummary {
|
|
39
|
+
sessionId: string;
|
|
40
|
+
agent: AgentRef;
|
|
41
|
+
key: string | null;
|
|
42
|
+
seq: number;
|
|
43
|
+
metadata: JsonValue;
|
|
44
|
+
updatedAt: string;
|
|
45
|
+
}
|
|
46
|
+
export interface Runnable {
|
|
47
|
+
sessionId: string;
|
|
48
|
+
seq: number;
|
|
49
|
+
/**
|
|
50
|
+
* What was waiting, with provenance and priority.
|
|
51
|
+
*
|
|
52
|
+
* Reading does not consume: the queue is cleared by the append that commits
|
|
53
|
+
* these as entries, in the same compare-and-swap. A worker that loses that
|
|
54
|
+
* race therefore leaves the messages where it found them, instead of having
|
|
55
|
+
* already destroyed them.
|
|
56
|
+
*/
|
|
57
|
+
pending: readonly Delivery[];
|
|
58
|
+
metadata: JsonValue;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Which session changed, and whether it now has work owed to it.
|
|
62
|
+
*
|
|
63
|
+
* Deliberately not the change itself. A watcher cannot read state from this and
|
|
64
|
+
* must not try: it says a session moved, and the only correct response is to
|
|
65
|
+
* ask the store what it says now. Carrying the entries here would make a second
|
|
66
|
+
* path to the log — one with no cursor, no ordering and no durability — beside
|
|
67
|
+
* the one that has all three.
|
|
68
|
+
*/
|
|
69
|
+
export interface StoreChange {
|
|
70
|
+
sessionId: string;
|
|
71
|
+
/** Whether that session now has undelivered input. Not whether `next` would return it. */
|
|
72
|
+
runnable: boolean;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Ordered, atomically-appended session logs. Seven methods, and one optional.
|
|
76
|
+
*
|
|
77
|
+
* Two mechanisms, and they do different jobs. `expectedSeq` is the correctness
|
|
78
|
+
* one: a write from a stale position loses and is told the real one, so no two
|
|
79
|
+
* writers can interleave at the same position. The claim taken by `next` is the
|
|
80
|
+
* exclusion one: it stops a second worker from starting a *second activation*
|
|
81
|
+
* of a session that is already running.
|
|
82
|
+
*
|
|
83
|
+
* Both are needed, and one does not imply the other. Compare-and-swap alone
|
|
84
|
+
* permits two activations to run concurrently at different positions, each
|
|
85
|
+
* committing happily until one of them loses a race mid-turn — which leaves a
|
|
86
|
+
* tool call asked and never answered, and destroys the messages the loser took.
|
|
87
|
+
* That is a real failure, observed, not a theoretical one.
|
|
88
|
+
*
|
|
89
|
+
* The claim is deliberately small: no renewal, no fencing token. It expires on
|
|
90
|
+
* its own so a worker that dies does not strand a session, and if that worker
|
|
91
|
+
* turns out to be alive its writes still fail the compare-and-swap. The claim
|
|
92
|
+
* saves work; the compare-and-swap is what makes the work safe.
|
|
93
|
+
*/
|
|
94
|
+
export interface Store {
|
|
95
|
+
create(input: {
|
|
96
|
+
sessionId: string;
|
|
97
|
+
agent: AgentRef;
|
|
98
|
+
/** Opaque application index key — a user, tenant, channel or parent session. Never interpreted. */
|
|
99
|
+
key?: string;
|
|
100
|
+
metadata?: JsonValue;
|
|
101
|
+
}): Promise<Result<void, StoreError>>;
|
|
102
|
+
read(input: {
|
|
103
|
+
sessionId: string;
|
|
104
|
+
afterSeq?: number;
|
|
105
|
+
}): Promise<Result<SessionRead, StoreError>>;
|
|
106
|
+
/**
|
|
107
|
+
* The one operation that makes orchestration safe. Entries, deliveries to
|
|
108
|
+
* other sessions, and a metadata merge commit together or not at all — so a
|
|
109
|
+
* handoff between agents can never be lost or duplicated.
|
|
110
|
+
*/
|
|
111
|
+
append(input: {
|
|
112
|
+
sessionId: string;
|
|
113
|
+
expectedSeq: number;
|
|
114
|
+
entries: readonly Entry[];
|
|
115
|
+
enqueue?: readonly Delivery[];
|
|
116
|
+
metadata?: JsonValue;
|
|
117
|
+
/**
|
|
118
|
+
* Remove this many deliveries from the front of this session's own queue,
|
|
119
|
+
* in the same transaction. This is how input taken from `next` is consumed:
|
|
120
|
+
* the messages are gone only once the entries carrying them are committed.
|
|
121
|
+
* Anything that arrived since is behind them and survives.
|
|
122
|
+
*
|
|
123
|
+
* More than the queue holds is refused, never clamped. It is only ever
|
|
124
|
+
* `claim.pending.length`, so a larger number means the caller is working
|
|
125
|
+
* from a queue that is not there — and clamping it would drop messages
|
|
126
|
+
* nothing recorded, which is the one loss this design exists to prevent.
|
|
127
|
+
*/
|
|
128
|
+
takePending?: number;
|
|
129
|
+
}): Promise<Result<{
|
|
130
|
+
seq: number;
|
|
131
|
+
}, StoreConflict | StoreError>>;
|
|
132
|
+
/**
|
|
133
|
+
* Sessions by the application's opaque key, newest first.
|
|
134
|
+
*
|
|
135
|
+
* `before` is a page boundary, and its shape is part of the contract because
|
|
136
|
+
* a caller has to be able to build one: `"<updatedAt>|<sessionId>"`, taken
|
|
137
|
+
* from the last row of the previous page. The id is in it because sessions
|
|
138
|
+
* written in the same instant have no order without it, and a plain `<` on
|
|
139
|
+
* the timestamp then steps over every row that shares the boundary. Left
|
|
140
|
+
* unsaid, two stores answered it two different ways and one of them ignored
|
|
141
|
+
* it entirely.
|
|
142
|
+
*/
|
|
143
|
+
list(input: {
|
|
144
|
+
key?: string;
|
|
145
|
+
limit?: number;
|
|
146
|
+
before?: string;
|
|
147
|
+
}): Promise<Result<readonly SessionSummary[], StoreError>>;
|
|
148
|
+
/**
|
|
149
|
+
* Claim the next session that has input and is not already running.
|
|
150
|
+
*
|
|
151
|
+
* The queue is reported, not taken — see `takePending`. `undefined` means
|
|
152
|
+
* nothing is owed, everything owed is already being worked on, or the caller
|
|
153
|
+
* gave up: a `signal` that has already aborted answers `undefined`, because
|
|
154
|
+
* nothing is owed to somebody who stopped asking.
|
|
155
|
+
*/
|
|
156
|
+
next(input: {
|
|
157
|
+
signal?: AbortSignal;
|
|
158
|
+
}): Promise<Result<Runnable | undefined, StoreError>>;
|
|
159
|
+
/**
|
|
160
|
+
* Claim a session whose activation was interrupted: an open run whose claim
|
|
161
|
+
* has lapsed, with nothing waiting to make it runnable the ordinary way.
|
|
162
|
+
*
|
|
163
|
+
* `next` answers what has been asked for, which is the right question almost
|
|
164
|
+
* always. This is the other one — what was being worked when a process
|
|
165
|
+
* stopped existing — and without it that work is invisible. `next` skips a
|
|
166
|
+
* session with an open activation, on purpose; the queue that made it
|
|
167
|
+
* runnable was consumed by the commit that recorded it; so a session whose
|
|
168
|
+
* worker was killed mid-run is owed to nobody and waits for a stranger to
|
|
169
|
+
* speak to it. Every application built on this rediscovers that, and the
|
|
170
|
+
* store is the only thing that can see it.
|
|
171
|
+
*
|
|
172
|
+
* Separate from `next` rather than folded into it because resuming is a
|
|
173
|
+
* decision, not a default: an application may want interrupted work finished
|
|
174
|
+
* at once, or left for whoever speaks to the session next. `pending` is empty
|
|
175
|
+
* by construction — a session with input waiting is `next`'s.
|
|
176
|
+
*
|
|
177
|
+
* Claimed on the same terms and with the same window. A run that commits
|
|
178
|
+
* nothing at all for longer than `claimMs` looks the same as one whose
|
|
179
|
+
* process died, here as in `next`. Two more consequences of that window,
|
|
180
|
+
* both accepted:
|
|
181
|
+
*
|
|
182
|
+
* An interrupted run is invisible until its claim lapses, so a killed
|
|
183
|
+
* worker's session waits out `claimMs` before anyone can pick it up. That is
|
|
184
|
+
* the price of having no heartbeat and no fencing token.
|
|
185
|
+
*
|
|
186
|
+
* A store keeps one mark for "claimed" and "an activation is open", on
|
|
187
|
+
* purpose — two fields could disagree, and the log is the only thing that
|
|
188
|
+
* knows. The cost is that a session claimed by `next` whose worker committed
|
|
189
|
+
* something other than `run.started` is indistinguishable from an interrupted
|
|
190
|
+
* run. `runAgent` always opens with one, so this is reachable only by a
|
|
191
|
+
* caller writing entries itself.
|
|
192
|
+
*/
|
|
193
|
+
interrupted(input: {
|
|
194
|
+
signal?: AbortSignal;
|
|
195
|
+
}): Promise<Result<Runnable | undefined, StoreError>>;
|
|
196
|
+
/**
|
|
197
|
+
* Be told to look again, instead of asking on a timer.
|
|
198
|
+
*
|
|
199
|
+
* Optional, and honestly so: a store reached over a channel with no push —
|
|
200
|
+
* a file, a plain HTTP API — cannot offer this, and pretending otherwise
|
|
201
|
+
* would be a promise nothing keeps. A caller branches on its absence.
|
|
202
|
+
*
|
|
203
|
+
* **It is an interrupt line, not a feed of events.** A wake is a request to
|
|
204
|
+
* look, never a description of what to do. That is what makes it safe to be
|
|
205
|
+
* wrong about: a spurious wake costs one query, and a lost wake costs the
|
|
206
|
+
* heartbeat rather than the work.
|
|
207
|
+
*
|
|
208
|
+
* What is promised:
|
|
209
|
+
*
|
|
210
|
+
* - A watcher is called only once the change is readable through this store,
|
|
211
|
+
* so looking after a wake always finds at least what woke it.
|
|
212
|
+
* - A change committed through this store wakes this store's own watchers,
|
|
213
|
+
* including when the writer and the reader are the same process. That
|
|
214
|
+
* sounds obvious and is the defect an implementation actually shipped: it
|
|
215
|
+
* skipped its own notification to avoid an echo, and a delivery written by
|
|
216
|
+
* the surface woke the worker beside it not at all.
|
|
217
|
+
* - Unsubscribing is idempotent, and `close()` ends every watch. A wake
|
|
218
|
+
* already on its way when either is called is not delivered.
|
|
219
|
+
* - A watcher that throws is the caller's own bug. It does not fail the write
|
|
220
|
+
* that woke it and does not cost another watcher its wake; the error
|
|
221
|
+
* surfaces where an unhandled one does. That last part is deliberately not
|
|
222
|
+
* a conformance case, because a case that provokes it fails the run that
|
|
223
|
+
* asserts it.
|
|
224
|
+
*
|
|
225
|
+
* What is not:
|
|
226
|
+
*
|
|
227
|
+
* - **Delivery.** A connection that was down when a change landed loses that
|
|
228
|
+
* wake for good. A caller keeps a heartbeat; this removes latency, not the
|
|
229
|
+
* need to look.
|
|
230
|
+
* - **Reach.** How far a store sees is the store's own, and it says so where
|
|
231
|
+
* it can be held to it: the conformance subject declares `process` or
|
|
232
|
+
* `deployment`, and a feed claiming the second must prove a write on one
|
|
233
|
+
* connection wakes a watcher on another. Nothing branches on it at runtime,
|
|
234
|
+
* which is why it is not a field here — the heartbeat is mandatory either
|
|
235
|
+
* way, so the difference is latency, not correctness.
|
|
236
|
+
* - **One wake per change.** Several may arrive as one, and one may arrive
|
|
237
|
+
* twice.
|
|
238
|
+
* - **Ordering** between sessions, or against any other wake.
|
|
239
|
+
*/
|
|
240
|
+
watch?(watcher: (change: StoreChange) => void): () => void;
|
|
241
|
+
close(): Promise<void>;
|
|
242
|
+
}
|
|
243
|
+
/** Re-exported for the same reason the model port re-exports its own. */
|
|
244
|
+
export type { Delivery };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/store/store.ts"],"names":[],"mappings":"","sourcesContent":["import type { Delivery, Entry, Stored } from \"../session/entry.js\";\nimport type { Failure, Result } from \"../result.js\";\nimport type { JsonValue } from \"../json.js\";\n\nexport interface AgentRef { id: string; version: string }\n\nexport interface StoreError extends Failure {\n code: \"unavailable\" | \"not-found\" | \"conflict\" | \"failed\";\n}\n\n/** Someone else advanced this session first. Retry means re-read and re-decide, not re-send. */\nexport interface StoreConflict extends StoreError { code: \"conflict\"; actualSeq: number }\n\n/**\n * A session id and a run id are UUIDs.\n *\n * `runAgent` mints both with `crypto.randomUUID()` and the library never\n * produces anything else, so the only place another shape could enter is a\n * caller-supplied `sessionId` — and stating it is what lets a store keep them\n * in a `uuid` column, which is not a detail: it is sixteen bytes and index\n * locality on the hottest table a deployment has. Left unstated, a store that\n * did so was narrowing a contract nobody had written down.\n *\n * An application's own naming goes in `key`, which exists for exactly that and\n * is opaque here.\n */\nexport interface SessionRead {\n sessionId: string;\n agent: AgentRef;\n seq: number;\n metadata: JsonValue;\n entries: readonly Stored[];\n /** Undelivered input. Visible to any process, which is how a delivery to a busy session is noticed. */\n pending: readonly Delivery[];\n}\n\nexport interface SessionSummary {\n sessionId: string;\n agent: AgentRef;\n key: string | null;\n seq: number;\n metadata: JsonValue;\n updatedAt: string;\n}\n\nexport interface Runnable {\n sessionId: string;\n seq: number;\n /**\n * What was waiting, with provenance and priority.\n *\n * Reading does not consume: the queue is cleared by the append that commits\n * these as entries, in the same compare-and-swap. A worker that loses that\n * race therefore leaves the messages where it found them, instead of having\n * already destroyed them.\n */\n pending: readonly Delivery[];\n metadata: JsonValue;\n}\n\n/**\n * Which session changed, and whether it now has work owed to it.\n *\n * Deliberately not the change itself. A watcher cannot read state from this and\n * must not try: it says a session moved, and the only correct response is to\n * ask the store what it says now. Carrying the entries here would make a second\n * path to the log — one with no cursor, no ordering and no durability — beside\n * the one that has all three.\n */\nexport interface StoreChange {\n sessionId: string;\n /** Whether that session now has undelivered input. Not whether `next` would return it. */\n runnable: boolean;\n}\n\n/**\n * Ordered, atomically-appended session logs. Seven methods, and one optional.\n *\n * Two mechanisms, and they do different jobs. `expectedSeq` is the correctness\n * one: a write from a stale position loses and is told the real one, so no two\n * writers can interleave at the same position. The claim taken by `next` is the\n * exclusion one: it stops a second worker from starting a *second activation*\n * of a session that is already running.\n *\n * Both are needed, and one does not imply the other. Compare-and-swap alone\n * permits two activations to run concurrently at different positions, each\n * committing happily until one of them loses a race mid-turn — which leaves a\n * tool call asked and never answered, and destroys the messages the loser took.\n * That is a real failure, observed, not a theoretical one.\n *\n * The claim is deliberately small: no renewal, no fencing token. It expires on\n * its own so a worker that dies does not strand a session, and if that worker\n * turns out to be alive its writes still fail the compare-and-swap. The claim\n * saves work; the compare-and-swap is what makes the work safe.\n */\nexport interface Store {\n create(input: {\n sessionId: string;\n agent: AgentRef;\n /** Opaque application index key — a user, tenant, channel or parent session. Never interpreted. */\n key?: string;\n metadata?: JsonValue;\n }): Promise<Result<void, StoreError>>;\n\n read(input: { sessionId: string; afterSeq?: number }): Promise<Result<SessionRead, StoreError>>;\n\n /**\n * The one operation that makes orchestration safe. Entries, deliveries to\n * other sessions, and a metadata merge commit together or not at all — so a\n * handoff between agents can never be lost or duplicated.\n */\n append(input: {\n sessionId: string;\n expectedSeq: number;\n entries: readonly Entry[];\n enqueue?: readonly Delivery[];\n metadata?: JsonValue;\n /**\n * Remove this many deliveries from the front of this session's own queue,\n * in the same transaction. This is how input taken from `next` is consumed:\n * the messages are gone only once the entries carrying them are committed.\n * Anything that arrived since is behind them and survives.\n *\n * More than the queue holds is refused, never clamped. It is only ever\n * `claim.pending.length`, so a larger number means the caller is working\n * from a queue that is not there — and clamping it would drop messages\n * nothing recorded, which is the one loss this design exists to prevent.\n */\n takePending?: number;\n }): Promise<Result<{ seq: number }, StoreConflict | StoreError>>;\n\n /**\n * Sessions by the application's opaque key, newest first.\n *\n * `before` is a page boundary, and its shape is part of the contract because\n * a caller has to be able to build one: `\"<updatedAt>|<sessionId>\"`, taken\n * from the last row of the previous page. The id is in it because sessions\n * written in the same instant have no order without it, and a plain `<` on\n * the timestamp then steps over every row that shares the boundary. Left\n * unsaid, two stores answered it two different ways and one of them ignored\n * it entirely.\n */\n list(input: { key?: string; limit?: number; before?: string }): Promise<Result<readonly SessionSummary[], StoreError>>;\n\n /**\n * Claim the next session that has input and is not already running.\n *\n * The queue is reported, not taken — see `takePending`. `undefined` means\n * nothing is owed, everything owed is already being worked on, or the caller\n * gave up: a `signal` that has already aborted answers `undefined`, because\n * nothing is owed to somebody who stopped asking.\n */\n next(input: { signal?: AbortSignal }): Promise<Result<Runnable | undefined, StoreError>>;\n\n\n /**\n * Claim a session whose activation was interrupted: an open run whose claim\n * has lapsed, with nothing waiting to make it runnable the ordinary way.\n *\n * `next` answers what has been asked for, which is the right question almost\n * always. This is the other one — what was being worked when a process\n * stopped existing — and without it that work is invisible. `next` skips a\n * session with an open activation, on purpose; the queue that made it\n * runnable was consumed by the commit that recorded it; so a session whose\n * worker was killed mid-run is owed to nobody and waits for a stranger to\n * speak to it. Every application built on this rediscovers that, and the\n * store is the only thing that can see it.\n *\n * Separate from `next` rather than folded into it because resuming is a\n * decision, not a default: an application may want interrupted work finished\n * at once, or left for whoever speaks to the session next. `pending` is empty\n * by construction — a session with input waiting is `next`'s.\n *\n * Claimed on the same terms and with the same window. A run that commits\n * nothing at all for longer than `claimMs` looks the same as one whose\n * process died, here as in `next`. Two more consequences of that window,\n * both accepted:\n *\n * An interrupted run is invisible until its claim lapses, so a killed\n * worker's session waits out `claimMs` before anyone can pick it up. That is\n * the price of having no heartbeat and no fencing token.\n *\n * A store keeps one mark for \"claimed\" and \"an activation is open\", on\n * purpose — two fields could disagree, and the log is the only thing that\n * knows. The cost is that a session claimed by `next` whose worker committed\n * something other than `run.started` is indistinguishable from an interrupted\n * run. `runAgent` always opens with one, so this is reachable only by a\n * caller writing entries itself.\n */\n interrupted(input: { signal?: AbortSignal }): Promise<Result<Runnable | undefined, StoreError>>;\n\n /**\n * Be told to look again, instead of asking on a timer.\n *\n * Optional, and honestly so: a store reached over a channel with no push —\n * a file, a plain HTTP API — cannot offer this, and pretending otherwise\n * would be a promise nothing keeps. A caller branches on its absence.\n *\n * **It is an interrupt line, not a feed of events.** A wake is a request to\n * look, never a description of what to do. That is what makes it safe to be\n * wrong about: a spurious wake costs one query, and a lost wake costs the\n * heartbeat rather than the work.\n *\n * What is promised:\n *\n * - A watcher is called only once the change is readable through this store,\n * so looking after a wake always finds at least what woke it.\n * - A change committed through this store wakes this store's own watchers,\n * including when the writer and the reader are the same process. That\n * sounds obvious and is the defect an implementation actually shipped: it\n * skipped its own notification to avoid an echo, and a delivery written by\n * the surface woke the worker beside it not at all.\n * - Unsubscribing is idempotent, and `close()` ends every watch. A wake\n * already on its way when either is called is not delivered.\n * - A watcher that throws is the caller's own bug. It does not fail the write\n * that woke it and does not cost another watcher its wake; the error\n * surfaces where an unhandled one does. That last part is deliberately not\n * a conformance case, because a case that provokes it fails the run that\n * asserts it.\n *\n * What is not:\n *\n * - **Delivery.** A connection that was down when a change landed loses that\n * wake for good. A caller keeps a heartbeat; this removes latency, not the\n * need to look.\n * - **Reach.** How far a store sees is the store's own, and it says so where\n * it can be held to it: the conformance subject declares `process` or\n * `deployment`, and a feed claiming the second must prove a write on one\n * connection wakes a watcher on another. Nothing branches on it at runtime,\n * which is why it is not a field here — the heartbeat is mandatory either\n * way, so the difference is latency, not correctness.\n * - **One wake per change.** Several may arrive as one, and one may arrive\n * twice.\n * - **Ordering** between sessions, or against any other wake.\n */\n watch?(watcher: (change: StoreChange) => void): () => void;\n\n close(): Promise<void>;\n}\n\n/** Re-exported for the same reason the model port re-exports its own. */\nexport type { Delivery };\n"]}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { Decide, Tool, ToolExecutor } from "./tool.js";
|
|
2
|
+
import type { Delivery } from "../session/entry.js";
|
|
3
|
+
import type { ToolCall } from "../session/entry.js";
|
|
4
|
+
import type { JsonValue } from "../json.js";
|
|
5
|
+
/**
|
|
6
|
+
* The one place a tool call becomes an effect: parse, validate, decide, run,
|
|
7
|
+
* record. Failures are model-visible results, never throws — a model that gets
|
|
8
|
+
* an exception learns nothing, while one that gets "invalid arguments: x must
|
|
9
|
+
* be a number" fixes its next call.
|
|
10
|
+
*
|
|
11
|
+
* A denial is a result like any other, so the model reads why and can act on
|
|
12
|
+
* it. Nothing here parks a batch waiting on a human: see `Decide`.
|
|
13
|
+
*/
|
|
14
|
+
export declare function createExecutor(input: {
|
|
15
|
+
tools: readonly Tool[];
|
|
16
|
+
decide?: Decide;
|
|
17
|
+
sessionId: string;
|
|
18
|
+
runId: string;
|
|
19
|
+
enqueue(delivery: Delivery): void;
|
|
20
|
+
report(callId: string, data: JsonValue): void;
|
|
21
|
+
/** Adjacent read-only calls run together; this caps how many at once. */
|
|
22
|
+
maxConcurrency?: number;
|
|
23
|
+
}): ToolExecutor;
|
|
24
|
+
export type { ToolCall };
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The one place a tool call becomes an effect: parse, validate, decide, run,
|
|
3
|
+
* record. Failures are model-visible results, never throws — a model that gets
|
|
4
|
+
* an exception learns nothing, while one that gets "invalid arguments: x must
|
|
5
|
+
* be a number" fixes its next call.
|
|
6
|
+
*
|
|
7
|
+
* A denial is a result like any other, so the model reads why and can act on
|
|
8
|
+
* it. Nothing here parks a batch waiting on a human: see `Decide`.
|
|
9
|
+
*/
|
|
10
|
+
export function createExecutor(input) {
|
|
11
|
+
const byName = new Map();
|
|
12
|
+
for (const tool of input.tools) {
|
|
13
|
+
if (byName.has(tool.spec.name))
|
|
14
|
+
throw new Error(`duplicate tool '${tool.spec.name}'`);
|
|
15
|
+
byName.set(tool.spec.name, tool);
|
|
16
|
+
}
|
|
17
|
+
const limit = input.maxConcurrency ?? 8;
|
|
18
|
+
const list = () => [...byName.values()].map((tool) => tool.spec);
|
|
19
|
+
const failed = (content) => ({ content, isError: true });
|
|
20
|
+
return {
|
|
21
|
+
list,
|
|
22
|
+
async execute({ calls, signal }) {
|
|
23
|
+
const planned = [];
|
|
24
|
+
const seen = new Set();
|
|
25
|
+
for (const call of calls) {
|
|
26
|
+
const settled = (result) => ({ callId: call.callId, concurrent: true, run: async () => result });
|
|
27
|
+
if (seen.has(call.callId)) {
|
|
28
|
+
planned.push(settled(failed(`call id '${call.callId}' was reused`)));
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
seen.add(call.callId);
|
|
32
|
+
const tool = byName.get(call.name);
|
|
33
|
+
if (!tool) {
|
|
34
|
+
planned.push(settled(failed(`Unknown tool '${call.name}'`)));
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
let raw;
|
|
38
|
+
try {
|
|
39
|
+
raw = JSON.parse(call.arguments);
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
planned.push(settled(failed("Tool arguments are not valid JSON")));
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
const prepared = tool.prepare(raw);
|
|
46
|
+
if (!prepared.ok) {
|
|
47
|
+
planned.push(settled(prepared.error));
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
// Decisions always see parsed, schema-valid arguments — never the raw
|
|
51
|
+
// string, and never before validation.
|
|
52
|
+
const decision = input.decide
|
|
53
|
+
? await input.decide({
|
|
54
|
+
tool: tool.spec, input: prepared.value.input,
|
|
55
|
+
sessionId: input.sessionId, runId: input.runId, callId: call.callId,
|
|
56
|
+
})
|
|
57
|
+
: { action: "execute" };
|
|
58
|
+
if (decision.action === "reject") {
|
|
59
|
+
planned.push(settled(failed(`Tool use denied: ${decision.message}`)));
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
const context = {
|
|
63
|
+
sessionId: input.sessionId, runId: input.runId, callId: call.callId,
|
|
64
|
+
signal: signal ?? new AbortController().signal,
|
|
65
|
+
enqueue: input.enqueue,
|
|
66
|
+
report: (data) => input.report(call.callId, data),
|
|
67
|
+
};
|
|
68
|
+
const annotations = tool.spec.annotations;
|
|
69
|
+
planned.push({
|
|
70
|
+
callId: call.callId,
|
|
71
|
+
concurrent: annotations?.readOnly === true && annotations.sequential !== true,
|
|
72
|
+
run: async () => {
|
|
73
|
+
try {
|
|
74
|
+
return await prepared.value.run(context);
|
|
75
|
+
}
|
|
76
|
+
catch (error) {
|
|
77
|
+
return failed(error instanceof Error ? error.message : String(error));
|
|
78
|
+
}
|
|
79
|
+
},
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
const results = [];
|
|
83
|
+
let index = 0;
|
|
84
|
+
while (index < planned.length) {
|
|
85
|
+
if (signal?.aborted) {
|
|
86
|
+
for (const item of planned.slice(index)) {
|
|
87
|
+
results.push({ callId: item.callId, result: failed("Tool use cancelled") });
|
|
88
|
+
}
|
|
89
|
+
break;
|
|
90
|
+
}
|
|
91
|
+
let end = index + 1;
|
|
92
|
+
if (planned[index].concurrent) {
|
|
93
|
+
while (end < planned.length && planned[end].concurrent && end - index < limit)
|
|
94
|
+
end += 1;
|
|
95
|
+
}
|
|
96
|
+
const segment = planned.slice(index, end);
|
|
97
|
+
const settled = await Promise.all(segment.map((item) => item.run()));
|
|
98
|
+
segment.forEach((item, offset) => results.push({ callId: item.callId, result: settled[offset] }));
|
|
99
|
+
index = end;
|
|
100
|
+
}
|
|
101
|
+
return { results };
|
|
102
|
+
},
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
//# sourceMappingURL=execute.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"execute.js","sourceRoot":"","sources":["../../src/tools/execute.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Decide, Tool, ToolContext, ToolExecutor } from \"./tool.js\";\nimport type { Delivery } from \"../session/entry.js\";\nimport type { ToolCall, ToolResult } from \"../session/entry.js\";\nimport type { ToolSpec } from \"./tool.js\";\n\nimport type { JsonValue } from \"../json.js\";\n\n/**\n * The one place a tool call becomes an effect: parse, validate, decide, run,\n * record. Failures are model-visible results, never throws — a model that gets\n * an exception learns nothing, while one that gets \"invalid arguments: x must\n * be a number\" fixes its next call.\n *\n * A denial is a result like any other, so the model reads why and can act on\n * it. Nothing here parks a batch waiting on a human: see `Decide`.\n */\nexport function createExecutor(input: {\n tools: readonly Tool[];\n decide?: Decide;\n sessionId: string;\n runId: string;\n enqueue(delivery: Delivery): void;\n report(callId: string, data: JsonValue): void;\n /** Adjacent read-only calls run together; this caps how many at once. */\n maxConcurrency?: number;\n}): ToolExecutor {\n const byName = new Map<string, Tool>();\n for (const tool of input.tools) {\n if (byName.has(tool.spec.name)) throw new Error(`duplicate tool '${tool.spec.name}'`);\n byName.set(tool.spec.name, tool);\n }\n const limit = input.maxConcurrency ?? 8;\n const list = (): readonly ToolSpec[] => [...byName.values()].map((tool) => tool.spec);\n const failed = (content: string): ToolResult => ({ content, isError: true });\n\n return {\n list,\n async execute({ calls, signal }) {\n interface Planned {\n callId: string;\n concurrent: boolean;\n run(): Promise<ToolResult>;\n }\n const planned: Planned[] = [];\n const seen = new Set<string>();\n\n for (const call of calls) {\n const settled = (result: ToolResult): Planned =>\n ({ callId: call.callId, concurrent: true, run: async () => result });\n\n if (seen.has(call.callId)) { planned.push(settled(failed(`call id '${call.callId}' was reused`))); continue; }\n seen.add(call.callId);\n\n const tool = byName.get(call.name);\n if (!tool) { planned.push(settled(failed(`Unknown tool '${call.name}'`))); continue; }\n\n let raw: unknown;\n try { raw = JSON.parse(call.arguments); }\n catch { planned.push(settled(failed(\"Tool arguments are not valid JSON\"))); continue; }\n\n const prepared = tool.prepare(raw);\n if (!prepared.ok) { planned.push(settled(prepared.error)); continue; }\n\n // Decisions always see parsed, schema-valid arguments — never the raw\n // string, and never before validation.\n const decision = input.decide\n ? await input.decide({\n tool: tool.spec, input: prepared.value.input,\n sessionId: input.sessionId, runId: input.runId, callId: call.callId,\n })\n : { action: \"execute\" as const };\n\n if (decision.action === \"reject\") {\n planned.push(settled(failed(`Tool use denied: ${decision.message}`)));\n continue;\n }\n\n const context: ToolContext = {\n sessionId: input.sessionId, runId: input.runId, callId: call.callId,\n signal: signal ?? new AbortController().signal,\n enqueue: input.enqueue,\n report: (data) => input.report(call.callId, data),\n };\n const annotations = tool.spec.annotations;\n planned.push({\n callId: call.callId,\n concurrent: annotations?.readOnly === true && annotations.sequential !== true,\n run: async () => {\n try { return await prepared.value.run(context); }\n catch (error) { return failed(error instanceof Error ? error.message : String(error)); }\n },\n });\n }\n\n const results: { callId: string; result: ToolResult }[] = [];\n let index = 0;\n while (index < planned.length) {\n if (signal?.aborted) {\n for (const item of planned.slice(index)) {\n results.push({ callId: item.callId, result: failed(\"Tool use cancelled\") });\n }\n break;\n }\n let end = index + 1;\n if (planned[index]!.concurrent) {\n while (end < planned.length && planned[end]!.concurrent && end - index < limit) end += 1;\n }\n const segment = planned.slice(index, end);\n const settled = await Promise.all(segment.map((item) => item.run()));\n segment.forEach((item, offset) => results.push({ callId: item.callId, result: settled[offset]! }));\n index = end;\n }\n return { results };\n },\n };\n}\n\nexport type { ToolCall };\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC","sourcesContent":["export { defineTool } from \"./tool.js\";\nexport type { Decide, Tool, ToolContext, ToolExecutor, ToolSpec } from \"./tool.js\";\n"]}
|