zidane 5.9.16 → 5.9.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/dist/chat.js +2 -2
  2. package/dist/eval.js +3 -3
  3. package/dist/{headless-CZwcLnG_.js → headless-D0yusQui.js} +5 -5
  4. package/dist/{headless-CZwcLnG_.js.map → headless-D0yusQui.js.map} +1 -1
  5. package/dist/headless.js +1 -1
  6. package/dist/index.js +8 -8
  7. package/dist/{login-Bo0hjNpN.js → login-WeATNRoo.js} +3 -3
  8. package/dist/{login-Bo0hjNpN.js.map → login-WeATNRoo.js.map} +1 -1
  9. package/dist/{messages-CWz0yRAE.js → messages-wOJ8LTs0.js} +2 -2
  10. package/dist/{messages-CWz0yRAE.js.map → messages-wOJ8LTs0.js.map} +1 -1
  11. package/dist/output/stream-json.js +1 -1
  12. package/dist/{presets-Dk77h8LE.js → presets-DQRxHLX1.js} +2 -2
  13. package/dist/{presets-Dk77h8LE.js.map → presets-DQRxHLX1.js.map} +1 -1
  14. package/dist/presets.js +1 -1
  15. package/dist/{providers-NAYlDy0H.js → providers-BcR0maEr.js} +2 -2
  16. package/dist/{providers-NAYlDy0H.js.map → providers-BcR0maEr.js.map} +1 -1
  17. package/dist/providers.js +2 -2
  18. package/dist/{read-state-Cr0MrWRm.js → read-state-DMHYFRR9.js} +61 -29
  19. package/dist/read-state-DMHYFRR9.js.map +1 -0
  20. package/dist/restate.d.ts.map +1 -1
  21. package/dist/restate.js +17 -5
  22. package/dist/restate.js.map +1 -1
  23. package/dist/{session-SMszIfE6.js → session-z0E9-e4b.js} +2 -2
  24. package/dist/{session-SMszIfE6.js.map → session-z0E9-e4b.js.map} +1 -1
  25. package/dist/session.js +2 -2
  26. package/dist/{tools-COop1vLo.js → tools-Cjxkfh-F.js} +4 -4
  27. package/dist/{tools-COop1vLo.js.map → tools-Cjxkfh-F.js.map} +1 -1
  28. package/dist/tools.js +2 -2
  29. package/dist/{transcript-anchors-D1E0-ROB.js → transcript-anchors-BkXXxUlW.js} +5 -5
  30. package/dist/{transcript-anchors-D1E0-ROB.js.map → transcript-anchors-BkXXxUlW.js.map} +1 -1
  31. package/dist/tui.js +6 -6
  32. package/package.json +1 -1
  33. package/dist/read-state-Cr0MrWRm.js.map +0 -1
package/dist/providers.js CHANGED
@@ -1,3 +1,3 @@
1
- import { c as arcee, i as cursor, l as anthropic, n as openai, r as local, s as cerebras, t as openrouter, u as applyAnthropicCacheBreakpoints } from "./providers-NAYlDy0H.js";
2
- import { S as sanitizeToolSpecs, _ as mapOAIFinishReason, g as classifyOpenAICompatError, m as OpenAICompatHttpError, v as openaiCompat, x as sanitizeToolSchema } from "./messages-CWz0yRAE.js";
1
+ import { c as arcee, i as cursor, l as anthropic, n as openai, r as local, s as cerebras, t as openrouter, u as applyAnthropicCacheBreakpoints } from "./providers-BcR0maEr.js";
2
+ import { S as sanitizeToolSpecs, _ as mapOAIFinishReason, g as classifyOpenAICompatError, m as OpenAICompatHttpError, v as openaiCompat, x as sanitizeToolSchema } from "./messages-wOJ8LTs0.js";
3
3
  export { OpenAICompatHttpError, anthropic, applyAnthropicCacheBreakpoints, arcee, cerebras, classifyOpenAICompatError, cursor, local, mapOAIFinishReason, openai, openaiCompat, openrouter, sanitizeToolSchema, sanitizeToolSpecs };
@@ -96,28 +96,16 @@ const READ_FILE_DEFAULT_MAX_BYTES = 262144;
96
96
  const READ_FILE_FOOTER_RE = /\n\n…(?:read lines|truncated)/;
97
97
  const READ_FILE_LINE_RE = /^\d{1,9}\t(.*)$/;
98
98
  /**
99
- * Rebuild the per-session read-state map from durable session turns.
100
- *
101
- * Durable replay runtimes may return recorded tool results without re-running
102
- * the tool body, so in-memory side effects like `readState.set(...)` can be
103
- * missing even though the transcript contains the successful `read_file`.
104
- * This helper is intentionally opt-in: live hosts keep the normal side-effect
105
- * behavior unless they call it themselves.
106
- *
107
- * Hydration only fills missing keys. Live in-memory state may already reflect a
108
- * newer read or edit from the current run, and durable history cannot prove it
109
- * is fresher. Relative paths are resolved against the current execution cwd,
110
- * matching replay hosts that run sessions from a stable workspace.
99
+ * Async replay hydrator for durable hosts that can cheaply read the current
100
+ * full file through their execution context. Transcript-only reconstruction is
101
+ * still preferred for full reads; partial/truncated read_file entries fall back
102
+ * to `readFileForHash` and hash those full current bytes.
111
103
  */
112
- function hydrateReadStateFromSession(session, cwd, options = {}) {
104
+ async function hydrateReadStateFromSessionAsync(session, cwd, options = {}) {
113
105
  if (!session) return 0;
114
106
  const readState = getReadState(session);
115
107
  if (!readState) return 0;
116
- const readFileToolName = options.readFileToolName ?? "read_file";
117
- const writeFileToolName = options.writeFileToolName ?? "write_file";
118
- const editToolName = options.editToolName ?? "edit";
119
- const multiEditToolName = options.multiEditToolName ?? "multi_edit";
120
- const defaultLineNumbers = options.defaultLineNumbers ?? true;
108
+ const normalized = normalizeHydrateReadStateOptions(options);
121
109
  const pending = /* @__PURE__ */ new Map();
122
110
  const known = /* @__PURE__ */ new Map();
123
111
  const invalidated = INVALIDATED.get(session);
@@ -125,7 +113,7 @@ function hydrateReadStateFromSession(session, cwd, options = {}) {
125
113
  let hydrated = 0;
126
114
  for (const turn of session.turns) for (const block of turn.content) {
127
115
  if (block.type === "tool_call") {
128
- if (block.name === readFileToolName || block.name === writeFileToolName || block.name === editToolName || block.name === multiEditToolName) pending.set(block.id, {
116
+ if (block.name === normalized.readFileToolName || block.name === normalized.writeFileToolName || block.name === normalized.editToolName || block.name === normalized.multiEditToolName) pending.set(block.id, {
129
117
  name: block.name,
130
118
  input: block.input
131
119
  });
@@ -136,13 +124,7 @@ function hydrateReadStateFromSession(session, cwd, options = {}) {
136
124
  if (!call) continue;
137
125
  pending.delete(block.callId);
138
126
  if (block.isError === true) continue;
139
- const next = stateFromToolResult(call, toolResultToText(block.output), turn, cwd, {
140
- readFileToolName,
141
- writeFileToolName,
142
- editToolName,
143
- multiEditToolName,
144
- defaultLineNumbers
145
- }, known);
127
+ const next = await stateFromToolResultAsync(call, toolResultToText(block.output), turn, cwd, normalized, known);
146
128
  if (!next) continue;
147
129
  if (invalidated?.has(next.key)) {
148
130
  known.set(next.key, next.file);
@@ -156,12 +138,29 @@ function hydrateReadStateFromSession(session, cwd, options = {}) {
156
138
  }
157
139
  return hydrated;
158
140
  }
141
+ function normalizeHydrateReadStateOptions(options) {
142
+ return {
143
+ readFileToolName: options.readFileToolName ?? "read_file",
144
+ writeFileToolName: options.writeFileToolName ?? "write_file",
145
+ editToolName: options.editToolName ?? "edit",
146
+ multiEditToolName: options.multiEditToolName ?? "multi_edit",
147
+ defaultLineNumbers: options.defaultLineNumbers ?? true,
148
+ ...options.readFileForHash ? { readFileForHash: options.readFileForHash } : {}
149
+ };
150
+ }
159
151
  function stateFromToolResult(call, output, resultTurn, cwd, options, known) {
160
152
  if (call.name === options.readFileToolName) return readFileStateFromResult(call.input, output, resultTurn, cwd, options.defaultLineNumbers);
161
153
  if (call.name === options.writeFileToolName) return writeFileStateFromResult(call.input, output, resultTurn, cwd);
162
154
  if (call.name === options.editToolName) return editStateFromResult(call.input, output, resultTurn, cwd, known);
163
155
  if (call.name === options.multiEditToolName) return multiEditStateFromResult(call.input, output, resultTurn, cwd, known);
164
156
  }
157
+ async function stateFromToolResultAsync(call, output, resultTurn, cwd, options, known) {
158
+ if (call.name === options.readFileToolName) return await readFileStateFromResultAsync(call.input, output, resultTurn, cwd, {
159
+ defaultLineNumbers: options.defaultLineNumbers,
160
+ readFileForHash: options.readFileForHash
161
+ });
162
+ return stateFromToolResult(call, output, resultTurn, cwd, options, known);
163
+ }
165
164
  function readFileStateFromResult(input, output, resultTurn, cwd, defaultLineNumbers) {
166
165
  const path = typeof input.path === "string" ? input.path : void 0;
167
166
  if (!path || !isSuccessfulFullReadOutput(output)) return void 0;
@@ -184,6 +183,35 @@ function readFileStateFromResult(input, output, resultTurn, cwd, defaultLineNumb
184
183
  }
185
184
  };
186
185
  }
186
+ async function readFileStateFromResultAsync(input, output, resultTurn, cwd, options) {
187
+ const reconstructed = readFileStateFromResult(input, output, resultTurn, cwd, options.defaultLineNumbers);
188
+ if (reconstructed) return reconstructed;
189
+ const path = typeof input.path === "string" ? input.path : void 0;
190
+ if (!path || !options.readFileForHash || !isSuccessfulReadOutput(output)) return void 0;
191
+ let content;
192
+ try {
193
+ content = await options.readFileForHash(path);
194
+ } catch {
195
+ return;
196
+ }
197
+ if (typeof content !== "string") return void 0;
198
+ const lineNumbers = typeof input.lineNumbers === "boolean" ? input.lineNumbers : options.defaultLineNumbers;
199
+ const entry = {
200
+ contentHash: hashContent(content),
201
+ offset: normalizeReadInteger(input.offset, READ_FILE_DEFAULT_OFFSET),
202
+ limit: normalizeReadInteger(input.limit, READ_FILE_DEFAULT_LIMIT),
203
+ maxBytes: normalizeReadInteger(input.maxBytes, READ_FILE_DEFAULT_MAX_BYTES),
204
+ lineNumbers,
205
+ mtimeMs: resultTurn.createdAt
206
+ };
207
+ return {
208
+ key: readStateKey(cwd, path),
209
+ file: {
210
+ content,
211
+ entry
212
+ }
213
+ };
214
+ }
187
215
  function writeFileStateFromResult(input, output, resultTurn, cwd) {
188
216
  const path = typeof input.path === "string" ? input.path : void 0;
189
217
  const content = typeof input.content === "string" ? input.content : void 0;
@@ -276,8 +304,12 @@ function parseMultiEditAppliedSteps(output, editCount) {
276
304
  return applied;
277
305
  }
278
306
  function isSuccessfulFullReadOutput(output) {
307
+ if (!isSuccessfulReadOutput(output) || READ_FILE_FOOTER_RE.test(output)) return false;
308
+ return true;
309
+ }
310
+ function isSuccessfulReadOutput(output) {
279
311
  if (output.length === 0) return true;
280
- if (output.startsWith("File not found:") || output.startsWith("[binary file:") || output.startsWith("Image:") || output.startsWith("Document:") || output.startsWith("[image too large to inline:") || output.startsWith("[document:") || output.startsWith("[document too large to attach:") || output.startsWith("Image read failed:") || output.startsWith("Document read failed:") || output.includes(" unchanged since the previous read in this session ") || READ_FILE_FOOTER_RE.test(output)) return false;
312
+ if (output.startsWith("File not found:") || output.startsWith("[binary file:") || output.startsWith("Image:") || output.startsWith("Document:") || output.startsWith("[image too large to inline:") || output.startsWith("[document:") || output.startsWith("[document too large to attach:") || output.startsWith("Image read failed:") || output.startsWith("Document read failed:") || output.includes(" unchanged since the previous read in this session ")) return false;
281
313
  return true;
282
314
  }
283
315
  function stripReadFileLineNumbers(output) {
@@ -309,6 +341,6 @@ function getToolDedupState(session) {
309
341
  return map;
310
342
  }
311
343
  //#endregion
312
- export { invalidateReadStatePath as a, hydrateReadStateFromSession as i, getToolDedupState as n, readStateKey as o, hashContent as r, resolveReadStateMap as s, getReadState as t };
344
+ export { invalidateReadStatePath as a, hydrateReadStateFromSessionAsync as i, getToolDedupState as n, readStateKey as o, hashContent as r, resolveReadStateMap as s, getReadState as t };
313
345
 
314
- //# sourceMappingURL=read-state-Cr0MrWRm.js.map
346
+ //# sourceMappingURL=read-state-DMHYFRR9.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"read-state-DMHYFRR9.js","names":[],"sources":["../src/tools/read-state.ts"],"sourcesContent":["/**\n * Per-session file read tracking + tool-dedup state.\n *\n * Two concerns, one module so they can share the `WeakMap<Session, …>`\n * pattern (state lives as long as the session does, GC'd alongside it —\n * no public schema changes, no persistence). Each section below stands\n * on its own; the two maps don't share keys or behavior.\n *\n * ## Read-state\n *\n * Shared between `read_file` (dedup re-reads) and `edit` / `multi_edit`\n * (`requireReadBeforeEdit` guard). The state map records, per canonical\n * absolute file path:\n *\n * - `contentHash` — FNV-1a hash of the bytes the model last saw. Identical\n * re-reads return a stub; edits compare against this hash to detect\n * stale content.\n * - `(offset, limit, maxBytes, lineNumbers)` — slice / shape of the last\n * read, so a wider re-read invalidates the prior stub and a different\n * `lineNumbers` mode doesn't dedup against the previous shape.\n * - `mtimeMs` — wall-clock at last read, diagnostic only.\n *\n * Resolution is split between two helpers so consumers don't have to\n * juggle the `Session` vs. explicit-map cases themselves:\n *\n * - {@link getReadState} returns the map keyed by `Session` instance.\n * - {@link resolveReadStateMap} prefers an explicit `ctx.readState`\n * (the path `spawn`'s `shareReadState` uses to forward the parent's\n * map into a sessionless child) and falls back to the session-keyed\n * lookup. Tools should call this helper, not `getReadState` directly.\n *\n * ## Tool-dedup\n *\n * Backs `behavior.dedupTools`. Records the most recent `(hash, result)`\n * per canonical tool name within a session. Same WeakMap pattern; no\n * cross-talk with the read-state map.\n */\n\nimport type { Session } from '../session'\nimport type { SessionTurn, ToolResultContent } from '../types'\nimport { resolve } from 'node:path'\nimport { toolResultToText } from '../types'\nimport { resolveOldString, styleReplacementForVia } from './edit-utils'\n\n// ---------------------------------------------------------------------------\n// Read-state\n// ---------------------------------------------------------------------------\n\nexport interface ReadStateEntry {\n contentHash: string\n /** Slice parameters for the last read. */\n offset: number\n limit: number\n maxBytes: number\n /**\n * Whether the prior read emitted line-number prefixes. Tracked so a\n * read with `lineNumbers: true` doesn't dedup against one with\n * `lineNumbers: false` (or vice versa) — the dedup stub would mislead\n * the model about the prior output's shape.\n */\n lineNumbers?: boolean\n /** Wall-clock at last read — diagnostic only, not used for invalidation. */\n mtimeMs: number\n}\n\nexport type ReadStateMap = Map<string, ReadStateEntry>\n\nconst STATE = new WeakMap<Session, ReadStateMap>()\nconst INVALIDATED = new WeakMap<Session, Set<string>>()\n\n/**\n * Get or lazily create the per-session read-state map. Returns `undefined`\n * when no session is provided.\n *\n * Most tool callers should prefer {@link resolveReadStateMap}, which\n * additionally honors an explicit `ctx.readState` (the path\n * `spawn`'s `shareReadState: true` uses to forward the parent's map\n * into a sessionless child). Use this helper directly only when the\n * Session-keyed map is exactly what you want and you don't need to\n * accept an override.\n */\nexport function getReadState(session: Session | undefined): ReadStateMap | undefined {\n if (!session)\n return undefined\n let map = STATE.get(session)\n if (!map) {\n map = new Map()\n STATE.set(session, map)\n }\n return map\n}\n\n/**\n * Resolve the active read-state map from a tool context. An explicit\n * `ctx.readState` wins (used by `spawn`'s `shareReadState` opt-in to\n * forward the parent's map into a sessionless child); otherwise the\n * usual `Session`-keyed lookup applies.\n *\n * Tools should call this helper instead of `getReadState(ctx.session)`\n * directly so the `shareReadState` plumbing is honored uniformly.\n */\nexport function resolveReadStateMap(ctx: {\n session?: Session\n readState?: ReadStateMap\n}): ReadStateMap | undefined {\n return ctx.readState ?? getReadState(ctx.session)\n}\n\n/**\n * Delete a read-state entry and remember that deletion for replay hydration.\n *\n * Stale-read elision intentionally makes the model re-read a file before the\n * next edit. Durable workflow replay hydration must not resurrect the same\n * historical `read_file` output after that invalidation.\n */\nexport function invalidateReadStatePath(ctx: {\n session?: Session\n readState?: ReadStateMap\n}, cwd: string, path: string): void {\n const key = readStateKey(cwd, path)\n ctx.readState?.delete(key)\n if (!ctx.session)\n return\n\n STATE.get(ctx.session)?.delete(key)\n let invalidated = INVALIDATED.get(ctx.session)\n if (!invalidated) {\n invalidated = new Set()\n INVALIDATED.set(ctx.session, invalidated)\n }\n invalidated.add(key)\n}\n\n/**\n * Canonical read-state key for a `(cwd, path)` pair.\n *\n * `ctx.execution.readFile(handle, path)` resolves the model-provided\n * path against `handle.cwd` before touching disk — so `src/App.tsx`,\n * `./src/App.tsx`, and `/abs/cwd/src/App.tsx` all read the **same**\n * bytes. The read-state map MUST mirror that resolution: without it,\n * a model that reads `src/App.tsx` and then edits `./src/App.tsx`\n * trips the `requireReadBeforeEdit` gate for a file it demonstrably\n * already saw (the gate's \"has not been read in this session\" message\n * fires on a stale key).\n *\n * `node:path`'s `resolve(cwd, path)` short-circuits when `path` is\n * already absolute, so absolute and relative shapes converge on the\n * same canonical form. We don't `realpath()` symlinks — the file IS\n * the path the model addressed, not the realpath behind it; the host's\n * execution context decides how to dereference.\n */\nexport function readStateKey(cwd: string, path: string): string {\n return resolve(cwd, path)\n}\n\n/**\n * FNV-1a 32-bit hash, hex-encoded. Fast, non-cryptographic — we only need\n * collision resistance against accidental matches between different file\n * contents within one session (~1 in 4 billion). Cheaper than allocating\n * a Buffer and pulling in `crypto`.\n */\nexport function hashContent(text: string): string {\n let h = 0x811C9DC5\n for (let i = 0; i < text.length; i++) {\n h ^= text.charCodeAt(i)\n h = (h + ((h << 1) + (h << 4) + (h << 7) + (h << 8) + (h << 24))) >>> 0\n }\n return h.toString(16).padStart(8, '0')\n}\n\nexport interface HydrateReadStateOptions {\n /** Canonical read-file tool name. Defaults to `read_file`. */\n readFileToolName?: string\n /** Canonical write-file tool name. Defaults to `write_file`. */\n writeFileToolName?: string\n /** Canonical edit tool name. Defaults to `edit`. */\n editToolName?: string\n /** Canonical multi-edit tool name. Defaults to `multi_edit`. */\n multiEditToolName?: string\n /** Agent-level default for omitted `read_file.lineNumbers`. */\n defaultLineNumbers?: boolean\n /**\n * Optional replay-only fallback for read_file results whose transcript output\n * is partial/truncated. Receives the model-provided path and should return\n * the current full text bytes to hash exactly like live read_file.\n */\n readFileForHash?: (path: string) => Promise<string | null | undefined>\n}\n\ntype NormalizedHydrateReadStateOptions = Required<Omit<HydrateReadStateOptions, 'readFileForHash'>> & {\n readFileForHash?: HydrateReadStateOptions['readFileForHash']\n}\n\ninterface PendingToolCall {\n name: string\n input: Record<string, unknown>\n}\n\ninterface KnownFile {\n content: string\n entry: ReadStateEntry\n}\n\nconst READ_FILE_DEFAULT_OFFSET = 1\nconst READ_FILE_DEFAULT_LIMIT = 2000\nconst READ_FILE_DEFAULT_MAX_BYTES = 262_144\nconst READ_FILE_FOOTER_RE = /\\n\\n…(?:read lines|truncated)/\nconst READ_FILE_LINE_RE = /^\\d{1,9}\\t(.*)$/\n\n/**\n * Rebuild the per-session read-state map from durable session turns.\n *\n * Durable replay runtimes may return recorded tool results without re-running\n * the tool body, so in-memory side effects like `readState.set(...)` can be\n * missing even though the transcript contains the successful `read_file`.\n * This helper is intentionally opt-in: live hosts keep the normal side-effect\n * behavior unless they call it themselves.\n *\n * Hydration only fills missing keys. Live in-memory state may already reflect a\n * newer read or edit from the current run, and durable history cannot prove it\n * is fresher. Relative paths are resolved against the current execution cwd,\n * matching replay hosts that run sessions from a stable workspace.\n */\nexport function hydrateReadStateFromSession(\n session: Session | undefined,\n cwd: string,\n options: HydrateReadStateOptions = {},\n): number {\n if (!session)\n return 0\n\n const readState = getReadState(session)\n if (!readState)\n return 0\n\n const normalized = normalizeHydrateReadStateOptions(options)\n const pending = new Map<string, PendingToolCall>()\n const known = new Map<string, KnownFile>()\n const invalidated = INVALIDATED.get(session)\n const preexistingKeys = new Set(readState.keys())\n let hydrated = 0\n\n for (const turn of session.turns) {\n for (const block of turn.content) {\n if (block.type === 'tool_call') {\n if (\n block.name === normalized.readFileToolName\n || block.name === normalized.writeFileToolName\n || block.name === normalized.editToolName\n || block.name === normalized.multiEditToolName\n ) {\n pending.set(block.id, { name: block.name, input: block.input })\n }\n continue\n }\n\n if (block.type !== 'tool_result')\n continue\n\n const call = pending.get(block.callId)\n if (!call)\n continue\n pending.delete(block.callId)\n if (block.isError === true)\n continue\n\n const output = toolResultToText(block.output)\n const next = stateFromToolResult(call, output, turn, cwd, normalized, known)\n if (!next)\n continue\n\n if (invalidated?.has(next.key)) {\n known.set(next.key, next.file)\n continue\n }\n if (!preexistingKeys.has(next.key)) {\n readState.set(next.key, next.file.entry)\n hydrated += 1\n }\n known.set(next.key, next.file)\n }\n }\n\n return hydrated\n}\n\n/**\n * Async replay hydrator for durable hosts that can cheaply read the current\n * full file through their execution context. Transcript-only reconstruction is\n * still preferred for full reads; partial/truncated read_file entries fall back\n * to `readFileForHash` and hash those full current bytes.\n */\nexport async function hydrateReadStateFromSessionAsync(\n session: Session | undefined,\n cwd: string,\n options: HydrateReadStateOptions = {},\n): Promise<number> {\n if (!session)\n return 0\n\n const readState = getReadState(session)\n if (!readState)\n return 0\n\n const normalized = normalizeHydrateReadStateOptions(options)\n const pending = new Map<string, PendingToolCall>()\n const known = new Map<string, KnownFile>()\n const invalidated = INVALIDATED.get(session)\n const preexistingKeys = new Set(readState.keys())\n let hydrated = 0\n\n for (const turn of session.turns) {\n for (const block of turn.content) {\n if (block.type === 'tool_call') {\n if (\n block.name === normalized.readFileToolName\n || block.name === normalized.writeFileToolName\n || block.name === normalized.editToolName\n || block.name === normalized.multiEditToolName\n ) {\n pending.set(block.id, { name: block.name, input: block.input })\n }\n continue\n }\n\n if (block.type !== 'tool_result')\n continue\n\n const call = pending.get(block.callId)\n if (!call)\n continue\n pending.delete(block.callId)\n if (block.isError === true)\n continue\n\n const output = toolResultToText(block.output)\n const next = await stateFromToolResultAsync(call, output, turn, cwd, normalized, known)\n if (!next)\n continue\n\n if (invalidated?.has(next.key)) {\n known.set(next.key, next.file)\n continue\n }\n if (!preexistingKeys.has(next.key)) {\n readState.set(next.key, next.file.entry)\n hydrated += 1\n }\n known.set(next.key, next.file)\n }\n }\n\n return hydrated\n}\n\nfunction normalizeHydrateReadStateOptions(options: HydrateReadStateOptions): NormalizedHydrateReadStateOptions {\n return {\n readFileToolName: options.readFileToolName ?? 'read_file',\n writeFileToolName: options.writeFileToolName ?? 'write_file',\n editToolName: options.editToolName ?? 'edit',\n multiEditToolName: options.multiEditToolName ?? 'multi_edit',\n defaultLineNumbers: options.defaultLineNumbers ?? true,\n ...(options.readFileForHash ? { readFileForHash: options.readFileForHash } : {}),\n }\n}\n\nfunction stateFromToolResult(\n call: PendingToolCall,\n output: string,\n resultTurn: SessionTurn,\n cwd: string,\n options: NormalizedHydrateReadStateOptions,\n known: Map<string, KnownFile>,\n): { key: string, file: KnownFile } | undefined {\n if (call.name === options.readFileToolName)\n return readFileStateFromResult(call.input, output, resultTurn, cwd, options.defaultLineNumbers)\n if (call.name === options.writeFileToolName)\n return writeFileStateFromResult(call.input, output, resultTurn, cwd)\n if (call.name === options.editToolName)\n return editStateFromResult(call.input, output, resultTurn, cwd, known)\n if (call.name === options.multiEditToolName)\n return multiEditStateFromResult(call.input, output, resultTurn, cwd, known)\n return undefined\n}\n\nasync function stateFromToolResultAsync(\n call: PendingToolCall,\n output: string,\n resultTurn: SessionTurn,\n cwd: string,\n options: NormalizedHydrateReadStateOptions,\n known: Map<string, KnownFile>,\n): Promise<{ key: string, file: KnownFile } | undefined> {\n if (call.name === options.readFileToolName) {\n return await readFileStateFromResultAsync(call.input, output, resultTurn, cwd, {\n defaultLineNumbers: options.defaultLineNumbers,\n readFileForHash: options.readFileForHash,\n })\n }\n return stateFromToolResult(call, output, resultTurn, cwd, options, known)\n}\n\nfunction readFileStateFromResult(\n input: Record<string, unknown>,\n output: string,\n resultTurn: SessionTurn,\n cwd: string,\n defaultLineNumbers: boolean,\n): { key: string, file: KnownFile } | undefined {\n const path = typeof input.path === 'string' ? input.path : undefined\n if (!path || !isSuccessfulFullReadOutput(output))\n return undefined\n\n const lineNumbers = typeof input.lineNumbers === 'boolean' ? input.lineNumbers : defaultLineNumbers\n const content = lineNumbers ? stripReadFileLineNumbers(output) : output\n if (content === undefined)\n return undefined\n\n const entry: ReadStateEntry = {\n contentHash: hashContent(content),\n offset: normalizeReadInteger(input.offset, READ_FILE_DEFAULT_OFFSET),\n limit: normalizeReadInteger(input.limit, READ_FILE_DEFAULT_LIMIT),\n maxBytes: normalizeReadInteger(input.maxBytes, READ_FILE_DEFAULT_MAX_BYTES),\n lineNumbers,\n mtimeMs: resultTurn.createdAt,\n }\n return { key: readStateKey(cwd, path), file: { content, entry } }\n}\n\nasync function readFileStateFromResultAsync(\n input: Record<string, unknown>,\n output: string,\n resultTurn: SessionTurn,\n cwd: string,\n options: {\n defaultLineNumbers: boolean\n readFileForHash?: HydrateReadStateOptions['readFileForHash']\n },\n): Promise<{ key: string, file: KnownFile } | undefined> {\n const reconstructed = readFileStateFromResult(input, output, resultTurn, cwd, options.defaultLineNumbers)\n if (reconstructed)\n return reconstructed\n\n const path = typeof input.path === 'string' ? input.path : undefined\n if (!path || !options.readFileForHash || !isSuccessfulReadOutput(output))\n return undefined\n\n let content: string | null | undefined\n try {\n content = await options.readFileForHash(path)\n }\n catch {\n return undefined\n }\n if (typeof content !== 'string')\n return undefined\n\n const lineNumbers = typeof input.lineNumbers === 'boolean' ? input.lineNumbers : options.defaultLineNumbers\n const entry: ReadStateEntry = {\n contentHash: hashContent(content),\n offset: normalizeReadInteger(input.offset, READ_FILE_DEFAULT_OFFSET),\n limit: normalizeReadInteger(input.limit, READ_FILE_DEFAULT_LIMIT),\n maxBytes: normalizeReadInteger(input.maxBytes, READ_FILE_DEFAULT_MAX_BYTES),\n lineNumbers,\n mtimeMs: resultTurn.createdAt,\n }\n return { key: readStateKey(cwd, path), file: { content, entry } }\n}\n\nfunction writeFileStateFromResult(\n input: Record<string, unknown>,\n output: string,\n resultTurn: SessionTurn,\n cwd: string,\n): { key: string, file: KnownFile } | undefined {\n const path = typeof input.path === 'string' ? input.path : undefined\n const content = typeof input.content === 'string' ? input.content : undefined\n if (!path || content === undefined)\n return undefined\n if (!output.startsWith(`Created ${path} (`) && !output.startsWith(`Updated ${path} (`))\n return undefined\n\n return {\n key: readStateKey(cwd, path),\n file: {\n content,\n entry: {\n contentHash: hashContent(content),\n offset: 0,\n limit: Number.POSITIVE_INFINITY,\n maxBytes: Number.POSITIVE_INFINITY,\n mtimeMs: resultTurn.createdAt,\n },\n },\n }\n}\n\nfunction editStateFromResult(\n input: Record<string, unknown>,\n output: string,\n resultTurn: SessionTurn,\n cwd: string,\n known: Map<string, KnownFile>,\n): { key: string, file: KnownFile } | undefined {\n const path = typeof input.path === 'string' ? input.path : undefined\n const oldString = typeof input.old_string === 'string' ? input.old_string : undefined\n const newString = typeof input.new_string === 'string' ? input.new_string : undefined\n if (!path || oldString === undefined || newString === undefined)\n return undefined\n if (!output.startsWith(`Edited ${path}: replaced `))\n return undefined\n\n const key = readStateKey(cwd, path)\n const prior = known.get(key)\n if (!prior)\n return undefined\n\n const nextContent = applyEdit(prior.content, oldString, newString, input.replace_all === true)\n if (nextContent === undefined)\n return undefined\n\n return {\n key,\n file: {\n content: nextContent,\n entry: { ...prior.entry, contentHash: hashContent(nextContent), mtimeMs: resultTurn.createdAt },\n },\n }\n}\n\ninterface MultiEditStep {\n old_string?: unknown\n new_string?: unknown\n replace_all?: unknown\n}\n\nfunction multiEditStateFromResult(\n input: Record<string, unknown>,\n output: string,\n resultTurn: SessionTurn,\n cwd: string,\n known: Map<string, KnownFile>,\n): { key: string, file: KnownFile } | undefined {\n const path = typeof input.path === 'string' ? input.path : undefined\n const edits = Array.isArray(input.edits) ? (input.edits as MultiEditStep[]) : undefined\n if (!path || !edits)\n return undefined\n if (!output.startsWith(`Edited ${path}: applied `))\n return undefined\n\n const key = readStateKey(cwd, path)\n const prior = known.get(key)\n if (!prior)\n return undefined\n\n const applied = parseMultiEditAppliedSteps(output, edits.length)\n let current = prior.content\n for (let i = 0; i < edits.length; i++) {\n if (!applied.has(i))\n continue\n const step = edits[i]\n if (typeof step.old_string !== 'string' || typeof step.new_string !== 'string')\n return undefined\n const next = applyEdit(current, step.old_string, step.new_string, step.replace_all === true)\n if (next === undefined)\n return undefined\n current = next\n }\n\n return {\n key,\n file: {\n content: current,\n entry: { ...prior.entry, contentHash: hashContent(current), mtimeMs: resultTurn.createdAt },\n },\n }\n}\n\nfunction applyEdit(content: string, oldString: string, newString: string, replaceAll: boolean): string | undefined {\n const match = resolveOldString(content, oldString)\n if (!match)\n return undefined\n if (match.occurrences > 1 && !replaceAll)\n return undefined\n const styledReplacement = styleReplacementForVia(newString, match.via, match.actual)\n return replaceAll\n ? content.split(match.actual).join(styledReplacement)\n : content.replace(match.actual, styledReplacement)\n}\n\nfunction parseMultiEditAppliedSteps(output: string, editCount: number): Set<number> {\n const annotationMatch = /<edit-outcomes>\\n([\\s\\S]*?)\\n<\\/edit-outcomes>/.exec(output)\n if (!annotationMatch) {\n return new Set(Array.from({ length: editCount }, (_, i) => i))\n }\n\n const applied = new Set<number>()\n for (const line of annotationMatch[1].split('\\n')) {\n const match = /^#(\\d+) applied$/.exec(line.trim())\n if (!match)\n continue\n const index = Number(match[1]) - 1\n if (index >= 0 && index < editCount)\n applied.add(index)\n }\n return applied\n}\n\nfunction isSuccessfulFullReadOutput(output: string): boolean {\n // Live read_file stores a hash of the raw full file before pagination or\n // truncation. Durable turns only contain rendered output, so partial reads\n // cannot be reconstructed safely; skip them and require a real re-read.\n if (!isSuccessfulReadOutput(output) || READ_FILE_FOOTER_RE.test(output))\n return false\n return true\n}\n\nfunction isSuccessfulReadOutput(output: string): boolean {\n if (output.length === 0)\n return true\n if (\n output.startsWith('File not found:')\n || output.startsWith('[binary file:')\n || output.startsWith('Image:')\n || output.startsWith('Document:')\n || output.startsWith('[image too large to inline:')\n || output.startsWith('[document:')\n || output.startsWith('[document too large to attach:')\n || output.startsWith('Image read failed:')\n || output.startsWith('Document read failed:')\n || output.includes(' unchanged since the previous read in this session ')\n ) {\n return false\n }\n return true\n}\n\nfunction stripReadFileLineNumbers(output: string): string | undefined {\n const lines = output.split('\\n')\n const stripped: string[] = []\n for (const line of lines) {\n const match = READ_FILE_LINE_RE.exec(line)\n if (!match)\n return undefined\n stripped.push(match[1])\n }\n return stripped.join('\\n')\n}\n\nfunction normalizeReadInteger(value: unknown, fallback: number): number {\n if (typeof value !== 'number' || !Number.isFinite(value) || value < 0)\n return fallback\n return Math.floor(value)\n}\n\n// ---------------------------------------------------------------------------\n// Tool-dedup\n// ---------------------------------------------------------------------------\n\nexport interface ToolDedupEntry {\n hash: string\n result: string | ToolResultContent[]\n /**\n * Number of replay-hits accumulated against this `(name, hash)` since\n * the most recent fresh dispatch. `0` immediately after a fresh\n * dispatch; incremented every time a `tool:gate` handler returns the\n * cached result for an identical input. Used by `dedup-tools` to\n * implement `mode: 'block-after'` — when the count crosses the\n * configured threshold, the gate stops replaying and refuses the call\n * with a `Blocked:` tool_result so the model breaks out of the loop.\n *\n * Resets to `0` on a hash change (a different input under the same\n * tool name is treated as a fresh sequence). Optional for back-compat\n * with consumers that built the entry directly; absent is treated as\n * `0`.\n */\n repeats?: number\n}\n\nexport type ToolDedupMap = Map<string, ToolDedupEntry>\n\nconst TOOL_DEDUP_STATE = new WeakMap<Session, ToolDedupMap>()\n\n/**\n * Get or lazily create the per-session tool-dedup map. Returns `undefined`\n * when no session is provided — middleware should treat that as \"no dedup\".\n */\nexport function getToolDedupState(session: Session | undefined): ToolDedupMap | undefined {\n if (!session)\n return undefined\n let map = TOOL_DEDUP_STATE.get(session)\n if (!map) {\n map = new Map()\n TOOL_DEDUP_STATE.set(session, map)\n }\n return map\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"restate.d.ts","names":[],"sources":["../src/restate/behavior.ts","../src/restate/types.ts","../src/restate/clock.ts","../src/restate/errors.ts","../src/restate/parallel.ts","../src/restate/provider.ts","../src/restate/session.ts","../src/restate/tool.ts"],"mappings":";;;;;AASA;;;;iBAAgB,eAAA,CAAgB,SAAA,GAAW,aAAA,GAAqB,aAAa;;;;;;AAA7E;;;;;;;;AAA6E;;;;ACU7E;;;UAAiB,iBAAA;EAEf;EAAA,gBAAA;EAIA;EAFA,gBAAA;EAMA;EAJA,oBAAA;EAMK;EAJL,gBAAA;EAce;EAZf,mBAAA;EAY+B;EAV/B,KAAA;AAAA;;;;;;AAYkB;AAuBpB;UAzBiB,gBAAA;EACf,EAAA;EACA,OAAA,EAAS,OAAO,CAAC,CAAA;AAAA;;;;;;;;;;;;;;;;;;;;;UAuBF,kBAAA;EACf,GAAA,MACE,IAAA,UACA,EAAA,QAAU,OAAA,CAAQ,CAAA,IAAK,CAAA,EACvB,OAAA,GAAU,iBAAA,KACP,OAAA,CAAQ,CAAA;EACb,IAAA;IAAQ,GAAA,QAAW,OAAA;EAAA;EACnB,IAAA;IAAQ,MAAA;EAAA;EACR,SAAA,WAAoB,gBAAA,CAAiB,CAAA;AAAA;AAAC;AAUxC;;;;;;AAVwC,UAUvB,wBAAA,SAAiC,kBAAA;EAChD,GAAA;EACA,GAAA,MAAS,IAAA,aAAiB,OAAA,CAAQ,CAAA;EAClC,GAAA,MAAS,IAAA,UAAc,KAAA,EAAO,CAAA;EAC9B,KAAA,GAAQ,IAAA;AAAA;;;;;;AArEV;;;;;iBCGgB,YAAA,CAAa,GAAA,EAAK,kBAAA,GAAqB,UAAU;;;;;;AFbjE;;;;iBGFgB,gCAAA,CAAiC,KAAc;;;UCJ9C,qBAAA,kBAAuC,OAAA,YAAmB,kBAAA;EACzE,GAAA,GAAM,MAAA,WAAiB,QAAA,OAAe,OAAA;AAAA;AAAA,KAG5B,kBAAA,MAAwB,OAAA,CAAQ,CAAA;EAC1C,GAAA,MAAS,MAAA,GAAS,KAAA,GAAQ,CAAA,EAAG,OAAA,eAAsB,CAAA,KAAM,OAAA,CAAQ,CAAA;AAAA;AAAA,UAGlD,+BAAA,kBAAiD,OAAA,YAAmB,kBAAA;EJFrD;;;AAA6C;EIO3E,QAAA,EAAU,qBAAA,CAAsB,QAAA;AAAA;;AHGlC;;;;;;iBGOgB,wBAAA,kBAA0C,OAAA,YAAmB,kBAAA,UAAA,CAC3E,OAAA,EAAS,+BAAA,CAAgC,QAAA,IACxC,iBAAA;;;UCHc,sBAAA;EJMf;;AAAK;AAUP;;;;EIRE,UAAA,GAAa,iBAAA;EJSb;;;;;AACkB;AAuBpB;EIzBE,SAAA,IAAa,GAAA,UAAa,IAAA,EAAM,aAAa;EJyBZ;;;;;;;EIjBjC,eAAA;AAAA;;;;;;;iBASc,eAAA,CACd,KAAA,EAAO,QAAA,EACP,GAAA,EAAK,kBAAA,EACL,OAAA,GAAS,sBAAA,GACR,QAAA;;;;;;;;;;;iBCFa,mBAAA,CAAoB,GAAA,EAAK,wBAAA,GAA2B,YAAY;;;UC/B/D,kBAAA;ENEV;AAUP;;;;;;EMJE,UAAA,GAAa,iBAAA;ENMJ;;;AAAS;AAuBpB;;;;EMpBE,SAAA,IAAa,GAAA,UAAa,IAAA,UAAc,KAAA,EAAO,MAAM;ENuB5B;;;;EMlBzB,sBAAA;AAAA;;;;;iBAUc,WAAA,CACd,KAAA,EAAO,OAAA,EACP,GAAA,EAAK,kBAAA,EACL,OAAA,GAAS,kBAAA,GACR,OAAA;;;;;;;;;iBAgFa,cAAA,CACd,KAAA,EAAO,MAAA,SAAe,OAAA,GACtB,GAAA,EAAK,kBAAA,EACL,IAAA,GAAM,kBAAA;EAAuB,OAAA;AAAA,IAC5B,MAAA,SAAe,OAAA"}
1
+ {"version":3,"file":"restate.d.ts","names":[],"sources":["../src/restate/behavior.ts","../src/restate/types.ts","../src/restate/clock.ts","../src/restate/errors.ts","../src/restate/parallel.ts","../src/restate/provider.ts","../src/restate/session.ts","../src/restate/tool.ts"],"mappings":";;;;;AASA;;;;iBAAgB,eAAA,CAAgB,SAAA,GAAW,aAAA,GAAqB,aAAa;;;;;;AAA7E;;;;;;;;AAA6E;;;;ACU7E;;;UAAiB,iBAAA;EAEf;EAAA,gBAAA;EAIA;EAFA,gBAAA;EAMA;EAJA,oBAAA;EAMK;EAJL,gBAAA;EAce;EAZf,mBAAA;EAY+B;EAV/B,KAAA;AAAA;;;;;;AAYkB;AAuBpB;UAzBiB,gBAAA;EACf,EAAA;EACA,OAAA,EAAS,OAAO,CAAC,CAAA;AAAA;;;;;;;;;;;;;;;;;;;;;UAuBF,kBAAA;EACf,GAAA,MACE,IAAA,UACA,EAAA,QAAU,OAAA,CAAQ,CAAA,IAAK,CAAA,EACvB,OAAA,GAAU,iBAAA,KACP,OAAA,CAAQ,CAAA;EACb,IAAA;IAAQ,GAAA,QAAW,OAAA;EAAA;EACnB,IAAA;IAAQ,MAAA;EAAA;EACR,SAAA,WAAoB,gBAAA,CAAiB,CAAA;AAAA;AAAC;AAUxC;;;;;;AAVwC,UAUvB,wBAAA,SAAiC,kBAAA;EAChD,GAAA;EACA,GAAA,MAAS,IAAA,aAAiB,OAAA,CAAQ,CAAA;EAClC,GAAA,MAAS,IAAA,UAAc,KAAA,EAAO,CAAA;EAC9B,KAAA,GAAQ,IAAA;AAAA;;;;;;AArEV;;;;;iBCGgB,YAAA,CAAa,GAAA,EAAK,kBAAA,GAAqB,UAAU;;;;;;AFbjE;;;;iBGFgB,gCAAA,CAAiC,KAAc;;;UCJ9C,qBAAA,kBAAuC,OAAA,YAAmB,kBAAA;EACzE,GAAA,GAAM,MAAA,WAAiB,QAAA,OAAe,OAAA;AAAA;AAAA,KAG5B,kBAAA,MAAwB,OAAA,CAAQ,CAAA;EAC1C,GAAA,MAAS,MAAA,GAAS,KAAA,GAAQ,CAAA,EAAG,OAAA,eAAsB,CAAA,KAAM,OAAA,CAAQ,CAAA;AAAA;AAAA,UAGlD,+BAAA,kBAAiD,OAAA,YAAmB,kBAAA;EJFrD;;;AAA6C;EIO3E,QAAA,EAAU,qBAAA,CAAsB,QAAA;AAAA;;AHGlC;;;;;;iBGOgB,wBAAA,kBAA0C,OAAA,YAAmB,kBAAA,UAAA,CAC3E,OAAA,EAAS,+BAAA,CAAgC,QAAA,IACxC,iBAAA;;;UCHc,sBAAA;EJMf;;AAAK;AAUP;;;;EIRE,UAAA,GAAa,iBAAA;EJSb;;;;;AACkB;AAuBpB;EIzBE,SAAA,IAAa,GAAA,UAAa,IAAA,EAAM,aAAa;EJyBZ;;;;;;;EIjBjC,eAAA;AAAA;;;;;;;iBASc,eAAA,CACd,KAAA,EAAO,QAAA,EACP,GAAA,EAAK,kBAAA,EACL,OAAA,GAAS,sBAAA,GACR,QAAA;;;;;;;;;;;iBCFa,mBAAA,CAAoB,GAAA,EAAK,wBAAA,GAA2B,YAAY;;;UC/B/D,kBAAA;ENEV;AAUP;;;;;;EMJE,UAAA,GAAa,iBAAA;ENMJ;;;AAAS;AAuBpB;;;;EMpBE,SAAA,IAAa,GAAA,UAAa,IAAA,UAAc,KAAA,EAAO,MAAM;ENuB5B;;;;EMlBzB,sBAAA;AAAA;;;;;iBAUc,WAAA,CACd,KAAA,EAAO,OAAA,EACP,GAAA,EAAK,kBAAA,EACL,OAAA,GAAS,kBAAA,GACR,OAAA;;;;;;;;;iBA2Fa,cAAA,CACd,KAAA,EAAO,MAAA,SAAe,OAAA,GACtB,GAAA,EAAK,kBAAA,EACL,IAAA,GAAM,kBAAA;EAAuB,OAAA;AAAA,IAC5B,MAAA,SAAe,OAAA"}
package/dist/restate.js CHANGED
@@ -1,4 +1,4 @@
1
- import { i as hydrateReadStateFromSession } from "./read-state-Cr0MrWRm.js";
1
+ import { i as hydrateReadStateFromSessionAsync } from "./read-state-DMHYFRR9.js";
2
2
  //#region src/restate/errors.ts
3
3
  /**
4
4
  * Restate control-flow errors must escape the agent loop. If they are turned
@@ -299,13 +299,25 @@ function restateTool(inner, ctx, options = {}) {
299
299
  const canonicalName = inner.spec.name;
300
300
  const shellBackgroundDisabled = (options.disableShellBackground ?? true) && canonicalName === "shell";
301
301
  let seq = 0;
302
- const executeDurably = (input, toolCtx) => {
303
- seq += 1;
302
+ const hydrateOnce = async (toolCtx) => {
304
303
  if (toolCtx.session && !HYDRATED_READ_STATE_SESSIONS.has(toolCtx.session)) {
305
- hydrateReadStateFromSession(toolCtx.session, toolCtx.handle.cwd, { defaultLineNumbers: toolCtx.behavior?.readLineNumbers ?? true });
306
304
  HYDRATED_READ_STATE_SESSIONS.add(toolCtx.session);
305
+ await hydrateReadStateFromSessionAsync(toolCtx.session, toolCtx.handle.cwd, {
306
+ defaultLineNumbers: toolCtx.behavior?.readLineNumbers ?? true,
307
+ readFileForHash: async (path) => {
308
+ try {
309
+ return await toolCtx.execution.readFile(toolCtx.handle, path);
310
+ } catch {
311
+ return null;
312
+ }
313
+ }
314
+ });
307
315
  }
308
- return ctx.run(nameFor(seq, canonicalName, input), () => {
316
+ };
317
+ const executeDurably = (input, toolCtx) => {
318
+ seq += 1;
319
+ return ctx.run(nameFor(seq, canonicalName, input), async () => {
320
+ await hydrateOnce(toolCtx);
309
321
  if (shellBackgroundDisabled && input.run_in_background === true) return SHELL_BACKGROUND_DISABLED_MESSAGE;
310
322
  return inner.execute(input, toolCtx);
311
323
  }, runOpts);
@@ -1 +1 @@
1
- {"version":3,"file":"restate.js","names":[],"sources":["../src/restate/errors.ts","../src/restate/behavior.ts","../src/restate/clock.ts","../src/restate/parallel.ts","../src/restate/provider.ts","../src/restate/session.ts","../src/restate/tool.ts"],"sourcesContent":["/**\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 */\nexport function restateBehavior(overrides: AgentBehavior = {}): AgentBehavior {\n return {\n maxConcurrentTools: 1,\n disableBackgroundTasks: true,\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","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 { RestateContextLike, RestateRunOptions } from './types'\n\nexport interface RestateProviderOptions {\n /**\n * `ctx.run` options forwarded on every wrapped stream call. Defaults\n * to `{ maxRetryAttempts: 3 }` — provider transients (rate limits,\n * 5xx, connection resets) get retried inside the journal entry. Once\n * the cap is reached the failure becomes terminal and surfaces\n * through the loop's normal `AgentProviderError` path.\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\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 const runOpts: RestateRunOptions = options.runOptions ?? { maxRetryAttempts: 3 }\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 () => inner.stream(streamOpts, durableCallbacks),\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 }\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 ctx.set(KEY_DATA, header)\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 next[idx] = sanitizeRunForState(run)\n else\n next.push(sanitizeRunForState(run))\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 * 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 { Session } from '../session'\nimport type { ToolDef } from '../tools/types'\nimport type { RestateContextLike, RestateRunOptions } from './types'\nimport { hydrateReadStateFromSession } from '../tools/read-state'\n\nexport interface RestateToolOptions {\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\n * and the call's input. Default: `tool-<name>-<seq>` where `<seq>` is\n * a per-wrapper monotonic counter. Override to inject the model's\n * `callId` (read it off `ToolContext.callId` inside `execute` if you\n * need an LLM-visible key — but the default counter is sufficient\n * for journal correctness).\n */\n entryName?: (seq: number, name: string, input: Record<string, unknown>) => string\n /**\n * Hide and reject the built-in shell tool's background mode. Defaults to\n * `true` because Restate cannot recover host-local background processes.\n */\n disableShellBackground?: 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(\n inner: ToolDef,\n ctx: RestateContextLike,\n options: RestateToolOptions = {},\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 ?? true\n const shellBackgroundDisabled = disableShellBackground && canonicalName === 'shell'\n let seq = 0\n const executeDurably = (input: Record<string, unknown>, toolCtx: Parameters<ToolDef['execute']>[1]) => {\n seq += 1\n if (toolCtx.session && !HYDRATED_READ_STATE_SESSIONS.has(toolCtx.session)) {\n hydrateReadStateFromSession(toolCtx.session, toolCtx.handle.cwd, {\n defaultLineNumbers: toolCtx.behavior?.readLineNumbers ?? true,\n })\n HYDRATED_READ_STATE_SESSIONS.add(toolCtx.session)\n }\n return ctx.run(\n nameFor(seq, canonicalName, input),\n () => {\n if (shellBackgroundDisabled && input.run_in_background === true)\n return SHELL_BACKGROUND_DISABLED_MESSAGE\n return inner.execute(input, toolCtx)\n },\n runOpts,\n )\n }\n\n return {\n ...inner,\n spec: shellBackgroundDisabled ? withoutShellBackgroundInput(inner.spec) : inner.spec,\n execute: executeDurably,\n durableExecute: executeDurably,\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: RestateToolOptions & { exclude?: readonly string[] } = {},\n): Record<string, ToolDef> {\n const excludeSet = new Set(opts.exclude ?? [])\n const wrapped: Record<string, ToolDef> = {}\n for (const [name, def] of Object.entries(tools)) {\n wrapped[name] = excludeSet.has(name) ? def : restateTool(def, ctx, opts)\n }\n return wrapped\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"restate.js","names":[],"sources":["../src/restate/errors.ts","../src/restate/behavior.ts","../src/restate/clock.ts","../src/restate/parallel.ts","../src/restate/provider.ts","../src/restate/session.ts","../src/restate/tool.ts"],"sourcesContent":["/**\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 */\nexport function restateBehavior(overrides: AgentBehavior = {}): AgentBehavior {\n return {\n maxConcurrentTools: 1,\n disableBackgroundTasks: true,\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","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 { RestateContextLike, RestateRunOptions } from './types'\n\nexport interface RestateProviderOptions {\n /**\n * `ctx.run` options forwarded on every wrapped stream call. Defaults\n * to `{ maxRetryAttempts: 3 }` — provider transients (rate limits,\n * 5xx, connection resets) get retried inside the journal entry. Once\n * the cap is reached the failure becomes terminal and surfaces\n * through the loop's normal `AgentProviderError` path.\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\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 const runOpts: RestateRunOptions = options.runOptions ?? { maxRetryAttempts: 3 }\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 () => inner.stream(streamOpts, durableCallbacks),\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 }\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 ctx.set(KEY_DATA, header)\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 next[idx] = sanitizeRunForState(run)\n else\n next.push(sanitizeRunForState(run))\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 * 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 { Session } from '../session'\nimport type { ToolDef } from '../tools/types'\nimport type { RestateContextLike, RestateRunOptions } from './types'\nimport { hydrateReadStateFromSessionAsync } from '../tools/read-state'\n\nexport interface RestateToolOptions {\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\n * and the call's input. Default: `tool-<name>-<seq>` where `<seq>` is\n * a per-wrapper monotonic counter. Override to inject the model's\n * `callId` (read it off `ToolContext.callId` inside `execute` if you\n * need an LLM-visible key — but the default counter is sufficient\n * for journal correctness).\n */\n entryName?: (seq: number, name: string, input: Record<string, unknown>) => string\n /**\n * Hide and reject the built-in shell tool's background mode. Defaults to\n * `true` because Restate cannot recover host-local background processes.\n */\n disableShellBackground?: 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(\n inner: ToolDef,\n ctx: RestateContextLike,\n options: RestateToolOptions = {},\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 ?? true\n const shellBackgroundDisabled = disableShellBackground && canonicalName === 'shell'\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 executeDurably = (input: Record<string, unknown>, toolCtx: Parameters<ToolDef['execute']>[1]) => {\n seq += 1\n return ctx.run(\n nameFor(seq, canonicalName, input),\n async () => {\n await hydrateOnce(toolCtx)\n if (shellBackgroundDisabled && input.run_in_background === true)\n return SHELL_BACKGROUND_DISABLED_MESSAGE\n return inner.execute(input, toolCtx)\n },\n runOpts,\n )\n }\n\n return {\n ...inner,\n spec: shellBackgroundDisabled ? withoutShellBackgroundInput(inner.spec) : inner.spec,\n execute: executeDurably,\n durableExecute: executeDurably,\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: RestateToolOptions & { exclude?: readonly string[] } = {},\n): Record<string, ToolDef> {\n const excludeSet = new Set(opts.exclude ?? [])\n const wrapped: Record<string, ToolDef> = {}\n for (const [name, def] of Object.entries(tools)) {\n wrapped[name] = excludeSet.has(name) ? def : restateTool(def, ctx, opts)\n }\n return wrapped\n}\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { p as toWireMessages } from "./messages-CWz0yRAE.js";
1
+ import { p as toWireMessages } from "./messages-wOJ8LTs0.js";
2
2
  //#region src/session/file-map.ts
3
3
  function toMeta(data) {
4
4
  return {
@@ -477,4 +477,4 @@ function generateId() {
477
477
  //#endregion
478
478
  export { createFileMapStore as a, createMemoryStore as i, loadSession as n, createRemoteStore as r, createSession as t };
479
479
 
480
- //# sourceMappingURL=session-SMszIfE6.js.map
480
+ //# sourceMappingURL=session-z0E9-e4b.js.map