@ponythewhite/base-context 1.0.9 → 1.0.11

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 (80) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/dist/base-context-runtime/pyproject.toml +1 -1
  3. package/dist/base-context-runtime/uv.lock +1 -1
  4. package/dist/build-info.json +1 -1
  5. package/dist/bundle/{bundled-modules-5JRM6P4T.js → bundled-modules-PEFT72QN.js} +2 -2
  6. package/dist/bundle/{chunk-VVI3UKGR.js → chunk-JZHGOOFM.js} +87 -57
  7. package/dist/bundle/{chunk-NEHLB7JV.js → chunk-TOOVREMP.js} +596 -102
  8. package/dist/bundle/{cli-main-YUDBEYE2.js → cli-main-BRXGYTGK.js} +2 -2
  9. package/dist/bundle/cli.js +1 -1
  10. package/dist/bundle/{main-ZLGGAAGU.js → main-POUXGEL6.js} +2 -2
  11. package/dist/core/agent-session.d.ts +0 -1
  12. package/dist/core/agent-session.d.ts.map +1 -1
  13. package/dist/core/agent-session.js +85 -45
  14. package/dist/core/agent-session.js.map +1 -1
  15. package/dist/core/canonical-context.d.ts +19 -3
  16. package/dist/core/canonical-context.d.ts.map +1 -1
  17. package/dist/core/canonical-context.js +245 -39
  18. package/dist/core/canonical-context.js.map +1 -1
  19. package/dist/core/context-epoch-copy.d.ts +1 -1
  20. package/dist/core/context-epoch-copy.d.ts.map +1 -1
  21. package/dist/core/context-epoch-copy.js +18 -7
  22. package/dist/core/context-epoch-copy.js.map +1 -1
  23. package/dist/core/context-epoch.d.ts +18 -3
  24. package/dist/core/context-epoch.d.ts.map +1 -1
  25. package/dist/core/context-epoch.js +13 -2
  26. package/dist/core/context-epoch.js.map +1 -1
  27. package/dist/core/context-tree.d.ts +1 -1
  28. package/dist/core/context-tree.d.ts.map +1 -1
  29. package/dist/core/context-tree.js +98 -8
  30. package/dist/core/context-tree.js.map +1 -1
  31. package/dist/core/history-index-worker.d.ts.map +1 -1
  32. package/dist/core/history-index-worker.js +59 -6
  33. package/dist/core/history-index-worker.js.map +1 -1
  34. package/dist/core/history-index.d.ts +17 -0
  35. package/dist/core/history-index.d.ts.map +1 -1
  36. package/dist/core/history-index.js +22 -0
  37. package/dist/core/history-index.js.map +1 -1
  38. package/dist/core/inference-coordinator.d.ts.map +1 -1
  39. package/dist/core/inference-coordinator.js +5 -1
  40. package/dist/core/inference-coordinator.js.map +1 -1
  41. package/dist/core/public-context.d.ts.map +1 -1
  42. package/dist/core/public-context.js +20 -8
  43. package/dist/core/public-context.js.map +1 -1
  44. package/dist/core/request-view-selection.d.ts +2 -1
  45. package/dist/core/request-view-selection.d.ts.map +1 -1
  46. package/dist/core/request-view-selection.js +29 -2
  47. package/dist/core/request-view-selection.js.map +1 -1
  48. package/dist/core/session-fork-messages.d.ts +5 -0
  49. package/dist/core/session-fork-messages.d.ts.map +1 -1
  50. package/dist/core/session-fork-messages.js +44 -0
  51. package/dist/core/session-fork-messages.js.map +1 -1
  52. package/dist/core/session-history-index.d.ts +5 -0
  53. package/dist/core/session-history-index.d.ts.map +1 -1
  54. package/dist/core/session-history-index.js +7 -0
  55. package/dist/core/session-history-index.js.map +1 -1
  56. package/dist/core/session-manager.d.ts +2 -0
  57. package/dist/core/session-manager.d.ts.map +1 -1
  58. package/dist/core/session-manager.js +155 -13
  59. package/dist/core/session-manager.js.map +1 -1
  60. package/dist/core/session-tree.d.ts +9 -0
  61. package/dist/core/session-tree.d.ts.map +1 -1
  62. package/dist/core/session-tree.js +71 -11
  63. package/dist/core/session-tree.js.map +1 -1
  64. package/dist/modes/agent-connection/in-process-agent-connection.d.ts.map +1 -1
  65. package/dist/modes/agent-connection/in-process-agent-connection.js +4 -4
  66. package/dist/modes/agent-connection/in-process-agent-connection.js.map +1 -1
  67. package/dist/modes/daemon/daemon-mode.d.ts.map +1 -1
  68. package/dist/modes/daemon/daemon-mode.js +19 -34
  69. package/dist/modes/daemon/daemon-mode.js.map +1 -1
  70. package/dist/modes/daemon/daemon-socket.d.ts +5 -0
  71. package/dist/modes/daemon/daemon-socket.d.ts.map +1 -1
  72. package/dist/modes/daemon/daemon-socket.js +19 -0
  73. package/dist/modes/daemon/daemon-socket.js.map +1 -1
  74. package/dist/modes/daemon/daemon-supervisor.d.ts.map +1 -1
  75. package/dist/modes/daemon/daemon-supervisor.js +6 -7
  76. package/dist/modes/daemon/daemon-supervisor.js.map +1 -1
  77. package/dist/modes/daemon/daemon-worker-client.d.ts.map +1 -1
  78. package/dist/modes/daemon/daemon-worker-client.js +5 -5
  79. package/dist/modes/daemon/daemon-worker-client.js.map +1 -1
  80. package/package.json +4 -4
@@ -27737,6 +27737,7 @@ var CONTEXT_POLICY_EPOCH_RENDERER = "native-canonical-epoch/5";
27737
27737
  var CONTEXT_TOOL_EPOCH_RENDERER = "native-canonical-epoch/6";
27738
27738
  var CONTEXT_SKILL_EPOCH_RENDERER = "native-canonical-epoch/7";
27739
27739
  var CONTEXT_TOOL_SUMMARY_RENDERER = "native-canonical-epoch/8";
27740
+ var CONTEXT_INTERRUPTED_TOOL_RENDERER = "native-canonical-epoch/9";
27740
27741
  function contextEpochMode(checkpoint, initial = "on") {
27741
27742
  return checkpoint ? checkpoint.version === 5 || checkpoint.version === 8 ? checkpoint.mode : "on" : initial;
27742
27743
  }
@@ -27785,10 +27786,16 @@ function readContextEpoch(details, maxBytes) {
27785
27786
  if (!details || typeof details !== "object" || !(CONTEXT_EPOCH_DETAIL in details))
27786
27787
  return;
27787
27788
  const value = details[CONTEXT_EPOCH_DETAIL];
27788
- if (!value || typeof value !== "object" || !("version" in value) || !("renderer" in value) || !(value.version === 1 && value.renderer === "native-canonical-epoch/1" || value.version === 2 && value.renderer === "native-canonical-epoch/2" || value.version === 3 && value.renderer === "native-canonical-epoch/3" || value.version === 4 && value.renderer === "native-canonical-epoch/4" || value.version === 5 && value.renderer === CONTEXT_POLICY_EPOCH_RENDERER || value.version === 6 && value.renderer === CONTEXT_TOOL_EPOCH_RENDERER || value.version === 8 && value.renderer === CONTEXT_TOOL_SUMMARY_RENDERER || [4, 5, 6].includes(value.version) && value.renderer === CONTEXT_SKILL_EPOCH_RENDERER) || (value.renderer === CONTEXT_SKILL_EPOCH_RENDERER || value.version === 8 && "selectedSkills" in value ? !("selectedSkills" in value) || !Array.isArray(value.selectedSkills) || value.selectedSkills.length === 0 || value.selectedSkills.some((item) => !item || typeof item.name !== "string" || !item.view || !["custom_message", "custom"].includes(item.view.ref?.kind) || typeof item.view.sourceRevision !== "string") || new Set(value.selectedSkills.map((item) => item.name)).size !== value.selectedSkills.length : "selectedSkills" in value) || !("source" in value) || !value.source || !("views" in value) || !Array.isArray(value.views) || !("literalTailId" in value) || typeof value.literalTailId !== "string" || !("representation" in value) || (value.version === 5 || value.version === 8 ? !("mode" in value) || value.mode !== "on" && value.mode !== "off" : "mode" in value) || value.version === 8 && (value.representation !== null || !("includeSummary" in value) || value.includeSummary !== true) || value.version === 5 && (value.representation !== null || !("policyOnly" in value) || value.policyOnly !== true) || "policyOnly" in value && (value.version !== 5 || value.policyOnly !== true || value.representation !== null || "includeSummary" in value) || "pendingRequestContract" in value && (value.version !== 5 || !("mode" in value) || value.mode !== "off" || value.pendingRequestContract !== true || "requestContract" in value) || "requestContract" in value && (value.version !== 5 || !isRequestContract(value.requestContract)) || !(typeof value.representation === "string" || value.version === 5 && value.representation === null && "policyOnly" in value && value.policyOnly === true || (value.version === 2 || value.version === 3 || value.version === 4 || value.version === 8) && value.representation === null && "includeSummary" in value && value.includeSummary === true) || "includeSummary" in value && (value.version !== 2 && value.version !== 3 && value.version !== 4 && value.version !== 8 || value.includeSummary !== true || value.representation !== null) || "replayContract" in value && value.replayContract !== "complete-context" && value.replayContract !== "message-groups" || "resourceRevision" in value && (typeof value.resourceRevision !== "string" || Buffer.byteLength(value.resourceRevision, "utf8") > MAX_RESOURCE_REVISION_BYTES) || "publicWindow" in value && (value.version !== 3 && value.version !== 4 && value.version !== 5 && value.version !== 6 && value.version !== 8 || value.publicWindow !== true) || "toolContinuations" in value && value.version !== 6 && value.version !== 8 || (value.version === 6 || value.version === 8) && (!("toolContinuations" in value) || !Array.isArray(value.toolContinuations) || !value.toolContinuations.length || !("replayContract" in value) || value.version === 6 && (!("publicWindow" in value) || value.publicWindow !== true || value.replayContract !== "message-groups")) || "continuation" in value && (value.version !== 3 && value.version !== 4 && value.version !== 5 && value.version !== 6 && value.version !== 8 || !value.continuation || typeof value.continuation !== "object" || !("kind" in value.continuation) || value.continuation.kind !== "harness-summary" && (value.version !== 4 && value.version !== 5 && value.version !== 6 || value.continuation.kind !== "portable-checkpoint") || !("publicTailThrough" in value.continuation) || !value.continuation.publicTailThrough))
27789
+ if (!value || typeof value !== "object" || !("version" in value) || !("renderer" in value) || !(value.version === 1 && value.renderer === "native-canonical-epoch/1" || value.version === 2 && value.renderer === "native-canonical-epoch/2" || value.version === 3 && value.renderer === "native-canonical-epoch/3" || value.version === 4 && value.renderer === "native-canonical-epoch/4" || value.version === 5 && value.renderer === CONTEXT_POLICY_EPOCH_RENDERER || value.version === 6 && value.renderer === CONTEXT_TOOL_EPOCH_RENDERER || value.version === 8 && value.renderer === CONTEXT_TOOL_SUMMARY_RENDERER || [6, 8].includes(value.version) && value.renderer === CONTEXT_INTERRUPTED_TOOL_RENDERER || [4, 5, 6].includes(value.version) && value.renderer === CONTEXT_SKILL_EPOCH_RENDERER) || (value.renderer === CONTEXT_SKILL_EPOCH_RENDERER || (value.version === 8 || value.renderer === CONTEXT_INTERRUPTED_TOOL_RENDERER) && "selectedSkills" in value ? !("selectedSkills" in value) || !Array.isArray(value.selectedSkills) || value.selectedSkills.length === 0 || value.selectedSkills.some((item) => !item || typeof item.name !== "string" || !item.view || !["custom_message", "custom"].includes(item.view.ref?.kind) || typeof item.view.sourceRevision !== "string") || new Set(value.selectedSkills.map((item) => item.name)).size !== value.selectedSkills.length : "selectedSkills" in value) || !("source" in value) || !value.source || !("views" in value) || !Array.isArray(value.views) || !("literalTailId" in value) || typeof value.literalTailId !== "string" || !("representation" in value) || (value.version === 5 || value.version === 8 ? !("mode" in value) || value.mode !== "on" && value.mode !== "off" : "mode" in value) || value.version === 8 && (value.representation !== null || !("includeSummary" in value) || value.includeSummary !== true) || value.version === 5 && (value.representation !== null || !("policyOnly" in value) || value.policyOnly !== true) || "policyOnly" in value && (value.version !== 5 || value.policyOnly !== true || value.representation !== null || "includeSummary" in value) || "pendingRequestContract" in value && (value.version !== 5 || !("mode" in value) || value.mode !== "off" || value.pendingRequestContract !== true || "requestContract" in value) || "requestContract" in value && (value.version !== 5 || !isRequestContract(value.requestContract)) || !(typeof value.representation === "string" || value.version === 5 && value.representation === null && "policyOnly" in value && value.policyOnly === true || (value.version === 2 || value.version === 3 || value.version === 4 || value.version === 8) && value.representation === null && "includeSummary" in value && value.includeSummary === true) || "includeSummary" in value && (value.version !== 2 && value.version !== 3 && value.version !== 4 && value.version !== 8 || value.includeSummary !== true || value.representation !== null) || "replayContract" in value && value.replayContract !== "complete-context" && value.replayContract !== "message-groups" || "resourceRevision" in value && (typeof value.resourceRevision !== "string" || Buffer.byteLength(value.resourceRevision, "utf8") > MAX_RESOURCE_REVISION_BYTES) || "publicWindow" in value && (value.version !== 3 && value.version !== 4 && value.version !== 5 && value.version !== 6 && value.version !== 8 || value.publicWindow !== true) || "toolContinuations" in value && value.version !== 6 && value.version !== 8 || (value.version === 6 || value.version === 8) && (!("toolContinuations" in value) || !Array.isArray(value.toolContinuations) || !value.toolContinuations.length || !("replayContract" in value) || value.version === 6 && (!("publicWindow" in value) || value.publicWindow !== true || value.replayContract !== "message-groups")) || "continuation" in value && (value.version !== 3 && value.version !== 4 && value.version !== 5 && value.version !== 6 && value.version !== 8 || !value.continuation || typeof value.continuation !== "object" || !("kind" in value.continuation) || value.continuation.kind !== "harness-summary" && (value.version !== 4 && value.version !== 5 && value.version !== 6 || value.continuation.kind !== "portable-checkpoint") || !("publicTailThrough" in value.continuation) || !value.continuation.publicTailThrough))
27789
27790
  throw new Error("Invalid committed context epoch");
27790
27791
  return snapshotContextEpoch(value, maxBytes);
27791
27792
  }
27793
+ var UnsupportedContextEpochConfigurationError = class extends Error {
27794
+ constructor() {
27795
+ super("Unsupported context epoch request configuration");
27796
+ this.name = "UnsupportedContextEpochConfigurationError";
27797
+ }
27798
+ };
27792
27799
  function contextEpochRepresentation(request, assessment, maxBytes, unbudgetedPublic = false, responseItemIdentity) {
27793
27800
  if (!assessment && !unbudgetedPublic || assessment && (!assessment.profile || assessment.limitSource !== "explicit-profile" || !assessment.route || !assessment.model) || request.body === void 0)
27794
27801
  throw new Error("Committed context epoch requires its explicit request profile");
@@ -27826,7 +27833,7 @@ function contextEpochRepresentation(request, assessment, maxBytes, unbudgetedPub
27826
27833
  if (["input", "messages", "previous_response_id", "prompt_cache_key"].includes(key2))
27827
27834
  continue;
27828
27835
  if (!fields.has(key2))
27829
- throw new Error("Unsupported context epoch request configuration");
27836
+ throw new UnsupportedContextEpochConfigurationError();
27830
27837
  configuration[key2] = value;
27831
27838
  }
27832
27839
  const input = "input" in body ? body.input : "messages" in body ? body.messages : void 0;
@@ -28443,19 +28450,27 @@ function renderToolContinuation(message2, entryId, source, group, maxBytes) {
28443
28450
  role: message2.role,
28444
28451
  content,
28445
28452
  ...message2.role === "assistant" ? {
28446
- calls: group.calls.map((call) => ({
28453
+ calls: group.calls.map((call, sourceOrder) => call.admission === "absent" ? {
28454
+ sourceOrder,
28455
+ admission: "not_recorded",
28456
+ capturedHistory: {
28457
+ sessionId: call.source.sessionId,
28458
+ leafId: call.source.leafId,
28459
+ sourceSequence: call.source.sourceSequence
28460
+ }
28461
+ } : {
28447
28462
  executionId: call.executionId,
28448
28463
  intentEntryId: call.intent.id,
28449
28464
  intent: "recorded",
28450
28465
  outcome: call.outcome,
28451
28466
  ...call.result ? { resultEntryId: call.result.id } : {}
28452
- }))
28467
+ })
28453
28468
  } : {}
28454
28469
  }, maxBytes);
28455
28470
  const rendered = {
28456
28471
  role: "custom",
28457
28472
  customType: PUBLIC_TOOL_CONTINUATION_RENDERER,
28458
- content: `Recorded tool continuation data. Intent acknowledgment records intent only; an absent finalized result leaves the outcome unknown.
28473
+ content: `Recorded tool continuation data. Intent acknowledgment records intent only; an absent finalized result leaves the outcome unknown.${group.calls.some((call) => call.admission === "absent") ? " For calls marked admission not recorded, no qualified admission or finalized result is recorded in that captured history; the outcome is unknown. This historical view does not authorize tool execution." : ""}
28459
28474
  ${data}`,
28460
28475
  display: false,
28461
28476
  timestamp: message2.timestamp
@@ -29057,6 +29072,15 @@ var HistoryIndex = class _HistoryIndex {
29057
29072
  snapshot: target
29058
29073
  });
29059
29074
  }
29075
+ /** Whole-source own usage for exactly the current acknowledged owner snapshot. */
29076
+ async currentSourceUsage(sessionId, snapshot) {
29077
+ return await this.request({
29078
+ id: this.nextId++,
29079
+ action: "current_source_usage",
29080
+ sessionId,
29081
+ snapshot
29082
+ });
29083
+ }
29060
29084
  /** Latest label control for this source target, including a clear. */
29061
29085
  async sourceLabel(sessionId, targetId, through) {
29062
29086
  return await this.request({ id: this.nextId++, action: "source_label", sessionId, targetId, through });
@@ -29071,6 +29095,17 @@ var HistoryIndex = class _HistoryIndex {
29071
29095
  through
29072
29096
  });
29073
29097
  }
29098
+ /** All matching source update refs, including off-branch and older revisions. */
29099
+ async sourceContextUpdates(sessionId, target, through, after = 0) {
29100
+ return await this.request({
29101
+ id: this.nextId++,
29102
+ action: "source_context_updates",
29103
+ sessionId,
29104
+ target: target.kind === "assistant-usage" ? { kind: target.kind, targetId: target.targetId } : { kind: target.kind, toolCallId: target.toolCallId },
29105
+ through,
29106
+ after
29107
+ });
29108
+ }
29074
29109
  async get(sessionId, eventId, scope) {
29075
29110
  return await this.request({
29076
29111
  id: this.nextId++,
@@ -29393,6 +29428,7 @@ function createSessionHistoryReadScope(index, source, query, scope) {
29393
29428
  }),
29394
29429
  sourceLabel: (targetId) => query(() => index.sourceLabel(sessionId, targetId, source.sourceSequence)),
29395
29430
  sourceAssistantUsage: (targetId) => query(() => index.sourceAssistantUsage(sessionId, targetId, source.sourceSequence)),
29431
+ sourceContextUpdates: (target, after = 0) => query(() => index.sourceContextUpdates(sessionId, target, source.sourceSequence, after)),
29396
29432
  ipythonSentMessages: (toolCallId, options = {}) => query(() => index.ipythonSentMessages(sessionId, branch, toolCallId, options)),
29397
29433
  get,
29398
29434
  page,
@@ -29486,6 +29522,12 @@ var SessionHistoryIndex = class {
29486
29522
  const index = await this.synchronize(captured);
29487
29523
  return index.currentSourceBootstrap(this.sessionId, captured);
29488
29524
  }
29525
+ /** Caller holds the owner queue until the exact current projection is read. */
29526
+ async currentSourceUsage(snapshot) {
29527
+ const captured = { ...snapshot };
29528
+ const index = await this.synchronize(captured);
29529
+ return index.currentSourceUsage(this.sessionId, captured);
29530
+ }
29489
29531
  /** Finish accepted indexing, then wait for the external worker to close. */
29490
29532
  close() {
29491
29533
  this.closing ??= (async () => {
@@ -31549,7 +31591,7 @@ function prepareCanonicalEpoch(messages, selectedUnitIds, representation, maxByt
31549
31591
  return {
31550
31592
  checkpoint: snapshotContextEpoch({
31551
31593
  version: context.toolContinuations?.length ? 6 : 4,
31552
- renderer: context.selectedSkills?.length ? CONTEXT_SKILL_EPOCH_RENDERER : context.toolContinuations?.length ? CONTEXT_TOOL_EPOCH_RENDERER : CONTEXT_EPOCH_RENDERER,
31594
+ renderer: context.toolContinuations?.some((group) => group.calls.some((call) => call.admission === "absent")) ? CONTEXT_INTERRUPTED_TOOL_RENDERER : context.selectedSkills?.length ? CONTEXT_SKILL_EPOCH_RENDERER : context.toolContinuations?.length ? CONTEXT_TOOL_EPOCH_RENDERER : CONTEXT_EPOCH_RENDERER,
31553
31595
  ...context.selectedSkills?.length ? { selectedSkills: context.selectedSkills } : {},
31554
31596
  ...context.toolContinuations?.length ? { toolContinuations: context.toolContinuations } : {},
31555
31597
  source: context.source,
@@ -31565,7 +31607,19 @@ function prepareCanonicalEpoch(messages, selectedUnitIds, representation, maxByt
31565
31607
  messages: chosen
31566
31608
  };
31567
31609
  }
31568
- function canonicalRecoveryBoundary(messages) {
31610
+ var MissingRecoveryReplayContractError = class extends Error {
31611
+ constructor() {
31612
+ super("Recovery compaction requires an accepted replay contract for its selected results");
31613
+ this.name = "MissingRecoveryReplayContractError";
31614
+ }
31615
+ };
31616
+ function sameRecoverySource(left, right, ownerStillCurrent = false) {
31617
+ return JSON.stringify(left) === JSON.stringify(right) || ownerStillCurrent && left.sessionId === right.sessionId && left.sessionFile === right.sessionFile && left.persistent === right.persistent;
31618
+ }
31619
+ function sameRecoveryReference(left, right, ownerStillCurrent = false) {
31620
+ return sameRecoverySource(left.source, right.source, ownerStillCurrent) && JSON.stringify(left.ref) === JSON.stringify(right.ref) && left.sourceRevision === right.sourceRevision;
31621
+ }
31622
+ function canonicalRecoveryBoundary(messages, authorization) {
31569
31623
  const context = compiledEpochContexts.get(messages);
31570
31624
  const units = getCanonicalViewUnits(messages);
31571
31625
  if (!context || !units)
@@ -31575,15 +31629,22 @@ function canonicalRecoveryBoundary(messages) {
31575
31629
  const recoveries = units.flatMap((unit, index) => unit.kind === "recovery" ? [context.references[index]] : []);
31576
31630
  if (!recoveries.length)
31577
31631
  return;
31632
+ if (authorization) {
31633
+ const ownerStillCurrent = authorization.isSourceCurrent?.();
31634
+ if (ownerStillCurrent === false || !sameRecoverySource(context.source, authorization.source, ownerStillCurrent === true) || context.resourceRevision !== authorization.resourceRevision || recoveries.length !== authorization.recoveries.length || recoveries.some((reference) => !reference || !authorization.recoveries.some((covered) => sameRecoveryReference(reference, covered, ownerStillCurrent === true))))
31635
+ throw new Error("Recovery compaction authorization no longer matches its captured source");
31636
+ return latestLiteralReference(context.references)?.ref.entryId;
31637
+ }
31578
31638
  const checkpoint = context.checkpoint;
31579
- if (!checkpoint?.representation || checkpoint.replayContract !== "message-groups" || recoveries.some((reference) => !reference || reference.ref.sequence > checkpoint.source.sourceSequence))
31580
- throw new Error("Recovery compaction requires an accepted replay contract for its selected results");
31639
+ const inherited = checkpoint?.includeSummary === true && checkpoint.replayContract === "message-groups";
31640
+ if (checkpoint?.replayContract !== "message-groups" || recoveries.some((reference) => !reference || (checkpoint.representation ? reference.ref.sequence > checkpoint.source.sourceSequence : !inherited || !context.inheritedRecoveryCoverage?.some((covered) => sameRecoveryReference(reference, covered)))))
31641
+ throw new MissingRecoveryReplayContractError();
31581
31642
  return checkpoint.literalTailId;
31582
31643
  }
31583
- function prepareRecoveryCompaction(messages, firstKeptEntryId, maxBytes) {
31584
- const boundary = canonicalRecoveryBoundary(messages);
31644
+ function prepareRecoveryCompaction(messages, firstKeptEntryId, maxBytes, authorization) {
31645
+ const boundary = canonicalRecoveryBoundary(messages, authorization);
31585
31646
  const context = compiledEpochContexts.get(messages);
31586
- const publicWindow = context?.checkpoint?.publicWindow === true && context.checkpoint.replayContract === "message-groups";
31647
+ const publicWindow = authorization ? authorization.publicWindow : context?.checkpoint?.publicWindow === true && context.checkpoint.replayContract === "message-groups";
31587
31648
  if (!boundary && !publicWindow && !context?.selectedSkills?.length && !context?.toolContinuations?.length)
31588
31649
  return;
31589
31650
  if (!context)
@@ -31620,7 +31681,7 @@ function prepareRecoveryCompaction(messages, firstKeptEntryId, maxBytes) {
31620
31681
  return;
31621
31682
  return snapshotContextEpoch({
31622
31683
  ...toolGroups.size ? { version: 8, mode: context.mode } : { version: 4 },
31623
- renderer: toolGroups.size ? CONTEXT_TOOL_SUMMARY_RENDERER : context.selectedSkills?.length ? CONTEXT_SKILL_EPOCH_RENDERER : CONTEXT_EPOCH_RENDERER,
31684
+ renderer: context.toolContinuations?.some((group) => group.calls.some((call) => call.admission === "absent")) ? CONTEXT_INTERRUPTED_TOOL_RENDERER : toolGroups.size ? CONTEXT_TOOL_SUMMARY_RENDERER : context.selectedSkills?.length ? CONTEXT_SKILL_EPOCH_RENDERER : CONTEXT_EPOCH_RENDERER,
31624
31685
  ...toolGroups.size ? { toolContinuations: context.toolContinuations } : {},
31625
31686
  ...context.selectedSkills?.length ? { selectedSkills: context.selectedSkills } : {},
31626
31687
  source: context.source,
@@ -32110,6 +32171,10 @@ ${JSON.stringify(selections.map((skill) => ({
32110
32171
  }
32111
32172
  const replayUnits = bindMessageReplayUnits(messages, sourceUnits, unitLimits);
32112
32173
  const frozenGroups = checkpoint?.toolContinuations ?? [];
32174
+ const assistantSequences = messages.flatMap((message2) => {
32175
+ const reference = epochReferences.get(message2);
32176
+ return message2.role === "assistant" && reference ? [reference.ref.sequence] : [];
32177
+ }).sort((left, right) => left - right);
32113
32178
  const candidates = messages.flatMap((message2, index) => {
32114
32179
  if (message2.role !== "assistant")
32115
32180
  return [];
@@ -32125,6 +32190,8 @@ ${JSON.stringify(selections.map((skill) => ({
32125
32190
  index,
32126
32191
  reference,
32127
32192
  prior,
32193
+ nextAssistantSequence: assistantSequences.find((sequence) => sequence > reference.ref.sequence) ?? Infinity,
32194
+ unqualifiedIntent: false,
32128
32195
  intents: /* @__PURE__ */ new Map()
32129
32196
  }
32130
32197
  ];
@@ -32140,48 +32207,63 @@ ${JSON.stringify(selections.map((skill) => ({
32140
32207
  countBytes(metadata);
32141
32208
  return hydrateCapturedHistoryEntry(metadata, maxSourceBytes, view.readPayload);
32142
32209
  };
32143
- const acceptIntent = async (metadata) => {
32144
- if (metadata.kind !== "tool_intent" || metadata.qualification !== "native-tool-execution" || metadata.retention === "retained-import")
32210
+ const acceptIntent = async (metadata, selected = candidates) => {
32211
+ if (metadata.kind !== "tool_intent")
32145
32212
  return;
32146
32213
  const hydrated = await readToolEvidence(metadata);
32147
32214
  const entry = hydrated.entry;
32148
- if (entry.type !== "tool_intent" || entry.assistant?.sessionId !== view.source.sessionId || entry.assistant.sessionFile !== view.source.sessionFile)
32215
+ if (entry.type !== "tool_intent")
32149
32216
  return;
32150
- const candidate = candidates.find((item) => item.reference.ref.entryId === entry.assistant?.entryId);
32217
+ const invocation = entry.invocation;
32218
+ const ownerMatch = selected.find((item) => item.reference.ref.entryId === entry.assistant?.entryId);
32219
+ const candidate = ownerMatch ?? selected.find((item) => metadata.sequence > item.reference.ref.sequence && metadata.sequence < item.nextAssistantSequence && item.message.content.some((part) => part.type === "toolCall" && part.id === invocation.toolCallId && part.name === invocation.toolName));
32151
32220
  if (!candidate)
32152
32221
  return;
32153
- const invocation = entry.invocation;
32222
+ if (metadata.qualification !== "native-tool-execution" || metadata.retention === "retained-import" || entry.assistant?.sessionId !== view.source.sessionId || entry.assistant.sessionFile !== view.source.sessionFile || entry.assistant.entryId !== candidate.reference.ref.entryId) {
32223
+ candidate.unqualifiedIntent = true;
32224
+ return;
32225
+ }
32154
32226
  const call = candidate.message.content.filter((part) => part.type === "toolCall")[invocation.sourceOrder];
32155
32227
  if (!Number.isSafeInteger(invocation.sourceOrder) || !call || call.id !== invocation.toolCallId || call.name !== invocation.toolName || !invocation.executionId || entry.id !== `${invocation.executionId}:intent` || metadata.sequence <= candidate.reference.ref.sequence || candidate.intents.has(invocation.sourceOrder))
32156
32228
  throw new Error("Tool continuation has ambiguous original intent");
32157
32229
  candidate.intents.set(invocation.sourceOrder, hydrated);
32158
32230
  };
32231
+ const absentPrefixes = /* @__PURE__ */ new Map();
32159
32232
  for (const candidate of candidates) {
32160
32233
  if (!candidate.prior)
32161
32234
  continue;
32162
32235
  if (!Array.isArray(candidate.prior.calls))
32163
32236
  throw new Error("Invalid committed tool continuation");
32164
32237
  for (const call of candidate.prior.calls) {
32238
+ if (call.admission === "absent") {
32239
+ if (checkpoint?.renderer !== CONTEXT_INTERRUPTED_TOOL_RENDERER || !call.source || call.source.sourceSequence < candidate.reference.ref.sequence || call.intent !== void 0 || call.executionId !== void 0 || call.outcome !== void 0 || call.result !== void 0)
32240
+ throw new Error("Invalid committed absent tool admission");
32241
+ const key2 = JSON.stringify(call.source);
32242
+ const prefix = absentPrefixes.get(key2) ?? { source: call.source, candidates: [] };
32243
+ if (!prefix.candidates.includes(candidate))
32244
+ prefix.candidates.push(candidate);
32245
+ absentPrefixes.set(key2, prefix);
32246
+ continue;
32247
+ }
32165
32248
  const actual = await view.get(call.intent.id);
32166
32249
  if (!actual || actual.revision !== call.intent.revision || actual.sequence !== call.intent.sequence)
32167
32250
  throw new Error("Committed tool intent is unavailable on this captured branch");
32168
- await acceptIntent(actual);
32251
+ await acceptIntent(actual, [candidate]);
32169
32252
  }
32170
32253
  }
32171
- const newGroups = candidates.filter((candidate) => !candidate.prior);
32172
- if (newGroups.length) {
32173
- let after = Math.min(...newGroups.map((candidate) => candidate.reference.ref.sequence));
32254
+ const scanIntents = async (readView, selected) => {
32255
+ let after = Math.min(...selected.map((candidate) => candidate.reference.ref.sequence));
32174
32256
  let scanned = 0;
32175
32257
  for (; ; ) {
32176
- const page = await view.page(after, Math.min(128, maxMessages - scanned + 1));
32258
+ const page = await readView.page(after, Math.min(128, maxMessages - scanned + 1));
32177
32259
  scanned += page.events.length;
32178
32260
  if (scanned > maxMessages)
32179
32261
  throw new Error("Tool continuation source item budget exceeded");
32180
32262
  if (page.coverage !== "complete")
32181
32263
  throw new Error("Tool continuation source coverage is incomplete");
32182
32264
  for (const metadata of page.events) {
32183
- if (!candidates.some((candidate) => candidate.prior?.calls.some((call) => call.intent.id === metadata.id)))
32184
- await acceptIntent(metadata);
32265
+ if (!selected.some((candidate) => [...candidate.intents.values()].some((intent) => intent.source.id === metadata.id)))
32266
+ await acceptIntent(metadata, selected);
32185
32267
  }
32186
32268
  if (page.nextAfter === null)
32187
32269
  break;
@@ -32189,21 +32271,51 @@ ${JSON.stringify(selections.map((skill) => ({
32189
32271
  throw new Error("Tool continuation source page did not advance");
32190
32272
  after = page.nextAfter;
32191
32273
  }
32274
+ };
32275
+ const newGroups = candidates.filter((candidate) => !candidate.prior);
32276
+ if (newGroups.length)
32277
+ await scanIntents(view, newGroups);
32278
+ for (const prefix of absentPrefixes.values()) {
32279
+ if (!view.atSnapshot)
32280
+ throw new Error("Absent tool admission requires its captured source");
32281
+ await scanIntents(await view.atSnapshot(prefix.source), prefix.candidates);
32192
32282
  }
32283
+ const checkAbsentScope = async (candidate) => {
32284
+ const entry = next.get(candidate.reference.ref.entryId)?.entry;
32285
+ const output = entry?.type === "message" ? entry.requestOutput : void 0;
32286
+ if (!output || typeof output.operationId !== "string" || !output.operationId || !Array.isArray(output.attemptIds) || output.attemptIds.some((id) => typeof id !== "string") || !output.source || output.source.sessionId !== view.source.sessionId || output.source.sessionFile !== view.source.sessionFile || !output.source.persistent || !Number.isSafeInteger(output.source.sourceSequence) || output.source.sourceSequence >= candidate.reference.ref.sequence || !view.atSnapshot)
32287
+ throw new Error("View-unit replay group is incomplete: original tool owner is unqualified");
32288
+ await view.atSnapshot(output.source);
32289
+ };
32193
32290
  const toolContinuations = [];
32194
32291
  const pendingPublicMessageGroups = [];
32195
32292
  for (const candidate of candidates) {
32196
32293
  const toolCalls = candidate.message.content.filter((part) => part.type === "toolCall");
32197
- if (!toolCalls.length || candidate.intents.size !== toolCalls.length || candidate.prior && candidate.prior.calls.length !== toolCalls.length)
32294
+ if (!toolCalls.length || candidate.unqualifiedIntent || candidate.prior && candidate.prior.calls.length !== toolCalls.length)
32198
32295
  throw new Error("View-unit replay group is incomplete: original tool owner is unqualified");
32296
+ if (candidate.intents.size !== toolCalls.length)
32297
+ await checkAbsentScope(candidate);
32199
32298
  const members = [candidate.index];
32200
32299
  const calls = [];
32201
32300
  for (let order = 0; order < toolCalls.length; order++) {
32202
32301
  const intent = candidate.intents.get(order);
32302
+ const original = candidate.prior?.calls[order];
32303
+ if (!intent) {
32304
+ if (original && original.admission !== "absent")
32305
+ throw new Error("Committed tool intent is unavailable on this captured branch");
32306
+ if (messages.some((message2) => {
32307
+ const sequence = epochReferences.get(message2)?.ref.sequence;
32308
+ return message2.role === "toolResult" && message2.toolCallId === toolCalls[order].id && sequence !== void 0 && sequence > candidate.reference.ref.sequence && sequence < candidate.nextAssistantSequence;
32309
+ }))
32310
+ throw new Error("Tool outcome lacks its original finalized owner");
32311
+ calls.push(original ?? { admission: "absent", source: { ...view.source } });
32312
+ continue;
32313
+ }
32314
+ if (original?.admission === "absent")
32315
+ throw new Error("Committed absent tool admission changed");
32203
32316
  if (intent.entry.type !== "tool_intent")
32204
32317
  throw new Error("Invalid native tool intent");
32205
32318
  const invocation = intent.entry.invocation;
32206
- const original = candidate.prior?.calls[order];
32207
32319
  if (original && (original.executionId !== invocation.executionId || original.intent.id !== intent.source.id))
32208
32320
  throw new Error("Committed tool execution identity changed");
32209
32321
  const actual = await view.get(invocation.executionId);
@@ -32264,10 +32376,83 @@ ${JSON.stringify(selections.map((skill) => ({
32264
32376
  units: selectionUnits,
32265
32377
  limits: unitLimits,
32266
32378
  ...mode === "on" && (taskFrameRebased || checkpoint) ? { requiresEpoch: true } : {},
32379
+ ...mode === "on" && sourceUnits.some((unit) => unit.kind === "recovery") ? { recoveryContractRequested: true } : {},
32267
32380
  ...pendingPublicMessageGroups.length ? { pendingPublicMessageGroups } : {}
32268
32381
  }
32269
32382
  });
32383
+ const inheritedRecoveryCoverage = [];
32384
+ if (checkpoint?.includeSummary && checkpoint.replayContract === "message-groups" && closedUnits.some((unit) => unit.kind === "recovery")) {
32385
+ const prefix = await view.atSnapshot(checkpoint.source);
32386
+ const suffix = /* @__PURE__ */ new Map();
32387
+ const frozenViews = /* @__PURE__ */ new Map();
32388
+ let capturedMessages = 0;
32389
+ let retained = false;
32390
+ let cursor2;
32391
+ for (; ; ) {
32392
+ const page = await prefix.contextManifest({ cursor: cursor2, limit: 128 });
32393
+ if (page.selection !== "known")
32394
+ throw new Error("Summary recovery source is unavailable");
32395
+ if (!cursor2 && page.summaryRef) {
32396
+ const entry = await hydrate(page.summaryRef, void 0, prefix);
32397
+ const metadata = await prefix.get(page.summaryRef.entryId);
32398
+ const prior = entry.type === "compaction" && metadata?.qualification === "native-context-epoch" && metadata.retention !== "retained-import" ? readContextEpoch(entry.details, maxSourceBytes) : void 0;
32399
+ if ((!prior || prior.includeSummary) && page.summaryRef.entryId === checkpoint.literalTailId)
32400
+ retained = true;
32401
+ capturedMessages += prior?.views.length ?? 0;
32402
+ for (const pinned of prior?.views ?? []) {
32403
+ if (pinned.ref.entryId === checkpoint.literalTailId)
32404
+ retained = true;
32405
+ if (retained) {
32406
+ suffix.set(pinned.ref.entryId, pinned.ref);
32407
+ frozenViews.set(pinned.ref.entryId, pinned);
32408
+ }
32409
+ }
32410
+ }
32411
+ for (const ref of page.refs) {
32412
+ if (ref.entryId === checkpoint.literalTailId)
32413
+ retained = true;
32414
+ if (retained)
32415
+ suffix.set(ref.entryId, ref);
32416
+ }
32417
+ capturedMessages += page.refs.length;
32418
+ if (capturedMessages > maxMessages)
32419
+ throw new Error("Summary recovery source exceeds its message budget");
32420
+ if (!page.nextCursor)
32421
+ break;
32422
+ cursor2 = page.nextCursor;
32423
+ }
32424
+ for (const [index, message2] of closedMessages.entries()) {
32425
+ if (closedUnits[index].kind !== "recovery")
32426
+ continue;
32427
+ const reference = epochReferences.get(message2);
32428
+ if (checkpoint.views.some((covered) => sameRecoveryReference(reference, covered))) {
32429
+ inheritedRecoveryCoverage.push(reference);
32430
+ continue;
32431
+ }
32432
+ const frozen = suffix.get(reference.ref.entryId);
32433
+ if (!frozen || JSON.stringify(frozen) !== JSON.stringify(reference.ref))
32434
+ continue;
32435
+ const pinned = frozenViews.get(frozen.entryId);
32436
+ if (pinned) {
32437
+ if (reference.sourceRevision === pinned.sourceRevision)
32438
+ inheritedRecoveryCoverage.push(reference);
32439
+ continue;
32440
+ }
32441
+ const revisions = [frozen.revision];
32442
+ const entry = next.get(frozen.entryId)?.entry;
32443
+ if (entry?.type === "message" && entry.message.role === "toolResult" && entry.message.toolName === "ipython") {
32444
+ const updates = await prefix.contextUpdates({
32445
+ kind: "ipython-sent-message",
32446
+ toolCallId: entry.message.toolCallId
32447
+ });
32448
+ revisions.push(...updates.refs.map((update) => update.revision));
32449
+ }
32450
+ if (reference.sourceRevision === JSON.stringify(revisions))
32451
+ inheritedRecoveryCoverage.push(reference);
32452
+ }
32453
+ }
32270
32454
  compiledEpochContexts.set(closedMessages, {
32455
+ ...inheritedRecoveryCoverage.length ? { inheritedRecoveryCoverage } : {},
32271
32456
  ...purpose === "read" ? { readOnly: true } : {},
32272
32457
  mode,
32273
32458
  source: { ...view.source },
@@ -32321,6 +32506,10 @@ var PublicContextBudgetError = class extends RequestTokenBudgetError {
32321
32506
  this.#summaryCapacity = summaryCapacity;
32322
32507
  }
32323
32508
  };
32509
+ var recoveryCompactionAuthorizations = /* @__PURE__ */ new WeakMap();
32510
+ function getRecoveryCompactionAuthorization(error) {
32511
+ return error ? recoveryCompactionAuthorizations.get(error) : void 0;
32512
+ }
32324
32513
  function captureRequestViewBoundary(messages, commit, validate2, fixedPrepare, isSourceCurrent) {
32325
32514
  const source = getCanonicalViewSelectionSource(messages);
32326
32515
  if (!source)
@@ -32419,7 +32608,7 @@ function publicBudgetFailure(boundary, messages, request, projection, budget, as
32419
32608
  });
32420
32609
  };
32421
32610
  const minimum = withRequestBody(request, JSON.stringify({ ...body, [inputKey]: retainedInput(/* @__PURE__ */ new Set()) }));
32422
- return new PublicContextBudgetError(boundary.source, assessment, original, budget.measure(minimum), (context.taskFrame?.messages.length ?? 0) > 1, JSON.stringify([
32611
+ const error = new PublicContextBudgetError(boundary.source, assessment, original, budget.measure(minimum), (context.taskFrame?.messages.length ?? 0) > 1, JSON.stringify([
32423
32612
  boundary.source.sessionId,
32424
32613
  boundary.source.sessionFile,
32425
32614
  source.units.map((unit) => [unit.id, unit.sourceRevision]),
@@ -32438,6 +32627,21 @@ function publicBudgetFailure(boundary, messages, request, projection, budget, as
32438
32627
  const measured = budget.measure(withRequestBody(request, JSON.stringify({ ...body, [inputKey]: kept })));
32439
32628
  return measured.status === "unknown" || measured.availableInputTokens === null || measured.estimatedInputTokens === null ? void 0 : Math.floor(measured.availableInputTokens - measured.estimatedInputTokens);
32440
32629
  }, boundary.isSourceCurrent);
32630
+ if (projection.replayContract === "message-groups") {
32631
+ const originalContext = getCanonicalEpochContext(boundary.messages);
32632
+ const recoveries = boundary.units.flatMap((unit, index) => unit.kind === "recovery" && originalContext.references[index] ? [originalContext.references[index]] : []);
32633
+ if (recoveries.length) {
32634
+ recoveryCompactionAuthorizations.set(error, {
32635
+ source: originalContext.source,
32636
+ recoveries,
32637
+ resourceRevision: originalContext.resourceRevision,
32638
+ // Do not extend a partial public conversion to native groups the encoder did not replace.
32639
+ publicWindow: messages !== boundary.messages && projection.publicWindow === true && boundary.units.every((unit, index) => !["recovery", "replay-group"].includes(unit.kind) || context.references[index]?.rendering !== void 0),
32640
+ isSourceCurrent: boundary.isSourceCurrent
32641
+ });
32642
+ }
32643
+ }
32644
+ return error;
32441
32645
  }
32442
32646
  async function prepareFixedRequestView(boundary, request, projection, assessment) {
32443
32647
  projection = canonicalRequestProjection(boundary, projection);
@@ -32510,7 +32714,7 @@ async function selectRequestView(boundary, request, projection, budget, allowShr
32510
32714
  const inputKey = requestInputKey(request, projection);
32511
32715
  if (budget && full?.limitSource !== "explicit-profile" || !inputKey)
32512
32716
  return;
32513
- if (!budget && !boundary.requiresEpoch && !boundary.pendingPublicMessageGroups?.length)
32717
+ if (!budget && !boundary.requiresEpoch && !boundary.recoveryContractRequested && !boundary.pendingPublicMessageGroups?.length)
32514
32718
  return;
32515
32719
  const payload = JSON.parse(request.body);
32516
32720
  const input = payload[inputKey];
@@ -33467,7 +33671,7 @@ var InferenceCoordinator = class _InferenceCoordinator {
33467
33671
  } : void 0;
33468
33672
  const requiredPublic = Boolean(boundary?.pendingPublicMessageGroups?.length);
33469
33673
  const requiredEpoch = boundary?.requiresEpoch === true;
33470
- const canSelect = (budget || boundary?.fixedPrepare || requiredPublic || requiredEpoch) && boundary && matchesRequestView(boundary, source, context);
33674
+ const canSelect = (budget || boundary?.fixedPrepare || requiredPublic || requiredEpoch || boundary?.recoveryContractRequested) && boundary && matchesRequestView(boundary, source, context);
33471
33675
  if (requiredPublic && (!canSelect || boundary?.fixedPrepare))
33472
33676
  throw new Error("Tool continuation requires a selectable native public request boundary");
33473
33677
  const responsesMessageIds = canSelect && !boundary.fixedPrepare && (model.api === "openai-responses" || model.api === "openai-codex-responses") ? boundary.providerMessageIndices.map((index) => {
@@ -34567,7 +34771,7 @@ function captureEpochCopyEntry(entry, source) {
34567
34771
  ...updateTarget ? { updateTarget } : {}
34568
34772
  };
34569
34773
  }
34570
- async function rebuildCopiedContextEpoch(history, copied, limits) {
34774
+ async function rebuildCopiedContextEpoch(history, copied, limits, metadataMaxBytes = limits.maxSourceBytes) {
34571
34775
  const view = history.branchContext;
34572
34776
  const manifest = await view.contextManifest({ limit: 1 });
34573
34777
  if (manifest.selection !== "known")
@@ -34596,15 +34800,26 @@ async function rebuildCopiedContextEpoch(history, copied, limits) {
34596
34800
  throw new Error("Tool continuation recipes require their original native execution source");
34597
34801
  if (!checkpoint || checkpoint.literalTailId !== entry.firstKeptEntryId || !view.atSnapshot)
34598
34802
  throw new Error("Copied context epoch boundary is unavailable");
34599
- if (copied.entries.length > limits.maxEntries || checkpoint.views.length > limits.maxEntries)
34803
+ if (checkpoint.views.length > limits.maxEntries)
34600
34804
  throw new Error("Copied context epoch item budget exceeded");
34601
- stringifyBoundedJson(copied, limits.maxSourceBytes);
34805
+ stringifyBoundedJson(copied, metadataMaxBytes);
34602
34806
  const oldByRevision = new Map([...oldById.values()].map((source) => [source.revision, source]));
34603
34807
  const destination = /* @__PURE__ */ new Map();
34604
- for (const source of oldById.values()) {
34605
- const actual = await history.get(source.id);
34606
- if (actual)
34607
- destination.set(source.id, actual);
34808
+ let after = 0;
34809
+ for (; ; ) {
34810
+ const page = await history.page(after, 128);
34811
+ if (page.indexedThrough < history.source.sourceSequence)
34812
+ throw new Error("Copied context destination has incomplete index coverage");
34813
+ for (const actual of page.events) {
34814
+ if (!oldById.has(actual.id))
34815
+ continue;
34816
+ if (destination.size >= limits.maxEntries)
34817
+ throw new Error("Copied context epoch item budget exceeded");
34818
+ destination.set(actual.id, actual);
34819
+ }
34820
+ if (page.nextAfter === null)
34821
+ break;
34822
+ after = page.nextAfter;
34608
34823
  }
34609
34824
  const prefixViews = /* @__PURE__ */ new Map();
34610
34825
  const prefix = async (source) => {
@@ -36595,6 +36810,7 @@ var DEFAULT_MANAGER_HISTORY_LIMITS = {
36595
36810
  maxEntries: 16384,
36596
36811
  maxSourceBytes: 64 * 1024 * 1024
36597
36812
  };
36813
+ var FORK_SOURCE_METADATA_MAX_BYTES = 64 * 1024 * 1024;
36598
36814
  async function readOwnedSessionHeader(snapshot) {
36599
36815
  const handle = await openFile(snapshot.journalPath, "r");
36600
36816
  let capturedHeader;
@@ -37122,6 +37338,19 @@ var SessionManager = class _SessionManager {
37122
37338
  readSourceHistory(read2) {
37123
37339
  return this._runHistoryRead(this._bindHistorySource((index, source, query) => createSessionHistoryReadScope(index, source, query, "source")), read2);
37124
37340
  }
37341
+ /** Read the owner-maintained own-spend projection without hydrating the source. */
37342
+ async readOwnUsageSummary() {
37343
+ this._assertMutable();
37344
+ if (!this.supportsCapturedHistoryReads())
37345
+ throw new Error("Own usage projection requires an owned native source");
37346
+ const state = this.writeState;
37347
+ return this._enqueue(state, 0, async () => {
37348
+ await state.owner.flush();
37349
+ const snapshot = state.owner.getSnapshot();
37350
+ await this._acknowledgedHistory(state, snapshot);
37351
+ return state.history.currentSourceUsage(snapshot);
37352
+ });
37353
+ }
37125
37354
  /** Complete bounded structured task reduction on one captured native branch. */
37126
37355
  async readTaskState(limits = {}) {
37127
37356
  const captured = taskStateReadLimits(limits);
@@ -38861,6 +39090,8 @@ var SessionManager = class _SessionManager {
38861
39090
  }
38862
39091
  async _captureForkInput(target, options) {
38863
39092
  const limits = { ...options.limits ?? DEFAULT_MANAGER_HISTORY_LIMITS };
39093
+ if (!Number.isSafeInteger(limits.maxEntries) || limits.maxEntries <= 0 || !Number.isSafeInteger(limits.maxSourceBytes) || limits.maxSourceBytes <= 0)
39094
+ throw new Error("Invalid fork source limits");
38864
39095
  const sourceFile = this.sessionFile;
38865
39096
  const header = JSON.parse(stringifyBoundedJson(this.getHeader(), limits.maxSourceBytes));
38866
39097
  const settings = {
@@ -38972,32 +39203,143 @@ var SessionManager = class _SessionManager {
38972
39203
  if (headerBytes >= limits.maxSourceBytes)
38973
39204
  throw new Error("Fork source byte budget exceeded");
38974
39205
  return this.readSourceHistory(async (history) => {
38975
- const materialized = await history.materialize({
38976
- ...limits,
38977
- maxSourceBytes: limits.maxSourceBytes - headerBytes
38978
- });
38979
- const entries = materialized.entries.map(({ entry, source }) => withEntryRetention(entry, source.retention, source.qualification));
38980
- const sourceEntries = materialized.entries.map(({ entry, source }) => captureEpochCopyEntry(entry, source));
38981
- const hasEpoch = sourceEntries.some((entry) => entry.kind === "compaction" && entry.qualification === "native-context-epoch");
39206
+ const metadata = /* @__PURE__ */ new Map();
39207
+ let metadataBytes = 0;
39208
+ let after = 0;
39209
+ for (; ; ) {
39210
+ const page2 = await history.page(after, 128);
39211
+ if (page2.indexedThrough < history.source.sourceSequence)
39212
+ throw new Error("Captured fork history has incomplete index coverage");
39213
+ for (const reference of page2.events) {
39214
+ const source = {
39215
+ id: reference.id,
39216
+ parentId: reference.parentId,
39217
+ kind: reference.kind,
39218
+ sequence: reference.sequence,
39219
+ revision: reference.revision,
39220
+ locator: { ...reference.locator },
39221
+ retention: reference.retention,
39222
+ qualification: reference.qualification
39223
+ };
39224
+ metadataBytes += Buffer.byteLength(JSON.stringify(source)) + 1;
39225
+ if (metadataBytes > FORK_SOURCE_METADATA_MAX_BYTES)
39226
+ throw new Error("Fork source metadata byte budget exceeded");
39227
+ metadata.set(source.id, source);
39228
+ }
39229
+ if (page2.nextAfter === null)
39230
+ break;
39231
+ after = page2.nextAfter;
39232
+ }
39233
+ const hasEpoch = [...metadata.values()].some((entry) => entry.kind === "compaction" && entry.qualification === "native-context-epoch");
39234
+ const loaded = /* @__PURE__ */ new Map();
39235
+ let sourceBytes = headerBytes;
39236
+ const load = async (id) => {
39237
+ const existing = loaded.get(id);
39238
+ if (existing)
39239
+ return existing;
39240
+ const reference = metadata.get(id);
39241
+ if (!reference)
39242
+ throw new Error("Fork selected source is unavailable");
39243
+ if (loaded.size >= limits.maxEntries)
39244
+ throw new Error("Fork entry budget exceeded");
39245
+ const remaining = limits.maxSourceBytes - sourceBytes;
39246
+ if (reference.locator.length > remaining)
39247
+ throw new Error("Fork source byte budget exceeded");
39248
+ const hydrated = await history.hydrateEntry(id, remaining);
39249
+ if (!hydrated)
39250
+ throw new Error("Fork selected source is unavailable");
39251
+ const entry = withEntryRetention(hydrated.entry, hydrated.source.retention, hydrated.source.qualification);
39252
+ loaded.set(id, entry);
39253
+ metadata.set(id, captureEpochCopyEntry(entry, hydrated.source));
39254
+ sourceBytes += reference.locator.length;
39255
+ return entry;
39256
+ };
39257
+ if ("entryId" in target && !metadata.has(target.entryId))
39258
+ throw new Error("Invalid entry ID for forking");
39259
+ const selected = "entryId" in target ? await load(target.entryId) : void 0;
39260
+ if ("entryId" in target && target.position === "before" && (selected?.type !== "message" || selected.message.role !== "user"))
39261
+ throw new Error("Invalid entry ID for forking");
39262
+ const leafId = "entryId" in target ? target.position === "at" ? selected.id : selected.parentId : target.leafId;
39263
+ const path6 = [];
39264
+ let page = await history.parentPathFrom(leafId);
39265
+ for (; ; ) {
39266
+ if (page.totalEntries > limits.maxEntries)
39267
+ throw new Error("Fork entry budget exceeded");
39268
+ for (const reference of page.events)
39269
+ path6.push(await load(reference.id));
39270
+ if (!page.nextCursor)
39271
+ break;
39272
+ page = await history.parentPathFrom(leafId, { cursor: page.nextCursor });
39273
+ }
39274
+ const copied = path6.filter((entry) => entry.type !== "label");
39275
+ const ids = new Set(copied.map((entry) => entry.id));
39276
+ if (hasEpoch) {
39277
+ for (const entry of copied) {
39278
+ if (entry.type !== "message")
39279
+ continue;
39280
+ if (entry.execution && "invocationId" in entry.execution)
39281
+ ids.add(entry.execution.invocationId);
39282
+ const updateTarget = entry.message.role === "assistant" ? { kind: "assistant-usage", targetId: entry.id } : entry.message.role === "toolResult" ? { kind: "ipython-sent-message", toolCallId: entry.message.toolCallId } : void 0;
39283
+ if (!updateTarget)
39284
+ continue;
39285
+ let after2 = 0;
39286
+ for (; ; ) {
39287
+ const updates = await history.sourceContextUpdates(updateTarget, after2);
39288
+ if (updates.indexedThrough < history.source.sourceSequence)
39289
+ throw new Error("Captured fork updates have incomplete index coverage");
39290
+ for (const reference of updates.events)
39291
+ ids.add(reference.id);
39292
+ if (updates.nextAfter === null)
39293
+ break;
39294
+ after2 = updates.nextAfter;
39295
+ }
39296
+ }
39297
+ for (const id of ids) {
39298
+ const reference = metadata.get(id);
39299
+ if (!reference)
39300
+ throw new Error("Fork related source is unavailable");
39301
+ if (reference.parentId !== null)
39302
+ ids.add(reference.parentId);
39303
+ }
39304
+ for (const id of ids)
39305
+ await load(id);
39306
+ } else {
39307
+ for (const entry of copied) {
39308
+ if (entry.type !== "message" || entry.message.role !== "assistant")
39309
+ continue;
39310
+ const latest = await history.sourceAssistantUsage(entry.id);
39311
+ if (latest)
39312
+ await load(latest.id);
39313
+ }
39314
+ }
39315
+ for (const id of ids) {
39316
+ const label = await history.sourceLabel(id);
39317
+ if (label)
39318
+ await load(label.id);
39319
+ }
39320
+ const entries = [...loaded.values()].sort((left, right) => metadata.get(left.id).sequence - metadata.get(right.id).sequence);
38982
39321
  if (!hasEpoch)
38983
39322
  applyChildUsageAttributions(entries);
38984
- return finish(entries, history, hasEpoch ? {
39323
+ const epochCopy = hasEpoch ? {
38985
39324
  sessionId: history.source.sessionId,
38986
39325
  sessionFile: history.source.sessionFile,
38987
39326
  through: history.source.sourceSequence,
38988
- entries: sourceEntries,
39327
+ entries: [...metadata.values()],
38989
39328
  retained: false
38990
- } : void 0);
39329
+ } : void 0;
39330
+ if (epochCopy)
39331
+ stringifyBoundedJson(epochCopy, FORK_SOURCE_METADATA_MAX_BYTES);
39332
+ return finish(entries, history, epochCopy);
38991
39333
  });
38992
39334
  }
38993
- async _rebuildCopiedEpoch(copied, limits) {
39335
+ async _rebuildCopiedEpoch(copied, limits, metadataMaxBytes = limits.maxSourceBytes) {
38994
39336
  if (!copied.entries.some((entry) => entry.kind === "compaction" && entry.qualification === "native-context-epoch"))
38995
39337
  return;
38996
39338
  if (!this.supportsCapturedHistoryReads())
38997
39339
  throw new Error("Copied context epochs require an owned persistent source");
38998
39340
  const sink = this.bindCompactionSink(limits);
38999
39341
  await this._runHistoryRead({ ...sink, readHistory: (read2) => sink[readCopiedEpochSource](read2) }, async (history) => {
39000
- const rebuilt = await rebuildCopiedContextEpoch(history, copied, limits);
39342
+ const rebuilt = await rebuildCopiedContextEpoch(history, copied, limits, metadataMaxBytes);
39001
39343
  if (rebuilt)
39002
39344
  await sink[appendContextEpoch](rebuilt.checkpoint, rebuilt.tokensBefore, rebuilt.summary);
39003
39345
  });
@@ -39034,7 +39376,7 @@ var SessionManager = class _SessionManager {
39034
39376
  if (input.epochCopy) {
39035
39377
  try {
39036
39378
  await next.branchTo(input.leafId ?? null);
39037
- await next._rebuildCopiedEpoch(input.epochCopy, input.limits);
39379
+ await next._rebuildCopiedEpoch(input.epochCopy, input.limits, FORK_SOURCE_METADATA_MAX_BYTES);
39038
39380
  } catch (error) {
39039
39381
  try {
39040
39382
  await next.close();
@@ -39427,13 +39769,6 @@ function parseBoundedSessionEntries(text2, maxEntries) {
39427
39769
  }
39428
39770
  return parseSessionEntries(text2);
39429
39771
  }
39430
- async function readSessionHistoryFile(inputPath, limits) {
39431
- limits = { ...limits };
39432
- const captured = await readSessionHistoryImage(inputPath, limits.maxSourceBytes);
39433
- const complete = captured.subarray(0, captured.lastIndexOf(10) + 1);
39434
- const text2 = new TextDecoder3("utf-8", { fatal: true, ignoreBOM: true }).decode(complete);
39435
- return parseBoundedSessionEntries(text2, limits.maxEntries);
39436
- }
39437
39772
  async function readExportHistory(inputPath, limits) {
39438
39773
  limits = { ...limits };
39439
39774
  const captured = await readSessionHistoryImage(inputPath, limits.maxSourceBytes);
@@ -40848,6 +41183,23 @@ var DaemonSocketPathLease = class {
40848
41183
  }
40849
41184
  }
40850
41185
  };
41186
+ async function closeDaemonServer(server, clients) {
41187
+ const closingClients = [...clients];
41188
+ for (const client of closingClients) {
41189
+ client.detachInput();
41190
+ client.socket.end();
41191
+ }
41192
+ const timeout = setTimeout(() => {
41193
+ for (const client of closingClients)
41194
+ client.socket.destroy();
41195
+ }, 1e3);
41196
+ timeout.unref();
41197
+ try {
41198
+ await new Promise((resolveClose) => server?.close(() => resolveClose()) ?? resolveClose());
41199
+ } finally {
41200
+ clearTimeout(timeout);
41201
+ }
41202
+ }
40851
41203
  function defaultDaemonSocketPath(packageDir = getPackageDir()) {
40852
41204
  if (process.platform === "win32") {
40853
41205
  return `\\\\.\\pipe\\${PRODUCT.command}-${daemonScopeId(packageDir)}`;
@@ -42842,16 +43194,43 @@ function readResidentContextTreeUsage(manager, limits = { maxEntries: 16384, max
42842
43194
  ...availabilityMaxSourceBytes === void 0 ? {} : { hasPostCompactionUsage: hasPostCompactionUsage(branch) }
42843
43195
  };
42844
43196
  }
43197
+ function isContextTreeUsageReference(reference) {
43198
+ return reference.kind === "message" && reference.authority === "assistant" || reference.kind === "compaction" || reference.kind === "branch_summary" || reference.kind === "child_usage_attributed";
43199
+ }
42845
43200
  async function readContextTreeUsage(manager, limits = { maxEntries: 16384, maxSourceBytes: 64 * 1024 * 1024 }, request, availabilityMaxSourceBytes) {
42846
43201
  if (!manager.supportsCapturedHistoryReads())
42847
43202
  return void 0;
42848
43203
  const sourceLimits = request?.limits ?? limits;
42849
43204
  const capturedLimits = { maxEntries: sourceLimits.maxEntries, maxSourceBytes: sourceLimits.maxSourceBytes };
43205
+ if (!Object.values(capturedLimits).every((value) => Number.isSafeInteger(value) && value > 0))
43206
+ throw new Error("Invalid history materialization limits");
42850
43207
  return manager.readSourceHistory((history) => {
42851
43208
  request?.retainMetadata(history.source);
42852
43209
  const reduce = async () => {
42853
- const materialized = await history.materialize(capturedLimits);
42854
- const allEntries = materialized.entries.map(({ entry }) => entry);
43210
+ const allEntries = [];
43211
+ let sourceBytes = 0;
43212
+ let after = 0;
43213
+ for (; ; ) {
43214
+ const page = await history.page(after);
43215
+ if (page.indexedThrough < history.source.sourceSequence)
43216
+ throw new Error("Captured history has incomplete index coverage");
43217
+ for (const reference of page.events) {
43218
+ if (!isContextTreeUsageReference(reference))
43219
+ continue;
43220
+ if (allEntries.length >= capturedLimits.maxEntries)
43221
+ throw new Error("History entry budget exceeded");
43222
+ if (sourceBytes + reference.locator.length > capturedLimits.maxSourceBytes)
43223
+ throw new Error("History source byte budget exceeded");
43224
+ const hydrated = await history.hydrateEntry(reference.id, capturedLimits.maxSourceBytes - sourceBytes);
43225
+ if (!hydrated)
43226
+ throw new Error("Context-tree usage entry source is unavailable");
43227
+ allEntries.push(hydrated.entry);
43228
+ sourceBytes += reference.locator.length;
43229
+ }
43230
+ if (page.nextAfter === null)
43231
+ break;
43232
+ after = page.nextAfter;
43233
+ }
42855
43234
  applyChildUsageAttributions(allEntries);
42856
43235
  const byId = new Map(allEntries.map((entry) => [entry.id, entry]));
42857
43236
  const branch = [];
@@ -42859,6 +43238,8 @@ async function readContextTreeUsage(manager, limits = { maxEntries: 16384, maxSo
42859
43238
  do {
42860
43239
  const page = await history.parentPath({ cursor });
42861
43240
  for (const reference of page.events) {
43241
+ if (!isContextTreeUsageReference(reference))
43242
+ continue;
42862
43243
  const entry = byId.get(reference.id);
42863
43244
  if (!entry)
42864
43245
  throw new Error("Context-tree parent-path entry source is unavailable");
@@ -42921,7 +43302,7 @@ function computeContextUsageFromEntries(allEntries, branch, contextWindow) {
42921
43302
  if (!hasPostCompactionUsage(branch)) {
42922
43303
  return { tokens: null, contextWindow, percent: null };
42923
43304
  }
42924
- const estimate = estimateContextTokens(buildSessionContext(allEntries).messages);
43305
+ const estimate = estimateContextTokens(buildSessionContext(allEntries, branch.at(-1)?.id ?? null).messages);
42925
43306
  if (estimate.tokens <= 0) {
42926
43307
  return void 0;
42927
43308
  }
@@ -43048,10 +43429,64 @@ function listChildSessionDirs(rlmSessionDir, request) {
43048
43429
  });
43049
43430
  return { paths, bytes };
43050
43431
  }
43432
+ async function readContextTreeProjectionFromDisk(sessionFile, request) {
43433
+ const entries = [];
43434
+ const hiddenParents = /* @__PURE__ */ new Map();
43435
+ let leafId = null;
43436
+ let hasHeader = false;
43437
+ let sourceBytes = 0;
43438
+ let metadataBytes = 0;
43439
+ try {
43440
+ await readCapturedSessionJournal(sessionFile, (record2) => {
43441
+ const value = record2.entry;
43442
+ if (!value || typeof value !== "object" || !("type" in value) || typeof value.type !== "string")
43443
+ throw new Error("Invalid session journal entry");
43444
+ const entry = value;
43445
+ if (!hasHeader) {
43446
+ if (entry.type !== "session" || typeof entry.id !== "string")
43447
+ throw new Error("Session source has no valid header");
43448
+ hasHeader = true;
43449
+ }
43450
+ if (entry.type !== "session")
43451
+ leafId = entry.id;
43452
+ if (entry.type === "request" || entry.type === "tool_intent") {
43453
+ metadataBytes += request.retainMetadata([entry.id, entry.parentId]);
43454
+ hiddenParents.set(entry.id, entry.parentId);
43455
+ return;
43456
+ }
43457
+ const bytes = record2.source?.locator.length ?? Buffer.byteLength(record2.json) + 1;
43458
+ if (sourceBytes + bytes > request.limits.maxSourceBytes)
43459
+ throw new ContextTreeLimitError("Context tree source byte budget exceeded");
43460
+ sourceBytes += bytes;
43461
+ if (entry.type === "session")
43462
+ return;
43463
+ if (entries.length >= request.limits.maxEntries)
43464
+ throw new ContextTreeLimitError("Context tree entry budget exceeded");
43465
+ entries.push(entry);
43466
+ });
43467
+ const visibleParent = (id) => {
43468
+ let remaining = hiddenParents.size;
43469
+ while (id !== null && hiddenParents.has(id)) {
43470
+ if (remaining-- === 0)
43471
+ throw new Error("Parent path lineage is unresolved");
43472
+ id = hiddenParents.get(id);
43473
+ }
43474
+ return id;
43475
+ };
43476
+ for (const entry of entries)
43477
+ entry.parentId = visibleParent(entry.parentId);
43478
+ const hasSourceLeaf = leafId !== null;
43479
+ leafId = visibleParent(leafId);
43480
+ applyChildUsageAttributions(entries);
43481
+ return { entries, leafId, hasSourceLeaf };
43482
+ } finally {
43483
+ request.releaseMetadata(metadataBytes);
43484
+ }
43485
+ }
43051
43486
  async function readContextTreeChildNodeFromDisk(childSessionDir, sessionFile, resolveContextWindow, request, identity) {
43052
- const allEntries = (await readSessionHistoryFile(sessionFile, request.limits)).filter((entry) => entry.type !== "session");
43053
- const branch = branchEntries(allEntries);
43054
- if (branch.length === 0) {
43487
+ const { entries: allEntries, leafId, hasSourceLeaf } = await readContextTreeProjectionFromDisk(sessionFile, request);
43488
+ const branch = branchEntries(allEntries, leafId);
43489
+ if (branch.length === 0 && !hasSourceLeaf) {
43055
43490
  return void 0;
43056
43491
  }
43057
43492
  const { ownUsage, totalUsage } = computeOwnAndTotalUsage(branch, allEntries);
@@ -45482,7 +45917,7 @@ async function loadExtensionModule(extensionPath) {
45482
45917
  // (file-path aliases would load a second, divergent copy of each package).
45483
45918
  // Also disable tryNative so jiti handles ALL imports (not just the entry point)
45484
45919
  // Node/dev must also share the native AI registry and implementation identities.
45485
- ...isBunBinary || isBundledCli ? { virtualModules: (await import("./bundled-modules-5JRM6P4T.js")).VIRTUAL_MODULES, tryNative: false } : {
45920
+ ...isBunBinary || isBundledCli ? { virtualModules: (await import("./bundled-modules-PEFT72QN.js")).VIRTUAL_MODULES, tryNative: false } : {
45486
45921
  alias: getAliases(),
45487
45922
  virtualModules: {
45488
45923
  "@ponythewhite/base-context-ai": src_exports,
@@ -48239,6 +48674,9 @@ var DEFAULT_FORK_MESSAGE_LIMITS = Object.freeze({
48239
48674
  async function readUserMessagesForForking(manager, limits = DEFAULT_FORK_MESSAGE_LIMITS) {
48240
48675
  const capturedLimits = { ...limits };
48241
48676
  const entries = manager.supportsCapturedHistoryReads() ? (await manager.materializeSourceHistory(capturedLimits)).entries.map(({ entry }) => entry) : manager.materializeResidentHistory(capturedLimits).entries;
48677
+ return projectUserMessages(entries);
48678
+ }
48679
+ function projectUserMessages(entries) {
48242
48680
  const result = [];
48243
48681
  for (const entry of entries) {
48244
48682
  if (entry.type !== "message" || entry.message.role !== "user")
@@ -48255,6 +48693,40 @@ async function readUserMessagesForForking(manager, limits = DEFAULT_FORK_MESSAGE
48255
48693
  }
48256
48694
  return result;
48257
48695
  }
48696
+ async function readVisibleUserMessagesForForking(manager, limits = DEFAULT_FORK_MESSAGE_LIMITS) {
48697
+ const { maxEntries, maxSourceBytes } = limits;
48698
+ if (!Number.isSafeInteger(maxEntries) || maxEntries <= 0 || !Number.isSafeInteger(maxSourceBytes) || maxSourceBytes <= 0)
48699
+ throw new Error("Invalid history materialization limits");
48700
+ if (!manager.supportsCapturedHistoryReads())
48701
+ return readUserMessagesForForking(manager, { maxEntries, maxSourceBytes });
48702
+ return manager.readSourceHistory(async (history) => {
48703
+ const entries = [];
48704
+ let sourceBytes = 0;
48705
+ let after = 0;
48706
+ for (; ; ) {
48707
+ const page = await history.page(after);
48708
+ if (page.indexedThrough < history.source.sourceSequence)
48709
+ throw new Error("Captured history has incomplete index coverage");
48710
+ for (const reference of page.events) {
48711
+ if (reference.kind !== "message" || reference.authority === "assistant" || reference.authority === "runtime")
48712
+ continue;
48713
+ if (entries.length >= maxEntries)
48714
+ throw new Error("History entry budget exceeded");
48715
+ if (sourceBytes + reference.locator.length > maxSourceBytes)
48716
+ throw new Error("History source byte budget exceeded");
48717
+ const hydrated = await history.hydrateEntry(reference.id, maxSourceBytes - sourceBytes);
48718
+ if (!hydrated)
48719
+ throw new Error("Fork message source is unavailable");
48720
+ sourceBytes += reference.locator.length;
48721
+ entries.push(hydrated.entry);
48722
+ }
48723
+ if (page.nextAfter === null)
48724
+ break;
48725
+ after = page.nextAfter;
48726
+ }
48727
+ return projectUserMessages(entries);
48728
+ });
48729
+ }
48258
48730
 
48259
48731
  // dist/core/session-jsonl-export.js
48260
48732
  import { mkdir as mkdir3, open as open4, unlink } from "node:fs/promises";
@@ -58942,7 +59414,7 @@ var AgentSession = class _AgentSession {
58942
59414
  const epochContext = getCanonicalEpochContext(messages);
58943
59415
  if (epochContext)
58944
59416
  this._contextMode = epochContext.mode;
58945
- const unbudgetedPublic = !contextEpochsEnabled && Boolean(epochContext?.toolContinuations?.length || epochContext?.taskFrameRebased || epochContext?.checkpoint);
59417
+ const unbudgetedPublic = !contextEpochsEnabled && Boolean(epochContext?.toolContinuations?.length || epochContext?.taskFrameRebased || epochContext?.checkpoint || getCanonicalViewSelectionSource(messages)?.recoveryContractRequested);
58946
59418
  const nativeSkills = Boolean(contextEpochsEnabled || epochContext?.checkpoint || unbudgetedPublic);
58947
59419
  const skillPolicy = nativeSkills ? this._nativeRecoveryEnabled() ? "enabled" : "unavailable" : void 0;
58948
59420
  if (this._baseSystemPromptOptions.nativeSkillSelection !== skillPolicy) {
@@ -58978,7 +59450,19 @@ var AgentSession = class _AgentSession {
58978
59450
  if (epochContext.toolContinuations?.length && (!candidate.publicMessages || JSON.stringify(getCanonicalEpochContext(candidate.publicMessages)?.toolContinuations) !== JSON.stringify(epochContext.toolContinuations) || candidate.projection.pendingPublicMessageGroups?.length))
58979
59451
  throw new Error("Tool continuation requires its exact public candidate before epoch ACK");
58980
59452
  assertResourceCurrent(resource);
58981
- const representation = contextEpochRepresentation(candidate.request, candidate.assessment, limits.maxSourceBytes, unbudgetedPublic, candidate.responseItemIdentity);
59453
+ let representation;
59454
+ try {
59455
+ representation = contextEpochRepresentation(candidate.request, candidate.assessment, limits.maxSourceBytes, unbudgetedPublic, candidate.responseItemIdentity);
59456
+ } catch (error) {
59457
+ if (error instanceof UnsupportedContextEpochConfigurationError && !contextEpochsEnabled && !candidate.assessment && !committed && !acknowledged && !epochContext.taskFrameRebased && !epochContext.selectedSkills?.length && !epochContext.toolContinuations?.length && !candidate.publicMessages) {
59458
+ const source = getCanonicalViewSelectionSource(messages);
59459
+ const selected = new Set(candidate.selectedUnitIds);
59460
+ if (source.recoveryContractRequested && !source.requiresEpoch && !source.pendingPublicMessageGroups?.length && this.sessionManager === epochManager && compaction.isCurrent() && JSON.stringify(candidate.source) === JSON.stringify(source.source) && candidate.selectedUnitIds.length === source.units.length && selected.size === source.units.length && source.units.every((unit) => selected.has(unit.id))) {
59461
+ return;
59462
+ }
59463
+ }
59464
+ throw error;
59465
+ }
58982
59466
  const replayContract = "replayContract" in candidate.projection && candidate.projection.replayContract === "message-groups" ? "message-groups" : "complete-context";
58983
59467
  const publicWindow = "publicWindow" in candidate.projection && candidate.projection.publicWindow === true;
58984
59468
  const selection = JSON.stringify([
@@ -62627,7 +63111,7 @@ var AgentSession = class _AgentSession {
62627
63111
  async _runPreTurnCompaction() {
62628
63112
  const lastAssistant = this._findLastAssistantMessage();
62629
63113
  if (lastAssistant)
62630
- await this._checkCompaction(lastAssistant, false, false);
63114
+ await this._checkCompaction(lastAssistant, false, false, void 0, true);
62631
63115
  }
62632
63116
  async _prepareForCommit(policy, steps) {
62633
63117
  if (policy.initialRefineBarrier === "always" || policy.initialRefineBarrier === "ifInFlight" && this._refineInFlight) {
@@ -65307,7 +65791,7 @@ ${parsed.args}` : block;
65307
65791
  }
65308
65792
  }
65309
65793
  /** A private compiled context keeps extension summary edits separate from retained source recipes. */
65310
- async _prepareCapturedCompaction(pathEntries, settings, requests, compaction, owner = this._captureCompactionOwner(), allowShortSession = false, budgetPressure = false) {
65794
+ async _prepareCapturedCompaction(pathEntries, settings, requests, compaction, owner = this._captureCompactionOwner(), allowShortSession = false, budgetPressure = false, capacity) {
65311
65795
  this._assertCompactionOwner(owner);
65312
65796
  const limits = this.settingsManager.getCanonicalContextLimits();
65313
65797
  const resource = this._captureKernelResource();
@@ -65324,10 +65808,11 @@ ${parsed.args}` : block;
65324
65808
  const context = getCanonicalEpochContext(messages);
65325
65809
  if (context.checkpoint?.includeSummary && pathEntries.at(-1)?.type === "compaction")
65326
65810
  return { preparation: void 0, maxSourceBytes: limits.maxSourceBytes };
65327
- const boundary = canonicalRecoveryBoundary(messages);
65811
+ const authorization = getRecoveryCompactionAuthorization(capacity);
65812
+ const boundary = canonicalRecoveryBoundary(messages, authorization);
65328
65813
  const preparation = budgetPressure || context.checkpoint || boundary ? prepareViewCompaction(messages, context.references.map((ref) => ref?.ref.entryId), pathEntries, settings, boundary, allowShortSession, budgetPressure) : prepareCompaction(pathEntries, settings, allowShortSession);
65329
65814
  if (preparation)
65330
- prepareRecoveryCompaction(messages, preparation.firstKeptEntryId, limits.maxSourceBytes);
65815
+ prepareRecoveryCompaction(messages, preparation.firstKeptEntryId, limits.maxSourceBytes, authorization);
65331
65816
  return {
65332
65817
  preparation,
65333
65818
  messages,
@@ -65343,7 +65828,7 @@ ${parsed.args}` : block;
65343
65828
  */
65344
65829
  async _performCompaction(options) {
65345
65830
  const { model, apiKey, headers, customInstructions, signal, thinkingLevel, requests, compaction, semanticEdges, pathEntries, settings, owner = this._captureCompactionOwner(), allowShortSession = false, budgetPressure = false } = options;
65346
- const prepared = await this._prepareCapturedCompaction(pathEntries, settings, requests, compaction, owner, allowShortSession, budgetPressure);
65831
+ const prepared = await this._prepareCapturedCompaction(pathEntries, settings, requests, compaction, owner, allowShortSession, budgetPressure, options.capacity);
65347
65832
  this._assertCompactionOwner(owner);
65348
65833
  if (prepared.resource)
65349
65834
  assertResourceCurrent(prepared.resource);
@@ -65424,7 +65909,7 @@ ${parsed.args}` : block;
65424
65909
  }
65425
65910
  this._assertCompactionOwner(owner);
65426
65911
  const result = JSON.parse(JSON.stringify({ summary, firstKeptEntryId, tokensBefore, details }));
65427
- const recovery = prepared.messages ? prepareRecoveryCompaction(prepared.messages, firstKeptEntryId, prepared.maxSourceBytes) : void 0;
65912
+ const recovery = prepared.messages ? prepareRecoveryCompaction(prepared.messages, firstKeptEntryId, prepared.maxSourceBytes, getRecoveryCompactionAuthorization(options.capacity)) : void 0;
65428
65913
  if (prepared.resource)
65429
65914
  assertResourceCurrent(prepared.resource);
65430
65915
  if (recovery) {
@@ -66047,7 +66532,30 @@ ${parsed.args}` : block;
66047
66532
  const sessionHistory = (async () => {
66048
66533
  if (residentEntries !== void 0)
66049
66534
  return residentEntries;
66050
- return (await this.sessionManager.materializeSourceHistory(limits)).entries.map(({ entry }) => entry);
66535
+ return this.sessionManager.readSourceHistory(async (history) => {
66536
+ const entries = [];
66537
+ let sourceBytes = 0;
66538
+ let after = 0;
66539
+ for (; ; ) {
66540
+ const page = await history.page(after, 128);
66541
+ if (page.indexedThrough < history.source.sourceSequence)
66542
+ throw new Error("Captured refinement history has incomplete index coverage");
66543
+ for (const reference of page.events) {
66544
+ if (reference.kind !== "custom")
66545
+ continue;
66546
+ if (entries.length >= limits.maxEntries)
66547
+ throw new Error("Refinement history entry budget exceeded");
66548
+ if (sourceBytes + reference.locator.length > limits.maxSourceBytes)
66549
+ throw new Error("Refinement history source byte budget exceeded");
66550
+ const hydrated = await hydrateCapturedHistoryEntry(reference, limits.maxSourceBytes - sourceBytes, history.readPayload);
66551
+ entries.push(hydrated.entry);
66552
+ sourceBytes += reference.locator.length;
66553
+ }
66554
+ if (page.nextAfter === null)
66555
+ return entries;
66556
+ after = page.nextAfter;
66557
+ }
66558
+ });
66051
66559
  })();
66052
66560
  const [globalResult, sessionResult] = await Promise.allSettled([globalHistory, sessionHistory]);
66053
66561
  if (globalResult.status === "rejected") {
@@ -66368,7 +66876,7 @@ ${parsed.args}` : block;
66368
66876
  return void 0;
66369
66877
  return calculateContextTokens(assistantMessage.usage);
66370
66878
  }
66371
- async _checkCompaction(assistantMessage, skipAbortedCheck = true, queueAutonomousContinuation = true, invocationOwner) {
66879
+ async _checkCompaction(assistantMessage, skipAbortedCheck = true, queueAutonomousContinuation = true, invocationOwner, beforeNextTurn = false) {
66372
66880
  if (this._compactionSetupFailure)
66373
66881
  return false;
66374
66882
  if (invocationOwner && !this._isCompactionSourceOwnerCurrent(invocationOwner))
@@ -66441,7 +66949,7 @@ ${parsed.args}` : block;
66441
66949
  if (messages.length > 0 && messages[messages.length - 1].role === "assistant") {
66442
66950
  this._removeLastAssistantFromContext();
66443
66951
  }
66444
- return await this._runAutoCompaction("overflow", true, owner);
66952
+ return await this._runAutoCompaction("overflow", true, owner, false, void 0, beforeNextTurn);
66445
66953
  }
66446
66954
  if (this._pendingRequestedCompaction !== void 0) {
66447
66955
  return await this._runAutoCompaction("requested", false, owner);
@@ -66463,7 +66971,7 @@ ${parsed.args}` : block;
66463
66971
  }
66464
66972
  if (!this._isCompactionOwnerCurrent(owner) || !this._contextOptimizationAllowed())
66465
66973
  return false;
66466
- return await this._runAutoCompaction("threshold", false, owner);
66974
+ return await this._runAutoCompaction("threshold", false, owner, false, void 0, beforeNextTurn);
66467
66975
  }
66468
66976
  return false;
66469
66977
  }
@@ -66509,7 +67017,7 @@ This compaction outcome could not be saved to session history: ${persistenceErro
66509
67017
  this._emit({ type: "message_start", message: outcomeMessage });
66510
67018
  this._emit({ type: "message_end", message: outcomeMessage });
66511
67019
  }
66512
- async _runAutoCompaction(reason, willRetry, capturedOwner, resumeInPlace = false, capacity) {
67020
+ async _runAutoCompaction(reason, willRetry, capturedOwner, resumeInPlace = false, capacity, beforeNextTurn = false) {
66513
67021
  const checkpoint = this._pendingCheckpoint;
66514
67022
  const pending = this._pendingRequestedCompaction;
66515
67023
  const owner = checkpoint?.owner ?? pending?.owner ?? capturedOwner ?? this._captureCompactionOwner();
@@ -66622,6 +67130,12 @@ This compaction outcome could not be saved to session history: ${persistenceErro
66622
67130
  if (!this._isCompactionSourceOwnerCurrent(owner))
66623
67131
  throw failure2;
66624
67132
  this._clearQueuedAutonomousContinuationsAfterSkippedThresholdCompaction(reason === "threshold" && shouldContinueAfterCompaction, queuedAutonomousContinuationsForThisCompaction);
67133
+ if (beforeNextTurn && error instanceof MissingRecoveryReplayContractError) {
67134
+ if (reason === "overflow")
67135
+ this._overflowRecovery = "idle";
67136
+ await this._endCompactionUnsuccessfully(reason, "skipped", "Compaction deferred until the next native request establishes recovery replay coverage.", { errorSeverity: "warning", customInstructions, owner });
67137
+ return false;
67138
+ }
66625
67139
  const errorMessage4 = error instanceof Error ? error.message : "compaction failed";
66626
67140
  const aborted = errorMessage4 === "Compaction cancelled" || error instanceof Error && error.name === "AbortError" || abort.signal.aborted;
66627
67141
  if (aborted) {
@@ -69385,34 +69899,13 @@ ${command}` : command;
69385
69899
  _contextWindowResolver() {
69386
69900
  return (provider, modelId) => this._modelRegistry.find(provider, modelId)?.contextWindow;
69387
69901
  }
69388
- _ownUsageMemo;
69389
69902
  // Whole-source own spend, identical to the catalog reduction at passivation.
69390
69903
  async getOwnUsageSummary() {
69391
69904
  if (!this.sessionManager.supportsCapturedHistoryReads()) {
69392
- const entries = await this.sessionManager.readEntries();
69905
+ const entries = this.sessionManager.getEntries();
69393
69906
  return sessionUsageSummaryFrom(computeOwnAndTotalUsage(entries, entries).ownUsage);
69394
69907
  }
69395
- const limits = { maxEntries: 16384, maxSourceBytes: 64 * 1024 * 1024 };
69396
- return this.sessionManager.readSourceHistory(async (history) => {
69397
- const { sessionId, sessionFile, sourceSequence } = history.source;
69398
- const memo = this._ownUsageMemo;
69399
- if (memo && memo.sessionId === sessionId && memo.sessionFile === sessionFile && memo.sourceSequence === sourceSequence && memo.count <= limits.maxEntries && memo.sourceBytes <= limits.maxSourceBytes) {
69400
- return memo.usage ? { ...memo.usage } : void 0;
69401
- }
69402
- const materialized = await history.materialize(limits);
69403
- const entries = materialized.entries.map(({ entry }) => entry);
69404
- applyChildUsageAttributions(entries);
69405
- const usage = sessionUsageSummaryFrom(computeOwnAndTotalUsage(entries, entries).ownUsage);
69406
- this._ownUsageMemo = {
69407
- sessionId,
69408
- sessionFile,
69409
- sourceSequence,
69410
- count: entries.length,
69411
- sourceBytes: materialized.sourceBytes,
69412
- usage
69413
- };
69414
- return usage ? { ...usage } : void 0;
69415
- });
69908
+ return this.sessionManager.readOwnUsageSummary();
69416
69909
  }
69417
69910
  /**
69418
69911
  * Build the agent context overview for /context: this session as the root
@@ -70013,7 +70506,7 @@ import { resolve as resolve15 } from "node:path";
70013
70506
  var BASE_CONTEXT_BUILD_ID_ENV = "BASE_CONTEXT_BUILD_ID";
70014
70507
  var BASE_CONTEXT_LAUNCHER_PATH_ENV = "BASE_CONTEXT_LAUNCHER_PATH";
70015
70508
  function bundledBuildId() {
70016
- return false ? void 0 : "v1.0.9";
70509
+ return false ? void 0 : "v1.0.10-1-g67d926ccc";
70017
70510
  }
70018
70511
  function getDaemonRuntimeIdentity(environment = process.env) {
70019
70512
  const entrypoint = process.argv[1];
@@ -70805,6 +71298,7 @@ export {
70805
71298
  maybeRunOwnedSessionWorkerFrontend,
70806
71299
  installOwnedSessionWorkerOwnerWatch,
70807
71300
  closeOwnedSessionWorkerOwnerWatch,
71301
+ closeDaemonServer,
70808
71302
  defaultDaemonSocketPath,
70809
71303
  acquireDaemonSocketPathLease,
70810
71304
  prepareDaemonSocketPath,
@@ -70839,7 +71333,7 @@ export {
70839
71333
  passivatedWorkerRosterEntry,
70840
71334
  sessionSummaryFromRosterEntry,
70841
71335
  AgentRoster,
70842
- readUserMessagesForForking,
71336
+ readVisibleUserMessagesForForking,
70843
71337
  SERPER_CREDENTIAL_ID,
70844
71338
  SERPER_CREDENTIAL_NAME,
70845
71339
  PromptAdmissionCancelledError,