zidane 5.13.21 → 5.13.22

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 (63) hide show
  1. package/dist/{acp-aJVJED3r.js → acp-D5Z_muH-.js} +4 -4
  2. package/dist/{acp-aJVJED3r.js.map → acp-D5Z_muH-.js.map} +1 -1
  3. package/dist/acp-cli.js +2 -2
  4. package/dist/acp.d.ts +2 -2
  5. package/dist/acp.js +1 -1
  6. package/dist/{agent-B_jcbRS1.d.ts → agent-DQIL5BFk.d.ts} +2 -21
  7. package/dist/{agent-B_jcbRS1.d.ts.map → agent-DQIL5BFk.d.ts.map} +1 -1
  8. package/dist/chat/pure.d.ts +3 -3
  9. package/dist/chat.d.ts +6 -6
  10. package/dist/chat.js +2 -2
  11. package/dist/contexts/daytona.d.ts +1 -1
  12. package/dist/contexts/e2b.d.ts +1 -1
  13. package/dist/eval.d.ts +1 -1
  14. package/dist/eval.js +1 -1
  15. package/dist/{headless-XTYJhHcn.js → headless-Dk5JvNjb.js} +3 -3
  16. package/dist/{headless-XTYJhHcn.js.map → headless-Dk5JvNjb.js.map} +1 -1
  17. package/dist/headless.d.ts +1 -1
  18. package/dist/headless.js +1 -1
  19. package/dist/{index-C8bTrzYr.d.ts → index-C5qw3pj7.d.ts} +2 -2
  20. package/dist/{index-C8bTrzYr.d.ts.map → index-C5qw3pj7.d.ts.map} +1 -1
  21. package/dist/{index-B9tOi27d.d.ts → index-YY3vp2F2.d.ts} +2 -2
  22. package/dist/{index-B9tOi27d.d.ts.map → index-YY3vp2F2.d.ts.map} +1 -1
  23. package/dist/index.d.ts +5 -5
  24. package/dist/index.js +5 -5
  25. package/dist/{logger-SE8Qb62V.d.ts → logger-C2ngE8CY.d.ts} +2 -2
  26. package/dist/{logger-SE8Qb62V.d.ts.map → logger-C2ngE8CY.d.ts.map} +1 -1
  27. package/dist/mcp.d.ts +1 -1
  28. package/dist/output/stream-json.d.ts +2 -2
  29. package/dist/output/stream-json.js +1 -1
  30. package/dist/output/terminal.d.ts +2 -2
  31. package/dist/{presets-4bHMTjG3.js → presets-BVUwZhtJ.js} +2 -2
  32. package/dist/{presets-4bHMTjG3.js.map → presets-BVUwZhtJ.js.map} +1 -1
  33. package/dist/presets.d.ts +2 -2
  34. package/dist/presets.js +1 -1
  35. package/dist/providers.d.ts +1 -1
  36. package/dist/{read-state-B9O85Lel.js → read-state-BymF41Jb.js} +2 -35
  37. package/dist/{read-state-B9O85Lel.js.map → read-state-BymF41Jb.js.map} +1 -1
  38. package/dist/restate.d.ts +1 -1
  39. package/dist/restate.d.ts.map +1 -1
  40. package/dist/restate.js +9 -10
  41. package/dist/restate.js.map +1 -1
  42. package/dist/session/sqlite.d.ts +1 -1
  43. package/dist/session.d.ts +1 -1
  44. package/dist/skills.d.ts +2 -2
  45. package/dist/{tool-formatters-CmhXO6rT.d.ts → tool-formatters-w5oaoCS4.d.ts} +2 -2
  46. package/dist/{tool-formatters-CmhXO6rT.d.ts.map → tool-formatters-w5oaoCS4.d.ts.map} +1 -1
  47. package/dist/tools/fetch-url.d.ts +1 -1
  48. package/dist/tools/web-search.d.ts +1 -1
  49. package/dist/{tools-DcUatsZX.js → tools-C4mCSY-v.js} +64 -18
  50. package/dist/{tools-DcUatsZX.js.map → tools-C4mCSY-v.js.map} +1 -1
  51. package/dist/tools.d.ts +3 -3
  52. package/dist/tools.js +3 -3
  53. package/dist/{transcript-anchors-Pa_XV1L5.js → transcript-anchors-C2XIpLNm.js} +3 -3
  54. package/dist/{transcript-anchors-Pa_XV1L5.js.map → transcript-anchors-C2XIpLNm.js.map} +1 -1
  55. package/dist/{transcript-anchors-Ccd3F7TL.d.ts → transcript-anchors-Ck87n_AS.d.ts} +4 -4
  56. package/dist/{transcript-anchors-Ccd3F7TL.d.ts.map → transcript-anchors-Ck87n_AS.d.ts.map} +1 -1
  57. package/dist/tui.d.ts +3 -3
  58. package/dist/tui.js +3 -3
  59. package/dist/{turn-operations-5lddMiNs.d.ts → turn-operations-CAE2bkOa.d.ts} +3 -3
  60. package/dist/{turn-operations-5lddMiNs.d.ts.map → turn-operations-CAE2bkOa.d.ts.map} +1 -1
  61. package/dist/types.d.ts +2 -2
  62. package/docs/ARCHITECTURE.md +1 -1
  63. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
- import { a as hydrateReadStateFromSession, c as readStateKey, i as hashContent, l as resolveReadStateMap, n as getReadState, o as hydrateReadStateFromSessionAsync, t as ensureReadStateHydratedOnce } from "./read-state-B9O85Lel.js";
1
+ import { a as hydrateReadStateFromSessionAsync, c as resolveReadStateMap, i as hydrateReadStateFromSession, r as hashContent, s as readStateKey, t as getReadState } from "./read-state-BymF41Jb.js";
2
2
  import { n as estimateTokens, r as utf8ByteLength, t as BYTES_PER_TOKEN } from "./utils-ngQzYzZD.js";
3
- import { $ as sliceForCompaction, A as PERSISTED_STUB_PREFIX, B as selectFilesFromSession, C as normalizeShellCommand, D as TOOL_USE_CANCELLED_MESSAGE, E as SHELL_CASCADE_CANCEL_MESSAGE, G as TRAILER, H as compactConversation, I as resolvePersistDir, J as buildFullCompactPrompt, K as buildCompactPrompt, L as resolveTasksDir, M as buildPersistedStub, N as cleanupPersistedSession, O as TOOL_USE_SKIPPED_MESSAGE, P as maybePersistToolResult, Q as anchorPreviewFor, R as buildPostCompactAttachments, S as defaultRepeatGuardTracked, T as INTERRUPT_MESSAGE_FOR_TOOL_USE, U as BASE_INSTRUCTIONS, V as selectRecentFiles, W as NO_TOOLS_PREAMBLE, X as buildUpToCompactPrompt, Y as buildTailCompactPrompt, Z as ANCHOR_PREVIEW_MAX_CHARS, _ as createSkillsReadTool, a as multiEdit, at as OperationTimeoutError, c as grep, ct as OUTPUT_RESERVE_TOKENS, d as createAgent, et as stripImagesFromTurns, g as createSkillsRunScriptTool, h as createSkillsUseTool, it as CompactPromptTooLongError, j as PERSISTENCE_PREVIEW_BYTES, k as validateToolArgs, l as glob, lt as effectiveContextWindow, n as createSpawnTool, nt as truncateHeadForPtlRetry, p as waitTask, q as buildFromCompactPrompt, rt as CompactInvalidInputError, s as createInteractionTool, st as AUTO_COMPACT_MIN_GROWTH_FRACTION, tt as summaryToTurn, u as edit, ut as shouldAutoCompact, v as createShellTool, w as stableStringify, x as defaultRepeatGuardNormalize, z as selectFilesFromReadState } from "./tools-DcUatsZX.js";
3
+ import { $ as sliceForCompaction, A as PERSISTED_STUB_PREFIX, B as selectFilesFromSession, C as normalizeShellCommand, D as TOOL_USE_CANCELLED_MESSAGE, E as SHELL_CASCADE_CANCEL_MESSAGE, G as TRAILER, H as compactConversation, I as resolvePersistDir, J as buildFullCompactPrompt, K as buildCompactPrompt, L as resolveTasksDir, M as buildPersistedStub, N as cleanupPersistedSession, O as TOOL_USE_SKIPPED_MESSAGE, P as maybePersistToolResult, Q as anchorPreviewFor, R as buildPostCompactAttachments, S as defaultRepeatGuardTracked, T as INTERRUPT_MESSAGE_FOR_TOOL_USE, U as BASE_INSTRUCTIONS, V as selectRecentFiles, W as NO_TOOLS_PREAMBLE, X as buildUpToCompactPrompt, Y as buildTailCompactPrompt, Z as ANCHOR_PREVIEW_MAX_CHARS, _ as createSkillsReadTool, a as multiEdit, at as OperationTimeoutError, c as grep, ct as OUTPUT_RESERVE_TOKENS, d as createAgent, et as stripImagesFromTurns, g as createSkillsRunScriptTool, h as createSkillsUseTool, it as CompactPromptTooLongError, j as PERSISTENCE_PREVIEW_BYTES, k as validateToolArgs, l as glob, lt as effectiveContextWindow, n as createSpawnTool, nt as truncateHeadForPtlRetry, p as waitTask, q as buildFromCompactPrompt, rt as CompactInvalidInputError, s as createInteractionTool, st as AUTO_COMPACT_MIN_GROWTH_FRACTION, tt as summaryToTurn, u as edit, ut as shouldAutoCompact, v as createShellTool, w as stableStringify, x as defaultRepeatGuardNormalize, z as selectFilesFromReadState } from "./tools-C4mCSY-v.js";
4
4
  import { n as createProcessContext, t as resolveDetachedTasksCapability } from "./contexts-BebciJyQ.js";
5
5
  import { createSandboxContext } from "./contexts/sandbox.js";
6
6
  import { a as toolOutputBudgetByteLength, o as toolOutputByteLength, s as toolResultToText } from "./types-CyVGdbia.js";
@@ -9,8 +9,8 @@ import { A as joinSystemPrompt, C as sanitizeToolSchema, D as appendDynamicSecti
9
9
  import { _ as validateResourcePath, a as writeSkillsToDisk, b as validateSkillName, d as buildCatalog, f as IMPLICITLY_ALLOWED_SKILL_TOOLS, g as parseAllowedToolPattern, h as matchesAllowedTool, i as writeSkillToDisk, m as isToolAllowedByUnion, n as stripShellInterpolations, o as discoverSkills, p as installAllowedToolsGate, r as resolveSkills, t as interpolateShellCommands, u as parseSkillFile, v as validateResourcePathReal, x as createSkillActivationState, y as validateSkillForWrite } from "./interpolate-BtIgcCuz.js";
10
10
  import { i as statsByModel, n as flattenTurns } from "./stats-DAKBEKjc.js";
11
11
  import { a as normalizeMcpServers, d as createMemoryMcpCredentialStore, f as hasAuthorizationHeader, i as normalizeMcpBlocks, n as connectMcpServers, o as resultToString, u as McpOAuthProvider } from "./mcp-Dn5W65Lv.js";
12
- import { i as basic_default, n as definePreset, r as basicTools } from "./presets-4bHMTjG3.js";
13
- import { a as headlessEventToJsonl, c as runHeadless, d as createRunSummaryCollector, l as transcriptToOpenAIMessages } from "./headless-XTYJhHcn.js";
12
+ import { i as basic_default, n as definePreset, r as basicTools } from "./presets-BVUwZhtJ.js";
13
+ import { a as headlessEventToJsonl, c as runHeadless, d as createRunSummaryCollector, l as transcriptToOpenAIMessages } from "./headless-Dk5JvNjb.js";
14
14
  import { a as createMemoryStore, i as createRemoteStore, o as createFileMapStore, r as loadSession, t as createSession } from "./session-CiA1_8SB.js";
15
15
  import { EFFICIENCY_METRICS, EvalMetricError, artifactPath, buildEvalRunSummary, buildRegisteredEvals, buildTrajectory, clearRegisteredEvals, computeEvalTagScores, createEvalAgent, createEvalRunReporter, createReusableExecutionContext, defineEval, defineMetrics, efficiencyMetricValues, emitEfficiencyMetrics, fileContains, fileContentQuality, fileExists, fileExistsOneOf, finalizeEvalMetrics, formatEvalCaseSummary, formatEvalRunSummary, formatTrajectoryLine, functionalityMetric, llmJudge, normalizeMetric, registerEvalTests, relativeArtifactPath, runEvalCase, statusCompleted } from "./eval.js";
16
16
  import { i as jsonSink, n as createLogger, r as createLoggingHooks, t as consoleSink } from "./logger-Ktm-lj1s.js";
@@ -1267,6 +1267,6 @@ function zodToJsonSchema(jsonSchema) {
1267
1267
  return rest;
1268
1268
  }
1269
1269
  //#endregion
1270
- export { ANCHOR_PREVIEW_MAX_CHARS, AUTO_COMPACT_MIN_GROWTH_FRACTION, AgentAbortedError, AgentBudgetExceededError, AgentContextExceededError, AgentProviderError, AgentToolNotAllowedError, AgentToolPairingError, BASE_INSTRUCTIONS, BYTES_PER_TOKEN, CONTEXT_EXCEEDED_MESSAGE_PATTERNS, CompactInvalidInputError, CompactPromptTooLongError, EFFICIENCY_METRICS, EvalMetricError, GEN_AI_ATTRIBUTES, IMPLICITLY_ALLOWED_SKILL_TOOLS, INTERRUPT_MESSAGE_FOR_TOOL_USE, McpOAuthProvider, NO_TOOLS_PREAMBLE, ORPHANED_TOOL_RESULT_MARKER, OUTPUT_RESERVE_TOKENS, OpenAICompatHttpError, OperationTimeoutError, PERSISTED_STUB_PREFIX, PERSISTENCE_PREVIEW_BYTES, SHELL_CASCADE_CANCEL_MESSAGE, SYNTHETIC_TOOL_RESULT_PLACEHOLDER, SYSTEM_PROMPT_BOUNDARY, TOOL_USE_CANCELLED_MESSAGE, TOOL_USE_INTERRUPTED_MARKER, TOOL_USE_SKIPPED_MESSAGE, TRAILER, anchorPreviewFor, anthropic, appendDynamicSection, appendStaticSection, applyAnthropicCacheBreakpoints, arcee, artifactPath, autoDetectAndConvert, baseten, basic_default as basic, basicTools, buildCatalog, buildCompactPrompt, buildEvalRunSummary, buildFromCompactPrompt, buildFullCompactPrompt, buildPersistedStub, buildPostCompactAttachments, buildRegisteredEvals, buildTailCompactPrompt, buildTrajectory, buildUpToCompactPrompt, cerebras, classifyOpenAICompatError, cleanupPersistedSession, clearRegisteredEvals, compactConversation, computeEvalTagScores, connectMcpServers, consoleSink, createAgent, createEvalAgent, createEvalRunReporter, createFileMapStore, createInteractionTool, createLogger, createLoggingHooks, createMemoryMcpCredentialStore, createMemoryStore, createMetricsHooks, createProcessContext, createRemoteStore, createReusableExecutionContext, createRunSummaryCollector, createSandboxContext, createSession, createShellTool, createSkillActivationState, createSkillsReadTool, createSkillsRunScriptTool, createSkillsUseTool, createSpawnTool, createTracingHooks, defaultRepeatGuardNormalize, defaultRepeatGuardTracked, defineEval, defineMetrics, definePreset, defineSkill, detectTurnInterruption, diffCacheDimensions, discoverSkills, edit, effectiveContextWindow, efficiencyMetricValues, emitEfficiencyMetrics, ensureEndsWithUserMessage, ensureReadStateHydratedOnce, ensureToolResultPairing, errorMessage, estimateTokens, fileContains, fileContentQuality, fileExists, fileExistsOneOf, filterUnresolvedToolUses, finalizeEvalMetrics, flattenTurns, fnv1a32, formatEvalCaseSummary, formatEvalRunSummary, formatTrajectoryLine, fromAnthropic, fromOpenAI, functionalityMetric, getReadState, glob, grep, hasAuthorizationHeader, hasSystemPromptBoundary, hashContent, headlessEventToJsonl, hydrateReadStateFromSession, hydrateReadStateFromSessionAsync, installAllowedToolsGate, installCacheBreakLogger, interpolateShellCommands, isToolAllowedByUnion, joinSystemPrompt, jsonSink, llmJudge, loadSession, local, loginMcpServer, mapOAIFinishReason, matchesAllowedTool, matchesContextExceeded, maybePersistToolResult, multiEdit, normalizeMcpBlocks, normalizeMcpServers, normalizeMetric, normalizeShellCommand, openai, openaiCompat, openrouter, parseAllowedToolPattern, parseSkillFile, readStateKey, registerEvalTests, relativeArtifactPath, remintDuplicateToolCallIds, renderSystemForWire, replaceDynamicSection, resolveDetachedTasksCapability, resolvePersistDir, resolveReadStateMap, resolveSkills, resolveTasksDir, resultToString, runEvalCase, runHeadless, sanitizeToolSchema, sanitizeToolSpecs, selectFilesFromReadState, selectFilesFromSession, selectRecentFiles, shouldAutoCompact, sliceForCompaction, snapshotCacheDimensions, splitSystemPrompt, stableStringify, startOAuthCallback, statsByModel, statusCompleted, stripImagesFromTurns, stripShellInterpolations, summaryToTurn, toAnthropic, toOpenAI, toTypedError, toWireMessages, toolOutputBudgetByteLength, toolOutputByteLength, toolResultToText, transcriptToOpenAIMessages, truncateHeadForPtlRetry, utf8ByteLength, validateResourcePath, validateResourcePathReal, validateSkillForWrite, validateSkillName, validateToolArgs, waitTask, writeSkillToDisk, writeSkillsToDisk, xai, zodToJsonSchema };
1270
+ export { ANCHOR_PREVIEW_MAX_CHARS, AUTO_COMPACT_MIN_GROWTH_FRACTION, AgentAbortedError, AgentBudgetExceededError, AgentContextExceededError, AgentProviderError, AgentToolNotAllowedError, AgentToolPairingError, BASE_INSTRUCTIONS, BYTES_PER_TOKEN, CONTEXT_EXCEEDED_MESSAGE_PATTERNS, CompactInvalidInputError, CompactPromptTooLongError, EFFICIENCY_METRICS, EvalMetricError, GEN_AI_ATTRIBUTES, IMPLICITLY_ALLOWED_SKILL_TOOLS, INTERRUPT_MESSAGE_FOR_TOOL_USE, McpOAuthProvider, NO_TOOLS_PREAMBLE, ORPHANED_TOOL_RESULT_MARKER, OUTPUT_RESERVE_TOKENS, OpenAICompatHttpError, OperationTimeoutError, PERSISTED_STUB_PREFIX, PERSISTENCE_PREVIEW_BYTES, SHELL_CASCADE_CANCEL_MESSAGE, SYNTHETIC_TOOL_RESULT_PLACEHOLDER, SYSTEM_PROMPT_BOUNDARY, TOOL_USE_CANCELLED_MESSAGE, TOOL_USE_INTERRUPTED_MARKER, TOOL_USE_SKIPPED_MESSAGE, TRAILER, anchorPreviewFor, anthropic, appendDynamicSection, appendStaticSection, applyAnthropicCacheBreakpoints, arcee, artifactPath, autoDetectAndConvert, baseten, basic_default as basic, basicTools, buildCatalog, buildCompactPrompt, buildEvalRunSummary, buildFromCompactPrompt, buildFullCompactPrompt, buildPersistedStub, buildPostCompactAttachments, buildRegisteredEvals, buildTailCompactPrompt, buildTrajectory, buildUpToCompactPrompt, cerebras, classifyOpenAICompatError, cleanupPersistedSession, clearRegisteredEvals, compactConversation, computeEvalTagScores, connectMcpServers, consoleSink, createAgent, createEvalAgent, createEvalRunReporter, createFileMapStore, createInteractionTool, createLogger, createLoggingHooks, createMemoryMcpCredentialStore, createMemoryStore, createMetricsHooks, createProcessContext, createRemoteStore, createReusableExecutionContext, createRunSummaryCollector, createSandboxContext, createSession, createShellTool, createSkillActivationState, createSkillsReadTool, createSkillsRunScriptTool, createSkillsUseTool, createSpawnTool, createTracingHooks, defaultRepeatGuardNormalize, defaultRepeatGuardTracked, defineEval, defineMetrics, definePreset, defineSkill, detectTurnInterruption, diffCacheDimensions, discoverSkills, edit, effectiveContextWindow, efficiencyMetricValues, emitEfficiencyMetrics, ensureEndsWithUserMessage, ensureToolResultPairing, errorMessage, estimateTokens, fileContains, fileContentQuality, fileExists, fileExistsOneOf, filterUnresolvedToolUses, finalizeEvalMetrics, flattenTurns, fnv1a32, formatEvalCaseSummary, formatEvalRunSummary, formatTrajectoryLine, fromAnthropic, fromOpenAI, functionalityMetric, getReadState, glob, grep, hasAuthorizationHeader, hasSystemPromptBoundary, hashContent, headlessEventToJsonl, hydrateReadStateFromSession, hydrateReadStateFromSessionAsync, installAllowedToolsGate, installCacheBreakLogger, interpolateShellCommands, isToolAllowedByUnion, joinSystemPrompt, jsonSink, llmJudge, loadSession, local, loginMcpServer, mapOAIFinishReason, matchesAllowedTool, matchesContextExceeded, maybePersistToolResult, multiEdit, normalizeMcpBlocks, normalizeMcpServers, normalizeMetric, normalizeShellCommand, openai, openaiCompat, openrouter, parseAllowedToolPattern, parseSkillFile, readStateKey, registerEvalTests, relativeArtifactPath, remintDuplicateToolCallIds, renderSystemForWire, replaceDynamicSection, resolveDetachedTasksCapability, resolvePersistDir, resolveReadStateMap, resolveSkills, resolveTasksDir, resultToString, runEvalCase, runHeadless, sanitizeToolSchema, sanitizeToolSpecs, selectFilesFromReadState, selectFilesFromSession, selectRecentFiles, shouldAutoCompact, sliceForCompaction, snapshotCacheDimensions, splitSystemPrompt, stableStringify, startOAuthCallback, statsByModel, statusCompleted, stripImagesFromTurns, stripShellInterpolations, summaryToTurn, toAnthropic, toOpenAI, toTypedError, toWireMessages, toolOutputBudgetByteLength, toolOutputByteLength, toolResultToText, transcriptToOpenAIMessages, truncateHeadForPtlRetry, utf8ByteLength, validateResourcePath, validateResourcePathReal, validateSkillForWrite, validateSkillName, validateToolArgs, waitTask, writeSkillToDisk, writeSkillsToDisk, xai, zodToJsonSchema };
1271
1271
 
1272
1272
  //# sourceMappingURL=index.js.map
@@ -1,4 +1,4 @@
1
- import { r as AgentHooks } from "./agent-B_jcbRS1.js";
1
+ import { r as AgentHooks } from "./agent-DQIL5BFk.js";
2
2
  import { Hookable } from "hookable";
3
3
 
4
4
  //#region src/logger.d.ts
@@ -99,4 +99,4 @@ interface LoggingHookSet {
99
99
  declare function createLoggingHooks(options: LoggingHooksOptions): LoggingHookSet;
100
100
  //#endregion
101
101
  export { Logger as a, consoleSink as c, jsonSink as d, LogSink as i, createLogger as l, LogLevel as n, LoggingHookSet as o, LogRecord as r, LoggingHooksOptions as s, ConsoleSinkOptions as t, createLoggingHooks as u };
102
- //# sourceMappingURL=logger-SE8Qb62V.d.ts.map
102
+ //# sourceMappingURL=logger-C2ngE8CY.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"logger-SE8Qb62V.d.ts","names":[],"sources":["../src/logger.ts"],"mappings":";;;;KAgCY,QAAA;AAAA,UAEK,SAAA;EACf,KAAA,EAAO,QAAA;EAUiB;EARxB,SAAA;EAWqB;EATrB,OAAA;EAUiC;EARjC,KAAA,EAAO,MAAM;AAAA;AAAA,UAGE,OAAA;EACf,IAAA,GAAO,MAAA,EAAQ,SAAS;AAAA;AAAA,UAGT,MAAA;EACf,KAAA,GAAQ,OAAA,UAAiB,KAAA,GAAQ,MAAA;EACjC,IAAA,GAAO,OAAA,UAAiB,KAAA,GAAQ,MAAA;EAChC,IAAA,GAAO,OAAA,UAAiB,KAAA,GAAQ,MAAA;EAChC,KAAA,GAAQ,OAAA,UAAiB,KAAA,GAAQ,MAAA;EAHzB;;;;;EASR,IAAA,GAAO,KAAA,EAAO,MAAA,sBAA4B,MAAA;EARlB;;;;EAAA,SAaf,cAAA,EAAgB,QAAA,CAAS,MAAA;AAAA;;;;;iBAWpB,YAAA,CACd,IAAA,EAAM,OAAA,EACN,cAAA,GAAgB,QAAA,CAAS,MAAA,qBACxB,MAAA;AAAA,UA6Bc,kBAAA;EAhD2B;;;;;EAsD1C,QAAA,GAAW,QAAQ;EAtCL;EAwCd,MAAA;IAAW,KAAA,GAAQ,KAAA;EAAA;AAAA;;;;;;;;iBAiBL,WAAA,CAAY,OAAA,GAAS,kBAAA,GAA0B,OAAO;;;;AAtD7D;iBA2EO,QAAA,CAAS,OAAA,GAAS,kBAAA,GAA0B,OAAO;AAAA,UAqBlD,mBAAA;EACf,MAAA,EAAQ,MAAA;EA9DW;;;;;EAoEnB,KAAA,GAAQ,QAAQ;EAlEgB;AAAA;AAiBlC;;;;;EAyDE,gBAAA;AAAA;AAAA,UAGe,cAAA;EACf,OAAA,GAAU,KAAA,EAAO,QAAQ,CAAC,UAAA;AAAA;;;;;;;;AAxCuC;AAqBnE;;;;;;iBAoCgB,kBAAA,CAAmB,OAAA,EAAS,mBAAA,GAAsB,cAAc"}
1
+ {"version":3,"file":"logger-C2ngE8CY.d.ts","names":[],"sources":["../src/logger.ts"],"mappings":";;;;KAgCY,QAAA;AAAA,UAEK,SAAA;EACf,KAAA,EAAO,QAAA;EAUiB;EARxB,SAAA;EAWqB;EATrB,OAAA;EAUiC;EARjC,KAAA,EAAO,MAAM;AAAA;AAAA,UAGE,OAAA;EACf,IAAA,GAAO,MAAA,EAAQ,SAAS;AAAA;AAAA,UAGT,MAAA;EACf,KAAA,GAAQ,OAAA,UAAiB,KAAA,GAAQ,MAAA;EACjC,IAAA,GAAO,OAAA,UAAiB,KAAA,GAAQ,MAAA;EAChC,IAAA,GAAO,OAAA,UAAiB,KAAA,GAAQ,MAAA;EAChC,KAAA,GAAQ,OAAA,UAAiB,KAAA,GAAQ,MAAA;EAHzB;;;;;EASR,IAAA,GAAO,KAAA,EAAO,MAAA,sBAA4B,MAAA;EARlB;;;;EAAA,SAaf,cAAA,EAAgB,QAAA,CAAS,MAAA;AAAA;;;;;iBAWpB,YAAA,CACd,IAAA,EAAM,OAAA,EACN,cAAA,GAAgB,QAAA,CAAS,MAAA,qBACxB,MAAA;AAAA,UA6Bc,kBAAA;EAhD2B;;;;;EAsD1C,QAAA,GAAW,QAAQ;EAtCL;EAwCd,MAAA;IAAW,KAAA,GAAQ,KAAA;EAAA;AAAA;;;;;;;;iBAiBL,WAAA,CAAY,OAAA,GAAS,kBAAA,GAA0B,OAAO;;;;AAtD7D;iBA2EO,QAAA,CAAS,OAAA,GAAS,kBAAA,GAA0B,OAAO;AAAA,UAqBlD,mBAAA;EACf,MAAA,EAAQ,MAAA;EA9DW;;;;;EAoEnB,KAAA,GAAQ,QAAQ;EAlEgB;AAAA;AAiBlC;;;;;EAyDE,gBAAA;AAAA;AAAA,UAGe,cAAA;EACf,OAAA,GAAU,KAAA,EAAO,QAAQ,CAAC,UAAA;AAAA;;;;;;;;AAxCuC;AAqBnE;;;;;;iBAoCgB,kBAAA,CAAmB,OAAA,EAAS,mBAAA,GAAsB,cAAc"}
package/dist/mcp.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- import { C as wrapDiscoveredMcpTools, Cn as McpServerConfig, S as resultToString, Tn as McpToolSchema, _ as attachStderrWarnPump, b as normalizeMcpBlocks, g as McpConnection, h as ConnectMcpServersOptions, v as connectMcpServers, x as normalizeMcpServers, y as deriveMcpToolMeta } from "./agent-B_jcbRS1.js";
1
+ import { C as wrapDiscoveredMcpTools, S as resultToString, Sn as McpServerConfig, _ as attachStderrWarnPump, b as normalizeMcpBlocks, g as McpConnection, h as ConnectMcpServersOptions, v as connectMcpServers, wn as McpToolSchema, x as normalizeMcpServers, y as deriveMcpToolMeta } from "./agent-DQIL5BFk.js";
2
2
  export { ConnectMcpServersOptions, McpConnection, type McpServerConfig, type McpToolSchema, attachStderrWarnPump, connectMcpServers, deriveMcpToolMeta, normalizeMcpBlocks, normalizeMcpServers, resultToString, wrapDiscoveredMcpTools };
@@ -1,5 +1,5 @@
1
- import { t as Agent } from "../agent-B_jcbRS1.js";
2
- import { Dn as FormattedHeadlessTurnEvent, En as FormattedHeadlessResult, Mn as HeadlessResult, jn as HeadlessOutputFormat, kn as HeadlessEvent } from "../index-B9tOi27d.js";
1
+ import { t as Agent } from "../agent-DQIL5BFk.js";
2
+ import { Dn as FormattedHeadlessTurnEvent, En as FormattedHeadlessResult, Mn as HeadlessResult, jn as HeadlessOutputFormat, kn as HeadlessEvent } from "../index-YY3vp2F2.js";
3
3
 
4
4
  //#region src/output/stream-json.d.ts
5
5
  type StreamJsonOutputFormat = HeadlessOutputFormat;
@@ -1,4 +1,4 @@
1
- import { i as formattedHeadlessTurnEventToJsonl, n as formatHeadlessResult, o as installHeadlessEventAdapter, r as formatHeadlessTurnEvent } from "../headless-XTYJhHcn.js";
1
+ import { i as formattedHeadlessTurnEventToJsonl, n as formatHeadlessResult, o as installHeadlessEventAdapter, r as formatHeadlessTurnEvent } from "../headless-Dk5JvNjb.js";
2
2
  //#region src/output/stream-json.ts
3
3
  function resolveFormatOptions(options) {
4
4
  return {
@@ -1,5 +1,5 @@
1
- import { r as AgentHooks, t as Agent } from "../agent-B_jcbRS1.js";
2
- import { t as Preset } from "../index-B9tOi27d.js";
1
+ import { r as AgentHooks, t as Agent } from "../agent-DQIL5BFk.js";
2
+ import { t as Preset } from "../index-YY3vp2F2.js";
3
3
 
4
4
  //#region src/output/terminal.d.ts
5
5
  interface TerminalOutputOptions {
@@ -1,4 +1,4 @@
1
- import { a as multiEdit, i as readFile, n as createSpawnTool, o as listFiles, p as waitTask, r as shellKill, t as writeFile, u as edit, y as shell } from "./tools-DcUatsZX.js";
1
+ import { a as multiEdit, i as readFile, n as createSpawnTool, o as listFiles, p as waitTask, r as shellKill, t as writeFile, u as edit, y as shell } from "./tools-C4mCSY-v.js";
2
2
  //#region src/presets/basic.ts
3
3
  /**
4
4
  * Core tools available in every basic preset (without spawn).
@@ -110,4 +110,4 @@ function composePresets(...presets) {
110
110
  //#endregion
111
111
  export { basic_default as i, definePreset as n, basicTools as r, composePresets as t };
112
112
 
113
- //# sourceMappingURL=presets-4bHMTjG3.js.map
113
+ //# sourceMappingURL=presets-BVUwZhtJ.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"presets-4bHMTjG3.js","names":[],"sources":["../src/presets/basic.ts","../src/presets/index.ts"],"sourcesContent":["import { definePreset } from '.'\nimport { edit, listFiles, multiEdit, readFile, shell, shellKill, waitTask, writeFile } from '../tools'\nimport { createSpawnTool } from '../tools/spawn'\n\n/**\n * Core tools available in every basic preset (without spawn).\n *\n * `edit` and `multi_edit` ship in the basic set because surgical edits are the\n * default modality for production agents — `write_file` is for full overwrites.\n * `glob` and `grep` are exported but opt-in: not every agent needs codebase\n * search, and shipping them by default would force `tool:gate` work onto\n * consumers that prefer the model to use `shell` + classic Unix tools.\n */\nexport const basicTools = { shell, shellKill, waitTask, readFile, writeFile, listFiles, edit, multiEdit }\n\nexport default definePreset({\n name: 'basic',\n system: 'You are a helpful assistant with access to shell, file reading, file writing, surgical and multi-edit tools, directory listing, and sub-agent spawning. Prefer `edit` / `multi_edit` for in-place changes and `write_file` for full file overwrites. Use them to accomplish tasks in the project directory.',\n // `tools` is a getter so each access (every `{ ...basic }` spread into\n // `createAgent`) mints a FRESH spawn tool. `createSpawnTool()` carries\n // per-instance state (running children, concurrency counter, child-stats\n // accumulator); a module-level singleton instance would be shared by every\n // agent in the process, breaking concurrent rollouts.\n //\n // `persist: true` shares the parent's session with every child agent — child\n // turns land in `session.turns` tagged with their own `runId`, and the run\n // itself is recorded in `session.runs` with `parentRunId` + `depth`. That's\n // what lets a reloaded TUI session reconstruct the full subagent tree (see\n // `eventsFromTurns` in `tui/store.ts`). Hosts that want children in-memory\n // only can construct their own preset with `createSpawnTool()`.\n get tools() {\n return { ...basicTools, spawn: createSpawnTool({ persist: true }) }\n },\n})\n","import type { AgentHooks, AgentOptions } from '../agent'\n\nexport type { AgentHookMap } from '../agent'\n\n/**\n * A preset is a reusable slice of `AgentOptions` — spread it into `createAgent()`\n * to configure tools, a default system prompt, aliases, behavior defaults, and\n * agent-lifetime hooks.\n *\n * `provider`, `execution`, `session`, and `mcpConnector` are excluded — they're\n * ambient / per-invocation runtime wiring (a custom `mcpConnector` is the MCP\n * connection seam, often closure-bound to a transport / auth provider), so\n * presets stay shareable and composable.\n *\n * ```ts\n * import { basic } from 'zidane/presets'\n * createAgent({ ...basic, provider })\n * ```\n *\n * ### Composing multiple presets\n *\n * Bare `...spread` is shallow — `{ ...a, ...b }` overwrites every key `b`\n * defines, including `hooks`. Use {@link composePresets} when you want\n * field-aware merging (per-event hook concat, tools shallow-merge, etc.):\n *\n * ```ts\n * createAgent({ ...composePresets(basic, telemetry, mine), provider })\n * ```\n */\nexport type Preset = Omit<Partial<AgentOptions>, 'provider' | 'execution' | 'session' | 'mcpConnector'>\n\n/**\n * Identity helper for type inference when defining a preset.\n */\nexport function definePreset(config: Preset): Preset {\n return config\n}\n\n/**\n * Field-aware composition of presets. Right-most preset wins for scalar fields;\n * objects shallow-merge; arrays and hook handler lists concatenate. Designed so\n * stacking presets does the obvious thing without the spread-collision footgun:\n *\n * - `name`, `system`, `eager`, `skills` → last-defined wins\n * - `tools`, `toolAliases`, `behavior` → shallow-merge (later keys override)\n * - `behavior.dedupTools`, `behavior.toolBudgets` → **deep-merge** (per-tool-name; later wins on collision)\n * - `mcpServers` → concat with last-wins on `name` collision\n * - `hooks` → per-event concat; every handler fires\n *\n * `hooks` always emerges as `event → handler[]` so downstream registration\n * (in `createAgent`) sees a uniform shape. Order of handlers within an event\n * follows preset order: earlier presets register first.\n *\n * `mcpServers` is deduped by `name` because shipping two servers with the same\n * name would trip the connector at runtime — a later preset overriding an\n * earlier preset's `github` server is the practical intent.\n *\n * `behavior.dedupTools` and `behavior.toolBudgets` get the same per-key deep-merge\n * because they are tool-name-keyed records — a preset that ships a dedup hasher\n * for one tool should not erase a hasher another preset ships for a different\n * tool. Last-wins still applies on a per-tool collision so a downstream preset\n * can override an upstream preset's policy for one specific tool. Other\n * `behavior` fields keep last-wins semantics.\n */\nexport function composePresets(...presets: Preset[]): Preset {\n const out: Preset = {}\n const hooksByEvent: { [K in keyof AgentHooks]?: AgentHooks[K][] } = {}\n // Keep mcpServers in source-order on first sight, but allow later\n // declarations to override earlier ones with the same `name`. A `Map`\n // keyed by name gives O(1) override + stable iteration.\n const mcpByName = new Map<string, NonNullable<Preset['mcpServers']>[number]>()\n\n for (const p of presets) {\n if (p.name !== undefined)\n out.name = p.name\n if (p.system !== undefined)\n out.system = p.system\n if (p.eager !== undefined)\n out.eager = p.eager\n if (p.skills !== undefined)\n out.skills = p.skills\n if (p.tools)\n out.tools = { ...out.tools, ...p.tools }\n if (p.toolAliases)\n out.toolAliases = { ...out.toolAliases, ...p.toolAliases }\n if (p.behavior) {\n // Top-level shallow-merge first; then deep-merge the two tool-name-keyed\n // sub-records so per-tool entries from earlier presets aren't clobbered.\n const merged: NonNullable<Preset['behavior']> = { ...out.behavior, ...p.behavior }\n if (out.behavior?.dedupTools || p.behavior.dedupTools) {\n merged.dedupTools = { ...out.behavior?.dedupTools, ...p.behavior.dedupTools }\n }\n if (out.behavior?.toolBudgets || p.behavior.toolBudgets) {\n merged.toolBudgets = { ...out.behavior?.toolBudgets, ...p.behavior.toolBudgets }\n }\n out.behavior = merged\n }\n if (p.mcpServers) {\n for (const server of p.mcpServers)\n mcpByName.set(server.name, server)\n }\n if (p.hooks) {\n for (const [event, handler] of Object.entries(p.hooks)) {\n if (handler === undefined)\n continue\n const list = Array.isArray(handler) ? handler : [handler]\n const key = event as keyof AgentHooks\n // Safe cast: we read the loose `AgentHookMap` shape (handler-or-array)\n // and re-emit only as arrays. Each `list` element matches the event's\n // handler signature by construction (the input was typed `AgentHookMap`).\n const bucket = (hooksByEvent[key] ??= []) as unknown[]\n bucket.push(...(list as unknown[]))\n }\n }\n }\n\n if (mcpByName.size > 0)\n out.mcpServers = [...mcpByName.values()]\n\n if (Object.keys(hooksByEvent).length > 0)\n out.hooks = hooksByEvent\n\n return out\n}\n\nexport { default as basic, basicTools } from './basic'\n"],"mappings":";;;;;;;;;;;AAaA,MAAa,aAAa;CAAE;CAAO;CAAW;CAAU;CAAU;CAAW;CAAW;CAAM;AAAU;AAExG,IAAA,gBAAe,aAAa;CAC1B,MAAM;CACN,QAAQ;CAaR,IAAI,QAAQ;EACV,OAAO;GAAE,GAAG;GAAY,OAAO,gBAAgB,EAAE,SAAS,KAAK,CAAC;EAAE;CACpE;AACF,CAAC;;;;;;ACCD,SAAgB,aAAa,QAAwB;CACnD,OAAO;AACT;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4BA,SAAgB,eAAe,GAAG,SAA2B;CAC3D,MAAM,MAAc,CAAC;CACrB,MAAM,eAA8D,CAAC;CAIrE,MAAM,4BAAY,IAAI,IAAuD;CAE7E,KAAK,MAAM,KAAK,SAAS;EACvB,IAAI,EAAE,SAAS,KAAA,GACb,IAAI,OAAO,EAAE;EACf,IAAI,EAAE,WAAW,KAAA,GACf,IAAI,SAAS,EAAE;EACjB,IAAI,EAAE,UAAU,KAAA,GACd,IAAI,QAAQ,EAAE;EAChB,IAAI,EAAE,WAAW,KAAA,GACf,IAAI,SAAS,EAAE;EACjB,IAAI,EAAE,OACJ,IAAI,QAAQ;GAAE,GAAG,IAAI;GAAO,GAAG,EAAE;EAAM;EACzC,IAAI,EAAE,aACJ,IAAI,cAAc;GAAE,GAAG,IAAI;GAAa,GAAG,EAAE;EAAY;EAC3D,IAAI,EAAE,UAAU;GAGd,MAAM,SAA0C;IAAE,GAAG,IAAI;IAAU,GAAG,EAAE;GAAS;GACjF,IAAI,IAAI,UAAU,cAAc,EAAE,SAAS,YACzC,OAAO,aAAa;IAAE,GAAG,IAAI,UAAU;IAAY,GAAG,EAAE,SAAS;GAAW;GAE9E,IAAI,IAAI,UAAU,eAAe,EAAE,SAAS,aAC1C,OAAO,cAAc;IAAE,GAAG,IAAI,UAAU;IAAa,GAAG,EAAE,SAAS;GAAY;GAEjF,IAAI,WAAW;EACjB;EACA,IAAI,EAAE,YACJ,KAAK,MAAM,UAAU,EAAE,YACrB,UAAU,IAAI,OAAO,MAAM,MAAM;EAErC,IAAI,EAAE,OACJ,KAAK,MAAM,CAAC,OAAO,YAAY,OAAO,QAAQ,EAAE,KAAK,GAAG;GACtD,IAAI,YAAY,KAAA,GACd;GACF,MAAM,OAAO,MAAM,QAAQ,OAAO,IAAI,UAAU,CAAC,OAAO;GACxD,MAAM,MAAM;GAKZ,CADgB,aAAa,SAAS,CAAC,GAChC,KAAK,GAAI,IAAkB;EACpC;CAEJ;CAEA,IAAI,UAAU,OAAO,GACnB,IAAI,aAAa,CAAC,GAAG,UAAU,OAAO,CAAC;CAEzC,IAAI,OAAO,KAAK,YAAY,EAAE,SAAS,GACrC,IAAI,QAAQ;CAEd,OAAO;AACT"}
1
+ {"version":3,"file":"presets-BVUwZhtJ.js","names":[],"sources":["../src/presets/basic.ts","../src/presets/index.ts"],"sourcesContent":["import { definePreset } from '.'\nimport { edit, listFiles, multiEdit, readFile, shell, shellKill, waitTask, writeFile } from '../tools'\nimport { createSpawnTool } from '../tools/spawn'\n\n/**\n * Core tools available in every basic preset (without spawn).\n *\n * `edit` and `multi_edit` ship in the basic set because surgical edits are the\n * default modality for production agents — `write_file` is for full overwrites.\n * `glob` and `grep` are exported but opt-in: not every agent needs codebase\n * search, and shipping them by default would force `tool:gate` work onto\n * consumers that prefer the model to use `shell` + classic Unix tools.\n */\nexport const basicTools = { shell, shellKill, waitTask, readFile, writeFile, listFiles, edit, multiEdit }\n\nexport default definePreset({\n name: 'basic',\n system: 'You are a helpful assistant with access to shell, file reading, file writing, surgical and multi-edit tools, directory listing, and sub-agent spawning. Prefer `edit` / `multi_edit` for in-place changes and `write_file` for full file overwrites. Use them to accomplish tasks in the project directory.',\n // `tools` is a getter so each access (every `{ ...basic }` spread into\n // `createAgent`) mints a FRESH spawn tool. `createSpawnTool()` carries\n // per-instance state (running children, concurrency counter, child-stats\n // accumulator); a module-level singleton instance would be shared by every\n // agent in the process, breaking concurrent rollouts.\n //\n // `persist: true` shares the parent's session with every child agent — child\n // turns land in `session.turns` tagged with their own `runId`, and the run\n // itself is recorded in `session.runs` with `parentRunId` + `depth`. That's\n // what lets a reloaded TUI session reconstruct the full subagent tree (see\n // `eventsFromTurns` in `tui/store.ts`). Hosts that want children in-memory\n // only can construct their own preset with `createSpawnTool()`.\n get tools() {\n return { ...basicTools, spawn: createSpawnTool({ persist: true }) }\n },\n})\n","import type { AgentHooks, AgentOptions } from '../agent'\n\nexport type { AgentHookMap } from '../agent'\n\n/**\n * A preset is a reusable slice of `AgentOptions` — spread it into `createAgent()`\n * to configure tools, a default system prompt, aliases, behavior defaults, and\n * agent-lifetime hooks.\n *\n * `provider`, `execution`, `session`, and `mcpConnector` are excluded — they're\n * ambient / per-invocation runtime wiring (a custom `mcpConnector` is the MCP\n * connection seam, often closure-bound to a transport / auth provider), so\n * presets stay shareable and composable.\n *\n * ```ts\n * import { basic } from 'zidane/presets'\n * createAgent({ ...basic, provider })\n * ```\n *\n * ### Composing multiple presets\n *\n * Bare `...spread` is shallow — `{ ...a, ...b }` overwrites every key `b`\n * defines, including `hooks`. Use {@link composePresets} when you want\n * field-aware merging (per-event hook concat, tools shallow-merge, etc.):\n *\n * ```ts\n * createAgent({ ...composePresets(basic, telemetry, mine), provider })\n * ```\n */\nexport type Preset = Omit<Partial<AgentOptions>, 'provider' | 'execution' | 'session' | 'mcpConnector'>\n\n/**\n * Identity helper for type inference when defining a preset.\n */\nexport function definePreset(config: Preset): Preset {\n return config\n}\n\n/**\n * Field-aware composition of presets. Right-most preset wins for scalar fields;\n * objects shallow-merge; arrays and hook handler lists concatenate. Designed so\n * stacking presets does the obvious thing without the spread-collision footgun:\n *\n * - `name`, `system`, `eager`, `skills` → last-defined wins\n * - `tools`, `toolAliases`, `behavior` → shallow-merge (later keys override)\n * - `behavior.dedupTools`, `behavior.toolBudgets` → **deep-merge** (per-tool-name; later wins on collision)\n * - `mcpServers` → concat with last-wins on `name` collision\n * - `hooks` → per-event concat; every handler fires\n *\n * `hooks` always emerges as `event → handler[]` so downstream registration\n * (in `createAgent`) sees a uniform shape. Order of handlers within an event\n * follows preset order: earlier presets register first.\n *\n * `mcpServers` is deduped by `name` because shipping two servers with the same\n * name would trip the connector at runtime — a later preset overriding an\n * earlier preset's `github` server is the practical intent.\n *\n * `behavior.dedupTools` and `behavior.toolBudgets` get the same per-key deep-merge\n * because they are tool-name-keyed records — a preset that ships a dedup hasher\n * for one tool should not erase a hasher another preset ships for a different\n * tool. Last-wins still applies on a per-tool collision so a downstream preset\n * can override an upstream preset's policy for one specific tool. Other\n * `behavior` fields keep last-wins semantics.\n */\nexport function composePresets(...presets: Preset[]): Preset {\n const out: Preset = {}\n const hooksByEvent: { [K in keyof AgentHooks]?: AgentHooks[K][] } = {}\n // Keep mcpServers in source-order on first sight, but allow later\n // declarations to override earlier ones with the same `name`. A `Map`\n // keyed by name gives O(1) override + stable iteration.\n const mcpByName = new Map<string, NonNullable<Preset['mcpServers']>[number]>()\n\n for (const p of presets) {\n if (p.name !== undefined)\n out.name = p.name\n if (p.system !== undefined)\n out.system = p.system\n if (p.eager !== undefined)\n out.eager = p.eager\n if (p.skills !== undefined)\n out.skills = p.skills\n if (p.tools)\n out.tools = { ...out.tools, ...p.tools }\n if (p.toolAliases)\n out.toolAliases = { ...out.toolAliases, ...p.toolAliases }\n if (p.behavior) {\n // Top-level shallow-merge first; then deep-merge the two tool-name-keyed\n // sub-records so per-tool entries from earlier presets aren't clobbered.\n const merged: NonNullable<Preset['behavior']> = { ...out.behavior, ...p.behavior }\n if (out.behavior?.dedupTools || p.behavior.dedupTools) {\n merged.dedupTools = { ...out.behavior?.dedupTools, ...p.behavior.dedupTools }\n }\n if (out.behavior?.toolBudgets || p.behavior.toolBudgets) {\n merged.toolBudgets = { ...out.behavior?.toolBudgets, ...p.behavior.toolBudgets }\n }\n out.behavior = merged\n }\n if (p.mcpServers) {\n for (const server of p.mcpServers)\n mcpByName.set(server.name, server)\n }\n if (p.hooks) {\n for (const [event, handler] of Object.entries(p.hooks)) {\n if (handler === undefined)\n continue\n const list = Array.isArray(handler) ? handler : [handler]\n const key = event as keyof AgentHooks\n // Safe cast: we read the loose `AgentHookMap` shape (handler-or-array)\n // and re-emit only as arrays. Each `list` element matches the event's\n // handler signature by construction (the input was typed `AgentHookMap`).\n const bucket = (hooksByEvent[key] ??= []) as unknown[]\n bucket.push(...(list as unknown[]))\n }\n }\n }\n\n if (mcpByName.size > 0)\n out.mcpServers = [...mcpByName.values()]\n\n if (Object.keys(hooksByEvent).length > 0)\n out.hooks = hooksByEvent\n\n return out\n}\n\nexport { default as basic, basicTools } from './basic'\n"],"mappings":";;;;;;;;;;;AAaA,MAAa,aAAa;CAAE;CAAO;CAAW;CAAU;CAAU;CAAW;CAAW;CAAM;AAAU;AAExG,IAAA,gBAAe,aAAa;CAC1B,MAAM;CACN,QAAQ;CAaR,IAAI,QAAQ;EACV,OAAO;GAAE,GAAG;GAAY,OAAO,gBAAgB,EAAE,SAAS,KAAK,CAAC;EAAE;CACpE;AACF,CAAC;;;;;;ACCD,SAAgB,aAAa,QAAwB;CACnD,OAAO;AACT;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4BA,SAAgB,eAAe,GAAG,SAA2B;CAC3D,MAAM,MAAc,CAAC;CACrB,MAAM,eAA8D,CAAC;CAIrE,MAAM,4BAAY,IAAI,IAAuD;CAE7E,KAAK,MAAM,KAAK,SAAS;EACvB,IAAI,EAAE,SAAS,KAAA,GACb,IAAI,OAAO,EAAE;EACf,IAAI,EAAE,WAAW,KAAA,GACf,IAAI,SAAS,EAAE;EACjB,IAAI,EAAE,UAAU,KAAA,GACd,IAAI,QAAQ,EAAE;EAChB,IAAI,EAAE,WAAW,KAAA,GACf,IAAI,SAAS,EAAE;EACjB,IAAI,EAAE,OACJ,IAAI,QAAQ;GAAE,GAAG,IAAI;GAAO,GAAG,EAAE;EAAM;EACzC,IAAI,EAAE,aACJ,IAAI,cAAc;GAAE,GAAG,IAAI;GAAa,GAAG,EAAE;EAAY;EAC3D,IAAI,EAAE,UAAU;GAGd,MAAM,SAA0C;IAAE,GAAG,IAAI;IAAU,GAAG,EAAE;GAAS;GACjF,IAAI,IAAI,UAAU,cAAc,EAAE,SAAS,YACzC,OAAO,aAAa;IAAE,GAAG,IAAI,UAAU;IAAY,GAAG,EAAE,SAAS;GAAW;GAE9E,IAAI,IAAI,UAAU,eAAe,EAAE,SAAS,aAC1C,OAAO,cAAc;IAAE,GAAG,IAAI,UAAU;IAAa,GAAG,EAAE,SAAS;GAAY;GAEjF,IAAI,WAAW;EACjB;EACA,IAAI,EAAE,YACJ,KAAK,MAAM,UAAU,EAAE,YACrB,UAAU,IAAI,OAAO,MAAM,MAAM;EAErC,IAAI,EAAE,OACJ,KAAK,MAAM,CAAC,OAAO,YAAY,OAAO,QAAQ,EAAE,KAAK,GAAG;GACtD,IAAI,YAAY,KAAA,GACd;GACF,MAAM,OAAO,MAAM,QAAQ,OAAO,IAAI,UAAU,CAAC,OAAO;GACxD,MAAM,MAAM;GAKZ,CADgB,aAAa,SAAS,CAAC,GAChC,KAAK,GAAI,IAAkB;EACpC;CAEJ;CAEA,IAAI,UAAU,OAAO,GACnB,IAAI,aAAa,CAAC,GAAG,UAAU,OAAO,CAAC;CAEzC,IAAI,OAAO,KAAK,YAAY,EAAE,SAAS,GACrC,IAAI,QAAQ;CAEd,OAAO;AACT"}
package/dist/presets.d.ts CHANGED
@@ -1,3 +1,3 @@
1
- import { n as AgentHookMap } from "./agent-B_jcbRS1.js";
2
- import { a as basicTools, i as _default, n as composePresets, r as definePreset, t as Preset } from "./index-B9tOi27d.js";
1
+ import { n as AgentHookMap } from "./agent-DQIL5BFk.js";
2
+ import { a as basicTools, i as _default, n as composePresets, r as definePreset, t as Preset } from "./index-YY3vp2F2.js";
3
3
  export { type AgentHookMap, Preset, _default as basic, basicTools, composePresets, definePreset };
package/dist/presets.js CHANGED
@@ -1,2 +1,2 @@
1
- import { i as basic_default, n as definePreset, r as basicTools, t as composePresets } from "./presets-4bHMTjG3.js";
1
+ import { i as basic_default, n as definePreset, r as basicTools, t as composePresets } from "./presets-BVUwZhtJ.js";
2
2
  export { basic_default as basic, basicTools, composePresets, definePreset };
@@ -1,2 +1,2 @@
1
- import { $t as CerebrasParams, At as ToolSpec, Bt as openrouter, Ct as Provider, Dt as TokenCountPayload, Et as StreamOptions, Ft as SchemaSanitizeProfile, Gt as mapOAIFinishReason, Ht as OpenAICompatHttpError, It as SchemaSanitizeResult, Jt as openai, Kt as openaiCompat, Lt as sanitizeToolSchema, Mt as XaiParams, Nt as xai, Ot as ToolCall, Pt as SchemaSanitizeOptions, Qt as cursor, Rt as sanitizeToolSpecs, Tt as StreamCallbacks, Ut as OpenAICompatParams, Vt as OpenAICompatAuthHeader, Wt as classifyOpenAICompatError, Xt as local, Yt as LocalParams, Zt as CursorParams, an as arcee, cn as applyAnthropicCacheBreakpoints, en as cerebras, in as ArceeParams, jt as TurnResult, kt as ToolResult, nn as baseten, on as AnthropicParams, qt as OpenAIParams, rn as planBasetenReasoning, sn as anthropic, tn as BasetenParams, wt as ProviderCapabilities, zt as OpenRouterParams } from "./agent-B_jcbRS1.js";
1
+ import { $t as cerebras, At as TurnResult, Bt as OpenAICompatAuthHeader, Ct as ProviderCapabilities, Dt as ToolCall, Et as TokenCountPayload, Ft as SchemaSanitizeResult, Gt as openaiCompat, Ht as OpenAICompatParams, It as sanitizeToolSchema, Jt as LocalParams, Kt as OpenAIParams, Lt as sanitizeToolSpecs, Mt as xai, Nt as SchemaSanitizeOptions, Ot as ToolResult, Pt as SchemaSanitizeProfile, Qt as CerebrasParams, Rt as OpenRouterParams, St as Provider, Tt as StreamOptions, Ut as classifyOpenAICompatError, Vt as OpenAICompatHttpError, Wt as mapOAIFinishReason, Xt as CursorParams, Yt as local, Zt as cursor, an as AnthropicParams, en as BasetenParams, in as arcee, jt as XaiParams, kt as ToolSpec, nn as planBasetenReasoning, on as anthropic, qt as openai, rn as ArceeParams, sn as applyAnthropicCacheBreakpoints, tn as baseten, wt as StreamCallbacks, zt as openrouter } from "./agent-DQIL5BFk.js";
2
2
  export { type AnthropicParams, type ArceeParams, type BasetenParams, type CerebrasParams, type CursorParams, type LocalParams, type OpenAICompatAuthHeader, OpenAICompatHttpError, type OpenAICompatParams, type OpenAIParams, type OpenRouterParams, Provider, ProviderCapabilities, type SchemaSanitizeOptions, type SchemaSanitizeProfile, type SchemaSanitizeResult, StreamCallbacks, StreamOptions, TokenCountPayload, ToolCall, ToolResult, ToolSpec, TurnResult, type XaiParams, anthropic, applyAnthropicCacheBreakpoints, arcee, baseten, cerebras, classifyOpenAICompatError, cursor, local, mapOAIFinishReason, openai, openaiCompat, openrouter, planBasetenReasoning, sanitizeToolSchema, sanitizeToolSpecs, xai };
@@ -386,39 +386,6 @@ async function hydrateReadStateFromSessionAsync(session, cwd, options = {}) {
386
386
  }
387
387
  return hydrated;
388
388
  }
389
- /**
390
- * Module-level "already hydrated" guard, shared by every host that rebuilds
391
- * read-state from a persisted transcript (the agent's run-start pass and the
392
- * Restate tool wrapper alike). Keyed by `Session` identity: a host that
393
- * reloads a fresh `Session` object from a store on each resume (the common
394
- * store-backed pattern) hydrates that object exactly once, while a long-lived
395
- * in-process `Session` never re-scans its turns. WeakSet entries are GC'd
396
- * with the session, so this never leaks.
397
- */
398
- const HYDRATED_READ_STATE_SESSIONS = /* @__PURE__ */ new WeakSet();
399
- /**
400
- * Rebuild a session's read-state from its durable turns AT MOST ONCE.
401
- *
402
- * The read-state map lives in an in-memory `WeakMap<Session, …>` and is never
403
- * serialized with the session. So any host that reloads a `Session` from a
404
- * store on resume starts each run with an EMPTY map — and `requireReadBeforeEdit`
405
- * then rejects an `edit` on a file the model demonstrably read in an earlier
406
- * turn ("has not been read in this session"), degrading the model into
407
- * re-reading or falling back to `write_file` on every edit. This restores the
408
- * gate (and read dedup) across the resume boundary by replaying `session.turns`.
409
- *
410
- * Idempotent and cheap on a warm session: the WeakSet guard short-circuits
411
- * repeat calls. The guard is set BEFORE the await so concurrent first-tool
412
- * callers (Restate fans out concurrency-safe reads) don't double-scan.
413
- *
414
- * Returns the number of newly hydrated entries (`0` when already hydrated or
415
- * sessionless).
416
- */
417
- async function ensureReadStateHydratedOnce(session, cwd, options = {}) {
418
- if (!session || HYDRATED_READ_STATE_SESSIONS.has(session)) return 0;
419
- HYDRATED_READ_STATE_SESSIONS.add(session);
420
- return await hydrateReadStateFromSessionAsync(session, cwd, options);
421
- }
422
389
  function normalizeHydrateReadStateOptions(options) {
423
390
  return {
424
391
  readFileToolName: options.readFileToolName ?? "read_file",
@@ -631,6 +598,6 @@ function getToolDedupState(session) {
631
598
  return map;
632
599
  }
633
600
  //#endregion
634
- export { hydrateReadStateFromSession as a, readStateKey as c, buildAliasMaps as d, buildSanitizedWireAliases as f, toWireName as g, toCanonicalName as h, hashContent as i, resolveReadStateMap as l, rewriteMessagesToWire as m, getReadState as n, hydrateReadStateFromSessionAsync as o, rewriteContentToCanonical as p, getToolDedupState as r, markReadStateElided as s, ensureReadStateHydratedOnce as t, augmentMcpDoubleUnderscoreAliases as u };
601
+ export { hydrateReadStateFromSessionAsync as a, resolveReadStateMap as c, buildSanitizedWireAliases as d, rewriteContentToCanonical as f, toWireName as h, hydrateReadStateFromSession as i, augmentMcpDoubleUnderscoreAliases as l, toCanonicalName as m, getToolDedupState as n, markReadStateElided as o, rewriteMessagesToWire as p, hashContent as r, readStateKey as s, getReadState as t, buildAliasMaps as u };
635
602
 
636
- //# sourceMappingURL=read-state-B9O85Lel.js.map
603
+ //# sourceMappingURL=read-state-BymF41Jb.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"read-state-B9O85Lel.js","names":[],"sources":["../src/aliasing.ts","../src/tools/read-state.ts"],"sourcesContent":["/**\n * Tool-name aliasing helpers.\n *\n * Aliasing is applied at the LLM boundary only: the provider sees the aliased\n * name, but hooks and persisted turns use canonical names. See `AgentOptions.toolAliases`.\n */\n\nimport type { SessionContentBlock, SessionMessage } from './types'\nimport { fnv1aBase36 } from './hash'\n\n/** Forward + reverse lookup between canonical and aliased tool names */\nexport interface AliasMaps {\n /** canonical → alias (only entries where alias !== canonical) */\n aliasByCanonical: Map<string, string>\n /** alias → canonical (only entries where alias !== canonical) */\n canonicalByAlias: Map<string, string>\n}\n\n/**\n * Build alias lookup maps from a `toolAliases` record.\n *\n * Validates:\n * - No two canonical names map to the same alias (collision).\n * - No alias collides with another canonical tool name (would shadow).\n *\n * Silently ignores alias entries whose canonical name isn't in `canonicalNames` —\n * preset/agent authors can declare aliases for tools that may be added later via MCP.\n *\n * @param aliases - The `toolAliases` map from the agent options.\n * @param canonicalNames - All tool canonical names currently in scope (agent + MCP).\n */\nexport function buildAliasMaps(\n aliases: Record<string, string> | undefined,\n canonicalNames: Iterable<string>,\n): AliasMaps {\n const aliasByCanonical = new Map<string, string>()\n const canonicalByAlias = new Map<string, string>()\n\n if (!aliases) {\n return { aliasByCanonical, canonicalByAlias }\n }\n\n const canonicalSet = new Set(canonicalNames)\n\n // A canonical name is \"genuinely remapped\" when it has an alias entry that is\n // both non-empty and different from itself. Identity aliases or missing keys\n // mean the tool still answers to its canonical name on the wire.\n function isRemappedAway(canonical: string): boolean {\n const mapped = aliases![canonical]\n return typeof mapped === 'string' && mapped.length > 0 && mapped !== canonical\n }\n\n for (const [canonical, alias] of Object.entries(aliases)) {\n if (typeof alias !== 'string' || alias.length === 0)\n throw new Error(`Tool alias for \"${canonical}\" must be a non-empty string`)\n\n if (alias === canonical)\n continue\n\n if (!canonicalSet.has(canonical))\n continue\n\n // When the alias matches an existing canonical tool name, only allow it if\n // that other canonical is itself being remapped away (i.e. a name swap).\n // Otherwise the wire name would shadow a real tool.\n if (canonicalSet.has(alias) && !isRemappedAway(alias)) {\n throw new Error(`Tool alias \"${canonical}\" -> \"${alias}\" collides with an existing canonical tool name`)\n }\n\n const existingCanonical = canonicalByAlias.get(alias)\n if (existingCanonical && existingCanonical !== canonical) {\n throw new Error(\n `Tool alias collision: both \"${existingCanonical}\" and \"${canonical}\" map to alias \"${alias}\"`,\n )\n }\n\n aliasByCanonical.set(canonical, alias)\n canonicalByAlias.set(alias, canonical)\n }\n\n return { aliasByCanonical, canonicalByAlias }\n}\n\n/** Return the alias for a canonical name, falling back to the canonical name itself. */\nexport function toWireName(canonical: string, maps: AliasMaps): string {\n return maps.aliasByCanonical.get(canonical) ?? canonical\n}\n\n/** Return the canonical name for a wire name, falling back to the wire name itself. */\nexport function toCanonicalName(wire: string, maps: AliasMaps): string {\n return maps.canonicalByAlias.get(wire) ?? wire\n}\n\n/**\n * Tool names must match `^[a-zA-Z0-9_-]{1,N}$`. The charset is universal; the\n * length cap is taken as the STRICTEST across providers (OpenAI/-compat: 64;\n * Anthropic allows 128) so a sanitized name is valid on EVERY provider — and so\n * a mid-session model switch can never make the provider-level drop guard\n * (`sanitizeToolSpecs`) discard a tool we could have kept.\n *\n * MCP tool names are minted verbatim as `mcp_<server>_<tool>` (see\n * `connectMcpServers`), so a server configured as `SSH Ipseity` yields\n * `mcp_SSH Ipseity_exec` — the space (and `.`/`:`/`/`, unicode, or a >64-char\n * join) 400s the request the instant that tool lands in the `tools` array:\n * `tools.N.custom.name: String should match pattern ...`.\n */\nconst WIRE_NAME_MAX = 64\nconst WIRE_NAME_OK = /^[\\w-]{1,64}$/\nconst WIRE_NAME_BAD_CHAR = /[^\\w-]/g\n\n/**\n * Build OUTBOUND wire aliases that coerce any tool name violating the provider\n * name constraint into a valid one. Only offenders get an entry; clean setups\n * return `undefined` (no alias map churn, prompt cache untouched).\n *\n * Returned as a `Record` so it merges into `effectiveToolAliases` upstream of\n * BOTH wire-name computations — the `tool_search` catalog and the `tools` array\n * — keeping them in lockstep. Canonical names (dispatch, hooks, persisted\n * turns) never change; only the bytes the model sees do.\n *\n * Scoped to MCP names (the only third-party-controlled, thus only realistically\n * invalid, source). The hash suffix keeps distinct originals distinct even when\n * they collapse to the same replacement; `taken` guards the residual collision.\n */\nexport function buildSanitizedWireAliases(\n names: Iterable<string>,\n existing: Record<string, string> | undefined,\n): Record<string, string> | undefined {\n const wireOf = (name: string): string => {\n const alias = existing?.[name]\n return typeof alias === 'string' && alias.length > 0 ? alias : name\n }\n\n // Already-valid wire names stay occupied so a freshly minted one can never\n // shadow another tool.\n const taken = new Set<string>()\n const offenders: string[] = []\n for (const name of names) {\n const wire = wireOf(name)\n if (WIRE_NAME_OK.test(wire))\n taken.add(wire)\n else\n offenders.push(name)\n }\n if (offenders.length === 0)\n return undefined\n\n const out: Record<string, string> = {}\n for (const name of offenders) {\n const sanitized = sanitizeWireName(wireOf(name), taken)\n out[name] = sanitized\n taken.add(sanitized)\n }\n return out\n}\n\nfunction sanitizeWireName(name: string, taken: ReadonlySet<string>): string {\n let base = name.replace(WIRE_NAME_BAD_CHAR, '_')\n if (base.length === 0)\n base = 'tool'\n // Hash the ORIGINAL so `a.b` vs `a/b` (both → `a_b`) and truncated long\n // names stay distinct and deterministic across runs.\n const hash = fnv1aBase36(name)\n const withSuffix = (suffix: string): string =>\n `${base.slice(0, Math.max(1, WIRE_NAME_MAX - suffix.length))}${suffix}`\n let candidate = withSuffix(`_${hash}`)\n for (let n = 1; taken.has(candidate); n++)\n candidate = withSuffix(`_${hash}_${n}`)\n return candidate\n}\n\n/**\n * Augment {@link AliasMaps} with INBOUND-ONLY aliases for the Claude Code\n * `mcp__server__tool` double-underscore naming convention. For every MCP\n * tool registered with the canonical `mcp_<server>_<tool>` form, add a\n * `canonicalByAlias` entry mapping the double-underscore variant to the\n * same canonical name. Outbound (`aliasByCanonical`) is left untouched —\n * the model still sees the single-underscore canonical on the wire, so\n * the tools-array byte count (and the provider prompt cache) is\n * unaffected.\n *\n * Why: SDK consumers and tool descriptions across the ecosystem\n * inconsistently reference one form or the other (Anthropic's docs use\n * double, zidane uses single). A Claude-Code-trained model emitting\n * `mcp__acme__apply_migration` against a server zidane registered as\n * `mcp_acme_apply_migration` would otherwise trip the `tool:unknown`\n * path and waste a turn on the correction.\n *\n * Idempotent: a canonical that already has a double-underscore alias\n * mapped (host's explicit `toolAliases` got there first) is left alone.\n * Tools whose canonical name DOESN'T start with `mcp_` (or that contain\n * no inner separator) are skipped — we don't want to invent aliases for\n * non-MCP tools or malformed names.\n *\n * Mutates `maps.canonicalByAlias` in place and returns the same object\n * for chaining.\n */\nexport function augmentMcpDoubleUnderscoreAliases(\n maps: AliasMaps,\n canonicalNames: Iterable<string>,\n): AliasMaps {\n for (const canonical of canonicalNames) {\n if (!canonical.startsWith('mcp_'))\n continue\n // Strip leading `mcp_`, then require AT LEAST one more `_` so the\n // remainder is `<server>_<tool>` (a degenerate `mcp_foo` with no\n // tool segment has nothing meaningful to double-underscore).\n const tail = canonical.slice(4)\n const sep = tail.indexOf('_')\n if (sep <= 0 || sep >= tail.length - 1)\n continue\n const server = tail.slice(0, sep)\n const tool = tail.slice(sep + 1)\n const doubleForm = `mcp__${server}__${tool}`\n if (doubleForm === canonical)\n continue // shouldn't happen but defensive\n if (maps.canonicalByAlias.has(doubleForm))\n continue // host alias or earlier pass got there first\n maps.canonicalByAlias.set(doubleForm, canonical)\n }\n return maps\n}\n\n/**\n * Rewrite `tool_call` block names in a content array from canonical → wire for outbound\n * messages sent to the provider. Mutation is non-destructive (returns a new array).\n */\nexport function rewriteContentToWire(\n content: SessionContentBlock[],\n maps: AliasMaps,\n): SessionContentBlock[] {\n if (maps.aliasByCanonical.size === 0)\n return content\n return content.map((block) => {\n if (block.type !== 'tool_call')\n return block\n const wire = maps.aliasByCanonical.get(block.name)\n if (!wire || wire === block.name)\n return block\n return { ...block, name: wire }\n })\n}\n\n/**\n * Rewrite `tool_call` block names in a content array from wire → canonical for inbound\n * messages received from the provider. Non-destructive.\n */\nexport function rewriteContentToCanonical(\n content: SessionContentBlock[],\n maps: AliasMaps,\n): SessionContentBlock[] {\n if (maps.canonicalByAlias.size === 0)\n return content\n return content.map((block) => {\n if (block.type !== 'tool_call')\n return block\n const canonical = maps.canonicalByAlias.get(block.name)\n if (!canonical || canonical === block.name)\n return block\n return { ...block, name: canonical }\n })\n}\n\n/**\n * Rewrite every `SessionMessage.content` in an array from canonical → wire.\n * Returns a new array of new message objects — input messages are not mutated.\n * When the alias map is empty, returns the input by reference (no allocation).\n */\nexport function rewriteMessagesToWire(\n messages: SessionMessage[],\n maps: AliasMaps,\n): SessionMessage[] {\n if (maps.aliasByCanonical.size === 0)\n return messages\n return messages.map(msg => ({ ...msg, content: rewriteContentToWire(msg.content, maps) }))\n}\n","/**\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` — 64-bit FNV-style 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 { AliasMaps } from '../aliasing'\nimport type { Session } from '../session'\nimport type { SessionTurn, ToolResultContent } from '../types'\nimport { resolve } from 'node:path'\nimport { toCanonicalName } from '../aliasing'\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 * Set when stale-read elision removed this path's read output from the\n * on-wire history. The entry stays registered — `requireReadBeforeEdit`\n * must keep passing (the contentHash still guards against disk drift;\n * un-registering here is what degraded models into shell-edit one-liner\n * workarounds) — but `read_file`'s dedup must MISS on the next identical\n * re-read: the \"unchanged since the previous read\" stub would point at\n * content the model can no longer see. Cleared by the next fresh read\n * (`rememberRead` writes a flag-less entry).\n */\n elided?: true\n}\n\nexport type ReadStateMap = Map<string, ReadStateEntry>\n\nconst STATE = new WeakMap<Session, ReadStateMap>()\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 * Mark a read-state entry as elided from the on-wire history WITHOUT\n * un-registering it.\n *\n * Used by the loop's `elideStaleReads` pass. The entry must survive —\n * deleting it made the `requireReadBeforeEdit` gate reject the very next\n * edit on a file the model had demonstrably read and just edited (the\n * gate's failure mode then defeats the gate: models degrade to raw shell\n * edits that bypass the guard entirely). The `elided` flag instead\n * defeats only the dedup stub: the next identical re-read returns the\n * full body again, and `rememberRead` clears the flag.\n *\n * No-op when the path has no entry in the resolved map(s).\n */\nexport function markReadStateElided(ctx: {\n session?: Session\n readState?: ReadStateMap\n}, cwd: string, path: string): void {\n const key = readStateKey(cwd, path)\n for (const map of [ctx.readState, ctx.session ? STATE.get(ctx.session) : undefined]) {\n const entry = map?.get(key)\n if (entry && entry.elided !== true)\n map!.set(key, { ...entry, elided: true })\n }\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 * 64-bit content hash: two independent 32-bit FNV-1a-style lanes (different\n * offset bases + multipliers) concatenated as 16 hex chars. Fast,\n * non-cryptographic — but wide enough that the `requireReadBeforeEdit`\n * drift gate, which silently corrupts a file on a false \"unchanged\"\n * verdict, isn't betting on a 32-bit birthday bound (~1 in 4 billion per\n * pair; uncomfortably reachable over many files × many sessions). Entries\n * live only in per-session in-memory maps, so widening needs no\n * stored-format migration. Still cheaper than allocating a Buffer and\n * pulling in `crypto`.\n */\nexport function hashContent(text: string): string {\n let h1 = 0x811C9DC5 // FNV-1a offset basis\n let h2 = 0x7EE36237 // arbitrary distinct basis for the second lane\n for (let i = 0; i < text.length; i++) {\n const c = text.charCodeAt(i)\n h1 = Math.imul(h1 ^ c, 0x01000193) >>> 0 // FNV prime 16777619\n h2 = Math.imul(h2 ^ c, 0x85EBCA6B) >>> 0 // murmur3 fmix multiplier\n }\n return h1.toString(16).padStart(8, '0') + h2.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 * Tool-name aliases in effect for the transcript being replayed. zidane's\n * loop canonicalizes tool-call names before persisting, so durable turns\n * normally already carry canonical names — but a transcript captured from a\n * host that persists WIRE names (the aliased form the model saw, e.g.\n * `Read` / `Edit`), or one imported from another stack, would otherwise be\n * unrecognized and hydrate nothing. When provided, each tool-call name is\n * resolved to canonical (`toCanonicalName`) before matching, so both the\n * canonical and the aliased shape are honored. No-op for already-canonical\n * names.\n */\n aliasMaps?: AliasMaps\n}\n\ntype NormalizedHydrateReadStateOptions = Required<Omit<HydrateReadStateOptions, 'readFileForHash' | 'aliasMaps'>> & {\n readFileForHash?: HydrateReadStateOptions['readFileForHash']\n aliasMaps?: AliasMaps\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 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 // Resolve wire aliases (e.g. `Read`/`Edit`) to canonical before\n // matching, and STORE the canonical name in `pending` so the\n // downstream `stateFromToolResult` dispatch (which keys off the\n // canonical tool-name options) lines up regardless of how the\n // transcript spelled the call.\n const canonicalName = canonicalToolCallName(block.name, normalized)\n if (\n canonicalName === normalized.readFileToolName\n || canonicalName === normalized.writeFileToolName\n || canonicalName === normalized.editToolName\n || canonicalName === normalized.multiEditToolName\n ) {\n pending.set(block.id, { name: canonicalName, 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 (!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 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 // Resolve wire aliases (e.g. `Read`/`Edit`) to canonical before\n // matching, and STORE the canonical name in `pending` so the\n // downstream `stateFromToolResult` dispatch (which keys off the\n // canonical tool-name options) lines up regardless of how the\n // transcript spelled the call.\n const canonicalName = canonicalToolCallName(block.name, normalized)\n if (\n canonicalName === normalized.readFileToolName\n || canonicalName === normalized.writeFileToolName\n || canonicalName === normalized.editToolName\n || canonicalName === normalized.multiEditToolName\n ) {\n pending.set(block.id, { name: canonicalName, 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 (!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 * Module-level \"already hydrated\" guard, shared by every host that rebuilds\n * read-state from a persisted transcript (the agent's run-start pass and the\n * Restate tool wrapper alike). Keyed by `Session` identity: a host that\n * reloads a fresh `Session` object from a store on each resume (the common\n * store-backed pattern) hydrates that object exactly once, while a long-lived\n * in-process `Session` never re-scans its turns. WeakSet entries are GC'd\n * with the session, so this never leaks.\n */\nconst HYDRATED_READ_STATE_SESSIONS = new WeakSet<Session>()\n\n/**\n * Rebuild a session's read-state from its durable turns AT MOST ONCE.\n *\n * The read-state map lives in an in-memory `WeakMap<Session, …>` and is never\n * serialized with the session. So any host that reloads a `Session` from a\n * store on resume starts each run with an EMPTY map — and `requireReadBeforeEdit`\n * then rejects an `edit` on a file the model demonstrably read in an earlier\n * turn (\"has not been read in this session\"), degrading the model into\n * re-reading or falling back to `write_file` on every edit. This restores the\n * gate (and read dedup) across the resume boundary by replaying `session.turns`.\n *\n * Idempotent and cheap on a warm session: the WeakSet guard short-circuits\n * repeat calls. The guard is set BEFORE the await so concurrent first-tool\n * callers (Restate fans out concurrency-safe reads) don't double-scan.\n *\n * Returns the number of newly hydrated entries (`0` when already hydrated or\n * sessionless).\n */\nexport async function ensureReadStateHydratedOnce(\n session: Session | undefined,\n cwd: string,\n options: HydrateReadStateOptions = {},\n): Promise<number> {\n if (!session || HYDRATED_READ_STATE_SESSIONS.has(session))\n return 0\n HYDRATED_READ_STATE_SESSIONS.add(session)\n return await hydrateReadStateFromSessionAsync(session, cwd, options)\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 ...(options.aliasMaps ? { aliasMaps: options.aliasMaps } : {}),\n }\n}\n\n/**\n * Resolve a transcript tool-call name to its canonical form for matching.\n * Honors `aliasMaps` (wire → canonical) when present; otherwise the name is\n * already canonical (zidane persists canonical names) and passes through.\n */\nfunction canonicalToolCallName(name: string, options: NormalizedHydrateReadStateOptions): string {\n return options.aliasMaps ? toCanonicalName(name, options.aliasMaps) : name\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
+ {"version":3,"file":"read-state-BymF41Jb.js","names":[],"sources":["../src/aliasing.ts","../src/tools/read-state.ts"],"sourcesContent":["/**\n * Tool-name aliasing helpers.\n *\n * Aliasing is applied at the LLM boundary only: the provider sees the aliased\n * name, but hooks and persisted turns use canonical names. See `AgentOptions.toolAliases`.\n */\n\nimport type { SessionContentBlock, SessionMessage } from './types'\nimport { fnv1aBase36 } from './hash'\n\n/** Forward + reverse lookup between canonical and aliased tool names */\nexport interface AliasMaps {\n /** canonical → alias (only entries where alias !== canonical) */\n aliasByCanonical: Map<string, string>\n /** alias → canonical (only entries where alias !== canonical) */\n canonicalByAlias: Map<string, string>\n}\n\n/**\n * Build alias lookup maps from a `toolAliases` record.\n *\n * Validates:\n * - No two canonical names map to the same alias (collision).\n * - No alias collides with another canonical tool name (would shadow).\n *\n * Silently ignores alias entries whose canonical name isn't in `canonicalNames` —\n * preset/agent authors can declare aliases for tools that may be added later via MCP.\n *\n * @param aliases - The `toolAliases` map from the agent options.\n * @param canonicalNames - All tool canonical names currently in scope (agent + MCP).\n */\nexport function buildAliasMaps(\n aliases: Record<string, string> | undefined,\n canonicalNames: Iterable<string>,\n): AliasMaps {\n const aliasByCanonical = new Map<string, string>()\n const canonicalByAlias = new Map<string, string>()\n\n if (!aliases) {\n return { aliasByCanonical, canonicalByAlias }\n }\n\n const canonicalSet = new Set(canonicalNames)\n\n // A canonical name is \"genuinely remapped\" when it has an alias entry that is\n // both non-empty and different from itself. Identity aliases or missing keys\n // mean the tool still answers to its canonical name on the wire.\n function isRemappedAway(canonical: string): boolean {\n const mapped = aliases![canonical]\n return typeof mapped === 'string' && mapped.length > 0 && mapped !== canonical\n }\n\n for (const [canonical, alias] of Object.entries(aliases)) {\n if (typeof alias !== 'string' || alias.length === 0)\n throw new Error(`Tool alias for \"${canonical}\" must be a non-empty string`)\n\n if (alias === canonical)\n continue\n\n if (!canonicalSet.has(canonical))\n continue\n\n // When the alias matches an existing canonical tool name, only allow it if\n // that other canonical is itself being remapped away (i.e. a name swap).\n // Otherwise the wire name would shadow a real tool.\n if (canonicalSet.has(alias) && !isRemappedAway(alias)) {\n throw new Error(`Tool alias \"${canonical}\" -> \"${alias}\" collides with an existing canonical tool name`)\n }\n\n const existingCanonical = canonicalByAlias.get(alias)\n if (existingCanonical && existingCanonical !== canonical) {\n throw new Error(\n `Tool alias collision: both \"${existingCanonical}\" and \"${canonical}\" map to alias \"${alias}\"`,\n )\n }\n\n aliasByCanonical.set(canonical, alias)\n canonicalByAlias.set(alias, canonical)\n }\n\n return { aliasByCanonical, canonicalByAlias }\n}\n\n/** Return the alias for a canonical name, falling back to the canonical name itself. */\nexport function toWireName(canonical: string, maps: AliasMaps): string {\n return maps.aliasByCanonical.get(canonical) ?? canonical\n}\n\n/** Return the canonical name for a wire name, falling back to the wire name itself. */\nexport function toCanonicalName(wire: string, maps: AliasMaps): string {\n return maps.canonicalByAlias.get(wire) ?? wire\n}\n\n/**\n * Tool names must match `^[a-zA-Z0-9_-]{1,N}$`. The charset is universal; the\n * length cap is taken as the STRICTEST across providers (OpenAI/-compat: 64;\n * Anthropic allows 128) so a sanitized name is valid on EVERY provider — and so\n * a mid-session model switch can never make the provider-level drop guard\n * (`sanitizeToolSpecs`) discard a tool we could have kept.\n *\n * MCP tool names are minted verbatim as `mcp_<server>_<tool>` (see\n * `connectMcpServers`), so a server configured as `SSH Ipseity` yields\n * `mcp_SSH Ipseity_exec` — the space (and `.`/`:`/`/`, unicode, or a >64-char\n * join) 400s the request the instant that tool lands in the `tools` array:\n * `tools.N.custom.name: String should match pattern ...`.\n */\nconst WIRE_NAME_MAX = 64\nconst WIRE_NAME_OK = /^[\\w-]{1,64}$/\nconst WIRE_NAME_BAD_CHAR = /[^\\w-]/g\n\n/**\n * Build OUTBOUND wire aliases that coerce any tool name violating the provider\n * name constraint into a valid one. Only offenders get an entry; clean setups\n * return `undefined` (no alias map churn, prompt cache untouched).\n *\n * Returned as a `Record` so it merges into `effectiveToolAliases` upstream of\n * BOTH wire-name computations — the `tool_search` catalog and the `tools` array\n * — keeping them in lockstep. Canonical names (dispatch, hooks, persisted\n * turns) never change; only the bytes the model sees do.\n *\n * Scoped to MCP names (the only third-party-controlled, thus only realistically\n * invalid, source). The hash suffix keeps distinct originals distinct even when\n * they collapse to the same replacement; `taken` guards the residual collision.\n */\nexport function buildSanitizedWireAliases(\n names: Iterable<string>,\n existing: Record<string, string> | undefined,\n): Record<string, string> | undefined {\n const wireOf = (name: string): string => {\n const alias = existing?.[name]\n return typeof alias === 'string' && alias.length > 0 ? alias : name\n }\n\n // Already-valid wire names stay occupied so a freshly minted one can never\n // shadow another tool.\n const taken = new Set<string>()\n const offenders: string[] = []\n for (const name of names) {\n const wire = wireOf(name)\n if (WIRE_NAME_OK.test(wire))\n taken.add(wire)\n else\n offenders.push(name)\n }\n if (offenders.length === 0)\n return undefined\n\n const out: Record<string, string> = {}\n for (const name of offenders) {\n const sanitized = sanitizeWireName(wireOf(name), taken)\n out[name] = sanitized\n taken.add(sanitized)\n }\n return out\n}\n\nfunction sanitizeWireName(name: string, taken: ReadonlySet<string>): string {\n let base = name.replace(WIRE_NAME_BAD_CHAR, '_')\n if (base.length === 0)\n base = 'tool'\n // Hash the ORIGINAL so `a.b` vs `a/b` (both → `a_b`) and truncated long\n // names stay distinct and deterministic across runs.\n const hash = fnv1aBase36(name)\n const withSuffix = (suffix: string): string =>\n `${base.slice(0, Math.max(1, WIRE_NAME_MAX - suffix.length))}${suffix}`\n let candidate = withSuffix(`_${hash}`)\n for (let n = 1; taken.has(candidate); n++)\n candidate = withSuffix(`_${hash}_${n}`)\n return candidate\n}\n\n/**\n * Augment {@link AliasMaps} with INBOUND-ONLY aliases for the Claude Code\n * `mcp__server__tool` double-underscore naming convention. For every MCP\n * tool registered with the canonical `mcp_<server>_<tool>` form, add a\n * `canonicalByAlias` entry mapping the double-underscore variant to the\n * same canonical name. Outbound (`aliasByCanonical`) is left untouched —\n * the model still sees the single-underscore canonical on the wire, so\n * the tools-array byte count (and the provider prompt cache) is\n * unaffected.\n *\n * Why: SDK consumers and tool descriptions across the ecosystem\n * inconsistently reference one form or the other (Anthropic's docs use\n * double, zidane uses single). A Claude-Code-trained model emitting\n * `mcp__acme__apply_migration` against a server zidane registered as\n * `mcp_acme_apply_migration` would otherwise trip the `tool:unknown`\n * path and waste a turn on the correction.\n *\n * Idempotent: a canonical that already has a double-underscore alias\n * mapped (host's explicit `toolAliases` got there first) is left alone.\n * Tools whose canonical name DOESN'T start with `mcp_` (or that contain\n * no inner separator) are skipped — we don't want to invent aliases for\n * non-MCP tools or malformed names.\n *\n * Mutates `maps.canonicalByAlias` in place and returns the same object\n * for chaining.\n */\nexport function augmentMcpDoubleUnderscoreAliases(\n maps: AliasMaps,\n canonicalNames: Iterable<string>,\n): AliasMaps {\n for (const canonical of canonicalNames) {\n if (!canonical.startsWith('mcp_'))\n continue\n // Strip leading `mcp_`, then require AT LEAST one more `_` so the\n // remainder is `<server>_<tool>` (a degenerate `mcp_foo` with no\n // tool segment has nothing meaningful to double-underscore).\n const tail = canonical.slice(4)\n const sep = tail.indexOf('_')\n if (sep <= 0 || sep >= tail.length - 1)\n continue\n const server = tail.slice(0, sep)\n const tool = tail.slice(sep + 1)\n const doubleForm = `mcp__${server}__${tool}`\n if (doubleForm === canonical)\n continue // shouldn't happen but defensive\n if (maps.canonicalByAlias.has(doubleForm))\n continue // host alias or earlier pass got there first\n maps.canonicalByAlias.set(doubleForm, canonical)\n }\n return maps\n}\n\n/**\n * Rewrite `tool_call` block names in a content array from canonical → wire for outbound\n * messages sent to the provider. Mutation is non-destructive (returns a new array).\n */\nexport function rewriteContentToWire(\n content: SessionContentBlock[],\n maps: AliasMaps,\n): SessionContentBlock[] {\n if (maps.aliasByCanonical.size === 0)\n return content\n return content.map((block) => {\n if (block.type !== 'tool_call')\n return block\n const wire = maps.aliasByCanonical.get(block.name)\n if (!wire || wire === block.name)\n return block\n return { ...block, name: wire }\n })\n}\n\n/**\n * Rewrite `tool_call` block names in a content array from wire → canonical for inbound\n * messages received from the provider. Non-destructive.\n */\nexport function rewriteContentToCanonical(\n content: SessionContentBlock[],\n maps: AliasMaps,\n): SessionContentBlock[] {\n if (maps.canonicalByAlias.size === 0)\n return content\n return content.map((block) => {\n if (block.type !== 'tool_call')\n return block\n const canonical = maps.canonicalByAlias.get(block.name)\n if (!canonical || canonical === block.name)\n return block\n return { ...block, name: canonical }\n })\n}\n\n/**\n * Rewrite every `SessionMessage.content` in an array from canonical → wire.\n * Returns a new array of new message objects — input messages are not mutated.\n * When the alias map is empty, returns the input by reference (no allocation).\n */\nexport function rewriteMessagesToWire(\n messages: SessionMessage[],\n maps: AliasMaps,\n): SessionMessage[] {\n if (maps.aliasByCanonical.size === 0)\n return messages\n return messages.map(msg => ({ ...msg, content: rewriteContentToWire(msg.content, maps) }))\n}\n","/**\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` — 64-bit FNV-style 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 { AliasMaps } from '../aliasing'\nimport type { Session } from '../session'\nimport type { SessionTurn, ToolResultContent } from '../types'\nimport { resolve } from 'node:path'\nimport { toCanonicalName } from '../aliasing'\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 * Set when stale-read elision removed this path's read output from the\n * on-wire history. The entry stays registered — `requireReadBeforeEdit`\n * must keep passing (the contentHash still guards against disk drift;\n * un-registering here is what degraded models into shell-edit one-liner\n * workarounds) — but `read_file`'s dedup must MISS on the next identical\n * re-read: the \"unchanged since the previous read\" stub would point at\n * content the model can no longer see. Cleared by the next fresh read\n * (`rememberRead` writes a flag-less entry).\n */\n elided?: true\n}\n\nexport type ReadStateMap = Map<string, ReadStateEntry>\n\nconst STATE = new WeakMap<Session, ReadStateMap>()\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 * Mark a read-state entry as elided from the on-wire history WITHOUT\n * un-registering it.\n *\n * Used by the loop's `elideStaleReads` pass. The entry must survive —\n * deleting it made the `requireReadBeforeEdit` gate reject the very next\n * edit on a file the model had demonstrably read and just edited (the\n * gate's failure mode then defeats the gate: models degrade to raw shell\n * edits that bypass the guard entirely). The `elided` flag instead\n * defeats only the dedup stub: the next identical re-read returns the\n * full body again, and `rememberRead` clears the flag.\n *\n * No-op when the path has no entry in the resolved map(s).\n */\nexport function markReadStateElided(ctx: {\n session?: Session\n readState?: ReadStateMap\n}, cwd: string, path: string): void {\n const key = readStateKey(cwd, path)\n for (const map of [ctx.readState, ctx.session ? STATE.get(ctx.session) : undefined]) {\n const entry = map?.get(key)\n if (entry && entry.elided !== true)\n map!.set(key, { ...entry, elided: true })\n }\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 * 64-bit content hash: two independent 32-bit FNV-1a-style lanes (different\n * offset bases + multipliers) concatenated as 16 hex chars. Fast,\n * non-cryptographic — but wide enough that the `requireReadBeforeEdit`\n * drift gate, which silently corrupts a file on a false \"unchanged\"\n * verdict, isn't betting on a 32-bit birthday bound (~1 in 4 billion per\n * pair; uncomfortably reachable over many files × many sessions). Entries\n * live only in per-session in-memory maps, so widening needs no\n * stored-format migration. Still cheaper than allocating a Buffer and\n * pulling in `crypto`.\n */\nexport function hashContent(text: string): string {\n let h1 = 0x811C9DC5 // FNV-1a offset basis\n let h2 = 0x7EE36237 // arbitrary distinct basis for the second lane\n for (let i = 0; i < text.length; i++) {\n const c = text.charCodeAt(i)\n h1 = Math.imul(h1 ^ c, 0x01000193) >>> 0 // FNV prime 16777619\n h2 = Math.imul(h2 ^ c, 0x85EBCA6B) >>> 0 // murmur3 fmix multiplier\n }\n return h1.toString(16).padStart(8, '0') + h2.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 * Tool-name aliases in effect for the transcript being replayed. zidane's\n * loop canonicalizes tool-call names before persisting, so durable turns\n * normally already carry canonical names — but a transcript captured from a\n * host that persists WIRE names (the aliased form the model saw, e.g.\n * `Read` / `Edit`), or one imported from another stack, would otherwise be\n * unrecognized and hydrate nothing. When provided, each tool-call name is\n * resolved to canonical (`toCanonicalName`) before matching, so both the\n * canonical and the aliased shape are honored. No-op for already-canonical\n * names.\n */\n aliasMaps?: AliasMaps\n}\n\ntype NormalizedHydrateReadStateOptions = Required<Omit<HydrateReadStateOptions, 'readFileForHash' | 'aliasMaps'>> & {\n readFileForHash?: HydrateReadStateOptions['readFileForHash']\n aliasMaps?: AliasMaps\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 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 // Resolve wire aliases (e.g. `Read`/`Edit`) to canonical before\n // matching, and STORE the canonical name in `pending` so the\n // downstream `stateFromToolResult` dispatch (which keys off the\n // canonical tool-name options) lines up regardless of how the\n // transcript spelled the call.\n const canonicalName = canonicalToolCallName(block.name, normalized)\n if (\n canonicalName === normalized.readFileToolName\n || canonicalName === normalized.writeFileToolName\n || canonicalName === normalized.editToolName\n || canonicalName === normalized.multiEditToolName\n ) {\n pending.set(block.id, { name: canonicalName, 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 (!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 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 // Resolve wire aliases (e.g. `Read`/`Edit`) to canonical before\n // matching, and STORE the canonical name in `pending` so the\n // downstream `stateFromToolResult` dispatch (which keys off the\n // canonical tool-name options) lines up regardless of how the\n // transcript spelled the call.\n const canonicalName = canonicalToolCallName(block.name, normalized)\n if (\n canonicalName === normalized.readFileToolName\n || canonicalName === normalized.writeFileToolName\n || canonicalName === normalized.editToolName\n || canonicalName === normalized.multiEditToolName\n ) {\n pending.set(block.id, { name: canonicalName, 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 (!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 ...(options.aliasMaps ? { aliasMaps: options.aliasMaps } : {}),\n }\n}\n\n/**\n * Resolve a transcript tool-call name to its canonical form for matching.\n * Honors `aliasMaps` (wire → canonical) when present; otherwise the name is\n * already canonical (zidane persists canonical names) and passes through.\n */\nfunction canonicalToolCallName(name: string, options: NormalizedHydrateReadStateOptions): string {\n return options.aliasMaps ? toCanonicalName(name, options.aliasMaps) : name\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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"}
package/dist/restate.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Ct as Provider, Et as StreamOptions, T as ToolDef, Zn as ToolResultContent, ln as AgentBehavior, o as McpToolMeta, q as SessionStore, qn as ToolBatchExecutor, s as McpToolWrap, un as AgentClock, w as ToolContext } from "./agent-B_jcbRS1.js";
1
+ import { K as SessionStore, Kn as ToolBatchExecutor, St as Provider, T as ToolDef, Tt as StreamOptions, Xn as ToolResultContent, cn as AgentBehavior, ln as AgentClock, o as McpToolMeta, s as McpToolWrap, w as ToolContext } from "./agent-DQIL5BFk.js";
2
2
  import { h as TaskExitInfo, l as ExecutionHandle, m as TaskEntry, o as DetachedTasksCapability } from "./types-Bs2oY7Ux.js";
3
3
 
4
4
  //#region src/restate/types.d.ts
@@ -1 +1 @@
1
- {"version":3,"file":"restate.d.ts","names":[],"sources":["../src/restate/types.ts","../src/restate/awakeable.ts","../src/restate/awakeable-tool.ts","../src/restate/behavior.ts","../src/restate/clock.ts","../src/restate/errors.ts","../src/restate/replay.ts","../src/restate/mcp.ts","../src/restate/parallel.ts","../src/restate/provider.ts","../src/restate/session.ts","../src/restate/tool.ts","../src/restate/wait-background.ts"],"mappings":"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"}
1
+ {"version":3,"file":"restate.d.ts","names":[],"sources":["../src/restate/types.ts","../src/restate/awakeable.ts","../src/restate/awakeable-tool.ts","../src/restate/behavior.ts","../src/restate/clock.ts","../src/restate/errors.ts","../src/restate/replay.ts","../src/restate/mcp.ts","../src/restate/parallel.ts","../src/restate/provider.ts","../src/restate/session.ts","../src/restate/tool.ts","../src/restate/wait-background.ts"],"mappings":";;;;;;;;AAmBA;;;;;;;;;;;AAYO;AAUP;;UAtBiB,iBAAA;EAwBC;EAtBhB,gBAAA;EAqBA;EAnBA,gBAAA;EAoBS;EAlBT,oBAAA;EAkBkB;EAhBlB,gBAAA;EAuCe;EArCf,mBAAA;EAqCiC;EAnCjC,KAAA;AAAA;;;;;;;;UAUe,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;EA0BP;;;;;;;;;;;;EAb9B,KAAA,GAAQ,MAAA,aAAmB,OAAA;AAAA;;;;;;AAcP;;UAJL,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;;;;;AAtEH;AAUP;;;;;UClBiB,sBAAA,kBAAwC,OAAA,YAAmB,OAAA;EAC1E,IAAA,GAAO,MAAA,WAAiB,QAAA,OAAe,OAAA;AAAA;AAAA,UAGxB,2BAAA,kBAA6C,OAAA,YAAmB,OAAA;EDgB7D;AAAA;AAuBpB;;EClCE,SAAA;EDqCoB;;;;;;;EC7BpB,QAAA,GAAW,sBAAA,CAAuB,QAAA;AAAA;;;;;;;;;;;;;;;;;iBAmBpB,oBAAA,qBAAyC,OAAA,YAAmB,OAAA,UAAA,CAC1E,GAAA,EAAK,kBAAA,EACL,OAAA,GAAS,2BAAA,CAA4B,QAAA,IACpC,gBAAA,CAAiB,CAAA;;;UC5BH,2BAAA;EFgCA;EE9Bf,IAAA;EF8BiC;EE5BjC,WAAA;EF+BY;EE7BZ,WAAA,EAAa,MAAA;EF8BD;EE5BZ,GAAA,EAAK,kBAAA;EF6BA;;;;;EEvBL,MAAA,GAAS,IAAA;IACP,WAAA;IACA,KAAA,EAAO,MAAA;IACP,OAAA,EAAS,WAAA;EAAA,aACE,OAAA;EFiBD;;;;EEZZ,QAAA,IAAY,KAAA,EAAO,CAAA,EAAG,KAAA,EAAO,MAAA,+BAAqC,iBAAA;EFahE;;;;EERF,UAAA,GAAa,iBAAA;EFUM;;;;EELnB,iBAAA;AAAA;;;;;;AFoBkC;AAUpC;;iBEnBgB,oBAAA,aAAA,CACd,OAAA,EAAS,2BAAA,CAA4B,CAAA,IACpC,OAAA;;;;;;AF7DH;;;;;;;;;;;iBGFgB,eAAA,CAAgB,SAAA,GAAW,aAAA,GAAqB,aAAa;;;;;;AHctE;AAUP;;;;iBInBgB,YAAA,CAAa,GAAA,EAAK,kBAAA,GAAqB,UAAU;;;;;;;AJHjE;;;iBKZgB,gCAAA,CAAiC,KAAc;;;;;;;ALY/D;;;;;;;;;;;AAYO;AAUP;;;;;;;;;;AAEoB;AAuBpB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqBoC;AAUpC;;;UM1BiB,eAAA;EACf,QAAA,GAAW,IAAA,iBAAqB,GAAA,EAAK,MAAM;AAAA;AAAA,UAG5B,oBAAA;ENsBmD;;;;;;;EMdlE,KAAA,GAAQ,eAAe;ENgBW;;;;;;;;;AAEd;;;;AC9EtB;;;EK6EE,QAAA;AAAA;AAAA,UAGe,aAAA;EL/EwB;;;;;;EKsFvC,WAAA;ELtFwB;;;;AAAsB;AAGhD;;;;;;EK+FE,UAAA;ELlFiC;;;;;;EKyFjC,MAAA,GAAS,EAAA;ELzFE;;;AAA+B;AAmB5C;EK4EE,QAAA;AAAA;;;;;;iBAQc,mBAAA,CAAoB,OAAA,GAAS,oBAAA,GAA4B,aAAa;;;;;;;;;;;;iBAwDtE,gBAAA,CAAiB,OAAA,EAAS,aAAa,EAAE,KAAA;;;UClIxC,yBAAA;EPkBmB;AAUpC;;;;;EOrBE,aAAA,GAAgB,aAAA;EPqBgC;;;;;;;EObhD,UAAA,GAAa,iBAAA;EPea;;;;;EOT1B,SAAA,IAAa,GAAA,UAAa,IAAA,UAAc,KAAA,EAAO,MAAA,mBAAyB,MAAA;EPUjD;;;;AACH;;EOJpB,OAAA;;AN1EF;;;;;;;EMmFE,QAAA,IAAY,IAAA,EAAM,OAAA,EAAS,IAAA,EAAM,WAAA,KAAgB,OAAA;AAAA;;;;;;;iBAkCnC,kBAAA,CACd,GAAA,EAAK,kBAAA,EACL,OAAA,GAAS,yBAAA,GACR,WAAA;;;UC5Ic,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;ERUnF;;;;EQLA,QAAA,EAAU,qBAAA,CAAsB,QAAA;AAAA;;ARe3B;AAUP;;;;;iBQfgB,wBAAA,kBAA0C,OAAA,YAAmB,kBAAA,UAAA,CAC3E,OAAA,EAAS,+BAAA,CAAgC,QAAA,IACxC,iBAAA;;;UCFc,sBAAA;ETiBG;AAAA;AAuBpB;;;;;;;;;;;;;;;;;;;ESlBE,UAAA,GAAa,iBAAA;ETqBY;;;;;;;ESbzB,SAAA,IAAa,GAAA,UAAa,IAAA,EAAM,aAAA;ETgBb;;;;;;;ESRnB,eAAA;ETuBQ;;;AAA0B;AAUpC;;;ESzBE,aAAA,GAAgB,aAAA;AAAA;;;;;;;iBASF,eAAA,CACd,KAAA,EAAO,QAAA,EACP,GAAA,EAAK,kBAAA,EACL,OAAA,GAAS,sBAAA,GACR,QAAA;;;;;;;;;;;iBCzBa,mBAAA,CAAoB,GAAA,EAAK,wBAAA,GAA2B,YAAY;;;;;;;;;;;;;;;;;;;;;;;UCD/D,mBAAA;EXWb;EWTF,KAAA,GAAQ,KAAA,EAAO,MAAA,mBAAyB,OAAA,EAAS,WAAA,KAAgB,OAAA,CAAQ,KAAA,IAAS,KAAA;EXUrE;;;;;;;;;;;;EWGb,MAAA,IAAU,KAAA,EAAO,KAAA,EAAO,KAAA,EAAO,MAAA,mBAAyB,OAAA,EAAS,WAAA,KAAgB,OAAA,UAAiB,iBAAA;EXahE;AAAA;AAUpC;;;;;;;;;;;;;;;;;EWHE,IAAA,GAAO,kBAAA,CAAmB,KAAA,EAAO,OAAA;EXMxB;;;;;;AACW;;;;AC9EtB;;;;;;;;;;EU4FE,OAAA,IAAW,KAAA,EAAO,KAAA,EAAO,KAAA,EAAO,MAAA,mBAAyB,OAAA,EAAS,WAAA,KAAgB,OAAA;AAAA;;;;;;AV3FpC;AAGhD;;;;;UUsGiB,kBAAA;EVzFJ;;;;;;EUgGX,QAAA,GAAW,KAAA,EAAO,KAAA,EAAO,WAAA,UAAqB,KAAA,EAAO,MAAA,mBAAyB,OAAA,EAAS,WAAA,KAAgB,OAAA;EVhGvG;;;;AAA0C;AAmB5C;EUoFE,MAAA,GAAS,KAAA,EAAO,KAAA,EAAO,OAAA,EAAS,OAAA,SAAgB,KAAA,EAAO,MAAA,mBAAyB,OAAA,EAAS,WAAA,KAAgB,OAAA,UAAiB,iBAAA,eAAgC,iBAAA;EVpFxH;;;;;;;EU4FlC,SAAA,cAAuB,KAAA,EAAO,MAAA,mBAAyB,OAAA,EAAS,WAAA;EVzF/C;;;;;EU+FjB,QAAA,GAAW,sBAAA;EVjGN;;;;;;;;AAEc;;;;AC5BrB;;;;;;ES8IE,MAAA,IAAU,KAAA,EAAO,KAAA,EAAO,KAAA,EAAO,MAAA,mBAAyB,OAAA,EAAS,WAAA;AAAA;AAAA,UASlD,kBAAA;EThIc;;;;;;;ESwI7B,UAAA,GAAa,iBAAA;ETzJb;;;;;;;;ESkKA,SAAA,IAAa,GAAA,UAAa,IAAA,UAAc,KAAA,EAAO,MAAA,mBAAyB,MAAA;ETvJ7D;;;;;;;ES+JX,sBAAA;ETzJkE;;;;;AAUjD;AAWnB;;;;ES+IE,aAAA,GAAgB,uBAAA;ET7If;;;;;ESmJD,YAAA,GAAe,mBAAA,CAAoB,KAAA,EAAO,OAAA;ETpJ1C;;;AACQ;;;;AC/DV;EQ2NE,aAAA,GAAgB,aAAA;;;;;;;AR3N2D;;;;ACK7E;;;;;;;;AAAiE;;EO2O/D,UAAA;;AN1PF;;;;AAA+D;;;;ACgE/D;EKqME,kBAAA;AAAA;;;;;iBAsBc,WAAA,oCAAA,CACd,KAAA,EAAO,OAAA,EACP,GAAA,EAAK,kBAAA,EACL,OAAA,GAAS,kBAAA,CAAmB,KAAA,EAAO,OAAA,IAClC,OAAA;;AL9NyD;AAG5D;;;;;;iBKikBgB,cAAA,CACd,KAAA,EAAO,MAAA,SAAe,OAAA,GACtB,GAAA,EAAK,kBAAA,EACL,IAAA,GAAM,IAAA,CAAK,kBAAA;EAAwC,OAAA;AAAA,IAClD,MAAA,SAAe,OAAA;;;UCnmBD,4BAAA;EZ6BsB;EY3BrC,GAAA,EAAK,kBAAA;EZwCsB;;;;;;EYjC3B,KAAA,GAAQ,MAAA,EAAQ,eAAA,EAAiB,MAAA,aAAmB,OAAA,UAAiB,SAAA,eAAwB,SAAA;EZezE;;;;;;EYRpB,QAAA,GAAW,WAAA,UAAqB,MAAA,UAAgB,MAAA,EAAQ,eAAA,KAAoB,OAAA;EZW5E;;;;;EYLA,MAAA,IAAU,WAAA,UAAqB,MAAA,UAAgB,IAAA,EAAM,YAAA,SAAqB,MAAA,EAAQ,eAAA,KAAoB,OAAA;EZO1F;;;;;EYDZ,SAAA;EZckC;AAAA;AAUpC;;;EYlBE,QAAA,GAAW,sBAAA;EZoBe;EYlB1B,UAAA,GAAa,iBAAA;EZgBmC;EYdhD,WAAA;EZckE;EYZlE,aAAA,GAAgB,aAAA;AAAA;;;;;;iBAiDF,qBAAA,CACd,OAAA,EAAS,4BAAA,IACP,MAAA,EAAQ,eAAA,EAAiB,MAAA,UAAgB,IAAA;EAAS,SAAA;EAAoB,MAAA,GAAS,WAAA;AAAA,MAAkB,OAAA,CAAQ,YAAA"}
package/dist/restate.js CHANGED
@@ -1,4 +1,4 @@
1
- import { d as buildAliasMaps, o as hydrateReadStateFromSessionAsync } from "./read-state-B9O85Lel.js";
1
+ import { a as hydrateReadStateFromSessionAsync, u as buildAliasMaps } from "./read-state-BymF41Jb.js";
2
2
  import { r as coerceToolResultContent } from "./types-CyVGdbia.js";
3
3
  //#region src/restate/awakeable.ts
4
4
  /**
@@ -204,16 +204,15 @@ function rethrowSoftToolError(value) {
204
204
  //#region src/restate/tool.ts
205
205
  const SHELL_BACKGROUND_DISABLED_MESSAGE = "shell error: background mode is disabled for Restate-backed agents. Fall back to foreground (drop `run_in_background`).";
206
206
  /**
207
- * Restate keeps its OWN once-per-session hydration guard deliberately
208
- * independent of the agent's run-start `ensureReadStateHydratedOnce` guard.
207
+ * Once-per-session (per process) guard for the restate tool wrapper's read-state
208
+ * hydration. Rebuilds the map from `session.turns` the first time any wrapped
209
+ * tool runs LIVE in a process, so `read_file` re-reads dedup correctly across a
210
+ * replay (a journaled read never re-runs its live `rememberRead`).
209
211
  *
210
- * The two passes fire at different points and a SHARED guard would let the
211
- * early one starve the late one: `agent.run()` hydrates at invocation start
212
- * (before any tool runs), but within a single Restate invocation that REPLAYS,
213
- * a journaled read re-appears in `session.turns` only DURING replay and never
214
- * re-runs its live `rememberRead`. So the read-state must be rebuilt again at
215
- * the first LIVE tool (typically the edit), after the re-append. Keeping this
216
- * guard separate guarantees that per-tool pass always gets to run.
212
+ * Note: the authoritative `requireReadBeforeEdit` recovery lives in the loop's
213
+ * read-before-edit pre-hydration gate (see `agent.ts`), which fires regardless
214
+ * of how tools are wrapped. This pass is the dedup-side complement for
215
+ * `restateTool`-wrapped consumers; it is NOT what the gate depends on.
217
216
  */
218
217
  const HYDRATED_READ_STATE_SESSIONS = /* @__PURE__ */ new WeakSet();
219
218
  /**