zidane 5.13.13 → 5.13.16
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/dist/acp-cli.js +8 -7
- package/dist/acp-cli.js.map +1 -1
- package/dist/{acp-CqXcM2Km.js → acp-eGzYbNGF.js} +8 -8
- package/dist/{acp-CqXcM2Km.js.map → acp-eGzYbNGF.js.map} +1 -1
- package/dist/acp.d.ts +2 -2
- package/dist/acp.js +1 -1
- package/dist/{agent-NkKgz5Dh.d.ts → agent-CNIOsTUg.d.ts} +44 -2
- package/dist/agent-CNIOsTUg.d.ts.map +1 -0
- package/dist/{auth-CGTf8v1_.js → auth-D9rP8khI.js} +2 -2
- package/dist/{auth-CGTf8v1_.js.map → auth-D9rP8khI.js.map} +1 -1
- package/dist/chat/pure.d.ts +3 -3
- package/dist/chat.d.ts +6 -6
- package/dist/chat.js +3 -3
- package/dist/contexts/daytona.d.ts +22 -4
- package/dist/contexts/daytona.d.ts.map +1 -1
- package/dist/contexts/daytona.js +6 -5
- package/dist/contexts/daytona.js.map +1 -1
- package/dist/contexts/docker.js +2 -1
- package/dist/contexts/docker.js.map +1 -1
- package/dist/contexts/e2b.d.ts +2 -2
- package/dist/contexts/sandbox.d.ts +2 -0
- package/dist/contexts/sandbox.js +55 -0
- package/dist/contexts/sandbox.js.map +1 -0
- package/dist/{contexts-DHi8LPCp.js → contexts-BebciJyQ.js} +3 -53
- package/dist/contexts-BebciJyQ.js.map +1 -0
- package/dist/contexts.d.ts +2 -1
- package/dist/contexts.js +2 -1
- package/dist/{errors-BpPfMo_4.js → errors-DJUxZg9b.js} +3 -2
- package/dist/{errors-BpPfMo_4.js.map → errors-DJUxZg9b.js.map} +1 -1
- package/dist/eval.d.ts +1 -1
- package/dist/eval.js +3 -3
- package/dist/{fetch-url-Cgbq-HYx.js → fetch-url-CWE8X5OD.js} +2 -2
- package/dist/{fetch-url-Cgbq-HYx.js.map → fetch-url-CWE8X5OD.js.map} +1 -1
- package/dist/{glob-DCWXy_tr.js → glob-D56-KpBp.js} +2 -12
- package/dist/glob-D56-KpBp.js.map +1 -0
- package/dist/glob-shell-rJMoCIGb.js +21 -0
- package/dist/glob-shell-rJMoCIGb.js.map +1 -0
- package/dist/{headless-C6Idunwh.js → headless-HAFnYaDY.js} +6 -6
- package/dist/{headless-C6Idunwh.js.map → headless-HAFnYaDY.js.map} +1 -1
- package/dist/headless.d.ts +1 -1
- package/dist/headless.js +1 -1
- package/dist/{index-BgB_425D.d.ts → index-Bzh-W2RD.d.ts} +26 -8
- package/dist/index-Bzh-W2RD.d.ts.map +1 -0
- package/dist/{index-BFY7mcar.d.ts → index-DuB7Cf02.d.ts} +2 -2
- package/dist/{index-BFY7mcar.d.ts.map → index-DuB7Cf02.d.ts.map} +1 -1
- package/dist/index-HQJDOWvo.d.ts +7 -0
- package/dist/index-HQJDOWvo.d.ts.map +1 -0
- package/dist/index.d.ts +6 -5
- package/dist/index.js +12 -11
- package/dist/index.js.map +1 -1
- package/dist/{interpolate-ConAiXGy.js → interpolate-BtIgcCuz.js} +2 -2
- package/dist/{interpolate-ConAiXGy.js.map → interpolate-BtIgcCuz.js.map} +1 -1
- package/dist/{logger-LQmSBfD_.d.ts → logger-HOG4EGv6.d.ts} +2 -2
- package/dist/{logger-LQmSBfD_.d.ts.map → logger-HOG4EGv6.d.ts.map} +1 -1
- package/dist/{login-DE-_d045.js → login-CCA-1lgK.js} +2 -2
- package/dist/{login-DE-_d045.js.map → login-CCA-1lgK.js.map} +1 -1
- package/dist/{mcp-2OGi_NQu.js → mcp-Dn5W65Lv.js} +2 -2
- package/dist/{mcp-2OGi_NQu.js.map → mcp-Dn5W65Lv.js.map} +1 -1
- package/dist/mcp.d.ts +1 -1
- package/dist/mcp.js +1 -1
- package/dist/{messages-U_87Z7GH.js → messages-FUqY3pci.js} +2 -2
- package/dist/{messages-U_87Z7GH.js.map → messages-FUqY3pci.js.map} +1 -1
- package/dist/output/stream-json.d.ts +2 -2
- package/dist/output/stream-json.js +1 -1
- package/dist/output/terminal.d.ts +2 -2
- package/dist/{presets-eC4VwuHh.js → presets-DDRkelUs.js} +2 -2
- package/dist/{presets-eC4VwuHh.js.map → presets-DDRkelUs.js.map} +1 -1
- package/dist/presets.d.ts +2 -2
- package/dist/presets.js +1 -1
- package/dist/{providers-DyMPTo51.js → providers-BPVOGmde.js} +13 -5
- package/dist/providers-BPVOGmde.js.map +1 -0
- package/dist/providers.d.ts +1 -1
- package/dist/providers.js +2 -2
- package/dist/restate.d.ts +38 -2
- package/dist/restate.d.ts.map +1 -1
- package/dist/restate.js +22 -0
- package/dist/restate.js.map +1 -1
- package/dist/{index-CF15aqlk.d.ts → sandbox-B-bMq3K6.d.ts} +2 -5
- package/dist/sandbox-B-bMq3K6.d.ts.map +1 -0
- package/dist/session/sqlite.d.ts +1 -1
- package/dist/session/sqlite.js +1 -1
- package/dist/{session-DQ4bEncf.js → session-C0D4p0Gy.js} +2 -2
- package/dist/{session-DQ4bEncf.js.map → session-C0D4p0Gy.js.map} +1 -1
- package/dist/session.d.ts +1 -1
- package/dist/session.js +2 -2
- package/dist/skills.d.ts +2 -2
- package/dist/skills.js +1 -1
- package/dist/{tool-formatters-DvtGhbJN.d.ts → tool-formatters-B4Ll4Xpz.d.ts} +2 -2
- package/dist/{tool-formatters-DvtGhbJN.d.ts.map → tool-formatters-B4Ll4Xpz.d.ts.map} +1 -1
- package/dist/tools/fetch-url.d.ts +1 -1
- package/dist/tools/fetch-url.js +1 -1
- package/dist/tools/web-search.d.ts +1 -1
- package/dist/tools/web-search.js +2 -2
- package/dist/{tools-BvATiiCO.js → tools-BwqbsLcJ.js} +83 -26
- package/dist/tools-BwqbsLcJ.js.map +1 -0
- package/dist/tools.d.ts +2 -2
- package/dist/tools.js +1 -1
- package/dist/{transcript-anchors-DFmfOesU.d.ts → transcript-anchors-CRnGrkTd.d.ts} +4 -4
- package/dist/{transcript-anchors-DFmfOesU.d.ts.map → transcript-anchors-CRnGrkTd.d.ts.map} +1 -1
- package/dist/{transcript-anchors-Cn1Unhn-.js → transcript-anchors-dPvyuqmU.js} +9 -9
- package/dist/{transcript-anchors-Cn1Unhn-.js.map → transcript-anchors-dPvyuqmU.js.map} +1 -1
- package/dist/tui.d.ts +3 -3
- package/dist/tui.js +10 -10
- package/dist/tui.js.map +1 -1
- package/dist/{turn-operations-DWUN8cHo.d.ts → turn-operations-DYbhKmSu.d.ts} +3 -3
- package/dist/{turn-operations-DWUN8cHo.d.ts.map → turn-operations-DYbhKmSu.d.ts.map} +1 -1
- package/dist/types.d.ts +3 -3
- package/dist/types.js +1 -1
- package/docs/ARCHITECTURE.md +2 -0
- package/docs/CHAT.md +3 -3
- package/docs/RESTATE.md +58 -0
- package/docs/SKILL.md +1 -0
- package/docs/TUI.md +1 -1
- package/package.json +6 -1
- package/dist/agent-NkKgz5Dh.d.ts.map +0 -1
- package/dist/contexts-DHi8LPCp.js.map +0 -1
- package/dist/glob-DCWXy_tr.js.map +0 -1
- package/dist/index-BgB_425D.d.ts.map +0 -1
- package/dist/index-CF15aqlk.d.ts.map +0 -1
- package/dist/providers-DyMPTo51.js.map +0 -1
- package/dist/tools-BvATiiCO.js.map +0 -1
package/dist/restate.js
CHANGED
|
@@ -115,6 +115,13 @@ function restateBehavior(overrides = {}) {
|
|
|
115
115
|
disableBackgroundTasks: "non-durable",
|
|
116
116
|
cache: true,
|
|
117
117
|
shouldRethrowToolError: shouldRethrowRestateControlError,
|
|
118
|
+
compactStrategy: "tail",
|
|
119
|
+
compactThreshold: 128 * 1024,
|
|
120
|
+
compactKeepTurns: 8,
|
|
121
|
+
elideStaleReads: true,
|
|
122
|
+
mediaKeepTurns: 8,
|
|
123
|
+
toolOutputBudget: 64 * 1024,
|
|
124
|
+
autoCompact: { threshold: .85 },
|
|
118
125
|
...overrides
|
|
119
126
|
};
|
|
120
127
|
}
|
|
@@ -558,8 +565,10 @@ function suppressStreamingCallbacks(callbacks) {
|
|
|
558
565
|
function createReplayTracker(options = {}) {
|
|
559
566
|
let live = false;
|
|
560
567
|
let callbacks = [];
|
|
568
|
+
const resuming = options.resuming === true;
|
|
561
569
|
return {
|
|
562
570
|
isReplaying: () => !live,
|
|
571
|
+
isResuming: () => resuming && !live,
|
|
563
572
|
markLive: () => {
|
|
564
573
|
if (live) return;
|
|
565
574
|
live = true;
|
|
@@ -625,6 +634,12 @@ const KEY_RUNS = "session-runs";
|
|
|
625
634
|
*/
|
|
626
635
|
function restateSessionStore(ctx) {
|
|
627
636
|
let nextTurnSeq;
|
|
637
|
+
let warnedMismatch = false;
|
|
638
|
+
function guardSessionId(sessionId) {
|
|
639
|
+
if (warnedMismatch || sessionId === ctx.key) return;
|
|
640
|
+
warnedMismatch = true;
|
|
641
|
+
process.stderr.write(`[zidane/restate] restateSessionStore: sessionId "${sessionId}" != bound object key "${ctx.key}". This store ignores the sessionId and operates on the bound object — pass createSession({ id: ctx.key }) to silence this.\n`);
|
|
642
|
+
}
|
|
628
643
|
async function generateTurnId() {
|
|
629
644
|
if (nextTurnSeq === void 0) nextTurnSeq = (await ctx.get(KEY_TURNS) ?? []).length;
|
|
630
645
|
nextTurnSeq += 1;
|
|
@@ -639,6 +654,7 @@ function restateSessionStore(ctx) {
|
|
|
639
654
|
*/
|
|
640
655
|
generateTurnId,
|
|
641
656
|
async load(_sessionId) {
|
|
657
|
+
guardSessionId(_sessionId);
|
|
642
658
|
const header = await ctx.get(KEY_DATA);
|
|
643
659
|
const turns = sanitizeTurnsForState(await ctx.get(KEY_TURNS) ?? []);
|
|
644
660
|
const runs = sanitizeRunsForState(await ctx.get(KEY_RUNS) ?? []);
|
|
@@ -661,6 +677,7 @@ function restateSessionStore(ctx) {
|
|
|
661
677
|
};
|
|
662
678
|
},
|
|
663
679
|
async save(session) {
|
|
680
|
+
guardSessionId(session.id);
|
|
664
681
|
const { turns, runs, ...header } = session;
|
|
665
682
|
const prior = await ctx.get(KEY_DATA);
|
|
666
683
|
const now = await ctx.date.now();
|
|
@@ -673,6 +690,7 @@ function restateSessionStore(ctx) {
|
|
|
673
690
|
ctx.set(KEY_RUNS, sanitizeRunsForState(runs));
|
|
674
691
|
},
|
|
675
692
|
async delete(_sessionId) {
|
|
693
|
+
guardSessionId(_sessionId);
|
|
676
694
|
ctx.clear(KEY_DATA);
|
|
677
695
|
ctx.clear(KEY_TURNS);
|
|
678
696
|
ctx.clear(KEY_RUNS);
|
|
@@ -686,13 +704,16 @@ function restateSessionStore(ctx) {
|
|
|
686
704
|
return [];
|
|
687
705
|
},
|
|
688
706
|
async appendTurns(_sessionId, turns) {
|
|
707
|
+
guardSessionId(_sessionId);
|
|
689
708
|
const existing = sanitizeTurnsForState(await ctx.get(KEY_TURNS) ?? []);
|
|
690
709
|
ctx.set(KEY_TURNS, [...existing, ...sanitizeTurnsForState(turns)]);
|
|
691
710
|
},
|
|
692
711
|
async getTurns(_sessionId, from = 0, limit) {
|
|
712
|
+
guardSessionId(_sessionId);
|
|
693
713
|
return sanitizeTurnsForState(await ctx.get(KEY_TURNS) ?? []).slice(from, limit !== void 0 ? from + limit : void 0);
|
|
694
714
|
},
|
|
695
715
|
async updateRun(_sessionId, run) {
|
|
716
|
+
guardSessionId(_sessionId);
|
|
696
717
|
const runs = sanitizeRunsForState(await ctx.get(KEY_RUNS) ?? []);
|
|
697
718
|
const idx = runs.findIndex((r) => r.id === run.id);
|
|
698
719
|
const next = [...runs];
|
|
@@ -704,6 +725,7 @@ function restateSessionStore(ctx) {
|
|
|
704
725
|
ctx.set(KEY_RUNS, next);
|
|
705
726
|
},
|
|
706
727
|
async updateStatus(_sessionId, status) {
|
|
728
|
+
guardSessionId(_sessionId);
|
|
707
729
|
const header = await ctx.get(KEY_DATA);
|
|
708
730
|
const now = await ctx.date.now();
|
|
709
731
|
if (header) ctx.set(KEY_DATA, {
|
package/dist/restate.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"restate.js","names":[],"sources":["../src/restate/awakeable.ts","../src/restate/awakeable-tool.ts","../src/restate/errors.ts","../src/restate/behavior.ts","../src/restate/clock.ts","../src/restate/soft-errors.ts","../src/restate/tool.ts","../src/restate/mcp.ts","../src/restate/parallel.ts","../src/restate/provider.ts","../src/restate/replay.ts","../src/restate/session.ts","../src/restate/wait-background.ts"],"sourcesContent":["/**\n * Awakeable helpers — durable waits with deadlines.\n *\n * `awakeableWithTimeout` packages the canonical \"park until a resumer\n * fires, but not forever\" shape: an awakeable raced against a durable\n * `ctx.sleep(timeoutMs)` timer. The race itself survives process death —\n * on replay both branches resume from the journal and the same side\n * wins. This is the three-line building block for\n * `ExecutionContext.waitBackground` implementations on durable hosts\n * (runner fires task-exit → `resolveAwakeable(id, info)`; the timeout\n * branch maps to the seam's `null` return).\n */\n\nimport type { RestateAwakeable, RestateContextLike } from './types'\n\n/**\n * Structural subset of the SDK's `RestatePromise` static surface used by\n * {@link awakeableWithTimeout} — mirrors `RestatePromiseAllLike` from\n * `./parallel`. Pass `RestatePromise` from `@restatedev/restate-sdk` so\n * the race goes through the journaled combinator; native `Promise.race`\n * over two durable promises leaves the winner to the runtime's replay\n * ordering instead of an explicit journal entry.\n */\nexport interface RestatePromiseRaceLike<TPromise extends Promise<unknown> = Promise<unknown>> {\n race: (values: readonly TPromise[]) => Promise<unknown>\n}\n\nexport interface AwakeableWithTimeoutOptions<TPromise extends Promise<unknown> = Promise<unknown>> {\n /**\n * Durable deadline in milliseconds. Unset / non-positive = no timeout\n * (the returned awakeable is the plain `ctx.awakeable()` passthrough).\n */\n timeoutMs?: number\n /**\n * Durable race combinator — pass `RestatePromise` from the SDK. When\n * omitted, native `Promise.race` is used: correct at runtime and\n * replay-safe for THIS pattern (both branches are journaled\n * primitives), but the SDK combinator is the recommended belt-and-\n * braces choice for deterministic replay.\n */\n promises?: RestatePromiseRaceLike<TPromise>\n}\n\n/**\n * Mint an awakeable that resolves with the resumer's payload, or `null`\n * when `timeoutMs` elapses first. The id is journal-stable (send it\n * out-of-band as usual); the timeout is a durable `ctx.sleep`, so a\n * parked invocation suspends instead of holding a worker.\n *\n * Timeout surfaces as `null` — a resumer that resolves `undefined` is\n * indistinguishable from a timeout, so resolve a concrete payload.\n *\n * ```ts\n * // waitBackground for a durable host, in three lines:\n * const { id, promise } = awakeableWithTimeout<TaskExitInfo>(ctx, { timeoutMs, promises: RestatePromise })\n * await registerExitResumer(taskId, id) // runner → ctx.resolveAwakeable(id, info)\n * return await promise // TaskExitInfo, or null on timeout\n * ```\n */\nexport function awakeableWithTimeout<T, TPromise extends Promise<unknown> = Promise<unknown>>(\n ctx: RestateContextLike,\n options: AwakeableWithTimeoutOptions<TPromise> = {},\n): RestateAwakeable<T | null> {\n const awakeable = ctx.awakeable<T>()\n const timeoutMs = options.timeoutMs\n if (typeof timeoutMs !== 'number' || !Number.isFinite(timeoutMs) || timeoutMs <= 0)\n return awakeable\n\n const timer = ctx.sleep(timeoutMs)\n const raced = options.promises\n ? options.promises.race([awakeable.promise, timer] as readonly unknown[] as readonly TPromise[])\n : Promise.race<unknown>([awakeable.promise, timer])\n return {\n id: awakeable.id,\n // The sleep branch resolves `undefined`; normalize to the seam's\n // `null` so callers get one documented timeout sentinel.\n promise: raced.then(value => (value === undefined ? null : value as T)),\n }\n}\n","/**\n * Awakeable-backed tool — durable human/external-in-the-loop waits.\n *\n * Builds a `ToolDef` whose `execute` parks on a Restate awakeable: the\n * tool mints a journal-stable awakeable id, broadcasts it out-of-band\n * (webhook, queue, collab stream — the `notify` callback), and suspends\n * until a resumer calls `ctx.resolveAwakeable(id, value)` on the SDK\n * side. The classic shape for `ask_user` / `request_review` /\n * `wait_for_approval` tools inside durable handlers.\n *\n * Replay contract\n * ---------------\n * - **Broadcast-once-across-replays**: `notify` runs inside `ctx.run`,\n * so a crash + replay returns the journaled marker without re-sending\n * the notification. The user is pinged exactly once per tool call, no\n * matter how many times the worker restarts.\n * - **Marker invariant**: the journaled marker records the awakeable id\n * it was broadcast for. On replay the freshly-minted awakeable id must\n * match (the SDK derives awakeable ids deterministically from the\n * journal position); a mismatch means the journal and the code path\n * drifted — the tool throws instead of parking on an id nobody will\n * ever resolve.\n */\n\nimport type { ToolContext, ToolDef } from '../tools/types'\nimport type { ToolResultContent } from '../types'\nimport type { RestateContextLike, RestateRunOptions } from './types'\n\n/** Journaled broadcast marker — see \"Marker invariant\" in the module doc. */\ninterface AwakeableNotifyMarker {\n notified: true\n awakeableId: string\n}\n\nexport interface RestateAwakeableToolOptions<T = unknown> {\n /** Canonical tool name (what the model calls). */\n name: string\n /** Model-facing tool description. */\n description: string\n /** JSON schema for the tool input. */\n inputSchema: Record<string, unknown>\n /** The Restate context the awakeable + journal entries bind to. */\n ctx: RestateContextLike\n /**\n * Send the awakeable id (plus the call's input) out-of-band so a\n * resumer can later call `ctx.resolveAwakeable(awakeableId, value)`.\n * Runs inside `ctx.run` — fires exactly once across replays.\n */\n notify: (info: {\n awakeableId: string\n input: Record<string, unknown>\n toolCtx: ToolContext\n }) => void | Promise<void>\n /**\n * Map the resolved awakeable payload to the tool result. Default:\n * strings pass through, everything else is JSON-stringified.\n */\n toResult?: (value: T, input: Record<string, unknown>) => string | ToolResultContent[]\n /**\n * `ctx.run` options for the notify entry. Defaults to\n * `{ maxRetryAttempts: 1 }`, matching `restateTool`'s rationale.\n */\n runOptions?: RestateRunOptions\n /**\n * Concurrency-safety flag passed through to the `ToolDef`. Defaults to\n * `false` — a parked wait holding a scheduler slot should barrier.\n */\n isConcurrencySafe?: boolean\n}\n\n/**\n * Build a `ToolDef` that parks on a Restate awakeable until an external\n * resumer resolves it. See the module doc for the replay contract.\n *\n * Do NOT additionally wrap the returned tool in `restateTool` — the\n * journal discipline is already internal, and an outer `ctx.run` would\n * illegally nest the suspension point inside a journaled closure.\n */\nexport function restateAwakeableTool<T = unknown>(\n options: RestateAwakeableToolOptions<T>,\n): ToolDef {\n const { name, description, inputSchema, ctx, notify, toResult } = options\n const runOpts: RestateRunOptions = options.runOptions ?? { maxRetryAttempts: 1 }\n let seq = 0\n\n const execute = async (input: Record<string, unknown>, toolCtx: ToolContext): Promise<string | ToolResultContent[]> => {\n seq += 1\n // Mint BEFORE the journaled broadcast: the awakeable's journal\n // position precedes the notify entry, so on replay both come back\n // in the same order with the same id.\n const awakeable = ctx.awakeable<T>()\n\n const marker = await ctx.run<AwakeableNotifyMarker>(\n `awakeable-${name}-${seq}-notify`,\n async () => {\n await notify({ awakeableId: awakeable.id, input, toolCtx })\n return { notified: true, awakeableId: awakeable.id }\n },\n runOpts,\n )\n\n // Marker invariant — a drifted journal would otherwise park this\n // call on an id that was never broadcast (nobody will resolve it).\n if (marker.awakeableId !== awakeable.id) {\n throw new Error(\n `restateAwakeableTool(${name}): journal drift — broadcast marker carries awakeable \"${marker.awakeableId}\" but this replay minted \"${awakeable.id}\". The journal and the code path no longer line up; refusing to park on an unreachable awakeable.`,\n )\n }\n\n const value = await awakeable.promise\n if (toResult)\n return toResult(value, input)\n return typeof value === 'string' ? value : JSON.stringify(value)\n }\n\n return {\n spec: { name, description, inputSchema },\n ...(options.isConcurrencySafe !== undefined ? { isConcurrencySafe: options.isConcurrencySafe } : {}),\n execute,\n // The awakeable park IS the durable body — the loop's durable path\n // can use it directly without an extra wrapper.\n durableExecute: execute,\n }\n}\n","/**\n * Restate control-flow errors must escape the agent loop. If they are turned\n * into model-visible tool results, the runtime can retry/suspend incorrectly.\n *\n * Kept structural so `zidane/restate` does not need to import the SDK at\n * runtime just to recognize the common error shapes.\n */\nexport function shouldRethrowRestateControlError(error: unknown): boolean {\n if (!(error instanceof Error))\n return false\n\n const codeValue = Reflect.get(error, 'code')\n const code = typeof codeValue === 'number'\n ? codeValue\n : undefined\n if (code === 599)\n return true\n\n const name = error.name\n if (\n name === 'TerminalError'\n || name === 'TimeoutError'\n || name === 'CancelledError'\n || name === 'SuspendedError'\n ) {\n return true\n }\n\n const ctorName = error.constructor?.name\n const serializedCtorNameValue = Reflect.get(error, 'constructorName')\n const serializedCtorName = typeof serializedCtorNameValue === 'string'\n ? serializedCtorNameValue\n : undefined\n if (\n ctorName === 'TerminalError'\n || ctorName === 'TimeoutError'\n || ctorName === 'CancelledError'\n || ctorName === 'SuspendedError'\n || serializedCtorName === 'TerminalError'\n || serializedCtorName === 'TimeoutError'\n || serializedCtorName === 'CancelledError'\n || serializedCtorName === 'SuspendedError'\n ) {\n return true\n }\n\n return typeof name === 'string' && name.toLowerCase().includes('suspend')\n}\n","import type { AgentBehavior } from '../types'\nimport { shouldRethrowRestateControlError } from './errors'\n\n/**\n * Conservative behavior defaults for agents running inside Restate.\n *\n * The helper is opt-in and returns a plain AgentBehavior object, so callers can\n * spread or override it without changing non-Restate harness defaults.\n *\n * `disableBackgroundTasks: 'non-durable'` is capability-aware: background\n * tasks stay enabled for execution contexts whose\n * `capabilities.detachedTasks` is `'durable'` (tasks live on a remote\n * runner and survive worker crashes) and are disabled for everything\n * else (host-local processes don't survive process death). Hosts on\n * plain `ProcessContext` see the same effective behavior as the old\n * blanket `true`.\n */\nexport function restateBehavior(overrides: AgentBehavior = {}): AgentBehavior {\n return {\n maxConcurrentTools: 1,\n disableBackgroundTasks: 'non-durable',\n cache: true,\n shouldRethrowToolError: shouldRethrowRestateControlError,\n ...overrides,\n }\n}\n","/**\n * Restate-backed {@link AgentClock} — journals `now()` + `randomUUID()` so\n * `SessionTurn.createdAt`, `runId`, and fallback / synthetic turn ids stay\n * byte-identical across replays of the same invocation.\n *\n * Pass to `agent.run({ clock: restateClock(ctx) })` or bake it into\n * `createAgent({ clock: restateClock(ctx) })` for the duration of a\n * handler invocation. The clock holds a reference to `ctx`; do not reuse\n * a clock instance across invocations.\n */\n\nimport type { AgentClock } from '../types'\nimport type { RestateContextLike } from './types'\n\n/**\n * Wrap a Restate context's `date.now()` + `rand.uuidv4()` into the\n * {@link AgentClock} shape Zidane consumes for journaled metadata.\n *\n * The returned clock is a thin live view onto `ctx` — each call hits\n * the SDK afresh. No caching, no closure-captured values. Restate's\n * journal handles determinism on its end.\n */\nexport function restateClock(ctx: RestateContextLike): AgentClock {\n return {\n now: () => ctx.date.now(),\n randomUUID: () => ctx.rand.uuidv4(),\n }\n}\n","/**\n * Soft tool-error plumbing shared by {@link restateTool} and\n * {@link restateMcpToolWrap}.\n *\n * The problem: `restateTool` runs a tool body inside `ctx.run(...,\n * { maxRetryAttempts: 1 })`. An ordinary, recoverable tool throw (a failed\n * shell command, a transport error, an MCP `isError` result) would exhaust the\n * retry budget and surface as a Restate `TerminalError` — which\n * `restateBehavior`'s `shouldRethrowToolError` re-throws, aborting the whole\n * run. That's the opposite of the non-Restate model, where a tool throw becomes\n * a model-visible `tool_result { isError }` and the loop keeps going.\n *\n * The fix (same shape the MCP wrapper has always used): catch the recoverable\n * throw INSIDE the journaled closure and record it as a JSON-serializable\n * sentinel — so `ctx.run` journals a *value*, never a failed action. OUTSIDE the\n * journal (on both live and replay) the sentinel is turned back into a plain,\n * non-control `Error`, so the loop produces a `tool_result { isError }` and\n * continues. Real Restate control errors and deliberate aborts are never\n * softened — they must escape so the runtime can suspend / retry / cancel.\n */\n\nimport { shouldRethrowRestateControlError } from './errors'\n\n/** Journal value recorded for a softened tool throw. */\nconst SOFT_ERROR_KEY = '__zidaneRestateSoftError'\n\nexport interface SoftToolError {\n [SOFT_ERROR_KEY]: true\n message: string\n}\n\nexport function isSoftToolError(value: unknown): value is SoftToolError {\n return typeof value === 'object'\n && value !== null\n && (value as Record<string, unknown>)[SOFT_ERROR_KEY] === true\n}\n\n/** Build the sentinel recorded as the journal value for a softened throw. */\nexport function makeSoftToolError(error: unknown): SoftToolError {\n return { [SOFT_ERROR_KEY]: true, message: error instanceof Error ? error.message : String(error) }\n}\n\n/**\n * Recoverable throws soften; control-flow + abort throws do not.\n *\n * - Restate control errors (`TerminalError`, `SuspendedError`, …) must escape\n * so the runtime can act on them.\n * - Deliberate aborts (run cancel, `cancelTool`, sibling cascade) are a\n * timing-dependent, non-deterministic outcome — journaling one would bake it\n * into replay. The `signal.aborted` check also catches transports (the MCP\n * layer) that reject an aborted call with a plain `Error` carrying no\n * `AbortError` name.\n */\nexport function isRestateControlOrAbort(error: unknown, signal?: AbortSignal): boolean {\n if (shouldRethrowRestateControlError(error))\n return true\n if (error instanceof Error && error.name === 'AbortError')\n return true\n return signal?.aborted === true\n}\n\n/**\n * Outside-the-journal counterpart to {@link makeSoftToolError}: re-throw a\n * recorded sentinel as a plain (non-control) `Error`, else pass the value\n * through untouched.\n */\nexport function rethrowSoftToolError<T>(value: T): Exclude<T, SoftToolError> {\n if (isSoftToolError(value))\n throw new Error(value.message)\n return value as Exclude<T, SoftToolError>\n}\n","/**\n * Restate-backed tool wrappers.\n *\n * Wraps `ToolDef.execute` so every tool invocation is journaled. The\n * tool body runs on the original execution; after Restate persists the\n * journal entry, replay returns the recorded result without re-executing.\n * If the process dies before the entry is durable, the latest in-flight\n * tool can run again, so non-idempotent tools still need idempotency keys.\n *\n * `tool:gate`, `tool:transform`, `tool:after` hooks fire OUTSIDE the\n * journaled boundary, so they re-execute on replay. Built-in handlers\n * are deterministic given the journaled input + output (truncation,\n * image-stripping, `<edit-outcomes>` merge — all pure). Consumer hooks\n * that hit external services should themselves wrap side effects in\n * `ctx.run` so the substitution / annotation is replay-stable.\n *\n * `isConcurrencySafe` is preserved — Restate's per-key serialization\n * doesn't preclude in-handler parallelism. The loop's scheduler still\n * fans out safe tools up to `behavior.maxConcurrentTools`, each call\n * lands in its own journal entry. Order-of-journal-completion does NOT\n * affect replay correctness: Restate journals by call-site name, not\n * by completion order.\n */\n\nimport type { DetachedTasksCapability } from '../contexts'\nimport type { Session } from '../session'\nimport type { ToolContext, ToolDef } from '../tools/types'\nimport type { ToolResultContent } from '../types'\nimport type { RestatePromiseRaceLike } from './awakeable'\nimport type { RestatePromiseLike } from './parallel'\nimport type { ReplayTracker } from './replay'\nimport type { RestateContextLike, RestateRunOptions } from './types'\nimport { hydrateReadStateFromSessionAsync } from '../tools/read-state'\nimport { coerceToolResultContent } from '../types'\nimport { awakeableWithTimeout } from './awakeable'\nimport { isRestateControlOrAbort, makeSoftToolError, rethrowSoftToolError } from './soft-errors'\n\n/**\n * Opt-in two-phase journaling for long-running, re-attachable tools.\n *\n * The default `restateTool` wrapping journals only the COMPLETED result —\n * a crash mid-execute re-runs the tool on replay, which is unacceptable\n * for builds / migrations / deploys. `durableStart` splits the execution:\n *\n * 1. `start` runs inside its own `ctx.run` entry, journaled BEFORE the\n * body — it kicks off the side effect and returns a re-attach token\n * (a background task id, a job handle, an idempotency key).\n * 2. the wait — either `attach` (one `ctx.run` holding the wait in the\n * result entry; only for short, bounded waits) or `wait` (awakeable\n * park: register a resumer in a journaled entry, suspend outside\n * the journal, synthesize the result in a final entry). On replay\n * both receive the SAME token and re-attach to the already-running\n * work instead of starting it again.\n *\n * The wrapped tool's own `execute` is bypassed; the start + wait pair IS\n * the execution.\n */\nexport interface RestateDurableStart<Token = unknown, Resumed = unknown> {\n /** Kick off the side effect; journaled before `attach`. Must be cheap + idempotent-safe up to journal persistence. */\n start: (input: Record<string, unknown>, toolCtx: ToolContext) => Promise<Token> | Token\n /**\n * Await / re-attach to the work identified by `token` and produce the\n * tool result. Runs inside ONE `ctx.run` entry, so the body must\n * settle within the runtime's attempt lifecycle — a long busy-poll in\n * here starves the journal, trips the server's inactivity/abort\n * timeouts, and each retry restarts the wait from scratch. Use this\n * only for waits bounded well below the inactivity timeout (or as the\n * degraded mode on hosts without a push seam); prefer {@link wait}\n * for anything long-running.\n *\n * Required unless {@link wait} is provided; ignored when both are set.\n */\n attach?: (token: Token, input: Record<string, unknown>, toolCtx: ToolContext) => Promise<string | ToolResultContent[]>\n /**\n * Awakeable-based completion wait — the durable alternative to\n * {@link attach} for long-running work on hosts with a push seam\n * (e.g. a runner that fires `task:exit` → resumer → `ctx.resolveAwakeable`).\n * `executeTwoPhase` orchestrates three phases with the same journal\n * discipline as `restateAwakeableTool`:\n *\n * 1. `register` — a short, journaled `ctx.run`: hand the awakeable\n * id to the host as the exit resumer for `token`. Fires exactly\n * once across replays (marker invariant included).\n * 2. park — `await awakeable.promise`, OUTSIDE any `ctx.run`. The\n * invocation suspends cleanly: no held worker, immune to\n * inactivity/abort timeouts. With `timeoutMs`, the park is a\n * durable race against `ctx.sleep` (replay-stable — no\n * `Date.now()` deadline that resets per attempt).\n * 3. `result` — a final journaled `ctx.run`: synthesize the tool\n * result from the resumer payload (`null` = timeout; kill the\n * job and shape the timeout result here).\n */\n wait?: RestateDurableWait<Token, Resumed>\n /**\n * Best-effort cleanup when the per-call abort signal fires before the\n * wait settles — `attach` or the awakeable park alike (run abort,\n * `agent.cancelTool`, sibling-cascade\n * cancel, `agent.destroy()` mid-run). Without it, the journaled token\n * identifies a remote job that keeps running with nobody attached —\n * a leak for hosts whose jobs outlive the session.\n *\n * Contract:\n * - Fires at most once per call, outside the journal (an aborting\n * invocation can't open new `ctx.run` entries reliably) — journal\n * your own cleanup on the host side if it must be durable.\n * - May run concurrently with a still-unwinding `attach`; make it\n * idempotent against \"job already gone\".\n * - NOT called on process death — that's not termination: the\n * journaled token re-attaches on replay instead. This seam is for\n * deliberate aborts, where no replay is coming.\n * - Errors are swallowed (surfaced under `ZIDANE_DEBUG`) — cleanup\n * failure must not mask the abort itself.\n */\n onAbort?: (token: Token, input: Record<string, unknown>, toolCtx: ToolContext) => Promise<void> | void\n}\n\n/**\n * Awakeable-based completion wait for {@link RestateDurableStart.wait}.\n *\n * Replay contract (mirrors `restateAwakeableTool`):\n * - The awakeable is minted BEFORE the journaled `register` entry, so on\n * replay both come back in the same order with the same id — a replayed\n * call re-parks on the SAME awakeable without re-registering.\n * - The journaled marker records the awakeable id it was registered for;\n * a mismatch on replay (journal drift) throws instead of parking on an\n * id nobody will ever resolve.\n */\nexport interface RestateDurableWait<Token = unknown, Resumed = unknown> {\n /**\n * Register `awakeableId` as the exit resumer for the work identified\n * by `token` — the host must call `ctx.resolveAwakeable(awakeableId,\n * payload)` when the work completes. Runs inside `ctx.run`; must be\n * short and idempotent-safe up to journal persistence.\n */\n register: (token: Token, awakeableId: string, input: Record<string, unknown>, toolCtx: ToolContext) => Promise<void> | void\n /**\n * Synthesize the tool result once the park settles. `resumed` is the\n * resumer's payload, or `null` when `timeoutMs` elapsed first — kill\n * the still-running job and shape the timeout result in that branch.\n * Runs inside the final journaled `ctx.run` (the result entry).\n */\n result: (token: Token, resumed: Resumed | null, input: Record<string, unknown>, toolCtx: ToolContext) => Promise<string | ToolResultContent[]> | string | ToolResultContent[]\n /**\n * Durable park deadline in milliseconds — becomes the\n * `awakeableWithTimeout` duration (a `ctx.sleep` raced against the\n * awakeable, replay-stable). A function receives the call's input so\n * the model's own `timeout` parameter can drive it. Unset /\n * non-positive = park indefinitely.\n */\n timeoutMs?: number | ((input: Record<string, unknown>, toolCtx: ToolContext) => number | undefined)\n /**\n * Durable race combinator for the timeout race — pass `RestatePromise`\n * from the SDK. See `awakeableWithTimeout`'s rationale; native\n * `Promise.race` is the fallback.\n */\n promises?: RestatePromiseRaceLike\n /**\n * Per-call fast path: when this returns `true` for the journaled\n * `token`, the awakeable park is SKIPPED entirely — no awakeable is\n * minted, no `-register` entry is journaled, and the invocation never\n * suspends. `result` is invoked directly with `resumed = null` inside\n * the final result entry.\n *\n * This is for `start` phases that sometimes have nothing to wait on\n * (e.g. a shell tool that only spawns a real background task above a\n * duration threshold and otherwise runs the command inline in\n * `result`). Parking such calls pays a full suspend → resolve →\n * re-invoke → replay round-trip for nothing.\n *\n * MUST be a pure function of the journaled `token` (+ input) so the\n * decision is identical across replays — a token-derived branch keeps\n * the journal entry shape deterministic. When omitted, every call\n * parks (the original behaviour).\n */\n inline?: (token: Token, input: Record<string, unknown>, toolCtx: ToolContext) => boolean\n}\n\n/** Journaled registration marker — see the marker invariant in {@link RestateDurableWait}. */\ninterface DurableWaitRegisterMarker {\n registered: true\n awakeableId: string\n}\n\nexport interface RestateToolOptions<Token = unknown, Resumed = unknown> {\n /**\n * `ctx.run` options forwarded on every wrapped tool call. Defaults to\n * `{ maxRetryAttempts: 1 }` — tool errors are typically deterministic\n * (validation failures, missing files) so blind retries waste budget.\n * Override per-tool for network-heavy custom tools that benefit from\n * SDK-level retries.\n */\n runOptions?: RestateRunOptions\n /**\n * Override the journal-entry name. Receives the canonical tool name, the\n * call's input, and the model's `callId` (when the runtime provides one).\n * Default: `tool-<name>-<seq>` where `<seq>` is a per-wrapper monotonic\n * counter. The counter is replay-stable as long as dispatch order is\n * deterministic; key on `callId` instead for a model-deterministic name\n * that's robust even under `maxConcurrentTools > 1`.\n */\n entryName?: (seq: number, name: string, input: Record<string, unknown>, callId?: string) => string\n /**\n * Hide and reject the built-in shell tool's background mode.\n *\n * Default: derived from {@link RestateToolOptions.detachedTasks} —\n * disabled unless the execution context declares `'durable'` detached\n * tasks. An explicit boolean always wins.\n */\n disableShellBackground?: boolean\n /**\n * `detachedTasks` capability of the execution context the agent will\n * run with (see `ContextCapabilities.detachedTasks` /\n * `resolveDetachedTasksCapability`). Drives the\n * `disableShellBackground` default: a `'durable'` context keeps its\n * background tasks across worker crashes, so the wrapper leaves the\n * shell tool's background mode intact.\n *\n * Default: `undefined`, treated as non-durable (background disabled).\n */\n detachedTasks?: DetachedTasksCapability\n /**\n * Two-phase start/attach journaling for crash-safe long tools — see\n * {@link RestateDurableStart}. Per-tool by nature; not accepted by\n * `wrapAgentTools` (a single start/attach pair can't fit a whole map).\n */\n durableStart?: RestateDurableStart<Token, Resumed>\n /**\n * Per-invocation replay tracker (see `createReplayTracker`). When set,\n * the wrapper marks it live from inside its journaled closures — i.e.\n * the first time a tool body (or a `durableStart.start` phase)\n * ACTUALLY executes rather than replaying from the journal. Share one\n * tracker across the provider and tool wrappers of the same handler\n * invocation.\n */\n replayTracker?: ReplayTracker\n /**\n * Keep an ordinary, recoverable tool throw (a failed shell command, a\n * transport error, an MCP `isError`) NON-fatal under Restate.\n *\n * Without this, the throw rides out of the journaled `ctx.run` action,\n * exhausts the retry budget, and surfaces as a Restate `TerminalError` —\n * which `restateBehavior`'s `shouldRethrowToolError` re-throws, aborting the\n * whole run. With it, the throw is captured INSIDE the journal as a sentinel\n * value and re-thrown as a plain (non-control) error OUTSIDE it, so the loop\n * produces a model-visible `tool_result { isError }` and continues —\n * identical to the non-Restate soft-error model, and the same mechanism\n * `restateMcpToolWrap` already applies to MCP tools. Real Restate control\n * errors and deliberate aborts are never softened.\n *\n * Applies to the single-phase journaling path (the default wrapping and the\n * MCP path). The two-phase {@link RestateToolOptions.durableStart} mode owns\n * its own start/wait error shape and is unaffected.\n *\n * Default: `true`.\n */\n softErrors?: boolean\n /**\n * Collapse malformed structured result blocks (`{ type: 'image' }` with no\n * payload, foreign block shapes) to a text placeholder before the result is\n * journaled, so a downstream provider wire serializer never has to project an\n * unprojectable block (which, under Restate, would throw inside the journaled\n * provider call and become fatal). Well-formed results pass through\n * untouched. Applies to the single-phase journaling path.\n *\n * Default: `true`.\n */\n coerceResultBlocks?: boolean\n}\n\nconst SHELL_BACKGROUND_DISABLED_MESSAGE = 'shell error: background mode is disabled for Restate-backed agents. Fall back to foreground (drop `run_in_background`).'\nconst HYDRATED_READ_STATE_SESSIONS = new WeakSet<Session>()\n\n/**\n * Wrap a single `ToolDef` so its `execute` runs inside `ctx.run`. The\n * tool's `spec` and `isConcurrencySafe` pass through unchanged.\n */\nexport function restateTool<Token = unknown, Resumed = unknown>(\n inner: ToolDef,\n ctx: RestateContextLike,\n options: RestateToolOptions<Token, Resumed> = {},\n): ToolDef {\n const runOpts: RestateRunOptions = options.runOptions ?? { maxRetryAttempts: 1 }\n const nameFor = options.entryName ?? ((seq: number, name: string) => `tool-${name}-${seq}`)\n const canonicalName = inner.spec.name\n const disableShellBackground = options.disableShellBackground ?? (options.detachedTasks !== 'durable')\n const shellBackgroundDisabled = disableShellBackground && canonicalName === 'shell'\n const durableStart = options.durableStart\n if (durableStart && !durableStart.attach && !durableStart.wait)\n throw new Error(`restateTool(${canonicalName}): durableStart needs an \\`attach\\` (in-journal wait) or a \\`wait\\` (awakeable park) phase`)\n let seq = 0\n const hydrateOnce = async (toolCtx: Parameters<ToolDef['execute']>[1]) => {\n if (toolCtx.session && !HYDRATED_READ_STATE_SESSIONS.has(toolCtx.session)) {\n HYDRATED_READ_STATE_SESSIONS.add(toolCtx.session)\n await hydrateReadStateFromSessionAsync(toolCtx.session, toolCtx.handle.cwd, {\n defaultLineNumbers: toolCtx.behavior?.readLineNumbers ?? true,\n readFileForHash: async (path) => {\n try {\n return await toolCtx.execution.readFile(toolCtx.handle, path)\n }\n catch {\n return null\n }\n },\n })\n }\n }\n const softErrors = options.softErrors ?? true\n const coerceBlocks = options.coerceResultBlocks ?? true\n\n // The journaled action. NOT async, and the raw `ctx.run` promise is returned\n // without native combinators so `durableExecute` consumers (the Restate\n // batch scheduler) keep the runtime's own promise shape (`.map`) intact.\n //\n // Soft errors are captured INSIDE the closure: a recoverable throw is\n // recorded as a sentinel *value*, never a failed action — that's what keeps\n // `ctx.run` from promoting it to a fatal `TerminalError`. The sentinel is\n // turned back into a throw OUTSIDE the journal (see `executeDurably` /\n // `durableExecuteImpl`). Control / abort throws are never softened.\n const runJournaled = (input: Record<string, unknown>, toolCtx: Parameters<ToolDef['execute']>[1]) => {\n seq += 1\n return ctx.run(\n nameFor(seq, canonicalName, input, toolCtx.callId),\n async () => {\n // Closure executes only when live — replays return the journaled\n // result without entering here.\n options.replayTracker?.markLive()\n await hydrateOnce(toolCtx)\n if (shellBackgroundDisabled && input.run_in_background === true)\n return SHELL_BACKGROUND_DISABLED_MESSAGE\n if (!softErrors) {\n const out = await inner.execute(input, toolCtx)\n return coerceBlocks ? coerceToolResultContent(out) : out\n }\n try {\n const out = await inner.execute(input, toolCtx)\n return coerceBlocks ? coerceToolResultContent(out) : out\n }\n catch (err) {\n if (isRestateControlOrAbort(err, toolCtx.signal as AbortSignal | undefined))\n throw err\n return makeSoftToolError(err) as unknown as string\n }\n },\n runOpts,\n )\n }\n\n // Plain `execute`: await the journaled value and re-throw a captured soft\n // error outside the journal. When soft errors are off, the raw mappable\n // promise is the execute (unchanged legacy shape).\n const executeDurably: ToolDef['execute'] = softErrors\n ? async (input, toolCtx) => rethrowSoftToolError(await runJournaled(input, toolCtx))\n : runJournaled\n\n // `durableExecute`: compose the same soft-error unwrap INTO the runtime's\n // mappable promise so the batch scheduler still receives a `.map`-able value.\n // A softened throw becomes a rejected mapped promise, which the scheduler\n // routes to a `tool_result { isError }` (never fatal). Falls back to the raw\n // promise on a non-mappable ctx so the loop's durable guard can report it.\n const durableExecuteImpl: ToolDef['durableExecute'] = softErrors\n ? (input, toolCtx) => unwrapDurableSoftError(runJournaled(input, toolCtx))\n : runJournaled\n\n // Two-phase mode: journal the start token BEFORE the body so a crash\n // mid-execution re-attaches on replay instead of re-running. The await\n // between the two entries makes this a native-async composition, so the\n // tool deliberately does NOT advertise `durableExecute` — the batch\n // scheduler runs it sequentially via plain `execute`, which is the\n // right shape for long re-attachable work anyway.\n const executeTwoPhase = async (input: Record<string, unknown>, toolCtx: Parameters<ToolDef['execute']>[1]) => {\n const start = durableStart!\n seq += 1\n const entry = nameFor(seq, canonicalName, input, toolCtx.callId)\n const token = await ctx.run(\n `${entry}-start`,\n async () => {\n options.replayTracker?.markLive()\n await hydrateOnce(toolCtx)\n return start.start(input, toolCtx)\n },\n runOpts,\n )\n\n // Abort seam — see RestateDurableStart.onAbort. At-most-once via the\n // `fired` latch; armed only while the wait is in flight.\n const onAbort = start.onAbort\n const signal = toolCtx.signal as AbortSignal | undefined\n let fired = false\n const fireAbortCleanup = (): void => {\n if (fired || !onAbort)\n return\n fired = true\n Promise.resolve(onAbort(token, input, toolCtx)).catch((err: unknown) => {\n if (process.env.ZIDANE_DEBUG)\n process.stderr.write(`[zidane/restate] durableStart onAbort threw: ${err instanceof Error ? err.message : String(err)}\\n`)\n })\n }\n\n const wait = start.wait\n if (wait) {\n // Per-call fast path: nothing to wait on for this token (decided\n // purely from the journaled token, so replay-stable). Skip minting\n // the awakeable, the `-register` entry, and the suspend/resume\n // round-trip entirely — run the result inline. A short command that\n // executes in the result entry shouldn't pay a park it never uses.\n if (wait.inline?.(token, input, toolCtx)) {\n if (!onAbort || !signal) {\n return await ctx.run(entry, () => {\n options.replayTracker?.markLive()\n return wait.result(token, null, input, toolCtx)\n }, runOpts)\n }\n if (signal.aborted)\n fireAbortCleanup()\n else\n signal.addEventListener('abort', fireAbortCleanup, { once: true })\n try {\n return await ctx.run(entry, () => {\n options.replayTracker?.markLive()\n return wait.result(token, null, input, toolCtx)\n }, runOpts)\n }\n finally {\n signal.removeEventListener('abort', fireAbortCleanup)\n }\n }\n // Awakeable path — register / park / result. The park lives\n // OUTSIDE any ctx.run, so the invocation suspends cleanly instead\n // of busy-holding an attempt until the inactivity timeout fires.\n //\n // Pre-aborted: nobody will consume the result — clean up the\n // journaled start and bail without registering a resumer.\n if (signal?.aborted) {\n fireAbortCleanup()\n throw new Error(`${canonicalName}: aborted before durable wait registration`)\n }\n signal?.addEventListener('abort', fireAbortCleanup, { once: true })\n try {\n const timeoutMs = typeof wait.timeoutMs === 'function' ? wait.timeoutMs(input, toolCtx) : wait.timeoutMs\n // Mint BEFORE the journaled registration (same ordering contract\n // as restateAwakeableTool) — replay returns the same id.\n const awakeable = awakeableWithTimeout<Resumed>(ctx, {\n ...(timeoutMs !== undefined ? { timeoutMs } : {}),\n ...(wait.promises ? { promises: wait.promises } : {}),\n })\n const marker = await ctx.run<DurableWaitRegisterMarker>(\n `${entry}-register`,\n async () => {\n options.replayTracker?.markLive()\n await wait.register(token, awakeable.id, input, toolCtx)\n return { registered: true, awakeableId: awakeable.id }\n },\n runOpts,\n )\n if (marker.awakeableId !== awakeable.id) {\n throw new Error(\n `restateTool(${canonicalName}): journal drift — registration marker carries awakeable \"${marker.awakeableId}\" but this replay minted \"${awakeable.id}\". Refusing to park on an unreachable awakeable.`,\n )\n }\n const resumed = await parkWithSignal(awakeable.promise, signal, canonicalName)\n return await ctx.run(\n entry,\n () => {\n options.replayTracker?.markLive()\n return wait.result(token, resumed, input, toolCtx)\n },\n runOpts,\n )\n }\n finally {\n signal?.removeEventListener('abort', fireAbortCleanup)\n }\n }\n\n const attach = () => ctx.run(\n entry,\n () => {\n options.replayTracker?.markLive()\n return start.attach!(token, input, toolCtx)\n },\n runOpts,\n )\n\n if (!onAbort || !signal)\n return attach()\n\n // Pre-aborted: the journaled start already launched the job — clean\n // it up, then still run attach so the call surfaces the host's own\n // cancellation shape (it should fail fast on an aborted signal).\n if (signal.aborted) {\n fireAbortCleanup()\n return attach()\n }\n signal.addEventListener('abort', fireAbortCleanup, { once: true })\n try {\n return await attach()\n }\n finally {\n signal.removeEventListener('abort', fireAbortCleanup)\n }\n }\n\n if (durableStart) {\n // Strip any pre-existing `durableExecute` — see the executeTwoPhase\n // comment; advertising one here would hand the batch scheduler a\n // native promise it can't `.map`.\n const { durableExecute: _dropped, ...rest } = inner\n return {\n ...rest,\n spec: shellBackgroundDisabled ? withoutShellBackgroundInput(inner.spec) : inner.spec,\n execute: executeTwoPhase,\n }\n }\n\n return {\n ...inner,\n spec: shellBackgroundDisabled ? withoutShellBackgroundInput(inner.spec) : inner.spec,\n execute: executeDurably,\n durableExecute: durableExecuteImpl,\n }\n}\n\n/**\n * Compose the soft-error unwrap into the runtime's mappable durable promise.\n * A journaled sentinel becomes a thrown (rejected) value so the Restate batch\n * scheduler classifies it as a tool failure → `tool_result { isError }`; a real\n * action failure (control error) is rethrown verbatim. Non-mappable promises\n * (a ctx without the SDK's `RestatePromise`) pass through so the loop's durable\n * guard surfaces the \"not a mappable durable promise\" error instead.\n */\nfunction unwrapDurableSoftError(\n promise: Promise<string | ToolResultContent[]>,\n): Promise<string | ToolResultContent[]> {\n const mappable = promise as Partial<RestatePromiseLike<string | ToolResultContent[]>>\n if (typeof mappable.map !== 'function')\n return promise\n return mappable.map((value, failure) => {\n if (failure !== undefined)\n throw failure instanceof Error ? failure : new Error(String(failure))\n return rethrowSoftToolError(value as string | ToolResultContent[])\n })\n}\n\n/**\n * Park on `promise`, but stop waiting when the per-call abort signal\n * fires (run abort, `cancelTool`, sibling-cascade cancel) — a deliberate\n * abort means nobody will consume the result, and like `onAbort` it\n * implies no replay is coming, so the native (non-journaled) race is\n * replay-safe. The underlying awakeable stays registered; a late\n * resolution lands on a completed invocation and is dropped by the\n * runtime.\n */\nfunction parkWithSignal<T>(promise: Promise<T>, signal: AbortSignal | undefined, name: string): Promise<T> {\n if (!signal)\n return promise\n if (signal.aborted)\n return Promise.reject(new Error(`${name}: aborted while parked on durable wait`))\n return new Promise<T>((resolve, reject) => {\n const onAbortEvt = (): void => reject(new Error(`${name}: aborted while parked on durable wait`))\n signal.addEventListener('abort', onAbortEvt, { once: true })\n promise.then(\n (value) => {\n signal.removeEventListener('abort', onAbortEvt)\n resolve(value)\n },\n (err: unknown) => {\n signal.removeEventListener('abort', onAbortEvt)\n reject(err instanceof Error ? err : new Error(String(err)))\n },\n )\n })\n}\n\nfunction withoutShellBackgroundInput(spec: ToolDef['spec']): ToolDef['spec'] {\n const inputSchema = spec.inputSchema\n const properties = isRecord(inputSchema.properties) ? inputSchema.properties : undefined\n if (!properties || !Object.hasOwn(properties, 'run_in_background'))\n return spec\n\n const { run_in_background: _runInBackground, ...nextProperties } = properties\n const required = Array.isArray(inputSchema.required)\n ? inputSchema.required.filter(name => name !== 'run_in_background')\n : inputSchema.required\n return {\n ...spec,\n description: stripShellBackgroundDescription(spec.description),\n inputSchema: {\n ...inputSchema,\n properties: nextProperties,\n ...(required !== inputSchema.required ? { required } : {}),\n },\n }\n}\n\nfunction stripShellBackgroundDescription(description: string): string {\n return description\n .split('\\n')\n .filter(line =>\n !line.includes('run_in_background')\n && !line.includes('<task-notification>')\n && !line.includes('background task'),\n )\n .join('\\n')\n .replace(/\\n{3,}/g, '\\n\\n')\n .trim()\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n\n/**\n * Wrap an entire tool map at once — convenience for the common case of\n * \"journal every tool the agent has\". Pass-through for tools whose\n * names are listed in `opts.exclude` (e.g. fully-deterministic local\n * helpers where journaling is pure overhead).\n *\n * The returned map is a fresh object; the input is untouched.\n */\nexport function wrapAgentTools(\n tools: Record<string, ToolDef>,\n ctx: RestateContextLike,\n opts: Omit<RestateToolOptions, 'durableStart'> & { exclude?: readonly string[] } = {},\n): Record<string, ToolDef> {\n const excludeSet = new Set(opts.exclude ?? [])\n // `detachedTasks: 'durable'` implies the host's `waitBackground` parks\n // on an awakeable (that's the durable wait pattern) — and a Restate\n // suspension point must NOT nest inside a journaled `ctx.run` closure.\n // Auto-exclude the built-in `wait_task` from wrapping so its park runs\n // outside the journal; the wait result is replay-safe anyway (a replayed\n // wait re-attaches to an already-terminated task and resolves from the\n // registry). Hosts with a journal-safe wait (e.g. a bridge RPC poll)\n // can re-wrap explicitly via `restateTool(waitTask, ctx, …)`.\n const skipWaitTask = opts.detachedTasks === 'durable'\n const wrapped: Record<string, ToolDef> = {}\n for (const [name, def] of Object.entries(tools)) {\n const passThrough = excludeSet.has(name) || (skipWaitTask && def.spec.name === 'wait_task')\n wrapped[name] = passThrough ? def : restateTool(def, ctx, opts)\n }\n return wrapped\n}\n","/**\n * Restate-backed MCP tool journaling.\n *\n * Native tools have a clean durability seam: wrap them with\n * `wrapAgentTools(tools, ctx)` before `createAgent`. MCP tools don't — they are\n * discovered from `mcpServers` and registered by the agent internally, AFTER\n * your wrapping opportunity. So under Restate their raw `callTool` never rides\n * `ctx.run`, and every journal replay re-runs the real MCP call (a\n * side-effecting tool fires once per replay).\n *\n * {@link restateMcpToolWrap} closes that gap. It's the value for the core\n * `AgentOptions.mcpToolWrap` hook — the agent keeps owning discovery,\n * `mcp_<server>_<tool>` namespacing, per-server `instructions`, hooks, and\n * OAuth, and applies the wrap to each discovered tool. You journal MCP results\n * the way `wrapAgentTools` journals native ones:\n *\n * ```ts\n * createAgent({\n * provider: restateProvider(inner, ctx),\n * tools: wrapAgentTools(nativeTools, ctx),\n * mcpServers,\n * mcpToolWrap: restateMcpToolWrap(ctx),\n * })\n * ```\n *\n * The hook composes with any `mcpConnector`, so a custom transport / auth\n * connector and journaling stay orthogonal — no separate connector helper\n * needed:\n *\n * ```ts\n * createAgent({\n * mcpServers,\n * mcpConnector: (configs, hooks) => connectMcpServers(configs, undefined, hooks, { buildAuthProvider }),\n * mcpToolWrap: restateMcpToolWrap(ctx),\n * })\n * ```\n *\n * ## Error semantics (preserved)\n *\n * MCP tools signal failure by THROWING (`buildMcpToolDef` throws on transport\n * errors, timeouts, and `CallToolResult.isError`). Naively wrapping that in\n * `restateTool` would let the throw exhaust `ctx.run`'s retries and surface as\n * a Restate `TerminalError`, which `restateBehavior`'s `shouldRethrowToolError`\n * re-throws — turning a recoverable MCP error into a fatal run. To keep the\n * non-Restate behaviour (MCP error → model-visible `tool_result { isError }`,\n * run continues) the wrapper journals with `restateTool`'s `softErrors`: the\n * failure is captured INSIDE the journaled closure as a sentinel value and\n * re-thrown as a plain (non-control) error OUTSIDE it. Replay reproduces the\n * same error from the journal without re-running the call; real Restate control\n * / abort errors are passed through untouched. (Native tools wrapped with\n * `wrapAgentTools` get the identical treatment — this is no longer MCP-specific\n * plumbing, just the shared default.)\n *\n * ## Journaling policy\n *\n * Default is plain result-journaling — correct for the short request/response\n * shape of most MCP calls. A genuinely long-running MCP tool (a remote build,\n * a migration) can opt into two-phase `durableStart` per-tool via\n * {@link RestateMcpToolWrapOptions.override}; `exclude` skips journaling for\n * deterministic reads.\n */\n\nimport type { McpToolMeta, McpToolWrap } from '../agent'\nimport type { ToolDef } from '../tools/types'\nimport type { ReplayTracker } from './replay'\nimport type { RestateToolOptions } from './tool'\nimport type { RestateContextLike, RestateRunOptions } from './types'\nimport { restateTool } from './tool'\n\nexport interface RestateMcpToolWrapOptions {\n /**\n * Shared per-invocation replay tracker (see `createReplayTracker`) —\n * threaded into every wrapped MCP tool so the first live `callTool` marks\n * the tracker live, exactly like `restateProvider` / `wrapAgentTools`. Use\n * one tracker per handler invocation across provider + native + MCP tools.\n */\n replayTracker?: ReplayTracker\n /**\n * `ctx.run` options forwarded to every wrapped MCP tool (default\n * `{ maxRetryAttempts: 1 }`). Note: recoverable MCP failures are\n * soft-captured as the journal value rather than thrown, so this retry\n * budget governs only Restate control-flow retries of the journaled action,\n * not re-dialing a failed MCP call — the model decides whether to retry.\n */\n runOptions?: RestateRunOptions\n /**\n * Override the journal-entry name per MCP tool call. Default:\n * `tool-<name>-<callId>` (model-deterministic, robust under concurrency)\n * falling back to `tool-<name>-<seq>` when the runtime provides no `callId`.\n */\n entryName?: (seq: number, name: string, input: Record<string, unknown>, callId?: string) => string\n /**\n * Namespaced MCP tool names (`mcp_<server>_<tool>`) to leave un-journaled —\n * they pass through exactly as discovered. For deterministic,\n * side-effect-free reads where journaling is pure overhead. Wins over\n * {@link override}.\n */\n exclude?: readonly string[]\n /**\n * Per-tool wrapping override. Receives the discovered tool + its\n * {@link McpToolMeta}; return a `ToolDef` to use verbatim (e.g.\n * `restateTool(tool, ctx, { durableStart })` for a long-running tool), or\n * `undefined` to fall through to the default soft-error result-journaling.\n * Lets a deployment opt specific tools into a different policy without\n * changing the blanket one.\n */\n override?: (tool: ToolDef, meta: McpToolMeta) => ToolDef | undefined\n}\n\n/**\n * Journal one discovered MCP tool via `restateTool` with `softErrors` on (a\n * recoverable MCP throw becomes a journaled `tool_result { isError }`, not a\n * fatal run — see the module's \"Error semantics\"). `durableExecute` is dropped:\n * MCP tools are concurrency barriers, so the batch scheduler runs them via the\n * (still journaled) `execute`, and dropping the mappable promise keeps the\n * scheduler from treating an MCP tool as a parallel-fleet member.\n */\nfunction journalMcpTool(tool: ToolDef, ctx: RestateContextLike, toolOptions: RestateToolOptions): ToolDef {\n const journaled = restateTool(tool, ctx, { ...toolOptions, softErrors: true, coerceResultBlocks: true })\n const { durableExecute: _dropped, ...rest } = journaled\n return rest\n}\n\nfunction toToolOptions(options: RestateMcpToolWrapOptions): RestateToolOptions {\n const entryName = options.entryName\n ?? ((seq: number, name: string, _input: Record<string, unknown>, callId?: string) =>\n callId ? `tool-${name}-${callId}` : `tool-${name}-${seq}`)\n return {\n entryName,\n ...(options.replayTracker !== undefined ? { replayTracker: options.replayTracker } : {}),\n ...(options.runOptions !== undefined ? { runOptions: options.runOptions } : {}),\n }\n}\n\n/**\n * Build an {@link McpToolWrap} for the `AgentOptions.mcpToolWrap` hook —\n * journals every discovered MCP tool's result (soft-error-preserving). The\n * MCP analogue of `wrapAgentTools`, and the single supported way to make\n * discovered MCP tools durable under Restate.\n */\nexport function restateMcpToolWrap(\n ctx: RestateContextLike,\n options: RestateMcpToolWrapOptions = {},\n): McpToolWrap {\n const excludeSet = new Set(options.exclude ?? [])\n const toolOptions = toToolOptions(options)\n return (tool, meta) => {\n if (excludeSet.has(tool.spec.name))\n return tool\n return options.override?.(tool, meta) ?? journalMcpTool(tool, ctx, toolOptions)\n }\n}\n","import type { ToolResult } from '../providers'\nimport type { ToolBatchExecutionContext, ToolBatchExecutor } from '../types'\n\nexport interface RestatePromiseAllLike<TPromise extends Promise<unknown> = RestatePromiseLike<unknown>> {\n all: (values: readonly TPromise[]) => Promise<readonly unknown[]>\n}\n\nexport type RestatePromiseLike<T> = Promise<T> & {\n map: <U>(mapper: (value?: T, failure?: unknown) => U) => Promise<U>\n}\n\nexport interface RestateToolBatchExecutorOptions<TPromise extends Promise<unknown> = RestatePromiseLike<unknown>> {\n /**\n * Wait for a safe fleet through Restate's durable combinator. Pass\n * `RestatePromise` from `@restatedev/restate-sdk` in real deployments.\n */\n promises: RestatePromiseAllLike<TPromise>\n}\n\n/**\n * Tool batch scheduler for Restate-backed agents.\n *\n * It preserves unsafe-tool barriers and emits results in model submission\n * order. Safe fleets are started in submission order, capped by\n * `maxConcurrentTools`, and joined via the supplied durable `all()`.\n */\nexport function restateToolBatchExecutor<TPromise extends Promise<unknown> = RestatePromiseLike<unknown>>(\n options: RestateToolBatchExecutorOptions<TPromise>,\n): ToolBatchExecutor {\n return async (ctx: ToolBatchExecutionContext): Promise<ToolResult[]> => {\n const results: ToolResult[] = []\n const { toolCalls } = ctx\n\n const fillRemaining = (from: number, factory: (index: number) => ToolResult): ToolResult[] => {\n for (let i = from; i < toolCalls.length; i++)\n results[i] = factory(i)\n return results\n }\n\n for (let i = 0; i < toolCalls.length;) {\n if (ctx.signal.aborted)\n return fillRemaining(i, ctx.interruptedResult)\n if (ctx.steeringQueue.length > 0)\n return fillRemaining(i, ctx.skippedResult)\n\n if (!ctx.isConcurrencySafe(i)) {\n results[i] = await ctx.execute(i)\n i += 1\n continue\n }\n\n const start = i\n const fleet: number[] = []\n while (\n i < toolCalls.length\n && ctx.isConcurrencySafe(i)\n && fleet.length < ctx.maxConcurrentTools\n ) {\n fleet.push(i)\n i += 1\n }\n\n const fleetResults = fleet.every(index => ctx.canExecuteDurably(index))\n ? await ctx.executeDurable(\n fleet,\n async <T>(values: readonly Promise<T>[]): Promise<readonly T[]> => {\n const results = await options.promises.all(values as readonly TPromise[])\n return results as readonly T[]\n },\n )\n : await executeSequential(ctx, fleet)\n for (let offset = 0; offset < fleetResults.length; offset++)\n results[start + offset] = fleetResults[offset]\n }\n\n return results\n }\n}\n\nasync function executeSequential(\n ctx: ToolBatchExecutionContext,\n indices: readonly number[],\n): Promise<ToolResult[]> {\n const results: ToolResult[] = []\n for (const index of indices) {\n if (ctx.signal.aborted) {\n results.push(ctx.interruptedResult(index))\n continue\n }\n if (ctx.steeringQueue.length > 0) {\n results.push(ctx.skippedResult(index))\n continue\n }\n results.push(await ctx.execute(index))\n }\n return results\n}\n","/**\n * Restate-backed Provider wrapper.\n *\n * Wraps `Provider.stream` so every assistant turn (the LLM call as a\n * whole) is journaled. The model is invoked once per turn — the live\n * stream still fires `onText` / `onThinking` callbacks for UX during the\n * original execution. On replay, `ctx.run` returns the journaled\n * `TurnResult` immediately and the inner provider is NEVER re-invoked →\n * no duplicate billed tokens, no duplicate stream chunks.\n *\n * Replay caveat: stream callbacks don't re-fire on replay. Consumers\n * that paint live UI from `stream:text` should reconstruct transcripts\n * from `session.turns` via `eventsFromTurns` (zidane/chat) instead of\n * relying on hook re-emission. The chat layer already does this.\n *\n * Journal-entry naming: a monotonic per-wrapper counter (`llm-call-1`,\n * `llm-call-2`, …). One wrapper instance per Restate handler invocation\n * resets the counter; Restate's journal is invocation-scoped so names\n * don't need to be globally unique. The counter ticks the same way on\n * replay because the wrapper is constructed fresh each attempt.\n */\n\nimport type { Provider, StreamCallbacks, StreamOptions, TurnResult } from '../providers'\nimport type { ReplayTracker } from './replay'\nimport type { RestateContextLike, RestateRunOptions } from './types'\n\nexport interface RestateProviderOptions {\n /**\n * `ctx.run` options forwarded on every wrapped stream call.\n *\n * Default depends on {@link streamCallbacks}:\n *\n * - `'suppress'` → `{ maxRetryAttempts: 3 }` — provider transients\n * (rate limits, 5xx, connection resets) get retried inside the\n * journal entry; nothing streams to the host, so a retry is\n * invisible.\n * - `'live'` (the default) → `{ maxRetryAttempts: 1 }`. A live stream\n * that fails AFTER emitting deltas would be re-run inside the same\n * journal entry, re-firing `onText` into the loop's accumulating\n * text buffer and producing duplicated partial1+full2 output. The\n * loop's own retry (which only re-issues on a clean slate) is the\n * correct retry layer in live mode.\n *\n * Once the cap is reached the failure becomes terminal and surfaces\n * through the loop's normal `AgentProviderError` path. Set this\n * explicitly to override either default — but with live callbacks,\n * `maxRetryAttempts > 1` re-introduces the duplicate-delta hazard.\n */\n runOptions?: RestateRunOptions\n /**\n * Override the journal-entry name. Receives the 1-indexed sequence\n * number for this wrapper instance and the `StreamOptions` of the\n * call. Default: `llm-call-<n>`. Override to inject extra structure\n * (e.g. `${agentName}/llm-call-${n}`) when multiple agents share a\n * service.\n */\n entryName?: (seq: number, opts: StreamOptions) => string\n /**\n * Whether live stream callbacks should fire during the original execution.\n * Use `'suppress'` for strict durable mode: the model call still returns a\n * full TurnResult, and UIs reconstruct from persisted session turns.\n *\n * Default: `'live'`.\n */\n streamCallbacks?: 'live' | 'suppress'\n /**\n * Per-invocation replay tracker (see `createReplayTracker`). When set,\n * the wrapper marks it live from inside the journaled closure — i.e.\n * the first time the inner provider is ACTUALLY invoked rather than\n * replayed from the journal. Share one tracker across the provider\n * and tool wrappers of the same handler invocation.\n */\n replayTracker?: ReplayTracker\n}\n\n/**\n * Wrap a Zidane `Provider` so its `stream()` method journals each turn's\n * response inside `ctx.run`. All other Provider methods (`formatTools`,\n * `userMessage`, `toolResultsMessage`, `classifyError`, …) pass through\n * unchanged — they're pure functions over already-deterministic inputs.\n */\nexport function restateProvider(\n inner: Provider,\n ctx: RestateContextLike,\n options: RestateProviderOptions = {},\n): Provider {\n // Live callbacks must not retry inside the journal entry — a stream that\n // fails after emitting deltas would re-fire `onText` on the retry and\n // duplicate text in the loop's accumulator. See the `runOptions` doc.\n const runOpts: RestateRunOptions = options.runOptions\n ?? (options.streamCallbacks === 'suppress' ? { maxRetryAttempts: 3 } : { maxRetryAttempts: 1 })\n const nameFor = options.entryName ?? ((seq: number) => `llm-call-${seq}`)\n let seq = 0\n\n return {\n ...inner,\n stream(streamOpts: StreamOptions, callbacks: StreamCallbacks): Promise<TurnResult> {\n seq += 1\n const durableCallbacks = options.streamCallbacks === 'suppress'\n ? suppressStreamingCallbacks(callbacks)\n : callbacks\n return ctx.run<TurnResult>(\n nameFor(seq, streamOpts),\n () => {\n // Reached only when the journal cursor is past this entry —\n // a replayed call returns the journaled TurnResult without\n // executing this closure.\n options.replayTracker?.markLive()\n return inner.stream(streamOpts, durableCallbacks)\n },\n runOpts,\n )\n },\n }\n}\n\nfunction suppressStreamingCallbacks(callbacks: StreamCallbacks): StreamCallbacks {\n return {\n ...callbacks,\n onText: () => {},\n onThinking: undefined,\n onServerToolUse: undefined,\n onServerToolResult: undefined,\n onToolCallDelta: undefined,\n }\n}\n","/**\n * Replay-state tracking + replay-aware abort for Restate-backed agents.\n *\n * ## The problem\n *\n * `agent.abort()` during a journal replay is undefined behavior: the\n * loop throws `AgentAbortedError` at whatever point the replay cursor\n * happens to be, the host's catch arm typically journals something\n * (`report-fail`, a status write) mid-journal, and the invocation dies\n * with `[570 Journal mismatch]` — permanently, because every retry\n * replays into the same mismatch. Hosts have been inferring liveness\n * from side channels (e.g. counting live provider stream calls), which\n * works only because `restateProvider` replays `llm-call-N` without\n * touching the live provider — incidental coupling, not API.\n *\n * ## The seam\n *\n * The wrappers already know the answer: on replay, `ctx.run` returns\n * the journaled value WITHOUT invoking the wrapped closure; the first\n * time a closure actually executes, the journal cursor is past the\n * replayed prefix and the invocation is live. {@link createReplayTracker}\n * packages that signal:\n *\n * - `restateProvider(inner, ctx, { replayTracker })` and\n * `restateTool(tool, ctx, { replayTracker })` mark the tracker live\n * from inside their journaled closures.\n * - `tracker.isReplaying()` is the public liveness probe.\n * - `tracker.onLive(cb)` fires once at the replay→live transition\n * (immediately when already live).\n * - {@link replayAwareAbort} wraps `agent.abort` so external aborts\n * queue during replay and apply at the first live boundary — the\n * earliest point where the abort's side effects (loop throw, host\n * catch-arm journaling) append to the journal instead of forking it.\n *\n * ## Wiring\n *\n * ```ts\n * const tracker = createReplayTracker({ hooks: agent.hooks })\n * const provider = restateProvider(inner, ctx, { replayTracker: tracker })\n * const tools = wrapAgentTools(agentTools, ctx, { replayTracker: tracker })\n * const abort = replayAwareAbort(tracker, () => agent.abort())\n * // external cancel signal → abort() instead of agent.abort()\n * ```\n *\n * One tracker per handler invocation — like the wrappers themselves, it\n * is constructed fresh each attempt and must not be reused across\n * invocations.\n *\n * ## Semantics fine print\n *\n * \"Replaying\" is defined conservatively: `isReplaying()` returns `true`\n * until the first live closure executes. A fresh (non-resumed)\n * invocation therefore reports \"replaying\" for the short window before\n * its first journaled call — harmless for the abort use case (the abort\n * applies moments later, at that first live execution) and the honest\n * answer for journal safety: before the first `ctx.run` settles you\n * cannot know whether the SDK is about to feed you journal entries.\n *\n * A replay that completes without ever going live (the journaled run\n * already finished; the handler exits during replay) never fires\n * `onLive` — queued aborts are dropped with the invocation, which is\n * correct: there is nothing left to abort.\n */\n\n/** Minimal structural slice of the agent's Hookable for `replay:done`. */\nexport interface ReplayDoneHooks {\n callHook: (name: 'replay:done', ctx: Record<string, never>) => unknown\n}\n\nexport interface ReplayTrackerOptions {\n /**\n * Agent hooks to notify at the replay→live transition. When set, the\n * tracker fires `replay:done` exactly once, right after the `onLive`\n * callbacks. Rejections are swallowed (surfaced under `ZIDANE_DEBUG`)\n * — a misbehaving listener must not break the live execution that\n * triggered the transition.\n */\n hooks?: ReplayDoneHooks\n}\n\nexport interface ReplayTracker {\n /**\n * `true` until the first live (non-journaled) execution of a wrapped\n * provider stream / tool body. See the module doc for the fresh-\n * invocation caveat.\n */\n isReplaying: () => boolean\n /**\n * Register a callback for the replay→live transition. Fires once.\n * When the tracker is already live, the callback runs synchronously\n * before `onLive` returns. Returns an unregister function (no-op\n * after firing).\n */\n onLive: (cb: () => void) => () => void\n /**\n * Mark the invocation live. Called by the wrappers from inside their\n * journaled closures — a closure only executes when the journal\n * cursor is past it. Idempotent; only the first call transitions.\n */\n markLive: () => void\n}\n\n/**\n * Create a per-invocation replay tracker. Pass it to `restateProvider`\n * / `restateTool` / `wrapAgentTools` via their `replayTracker` option;\n * consume it via `isReplaying()` / `onLive()` / {@link replayAwareAbort}.\n */\nexport function createReplayTracker(options: ReplayTrackerOptions = {}): ReplayTracker {\n let live = false\n let callbacks: (() => void)[] = []\n\n return {\n isReplaying: () => !live,\n markLive: () => {\n if (live)\n return\n live = true\n const pending = callbacks\n callbacks = []\n for (const cb of pending) {\n try {\n cb()\n }\n catch (err) {\n if (process.env.ZIDANE_DEBUG)\n process.stderr.write(`[zidane/restate] onLive callback threw: ${err instanceof Error ? err.message : String(err)}\\n`)\n }\n }\n if (options.hooks) {\n Promise.resolve(options.hooks.callHook('replay:done', {})).catch((err: unknown) => {\n if (process.env.ZIDANE_DEBUG)\n process.stderr.write(`[zidane/restate] replay:done hook rejected: ${err instanceof Error ? err.message : String(err)}\\n`)\n })\n }\n },\n onLive: (cb) => {\n if (live) {\n cb()\n return () => {}\n }\n callbacks.push(cb)\n return () => {\n const idx = callbacks.indexOf(cb)\n if (idx >= 0)\n callbacks.splice(idx, 1)\n }\n },\n }\n}\n\n/**\n * Wrap an abort function so it defers during journal replay.\n *\n * Live invocation → `abort()` runs immediately, exactly like calling\n * `agent.abort()` directly. Replaying invocation → the abort is queued\n * and applied at the first live boundary (the start of the first\n * non-journaled provider stream or tool body), where the resulting\n * `AgentAbortedError` + host catch-arm journaling append to the journal\n * instead of forking it mid-replay. Multiple calls during replay\n * collapse into one queued abort.\n */\nexport function replayAwareAbort(tracker: ReplayTracker, abort: () => void): () => void {\n let queued = false\n return () => {\n if (!tracker.isReplaying()) {\n abort()\n return\n }\n if (queued)\n return\n queued = true\n tracker.onLive(abort)\n }\n}\n","/**\n * Restate-backed `SessionStore` — turn / run state lives in the bound\n * virtual object's K/V state instead of SQLite / file / remote HTTP.\n *\n * Trade-offs vs. journal-only replay\n * ----------------------------------\n * If you only care about durable execution within ONE invocation,\n * skip this — the journaled `ctx.run` entries (LLM calls, tool\n * executions) are enough to replay the loop to byte-identical state\n * after a crash. The in-memory `createMemoryStore()` is the right\n * choice; turns rematerialize from the journal each replay.\n *\n * Pick this store when EXTERNAL consumers (TUI, web GUI, support\n * tooling) need to read a session's history WITHOUT re-entering the\n * agent handler. Virtual-object state is exposed via the SDK's read\n * APIs (`ctx.get` from another handler, `restate-cli`, the Restate\n * web UI) — same data, different access path. The journal is\n * invocation-local; this state is the externally-visible projection\n * of it.\n *\n * Storage layout\n * --------------\n * One virtual-object key per session, three K/V slots:\n *\n * `session-data` → `SessionData` minus the `turns` array (small header)\n * `session-turns` → `SessionTurn[]` (the conversation history)\n * `session-runs` → `SessionRun[]` (run lifecycle records)\n *\n * Splitting `turns` / `runs` out keeps the header light for `load()` —\n * a handler that only needs metadata doesn't pull the full history.\n *\n * Listing / discovery\n * -------------------\n * `list()` returns `[]` because virtual objects don't expose cross-key\n * enumeration. `delete()` clears the current object's session keys only.\n * Use a separate index handler if you need discovery (one virtual object\n * per `projectRoot` that maintains an indexed list of session ids; this\n * store doesn't own that concern).\n * `generateSessionId` is omitted so the agent falls back to its\n * default UUID generator — for a session bound 1:1 to a virtual-\n * object key, pass `id: ctx.key` to `createSession()` instead and\n * skip ID generation entirely.\n */\n\nimport type { SessionData, SessionRun, SessionStore } from '../session'\nimport type { SessionTurn } from '../types'\nimport type { RestateObjectContextLike } from './types'\n\nconst KEY_DATA = 'session-data'\nconst KEY_TURNS = 'session-turns'\nconst KEY_RUNS = 'session-runs'\n\n/**\n * Construct a `SessionStore` backed by the bound virtual-object's K/V\n * state. The store is single-tenant — every method ignores the\n * `sessionId` argument because the virtual object is already keyed by\n * `ctx.key`. Calling `appendTurns('other-id', …)` writes to the\n * CURRENT object's state, not the one named in the argument. Bind one\n * virtual-object key per session and the contract holds.\n */\nexport function restateSessionStore(ctx: RestateObjectContextLike): SessionStore {\n let nextTurnSeq: number | undefined\n\n async function generateTurnId(): Promise<string> {\n if (nextTurnSeq === undefined) {\n const existing = (await ctx.get<SessionTurn[]>(KEY_TURNS)) ?? []\n nextTurnSeq = existing.length\n }\n nextTurnSeq += 1\n return `turn_${nextTurnSeq}`\n }\n\n return {\n /**\n * Turn ids are deterministic from the persisted turn count. Random ids\n * are replay-stable only when the whole handler replays from the same\n * point; restarting from an arbitrary journal step can shift the RNG\n * sequence before a state write.\n */\n generateTurnId,\n\n async load(_sessionId: string): Promise<SessionData | null> {\n const header = await ctx.get<Omit<SessionData, 'turns' | 'runs'>>(KEY_DATA)\n const turns = sanitizeTurnsForState((await ctx.get<SessionTurn[]>(KEY_TURNS)) ?? [])\n const runs = sanitizeRunsForState((await ctx.get<SessionRun[]>(KEY_RUNS)) ?? [])\n if (!header) {\n if (turns.length === 0 && runs.length === 0)\n return null\n return {\n id: _sessionId,\n turns,\n runs,\n status: inferStatus(runs),\n metadata: {},\n createdAt: inferCreatedAt(turns, runs),\n updatedAt: inferUpdatedAt(turns, runs),\n }\n }\n return { ...header, turns, runs }\n },\n\n async save(session: SessionData): Promise<void> {\n const { turns, runs, ...header } = session\n // Journal-stable header timestamps. The in-memory `Session` stamps\n // `createdAt` / `updatedAt` with raw `Date.now()` (its `touch()`\n // helper is synchronous and can't await a journaled clock), so the\n // values arriving here differ on every replay — and a replayed\n // `ctx.set` with drifting values is exactly the non-determinism\n // Restate exists to prevent. Source both from the journal instead:\n // `createdAt` sticks to the first persisted value, `updatedAt`\n // comes from `ctx.date.now()` (journaled — replay returns the\n // recorded reading).\n const prior = await ctx.get<Omit<SessionData, 'turns' | 'runs'>>(KEY_DATA)\n const now = await ctx.date.now()\n ctx.set(KEY_DATA, {\n ...header,\n createdAt: prior?.createdAt ?? now,\n updatedAt: now,\n })\n ctx.set(KEY_TURNS, sanitizeTurnsForState(turns))\n ctx.set(KEY_RUNS, sanitizeRunsForState(runs))\n },\n\n async delete(_sessionId: string): Promise<void> {\n ctx.clear(KEY_DATA)\n ctx.clear(KEY_TURNS)\n ctx.clear(KEY_RUNS)\n },\n\n /**\n * Always empty — virtual objects don't support cross-key\n * enumeration. Maintain a separate index handler if discovery\n * matters.\n */\n async list(): Promise<string[]> {\n return []\n },\n\n async appendTurns(_sessionId: string, turns: SessionTurn[]): Promise<void> {\n const existing = sanitizeTurnsForState((await ctx.get<SessionTurn[]>(KEY_TURNS)) ?? [])\n ctx.set(KEY_TURNS, [...existing, ...sanitizeTurnsForState(turns)])\n },\n\n async getTurns(_sessionId: string, from = 0, limit?: number): Promise<SessionTurn[]> {\n const turns = sanitizeTurnsForState((await ctx.get<SessionTurn[]>(KEY_TURNS)) ?? [])\n return turns.slice(from, limit !== undefined ? from + limit : undefined)\n },\n\n async updateRun(_sessionId: string, run: SessionRun): Promise<void> {\n const runs = sanitizeRunsForState((await ctx.get<SessionRun[]>(KEY_RUNS)) ?? [])\n const idx = runs.findIndex(r => r.id === run.id)\n const next = [...runs]\n if (idx >= 0) {\n // Journal-stable `startedAt`: the in-memory `Session.startRun`\n // stamps it with raw `Date.now()`, which re-evaluates on every\n // replay. Keep the previously persisted value (mirrors the\n // `createdAt: prior?.createdAt ?? now` pattern in `save()`) so a\n // replayed `ctx.set` payload doesn't drift.\n next[idx] = { ...sanitizeRunForState(run), startedAt: runs[idx].startedAt }\n }\n else {\n next.push(sanitizeRunForState(run))\n }\n ctx.set(KEY_RUNS, next)\n },\n\n async updateStatus(_sessionId: string, status: SessionData['status']): Promise<void> {\n const header = await ctx.get<Omit<SessionData, 'turns' | 'runs'>>(KEY_DATA)\n const now = await ctx.date.now()\n if (header) {\n ctx.set(KEY_DATA, { ...header, status, updatedAt: now })\n }\n else {\n ctx.set(KEY_DATA, {\n id: _sessionId,\n status,\n metadata: {},\n createdAt: now,\n updatedAt: now,\n })\n }\n },\n }\n}\n\nfunction sanitizeTurnsForState(turns: readonly SessionTurn[]): SessionTurn[] {\n return turns.map(sanitizeTurnForState)\n}\n\nfunction sanitizeTurnForState(turn: SessionTurn): SessionTurn {\n if (!turn.usage || turn.usage.timeToFirstTokenMs === undefined)\n return turn\n\n const { timeToFirstTokenMs: _timeToFirstTokenMs, ...usage } = turn.usage\n return { ...turn, usage }\n}\n\nfunction sanitizeRunsForState(runs: readonly SessionRun[]): SessionRun[] {\n return runs.map(sanitizeRunForState)\n}\n\nfunction sanitizeRunForState(run: SessionRun): SessionRun {\n if (!run.turnUsage?.some(usage => usage.timeToFirstTokenMs !== undefined))\n return run\n\n return {\n ...run,\n turnUsage: run.turnUsage.map((usage) => {\n if (usage.timeToFirstTokenMs === undefined)\n return usage\n const { timeToFirstTokenMs: _timeToFirstTokenMs, ...stableUsage } = usage\n return stableUsage\n }),\n }\n}\n\nfunction inferStatus(runs: readonly SessionRun[]): SessionData['status'] {\n if (runs.some(run => run.status === 'running'))\n return 'running'\n if (runs.some(run => run.status === 'error'))\n return 'error'\n if (runs.some(run => run.status === 'completed'))\n return 'completed'\n return 'idle'\n}\n\nfunction inferCreatedAt(turns: readonly SessionTurn[], runs: readonly SessionRun[]): number {\n return minDefined([\n ...turns.map(turn => turn.createdAt),\n ...runs.map(run => run.startedAt),\n ]) ?? 0\n}\n\nfunction inferUpdatedAt(turns: readonly SessionTurn[], runs: readonly SessionRun[]): number {\n return maxDefined([\n ...turns.map(turn => turn.createdAt),\n ...runs.map(run => run.endedAt ?? run.startedAt),\n ]) ?? inferCreatedAt(turns, runs)\n}\n\nfunction minDefined(values: readonly number[]): number | undefined {\n let min: number | undefined\n for (const value of values) {\n if (min === undefined || value < min)\n min = value\n }\n return min\n}\n\nfunction maxDefined(values: readonly number[]): number | undefined {\n let max: number | undefined\n for (const value of values) {\n if (max === undefined || value > max)\n max = value\n }\n return max\n}\n","/**\n * Durable `ExecutionContext.waitBackground` for Restate hosts.\n *\n * A durable execution context can't push a `task:exit` callback from a timer\n * back into a journaled handler. The race-safe pattern is an awakeable park:\n * the runner fires task-exit over its own bridge → `ctx.resolveAwakeable(id,\n * exitInfo)` → the parked `waitBackground` resumes. The *choreography* around\n * that park is entirely generic — only the persistence (which row maps a task\n * to its resumer awakeable) is host-specific. {@link restateWaitBackground}\n * owns the generic half; the host supplies `probe` / `register` / `settle`.\n *\n * Ordering contract (this is the whole point — get it wrong and you leak a\n * lost wakeup):\n *\n * 1. **mint** the awakeable (before the journaled register, so replay\n * re-derives the same id).\n * 2. **register** the awakeable id as the task's exit resumer — journaled,\n * and crucially BEFORE the probe. If we probed first and the task exited\n * in the gap before register, the runner's `task:exit` would fire with no\n * resumer row and the park would hang forever.\n * 3. **probe** the registry. If the task ALREADY terminated, fast-path: settle\n * and return its exit info without ever parking (a resolution that lands\n * on the registered awakeable afterwards is dropped by the runtime). If the\n * task is unknown, settle and return `null`. Otherwise:\n * 4. **park** on the awakeable, OUTSIDE any `ctx.run`, raced against the\n * durable `ctx.sleep(timeoutMs)` deadline and the caller's abort signal.\n * A timeout / abort resolves `null` (the seam's documented sentinel).\n * 5. **settle** — journaled finalization (stamp / clear the resumer row).\n *\n * The returned function matches `ExecutionContext.waitBackground` exactly, so a\n * host wires it with `execution.waitBackground = restateWaitBackground({ … })`.\n */\n\nimport type { ExecutionHandle, TaskEntry, TaskExitInfo } from '../contexts'\nimport type { RestatePromiseRaceLike } from './awakeable'\nimport type { ReplayTracker } from './replay'\nimport type { RestateContextLike, RestateRunOptions } from './types'\nimport { awakeableWithTimeout } from './awakeable'\n\n/** Journaled registration marker — mirrors the marker invariant in `restateAwakeableTool`. */\ninterface WaitBackgroundRegisterMarker {\n registered: true\n awakeableId: string\n}\n\nexport interface RestateWaitBackgroundOptions {\n /** The Restate context the awakeable + journal entries bind to. */\n ctx: RestateContextLike\n /**\n * Snapshot the host's task registry (the `listBackground` shape). Called\n * AFTER `register`, inside a journaled `ctx.run`. The helper finds `taskId`\n * in the result: terminated → fast-path return, running → park, absent →\n * `null`.\n */\n probe: (handle: ExecutionHandle, taskId: string) => Promise<readonly TaskEntry[]> | readonly TaskEntry[]\n /**\n * Persist `awakeableId` as the exit resumer for `taskId` BEFORE the probe —\n * the host's task-exit path must later call `ctx.resolveAwakeable(awakeableId,\n * exitInfo)`. Runs inside a journaled `ctx.run`; keep it short and\n * idempotent-safe up to journal persistence.\n */\n register: (awakeableId: string, taskId: string, handle: ExecutionHandle) => Promise<void> | void\n /**\n * Finalize the resumer row once the wait resolves — `exit` is the task's\n * {@link TaskExitInfo}, or `null` on timeout / abort / unknown task. Runs\n * inside a journaled `ctx.run`. Optional.\n */\n settle?: (awakeableId: string, taskId: string, exit: TaskExitInfo | null, handle: ExecutionHandle) => Promise<void> | void\n /**\n * Default park deadline in milliseconds. A per-call `options.timeoutMs`\n * (what the `wait_task` tool passes) wins. Unset / non-positive = park until\n * the resumer fires or the caller aborts.\n */\n timeoutMs?: number\n /**\n * Durable race combinator for the timeout race — pass `RestatePromise` from\n * the SDK. See {@link awakeableWithTimeout}; native `Promise.race` is the\n * replay-safe fallback.\n */\n promises?: RestatePromiseRaceLike\n /** `ctx.run` options for the journaled phases. Defaults to `{ maxRetryAttempts: 1 }`. */\n runOptions?: RestateRunOptions\n /** Journal-entry prefix. Default `wait-background`. */\n entryPrefix?: string\n /** Per-invocation replay tracker (see `createReplayTracker`). */\n replayTracker?: ReplayTracker\n}\n\nfunction entryToExit(entry: TaskEntry): TaskExitInfo {\n return {\n taskId: entry.taskId,\n // `entryToExit` is only called for terminated entries; `'running'` can't\n // reach here, but narrow defensively to the exit-only union.\n status: entry.status === 'running' ? 'exited' : entry.status,\n exitCode: entry.exitCode ?? 0,\n ...(entry.signal ? { signal: entry.signal } : {}),\n outputPath: entry.outputPath,\n durationMs: Math.max(0, (entry.endedAt ?? entry.startedAt) - entry.startedAt),\n command: entry.command,\n }\n}\n\n/**\n * Park on `promise` until it settles, the caller aborts, or (already handled\n * by `awakeableWithTimeout`) the durable deadline elapses. Abort and rejection\n * both resolve `null` — the `waitBackground` seam's contract is \"exit info, or\n * null when the task didn't cleanly exit before we stopped waiting\".\n */\nfunction parkUntilAbort<T>(promise: Promise<T>, signal?: AbortSignal): Promise<T | null> {\n if (!signal)\n return promise.then(value => value, () => null)\n if (signal.aborted)\n return Promise.resolve(null)\n return new Promise<T | null>((resolve) => {\n const onAbort = (): void => resolve(null)\n signal.addEventListener('abort', onAbort, { once: true })\n promise.then(\n (value) => {\n signal.removeEventListener('abort', onAbort)\n resolve(value)\n },\n () => {\n signal.removeEventListener('abort', onAbort)\n resolve(null)\n },\n )\n })\n}\n\n/**\n * Build a durable `ExecutionContext.waitBackground` — see the module doc for\n * the ordering contract. The returned function is the seam itself:\n * `(handle, taskId, options?) => Promise<TaskExitInfo | null>`.\n */\nexport function restateWaitBackground(\n options: RestateWaitBackgroundOptions,\n): (handle: ExecutionHandle, taskId: string, opts?: { timeoutMs?: number, signal?: AbortSignal }) => Promise<TaskExitInfo | null> {\n const { ctx, probe, register, settle } = options\n const runOpts: RestateRunOptions = options.runOptions ?? { maxRetryAttempts: 1 }\n const prefix = options.entryPrefix ?? 'wait-background'\n let seq = 0\n\n return async (handle, taskId, callOpts) => {\n seq += 1\n const entry = `${prefix}-${taskId}-${seq}`\n const timeoutMs = callOpts?.timeoutMs ?? options.timeoutMs\n const signal = callOpts?.signal\n\n const finalize = async (exit: TaskExitInfo | null, awakeableId: string): Promise<TaskExitInfo | null> => {\n if (settle) {\n await ctx.run(`${entry}-settle`, async () => {\n options.replayTracker?.markLive()\n await settle(awakeableId, taskId, exit, handle)\n }, runOpts)\n }\n return exit\n }\n\n // 1. Mint BEFORE the journaled register (same ordering contract as\n // restateAwakeableTool) — replay returns the same id. The timeout sleep\n // is armed here too, so the park below is a durable race.\n const awakeable = awakeableWithTimeout<TaskExitInfo>(ctx, {\n ...(timeoutMs !== undefined ? { timeoutMs } : {}),\n ...(options.promises ? { promises: options.promises } : {}),\n })\n\n // 2. Register the resumer BEFORE probing.\n const marker = await ctx.run<WaitBackgroundRegisterMarker>(`${entry}-register`, async () => {\n options.replayTracker?.markLive()\n await register(awakeable.id, taskId, handle)\n return { registered: true, awakeableId: awakeable.id }\n }, runOpts)\n if (marker.awakeableId !== awakeable.id) {\n throw new Error(\n `restateWaitBackground(${taskId}): journal drift — registration marker carries awakeable \"${marker.awakeableId}\" but this replay minted \"${awakeable.id}\". Refusing to park on an unreachable awakeable.`,\n )\n }\n\n // 3. Probe (journaled). Fast-path terminated / unknown without parking.\n const entries = await ctx.run<readonly TaskEntry[]>(`${entry}-probe`, async () => {\n options.replayTracker?.markLive()\n return [...await probe(handle, taskId)]\n }, runOpts)\n const found = entries.find(e => e.taskId === taskId)\n if (!found)\n return finalize(null, awakeable.id)\n if (found.status !== 'running')\n return finalize(entryToExit(found), awakeable.id)\n\n // 4. Park OUTSIDE any ctx.run — a suspension point must not nest in a\n // journaled closure. Timeout (via awakeableWithTimeout) and abort both\n // resolve null.\n const resumed = await parkUntilAbort(awakeable.promise, signal)\n\n // 5. Settle + return.\n return finalize(resumed, awakeable.id)\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"restate.js","names":[],"sources":["../src/restate/awakeable.ts","../src/restate/awakeable-tool.ts","../src/restate/errors.ts","../src/restate/behavior.ts","../src/restate/clock.ts","../src/restate/soft-errors.ts","../src/restate/tool.ts","../src/restate/mcp.ts","../src/restate/parallel.ts","../src/restate/provider.ts","../src/restate/replay.ts","../src/restate/session.ts","../src/restate/wait-background.ts"],"sourcesContent":["/**\n * Awakeable helpers — durable waits with deadlines.\n *\n * `awakeableWithTimeout` packages the canonical \"park until a resumer\n * fires, but not forever\" shape: an awakeable raced against a durable\n * `ctx.sleep(timeoutMs)` timer. The race itself survives process death —\n * on replay both branches resume from the journal and the same side\n * wins. This is the three-line building block for\n * `ExecutionContext.waitBackground` implementations on durable hosts\n * (runner fires task-exit → `resolveAwakeable(id, info)`; the timeout\n * branch maps to the seam's `null` return).\n */\n\nimport type { RestateAwakeable, RestateContextLike } from './types'\n\n/**\n * Structural subset of the SDK's `RestatePromise` static surface used by\n * {@link awakeableWithTimeout} — mirrors `RestatePromiseAllLike` from\n * `./parallel`. Pass `RestatePromise` from `@restatedev/restate-sdk` so\n * the race goes through the journaled combinator; native `Promise.race`\n * over two durable promises leaves the winner to the runtime's replay\n * ordering instead of an explicit journal entry.\n */\nexport interface RestatePromiseRaceLike<TPromise extends Promise<unknown> = Promise<unknown>> {\n race: (values: readonly TPromise[]) => Promise<unknown>\n}\n\nexport interface AwakeableWithTimeoutOptions<TPromise extends Promise<unknown> = Promise<unknown>> {\n /**\n * Durable deadline in milliseconds. Unset / non-positive = no timeout\n * (the returned awakeable is the plain `ctx.awakeable()` passthrough).\n */\n timeoutMs?: number\n /**\n * Durable race combinator — pass `RestatePromise` from the SDK. When\n * omitted, native `Promise.race` is used: correct at runtime and\n * replay-safe for THIS pattern (both branches are journaled\n * primitives), but the SDK combinator is the recommended belt-and-\n * braces choice for deterministic replay.\n */\n promises?: RestatePromiseRaceLike<TPromise>\n}\n\n/**\n * Mint an awakeable that resolves with the resumer's payload, or `null`\n * when `timeoutMs` elapses first. The id is journal-stable (send it\n * out-of-band as usual); the timeout is a durable `ctx.sleep`, so a\n * parked invocation suspends instead of holding a worker.\n *\n * Timeout surfaces as `null` — a resumer that resolves `undefined` is\n * indistinguishable from a timeout, so resolve a concrete payload.\n *\n * ```ts\n * // waitBackground for a durable host, in three lines:\n * const { id, promise } = awakeableWithTimeout<TaskExitInfo>(ctx, { timeoutMs, promises: RestatePromise })\n * await registerExitResumer(taskId, id) // runner → ctx.resolveAwakeable(id, info)\n * return await promise // TaskExitInfo, or null on timeout\n * ```\n */\nexport function awakeableWithTimeout<T, TPromise extends Promise<unknown> = Promise<unknown>>(\n ctx: RestateContextLike,\n options: AwakeableWithTimeoutOptions<TPromise> = {},\n): RestateAwakeable<T | null> {\n const awakeable = ctx.awakeable<T>()\n const timeoutMs = options.timeoutMs\n if (typeof timeoutMs !== 'number' || !Number.isFinite(timeoutMs) || timeoutMs <= 0)\n return awakeable\n\n const timer = ctx.sleep(timeoutMs)\n const raced = options.promises\n ? options.promises.race([awakeable.promise, timer] as readonly unknown[] as readonly TPromise[])\n : Promise.race<unknown>([awakeable.promise, timer])\n return {\n id: awakeable.id,\n // The sleep branch resolves `undefined`; normalize to the seam's\n // `null` so callers get one documented timeout sentinel.\n promise: raced.then(value => (value === undefined ? null : value as T)),\n }\n}\n","/**\n * Awakeable-backed tool — durable human/external-in-the-loop waits.\n *\n * Builds a `ToolDef` whose `execute` parks on a Restate awakeable: the\n * tool mints a journal-stable awakeable id, broadcasts it out-of-band\n * (webhook, queue, collab stream — the `notify` callback), and suspends\n * until a resumer calls `ctx.resolveAwakeable(id, value)` on the SDK\n * side. The classic shape for `ask_user` / `request_review` /\n * `wait_for_approval` tools inside durable handlers.\n *\n * Replay contract\n * ---------------\n * - **Broadcast-once-across-replays**: `notify` runs inside `ctx.run`,\n * so a crash + replay returns the journaled marker without re-sending\n * the notification. The user is pinged exactly once per tool call, no\n * matter how many times the worker restarts.\n * - **Marker invariant**: the journaled marker records the awakeable id\n * it was broadcast for. On replay the freshly-minted awakeable id must\n * match (the SDK derives awakeable ids deterministically from the\n * journal position); a mismatch means the journal and the code path\n * drifted — the tool throws instead of parking on an id nobody will\n * ever resolve.\n */\n\nimport type { ToolContext, ToolDef } from '../tools/types'\nimport type { ToolResultContent } from '../types'\nimport type { RestateContextLike, RestateRunOptions } from './types'\n\n/** Journaled broadcast marker — see \"Marker invariant\" in the module doc. */\ninterface AwakeableNotifyMarker {\n notified: true\n awakeableId: string\n}\n\nexport interface RestateAwakeableToolOptions<T = unknown> {\n /** Canonical tool name (what the model calls). */\n name: string\n /** Model-facing tool description. */\n description: string\n /** JSON schema for the tool input. */\n inputSchema: Record<string, unknown>\n /** The Restate context the awakeable + journal entries bind to. */\n ctx: RestateContextLike\n /**\n * Send the awakeable id (plus the call's input) out-of-band so a\n * resumer can later call `ctx.resolveAwakeable(awakeableId, value)`.\n * Runs inside `ctx.run` — fires exactly once across replays.\n */\n notify: (info: {\n awakeableId: string\n input: Record<string, unknown>\n toolCtx: ToolContext\n }) => void | Promise<void>\n /**\n * Map the resolved awakeable payload to the tool result. Default:\n * strings pass through, everything else is JSON-stringified.\n */\n toResult?: (value: T, input: Record<string, unknown>) => string | ToolResultContent[]\n /**\n * `ctx.run` options for the notify entry. Defaults to\n * `{ maxRetryAttempts: 1 }`, matching `restateTool`'s rationale.\n */\n runOptions?: RestateRunOptions\n /**\n * Concurrency-safety flag passed through to the `ToolDef`. Defaults to\n * `false` — a parked wait holding a scheduler slot should barrier.\n */\n isConcurrencySafe?: boolean\n}\n\n/**\n * Build a `ToolDef` that parks on a Restate awakeable until an external\n * resumer resolves it. See the module doc for the replay contract.\n *\n * Do NOT additionally wrap the returned tool in `restateTool` — the\n * journal discipline is already internal, and an outer `ctx.run` would\n * illegally nest the suspension point inside a journaled closure.\n */\nexport function restateAwakeableTool<T = unknown>(\n options: RestateAwakeableToolOptions<T>,\n): ToolDef {\n const { name, description, inputSchema, ctx, notify, toResult } = options\n const runOpts: RestateRunOptions = options.runOptions ?? { maxRetryAttempts: 1 }\n let seq = 0\n\n const execute = async (input: Record<string, unknown>, toolCtx: ToolContext): Promise<string | ToolResultContent[]> => {\n seq += 1\n // Mint BEFORE the journaled broadcast: the awakeable's journal\n // position precedes the notify entry, so on replay both come back\n // in the same order with the same id.\n const awakeable = ctx.awakeable<T>()\n\n const marker = await ctx.run<AwakeableNotifyMarker>(\n `awakeable-${name}-${seq}-notify`,\n async () => {\n await notify({ awakeableId: awakeable.id, input, toolCtx })\n return { notified: true, awakeableId: awakeable.id }\n },\n runOpts,\n )\n\n // Marker invariant — a drifted journal would otherwise park this\n // call on an id that was never broadcast (nobody will resolve it).\n if (marker.awakeableId !== awakeable.id) {\n throw new Error(\n `restateAwakeableTool(${name}): journal drift — broadcast marker carries awakeable \"${marker.awakeableId}\" but this replay minted \"${awakeable.id}\". The journal and the code path no longer line up; refusing to park on an unreachable awakeable.`,\n )\n }\n\n const value = await awakeable.promise\n if (toResult)\n return toResult(value, input)\n return typeof value === 'string' ? value : JSON.stringify(value)\n }\n\n return {\n spec: { name, description, inputSchema },\n ...(options.isConcurrencySafe !== undefined ? { isConcurrencySafe: options.isConcurrencySafe } : {}),\n execute,\n // The awakeable park IS the durable body — the loop's durable path\n // can use it directly without an extra wrapper.\n durableExecute: execute,\n }\n}\n","/**\n * Restate control-flow errors must escape the agent loop. If they are turned\n * into model-visible tool results, the runtime can retry/suspend incorrectly.\n *\n * Kept structural so `zidane/restate` does not need to import the SDK at\n * runtime just to recognize the common error shapes.\n */\nexport function shouldRethrowRestateControlError(error: unknown): boolean {\n if (!(error instanceof Error))\n return false\n\n const codeValue = Reflect.get(error, 'code')\n const code = typeof codeValue === 'number'\n ? codeValue\n : undefined\n if (code === 599)\n return true\n\n const name = error.name\n if (\n name === 'TerminalError'\n || name === 'TimeoutError'\n || name === 'CancelledError'\n || name === 'SuspendedError'\n ) {\n return true\n }\n\n const ctorName = error.constructor?.name\n const serializedCtorNameValue = Reflect.get(error, 'constructorName')\n const serializedCtorName = typeof serializedCtorNameValue === 'string'\n ? serializedCtorNameValue\n : undefined\n if (\n ctorName === 'TerminalError'\n || ctorName === 'TimeoutError'\n || ctorName === 'CancelledError'\n || ctorName === 'SuspendedError'\n || serializedCtorName === 'TerminalError'\n || serializedCtorName === 'TimeoutError'\n || serializedCtorName === 'CancelledError'\n || serializedCtorName === 'SuspendedError'\n ) {\n return true\n }\n\n return typeof name === 'string' && name.toLowerCase().includes('suspend')\n}\n","import type { AgentBehavior } from '../types'\nimport { shouldRethrowRestateControlError } from './errors'\n\n/**\n * Conservative behavior defaults for agents running inside Restate.\n *\n * The helper is opt-in and returns a plain AgentBehavior object, so callers can\n * spread or override it without changing non-Restate harness defaults.\n *\n * `disableBackgroundTasks: 'non-durable'` is capability-aware: background\n * tasks stay enabled for execution contexts whose\n * `capabilities.detachedTasks` is `'durable'` (tasks live on a remote\n * runner and survive worker crashes) and are disabled for everything\n * else (host-local processes don't survive process death). Hosts on\n * plain `ProcessContext` see the same effective behavior as the old\n * blanket `true`.\n */\nexport function restateBehavior(overrides: AgentBehavior = {}): AgentBehavior {\n return {\n maxConcurrentTools: 1,\n disableBackgroundTasks: 'non-durable',\n cache: true,\n shouldRethrowToolError: shouldRethrowRestateControlError,\n // Context discipline for long runs. These are client-side and\n // provider-agnostic: they trim the message array before it reaches the\n // provider, so they work for OSS / OpenAI-compat models too.\n // `tail` keeps the largest recent suffix of tool output under\n // `compactThreshold` bytes; `elideStaleReads` drops superseded file reads;\n // `mediaKeepTurns` ages base64 (pasted/Read images, PDFs) off the wire.\n compactStrategy: 'tail',\n compactThreshold: 128 * 1024,\n compactKeepTurns: 8,\n elideStaleReads: true,\n mediaKeepTurns: 8,\n toolOutputBudget: 64 * 1024,\n // Token-based proactive summarization. Inert unless a context window is\n // resolvable through `provider.meta.contextWindow` or an explicit\n // `autoCompact.contextWindow` override.\n autoCompact: { threshold: 0.85 },\n ...overrides,\n }\n}\n","/**\n * Restate-backed {@link AgentClock} — journals `now()` + `randomUUID()` so\n * `SessionTurn.createdAt`, `runId`, and fallback / synthetic turn ids stay\n * byte-identical across replays of the same invocation.\n *\n * Pass to `agent.run({ clock: restateClock(ctx) })` or bake it into\n * `createAgent({ clock: restateClock(ctx) })` for the duration of a\n * handler invocation. The clock holds a reference to `ctx`; do not reuse\n * a clock instance across invocations.\n */\n\nimport type { AgentClock } from '../types'\nimport type { RestateContextLike } from './types'\n\n/**\n * Wrap a Restate context's `date.now()` + `rand.uuidv4()` into the\n * {@link AgentClock} shape Zidane consumes for journaled metadata.\n *\n * The returned clock is a thin live view onto `ctx` — each call hits\n * the SDK afresh. No caching, no closure-captured values. Restate's\n * journal handles determinism on its end.\n */\nexport function restateClock(ctx: RestateContextLike): AgentClock {\n return {\n now: () => ctx.date.now(),\n randomUUID: () => ctx.rand.uuidv4(),\n }\n}\n","/**\n * Soft tool-error plumbing shared by {@link restateTool} and\n * {@link restateMcpToolWrap}.\n *\n * The problem: `restateTool` runs a tool body inside `ctx.run(...,\n * { maxRetryAttempts: 1 })`. An ordinary, recoverable tool throw (a failed\n * shell command, a transport error, an MCP `isError` result) would exhaust the\n * retry budget and surface as a Restate `TerminalError` — which\n * `restateBehavior`'s `shouldRethrowToolError` re-throws, aborting the whole\n * run. That's the opposite of the non-Restate model, where a tool throw becomes\n * a model-visible `tool_result { isError }` and the loop keeps going.\n *\n * The fix (same shape the MCP wrapper has always used): catch the recoverable\n * throw INSIDE the journaled closure and record it as a JSON-serializable\n * sentinel — so `ctx.run` journals a *value*, never a failed action. OUTSIDE the\n * journal (on both live and replay) the sentinel is turned back into a plain,\n * non-control `Error`, so the loop produces a `tool_result { isError }` and\n * continues. Real Restate control errors and deliberate aborts are never\n * softened — they must escape so the runtime can suspend / retry / cancel.\n */\n\nimport { shouldRethrowRestateControlError } from './errors'\n\n/** Journal value recorded for a softened tool throw. */\nconst SOFT_ERROR_KEY = '__zidaneRestateSoftError'\n\nexport interface SoftToolError {\n [SOFT_ERROR_KEY]: true\n message: string\n}\n\nexport function isSoftToolError(value: unknown): value is SoftToolError {\n return typeof value === 'object'\n && value !== null\n && (value as Record<string, unknown>)[SOFT_ERROR_KEY] === true\n}\n\n/** Build the sentinel recorded as the journal value for a softened throw. */\nexport function makeSoftToolError(error: unknown): SoftToolError {\n return { [SOFT_ERROR_KEY]: true, message: error instanceof Error ? error.message : String(error) }\n}\n\n/**\n * Recoverable throws soften; control-flow + abort throws do not.\n *\n * - Restate control errors (`TerminalError`, `SuspendedError`, …) must escape\n * so the runtime can act on them.\n * - Deliberate aborts (run cancel, `cancelTool`, sibling cascade) are a\n * timing-dependent, non-deterministic outcome — journaling one would bake it\n * into replay. The `signal.aborted` check also catches transports (the MCP\n * layer) that reject an aborted call with a plain `Error` carrying no\n * `AbortError` name.\n */\nexport function isRestateControlOrAbort(error: unknown, signal?: AbortSignal): boolean {\n if (shouldRethrowRestateControlError(error))\n return true\n if (error instanceof Error && error.name === 'AbortError')\n return true\n return signal?.aborted === true\n}\n\n/**\n * Outside-the-journal counterpart to {@link makeSoftToolError}: re-throw a\n * recorded sentinel as a plain (non-control) `Error`, else pass the value\n * through untouched.\n */\nexport function rethrowSoftToolError<T>(value: T): Exclude<T, SoftToolError> {\n if (isSoftToolError(value))\n throw new Error(value.message)\n return value as Exclude<T, SoftToolError>\n}\n","/**\n * Restate-backed tool wrappers.\n *\n * Wraps `ToolDef.execute` so every tool invocation is journaled. The\n * tool body runs on the original execution; after Restate persists the\n * journal entry, replay returns the recorded result without re-executing.\n * If the process dies before the entry is durable, the latest in-flight\n * tool can run again, so non-idempotent tools still need idempotency keys.\n *\n * `tool:gate`, `tool:transform`, `tool:after` hooks fire OUTSIDE the\n * journaled boundary, so they re-execute on replay. Built-in handlers\n * are deterministic given the journaled input + output (truncation,\n * image-stripping, `<edit-outcomes>` merge — all pure). Consumer hooks\n * that hit external services should themselves wrap side effects in\n * `ctx.run` so the substitution / annotation is replay-stable.\n *\n * `isConcurrencySafe` is preserved — Restate's per-key serialization\n * doesn't preclude in-handler parallelism. The loop's scheduler still\n * fans out safe tools up to `behavior.maxConcurrentTools`, each call\n * lands in its own journal entry. Order-of-journal-completion does NOT\n * affect replay correctness: Restate journals by call-site name, not\n * by completion order.\n */\n\nimport type { DetachedTasksCapability } from '../contexts'\nimport type { Session } from '../session'\nimport type { ToolContext, ToolDef } from '../tools/types'\nimport type { ToolResultContent } from '../types'\nimport type { RestatePromiseRaceLike } from './awakeable'\nimport type { RestatePromiseLike } from './parallel'\nimport type { ReplayTracker } from './replay'\nimport type { RestateContextLike, RestateRunOptions } from './types'\nimport { hydrateReadStateFromSessionAsync } from '../tools/read-state'\nimport { coerceToolResultContent } from '../types'\nimport { awakeableWithTimeout } from './awakeable'\nimport { isRestateControlOrAbort, makeSoftToolError, rethrowSoftToolError } from './soft-errors'\n\n/**\n * Opt-in two-phase journaling for long-running, re-attachable tools.\n *\n * The default `restateTool` wrapping journals only the COMPLETED result —\n * a crash mid-execute re-runs the tool on replay, which is unacceptable\n * for builds / migrations / deploys. `durableStart` splits the execution:\n *\n * 1. `start` runs inside its own `ctx.run` entry, journaled BEFORE the\n * body — it kicks off the side effect and returns a re-attach token\n * (a background task id, a job handle, an idempotency key).\n * 2. the wait — either `attach` (one `ctx.run` holding the wait in the\n * result entry; only for short, bounded waits) or `wait` (awakeable\n * park: register a resumer in a journaled entry, suspend outside\n * the journal, synthesize the result in a final entry). On replay\n * both receive the SAME token and re-attach to the already-running\n * work instead of starting it again.\n *\n * The wrapped tool's own `execute` is bypassed; the start + wait pair IS\n * the execution.\n */\nexport interface RestateDurableStart<Token = unknown, Resumed = unknown> {\n /** Kick off the side effect; journaled before `attach`. Must be cheap + idempotent-safe up to journal persistence. */\n start: (input: Record<string, unknown>, toolCtx: ToolContext) => Promise<Token> | Token\n /**\n * Await / re-attach to the work identified by `token` and produce the\n * tool result. Runs inside ONE `ctx.run` entry, so the body must\n * settle within the runtime's attempt lifecycle — a long busy-poll in\n * here starves the journal, trips the server's inactivity/abort\n * timeouts, and each retry restarts the wait from scratch. Use this\n * only for waits bounded well below the inactivity timeout (or as the\n * degraded mode on hosts without a push seam); prefer {@link wait}\n * for anything long-running.\n *\n * Required unless {@link wait} is provided; ignored when both are set.\n */\n attach?: (token: Token, input: Record<string, unknown>, toolCtx: ToolContext) => Promise<string | ToolResultContent[]>\n /**\n * Awakeable-based completion wait — the durable alternative to\n * {@link attach} for long-running work on hosts with a push seam\n * (e.g. a runner that fires `task:exit` → resumer → `ctx.resolveAwakeable`).\n * `executeTwoPhase` orchestrates three phases with the same journal\n * discipline as `restateAwakeableTool`:\n *\n * 1. `register` — a short, journaled `ctx.run`: hand the awakeable\n * id to the host as the exit resumer for `token`. Fires exactly\n * once across replays (marker invariant included).\n * 2. park — `await awakeable.promise`, OUTSIDE any `ctx.run`. The\n * invocation suspends cleanly: no held worker, immune to\n * inactivity/abort timeouts. With `timeoutMs`, the park is a\n * durable race against `ctx.sleep` (replay-stable — no\n * `Date.now()` deadline that resets per attempt).\n * 3. `result` — a final journaled `ctx.run`: synthesize the tool\n * result from the resumer payload (`null` = timeout; kill the\n * job and shape the timeout result here).\n */\n wait?: RestateDurableWait<Token, Resumed>\n /**\n * Best-effort cleanup when the per-call abort signal fires before the\n * wait settles — `attach` or the awakeable park alike (run abort,\n * `agent.cancelTool`, sibling-cascade\n * cancel, `agent.destroy()` mid-run). Without it, the journaled token\n * identifies a remote job that keeps running with nobody attached —\n * a leak for hosts whose jobs outlive the session.\n *\n * Contract:\n * - Fires at most once per call, outside the journal (an aborting\n * invocation can't open new `ctx.run` entries reliably) — journal\n * your own cleanup on the host side if it must be durable.\n * - May run concurrently with a still-unwinding `attach`; make it\n * idempotent against \"job already gone\".\n * - NOT called on process death — that's not termination: the\n * journaled token re-attaches on replay instead. This seam is for\n * deliberate aborts, where no replay is coming.\n * - Errors are swallowed (surfaced under `ZIDANE_DEBUG`) — cleanup\n * failure must not mask the abort itself.\n */\n onAbort?: (token: Token, input: Record<string, unknown>, toolCtx: ToolContext) => Promise<void> | void\n}\n\n/**\n * Awakeable-based completion wait for {@link RestateDurableStart.wait}.\n *\n * Replay contract (mirrors `restateAwakeableTool`):\n * - The awakeable is minted BEFORE the journaled `register` entry, so on\n * replay both come back in the same order with the same id — a replayed\n * call re-parks on the SAME awakeable without re-registering.\n * - The journaled marker records the awakeable id it was registered for;\n * a mismatch on replay (journal drift) throws instead of parking on an\n * id nobody will ever resolve.\n */\nexport interface RestateDurableWait<Token = unknown, Resumed = unknown> {\n /**\n * Register `awakeableId` as the exit resumer for the work identified\n * by `token` — the host must call `ctx.resolveAwakeable(awakeableId,\n * payload)` when the work completes. Runs inside `ctx.run`; must be\n * short and idempotent-safe up to journal persistence.\n */\n register: (token: Token, awakeableId: string, input: Record<string, unknown>, toolCtx: ToolContext) => Promise<void> | void\n /**\n * Synthesize the tool result once the park settles. `resumed` is the\n * resumer's payload, or `null` when `timeoutMs` elapsed first — kill\n * the still-running job and shape the timeout result in that branch.\n * Runs inside the final journaled `ctx.run` (the result entry).\n */\n result: (token: Token, resumed: Resumed | null, input: Record<string, unknown>, toolCtx: ToolContext) => Promise<string | ToolResultContent[]> | string | ToolResultContent[]\n /**\n * Durable park deadline in milliseconds — becomes the\n * `awakeableWithTimeout` duration (a `ctx.sleep` raced against the\n * awakeable, replay-stable). A function receives the call's input so\n * the model's own `timeout` parameter can drive it. Unset /\n * non-positive = park indefinitely.\n */\n timeoutMs?: number | ((input: Record<string, unknown>, toolCtx: ToolContext) => number | undefined)\n /**\n * Durable race combinator for the timeout race — pass `RestatePromise`\n * from the SDK. See `awakeableWithTimeout`'s rationale; native\n * `Promise.race` is the fallback.\n */\n promises?: RestatePromiseRaceLike\n /**\n * Per-call fast path: when this returns `true` for the journaled\n * `token`, the awakeable park is SKIPPED entirely — no awakeable is\n * minted, no `-register` entry is journaled, and the invocation never\n * suspends. `result` is invoked directly with `resumed = null` inside\n * the final result entry.\n *\n * This is for `start` phases that sometimes have nothing to wait on\n * (e.g. a shell tool that only spawns a real background task above a\n * duration threshold and otherwise runs the command inline in\n * `result`). Parking such calls pays a full suspend → resolve →\n * re-invoke → replay round-trip for nothing.\n *\n * MUST be a pure function of the journaled `token` (+ input) so the\n * decision is identical across replays — a token-derived branch keeps\n * the journal entry shape deterministic. When omitted, every call\n * parks (the original behaviour).\n */\n inline?: (token: Token, input: Record<string, unknown>, toolCtx: ToolContext) => boolean\n}\n\n/** Journaled registration marker — see the marker invariant in {@link RestateDurableWait}. */\ninterface DurableWaitRegisterMarker {\n registered: true\n awakeableId: string\n}\n\nexport interface RestateToolOptions<Token = unknown, Resumed = unknown> {\n /**\n * `ctx.run` options forwarded on every wrapped tool call. Defaults to\n * `{ maxRetryAttempts: 1 }` — tool errors are typically deterministic\n * (validation failures, missing files) so blind retries waste budget.\n * Override per-tool for network-heavy custom tools that benefit from\n * SDK-level retries.\n */\n runOptions?: RestateRunOptions\n /**\n * Override the journal-entry name. Receives the canonical tool name, the\n * call's input, and the model's `callId` (when the runtime provides one).\n * Default: `tool-<name>-<seq>` where `<seq>` is a per-wrapper monotonic\n * counter. The counter is replay-stable as long as dispatch order is\n * deterministic; key on `callId` instead for a model-deterministic name\n * that's robust even under `maxConcurrentTools > 1`.\n */\n entryName?: (seq: number, name: string, input: Record<string, unknown>, callId?: string) => string\n /**\n * Hide and reject the built-in shell tool's background mode.\n *\n * Default: derived from {@link RestateToolOptions.detachedTasks} —\n * disabled unless the execution context declares `'durable'` detached\n * tasks. An explicit boolean always wins.\n */\n disableShellBackground?: boolean\n /**\n * `detachedTasks` capability of the execution context the agent will\n * run with (see `ContextCapabilities.detachedTasks` /\n * `resolveDetachedTasksCapability`). Drives the\n * `disableShellBackground` default: a `'durable'` context keeps its\n * background tasks across worker crashes, so the wrapper leaves the\n * shell tool's background mode intact.\n *\n * Default: `undefined`, treated as non-durable (background disabled).\n */\n detachedTasks?: DetachedTasksCapability\n /**\n * Two-phase start/attach journaling for crash-safe long tools — see\n * {@link RestateDurableStart}. Per-tool by nature; not accepted by\n * `wrapAgentTools` (a single start/attach pair can't fit a whole map).\n */\n durableStart?: RestateDurableStart<Token, Resumed>\n /**\n * Per-invocation replay tracker (see `createReplayTracker`). When set,\n * the wrapper marks it live from inside its journaled closures — i.e.\n * the first time a tool body (or a `durableStart.start` phase)\n * ACTUALLY executes rather than replaying from the journal. Share one\n * tracker across the provider and tool wrappers of the same handler\n * invocation.\n */\n replayTracker?: ReplayTracker\n /**\n * Keep an ordinary, recoverable tool throw (a failed shell command, a\n * transport error, an MCP `isError`) NON-fatal under Restate.\n *\n * Without this, the throw rides out of the journaled `ctx.run` action,\n * exhausts the retry budget, and surfaces as a Restate `TerminalError` —\n * which `restateBehavior`'s `shouldRethrowToolError` re-throws, aborting the\n * whole run. With it, the throw is captured INSIDE the journal as a sentinel\n * value and re-thrown as a plain (non-control) error OUTSIDE it, so the loop\n * produces a model-visible `tool_result { isError }` and continues —\n * identical to the non-Restate soft-error model, and the same mechanism\n * `restateMcpToolWrap` already applies to MCP tools. Real Restate control\n * errors and deliberate aborts are never softened.\n *\n * Applies to the single-phase journaling path (the default wrapping and the\n * MCP path). The two-phase {@link RestateToolOptions.durableStart} mode owns\n * its own start/wait error shape and is unaffected.\n *\n * Default: `true`.\n */\n softErrors?: boolean\n /**\n * Collapse malformed structured result blocks (`{ type: 'image' }` with no\n * payload, foreign block shapes) to a text placeholder before the result is\n * journaled, so a downstream provider wire serializer never has to project an\n * unprojectable block (which, under Restate, would throw inside the journaled\n * provider call and become fatal). Well-formed results pass through\n * untouched. Applies to the single-phase journaling path.\n *\n * Default: `true`.\n */\n coerceResultBlocks?: boolean\n}\n\nconst SHELL_BACKGROUND_DISABLED_MESSAGE = 'shell error: background mode is disabled for Restate-backed agents. Fall back to foreground (drop `run_in_background`).'\nconst HYDRATED_READ_STATE_SESSIONS = new WeakSet<Session>()\n\n/**\n * Wrap a single `ToolDef` so its `execute` runs inside `ctx.run`. The\n * tool's `spec` and `isConcurrencySafe` pass through unchanged.\n */\nexport function restateTool<Token = unknown, Resumed = unknown>(\n inner: ToolDef,\n ctx: RestateContextLike,\n options: RestateToolOptions<Token, Resumed> = {},\n): ToolDef {\n const runOpts: RestateRunOptions = options.runOptions ?? { maxRetryAttempts: 1 }\n const nameFor = options.entryName ?? ((seq: number, name: string) => `tool-${name}-${seq}`)\n const canonicalName = inner.spec.name\n const disableShellBackground = options.disableShellBackground ?? (options.detachedTasks !== 'durable')\n const shellBackgroundDisabled = disableShellBackground && canonicalName === 'shell'\n const durableStart = options.durableStart\n if (durableStart && !durableStart.attach && !durableStart.wait)\n throw new Error(`restateTool(${canonicalName}): durableStart needs an \\`attach\\` (in-journal wait) or a \\`wait\\` (awakeable park) phase`)\n let seq = 0\n const hydrateOnce = async (toolCtx: Parameters<ToolDef['execute']>[1]) => {\n if (toolCtx.session && !HYDRATED_READ_STATE_SESSIONS.has(toolCtx.session)) {\n HYDRATED_READ_STATE_SESSIONS.add(toolCtx.session)\n await hydrateReadStateFromSessionAsync(toolCtx.session, toolCtx.handle.cwd, {\n defaultLineNumbers: toolCtx.behavior?.readLineNumbers ?? true,\n readFileForHash: async (path) => {\n try {\n return await toolCtx.execution.readFile(toolCtx.handle, path)\n }\n catch {\n return null\n }\n },\n })\n }\n }\n const softErrors = options.softErrors ?? true\n const coerceBlocks = options.coerceResultBlocks ?? true\n\n // The journaled action. NOT async, and the raw `ctx.run` promise is returned\n // without native combinators so `durableExecute` consumers (the Restate\n // batch scheduler) keep the runtime's own promise shape (`.map`) intact.\n //\n // Soft errors are captured INSIDE the closure: a recoverable throw is\n // recorded as a sentinel *value*, never a failed action — that's what keeps\n // `ctx.run` from promoting it to a fatal `TerminalError`. The sentinel is\n // turned back into a throw OUTSIDE the journal (see `executeDurably` /\n // `durableExecuteImpl`). Control / abort throws are never softened.\n const runJournaled = (input: Record<string, unknown>, toolCtx: Parameters<ToolDef['execute']>[1]) => {\n seq += 1\n return ctx.run(\n nameFor(seq, canonicalName, input, toolCtx.callId),\n async () => {\n // Closure executes only when live — replays return the journaled\n // result without entering here.\n options.replayTracker?.markLive()\n await hydrateOnce(toolCtx)\n if (shellBackgroundDisabled && input.run_in_background === true)\n return SHELL_BACKGROUND_DISABLED_MESSAGE\n if (!softErrors) {\n const out = await inner.execute(input, toolCtx)\n return coerceBlocks ? coerceToolResultContent(out) : out\n }\n try {\n const out = await inner.execute(input, toolCtx)\n return coerceBlocks ? coerceToolResultContent(out) : out\n }\n catch (err) {\n if (isRestateControlOrAbort(err, toolCtx.signal as AbortSignal | undefined))\n throw err\n return makeSoftToolError(err) as unknown as string\n }\n },\n runOpts,\n )\n }\n\n // Plain `execute`: await the journaled value and re-throw a captured soft\n // error outside the journal. When soft errors are off, the raw mappable\n // promise is the execute (unchanged legacy shape).\n const executeDurably: ToolDef['execute'] = softErrors\n ? async (input, toolCtx) => rethrowSoftToolError(await runJournaled(input, toolCtx))\n : runJournaled\n\n // `durableExecute`: compose the same soft-error unwrap INTO the runtime's\n // mappable promise so the batch scheduler still receives a `.map`-able value.\n // A softened throw becomes a rejected mapped promise, which the scheduler\n // routes to a `tool_result { isError }` (never fatal). Falls back to the raw\n // promise on a non-mappable ctx so the loop's durable guard can report it.\n const durableExecuteImpl: ToolDef['durableExecute'] = softErrors\n ? (input, toolCtx) => unwrapDurableSoftError(runJournaled(input, toolCtx))\n : runJournaled\n\n // Two-phase mode: journal the start token BEFORE the body so a crash\n // mid-execution re-attaches on replay instead of re-running. The await\n // between the two entries makes this a native-async composition, so the\n // tool deliberately does NOT advertise `durableExecute` — the batch\n // scheduler runs it sequentially via plain `execute`, which is the\n // right shape for long re-attachable work anyway.\n const executeTwoPhase = async (input: Record<string, unknown>, toolCtx: Parameters<ToolDef['execute']>[1]) => {\n const start = durableStart!\n seq += 1\n const entry = nameFor(seq, canonicalName, input, toolCtx.callId)\n const token = await ctx.run(\n `${entry}-start`,\n async () => {\n options.replayTracker?.markLive()\n await hydrateOnce(toolCtx)\n return start.start(input, toolCtx)\n },\n runOpts,\n )\n\n // Abort seam — see RestateDurableStart.onAbort. At-most-once via the\n // `fired` latch; armed only while the wait is in flight.\n const onAbort = start.onAbort\n const signal = toolCtx.signal as AbortSignal | undefined\n let fired = false\n const fireAbortCleanup = (): void => {\n if (fired || !onAbort)\n return\n fired = true\n Promise.resolve(onAbort(token, input, toolCtx)).catch((err: unknown) => {\n if (process.env.ZIDANE_DEBUG)\n process.stderr.write(`[zidane/restate] durableStart onAbort threw: ${err instanceof Error ? err.message : String(err)}\\n`)\n })\n }\n\n const wait = start.wait\n if (wait) {\n // Per-call fast path: nothing to wait on for this token (decided\n // purely from the journaled token, so replay-stable). Skip minting\n // the awakeable, the `-register` entry, and the suspend/resume\n // round-trip entirely — run the result inline. A short command that\n // executes in the result entry shouldn't pay a park it never uses.\n if (wait.inline?.(token, input, toolCtx)) {\n if (!onAbort || !signal) {\n return await ctx.run(entry, () => {\n options.replayTracker?.markLive()\n return wait.result(token, null, input, toolCtx)\n }, runOpts)\n }\n if (signal.aborted)\n fireAbortCleanup()\n else\n signal.addEventListener('abort', fireAbortCleanup, { once: true })\n try {\n return await ctx.run(entry, () => {\n options.replayTracker?.markLive()\n return wait.result(token, null, input, toolCtx)\n }, runOpts)\n }\n finally {\n signal.removeEventListener('abort', fireAbortCleanup)\n }\n }\n // Awakeable path — register / park / result. The park lives\n // OUTSIDE any ctx.run, so the invocation suspends cleanly instead\n // of busy-holding an attempt until the inactivity timeout fires.\n //\n // Pre-aborted: nobody will consume the result — clean up the\n // journaled start and bail without registering a resumer.\n if (signal?.aborted) {\n fireAbortCleanup()\n throw new Error(`${canonicalName}: aborted before durable wait registration`)\n }\n signal?.addEventListener('abort', fireAbortCleanup, { once: true })\n try {\n const timeoutMs = typeof wait.timeoutMs === 'function' ? wait.timeoutMs(input, toolCtx) : wait.timeoutMs\n // Mint BEFORE the journaled registration (same ordering contract\n // as restateAwakeableTool) — replay returns the same id.\n const awakeable = awakeableWithTimeout<Resumed>(ctx, {\n ...(timeoutMs !== undefined ? { timeoutMs } : {}),\n ...(wait.promises ? { promises: wait.promises } : {}),\n })\n const marker = await ctx.run<DurableWaitRegisterMarker>(\n `${entry}-register`,\n async () => {\n options.replayTracker?.markLive()\n await wait.register(token, awakeable.id, input, toolCtx)\n return { registered: true, awakeableId: awakeable.id }\n },\n runOpts,\n )\n if (marker.awakeableId !== awakeable.id) {\n throw new Error(\n `restateTool(${canonicalName}): journal drift — registration marker carries awakeable \"${marker.awakeableId}\" but this replay minted \"${awakeable.id}\". Refusing to park on an unreachable awakeable.`,\n )\n }\n const resumed = await parkWithSignal(awakeable.promise, signal, canonicalName)\n return await ctx.run(\n entry,\n () => {\n options.replayTracker?.markLive()\n return wait.result(token, resumed, input, toolCtx)\n },\n runOpts,\n )\n }\n finally {\n signal?.removeEventListener('abort', fireAbortCleanup)\n }\n }\n\n const attach = () => ctx.run(\n entry,\n () => {\n options.replayTracker?.markLive()\n return start.attach!(token, input, toolCtx)\n },\n runOpts,\n )\n\n if (!onAbort || !signal)\n return attach()\n\n // Pre-aborted: the journaled start already launched the job — clean\n // it up, then still run attach so the call surfaces the host's own\n // cancellation shape (it should fail fast on an aborted signal).\n if (signal.aborted) {\n fireAbortCleanup()\n return attach()\n }\n signal.addEventListener('abort', fireAbortCleanup, { once: true })\n try {\n return await attach()\n }\n finally {\n signal.removeEventListener('abort', fireAbortCleanup)\n }\n }\n\n if (durableStart) {\n // Strip any pre-existing `durableExecute` — see the executeTwoPhase\n // comment; advertising one here would hand the batch scheduler a\n // native promise it can't `.map`.\n const { durableExecute: _dropped, ...rest } = inner\n return {\n ...rest,\n spec: shellBackgroundDisabled ? withoutShellBackgroundInput(inner.spec) : inner.spec,\n execute: executeTwoPhase,\n }\n }\n\n return {\n ...inner,\n spec: shellBackgroundDisabled ? withoutShellBackgroundInput(inner.spec) : inner.spec,\n execute: executeDurably,\n durableExecute: durableExecuteImpl,\n }\n}\n\n/**\n * Compose the soft-error unwrap into the runtime's mappable durable promise.\n * A journaled sentinel becomes a thrown (rejected) value so the Restate batch\n * scheduler classifies it as a tool failure → `tool_result { isError }`; a real\n * action failure (control error) is rethrown verbatim. Non-mappable promises\n * (a ctx without the SDK's `RestatePromise`) pass through so the loop's durable\n * guard surfaces the \"not a mappable durable promise\" error instead.\n */\nfunction unwrapDurableSoftError(\n promise: Promise<string | ToolResultContent[]>,\n): Promise<string | ToolResultContent[]> {\n const mappable = promise as Partial<RestatePromiseLike<string | ToolResultContent[]>>\n if (typeof mappable.map !== 'function')\n return promise\n return mappable.map((value, failure) => {\n if (failure !== undefined)\n throw failure instanceof Error ? failure : new Error(String(failure))\n return rethrowSoftToolError(value as string | ToolResultContent[])\n })\n}\n\n/**\n * Park on `promise`, but stop waiting when the per-call abort signal\n * fires (run abort, `cancelTool`, sibling-cascade cancel) — a deliberate\n * abort means nobody will consume the result, and like `onAbort` it\n * implies no replay is coming, so the native (non-journaled) race is\n * replay-safe. The underlying awakeable stays registered; a late\n * resolution lands on a completed invocation and is dropped by the\n * runtime.\n */\nfunction parkWithSignal<T>(promise: Promise<T>, signal: AbortSignal | undefined, name: string): Promise<T> {\n if (!signal)\n return promise\n if (signal.aborted)\n return Promise.reject(new Error(`${name}: aborted while parked on durable wait`))\n return new Promise<T>((resolve, reject) => {\n const onAbortEvt = (): void => reject(new Error(`${name}: aborted while parked on durable wait`))\n signal.addEventListener('abort', onAbortEvt, { once: true })\n promise.then(\n (value) => {\n signal.removeEventListener('abort', onAbortEvt)\n resolve(value)\n },\n (err: unknown) => {\n signal.removeEventListener('abort', onAbortEvt)\n reject(err instanceof Error ? err : new Error(String(err)))\n },\n )\n })\n}\n\nfunction withoutShellBackgroundInput(spec: ToolDef['spec']): ToolDef['spec'] {\n const inputSchema = spec.inputSchema\n const properties = isRecord(inputSchema.properties) ? inputSchema.properties : undefined\n if (!properties || !Object.hasOwn(properties, 'run_in_background'))\n return spec\n\n const { run_in_background: _runInBackground, ...nextProperties } = properties\n const required = Array.isArray(inputSchema.required)\n ? inputSchema.required.filter(name => name !== 'run_in_background')\n : inputSchema.required\n return {\n ...spec,\n description: stripShellBackgroundDescription(spec.description),\n inputSchema: {\n ...inputSchema,\n properties: nextProperties,\n ...(required !== inputSchema.required ? { required } : {}),\n },\n }\n}\n\nfunction stripShellBackgroundDescription(description: string): string {\n return description\n .split('\\n')\n .filter(line =>\n !line.includes('run_in_background')\n && !line.includes('<task-notification>')\n && !line.includes('background task'),\n )\n .join('\\n')\n .replace(/\\n{3,}/g, '\\n\\n')\n .trim()\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n\n/**\n * Wrap an entire tool map at once — convenience for the common case of\n * \"journal every tool the agent has\". Pass-through for tools whose\n * names are listed in `opts.exclude` (e.g. fully-deterministic local\n * helpers where journaling is pure overhead).\n *\n * The returned map is a fresh object; the input is untouched.\n */\nexport function wrapAgentTools(\n tools: Record<string, ToolDef>,\n ctx: RestateContextLike,\n opts: Omit<RestateToolOptions, 'durableStart'> & { exclude?: readonly string[] } = {},\n): Record<string, ToolDef> {\n const excludeSet = new Set(opts.exclude ?? [])\n // `detachedTasks: 'durable'` implies the host's `waitBackground` parks\n // on an awakeable (that's the durable wait pattern) — and a Restate\n // suspension point must NOT nest inside a journaled `ctx.run` closure.\n // Auto-exclude the built-in `wait_task` from wrapping so its park runs\n // outside the journal; the wait result is replay-safe anyway (a replayed\n // wait re-attaches to an already-terminated task and resolves from the\n // registry). Hosts with a journal-safe wait (e.g. a bridge RPC poll)\n // can re-wrap explicitly via `restateTool(waitTask, ctx, …)`.\n const skipWaitTask = opts.detachedTasks === 'durable'\n const wrapped: Record<string, ToolDef> = {}\n for (const [name, def] of Object.entries(tools)) {\n const passThrough = excludeSet.has(name) || (skipWaitTask && def.spec.name === 'wait_task')\n wrapped[name] = passThrough ? def : restateTool(def, ctx, opts)\n }\n return wrapped\n}\n","/**\n * Restate-backed MCP tool journaling.\n *\n * Native tools have a clean durability seam: wrap them with\n * `wrapAgentTools(tools, ctx)` before `createAgent`. MCP tools don't — they are\n * discovered from `mcpServers` and registered by the agent internally, AFTER\n * your wrapping opportunity. So under Restate their raw `callTool` never rides\n * `ctx.run`, and every journal replay re-runs the real MCP call (a\n * side-effecting tool fires once per replay).\n *\n * {@link restateMcpToolWrap} closes that gap. It's the value for the core\n * `AgentOptions.mcpToolWrap` hook — the agent keeps owning discovery,\n * `mcp_<server>_<tool>` namespacing, per-server `instructions`, hooks, and\n * OAuth, and applies the wrap to each discovered tool. You journal MCP results\n * the way `wrapAgentTools` journals native ones:\n *\n * ```ts\n * createAgent({\n * provider: restateProvider(inner, ctx),\n * tools: wrapAgentTools(nativeTools, ctx),\n * mcpServers,\n * mcpToolWrap: restateMcpToolWrap(ctx),\n * })\n * ```\n *\n * The hook composes with any `mcpConnector`, so a custom transport / auth\n * connector and journaling stay orthogonal — no separate connector helper\n * needed:\n *\n * ```ts\n * createAgent({\n * mcpServers,\n * mcpConnector: (configs, hooks) => connectMcpServers(configs, undefined, hooks, { buildAuthProvider }),\n * mcpToolWrap: restateMcpToolWrap(ctx),\n * })\n * ```\n *\n * ## Error semantics (preserved)\n *\n * MCP tools signal failure by THROWING (`buildMcpToolDef` throws on transport\n * errors, timeouts, and `CallToolResult.isError`). Naively wrapping that in\n * `restateTool` would let the throw exhaust `ctx.run`'s retries and surface as\n * a Restate `TerminalError`, which `restateBehavior`'s `shouldRethrowToolError`\n * re-throws — turning a recoverable MCP error into a fatal run. To keep the\n * non-Restate behaviour (MCP error → model-visible `tool_result { isError }`,\n * run continues) the wrapper journals with `restateTool`'s `softErrors`: the\n * failure is captured INSIDE the journaled closure as a sentinel value and\n * re-thrown as a plain (non-control) error OUTSIDE it. Replay reproduces the\n * same error from the journal without re-running the call; real Restate control\n * / abort errors are passed through untouched. (Native tools wrapped with\n * `wrapAgentTools` get the identical treatment — this is no longer MCP-specific\n * plumbing, just the shared default.)\n *\n * ## Journaling policy\n *\n * Default is plain result-journaling — correct for the short request/response\n * shape of most MCP calls. A genuinely long-running MCP tool (a remote build,\n * a migration) can opt into two-phase `durableStart` per-tool via\n * {@link RestateMcpToolWrapOptions.override}; `exclude` skips journaling for\n * deterministic reads.\n */\n\nimport type { McpToolMeta, McpToolWrap } from '../agent'\nimport type { ToolDef } from '../tools/types'\nimport type { ReplayTracker } from './replay'\nimport type { RestateToolOptions } from './tool'\nimport type { RestateContextLike, RestateRunOptions } from './types'\nimport { restateTool } from './tool'\n\nexport interface RestateMcpToolWrapOptions {\n /**\n * Shared per-invocation replay tracker (see `createReplayTracker`) —\n * threaded into every wrapped MCP tool so the first live `callTool` marks\n * the tracker live, exactly like `restateProvider` / `wrapAgentTools`. Use\n * one tracker per handler invocation across provider + native + MCP tools.\n */\n replayTracker?: ReplayTracker\n /**\n * `ctx.run` options forwarded to every wrapped MCP tool (default\n * `{ maxRetryAttempts: 1 }`). Note: recoverable MCP failures are\n * soft-captured as the journal value rather than thrown, so this retry\n * budget governs only Restate control-flow retries of the journaled action,\n * not re-dialing a failed MCP call — the model decides whether to retry.\n */\n runOptions?: RestateRunOptions\n /**\n * Override the journal-entry name per MCP tool call. Default:\n * `tool-<name>-<callId>` (model-deterministic, robust under concurrency)\n * falling back to `tool-<name>-<seq>` when the runtime provides no `callId`.\n */\n entryName?: (seq: number, name: string, input: Record<string, unknown>, callId?: string) => string\n /**\n * Namespaced MCP tool names (`mcp_<server>_<tool>`) to leave un-journaled —\n * they pass through exactly as discovered. For deterministic,\n * side-effect-free reads where journaling is pure overhead. Wins over\n * {@link override}.\n */\n exclude?: readonly string[]\n /**\n * Per-tool wrapping override. Receives the discovered tool + its\n * {@link McpToolMeta}; return a `ToolDef` to use verbatim (e.g.\n * `restateTool(tool, ctx, { durableStart })` for a long-running tool), or\n * `undefined` to fall through to the default soft-error result-journaling.\n * Lets a deployment opt specific tools into a different policy without\n * changing the blanket one.\n */\n override?: (tool: ToolDef, meta: McpToolMeta) => ToolDef | undefined\n}\n\n/**\n * Journal one discovered MCP tool via `restateTool` with `softErrors` on (a\n * recoverable MCP throw becomes a journaled `tool_result { isError }`, not a\n * fatal run — see the module's \"Error semantics\"). `durableExecute` is dropped:\n * MCP tools are concurrency barriers, so the batch scheduler runs them via the\n * (still journaled) `execute`, and dropping the mappable promise keeps the\n * scheduler from treating an MCP tool as a parallel-fleet member.\n */\nfunction journalMcpTool(tool: ToolDef, ctx: RestateContextLike, toolOptions: RestateToolOptions): ToolDef {\n const journaled = restateTool(tool, ctx, { ...toolOptions, softErrors: true, coerceResultBlocks: true })\n const { durableExecute: _dropped, ...rest } = journaled\n return rest\n}\n\nfunction toToolOptions(options: RestateMcpToolWrapOptions): RestateToolOptions {\n const entryName = options.entryName\n ?? ((seq: number, name: string, _input: Record<string, unknown>, callId?: string) =>\n callId ? `tool-${name}-${callId}` : `tool-${name}-${seq}`)\n return {\n entryName,\n ...(options.replayTracker !== undefined ? { replayTracker: options.replayTracker } : {}),\n ...(options.runOptions !== undefined ? { runOptions: options.runOptions } : {}),\n }\n}\n\n/**\n * Build an {@link McpToolWrap} for the `AgentOptions.mcpToolWrap` hook —\n * journals every discovered MCP tool's result (soft-error-preserving). The\n * MCP analogue of `wrapAgentTools`, and the single supported way to make\n * discovered MCP tools durable under Restate.\n */\nexport function restateMcpToolWrap(\n ctx: RestateContextLike,\n options: RestateMcpToolWrapOptions = {},\n): McpToolWrap {\n const excludeSet = new Set(options.exclude ?? [])\n const toolOptions = toToolOptions(options)\n return (tool, meta) => {\n if (excludeSet.has(tool.spec.name))\n return tool\n return options.override?.(tool, meta) ?? journalMcpTool(tool, ctx, toolOptions)\n }\n}\n","import type { ToolResult } from '../providers'\nimport type { ToolBatchExecutionContext, ToolBatchExecutor } from '../types'\n\nexport interface RestatePromiseAllLike<TPromise extends Promise<unknown> = RestatePromiseLike<unknown>> {\n all: (values: readonly TPromise[]) => Promise<readonly unknown[]>\n}\n\nexport type RestatePromiseLike<T> = Promise<T> & {\n map: <U>(mapper: (value?: T, failure?: unknown) => U) => Promise<U>\n}\n\nexport interface RestateToolBatchExecutorOptions<TPromise extends Promise<unknown> = RestatePromiseLike<unknown>> {\n /**\n * Wait for a safe fleet through Restate's durable combinator. Pass\n * `RestatePromise` from `@restatedev/restate-sdk` in real deployments.\n */\n promises: RestatePromiseAllLike<TPromise>\n}\n\n/**\n * Tool batch scheduler for Restate-backed agents.\n *\n * It preserves unsafe-tool barriers and emits results in model submission\n * order. Safe fleets are started in submission order, capped by\n * `maxConcurrentTools`, and joined via the supplied durable `all()`.\n */\nexport function restateToolBatchExecutor<TPromise extends Promise<unknown> = RestatePromiseLike<unknown>>(\n options: RestateToolBatchExecutorOptions<TPromise>,\n): ToolBatchExecutor {\n return async (ctx: ToolBatchExecutionContext): Promise<ToolResult[]> => {\n const results: ToolResult[] = []\n const { toolCalls } = ctx\n\n const fillRemaining = (from: number, factory: (index: number) => ToolResult): ToolResult[] => {\n for (let i = from; i < toolCalls.length; i++)\n results[i] = factory(i)\n return results\n }\n\n for (let i = 0; i < toolCalls.length;) {\n if (ctx.signal.aborted)\n return fillRemaining(i, ctx.interruptedResult)\n if (ctx.steeringQueue.length > 0)\n return fillRemaining(i, ctx.skippedResult)\n\n if (!ctx.isConcurrencySafe(i)) {\n results[i] = await ctx.execute(i)\n i += 1\n continue\n }\n\n const start = i\n const fleet: number[] = []\n while (\n i < toolCalls.length\n && ctx.isConcurrencySafe(i)\n && fleet.length < ctx.maxConcurrentTools\n ) {\n fleet.push(i)\n i += 1\n }\n\n const fleetResults = fleet.every(index => ctx.canExecuteDurably(index))\n ? await ctx.executeDurable(\n fleet,\n async <T>(values: readonly Promise<T>[]): Promise<readonly T[]> => {\n const results = await options.promises.all(values as readonly TPromise[])\n return results as readonly T[]\n },\n )\n : await executeSequential(ctx, fleet)\n for (let offset = 0; offset < fleetResults.length; offset++)\n results[start + offset] = fleetResults[offset]\n }\n\n return results\n }\n}\n\nasync function executeSequential(\n ctx: ToolBatchExecutionContext,\n indices: readonly number[],\n): Promise<ToolResult[]> {\n const results: ToolResult[] = []\n for (const index of indices) {\n if (ctx.signal.aborted) {\n results.push(ctx.interruptedResult(index))\n continue\n }\n if (ctx.steeringQueue.length > 0) {\n results.push(ctx.skippedResult(index))\n continue\n }\n results.push(await ctx.execute(index))\n }\n return results\n}\n","/**\n * Restate-backed Provider wrapper.\n *\n * Wraps `Provider.stream` so every assistant turn (the LLM call as a\n * whole) is journaled. The model is invoked once per turn — the live\n * stream still fires `onText` / `onThinking` callbacks for UX during the\n * original execution. On replay, `ctx.run` returns the journaled\n * `TurnResult` immediately and the inner provider is NEVER re-invoked →\n * no duplicate billed tokens, no duplicate stream chunks.\n *\n * Replay caveat: stream callbacks don't re-fire on replay. Consumers\n * that paint live UI from `stream:text` should reconstruct transcripts\n * from `session.turns` via `eventsFromTurns` (zidane/chat) instead of\n * relying on hook re-emission. The chat layer already does this.\n *\n * Journal-entry naming: a monotonic per-wrapper counter (`llm-call-1`,\n * `llm-call-2`, …). One wrapper instance per Restate handler invocation\n * resets the counter; Restate's journal is invocation-scoped so names\n * don't need to be globally unique. The counter ticks the same way on\n * replay because the wrapper is constructed fresh each attempt.\n */\n\nimport type { Provider, StreamCallbacks, StreamOptions, TurnResult } from '../providers'\nimport type { ReplayTracker } from './replay'\nimport type { RestateContextLike, RestateRunOptions } from './types'\n\nexport interface RestateProviderOptions {\n /**\n * `ctx.run` options forwarded on every wrapped stream call.\n *\n * Default depends on {@link streamCallbacks}:\n *\n * - `'suppress'` → `{ maxRetryAttempts: 3 }` — provider transients\n * (rate limits, 5xx, connection resets) get retried inside the\n * journal entry; nothing streams to the host, so a retry is\n * invisible.\n * - `'live'` (the default) → `{ maxRetryAttempts: 1 }`. A live stream\n * that fails AFTER emitting deltas would be re-run inside the same\n * journal entry, re-firing `onText` into the loop's accumulating\n * text buffer and producing duplicated partial1+full2 output. The\n * loop's own retry (which only re-issues on a clean slate) is the\n * correct retry layer in live mode.\n *\n * Once the cap is reached the failure becomes terminal and surfaces\n * through the loop's normal `AgentProviderError` path. Set this\n * explicitly to override either default — but with live callbacks,\n * `maxRetryAttempts > 1` re-introduces the duplicate-delta hazard.\n */\n runOptions?: RestateRunOptions\n /**\n * Override the journal-entry name. Receives the 1-indexed sequence\n * number for this wrapper instance and the `StreamOptions` of the\n * call. Default: `llm-call-<n>`. Override to inject extra structure\n * (e.g. `${agentName}/llm-call-${n}`) when multiple agents share a\n * service.\n */\n entryName?: (seq: number, opts: StreamOptions) => string\n /**\n * Whether live stream callbacks should fire during the original execution.\n * Use `'suppress'` for strict durable mode: the model call still returns a\n * full TurnResult, and UIs reconstruct from persisted session turns.\n *\n * Default: `'live'`.\n */\n streamCallbacks?: 'live' | 'suppress'\n /**\n * Per-invocation replay tracker (see `createReplayTracker`). When set,\n * the wrapper marks it live from inside the journaled closure — i.e.\n * the first time the inner provider is ACTUALLY invoked rather than\n * replayed from the journal. Share one tracker across the provider\n * and tool wrappers of the same handler invocation.\n */\n replayTracker?: ReplayTracker\n}\n\n/**\n * Wrap a Zidane `Provider` so its `stream()` method journals each turn's\n * response inside `ctx.run`. All other Provider methods (`formatTools`,\n * `userMessage`, `toolResultsMessage`, `classifyError`, …) pass through\n * unchanged — they're pure functions over already-deterministic inputs.\n */\nexport function restateProvider(\n inner: Provider,\n ctx: RestateContextLike,\n options: RestateProviderOptions = {},\n): Provider {\n // Live callbacks must not retry inside the journal entry — a stream that\n // fails after emitting deltas would re-fire `onText` on the retry and\n // duplicate text in the loop's accumulator. See the `runOptions` doc.\n const runOpts: RestateRunOptions = options.runOptions\n ?? (options.streamCallbacks === 'suppress' ? { maxRetryAttempts: 3 } : { maxRetryAttempts: 1 })\n const nameFor = options.entryName ?? ((seq: number) => `llm-call-${seq}`)\n let seq = 0\n\n return {\n ...inner,\n stream(streamOpts: StreamOptions, callbacks: StreamCallbacks): Promise<TurnResult> {\n seq += 1\n const durableCallbacks = options.streamCallbacks === 'suppress'\n ? suppressStreamingCallbacks(callbacks)\n : callbacks\n return ctx.run<TurnResult>(\n nameFor(seq, streamOpts),\n () => {\n // Reached only when the journal cursor is past this entry —\n // a replayed call returns the journaled TurnResult without\n // executing this closure.\n options.replayTracker?.markLive()\n return inner.stream(streamOpts, durableCallbacks)\n },\n runOpts,\n )\n },\n }\n}\n\nfunction suppressStreamingCallbacks(callbacks: StreamCallbacks): StreamCallbacks {\n return {\n ...callbacks,\n onText: () => {},\n onThinking: undefined,\n onServerToolUse: undefined,\n onServerToolResult: undefined,\n onToolCallDelta: undefined,\n }\n}\n","/**\n * Replay-state tracking + replay-aware abort for Restate-backed agents.\n *\n * ## The problem\n *\n * `agent.abort()` during a journal replay is undefined behavior: the\n * loop throws `AgentAbortedError` at whatever point the replay cursor\n * happens to be, the host's catch arm typically journals something\n * (`report-fail`, a status write) mid-journal, and the invocation dies\n * with `[570 Journal mismatch]` — permanently, because every retry\n * replays into the same mismatch. Hosts have been inferring liveness\n * from side channels (e.g. counting live provider stream calls), which\n * works only because `restateProvider` replays `llm-call-N` without\n * touching the live provider — incidental coupling, not API.\n *\n * ## The seam\n *\n * The wrappers already know the answer: on replay, `ctx.run` returns\n * the journaled value WITHOUT invoking the wrapped closure; the first\n * time a closure actually executes, the journal cursor is past the\n * replayed prefix and the invocation is live. {@link createReplayTracker}\n * packages that signal:\n *\n * - `restateProvider(inner, ctx, { replayTracker })` and\n * `restateTool(tool, ctx, { replayTracker })` mark the tracker live\n * from inside their journaled closures.\n * - `tracker.isReplaying()` is the public liveness probe.\n * - `tracker.onLive(cb)` fires once at the replay→live transition\n * (immediately when already live).\n * - {@link replayAwareAbort} wraps `agent.abort` so external aborts\n * queue during replay and apply at the first live boundary — the\n * earliest point where the abort's side effects (loop throw, host\n * catch-arm journaling) append to the journal instead of forking it.\n *\n * ## Wiring\n *\n * ```ts\n * const tracker = createReplayTracker({ hooks: agent.hooks })\n * const provider = restateProvider(inner, ctx, { replayTracker: tracker })\n * const tools = wrapAgentTools(agentTools, ctx, { replayTracker: tracker })\n * const abort = replayAwareAbort(tracker, () => agent.abort())\n * // external cancel signal → abort() instead of agent.abort()\n * ```\n *\n * One tracker per handler invocation — like the wrappers themselves, it\n * is constructed fresh each attempt and must not be reused across\n * invocations.\n *\n * ## Semantics fine print\n *\n * \"Replaying\" is defined conservatively: `isReplaying()` returns `true`\n * until the first live closure executes. A fresh (non-resumed)\n * invocation therefore reports \"replaying\" for the short window before\n * its first journaled call — harmless for the abort use case (the abort\n * applies moments later, at that first live execution) and the honest\n * answer for journal safety: before the first `ctx.run` settles you\n * cannot know whether the SDK is about to feed you journal entries.\n *\n * That conservative window is wrong for live STREAMING, though: on a\n * fresh run it would suppress the opening output. Streamers should pass\n * `resuming` (the host knows whether this is a crash-recovery replay) and\n * gate on {@link ReplayTracker.isResuming} instead — `false` from the\n * start of a fresh run, `true` only while replaying a resumed journal.\n *\n * A replay that completes without ever going live (the journaled run\n * already finished; the handler exits during replay) never fires\n * `onLive` — queued aborts are dropped with the invocation, which is\n * correct: there is nothing left to abort.\n */\n\n/** Minimal structural slice of the agent's Hookable for `replay:done`. */\nexport interface ReplayDoneHooks {\n callHook: (name: 'replay:done', ctx: Record<string, never>) => unknown\n}\n\nexport interface ReplayTrackerOptions {\n /**\n * Agent hooks to notify at the replay→live transition. When set, the\n * tracker fires `replay:done` exactly once, right after the `onLive`\n * callbacks. Rejections are swallowed (surfaced under `ZIDANE_DEBUG`)\n * — a misbehaving listener must not break the live execution that\n * triggered the transition.\n */\n hooks?: ReplayDoneHooks\n /**\n * Whether THIS invocation is resuming a prior journal (a crash-recovery /\n * resume replay) rather than running fresh. The host supplies it — it's the\n * one bit the tracker can't infer on its own (before the first `ctx.run`\n * settles, \"fresh, not yet live\" and \"replaying a resumed journal\" look\n * identical from inside the wrappers). Determine it from your own state: e.g.\n * the bound object already has persisted session turns, or the SDK reports a\n * non-first attempt.\n *\n * Powers {@link ReplayTracker.isResuming} — the probe streaming consumers\n * should gate on (vs {@link ReplayTracker.isReplaying}, which stays\n * conservative for the abort/journal-safety use case). On a fresh invocation\n * (`resuming: false`, the default) `isResuming()` is `false` from the very\n * start, so a streamer emits the opening deltas / start-step instead of\n * suppressing them until the first journaled call settles.\n */\n resuming?: boolean\n}\n\nexport interface ReplayTracker {\n /**\n * `true` until the first live (non-journaled) execution of a wrapped\n * provider stream / tool body. See the module doc for the fresh-\n * invocation caveat. Use this for journal-safety decisions (deferred\n * abort) where the conservative answer is the correct one.\n */\n isReplaying: () => boolean\n /**\n * `true` only while ACTIVELY replaying a resumed journal — i.e. the\n * invocation was constructed with `resuming: true` AND hasn't gone live\n * yet. Always `false` on a fresh invocation (`resuming: false`).\n *\n * This is the probe for live-streaming consumers: gate emission on\n * `!isResuming()` to suppress re-emitted deltas during a resume replay\n * while still emitting the opening output of a fresh run. (Contrast\n * {@link isReplaying}, which is conservatively `true` at the start of a\n * fresh run too.)\n */\n isResuming: () => boolean\n /**\n * Register a callback for the replay→live transition. Fires once.\n * When the tracker is already live, the callback runs synchronously\n * before `onLive` returns. Returns an unregister function (no-op\n * after firing).\n */\n onLive: (cb: () => void) => () => void\n /**\n * Mark the invocation live. Called by the wrappers from inside their\n * journaled closures — a closure only executes when the journal\n * cursor is past it. Idempotent; only the first call transitions.\n */\n markLive: () => void\n}\n\n/**\n * Create a per-invocation replay tracker. Pass it to `restateProvider`\n * / `restateTool` / `wrapAgentTools` via their `replayTracker` option;\n * consume it via `isReplaying()` / `onLive()` / {@link replayAwareAbort}.\n */\nexport function createReplayTracker(options: ReplayTrackerOptions = {}): ReplayTracker {\n let live = false\n let callbacks: (() => void)[] = []\n const resuming = options.resuming === true\n\n return {\n isReplaying: () => !live,\n isResuming: () => resuming && !live,\n markLive: () => {\n if (live)\n return\n live = true\n const pending = callbacks\n callbacks = []\n for (const cb of pending) {\n try {\n cb()\n }\n catch (err) {\n if (process.env.ZIDANE_DEBUG)\n process.stderr.write(`[zidane/restate] onLive callback threw: ${err instanceof Error ? err.message : String(err)}\\n`)\n }\n }\n if (options.hooks) {\n Promise.resolve(options.hooks.callHook('replay:done', {})).catch((err: unknown) => {\n if (process.env.ZIDANE_DEBUG)\n process.stderr.write(`[zidane/restate] replay:done hook rejected: ${err instanceof Error ? err.message : String(err)}\\n`)\n })\n }\n },\n onLive: (cb) => {\n if (live) {\n cb()\n return () => {}\n }\n callbacks.push(cb)\n return () => {\n const idx = callbacks.indexOf(cb)\n if (idx >= 0)\n callbacks.splice(idx, 1)\n }\n },\n }\n}\n\n/**\n * Wrap an abort function so it defers during journal replay.\n *\n * Live invocation → `abort()` runs immediately, exactly like calling\n * `agent.abort()` directly. Replaying invocation → the abort is queued\n * and applied at the first live boundary (the start of the first\n * non-journaled provider stream or tool body), where the resulting\n * `AgentAbortedError` + host catch-arm journaling append to the journal\n * instead of forking it mid-replay. Multiple calls during replay\n * collapse into one queued abort.\n */\nexport function replayAwareAbort(tracker: ReplayTracker, abort: () => void): () => void {\n let queued = false\n return () => {\n if (!tracker.isReplaying()) {\n abort()\n return\n }\n if (queued)\n return\n queued = true\n tracker.onLive(abort)\n }\n}\n","/**\n * Restate-backed `SessionStore` — turn / run state lives in the bound\n * virtual object's K/V state instead of SQLite / file / remote HTTP.\n *\n * Trade-offs vs. journal-only replay\n * ----------------------------------\n * If you only care about durable execution within ONE invocation,\n * skip this — the journaled `ctx.run` entries (LLM calls, tool\n * executions) are enough to replay the loop to byte-identical state\n * after a crash. The in-memory `createMemoryStore()` is the right\n * choice; turns rematerialize from the journal each replay.\n *\n * Pick this store when EXTERNAL consumers (TUI, web GUI, support\n * tooling) need to read a session's history WITHOUT re-entering the\n * agent handler. Virtual-object state is exposed via the SDK's read\n * APIs (`ctx.get` from another handler, `restate-cli`, the Restate\n * web UI) — same data, different access path. The journal is\n * invocation-local; this state is the externally-visible projection\n * of it.\n *\n * Storage layout\n * --------------\n * One virtual-object key per session, three K/V slots:\n *\n * `session-data` → `SessionData` minus the `turns` array (small header)\n * `session-turns` → `SessionTurn[]` (the conversation history)\n * `session-runs` → `SessionRun[]` (run lifecycle records)\n *\n * Splitting `turns` / `runs` out keeps the header light for `load()` —\n * a handler that only needs metadata doesn't pull the full history.\n *\n * Listing / discovery\n * -------------------\n * `list()` returns `[]` because virtual objects don't expose cross-key\n * enumeration. `delete()` clears the current object's session keys only.\n * Use a separate index handler if you need discovery (one virtual object\n * per `projectRoot` that maintains an indexed list of session ids; this\n * store doesn't own that concern).\n * `generateSessionId` is omitted so the agent falls back to its\n * default UUID generator — for a session bound 1:1 to a virtual-\n * object key, pass `id: ctx.key` to `createSession()` instead and\n * skip ID generation entirely.\n */\n\nimport type { SessionData, SessionRun, SessionStore } from '../session'\nimport type { SessionTurn } from '../types'\nimport type { RestateObjectContextLike } from './types'\n\nconst KEY_DATA = 'session-data'\nconst KEY_TURNS = 'session-turns'\nconst KEY_RUNS = 'session-runs'\n\n/**\n * Construct a `SessionStore` backed by the bound virtual-object's K/V\n * state. The store is single-tenant — every method ignores the\n * `sessionId` argument because the virtual object is already keyed by\n * `ctx.key`. Calling `appendTurns('other-id', …)` writes to the\n * CURRENT object's state, not the one named in the argument. Bind one\n * virtual-object key per session and the contract holds.\n */\nexport function restateSessionStore(ctx: RestateObjectContextLike): SessionStore {\n let nextTurnSeq: number | undefined\n let warnedMismatch = false\n\n // The store is single-tenant (keyed by `ctx.key`), so a `sessionId` arg that\n // doesn't match `ctx.key` means a method is silently writing to/reading from\n // a different object than the caller named — the classic footgun when a host\n // forgets `createSession({ id: ctx.key })` and the agent mints a random id.\n // Warn ONCE (never throw — a 1:1 binding with a non-matching id still routes\n // correctly, and throwing would break it). Hosts binding `id: ctx.key` never\n // see this.\n function guardSessionId(sessionId: string): void {\n if (warnedMismatch || sessionId === ctx.key)\n return\n warnedMismatch = true\n process.stderr.write(\n `[zidane/restate] restateSessionStore: sessionId \"${sessionId}\" != bound object key \"${ctx.key}\". `\n + `This store ignores the sessionId and operates on the bound object — pass createSession({ id: ctx.key }) to silence this.\\n`,\n )\n }\n\n async function generateTurnId(): Promise<string> {\n if (nextTurnSeq === undefined) {\n const existing = (await ctx.get<SessionTurn[]>(KEY_TURNS)) ?? []\n nextTurnSeq = existing.length\n }\n nextTurnSeq += 1\n return `turn_${nextTurnSeq}`\n }\n\n return {\n /**\n * Turn ids are deterministic from the persisted turn count. Random ids\n * are replay-stable only when the whole handler replays from the same\n * point; restarting from an arbitrary journal step can shift the RNG\n * sequence before a state write.\n */\n generateTurnId,\n\n async load(_sessionId: string): Promise<SessionData | null> {\n guardSessionId(_sessionId)\n const header = await ctx.get<Omit<SessionData, 'turns' | 'runs'>>(KEY_DATA)\n const turns = sanitizeTurnsForState((await ctx.get<SessionTurn[]>(KEY_TURNS)) ?? [])\n const runs = sanitizeRunsForState((await ctx.get<SessionRun[]>(KEY_RUNS)) ?? [])\n if (!header) {\n if (turns.length === 0 && runs.length === 0)\n return null\n return {\n id: _sessionId,\n turns,\n runs,\n status: inferStatus(runs),\n metadata: {},\n createdAt: inferCreatedAt(turns, runs),\n updatedAt: inferUpdatedAt(turns, runs),\n }\n }\n return { ...header, turns, runs }\n },\n\n async save(session: SessionData): Promise<void> {\n guardSessionId(session.id)\n const { turns, runs, ...header } = session\n // Journal-stable header timestamps. The in-memory `Session` stamps\n // `createdAt` / `updatedAt` with raw `Date.now()` (its `touch()`\n // helper is synchronous and can't await a journaled clock), so the\n // values arriving here differ on every replay — and a replayed\n // `ctx.set` with drifting values is exactly the non-determinism\n // Restate exists to prevent. Source both from the journal instead:\n // `createdAt` sticks to the first persisted value, `updatedAt`\n // comes from `ctx.date.now()` (journaled — replay returns the\n // recorded reading).\n const prior = await ctx.get<Omit<SessionData, 'turns' | 'runs'>>(KEY_DATA)\n const now = await ctx.date.now()\n ctx.set(KEY_DATA, {\n ...header,\n createdAt: prior?.createdAt ?? now,\n updatedAt: now,\n })\n ctx.set(KEY_TURNS, sanitizeTurnsForState(turns))\n ctx.set(KEY_RUNS, sanitizeRunsForState(runs))\n },\n\n async delete(_sessionId: string): Promise<void> {\n guardSessionId(_sessionId)\n ctx.clear(KEY_DATA)\n ctx.clear(KEY_TURNS)\n ctx.clear(KEY_RUNS)\n },\n\n /**\n * Always empty — virtual objects don't support cross-key\n * enumeration. Maintain a separate index handler if discovery\n * matters.\n */\n async list(): Promise<string[]> {\n return []\n },\n\n async appendTurns(_sessionId: string, turns: SessionTurn[]): Promise<void> {\n guardSessionId(_sessionId)\n const existing = sanitizeTurnsForState((await ctx.get<SessionTurn[]>(KEY_TURNS)) ?? [])\n ctx.set(KEY_TURNS, [...existing, ...sanitizeTurnsForState(turns)])\n },\n\n async getTurns(_sessionId: string, from = 0, limit?: number): Promise<SessionTurn[]> {\n guardSessionId(_sessionId)\n const turns = sanitizeTurnsForState((await ctx.get<SessionTurn[]>(KEY_TURNS)) ?? [])\n return turns.slice(from, limit !== undefined ? from + limit : undefined)\n },\n\n async updateRun(_sessionId: string, run: SessionRun): Promise<void> {\n guardSessionId(_sessionId)\n const runs = sanitizeRunsForState((await ctx.get<SessionRun[]>(KEY_RUNS)) ?? [])\n const idx = runs.findIndex(r => r.id === run.id)\n const next = [...runs]\n if (idx >= 0) {\n // Journal-stable `startedAt`: the in-memory `Session.startRun`\n // stamps it with raw `Date.now()`, which re-evaluates on every\n // replay. Keep the previously persisted value (mirrors the\n // `createdAt: prior?.createdAt ?? now` pattern in `save()`) so a\n // replayed `ctx.set` payload doesn't drift.\n next[idx] = { ...sanitizeRunForState(run), startedAt: runs[idx].startedAt }\n }\n else {\n next.push(sanitizeRunForState(run))\n }\n ctx.set(KEY_RUNS, next)\n },\n\n async updateStatus(_sessionId: string, status: SessionData['status']): Promise<void> {\n guardSessionId(_sessionId)\n const header = await ctx.get<Omit<SessionData, 'turns' | 'runs'>>(KEY_DATA)\n const now = await ctx.date.now()\n if (header) {\n ctx.set(KEY_DATA, { ...header, status, updatedAt: now })\n }\n else {\n ctx.set(KEY_DATA, {\n id: _sessionId,\n status,\n metadata: {},\n createdAt: now,\n updatedAt: now,\n })\n }\n },\n }\n}\n\nfunction sanitizeTurnsForState(turns: readonly SessionTurn[]): SessionTurn[] {\n return turns.map(sanitizeTurnForState)\n}\n\nfunction sanitizeTurnForState(turn: SessionTurn): SessionTurn {\n if (!turn.usage || turn.usage.timeToFirstTokenMs === undefined)\n return turn\n\n const { timeToFirstTokenMs: _timeToFirstTokenMs, ...usage } = turn.usage\n return { ...turn, usage }\n}\n\nfunction sanitizeRunsForState(runs: readonly SessionRun[]): SessionRun[] {\n return runs.map(sanitizeRunForState)\n}\n\nfunction sanitizeRunForState(run: SessionRun): SessionRun {\n if (!run.turnUsage?.some(usage => usage.timeToFirstTokenMs !== undefined))\n return run\n\n return {\n ...run,\n turnUsage: run.turnUsage.map((usage) => {\n if (usage.timeToFirstTokenMs === undefined)\n return usage\n const { timeToFirstTokenMs: _timeToFirstTokenMs, ...stableUsage } = usage\n return stableUsage\n }),\n }\n}\n\nfunction inferStatus(runs: readonly SessionRun[]): SessionData['status'] {\n if (runs.some(run => run.status === 'running'))\n return 'running'\n if (runs.some(run => run.status === 'error'))\n return 'error'\n if (runs.some(run => run.status === 'completed'))\n return 'completed'\n return 'idle'\n}\n\nfunction inferCreatedAt(turns: readonly SessionTurn[], runs: readonly SessionRun[]): number {\n return minDefined([\n ...turns.map(turn => turn.createdAt),\n ...runs.map(run => run.startedAt),\n ]) ?? 0\n}\n\nfunction inferUpdatedAt(turns: readonly SessionTurn[], runs: readonly SessionRun[]): number {\n return maxDefined([\n ...turns.map(turn => turn.createdAt),\n ...runs.map(run => run.endedAt ?? run.startedAt),\n ]) ?? inferCreatedAt(turns, runs)\n}\n\nfunction minDefined(values: readonly number[]): number | undefined {\n let min: number | undefined\n for (const value of values) {\n if (min === undefined || value < min)\n min = value\n }\n return min\n}\n\nfunction maxDefined(values: readonly number[]): number | undefined {\n let max: number | undefined\n for (const value of values) {\n if (max === undefined || value > max)\n max = value\n }\n return max\n}\n","/**\n * Durable `ExecutionContext.waitBackground` for Restate hosts.\n *\n * A durable execution context can't push a `task:exit` callback from a timer\n * back into a journaled handler. The race-safe pattern is an awakeable park:\n * the runner fires task-exit over its own bridge → `ctx.resolveAwakeable(id,\n * exitInfo)` → the parked `waitBackground` resumes. The *choreography* around\n * that park is entirely generic — only the persistence (which row maps a task\n * to its resumer awakeable) is host-specific. {@link restateWaitBackground}\n * owns the generic half; the host supplies `probe` / `register` / `settle`.\n *\n * Ordering contract (this is the whole point — get it wrong and you leak a\n * lost wakeup):\n *\n * 1. **mint** the awakeable (before the journaled register, so replay\n * re-derives the same id).\n * 2. **register** the awakeable id as the task's exit resumer — journaled,\n * and crucially BEFORE the probe. If we probed first and the task exited\n * in the gap before register, the runner's `task:exit` would fire with no\n * resumer row and the park would hang forever.\n * 3. **probe** the registry. If the task ALREADY terminated, fast-path: settle\n * and return its exit info without ever parking (a resolution that lands\n * on the registered awakeable afterwards is dropped by the runtime). If the\n * task is unknown, settle and return `null`. Otherwise:\n * 4. **park** on the awakeable, OUTSIDE any `ctx.run`, raced against the\n * durable `ctx.sleep(timeoutMs)` deadline and the caller's abort signal.\n * A timeout / abort resolves `null` (the seam's documented sentinel).\n * 5. **settle** — journaled finalization (stamp / clear the resumer row).\n *\n * The returned function matches `ExecutionContext.waitBackground` exactly, so a\n * host wires it with `execution.waitBackground = restateWaitBackground({ … })`.\n */\n\nimport type { ExecutionHandle, TaskEntry, TaskExitInfo } from '../contexts'\nimport type { RestatePromiseRaceLike } from './awakeable'\nimport type { ReplayTracker } from './replay'\nimport type { RestateContextLike, RestateRunOptions } from './types'\nimport { awakeableWithTimeout } from './awakeable'\n\n/** Journaled registration marker — mirrors the marker invariant in `restateAwakeableTool`. */\ninterface WaitBackgroundRegisterMarker {\n registered: true\n awakeableId: string\n}\n\nexport interface RestateWaitBackgroundOptions {\n /** The Restate context the awakeable + journal entries bind to. */\n ctx: RestateContextLike\n /**\n * Snapshot the host's task registry (the `listBackground` shape). Called\n * AFTER `register`, inside a journaled `ctx.run`. The helper finds `taskId`\n * in the result: terminated → fast-path return, running → park, absent →\n * `null`.\n */\n probe: (handle: ExecutionHandle, taskId: string) => Promise<readonly TaskEntry[]> | readonly TaskEntry[]\n /**\n * Persist `awakeableId` as the exit resumer for `taskId` BEFORE the probe —\n * the host's task-exit path must later call `ctx.resolveAwakeable(awakeableId,\n * exitInfo)`. Runs inside a journaled `ctx.run`; keep it short and\n * idempotent-safe up to journal persistence.\n */\n register: (awakeableId: string, taskId: string, handle: ExecutionHandle) => Promise<void> | void\n /**\n * Finalize the resumer row once the wait resolves — `exit` is the task's\n * {@link TaskExitInfo}, or `null` on timeout / abort / unknown task. Runs\n * inside a journaled `ctx.run`. Optional.\n */\n settle?: (awakeableId: string, taskId: string, exit: TaskExitInfo | null, handle: ExecutionHandle) => Promise<void> | void\n /**\n * Default park deadline in milliseconds. A per-call `options.timeoutMs`\n * (what the `wait_task` tool passes) wins. Unset / non-positive = park until\n * the resumer fires or the caller aborts.\n */\n timeoutMs?: number\n /**\n * Durable race combinator for the timeout race — pass `RestatePromise` from\n * the SDK. See {@link awakeableWithTimeout}; native `Promise.race` is the\n * replay-safe fallback.\n */\n promises?: RestatePromiseRaceLike\n /** `ctx.run` options for the journaled phases. Defaults to `{ maxRetryAttempts: 1 }`. */\n runOptions?: RestateRunOptions\n /** Journal-entry prefix. Default `wait-background`. */\n entryPrefix?: string\n /** Per-invocation replay tracker (see `createReplayTracker`). */\n replayTracker?: ReplayTracker\n}\n\nfunction entryToExit(entry: TaskEntry): TaskExitInfo {\n return {\n taskId: entry.taskId,\n // `entryToExit` is only called for terminated entries; `'running'` can't\n // reach here, but narrow defensively to the exit-only union.\n status: entry.status === 'running' ? 'exited' : entry.status,\n exitCode: entry.exitCode ?? 0,\n ...(entry.signal ? { signal: entry.signal } : {}),\n outputPath: entry.outputPath,\n durationMs: Math.max(0, (entry.endedAt ?? entry.startedAt) - entry.startedAt),\n command: entry.command,\n }\n}\n\n/**\n * Park on `promise` until it settles, the caller aborts, or (already handled\n * by `awakeableWithTimeout`) the durable deadline elapses. Abort and rejection\n * both resolve `null` — the `waitBackground` seam's contract is \"exit info, or\n * null when the task didn't cleanly exit before we stopped waiting\".\n */\nfunction parkUntilAbort<T>(promise: Promise<T>, signal?: AbortSignal): Promise<T | null> {\n if (!signal)\n return promise.then(value => value, () => null)\n if (signal.aborted)\n return Promise.resolve(null)\n return new Promise<T | null>((resolve) => {\n const onAbort = (): void => resolve(null)\n signal.addEventListener('abort', onAbort, { once: true })\n promise.then(\n (value) => {\n signal.removeEventListener('abort', onAbort)\n resolve(value)\n },\n () => {\n signal.removeEventListener('abort', onAbort)\n resolve(null)\n },\n )\n })\n}\n\n/**\n * Build a durable `ExecutionContext.waitBackground` — see the module doc for\n * the ordering contract. The returned function is the seam itself:\n * `(handle, taskId, options?) => Promise<TaskExitInfo | null>`.\n */\nexport function restateWaitBackground(\n options: RestateWaitBackgroundOptions,\n): (handle: ExecutionHandle, taskId: string, opts?: { timeoutMs?: number, signal?: AbortSignal }) => Promise<TaskExitInfo | null> {\n const { ctx, probe, register, settle } = options\n const runOpts: RestateRunOptions = options.runOptions ?? { maxRetryAttempts: 1 }\n const prefix = options.entryPrefix ?? 'wait-background'\n let seq = 0\n\n return async (handle, taskId, callOpts) => {\n seq += 1\n const entry = `${prefix}-${taskId}-${seq}`\n const timeoutMs = callOpts?.timeoutMs ?? options.timeoutMs\n const signal = callOpts?.signal\n\n const finalize = async (exit: TaskExitInfo | null, awakeableId: string): Promise<TaskExitInfo | null> => {\n if (settle) {\n await ctx.run(`${entry}-settle`, async () => {\n options.replayTracker?.markLive()\n await settle(awakeableId, taskId, exit, handle)\n }, runOpts)\n }\n return exit\n }\n\n // 1. Mint BEFORE the journaled register (same ordering contract as\n // restateAwakeableTool) — replay returns the same id. The timeout sleep\n // is armed here too, so the park below is a durable race.\n const awakeable = awakeableWithTimeout<TaskExitInfo>(ctx, {\n ...(timeoutMs !== undefined ? { timeoutMs } : {}),\n ...(options.promises ? { promises: options.promises } : {}),\n })\n\n // 2. Register the resumer BEFORE probing.\n const marker = await ctx.run<WaitBackgroundRegisterMarker>(`${entry}-register`, async () => {\n options.replayTracker?.markLive()\n await register(awakeable.id, taskId, handle)\n return { registered: true, awakeableId: awakeable.id }\n }, runOpts)\n if (marker.awakeableId !== awakeable.id) {\n throw new Error(\n `restateWaitBackground(${taskId}): journal drift — registration marker carries awakeable \"${marker.awakeableId}\" but this replay minted \"${awakeable.id}\". Refusing to park on an unreachable awakeable.`,\n )\n }\n\n // 3. Probe (journaled). Fast-path terminated / unknown without parking.\n const entries = await ctx.run<readonly TaskEntry[]>(`${entry}-probe`, async () => {\n options.replayTracker?.markLive()\n return [...await probe(handle, taskId)]\n }, runOpts)\n const found = entries.find(e => e.taskId === taskId)\n if (!found)\n return finalize(null, awakeable.id)\n if (found.status !== 'running')\n return finalize(entryToExit(found), awakeable.id)\n\n // 4. Park OUTSIDE any ctx.run — a suspension point must not nest in a\n // journaled closure. Timeout (via awakeableWithTimeout) and abort both\n // resolve null.\n const resumed = await parkUntilAbort(awakeable.promise, signal)\n\n // 5. Settle + return.\n return finalize(resumed, awakeable.id)\n }\n}\n"],"mappings":"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"}
|