@retaw106/mmc-oc 2.0.0 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (100) hide show
  1. package/dist/cli.js +1 -1
  2. package/dist/config/live-run-config.d.ts.map +1 -1
  3. package/dist/config-init.js +1 -1
  4. package/dist/{context-95zkksn3.js → context-vhcstgs3.js} +1812 -814
  5. package/dist/features/magic-context/memory/types.d.ts +1 -0
  6. package/dist/features/magic-context/memory/types.d.ts.map +1 -1
  7. package/dist/features/magic-context/overflow-detection.d.ts.map +1 -1
  8. package/dist/features/magic-context/session-project-storage.d.ts +8 -2
  9. package/dist/features/magic-context/session-project-storage.d.ts.map +1 -1
  10. package/dist/features/magic-context/storage-meta-persisted.d.ts +12 -0
  11. package/dist/features/magic-context/storage-meta-persisted.d.ts.map +1 -1
  12. package/dist/features/magic-context/storage-meta-session.d.ts +6 -0
  13. package/dist/features/magic-context/storage-meta-session.d.ts.map +1 -1
  14. package/dist/features/magic-context/storage-tags.d.ts +2 -2
  15. package/dist/features/magic-context/storage-tags.d.ts.map +1 -1
  16. package/dist/features/magic-context/transform-decision-log.d.ts +3 -1
  17. package/dist/features/magic-context/transform-decision-log.d.ts.map +1 -1
  18. package/dist/hooks/magic-context/compartment-runner-types.d.ts +3 -5
  19. package/dist/hooks/magic-context/compartment-runner-types.d.ts.map +1 -1
  20. package/dist/hooks/magic-context/compartment-runner.d.ts +2 -1
  21. package/dist/hooks/magic-context/compartment-runner.d.ts.map +1 -1
  22. package/dist/hooks/magic-context/compartment-trigger.d.ts.map +1 -1
  23. package/dist/hooks/magic-context/final-wire-token-estimate.d.ts +2 -0
  24. package/dist/hooks/magic-context/final-wire-token-estimate.d.ts.map +1 -1
  25. package/dist/hooks/magic-context/historian-drain-gate.d.ts +11 -0
  26. package/dist/hooks/magic-context/historian-drain-gate.d.ts.map +1 -0
  27. package/dist/hooks/magic-context/lkg-replay-fit.d.ts +118 -0
  28. package/dist/hooks/magic-context/lkg-replay-fit.d.ts.map +1 -0
  29. package/dist/hooks/magic-context/lkg-replay.d.ts +2 -0
  30. package/dist/hooks/magic-context/lkg-replay.d.ts.map +1 -1
  31. package/dist/hooks/magic-context/protected-tail-boundary.d.ts.map +1 -1
  32. package/dist/hooks/magic-context/read-session-true-raw-tokens.d.ts.map +1 -1
  33. package/dist/hooks/magic-context/transform-compartment-phase.d.ts +3 -28
  34. package/dist/hooks/magic-context/transform-compartment-phase.d.ts.map +1 -1
  35. package/dist/hooks/magic-context/transform.d.ts.map +1 -1
  36. package/dist/{index-fg34g6a5.js → index-1j34a56j.js} +49 -8
  37. package/dist/{index-5pg0acf7.js → index-amycb7b1.js} +1 -1
  38. package/dist/{index-1mjhzqq7.js → index-dr0gepzw.js} +86 -23
  39. package/dist/{index-xt7y10x6.js → index-n0vnzz6h.js} +1 -1
  40. package/dist/{index-977gxfz0.js → index-ramz5kkm.js} +1 -1
  41. package/dist/{index-bdt9my9y.js → index-wtb9hzk6.js} +130 -50
  42. package/dist/index.js +1 -1
  43. package/dist/{message-time-backfill-zfernxbw.js → message-time-backfill-phrwp2fz.js} +1 -1
  44. package/dist/{read-session-chunk-hp464g13.js → read-session-chunk-82rkqa8j.js} +3 -3
  45. package/dist/{recomp-orchestrator-3qxeqwb9.js → recomp-orchestrator-vc5dkzy2.js} +6 -6
  46. package/dist/{send-session-notification-y29y9fsr.js → send-session-notification-rnc4nrsr.js} +3 -3
  47. package/dist/shared/harness.d.ts +1 -1
  48. package/dist/shared/harness.d.ts.map +1 -1
  49. package/dist/shared/historian-tool-expansions.d.ts +1 -1
  50. package/dist/shared/historian-tool-expansions.d.ts.map +1 -1
  51. package/dist/shared/historian-tool-template.d.ts +2 -2
  52. package/dist/shared/historian-tool-template.d.ts.map +1 -1
  53. package/dist/shared/model-resolution.d.ts +1 -1
  54. package/dist/shared/model-resolution.d.ts.map +1 -1
  55. package/dist/shared/sqlite.d.ts +14 -1
  56. package/dist/shared/sqlite.d.ts.map +1 -1
  57. package/dist/tools/ctx-expand/render.d.ts.map +1 -1
  58. package/dist/v2/fold/host-media.d.ts +4 -0
  59. package/dist/v2/fold/host-media.d.ts.map +1 -1
  60. package/dist/v2/fold/memory-cache.d.ts +70 -0
  61. package/dist/v2/fold/memory-cache.d.ts.map +1 -0
  62. package/dist/v2/fold/native-codec.d.ts +10 -0
  63. package/dist/v2/fold/native-codec.d.ts.map +1 -0
  64. package/dist/v2/fold/native-replay.d.ts +58 -0
  65. package/dist/v2/fold/native-replay.d.ts.map +1 -0
  66. package/dist/v2/fold/policy.d.ts +24 -0
  67. package/dist/v2/fold/policy.d.ts.map +1 -0
  68. package/dist/v2/hidden-child-record.d.ts +6 -0
  69. package/dist/v2/hidden-child-record.d.ts.map +1 -1
  70. package/dist/v2/hidden-completion.d.ts.map +1 -1
  71. package/dist/v2/hooks/context.d.ts.map +1 -1
  72. package/dist/v2/hooks/types.d.ts +6 -0
  73. package/dist/v2/hooks/types.d.ts.map +1 -1
  74. package/dist/v2/server.js +1763 -528
  75. package/dist/v2/store-reader.d.ts +16 -0
  76. package/dist/v2/store-reader.d.ts.map +1 -1
  77. package/dist/web/api.d.ts.map +1 -1
  78. package/dist/web/fixtures.d.ts +41 -0
  79. package/dist/web/fixtures.d.ts.map +1 -1
  80. package/dist/web/host-opencode.d.ts +9 -0
  81. package/dist/web/host-opencode.d.ts.map +1 -1
  82. package/dist/web/main.js +705 -53
  83. package/dist/web/memories.d.ts +18 -2
  84. package/dist/web/memories.d.ts.map +1 -1
  85. package/dist/web/ui/panel.css +2 -0
  86. package/dist/web/ui/panel.js +135 -77
  87. package/dist/web/views.d.ts +50 -9
  88. package/dist/web/views.d.ts.map +1 -1
  89. package/dist/{wrapup-orchestrator-wgb2nd19.js → wrapup-orchestrator-x9xamts2.js} +6 -6
  90. package/package.json +1 -1
  91. package/src/config/live-run-config.ts +28 -0
  92. package/src/shared/harness.ts +1 -1
  93. package/src/shared/historian-tool-defaults.json +6 -6
  94. package/src/shared/historian-tool-expansions.ts +65 -8
  95. package/src/shared/historian-tool-preview-defaults.json +13 -0
  96. package/src/shared/historian-tool-template.ts +48 -14
  97. package/src/shared/model-resolution.ts +1 -1
  98. package/src/shared/sqlite-acquisition-routing.test.ts +18 -0
  99. package/src/shared/sqlite.ts +100 -15
  100. package/src/shared/write-transaction-attribution.test.ts +2 -2
@@ -102,6 +102,7 @@ import {
102
102
  resolveCompactionModeRecord,
103
103
  getCompactionModeRecord,
104
104
  setCompactionModeRecord,
105
+ getProtectedTailDrainBudgetSkip,
105
106
  clearPersistedReasoningWatermark,
106
107
  getEmergencyInputSample,
107
108
  setEmergencyDropSample,
@@ -246,13 +247,15 @@ import {
246
247
  hasCompleteCachedM0M1,
247
248
  injectM0M1,
248
249
  RECOVERY_NO_HEAD_LIMIT,
250
+ deriveProtectedTailTokenTarget,
251
+ selectPerRunCap,
249
252
  resolveOpenCodeProtectedTailBoundary,
250
253
  getRawHistoryEligibility,
251
254
  hasRunnableCompartmentWindow,
252
255
  recordHighPressureNoEligibleHead,
253
256
  getActiveCompartmentRun,
254
257
  startCompartmentAgent
255
- } from "./index-bdt9my9y.js";
258
+ } from "./index-wtb9hzk6.js";
256
259
  import {
257
260
  getHarness,
258
261
  getDataDir,
@@ -386,6 +389,7 @@ import {
386
389
  getMeasuredToolDefinitionTokens,
387
390
  describeFinalWireTail,
388
391
  estimateMessageTokens,
392
+ wireContentBytes,
389
393
  createFinalWireUsageTracker,
390
394
  estimateFinalWireInputTokens,
391
395
  modelAcceptsEmptyContent,
@@ -412,7 +416,7 @@ import {
412
416
  primeInMemoryTailRawMessageCache2,
413
417
  readRawSessionMessageById2,
414
418
  readSessionChunk2
415
- } from "./index-1mjhzqq7.js";
419
+ } from "./index-dr0gepzw.js";
416
420
  import {
417
421
  getSqliteMemoryStats,
418
422
  withSqliteBackgroundWriter,
@@ -421,7 +425,7 @@ import {
421
425
  isTransientSqliteError,
422
426
  SqliteAcquisitionBusyError,
423
427
  withAsyncPrivilegedWriter
424
- } from "./index-fg34g6a5.js";
428
+ } from "./index-1j34a56j.js";
425
429
  import {
426
430
  canonicalModelIdentity,
427
431
  piModelRefToCanonical,
@@ -435,7 +439,7 @@ import {
435
439
  withReadOnlySessionDb,
436
440
  getMessageTimesFromOpenCodeDb,
437
441
  findLastAssistantModelFromOpenCodeDb
438
- } from "./index-977gxfz0.js";
442
+ } from "./index-ramz5kkm.js";
439
443
  import {
440
444
  registerNotificationSink2,
441
445
  pushNotification2,
@@ -448,7 +452,7 @@ import {
448
452
  getErrorMessage,
449
453
  flushIgnoredMessages2,
450
454
  sendStatusNotification2
451
- } from "./index-5pg0acf7.js";
455
+ } from "./index-amycb7b1.js";
452
456
  import {
453
457
  resolveHistorianModel2
454
458
  } from "./index-z2g20msd.js";
@@ -3034,6 +3038,10 @@ function sampleLiveConfig(boot, fresh) {
3034
3038
  let value = fresh;
3035
3039
  for (const part of parts)
3036
3040
  value = value?.[part];
3041
+ if (value === undefined) {
3042
+ removeLeaf(result, parts);
3043
+ continue;
3044
+ }
3037
3045
  let target = result;
3038
3046
  for (const part of parts.slice(0, -1)) {
3039
3047
  const child = target[part];
@@ -3047,6 +3055,26 @@ function sampleLiveConfig(boot, fresh) {
3047
3055
  }
3048
3056
  return result;
3049
3057
  }
3058
+ function removeLeaf(root, parts) {
3059
+ const parents = parts.slice(0, -1);
3060
+ let node = root;
3061
+ for (const part of parents) {
3062
+ const child = node[part];
3063
+ if (!child || typeof child !== "object" || Array.isArray(child))
3064
+ return;
3065
+ node = child;
3066
+ }
3067
+ const leaf = parts.at(-1);
3068
+ if (leaf === undefined || !Object.hasOwn(node, leaf))
3069
+ return;
3070
+ let target = root;
3071
+ for (const part of parents) {
3072
+ const copy = { ...target[part] };
3073
+ target[part] = copy;
3074
+ target = copy;
3075
+ }
3076
+ delete target[leaf];
3077
+ }
3050
3078
  function changedLiveKeys(previous, next) {
3051
3079
  const at = (config, path) => path.split(".").reduce((node, part) => node?.[part], config);
3052
3080
  return LIVE_RELOAD_CONFIG_PATHS.filter((path) => JSON.stringify(at(previous, path)) !== JSON.stringify(at(next, path)));
@@ -8599,6 +8627,9 @@ function createToolExecuteAfterHook(args) {
8599
8627
  };
8600
8628
  }
8601
8629
 
8630
+ // src/hooks/magic-context/lkg-measured-request.ts
8631
+ import { createHash as createHash3 } from "node:crypto";
8632
+
8602
8633
  // src/shared/provider-response-completion.ts
8603
8634
  function providerResponseFailed(input) {
8604
8635
  if (input.error !== undefined && input.error !== null && input.error !== "")
@@ -8620,9 +8651,49 @@ function lkgProviderInputTotal(tokens) {
8620
8651
  const counts = [tokens?.input ?? 0, tokens?.cache?.read ?? 0, tokens?.cache?.write ?? 0];
8621
8652
  return counts.every((count) => Number.isSafeInteger(count) && count >= 0) ? counts.reduce((sum, count) => sum + count, 0) : Number.NaN;
8622
8653
  }
8654
+ function identity(slot) {
8655
+ return createHash3("sha256").update(JSON.stringify([
8656
+ slot.capturedAt,
8657
+ slot.captureSequence,
8658
+ slot.rowVersion,
8659
+ slot.modelKey,
8660
+ slot.providerKey,
8661
+ slot.inputIdSeq,
8662
+ slot.inputContentDigests
8663
+ ])).update(slot.jsonPrefix).digest("hex");
8664
+ }
8665
+ function envelope(modelKey, systemPromptTokens, agentName) {
8666
+ const slash = modelKey.indexOf("/");
8667
+ return JSON.stringify([
8668
+ modelKey,
8669
+ systemPromptTokens,
8670
+ agentName,
8671
+ getMeasuredToolDefinitionTokens(modelKey.slice(0, slash), modelKey.slice(slash + 1), agentName)
8672
+ ]);
8673
+ }
8623
8674
  function beginV2LkgRequest(sessionId, modelKey, previousResponseId) {
8624
8675
  requests.set(sessionId, { kind: "v2", previousResponseId, startedAt: Date.now(), modelKey });
8625
8676
  }
8677
+ function claimLkgRequestIdentity(sessionId) {
8678
+ const request = requests.get(sessionId);
8679
+ if (!request || claimedRequests.has(request))
8680
+ return;
8681
+ claimedRequests.add(request);
8682
+ return request;
8683
+ }
8684
+ function noteCapturedLkgRequest(args) {
8685
+ const request = args.request;
8686
+ if (!request || request.modelKey !== args.slot.modelKey) {
8687
+ captures.delete(args.sessionId);
8688
+ return;
8689
+ }
8690
+ captures.set(args.sessionId, {
8691
+ request,
8692
+ slot: identity(args.slot),
8693
+ prefixCount: JSON.parse(args.slot.jsonPrefix).length,
8694
+ envelope: envelope(request.modelKey, args.systemPromptTokens, args.agentName)
8695
+ });
8696
+ }
8626
8697
  function noteLkgProviderResponse(args) {
8627
8698
  if (!args.responseId || !args.modelKey)
8628
8699
  return;
@@ -8650,7 +8721,7 @@ function noteLkgProviderResponse(args) {
8650
8721
  }
8651
8722
 
8652
8723
  // src/hooks/magic-context/lkg-persist.ts
8653
- import { createHash as createHash3 } from "node:crypto";
8724
+ import { createHash as createHash4 } from "node:crypto";
8654
8725
  function parseStringArray(value) {
8655
8726
  if (typeof value !== "string")
8656
8727
  return null;
@@ -8764,7 +8835,7 @@ function rememberFingerprint(db, sessionId, fingerprint) {
8764
8835
  saved.set(sessionId, fingerprint);
8765
8836
  }
8766
8837
  function slotFingerprint(slot) {
8767
- return createHash3("sha256").update(JSON.stringify([
8838
+ return createHash4("sha256").update(JSON.stringify([
8768
8839
  slot.jsonPrefix,
8769
8840
  slot.inputIdSeq,
8770
8841
  slot.inputContentDigests,
@@ -9210,7 +9281,7 @@ function captureLkgSlot(args) {
9210
9281
  if (!built)
9211
9282
  return false;
9212
9283
  const modelKeys = canonicalLkgModelKeys(args.modelKey, args.providerKey);
9213
- return captureSlot(args.sessionId, {
9284
+ const slot = {
9214
9285
  jsonPrefix: built.jsonPrefix,
9215
9286
  inputIdSeq: built.inputIdSeq,
9216
9287
  inputContentDigests: built.inputContentDigests,
@@ -9218,7 +9289,17 @@ function captureLkgSlot(args) {
9218
9289
  modelKey: modelKeys.modelKey,
9219
9290
  providerKey: modelKeys.providerKey,
9220
9291
  capturedAt: args.capturedAt ?? Date.now()
9221
- });
9292
+ };
9293
+ const captured = captureSlot(args.sessionId, slot);
9294
+ if (captured)
9295
+ noteCapturedLkgRequest({
9296
+ sessionId: args.sessionId,
9297
+ slot,
9298
+ request: built.anchorIndex === args.input.length - 1 ? claimLkgRequestIdentity(args.sessionId) : undefined,
9299
+ systemPromptTokens: args.systemPromptTokens ?? 0,
9300
+ agentName: args.agentName
9301
+ });
9302
+ return captured;
9222
9303
  }
9223
9304
  function entryIdsAreValid(slot, entryIds) {
9224
9305
  if (slot.inputIdSeq.length === 0 || entryIds.length < slot.inputIdSeq.length)
@@ -9444,6 +9525,45 @@ function replayLkg(args) {
9444
9525
  return { ok: true, messages: replayed };
9445
9526
  }
9446
9527
 
9528
+ // src/hooks/magic-context/lkg-replay-fit.ts
9529
+ var RAW_FALLBACK_BYTES_PER_CONTEXT_TOKEN = 4;
9530
+ function lkgReplayLimit(args) {
9531
+ const { db, sessionId, model } = args;
9532
+ const trusted = model ? resolveTrustedContextLimit(model.providerID, model.modelID, { db, sessionID: sessionId }) : undefined;
9533
+ if (trusted !== undefined && trusted > 0)
9534
+ return trusted;
9535
+ const detected = getOverflowState(db, sessionId, args.modelKey).detectedContextLimit;
9536
+ return detected > 0 ? detected : undefined;
9537
+ }
9538
+ function measureLkgReplay(args) {
9539
+ const baseline = args.measuredInputTokens ?? 0;
9540
+ const tailLimit = Math.max(0, args.limit - baseline);
9541
+ const proxy = wireContentBytes(args.messages, tailLimit * RAW_FALLBACK_BYTES_PER_CONTEXT_TOKEN, RAW_FALLBACK_BYTES_PER_CONTEXT_TOKEN);
9542
+ const skipped = { proxy, estimatorRan: false, trusted: false };
9543
+ if (proxy === null)
9544
+ return { fit: "unproven", tokens: null, ...skipped };
9545
+ const proxyTokens = baseline + Math.ceil(proxy.bytes / RAW_FALLBACK_BYTES_PER_CONTEXT_TOKEN);
9546
+ if (proxy.aborted || proxyTokens > args.limit) {
9547
+ return { fit: "over", tokens: null, proxyTokens, ...skipped };
9548
+ }
9549
+ let estimate;
9550
+ try {
9551
+ estimate = args.estimate();
9552
+ } catch {
9553
+ return { fit: "unproven", tokens: null, ...skipped };
9554
+ }
9555
+ const seen = { proxy, estimatorRan: true, trusted: estimate.trusted };
9556
+ const tokens = baseline + estimate.tokens;
9557
+ if (!estimate.trusted || !Number.isFinite(tokens) || tokens <= 0 || estimate.tokens < 0) {
9558
+ return {
9559
+ fit: "unproven",
9560
+ tokens: Number.isFinite(estimate.tokens) ? estimate.tokens : null,
9561
+ ...seen
9562
+ };
9563
+ }
9564
+ return tokens > args.limit ? { fit: "over", tokens, proxyTokens, ...seen } : { fit: "under", tokens, ...seen };
9565
+ }
9566
+
9447
9567
  // src/hooks/magic-context/storage-busy-refusal.ts
9448
9568
  var STORAGE_BUSY_MESSAGE = "Magic Context's database is busy (another process held it too long); send your message again.";
9449
9569
  function describeStorageBusyCause(cause) {
@@ -9471,7 +9591,7 @@ class StorageBusyRefusalError extends Error {
9471
9591
  }
9472
9592
 
9473
9593
  // src/hooks/magic-context/system-prompt-hash.ts
9474
- import { createHash as createHash4 } from "node:crypto";
9594
+ import { createHash as createHash5 } from "node:crypto";
9475
9595
 
9476
9596
  // src/agents/magic-context-prompt.ts
9477
9597
  var LONG_TERM_PARTNER_FRAME = `### You are the user's long-term partner on this project — not a one-off hire
@@ -9712,7 +9832,7 @@ function createSystemPromptHashHandler(deps) {
9712
9832
  }
9713
9833
  const stickyDate = stickyDateBySession.get(sessionId);
9714
9834
  const stableCandidate = currentDate && stickyDate && currentDate !== stickyDate ? liveSystemContent.replace(DATE_PATTERN_ALL, stickyDate) : liveSystemContent;
9715
- const stableCandidateHash = createHash4("md5").update(promptSurfaceHashMaterial(stableCandidate, promptSurface.preset)).digest("hex");
9835
+ const stableCandidateHash = createHash5("md5").update(promptSurfaceHashMaterial(stableCandidate, promptSurface.preset)).digest("hex");
9716
9836
  const contentOrPresetChanged = hasPersistedHash && stableCandidateHash !== previousHash;
9717
9837
  const dateMayAdvance = isCacheBusting || idleCacheExpired || contentOrPresetChanged;
9718
9838
  if (currentDate && !stickyDate) {
@@ -9732,7 +9852,7 @@ function createSystemPromptHashHandler(deps) {
9732
9852
  `);
9733
9853
  if (!availability.frozen || !modelKey)
9734
9854
  return;
9735
- const currentHash = createHash4("md5").update(promptSurfaceHashMaterial(systemContent, promptSurface.preset)).digest("hex");
9855
+ const currentHash = createHash5("md5").update(promptSurfaceHashMaterial(systemContent, promptSurface.preset)).digest("hex");
9736
9856
  if (!sessionMetaEarly) {
9737
9857
  return;
9738
9858
  }
@@ -9947,10 +10067,14 @@ function recordSessionProjectIdentity(db, sessionId, projectPath) {
9947
10067
  return;
9948
10068
  const harness = getHarness();
9949
10069
  const now = Date.now();
10070
+ let previousProjectPath;
9950
10071
  db.transaction(() => {
10072
+ const existing = db.prepare("SELECT project_path FROM session_projects WHERE session_id = ? AND harness = ?").get(sessionId, harness);
10073
+ previousProjectPath = existing?.project_path;
9951
10074
  getUpsertSessionProjectStatement(db).run(sessionId, harness, projectPath, now);
9952
10075
  getRepairSessionChunkProjectStatement(db).run(projectPath, sessionId, harness, projectPath, SESSION_CHUNK_REPAIR_BATCH_SIZE);
9953
10076
  }).immediate();
10077
+ return previousProjectPath === projectPath ? undefined : { previousProjectPath, projectPath };
9954
10078
  }
9955
10079
  function hasRecordedSessionProjectIdentity(db, sessionId) {
9956
10080
  const row = db.prepare("SELECT 1 AS found FROM session_projects WHERE session_id = ? AND harness = ?").get(sessionId, getHarness());
@@ -10384,6 +10508,29 @@ function commitCompactionModeRecord(db, sessionId, record) {
10384
10508
  setCompactionModeRecord(db, sessionId, record);
10385
10509
  }
10386
10510
 
10511
+ // src/hooks/magic-context/historian-drain-gate.ts
10512
+ var loggedWindows = new WeakMap;
10513
+ function isHistorianDrainBudgetSpent(args) {
10514
+ const target = deriveProtectedTailTokenTarget(args);
10515
+ const state = getProtectedTailDrainBudgetSkip({
10516
+ ...args,
10517
+ usable: target.usable,
10518
+ perRunCap: selectPerRunCap({ ...args, N: target.N })
10519
+ });
10520
+ if (!state)
10521
+ return false;
10522
+ let windows = loggedWindows.get(args.db);
10523
+ if (!windows) {
10524
+ windows = new Map;
10525
+ loggedWindows.set(args.db, windows);
10526
+ }
10527
+ if (windows.get(args.sessionId) !== state.resetsAt) {
10528
+ windows.set(args.sessionId, state.resetsAt);
10529
+ sessionLog(args.sessionId, `historian skip: internal drain budget spent (${state.spentTokens}/${state.limitTokens} tokens); next eligible at ${new Date(state.nextEligibleAt).toISOString()}`);
10530
+ }
10531
+ return true;
10532
+ }
10533
+
10387
10534
  // src/features/magic-context/storage-reasoning-removal.ts
10388
10535
  var NAMESPACE2 = "reasoningRemoval";
10389
10536
  var BACKUP_NAMESPACE = "reasoningRemovalBackup";
@@ -11375,7 +11522,7 @@ function getUnsummarizedTailInfo(db, sessionId, triggerBudget, usage, executeThr
11375
11522
  taggerFloor,
11376
11523
  storedTotalsExcludeToolTags
11377
11524
  });
11378
- const hasProtectedEligibleHead = boundary.offset < boundary.protectedTailStart;
11525
+ const hasProtectedEligibleHead = boundary.offset < Math.min(boundary.protectedTailStart, boundary.eligibleEndOrdinal);
11379
11526
  if (!hasProtectedEligibleHead) {
11380
11527
  return {
11381
11528
  ...TAIL_INFO_DEFAULTS,
@@ -11387,7 +11534,7 @@ function getUnsummarizedTailInfo(db, sessionId, triggerBudget, usage, executeThr
11387
11534
  const seed = sessionDecisionCalibration(db, sessionId);
11388
11535
  const sourceRatio = Math.max(seed.proseRatio, seed.toolsRatio);
11389
11536
  const scanBudget = Math.floor(Math.max(MIN_PROACTIVE_TAIL_TOKEN_ESTIMATE, triggerBudget * TAIL_SIZE_TRIGGER_MULTIPLIER) / sourceRatio);
11390
- const chunk = readSessionChunk2(sessionId, scanBudget, rawEligibility.offset, boundary.protectedTailStart);
11537
+ const chunk = readSessionChunk2(sessionId, scanBudget, rawEligibility.offset, boundary.eligibleEndOrdinal);
11391
11538
  const isMeaningful = chunk.hasMore || boundary.trueRawEligibleTokens >= MIN_PROACTIVE_TAIL_TOKEN_ESTIMATE || Math.ceil(chunk.tokenEstimate * sourceRatio) >= MIN_PROACTIVE_TAIL_TOKEN_ESTIMATE || chunk.messageCount >= MIN_PROACTIVE_TAIL_MESSAGE_COUNT;
11392
11539
  return {
11393
11540
  nextStartOrdinal: rawEligibility.offset,
@@ -11414,6 +11561,14 @@ function checkCompartmentTrigger(db, sessionId, sessionMeta, usage, _previousPer
11414
11561
  sessionLog(sessionId, `compartment trigger: skipped — historian already in progress (usage=${usage.percentage.toFixed(1)}%)`);
11415
11562
  return { shouldFire: false };
11416
11563
  }
11564
+ if (isHistorianDrainBudgetSpent({
11565
+ db,
11566
+ sessionId,
11567
+ usagePercentage: usage.percentage,
11568
+ contextLimit: resolveBoundaryContextLimit(usage, contextLimit),
11569
+ executeThresholdPercentage
11570
+ }))
11571
+ return { shouldFire: false };
11417
11572
  const lazyInMemoryTail = typeof inMemoryTail === "function" ? inMemoryTail : undefined;
11418
11573
  let resolvedInMemoryTail = typeof inMemoryTail === "function" ? undefined : inMemoryTail;
11419
11574
  if (resolvedInMemoryTail) {
@@ -11927,8 +12082,24 @@ function historianJoinFailClosedMessage(input) {
11927
12082
  return `historian did not complete within ${seconds} s: ${reason}`;
11928
12083
  }
11929
12084
  function runCompartmentPhase(args) {
12085
+ if (args.historianRunnable !== false && !args.compactionOff && args.canRunCompartments && !getActiveCompartmentRun(args.sessionId) && (args.sessionMeta.compartmentInProgress || args.contextUsage.percentage >= BLOCK_UNTIL_DONE_PERCENTAGE) && isHistorianDrainBudgetSpent({
12086
+ db: args.db,
12087
+ sessionId: args.sessionId,
12088
+ contextLimit: args.boundaryContextLimit,
12089
+ executeThresholdPercentage: args.boundaryExecuteThresholdPercentage,
12090
+ usagePercentage: args.boundaryUsage.percentage
12091
+ })) {
12092
+ if (args.sessionMeta.compartmentInProgress) {
12093
+ updateSessionMeta(args.db, args.sessionId, { compartmentInProgress: false });
12094
+ }
12095
+ return runCompartmentPhaseImpl({
12096
+ ...args,
12097
+ canRunCompartments: false,
12098
+ sessionMeta: { compartmentInProgress: false }
12099
+ });
12100
+ }
11930
12101
  const historianRunnable = args.historianRunnable !== false;
11931
- const willReadRawHistory = historianRunnable && !args.compactionOff && args.canRunCompartments && getActiveCompartmentRun(args.sessionId) === undefined && (args.sessionMeta.compartmentInProgress || args.contextUsage.percentage >= BLOCK_UNTIL_DONE_PERCENTAGE);
12102
+ const willReadRawHistory = historianRunnable && !args.compactionOff && args.canRunCompartments && getActiveCompartmentRun(args.sessionId) === undefined && args.contextUsage.percentage >= BLOCK_UNTIL_DONE_PERCENTAGE;
11932
12103
  if (!willReadRawHistory) {
11933
12104
  return runCompartmentPhaseImpl(args);
11934
12105
  }
@@ -12054,7 +12225,7 @@ async function runCompartmentPhaseImpl(args) {
12054
12225
  compartmentInProgress = false;
12055
12226
  }
12056
12227
  if (historianRunnable && args.canRunCompartments && args.sessionMeta.compartmentInProgress && !getActiveCompartmentRun(args.sessionId)) {
12057
- if (!hasEligibleHistoryForCompartment()) {
12228
+ if (args.contextUsage.percentage >= BLOCK_UNTIL_DONE_PERCENTAGE && !hasEligibleHistoryForCompartment()) {
12058
12229
  sessionLog(args.sessionId, `transform: skipping compartment start, no eligible history before protected tail (beyond ${lastObservedCompartmentEnd})`);
12059
12230
  updateSessionMeta(args.db, args.sessionId, { compartmentInProgress: false });
12060
12231
  compartmentInProgress = false;
@@ -12071,7 +12242,7 @@ async function runCompartmentPhaseImpl(args) {
12071
12242
  db: args.db,
12072
12243
  sessionId: args.sessionId,
12073
12244
  historianChunkTokens: args.historianChunkTokens,
12074
- boundarySnapshot: getBoundarySnapshotForCompartment() ?? undefined,
12245
+ boundarySnapshot: args.preResolvedBoundarySnapshot,
12075
12246
  currentContextLimit: args.boundaryContextLimit,
12076
12247
  historyBudgetTokens: args.historyBudgetTokens,
12077
12248
  historianTimeoutMs: args.historianTimeoutMs,
@@ -12089,6 +12260,12 @@ async function runCompartmentPhaseImpl(args) {
12089
12260
  autoPromote: args.autoPromote,
12090
12261
  onCompartmentStatePublished: args.onCompartmentStatePublished,
12091
12262
  preserveInjectionCacheUntilConsumed: true
12263
+ }, undefined, () => {
12264
+ const snapshot = getBoundarySnapshotForCompartment();
12265
+ if (snapshot && hasRunnableCompartmentWindow(snapshot))
12266
+ return snapshot;
12267
+ sessionLog(args.sessionId, `transform: skipping compartment start, no eligible history before protected tail (beyond ${lastObservedCompartmentEnd})`);
12268
+ return null;
12092
12269
  });
12093
12270
  compartmentInProgress = true;
12094
12271
  }
@@ -15833,19 +16010,33 @@ function createTransform(deps) {
15833
16010
  if (false) {}
15834
16011
  return false;
15835
16012
  };
15836
- const startRecoveryRun = () => {
15837
- const scale = emergencyUsagePercentageEarly >= 95 ? 0.25 : 0.5;
15838
- let boundarySnapshot = getRunnableBoundaryForCompartment();
15839
- if (!boundarySnapshot || !hasRunnableCompartmentWindow(boundarySnapshot)) {
15840
- boundarySnapshot = getRunnableBoundaryForCompartment(scale);
15841
- }
15842
- if (false) {}
15843
- if (!canRunCompartments || !deps.client && !deps.hiddenCompletionExecutor || !boundarySnapshot || !hasRunnableCompartmentWindow(boundarySnapshot)) {
16013
+ const startRecoveryRun = (onReady) => {
16014
+ if (isHistorianDrainBudgetSpent({
16015
+ db,
16016
+ sessionId,
16017
+ contextLimit: boundaryContextLimit,
16018
+ executeThresholdPercentage: boundaryExecuteThreshold,
16019
+ usagePercentage: boundaryUsageForProtectedTail.percentage
16020
+ }))
15844
16021
  return false;
15845
- }
15846
- if (getActiveCompartmentRun(sessionId)) {
16022
+ if (!canRunCompartments || !deps.client && !deps.hiddenCompletionExecutor || getActiveCompartmentRun(sessionId))
16023
+ return false;
16024
+ const prepareRecoveryBoundary = () => {
16025
+ const scale = emergencyUsagePercentageEarly >= 95 ? 0.25 : 0.5;
16026
+ let boundarySnapshot = getRunnableBoundaryForCompartment();
16027
+ if (!boundarySnapshot || !hasRunnableCompartmentWindow(boundarySnapshot)) {
16028
+ boundarySnapshot = getRunnableBoundaryForCompartment(scale);
16029
+ }
16030
+ if (false) {}
16031
+ if (!boundarySnapshot || !hasRunnableCompartmentWindow(boundarySnapshot))
16032
+ return null;
16033
+ onReady?.();
16034
+ return boundarySnapshot;
16035
+ };
16036
+ const urgent = emergencyUsagePercentageEarly >= 95;
16037
+ const boundarySnapshot = urgent ? prepareRecoveryBoundary() : undefined;
16038
+ if (urgent && !boundarySnapshot)
15847
16039
  return false;
15848
- }
15849
16040
  updateSessionMeta(db, sessionId, { compartmentInProgress: true });
15850
16041
  startCompartmentAgent({
15851
16042
  client: deps.client,
@@ -15854,7 +16045,7 @@ function createTransform(deps) {
15854
16045
  db,
15855
16046
  sessionId,
15856
16047
  historianChunkTokens: historianRun?.chunkTokens ?? deps.getHistorianChunkTokens?.() ?? 20000,
15857
- boundarySnapshot,
16048
+ boundarySnapshot: boundarySnapshot ?? undefined,
15858
16049
  currentContextLimit: boundaryContextLimit,
15859
16050
  historyBudgetTokens,
15860
16051
  historianTimeoutMs: historianRun?.timeoutMs ?? deps.historianTimeoutMs,
@@ -15874,7 +16065,7 @@ function createTransform(deps) {
15874
16065
  deferredHistoryRefreshSessions.add(sid);
15875
16066
  deferredMaterializationSessions.add(sid);
15876
16067
  }
15877
- });
16068
+ }, undefined, urgent ? undefined : prepareRecoveryBoundary);
15878
16069
  return true;
15879
16070
  };
15880
16071
  if (fullFeatureMode && !compactionOff && historianFailureState.failureCount > 0 && emergencyUsagePercentageEarly >= 95 && !recoveryNoHeadEscapeActive) {
@@ -15888,13 +16079,15 @@ function createTransform(deps) {
15888
16079
  sessionLog(sessionId, "transform: emergency recovery remains armed — no complete eligible head before protected tail");
15889
16080
  }
15890
16081
  sessionLog(sessionId, `EMERGENCY: historian recovery requested at ${emergencyPercentage}%, failures: ${historianFailureState.failureCount}`);
15891
- } else if (fullFeatureMode && !compactionOff && isFirstTransformPassForSession && historianFailureState.failureCount > 0 && getEligibleHistoryForCompartment() && startRecoveryRun()) {
15892
- sessionLog(sessionId, `transform: historian recovery triggered on session load after ${historianFailureState.failureCount} failure(s)`);
15893
- if (deps.client) {
15894
- withoutSqliteTransformPass(() => sendStatusNotification2(deps.client, sessionId, `## Historian recovery
16082
+ } else if (fullFeatureMode && !compactionOff && isFirstTransformPassForSession && historianFailureState.failureCount > 0) {
16083
+ startRecoveryRun(() => {
16084
+ sessionLog(sessionId, `transform: historian recovery triggered on session load after ${historianFailureState.failureCount} failure(s)`);
16085
+ if (deps.client) {
16086
+ withoutSqliteTransformPass(() => sendStatusNotification2(deps.client, sessionId, `## Historian recovery
15895
16087
 
15896
16088
  Historian previously failed ${historianFailureState.failureCount} time(s), so Magic Context is retrying history comparting immediately after restart.`, notificationParams));
15897
- }
16089
+ }
16090
+ });
15898
16091
  }
15899
16092
  logTransformTiming(sessionId, "emergencyRecoveryBlock", tFirstPass);
15900
16093
  const memoryProjectDirectory = compartmentDirectory || process.cwd();
@@ -16441,7 +16634,9 @@ Historian previously failed ${historianFailureState.failureCount} time(s), so Ma
16441
16634
  input: lkgInput,
16442
16635
  output: messages,
16443
16636
  modelKey,
16444
- providerKey
16637
+ providerKey,
16638
+ systemPromptTokens: sessionMeta.systemPromptTokens,
16639
+ agentName: notificationParams?.agent
16445
16640
  });
16446
16641
  if (captured) {
16447
16642
  const capturedSlot = getInMemorySlot(sessionId);
@@ -17855,8 +18050,8 @@ function registerRpcHandlers(rpcServer, args) {
17855
18050
  const db = readDatabase();
17856
18051
  if (!db)
17857
18052
  return { ok: false, error: "db unavailable" };
17858
- const { runManagedRecomp } = await import("./recomp-orchestrator-3qxeqwb9.js");
17859
- const { sendIgnoredMessage } = await import("./send-session-notification-y29y9fsr.js");
18053
+ const { runManagedRecomp } = await import("./recomp-orchestrator-vc5dkzy2.js");
18054
+ const { sendIgnoredMessage } = await import("./send-session-notification-rnc4nrsr.js");
17860
18055
  log(`[rpc] recomp requested for session ${sessionId}`);
17861
18056
  if (!args.client && !args.hiddenCompletionExecutor) {
17862
18057
  return {
@@ -17905,7 +18100,7 @@ function registerRpcHandlers(rpcServer, args) {
17905
18100
  const db = readDatabase();
17906
18101
  if (!db)
17907
18102
  return { ok: false, error: "db unavailable" };
17908
- const { runManagedWrapup } = await import("./wrapup-orchestrator-wgb2nd19.js");
18103
+ const { runManagedWrapup } = await import("./wrapup-orchestrator-x9xamts2.js");
17909
18104
  const model = liveSessionState.liveModelBySession.get(sessionId);
17910
18105
  const contextLimit = model ? resolveContextLimit(model.providerID, model.modelID, { db, sessionID: sessionId }) : 128000;
17911
18106
  const ctx = {
@@ -18646,7 +18841,8 @@ function hostUsesMediaAssets() {
18646
18841
  schemaUsesAssets.set(messageClass, uses);
18647
18842
  return uses;
18648
18843
  }
18649
- function decodeThroughHostSchema(source) {
18844
+ function decodeThroughHostSchema(encoded) {
18845
+ const source = encoded.source;
18650
18846
  const messageClass = rememberedMessageClass;
18651
18847
  if (!messageClass)
18652
18848
  return "no host message class seen";
@@ -18666,7 +18862,7 @@ function decodeThroughHostSchema(source) {
18666
18862
  const run = decode?.run;
18667
18863
  if (typeof run !== "function")
18668
18864
  return "host media schema has no decode transformation";
18669
- const result = run.call(decode, { _tag: "Some", value: { source } }, {});
18865
+ const result = run.call(decode, { _tag: "Some", value: encoded }, {});
18670
18866
  const option = result?._tag === "Success" ? result.value : undefined;
18671
18867
  const asset = option?._tag === "Some" ? option.value : undefined;
18672
18868
  if (!isClassInstance(asset) || asset.source !== source)
@@ -18674,18 +18870,30 @@ function decodeThroughHostSchema(source) {
18674
18870
  return asset;
18675
18871
  }
18676
18872
  function hostMediaAsset(data, mediaType) {
18677
- const source = { type: "base64", data, mediaType };
18873
+ return hostMediaFromEncoded({ source: { type: "base64", data, mediaType } });
18874
+ }
18875
+ function hostMediaFromEncoded(value) {
18876
+ if (!isRecord3(value.source))
18877
+ return "missing Media.Asset source";
18878
+ const encoded = structuredClone(value);
18879
+ if (encoded.source.type === "bytes") {
18880
+ if (typeof encoded.source.data !== "string")
18881
+ return "bytes media has no JSON codec payload";
18882
+ encoded.source.data = new Uint8Array(Buffer.from(encoded.source.data, "base64"));
18883
+ }
18884
+ if (!["bytes", "base64", "url", "ref"].includes(String(encoded.source.type)))
18885
+ return "unknown Media.Asset source";
18678
18886
  let first = "no Media.Asset seen in this process";
18679
18887
  if (rememberedAssetClass) {
18680
18888
  try {
18681
- return new rememberedAssetClass({ source });
18889
+ return new rememberedAssetClass(encoded);
18682
18890
  } catch (error) {
18683
18891
  first = `remembered asset class threw: ${String(error)}`;
18684
18892
  }
18685
18893
  }
18686
18894
  let second;
18687
18895
  try {
18688
- const decoded = decodeThroughHostSchema(source);
18896
+ const decoded = decodeThroughHostSchema(encoded);
18689
18897
  if (typeof decoded !== "string")
18690
18898
  return decoded;
18691
18899
  second = decoded;
@@ -18703,9 +18911,12 @@ var v2CompactionMarkerStrategy = {
18703
18911
  reconcile: () => false
18704
18912
  };
18705
18913
 
18914
+ // src/v2/fold/memory-cache.ts
18915
+ import { randomUUID as randomUUID2 } from "node:crypto";
18916
+
18706
18917
  // src/v2/fold/owner.ts
18707
- import { createHash as createHash5 } from "node:crypto";
18708
- var foldDigest = (value) => createHash5("sha256").update(value).digest("hex");
18918
+ import { createHash as createHash6 } from "node:crypto";
18919
+ var foldDigest = (value) => createHash6("sha256").update(value).digest("hex");
18709
18920
 
18710
18921
  class FoldOwner {
18711
18922
  storage;
@@ -18785,78 +18996,693 @@ class FoldOwner {
18785
18996
  }
18786
18997
  }
18787
18998
 
18788
- // src/v2/fold/restore.ts
18789
- import { fileURLToPath as fileURLToPath2 } from "node:url";
18999
+ // src/v2/fold/memory-cache.ts
19000
+ var DEFAULT_NATIVE_FOLD_BUDGET = Object.freeze({
19001
+ maxSessionBytes: 16 * 1024 * 1024,
19002
+ maxSessions: 16
19003
+ });
19004
+ var stringBytes = (value) => (value?.length ?? 0) * 2;
19005
+
19006
+ class NativeFoldCache {
19007
+ resolveDB;
19008
+ sourceID = randomUUID2();
19009
+ tails = new Map;
19010
+ nativeRows = new Map;
19011
+ admissions = new Map;
19012
+ retention = new Map;
19013
+ evictionListeners = new Set;
19014
+ budget;
19015
+ constructor(resolveDB, budget = DEFAULT_NATIVE_FOLD_BUDGET) {
19016
+ this.resolveDB = resolveDB;
19017
+ if (!Number.isSafeInteger(budget.maxSessionBytes) || budget.maxSessionBytes < 1 || !Number.isSafeInteger(budget.maxSessions) || budget.maxSessions < 1)
19018
+ throw new Error("Native fold cache budgets must be positive integers");
19019
+ this.budget = { ...budget };
19020
+ }
19021
+ onEvict(listener) {
19022
+ this.evictionListeners.add(listener);
19023
+ }
19024
+ touch(sessionID) {
19025
+ const state = this.retention.get(sessionID) ?? { active: 0, bytes: 0, replayBytes: 0 };
19026
+ this.retention.delete(sessionID);
19027
+ this.retention.set(sessionID, state);
19028
+ return state;
19029
+ }
19030
+ hold(sessionID) {
19031
+ const state = this.touch(sessionID);
19032
+ state.active++;
19033
+ return () => {
19034
+ state.active--;
19035
+ this.enforceBudget();
19036
+ };
19037
+ }
19038
+ accountReplay(sessionID, bytes) {
19039
+ this.touch(sessionID).replayBytes = bytes;
19040
+ this.recount(sessionID);
19041
+ }
19042
+ usage() {
19043
+ return {
19044
+ sessions: this.retention.size,
19045
+ bytes: [...this.retention.values()].reduce((total, state) => total + state.bytes, 0)
19046
+ };
19047
+ }
19048
+ recount(sessionID) {
19049
+ const state = this.touch(sessionID);
19050
+ let bytes = 256 + stringBytes(sessionID) + state.replayBytes;
19051
+ const tail = this.tails.get(sessionID);
19052
+ if (tail)
19053
+ bytes += 128 + stringBytes(tail.data) + stringBytes(tail.digest);
19054
+ for (const row of this.nativeRows.get(sessionID)?.values() ?? [])
19055
+ bytes += 256 + stringBytes(row.id) + stringBytes(row.type) + stringBytes(row.data) + stringBytes(row.digest);
19056
+ for (const row of this.admissions.get(sessionID)?.values() ?? [])
19057
+ bytes += 256 + stringBytes(row.admission_id) + stringBytes(row.status) + stringBytes(row.owner_token) + stringBytes(row.data) + stringBytes(row.payload) + stringBytes(row.digest);
19058
+ state.bytes = bytes;
19059
+ this.enforceBudget();
19060
+ }
19061
+ enforceBudget() {
19062
+ for (const [id, state] of this.retention)
19063
+ if (!state.active && state.bytes > this.budget.maxSessionBytes)
19064
+ this.evict(id);
19065
+ for (const [id, state] of this.retention) {
19066
+ if (this.retention.size <= this.budget.maxSessions)
19067
+ break;
19068
+ if (!state.active)
19069
+ this.evict(id);
19070
+ }
19071
+ }
19072
+ evict(sessionID) {
19073
+ this.tails.delete(sessionID);
19074
+ this.nativeRows.delete(sessionID);
19075
+ this.admissions.delete(sessionID);
19076
+ this.retention.delete(sessionID);
19077
+ for (const listener of this.evictionListeners)
19078
+ listener(sessionID);
19079
+ }
19080
+ get db() {
19081
+ return this.resolveDB();
19082
+ }
19083
+ tail(sessionID) {
19084
+ const record = this.tails.get(sessionID);
19085
+ if (record)
19086
+ this.touch(sessionID);
19087
+ return record && { ...record };
19088
+ }
19089
+ async saveTail(sessionID, data, rows) {
19090
+ this.tails.set(sessionID, {
19091
+ revision: (this.tails.get(sessionID)?.revision ?? -1) + 1,
19092
+ data,
19093
+ digest: foldDigest(data)
19094
+ });
19095
+ const kept = this.nativeRows.get(sessionID) ?? new Map;
19096
+ for (const row of rows)
19097
+ kept.set(row.id, Object.freeze({ ...row, revision: (kept.get(row.id)?.revision ?? -1) + 1 }));
19098
+ this.nativeRows.set(sessionID, kept);
19099
+ this.recount(sessionID);
19100
+ }
19101
+ replaceRows(sessionID, through, rows, after = -1) {
19102
+ const kept = this.nativeRows.get(sessionID) ?? new Map;
19103
+ for (const [id, row] of kept)
19104
+ if (row.seq > after && row.seq <= through)
19105
+ kept.delete(id);
19106
+ for (const row of rows)
19107
+ kept.set(row.id, Object.freeze({ ...row, revision: 0 }));
19108
+ this.nativeRows.set(sessionID, kept);
19109
+ this.recount(sessionID);
19110
+ }
19111
+ truncate(sessionID, through) {
19112
+ const kept = this.nativeRows.get(sessionID);
19113
+ if (kept) {
19114
+ for (const [id, row] of kept)
19115
+ if (row.seq > through)
19116
+ kept.delete(id);
19117
+ }
19118
+ if (kept)
19119
+ this.recount(sessionID);
19120
+ }
19121
+ sequenceForID(sessionID, id) {
19122
+ return this.nativeRows.get(sessionID)?.get(id)?.seq;
19123
+ }
19124
+ containsRows(sessionID, ids) {
19125
+ const kept = this.nativeRows.get(sessionID);
19126
+ return ids.every((id) => kept?.has(id));
19127
+ }
19128
+ rows(sessionID, after, through) {
19129
+ if (this.retention.has(sessionID))
19130
+ this.touch(sessionID);
19131
+ return [...this.nativeRows.get(sessionID)?.values() ?? []].filter((row) => row.seq > after && row.seq <= through).sort((a, b) => a.seq - b.seq).map((row) => ({ ...row }));
19132
+ }
19133
+ admission(sessionID, id) {
19134
+ const record = this.admissions.get(sessionID)?.get(id);
19135
+ if (record)
19136
+ this.touch(sessionID);
19137
+ return record && { ...record };
19138
+ }
19139
+ put(sessionID, id, record) {
19140
+ const kept = this.admissions.get(sessionID) ?? new Map;
19141
+ kept.set(id, Object.freeze({ ...record }));
19142
+ this.admissions.set(sessionID, kept);
19143
+ this.recount(sessionID);
19144
+ }
19145
+ async supply(sessionID, id, payload) {
19146
+ const old = this.admission(sessionID, id);
19147
+ this.put(sessionID, id, {
19148
+ admission_id: id,
19149
+ revision: (old?.revision ?? -1) + 1,
19150
+ status: old?.status ?? "supplied",
19151
+ owner_token: old?.owner_token ?? null,
19152
+ data: old?.data ?? "{}",
19153
+ payload,
19154
+ digest: foldDigest(payload),
19155
+ logged_at: old?.logged_at ?? null
19156
+ });
19157
+ }
19158
+ latestAttempt(sessionID) {
19159
+ const record = [...this.admissions.get(sessionID)?.values() ?? []].reverse().find((row) => JSON.parse(row.data).after !== undefined);
19160
+ return record && { ...record };
19161
+ }
19162
+ async claim(sessionID, id, data, owner, _now) {
19163
+ const old = this.admission(sessionID, id);
19164
+ if (old?.owner_token || old?.logged_at !== null && old?.logged_at !== undefined)
19165
+ return false;
19166
+ this.put(sessionID, id, {
19167
+ admission_id: id,
19168
+ revision: 0,
19169
+ status: "pending",
19170
+ owner_token: owner,
19171
+ data,
19172
+ payload: old?.payload ?? null,
19173
+ digest: old?.digest ?? null,
19174
+ logged_at: null
19175
+ });
19176
+ return true;
19177
+ }
19178
+ async finish(sessionID, id, owner, status, now) {
19179
+ const old = this.admission(sessionID, id);
19180
+ if (!old || old.owner_token !== owner || old.status !== "pending")
19181
+ return false;
19182
+ this.put(sessionID, id, { ...old, status, owner_token: null, logged_at: now });
19183
+ return true;
19184
+ }
19185
+ async forget(sessionID) {
19186
+ this.evict(sessionID);
19187
+ }
19188
+ }
19189
+ function nativeFoldCache(db, budget) {
19190
+ return new NativeFoldCache(typeof db === "function" ? db : () => db, budget);
19191
+ }
18790
19192
 
18791
- // src/v2/hooks/storage-notice.ts
18792
- var STORAGE_NOTICE_PREFIX = "[Magic Context storage notice] ";
18793
- function formatStorageRefusalNotice(reason) {
18794
- return `${STORAGE_NOTICE_PREFIX}This turn was not sent to the model. ${formatFailClosedBlockingSummary(reason)}`;
19193
+ // src/v2/tool-result.ts
19194
+ function isToolError(part) {
19195
+ const result = part.result;
19196
+ return part.resultType === "error" || result?.type === "error" || result !== null && typeof result === "object" && "error" in result;
18795
19197
  }
18796
- function formatStorageRecoveryNotice(hiddenWorkRecovered) {
18797
- return hiddenWorkRecovered ? `${STORAGE_NOTICE_PREFIX}Magic Context storage is available again and turns are sent to the model. The historian and dreamer are running again. Restart OpenCode to enable Magic Context's tools.` : `${STORAGE_NOTICE_PREFIX}Magic Context storage is available again and turns are sent to the model. Restart OpenCode to enable Magic Context's tools, historian and dreamer.`;
19198
+ function toolErrorText(result) {
19199
+ const value = result.value === undefined ? result : result.value;
19200
+ return typeof value === "string" ? value : JSON.stringify(value);
18798
19201
  }
18799
- function isStorageNoticeText(text) {
18800
- return typeof text === "string" && text.startsWith(STORAGE_NOTICE_PREFIX);
19202
+ function toolStateContent(state) {
19203
+ if (typeof state.output === "string")
19204
+ return state.output;
19205
+ if (state.status === "error")
19206
+ return toolErrorText({ error: state.error, content: state.content ?? [] });
19207
+ if (typeof state.content === "string")
19208
+ return state.content;
19209
+ if (!Array.isArray(state.content))
19210
+ return "";
19211
+ return state.content.map((part) => {
19212
+ if (typeof part === "string")
19213
+ return part;
19214
+ if (!part || typeof part !== "object")
19215
+ return "";
19216
+ const value = part;
19217
+ if (typeof value.text === "string")
19218
+ return value.text;
19219
+ if (typeof value.value === "string")
19220
+ return value.value;
19221
+ return "";
19222
+ }).filter(Boolean).join(`
19223
+ `);
18801
19224
  }
18802
- function hasStorageNoticeShape(message) {
18803
- if (message.role !== "user" || typeof message.id !== "string")
18804
- return false;
18805
- if (message.content.length !== 1)
19225
+
19226
+ // src/v2/hooks/payload.ts
19227
+ var HEAD_IDS = ["__magic_context_v2_m0__", "__magic_context_v2_m1__"];
19228
+ var HOST_CONTENT_TYPES = new Set([
19229
+ "text",
19230
+ "media",
19231
+ "tool-call",
19232
+ "tool-result",
19233
+ "reasoning",
19234
+ "compaction",
19235
+ "effort"
19236
+ ]);
19237
+ function rejectContentPart(message, part, reason) {
19238
+ const type = typeof part.type === "string" ? part.type : "<missing>";
19239
+ const text = `v2 context omitted a content part the host would reject: type=${type} message=${String(message.info.id ?? "<head>")} reason=${reason}`;
19240
+ if (typeof message.info.sessionID === "string")
19241
+ sessionLog(message.info.sessionID, text);
19242
+ else
19243
+ log(text);
19244
+ }
19245
+ function isHostInstance(value) {
19246
+ if (!value || typeof value !== "object" || Array.isArray(value))
18806
19247
  return false;
18807
- const part = message.content[0];
18808
- return part?.type === "text" && isStorageNoticeText(part.text);
19248
+ const prototype = Object.getPrototypeOf(value);
19249
+ return prototype !== Object.prototype && prototype !== null;
18809
19250
  }
18810
- async function dropStorageNotices(messages, isAdmittedSynthetic) {
18811
- const drop = new Set;
18812
- for (const message of messages) {
18813
- if (!hasStorageNoticeShape(message))
18814
- continue;
18815
- if (await isAdmittedSynthetic(message.id))
18816
- drop.add(message);
18817
- }
18818
- if (drop.size === 0)
18819
- return 0;
18820
- const kept = messages.filter((message) => !drop.has(message));
18821
- messages.splice(0, messages.length, ...kept);
18822
- return drop.size;
19251
+ function containsHostInstance(value) {
19252
+ if (isHostInstance(value))
19253
+ return true;
19254
+ if (Array.isArray(value))
19255
+ return value.some(containsHostInstance);
19256
+ if (value && typeof value === "object")
19257
+ return Object.values(value).some(containsHostInstance);
19258
+ return false;
18823
19259
  }
18824
-
18825
- // src/v2/fold/restore.ts
18826
- function unavailableAttachmentNote(name, mediaType) {
18827
- return `[Attachment ${name ? `"${name}" ` : ""}(${mediaType}) is not available in this restored history]`;
19260
+ function clonePreservingInstances(value) {
19261
+ if (isHostInstance(value))
19262
+ return value;
19263
+ if (Array.isArray(value))
19264
+ return value.map(clonePreservingInstances);
19265
+ if (value && typeof value === "object") {
19266
+ const copy = {};
19267
+ for (const [key, entry] of Object.entries(value))
19268
+ copy[key] = clonePreservingInstances(entry);
19269
+ return copy;
19270
+ }
19271
+ return value;
18828
19272
  }
18829
- var imageMimes = new Set(["image/png", "image/jpeg", "image/gif", "image/webp"]);
18830
- function attachmentParts(files, rowID, media) {
18831
- const seen = new Map;
18832
- return files.flatMap((file) => {
18833
- if (imageMimes.has(file.mime) && file.source.type === "inline" && file.mention?.text) {
18834
- const key = JSON.stringify([
18835
- file.mime,
18836
- file.name ?? null,
18837
- file.description ?? null,
18838
- file.mention.text
18839
- ]);
18840
- const payloads = seen.get(key) ?? new Set;
18841
- if (payloads.has(file.data))
18842
- return [];
18843
- payloads.add(file.data);
18844
- seen.set(key, payloads);
19273
+ function contentKey(value) {
19274
+ const plain = (entry) => {
19275
+ if (ArrayBuffer.isView(entry)) {
19276
+ return {
19277
+ bytes: Buffer.from(entry.buffer, entry.byteOffset, entry.byteLength).toString("base64")
19278
+ };
18845
19279
  }
18846
- const uri = file.source.type === "uri" ? file.source.uri : undefined;
18847
- const location = uri?.startsWith("file:") ? fileURLToPath2(uri) : undefined;
18848
- if (file.mime === "text/plain" || file.mime === "application/x-directory") {
18849
- const directory = file.mime === "application/x-directory";
18850
- return [
18851
- {
18852
- type: "text",
18853
- text: `
18854
-
18855
- ${[
18856
- directory ? `Attached directory: ${location ?? file.name ?? uri ?? "directory"}` : `Attached file: ${file.name ?? uri ?? "inline attachment"}`,
18857
- file.description === undefined ? undefined : `Description: ${file.description}`,
18858
- directory && !file.data.length ? undefined : "",
18859
- directory && !file.data.length ? undefined : Buffer.from(file.data, "base64").toString("utf8")
19280
+ if (Array.isArray(entry))
19281
+ return entry.map(plain);
19282
+ if (entry && typeof entry === "object") {
19283
+ return Object.fromEntries(Object.entries(entry).map(([key, nested]) => [key, plain(nested)]));
19284
+ }
19285
+ return entry;
19286
+ };
19287
+ return JSON.stringify(plain(value));
19288
+ }
19289
+ function fileContentValue(result) {
19290
+ const value = result?.value;
19291
+ if (result?.type !== "content" || !Array.isArray(value))
19292
+ return;
19293
+ return value.some((item) => item?.type === "file") ? value : undefined;
19294
+ }
19295
+ function contentValueText(value) {
19296
+ return value.filter((item) => item?.type === "text" && typeof item.text === "string").map((item) => item.text).join(`
19297
+ `);
19298
+ }
19299
+ function contentValueAttachments(value) {
19300
+ return value.filter((item) => item?.type === "file").map((item) => ({
19301
+ type: "file",
19302
+ mime: item.mime,
19303
+ url: item.uri,
19304
+ ...typeof item.name === "string" ? { filename: item.name } : {}
19305
+ }));
19306
+ }
19307
+ function rebuildFileContent(value, output) {
19308
+ if (isDroppedToolOutput(output))
19309
+ return { type: "text", value: output };
19310
+ const rebuilt = [];
19311
+ let placed = false;
19312
+ for (const item of value) {
19313
+ if (item?.type !== "text") {
19314
+ rebuilt.push(item);
19315
+ continue;
19316
+ }
19317
+ if (placed)
19318
+ continue;
19319
+ placed = true;
19320
+ rebuilt.push({ ...item, text: output });
19321
+ }
19322
+ if (!placed && output)
19323
+ rebuilt.unshift({ type: "text", text: output });
19324
+ return { type: "content", value: rebuilt };
19325
+ }
19326
+ function adaptPayload(draft, admittedIDs = new Set) {
19327
+ const existingHeads = new Map(draft.messages.filter((m) => HEAD_IDS.some((id) => m.id === id)).map((m) => [m.id, m]));
19328
+ const source = draft.messages.filter((m) => !existingHeads.has(m.id));
19329
+ const results = new Map;
19330
+ const hostParts = new Map;
19331
+ const hostPartTypes = new Set;
19332
+ for (const message of source) {
19333
+ for (const part of message.content) {
19334
+ if (part.type !== "tool-call" && part.type !== "tool-result" && part.type !== "tool" && containsHostInstance(part)) {
19335
+ const key = contentKey(part);
19336
+ if (!hostParts.has(key))
19337
+ hostParts.set(key, part);
19338
+ hostPartTypes.add(part.type);
19339
+ }
19340
+ if (part.type === "tool-result" && typeof part.id === "string") {
19341
+ const queue = results.get(part.id) ?? [];
19342
+ queue.push({ part, message });
19343
+ results.set(part.id, queue);
19344
+ }
19345
+ }
19346
+ }
19347
+ const paired = new Set;
19348
+ const bridges = new Map;
19349
+ const originals = new Map;
19350
+ const bridgesByMessageID = new Map;
19351
+ const bridgesByCarrier = new Map;
19352
+ const originalsByID = new Map;
19353
+ const bridgesFor = (message) => typeof message.info.id === "string" ? bridgesByMessageID.get(message.info.id) : bridgesByCarrier.get(message);
19354
+ const nativeTool = (call, result) => {
19355
+ const hostResult = result?.part.result;
19356
+ const failed = result !== undefined && isToolError(result.part);
19357
+ const value = hostResult?.value;
19358
+ const files = fileContentValue(hostResult);
19359
+ const output = failed && hostResult ? toolErrorText(hostResult) : files ? contentValueText(files) : typeof value === "string" ? value : value === undefined ? "" : JSON.stringify(value);
19360
+ const part = {
19361
+ type: "tool",
19362
+ callID: call?.id ?? result?.part.id,
19363
+ tool: call?.name ?? result?.part.name,
19364
+ state: {
19365
+ input: structuredClone(call?.input ?? {}),
19366
+ status: failed ? "error" : result ? "completed" : "running",
19367
+ ...result ? { output } : {},
19368
+ ...result && (call?.name ?? result.part.name) === "question" ? { metadata: { userAnswer: true } } : {},
19369
+ ...files ? { attachments: contentValueAttachments(files) } : {}
19370
+ }
19371
+ };
19372
+ bridges.set(part, {
19373
+ call,
19374
+ result: result?.part,
19375
+ resultMessage: result?.message,
19376
+ output,
19377
+ files
19378
+ });
19379
+ if (result)
19380
+ paired.add(result.part);
19381
+ return part;
19382
+ };
19383
+ const convertedTool = (source) => {
19384
+ const sourceState = source.state && typeof source.state === "object" ? source.state : {};
19385
+ const output = toolStateContent(sourceState);
19386
+ const { content: _content, ...projectedState } = structuredClone(sourceState);
19387
+ const part = {
19388
+ type: "tool",
19389
+ callID: source.callID ?? source.id,
19390
+ tool: source.tool ?? source.name,
19391
+ state: { ...projectedState, output }
19392
+ };
19393
+ bridges.set(part, { native: source, output });
19394
+ return part;
19395
+ };
19396
+ const callParts = new Map;
19397
+ for (const message of source) {
19398
+ for (const part of message.content) {
19399
+ if (part.type === "tool-call") {
19400
+ callParts.set(part, nativeTool(part, results.get(String(part.id))?.shift()));
19401
+ } else if (part.type === "tool") {
19402
+ callParts.set(part, convertedTool(part));
19403
+ }
19404
+ }
19405
+ }
19406
+ const messages = [];
19407
+ for (const message of source) {
19408
+ const parts = [];
19409
+ for (const content of message.content) {
19410
+ if (paired.has(content))
19411
+ continue;
19412
+ const part = callParts.get(content) ?? (content.type === "tool-result" ? nativeTool(undefined, { part: content, message }) : clonePreservingInstances(content));
19413
+ if (message.id && admittedIDs.has(message.id))
19414
+ part.synthetic = true;
19415
+ parts.push(part);
19416
+ }
19417
+ if (!parts.length && message.content.length)
19418
+ continue;
19419
+ const byCallID = new Map;
19420
+ for (const part of parts) {
19421
+ const bridge = bridges.get(part);
19422
+ if (bridge && typeof part.callID === "string")
19423
+ byCallID.set(part.callID, bridge);
19424
+ }
19425
+ if (typeof message.id === "string") {
19426
+ bridgesByMessageID.set(message.id, byCallID);
19427
+ originalsByID.set(message.id, message);
19428
+ }
19429
+ const mapped = {
19430
+ info: {
19431
+ id: message.id,
19432
+ sessionID: draft.sessionID,
19433
+ role: message.role,
19434
+ ...{
19435
+ providerID: draft.model.providerID,
19436
+ modelID: draft.model.id,
19437
+ agent: draft.agent
19438
+ }
19439
+ },
19440
+ parts
19441
+ };
19442
+ originals.set(mapped, message);
19443
+ if (typeof message.id !== "string")
19444
+ bridgesByCarrier.set(mapped, byCallID);
19445
+ messages.push(mapped);
19446
+ }
19447
+ return {
19448
+ messages,
19449
+ commit() {
19450
+ let head = 0;
19451
+ const rendered = [];
19452
+ for (const message of messages) {
19453
+ const original = originals.get(message) ?? (typeof message.info.id === "string" ? originalsByID.get(message.info.id) : undefined);
19454
+ const id = message.info.syntheticHead ? HEAD_IDS[head++] : original?.id;
19455
+ const content = [];
19456
+ const following = [];
19457
+ for (const candidate of message.parts) {
19458
+ const part = candidate;
19459
+ const bridge = bridges.get(part) ?? (part.type === "tool" && typeof part.callID === "string" ? bridgesFor(message)?.get(part.callID) : undefined);
19460
+ if (!bridge) {
19461
+ if (part.type === "tool") {
19462
+ const state = part.state;
19463
+ if (typeof part.callID !== "string" || typeof part.tool !== "string" || !state || typeof state !== "object") {
19464
+ rejectContentPart(message, part, "tool has no call ID, name, or state");
19465
+ continue;
19466
+ }
19467
+ content.push({
19468
+ type: "tool-call",
19469
+ id: part.callID,
19470
+ name: part.tool,
19471
+ input: state.input
19472
+ });
19473
+ if (state.status === "completed" || state.status === "error") {
19474
+ following.push({
19475
+ role: "tool",
19476
+ content: [
19477
+ {
19478
+ type: "tool-result",
19479
+ id: part.callID,
19480
+ name: part.tool,
19481
+ result: {
19482
+ type: state.status === "error" ? "error" : "text",
19483
+ value: toolStateContent(state)
19484
+ }
19485
+ }
19486
+ ]
19487
+ });
19488
+ }
19489
+ continue;
19490
+ }
19491
+ if (part.type === "file") {
19492
+ const mime = part.mime;
19493
+ const url = part.url;
19494
+ const prefix = `data:${mime};base64,`;
19495
+ if (typeof mime !== "string" || !/^image\/(png|jpeg|gif|webp)$/.test(mime) || typeof url !== "string" || !url.startsWith(prefix)) {
19496
+ rejectContentPart(message, part, "file is not an inline supported image");
19497
+ continue;
19498
+ }
19499
+ const asset = hostMediaAsset(url.slice(prefix.length), mime);
19500
+ if (typeof asset === "string") {
19501
+ rejectContentPart(message, part, `host media unavailable: ${asset}`);
19502
+ continue;
19503
+ }
19504
+ content.push({ type: "media", media: asset });
19505
+ continue;
19506
+ }
19507
+ if (!HOST_CONTENT_TYPES.has(String(part.type))) {
19508
+ rejectContentPart(message, part, "unknown host content type");
19509
+ continue;
19510
+ }
19511
+ const { synthetic: _synthetic, ...clean } = part;
19512
+ const original = hostPartTypes.has(clean.type) && !containsHostInstance(clean) ? hostParts.get(contentKey(clean)) : undefined;
19513
+ content.push(original ?? clean);
19514
+ continue;
19515
+ }
19516
+ const state = part.state;
19517
+ if (bridge.native) {
19518
+ const native = bridge.native;
19519
+ const callID = String(native.id ?? native.callID ?? part.callID);
19520
+ const name = String(native.name ?? native.tool ?? part.tool);
19521
+ content.push({ type: "tool-call", id: callID, name, input: state.input });
19522
+ if (state.status === "completed" || state.status === "error") {
19523
+ following.push({
19524
+ role: "tool",
19525
+ content: [
19526
+ {
19527
+ type: "tool-result",
19528
+ id: callID,
19529
+ name,
19530
+ result: {
19531
+ type: state.status === "error" ? "error" : "text",
19532
+ value: state.output
19533
+ }
19534
+ }
19535
+ ]
19536
+ });
19537
+ }
19538
+ continue;
19539
+ }
19540
+ if (bridge.call)
19541
+ content.push({ ...bridge.call, input: state.input });
19542
+ if (bridge.result && bridge.resultMessage) {
19543
+ const result = {
19544
+ ...bridge.result,
19545
+ result: state.output === bridge.output ? bridge.result.result : bridge.files && typeof state.output === "string" ? rebuildFileContent(bridge.files, state.output) : {
19546
+ type: state.status === "error" ? "error" : "text",
19547
+ value: state.output
19548
+ }
19549
+ };
19550
+ if (bridge.resultMessage === original)
19551
+ content.push(result);
19552
+ else
19553
+ following.push({ ...bridge.resultMessage, content: [result] });
19554
+ }
19555
+ }
19556
+ if (content.length || !original?.content.length) {
19557
+ const value = {
19558
+ ...original,
19559
+ id,
19560
+ role: message.info.role ?? "user",
19561
+ content
19562
+ };
19563
+ const existing = id ? existingHeads.get(id) : undefined;
19564
+ rendered.push(existing ? Object.assign(existing, { content }) : value);
19565
+ }
19566
+ rendered.push(...following);
19567
+ }
19568
+ draft.messages.splice(0, draft.messages.length, ...rendered);
19569
+ }
19570
+ };
19571
+ }
19572
+
19573
+ // src/v2/fold/native-codec.ts
19574
+ class NativeReplayUnavailable extends Error {
19575
+ }
19576
+ function encodeNative(messages) {
19577
+ for (const message of messages)
19578
+ for (const part of message.content) {
19579
+ if (part.type !== "media" || !part.media)
19580
+ continue;
19581
+ const asset = part.media;
19582
+ if (typeof asset.toJSON !== "function" || asset.headers !== undefined)
19583
+ throw new NativeReplayUnavailable("Native media has no lossless replay codec");
19584
+ const encoded = asset.toJSON();
19585
+ const revived = hostMediaFromEncoded(encoded);
19586
+ if (typeof revived === "string" || JSON.stringify(revived) !== JSON.stringify(asset))
19587
+ throw new NativeReplayUnavailable("Native media cannot be decoded losslessly before admission");
19588
+ }
19589
+ const encoded = JSON.parse(JSON.stringify(messages));
19590
+ const freeze = (value) => {
19591
+ if (!value || typeof value !== "object")
19592
+ return;
19593
+ for (const item of Object.values(value))
19594
+ freeze(item);
19595
+ Object.freeze(value);
19596
+ };
19597
+ freeze(encoded);
19598
+ return encoded;
19599
+ }
19600
+ function reviveNative(messages) {
19601
+ const result = structuredClone([...messages]);
19602
+ for (const message of result)
19603
+ for (const part of message.content) {
19604
+ if (part.type !== "media" || !part.media)
19605
+ continue;
19606
+ const asset = hostMediaFromEncoded(part.media);
19607
+ if (typeof asset === "string")
19608
+ throw new NativeReplayUnavailable(asset);
19609
+ part.media = asset;
19610
+ }
19611
+ return result;
19612
+ }
19613
+
19614
+ // src/v2/fold/restore.ts
19615
+ import { fileURLToPath as fileURLToPath2 } from "node:url";
19616
+
19617
+ // src/v2/hooks/storage-notice.ts
19618
+ var STORAGE_NOTICE_PREFIX = "[Magic Context storage notice] ";
19619
+ function formatStorageRefusalNotice(reason) {
19620
+ return `${STORAGE_NOTICE_PREFIX}This turn was not sent to the model. ${formatFailClosedBlockingSummary(reason)}`;
19621
+ }
19622
+ function formatStorageRecoveryNotice(hiddenWorkRecovered) {
19623
+ return hiddenWorkRecovered ? `${STORAGE_NOTICE_PREFIX}Magic Context storage is available again and turns are sent to the model. The historian and dreamer are running again. Restart OpenCode to enable Magic Context's tools.` : `${STORAGE_NOTICE_PREFIX}Magic Context storage is available again and turns are sent to the model. Restart OpenCode to enable Magic Context's tools, historian and dreamer.`;
19624
+ }
19625
+ function isStorageNoticeText(text) {
19626
+ return typeof text === "string" && text.startsWith(STORAGE_NOTICE_PREFIX);
19627
+ }
19628
+ function hasStorageNoticeShape(message) {
19629
+ if (message.role !== "user" || typeof message.id !== "string")
19630
+ return false;
19631
+ if (message.content.length !== 1)
19632
+ return false;
19633
+ const part = message.content[0];
19634
+ return part?.type === "text" && isStorageNoticeText(part.text);
19635
+ }
19636
+ async function dropStorageNotices(messages, isAdmittedSynthetic) {
19637
+ const drop = new Set;
19638
+ for (const message of messages) {
19639
+ if (!hasStorageNoticeShape(message))
19640
+ continue;
19641
+ if (await isAdmittedSynthetic(message.id))
19642
+ drop.add(message);
19643
+ }
19644
+ if (drop.size === 0)
19645
+ return 0;
19646
+ const kept = messages.filter((message) => !drop.has(message));
19647
+ messages.splice(0, messages.length, ...kept);
19648
+ return drop.size;
19649
+ }
19650
+
19651
+ // src/v2/fold/restore.ts
19652
+ function unavailableAttachmentNote(name, mediaType) {
19653
+ return `[Attachment ${name ? `"${name}" ` : ""}(${mediaType}) is not available in this restored history]`;
19654
+ }
19655
+ var imageMimes = new Set(["image/png", "image/jpeg", "image/gif", "image/webp"]);
19656
+ function attachmentParts(files, rowID, media) {
19657
+ const seen = new Map;
19658
+ return files.flatMap((file) => {
19659
+ if (imageMimes.has(file.mime) && file.source.type === "inline" && file.mention?.text) {
19660
+ const key = JSON.stringify([
19661
+ file.mime,
19662
+ file.name ?? null,
19663
+ file.description ?? null,
19664
+ file.mention.text
19665
+ ]);
19666
+ const payloads = seen.get(key) ?? new Set;
19667
+ if (payloads.has(file.data))
19668
+ return [];
19669
+ payloads.add(file.data);
19670
+ seen.set(key, payloads);
19671
+ }
19672
+ const uri = file.source.type === "uri" ? file.source.uri : undefined;
19673
+ const location = uri?.startsWith("file:") ? fileURLToPath2(uri) : undefined;
19674
+ if (file.mime === "text/plain" || file.mime === "application/x-directory") {
19675
+ const directory = file.mime === "application/x-directory";
19676
+ return [
19677
+ {
19678
+ type: "text",
19679
+ text: `
19680
+
19681
+ ${[
19682
+ directory ? `Attached directory: ${location ?? file.name ?? uri ?? "directory"}` : `Attached file: ${file.name ?? uri ?? "inline attachment"}`,
19683
+ file.description === undefined ? undefined : `Description: ${file.description}`,
19684
+ directory && !file.data.length ? undefined : "",
19685
+ directory && !file.data.length ? undefined : Buffer.from(file.data, "base64").toString("utf8")
18860
19686
  ].filter((line) => line !== undefined).join(`
18861
19687
  `)}`,
18862
19688
  metadata: {
@@ -18984,33 +19810,422 @@ ${data.output?.output ?? ""}`
18984
19810
  input = JSON.parse(input);
18985
19811
  } catch {}
18986
19812
  }
18987
- content.push({
18988
- type: "tool-call",
18989
- id: part.id,
18990
- name: part.name,
18991
- input,
18992
- providerExecuted: part.executed,
18993
- providerMetadata: toolReuse ? metadata(part.providerState) : undefined
18994
- });
18995
- if (!completed)
18996
- continue;
18997
- const toolContent = state.content ?? [];
18998
- const single = toolContent.length === 1 ? toolContent[0] : undefined;
18999
- const result = {
19000
- type: "tool-result",
19001
- id: part.id,
19002
- name: part.name,
19003
- providerExecuted: part.executed,
19004
- providerMetadata: toolReuse ? metadata(part.providerResultState ?? part.providerState) : sameProvider ? metadata(part.providerResultState) : undefined,
19005
- result: state.status === "error" ? { error: state.error, content: toolContent } : single?.type === "text" ? { type: "text", value: single.text } : { type: "content", value: toolContent },
19006
- ...state.status === "error" ? { resultType: "error" } : {}
19007
- };
19008
- if (part.executed === true)
19009
- content.push(result);
19010
- else
19011
- results.push({ role: "tool", content: [result] });
19813
+ content.push({
19814
+ type: "tool-call",
19815
+ id: part.id,
19816
+ name: part.name,
19817
+ input,
19818
+ providerExecuted: part.executed,
19819
+ providerMetadata: toolReuse ? metadata(part.providerState) : undefined
19820
+ });
19821
+ if (!completed)
19822
+ continue;
19823
+ const toolContent = state.content ?? [];
19824
+ const single = toolContent.length === 1 ? toolContent[0] : undefined;
19825
+ const result = {
19826
+ type: "tool-result",
19827
+ id: part.id,
19828
+ name: part.name,
19829
+ providerExecuted: part.executed,
19830
+ providerMetadata: toolReuse ? metadata(part.providerResultState ?? part.providerState) : sameProvider ? metadata(part.providerResultState) : undefined,
19831
+ result: state.status === "error" ? { error: state.error, content: toolContent } : single?.type === "text" ? { type: "text", value: single.text } : { type: "content", value: toolContent },
19832
+ ...state.status === "error" ? { resultType: "error" } : {}
19833
+ };
19834
+ if (part.executed === true)
19835
+ content.push(result);
19836
+ else
19837
+ results.push({ role: "tool", content: [result] });
19838
+ }
19839
+ return [...content.length ? [make("assistant", content)] : [], ...results];
19840
+ }
19841
+
19842
+ // src/v2/fold/native-replay.ts
19843
+ var coordinates = new WeakMap;
19844
+ function nativeRowID(message) {
19845
+ return coordinates.get(message) ?? message.id;
19846
+ }
19847
+ function copyNativeInput(messages) {
19848
+ const copies = reviveNative(encodeNative(messages));
19849
+ copies.forEach((copy, i) => {
19850
+ const original = messages[i];
19851
+ const id = original && nativeRowID(original);
19852
+ if (id !== undefined)
19853
+ coordinates.set(copy, id);
19854
+ });
19855
+ return copies;
19856
+ }
19857
+ function isLocalCheckpoint(row) {
19858
+ return row.type === "compaction" && row.data.status === "completed" && row.data.providerContext === undefined;
19859
+ }
19860
+ var conversational = (row) => RAW_MESSAGE_TYPES.includes(row.type) || row.type === "location-switched";
19861
+
19862
+ class NativeFoldReplay {
19863
+ storage;
19864
+ openReader;
19865
+ changed = new Set;
19866
+ dirty = new Set;
19867
+ unavailable = new Set;
19868
+ metadata = new Map;
19869
+ metadataThrough = new Map;
19870
+ loaded = new Map;
19871
+ sources = new Map;
19872
+ constructor(storage, openReader) {
19873
+ this.storage = storage;
19874
+ this.openReader = openReader;
19875
+ storage.onEvict((sessionID) => this.clear(sessionID));
19876
+ }
19877
+ account(sessionID) {
19878
+ const source = this.sources.get(sessionID);
19879
+ let bytes = 256 + (source?.length ?? 0) * 2;
19880
+ for (const row of this.metadata.get(sessionID) ?? [])
19881
+ bytes += 128 + (row.id.length + row.type.length) * 2;
19882
+ this.storage.accountReplay(sessionID, bytes);
19883
+ }
19884
+ async observeSource(sessionID, reader) {
19885
+ const source = reader.hostIdentity();
19886
+ const prior = this.sources.get(sessionID);
19887
+ if (prior && prior !== source)
19888
+ await this.forget(sessionID);
19889
+ this.sources.set(sessionID, source);
19890
+ this.account(sessionID);
19891
+ }
19892
+ onEvent(event) {
19893
+ const sessionID = event.data?.sessionID;
19894
+ if (sessionID && (event.type?.startsWith("session.revert.") || event.type === "session.message.content.updated"))
19895
+ this.invalidate(sessionID);
19896
+ }
19897
+ invalidate(sessionID, suppressNomination = false) {
19898
+ if (suppressNomination)
19899
+ this.unavailable.add(sessionID);
19900
+ this.dirty.add(sessionID);
19901
+ this.changed.add(sessionID);
19902
+ this.metadata.delete(sessionID);
19903
+ this.metadataThrough.delete(sessionID);
19904
+ this.account(sessionID);
19905
+ }
19906
+ tail(sessionID) {
19907
+ const record = this.storage.tail(sessionID);
19908
+ return record ? JSON.parse(record.data) : undefined;
19909
+ }
19910
+ async baseline(sessionID) {
19911
+ return this.tail(sessionID)?.baseline;
19912
+ }
19913
+ rendered(row, model) {
19914
+ return restoreRow(row, model, hostUsesMediaAssets() ? {
19915
+ asset: hostMediaAsset,
19916
+ unavailable: () => {}
19917
+ } : undefined);
19918
+ }
19919
+ record(row, messages) {
19920
+ const data = JSON.stringify(encodeNative(messages));
19921
+ return { id: row.id, type: row.type, seq: row.seq, data, digest: foldDigest(data) };
19922
+ }
19923
+ records(sessionID, native, reader) {
19924
+ let metadata = this.metadata.get(sessionID);
19925
+ const through = reader.latestSequence(sessionID);
19926
+ const known = new Set(metadata?.map((row) => row.id));
19927
+ if (!metadata || (this.metadataThrough.get(sessionID) ?? -1) < through || native.some((message) => message.id && !known.has(message.id))) {
19928
+ metadata = reader.rowStampsThrough(sessionID, through).filter(conversational);
19929
+ this.metadata.set(sessionID, metadata);
19930
+ this.metadataThrough.set(sessionID, through);
19931
+ }
19932
+ const byID = new Map(metadata.map((row) => [row.id, row]));
19933
+ const grouped = new Map;
19934
+ const anchorIndex = native.findIndex((message) => {
19935
+ const id = nativeRowID(message);
19936
+ return id !== undefined && byID.has(id);
19937
+ });
19938
+ const leading = native.slice(0, anchorIndex < 0 ? native.length : anchorIndex).filter((message) => !nativeRowID(message) && message.role === "system");
19939
+ const anchorMessage = native[anchorIndex];
19940
+ const anchorID = anchorMessage && nativeRowID(anchorMessage);
19941
+ const anchor = anchorID ? byID.get(anchorID) : undefined;
19942
+ const leadingRows = anchor ? metadata.filter((row) => row.type === "system" && row.seq < anchor.seq).slice(-leading.length) : [];
19943
+ const leadingIDs = new Map(leading.map((message, i) => [message, leadingRows[i]?.id]));
19944
+ let cursor = -1;
19945
+ let owner;
19946
+ for (const message of native) {
19947
+ let id = nativeRowID(message);
19948
+ if (!id && message.role === "system") {
19949
+ if (leadingIDs.has(message)) {
19950
+ id = leadingIDs.get(message);
19951
+ if (!id)
19952
+ continue;
19953
+ } else
19954
+ id = metadata.find((row) => row.type === "system" && row.seq > cursor)?.id;
19955
+ }
19956
+ if (!id && message.role === "tool")
19957
+ id = owner;
19958
+ const row = id ? byID.get(id) : undefined;
19959
+ if (!row)
19960
+ throw new NativeReplayUnavailable("Native carrier has no source row coordinate");
19961
+ cursor = row.seq;
19962
+ coordinates.set(message, row.id);
19963
+ if (message.role !== "tool")
19964
+ owner = row.id;
19965
+ const messages = grouped.get(row) ?? [];
19966
+ messages.push(message);
19967
+ grouped.set(row, messages);
19968
+ }
19969
+ return [...grouped].map(([row, messages]) => this.record(row, messages));
19970
+ }
19971
+ async capture(draft, native) {
19972
+ const release = this.storage.hold(draft.sessionID);
19973
+ try {
19974
+ rememberHostMedia(native);
19975
+ const reader = this.openReader(draft.sessionID);
19976
+ try {
19977
+ const rows = this.records(draft.sessionID, native, reader);
19978
+ const baseline = draft.messages.find((message) => message.id === HEAD_IDS[0])?.content.find((part) => part.type === "text")?.text;
19979
+ const through = Math.max(-1, ...rows.map((row) => row.seq));
19980
+ const tail = {
19981
+ model: `${draft.model.providerID}/${draft.model.id}`,
19982
+ sourceSeq: through,
19983
+ baseline: typeof baseline === "string" ? baseline : this.tail(draft.sessionID)?.baseline
19984
+ };
19985
+ await this.storage.saveTail(draft.sessionID, JSON.stringify(tail), rows);
19986
+ this.storage.truncate(draft.sessionID, through);
19987
+ this.loaded.set(draft.sessionID, through);
19988
+ this.unavailable.delete(draft.sessionID);
19989
+ this.changed.delete(draft.sessionID);
19990
+ } finally {
19991
+ reader.close();
19992
+ }
19993
+ } catch {
19994
+ this.unavailable.add(draft.sessionID);
19995
+ this.invalidate(draft.sessionID);
19996
+ } finally {
19997
+ this.account(draft.sessionID);
19998
+ release();
19999
+ }
20000
+ }
20001
+ async canReplay(sessionID, _reader) {
20002
+ return !this.unavailable.has(sessionID) && typeof await this.baseline(sessionID) === "string";
20003
+ }
20004
+ async supply(args) {
20005
+ const release = this.storage.hold(args.draft.sessionID);
20006
+ try {
20007
+ return await this.supplyHeld(args);
20008
+ } finally {
20009
+ this.account(args.draft.sessionID);
20010
+ release();
20011
+ }
20012
+ }
20013
+ async supplyHeld(args) {
20014
+ const { draft, reader, summary } = args;
20015
+ const tail = this.tail(draft.sessionID);
20016
+ const id = reader.latestRunningCompaction(draft.sessionID)?.id;
20017
+ if (!id || !tail || tail.model !== `${draft.model.providerID}/${draft.model.id}`)
20018
+ return false;
20019
+ const through = reader.latestSequence(draft.sessionID);
20020
+ const after = this.dirty.has(draft.sessionID) ? -1 : tail.sourceSeq;
20021
+ const fresh = reader.range(draft.sessionID, after, through).filter(conversational);
20022
+ const records = fresh.map((row) => this.record(row, this.rendered(row, draft.model)));
20023
+ if (this.dirty.has(draft.sessionID))
20024
+ this.storage.replaceRows(draft.sessionID, through, records);
20025
+ await this.storage.saveTail(draft.sessionID, JSON.stringify({
20026
+ ...tail,
20027
+ sourceSeq: Math.max(tail.sourceSeq, ...fresh.map((row) => row.seq))
20028
+ }), records);
20029
+ this.dirty.delete(draft.sessionID);
20030
+ this.metadata.delete(draft.sessionID);
20031
+ this.metadataThrough.delete(draft.sessionID);
20032
+ this.loaded.set(draft.sessionID, through);
20033
+ const snapshot = {
20034
+ source: this.storage.sourceID,
20035
+ sessionID: draft.sessionID,
20036
+ admissionID: id,
20037
+ summary
20038
+ };
20039
+ await this.storage.supply(draft.sessionID, id, JSON.stringify(snapshot));
20040
+ return true;
20041
+ }
20042
+ async restore(sessionID, cut, model, options = {}) {
20043
+ const release = this.storage.hold(sessionID);
20044
+ try {
20045
+ return await this.restoreHeld(sessionID, cut, model, options);
20046
+ } finally {
20047
+ this.account(sessionID);
20048
+ release();
20049
+ }
20050
+ }
20051
+ async restoreHeld(sessionID, cut, model, options) {
20052
+ if (!isLocalCheckpoint(cut))
20053
+ return;
20054
+ const resolvedModel = {
20055
+ providerID: model.slice(0, model.indexOf("/")),
20056
+ id: model.slice(model.indexOf("/") + 1)
20057
+ };
20058
+ const tail = this.tail(sessionID);
20059
+ if (tail && tail.model !== model)
20060
+ this.invalidate(sessionID);
20061
+ let after = options.after ?? -1;
20062
+ if (options.bounded && options.after === undefined && !this.changed.has(sessionID)) {
20063
+ const state = getOrCreateSessionMeta(this.storage.db, sessionID);
20064
+ const max = this.storage.db.prepare("SELECT COALESCE(MAX(id),0) AS id FROM m0_mutation_log WHERE session_id=?").get(sessionID);
20065
+ const boundary = this.storage.db.prepare("SELECT cached_m0_last_baseline_end_message_id AS id FROM session_meta WHERE session_id=?").get(sessionID)?.id;
20066
+ if (max.id <= (state.cachedM0MaxMutationId ?? 0) && boundary)
20067
+ after = this.storage.sequenceForID(sessionID, boundary) ?? -1;
20068
+ }
20069
+ const through = cut.seq - 1;
20070
+ let reader;
20071
+ try {
20072
+ let metadata = this.metadata.get(sessionID);
20073
+ if (!metadata || (this.metadataThrough.get(sessionID) ?? -1) < through) {
20074
+ reader = this.openReader(sessionID);
20075
+ metadata = reader.rowStampsThrough(sessionID, through).filter(conversational);
20076
+ this.metadata.set(sessionID, metadata);
20077
+ this.metadataThrough.set(sessionID, through);
20078
+ }
20079
+ const required = metadata.filter((row) => row.seq > after && row.seq <= through);
20080
+ if (this.dirty.has(sessionID) || !tail || (this.loaded.get(sessionID) ?? -1) < through && !this.storage.admission(sessionID, cut.id) || !this.storage.containsRows(sessionID, required.map((row) => row.id))) {
20081
+ reader ??= this.openReader(sessionID);
20082
+ const fresh = reader.range(sessionID, after, through).filter(conversational);
20083
+ const records = fresh.map((row) => this.record(row, this.rendered(row, resolvedModel)));
20084
+ const restored = new Set(records.map((row) => row.id));
20085
+ if (required.some((row) => !restored.has(row.id)))
20086
+ throw new NativeReplayUnavailable("Host restore omitted a required source row");
20087
+ this.storage.replaceRows(sessionID, through, records, after);
20088
+ await this.storage.saveTail(sessionID, JSON.stringify({
20089
+ model,
20090
+ sourceSeq: through,
20091
+ baseline: tail?.baseline ?? cut.data.summary
20092
+ }), []);
20093
+ this.loaded.set(sessionID, through);
20094
+ this.dirty.delete(sessionID);
20095
+ }
20096
+ } finally {
20097
+ reader?.close();
20098
+ }
20099
+ const messages = [];
20100
+ for (const row of this.storage.rows(sessionID, after, cut.seq - 1)) {
20101
+ const revived = reviveNative(JSON.parse(row.data));
20102
+ for (const message of revived)
20103
+ coordinates.set(message, row.id);
20104
+ messages.push(...revived);
20105
+ }
20106
+ return messages;
20107
+ }
20108
+ async restoreRead(sessionID, cut, model) {
20109
+ const reader = this.openReader(sessionID);
20110
+ try {
20111
+ return reader.range(sessionID, -1, cut.seq - 1).filter(conversational).flatMap((row) => {
20112
+ const messages = this.rendered(row, model);
20113
+ for (const message of messages)
20114
+ coordinates.set(message, row.id);
20115
+ return messages;
20116
+ });
20117
+ } finally {
20118
+ reader.close();
20119
+ }
20120
+ }
20121
+ sourceChanged(sessionID) {
20122
+ return this.changed.has(sessionID);
20123
+ }
20124
+ clear(sessionID) {
20125
+ this.sources.delete(sessionID);
20126
+ this.metadata.delete(sessionID);
20127
+ this.metadataThrough.delete(sessionID);
20128
+ this.loaded.delete(sessionID);
20129
+ this.unavailable.delete(sessionID);
20130
+ this.dirty.delete(sessionID);
20131
+ this.changed.delete(sessionID);
20132
+ }
20133
+ async forget(sessionID) {
20134
+ await this.storage.forget(sessionID);
20135
+ }
20136
+ }
20137
+
20138
+ // src/v2/fold/policy.ts
20139
+ import { randomUUID as randomUUID3 } from "node:crypto";
20140
+ class HostFoldPolicy {
20141
+ deps;
20142
+ active = new Set;
20143
+ owner = randomUUID3();
20144
+ constructor(deps) {
20145
+ this.deps = deps;
20146
+ }
20147
+ owned(sessionID, cut, id) {
20148
+ const row = this.deps.storage.admission(sessionID, id);
20149
+ if (!isLocalCheckpoint(cut) || cut.id !== id || !row?.payload || row.digest !== foldDigest(row.payload))
20150
+ return false;
20151
+ const snapshot = JSON.parse(row.payload);
20152
+ return snapshot.summary === cut.data.summary && snapshot.source === this.deps.storage.sourceID && snapshot.sessionID === sessionID && snapshot.admissionID === id;
20153
+ }
20154
+ async idle(sessionID) {
20155
+ const { storage, session, threshold } = this.deps;
20156
+ if (!Number.isSafeInteger(threshold) || threshold <= 0 || typeof session.compact !== "function" || this.active.has(sessionID))
20157
+ return;
20158
+ this.active.add(sessionID);
20159
+ const now = this.deps.now ?? Date.now;
20160
+ let attempt;
20161
+ let claimed = false;
20162
+ try {
20163
+ const reader = this.deps.openReader();
20164
+ try {
20165
+ const cut = reader.latestCompaction(sessionID);
20166
+ const previous = storage.latestAttempt(sessionID);
20167
+ const old = previous ? JSON.parse(previous.data) : undefined;
20168
+ if (cut && previous?.status === "pending" && old && this.owned(sessionID, cut, old.id)) {
20169
+ if (await storage.claim(sessionID, old.id, previous.data, this.owner, now()) && await storage.finish(sessionID, old.id, this.owner, "completed", now()))
20170
+ this.deps.log(sessionID, `v2 host fold: rows_before=${old.before} rows_after=${reader.storedRowsAfter(sessionID, cut.seq)} duration_ms=${now() - old.started} reason=row_threshold id=${cut.id} status=completed`);
20171
+ return;
20172
+ }
20173
+ const after = cut?.seq ?? -1;
20174
+ const before = reader.storedRowsAfter(sessionID, after);
20175
+ if (before < threshold || !await this.deps.canReplay(sessionID, reader))
20176
+ return;
20177
+ const retry = old?.after === after ? old.attempt + (previous?.status === "failed" || previous?.status === "coalesced" ? 1 : 0) : 0;
20178
+ const id = old?.after === after && previous?.status === "pending" ? old.id : `msg_mc_fold_${foldDigest(`${storage.sourceID}/${sessionID}/${after}/${retry}`).slice(0, 24)}`;
20179
+ attempt = {
20180
+ after,
20181
+ before,
20182
+ watermark: reader.latestSequence(sessionID),
20183
+ attempt: retry,
20184
+ id,
20185
+ started: now()
20186
+ };
20187
+ claimed = await storage.claim(sessionID, id, JSON.stringify(attempt), this.owner, now());
20188
+ if (!claimed)
20189
+ return;
20190
+ } finally {
20191
+ reader.close();
20192
+ }
20193
+ const admitted = await session.compact({
20194
+ sessionID,
20195
+ id: attempt.id,
20196
+ delivery: "queue"
20197
+ });
20198
+ await session.wait({ sessionID });
20199
+ const settled = this.deps.openReader();
20200
+ try {
20201
+ const cut = settled.latestCompaction(sessionID);
20202
+ if (admitted?.id !== attempt.id || !cut || cut.seq <= attempt.after || !this.owned(sessionID, cut, attempt.id)) {
20203
+ if (await storage.finish(sessionID, attempt.id, this.owner, "coalesced", now()))
20204
+ this.deps.log(sessionID, `v2 host fold: rows_before=${attempt.before} rows_after=unknown duration_ms=${now() - attempt.started} reason=row_threshold id=${attempt.id} actual_id=${cut?.id ?? admitted?.id ?? "unknown"} status=coalesced`);
20205
+ return;
20206
+ }
20207
+ const after = settled.storedRowsAfter(sessionID, cut.seq);
20208
+ if (await storage.finish(sessionID, attempt.id, this.owner, "completed", now()))
20209
+ this.deps.log(sessionID, `v2 host fold: rows_before=${attempt.before} rows_after=${after} duration_ms=${now() - attempt.started} reason=row_threshold id=${cut.id} status=completed`);
20210
+ } finally {
20211
+ settled.close();
20212
+ }
20213
+ } catch (error) {
20214
+ if (claimed && attempt) {
20215
+ let finished = false;
20216
+ try {
20217
+ finished = await storage.finish(sessionID, attempt.id, this.owner, "failed", now());
20218
+ } catch {
20219
+ finished = true;
20220
+ }
20221
+ if (finished)
20222
+ this.deps.log(sessionID, `v2 host fold: rows_before=${attempt.before} rows_after=unknown duration_ms=${now() - attempt.started} reason=row_threshold id=${attempt.id} status=failed error=${JSON.stringify(String(error))}`);
20223
+ } else
20224
+ this.deps.log(sessionID, `v2 host fold: rows_before=unknown rows_after=unknown duration_ms=0 reason=row_threshold status=failed error=${JSON.stringify(String(error))} cache_error=${JSON.stringify(String(error))}`);
20225
+ } finally {
20226
+ this.active.delete(sessionID);
20227
+ }
19012
20228
  }
19013
- return [...content.length ? [make("assistant", content)] : [], ...results];
19014
20229
  }
19015
20230
 
19016
20231
  // src/v2/fork-inheritance.ts
@@ -19133,12 +20348,13 @@ function seedV2ForkFromParent(args) {
19133
20348
  function keptUnderRetention(keepSubagents, child) {
19134
20349
  return keepSubagents && (child.ever_settled === true || child.role === "historian");
19135
20350
  }
20351
+ var HIDDEN_CHILD_ROLE_TITLES = {
20352
+ "maintainer-a": "Magic Context maintainer A",
20353
+ "maintainer-b": "Magic Context maintainer B",
20354
+ historian: "Magic Context historian"
20355
+ };
19136
20356
  function roleTitle(role) {
19137
- if (role === "maintainer-a")
19138
- return "Magic Context maintainer A";
19139
- if (role === "maintainer-b")
19140
- return "Magic Context maintainer B";
19141
- return "Magic Context historian";
20357
+ return HIDDEN_CHILD_ROLE_TITLES[role];
19142
20358
  }
19143
20359
  function roleAgent(role) {
19144
20360
  if (role === "maintainer-a")
@@ -19700,694 +20916,315 @@ async function createV2HiddenCompletionExecutor(host, options) {
19700
20916
  interruptAndRetire(run, "prompt-timeout").finally(() => abortReject(new Error("Hidden completion prompt timed out")));
19701
20917
  }, Math.max(0, deadline - Date.now()));
19702
20918
  request.signal?.addEventListener("abort", onAbort, { once: true });
19703
- try {
19704
- await Promise.race([
19705
- host.prompt({ sessionID: run.child.id, text: marker }),
19706
- aborted
19707
- ]);
19708
- await Promise.race([host.wait({ sessionID: run.child.id }), aborted]);
19709
- const row = await Promise.race([
19710
- awaitAssistantRow(options.openReader, async () => {
19711
- try {
19712
- const eventError = await host.terminalError?.({
19713
- sessionID: run.child.id
19714
- });
19715
- if (eventError !== undefined)
19716
- return eventError;
19717
- return (await host.get({ sessionID: run.child.id })).error;
19718
- } catch {
19719
- return;
19720
- }
19721
- }, () => attempt.refusal ?? attempt.stepLimit, run.child.id, baseline, deadline, request.signal),
19722
- aborted
19723
- ]);
19724
- if (!attempt.shaped) {
19725
- throw new HiddenCompletionRefusal("hidden_prompt_unrecognized", "Host did not dispatch the hidden child context hook", true);
19726
- }
19727
- const text = assistantText(row);
19728
- const system = typeof request.body.system === "string" ? request.body.system : run.identity.system;
19729
- const tokens = row.data.tokens;
19730
- const tokenNumber = (value) => typeof value === "number" && Number.isFinite(value) ? value : undefined;
19731
- const reportedInput = tokenNumber(tokens?.input);
19732
- const reportedOutput = tokenNumber(tokens?.output);
19733
- if (request.signal?.aborted || run.retired || Date.now() >= deadline) {
19734
- await interruptAndRetire(run, "prompt-aborted-or-timeout");
19735
- throw new Error(request.signal?.aborted ? "Hidden completion prompt aborted" : "Hidden completion prompt timed out");
19736
- }
19737
- run.completion = {
19738
- text,
19739
- tokenLog: runTokenLog(tokens, run.identity.maxOutputTokens, row.data.finish),
19740
- reasoning: text ? null : assistantReasoning(row),
19741
- usage: reportedInput !== undefined || reportedOutput !== undefined ? {
19742
- input: reportedInput ?? 0,
19743
- output: reportedOutput ?? 0,
19744
- cacheRead: tokenNumber(tokens?.cache?.read) ?? 0,
19745
- cacheWrite: tokenNumber(tokens?.cache?.write) ?? 0
19746
- } : meter(system, promptText(request), text ?? ""),
19747
- lengthCapped: ["length", "max_tokens"].includes(row.data.finish ?? ""),
19748
- providerId: row.data.model?.providerID ?? requested.providerID,
19749
- modelId: row.data.model?.id ?? requested.modelID,
19750
- ...attempt.steps === undefined ? {} : { steps: attempt.steps }
19751
- };
19752
- if (!run.child.ever_settled)
19753
- run.child = lifecycle.markEverSettled(run.child);
19754
- } catch (caught) {
19755
- const error = attempt.stepLimit ?? attempt.refusal ?? caught;
19756
- run.failed = true;
19757
- if (!(error instanceof HiddenProviderError)) {
19758
- run.unsettledFailure = true;
19759
- }
19760
- if (request.signal?.aborted && !run.retired) {
19761
- await interruptAndRetire(run, "prompt-aborted");
19762
- } else if (error instanceof Error && error.message.includes("timed out") && !run.retired) {
19763
- await interruptAndRetire(run, "prompt-timeout");
19764
- } else if ((error instanceof HiddenAgentStepLimit || error instanceof HiddenProviderError && error.settled) && !run.retired) {
19765
- await interruptAndRetire(run, error instanceof HiddenAgentStepLimit ? "hidden-run-step-limit" : "hidden-run-provider-error");
19766
- }
19767
- throw error;
19768
- } finally {
19769
- clearTimeout(deadlineTimer);
19770
- request.signal?.removeEventListener("abort", onAbort);
19771
- options.hook.releaseAttempt(marker);
19772
- }
19773
- },
19774
- async collect(handle) {
19775
- const completion = runs.get(handle)?.completion;
19776
- if (!completion)
19777
- throw new Error("Hidden completion has no settled output");
19778
- return completion;
19779
- },
19780
- async close(handle, settlement) {
19781
- if (!handle)
19782
- return;
19783
- const run = runs.get(handle);
19784
- if (!run)
19785
- return;
19786
- try {
19787
- const reusable = !run.retired && run.failed && !run.unsettledFailure;
19788
- if (!run.completion && (run.failed || !settlement.promptSettled) && !reusable) {
19789
- retire(run, "hidden-run-failed");
19790
- }
19791
- } finally {
19792
- runs.delete(handle);
19793
- run.releaseRole();
19794
- }
19795
- await lifecycle.finish(run.child, run.retired);
19796
- }
19797
- };
19798
- }
19799
-
19800
- // src/v2/hooks/channel2.ts
19801
- import { randomBytes as randomBytes2 } from "node:crypto";
19802
- var pendingCandidates = new WeakMap;
19803
- function syntheticCandidates(context, sessionID, stored) {
19804
- const pending = pendingCandidates.get(context.storage);
19805
- for (const [key, id] of pending ?? []) {
19806
- if (!key.startsWith(`${sessionID}/`))
19807
- continue;
19808
- if (stored.has(id))
19809
- pending?.delete(key);
19810
- else
19811
- stored.add(id);
19812
- }
19813
- return stored;
19814
- }
19815
- function clearSyntheticCandidates(context) {
19816
- pendingCandidates.delete(context.storage);
19817
- }
19818
- async function deliverSynthetic(context, sessionID, text) {
19819
- const id = `msg_${randomBytes2(12).toString("hex")}`;
19820
- await context.storage.set(`synthetic/${sessionID}/${id}`, { id });
19821
- let candidates = pendingCandidates.get(context.storage);
19822
- if (!candidates) {
19823
- candidates = new Map;
19824
- pendingCandidates.set(context.storage, candidates);
19825
- }
19826
- candidates.set(`${sessionID}/${id}`, id);
19827
- await context.session.synthetic({ sessionID, id, text, delivery: "steer" });
19828
- return id;
19829
- }
19830
- async function isAdmittedSynthetic(context, sessionID, id) {
19831
- const record = await context.storage.get(`synthetic/${sessionID}/${id}`);
19832
- return record !== null && typeof record === "object" && "id" in record && record.id === id;
19833
- }
19834
- async function deliverPendingChannel2(context, db, sessionID, baseline) {
19835
- if (getChannel2NudgeState(db, sessionID) !== "pending")
19836
- return;
19837
- const evaluation = evaluateChannel2(baseline);
19838
- if (!evaluation.evaluable || !evaluation.shouldTrigger)
19839
- return;
19840
- const token = randomBytes2(16).toString("hex");
19841
- if (!claimChannel2NudgeState(db, sessionID, token))
19842
- return;
19843
- try {
19844
- await deliverSynthetic(context, sessionID, buildChannel2Reminder(evaluation.reclaimableTokens, reclaimableToolOutputCount(baseline?.baselineParts ?? [])));
19845
- } catch (error) {
19846
- casChannel2NudgeClaim(db, sessionID, "pending", token);
19847
- throw error;
19848
- }
19849
- casChannel2NudgeClaim(db, sessionID, "delivered", token);
19850
- }
19851
-
19852
- // src/v2/hooks/commands.ts
19853
- async function registerV2Commands(args) {
19854
- const domain = args.command;
19855
- if (!domain || typeof domain.transform !== "function") {
19856
- log("[magic-context] v2 host exposes no command domain; /mmc-* commands are TUI-only");
19857
- return false;
19858
- }
19859
- const descriptions = getMagicContextBuiltinCommands(args.compactionEnabled);
19860
- const commands = buildV2Commands(args.rpc, args.directory);
19861
- try {
19862
- await domain.transform((editor) => {
19863
- for (const command of commands) {
19864
- editor.add({
19865
- name: command.name,
19866
- description: descriptions[command.name].description,
19867
- execute: command.execute
19868
- });
19869
- }
19870
- });
19871
- } catch (error) {
19872
- log("[magic-context] v2 command registration failed", error);
19873
- return false;
19874
- }
19875
- log(`[magic-context] registered server-side commands: ${commands.map((command) => command.name).join(" ")}`);
19876
- return true;
19877
- }
19878
- function commandArgument(input, name) {
19879
- const raw = typeof input.prompt?.text === "string" ? input.prompt.text.trim() : "";
19880
- const prefix = `/${name}`;
19881
- if (raw === prefix)
19882
- return "";
19883
- if (raw.startsWith(`${prefix} `))
19884
- return raw.slice(prefix.length).trim();
19885
- return raw;
19886
- }
19887
- function reportResult(sessionID, title, message) {
19888
- pushNotification2("action", { action: "show-result-dialog", title, message }, sessionID);
19889
- }
19890
- function reportUsage(sessionID, message) {
19891
- pushNotification2("toast", { message, variant: "warning" }, sessionID);
19892
- }
19893
- function reportRpcReply(sessionID, title, reply, pending) {
19894
- if (reply.ok !== true) {
19895
- const error = typeof reply.error === "string" ? reply.error : `${title} request failed`;
19896
- pushNotification2("toast", { message: error, variant: "error" }, sessionID);
19897
- return;
19898
- }
19899
- if (reply.started === true) {
19900
- pushNotification2("toast", { message: pending, variant: "info" }, sessionID);
19901
- return;
19902
- }
19903
- reportResult(sessionID, title, typeof reply.message === "string" ? reply.message : "");
19904
- }
19905
- function buildV2Commands(rpc, directory) {
19906
- return [
19907
- {
19908
- name: "mmc-status",
19909
- execute: async (input) => {
19910
- const detail = await rpc.dispatch("status-detail", {
19911
- sessionId: input.sessionID,
19912
- directory
19913
- });
19914
- if (typeof detail.error === "string") {
19915
- throw new Error(`Magic Context status is unavailable: ${detail.error}`);
19916
- }
19917
- pushNotification2("action", { action: "show-status-dialog" }, input.sessionID);
19918
- }
19919
- },
19920
- {
19921
- name: "mmc-recomp",
19922
- execute: async (input) => {
19923
- if (isTuiConnected2(input.sessionID)) {
19924
- pushNotification2("action", { action: "show-recomp-dialog" }, input.sessionID);
19925
- return;
20919
+ try {
20920
+ await Promise.race([
20921
+ host.prompt({ sessionID: run.child.id, text: marker }),
20922
+ aborted
20923
+ ]);
20924
+ await Promise.race([host.wait({ sessionID: run.child.id }), aborted]);
20925
+ const row = await Promise.race([
20926
+ awaitAssistantRow(options.openReader, async () => {
20927
+ try {
20928
+ const eventError = await host.terminalError?.({
20929
+ sessionID: run.child.id
20930
+ });
20931
+ if (eventError !== undefined)
20932
+ return eventError;
20933
+ return (await host.get({ sessionID: run.child.id })).error;
20934
+ } catch {
20935
+ return;
20936
+ }
20937
+ }, () => attempt.refusal ?? attempt.stepLimit, run.child.id, baseline, deadline, request.signal),
20938
+ aborted
20939
+ ]);
20940
+ if (!attempt.shaped) {
20941
+ const task = run.identity.title.replace(/^magic-context-dream-/, "");
20942
+ throw new HiddenCompletionRefusal("hidden_prompt_unrecognized", `Host did not dispatch the hidden child context hook (task=${task}, agent=${run.identity.agent}, child=${run.child.id}, directory=${run.identity.directory}, stage=context/HiddenChildHook.apply). Check that the child's location loads the owning Magic Context instance; changing models cannot repair missing context shaping.`, true);
19926
20943
  }
19927
- const reply = await rpc.dispatch("recomp", { sessionId: input.sessionID });
19928
- if (reply.ok !== true) {
19929
- throw new Error("Magic Context could not start the history rebuild.");
20944
+ const text = assistantText(row);
20945
+ const system = typeof request.body.system === "string" ? request.body.system : run.identity.system;
20946
+ const tokens = row.data.tokens;
20947
+ const tokenNumber = (value) => typeof value === "number" && Number.isFinite(value) ? value : undefined;
20948
+ const reportedInput = tokenNumber(tokens?.input);
20949
+ const reportedOutput = tokenNumber(tokens?.output);
20950
+ if (request.signal?.aborted || run.retired || Date.now() >= deadline) {
20951
+ await interruptAndRetire(run, "prompt-aborted-or-timeout");
20952
+ throw new Error(request.signal?.aborted ? "Hidden completion prompt aborted" : "Hidden completion prompt timed out");
19930
20953
  }
19931
- }
19932
- },
19933
- {
19934
- name: "mmc-flush",
19935
- execute: async (input) => {
19936
- const reply = await rpc.dispatch("flush", { sessionId: input.sessionID });
19937
- reportRpcReply(input.sessionID, "Flush", reply, "Flush started");
19938
- }
19939
- },
19940
- {
19941
- name: "mmc-wrapup",
19942
- execute: async (input) => {
19943
- const argument = commandArgument(input, "mmc-wrapup");
19944
- if (argument !== "" && !/^\d+$/.test(argument)) {
19945
- const usage = "Usage: /mmc-wrapup [messages_to_keep] where messages_to_keep is a positive integer";
19946
- reportUsage(input.sessionID, usage);
19947
- throw new Error(usage);
20954
+ run.completion = {
20955
+ text,
20956
+ tokenLog: runTokenLog(tokens, run.identity.maxOutputTokens, row.data.finish),
20957
+ reasoning: text ? null : assistantReasoning(row),
20958
+ usage: reportedInput !== undefined || reportedOutput !== undefined ? {
20959
+ input: reportedInput ?? 0,
20960
+ output: reportedOutput ?? 0,
20961
+ cacheRead: tokenNumber(tokens?.cache?.read) ?? 0,
20962
+ cacheWrite: tokenNumber(tokens?.cache?.write) ?? 0
20963
+ } : meter(system, promptText(request), text ?? ""),
20964
+ lengthCapped: ["length", "max_tokens"].includes(row.data.finish ?? ""),
20965
+ providerId: row.data.model?.providerID ?? requested.providerID,
20966
+ modelId: row.data.model?.id ?? requested.modelID,
20967
+ ...attempt.steps === undefined ? {} : { steps: attempt.steps }
20968
+ };
20969
+ if (!run.child.ever_settled)
20970
+ run.child = lifecycle.markEverSettled(run.child);
20971
+ } catch (caught) {
20972
+ const error = attempt.stepLimit ?? attempt.refusal ?? caught;
20973
+ run.failed = true;
20974
+ if (!(error instanceof HiddenProviderError)) {
20975
+ run.unsettledFailure = true;
19948
20976
  }
19949
- const messagesToKeep = argument === "" ? 20 : Number.parseInt(argument, 10);
19950
- if (messagesToKeep <= 0) {
19951
- const usage = "messages_to_keep must be a positive integer";
19952
- reportUsage(input.sessionID, usage);
19953
- throw new Error(usage);
20977
+ if (request.signal?.aborted && !run.retired) {
20978
+ await interruptAndRetire(run, "prompt-aborted");
20979
+ } else if (error instanceof Error && error.message.includes("timed out") && !run.retired) {
20980
+ await interruptAndRetire(run, "prompt-timeout");
20981
+ } else if ((error instanceof HiddenAgentStepLimit || error instanceof HiddenProviderError && error.settled) && !run.retired) {
20982
+ await interruptAndRetire(run, error instanceof HiddenAgentStepLimit ? "hidden-run-step-limit" : "hidden-run-provider-error");
19954
20983
  }
19955
- const reply = await rpc.dispatch("wrapup", {
19956
- sessionId: input.sessionID,
19957
- messagesToKeep
19958
- });
19959
- reportRpcReply(input.sessionID, "Wrapup", reply, "Wrapup started; the summary appears when it finishes");
20984
+ throw error;
20985
+ } finally {
20986
+ clearTimeout(deadlineTimer);
20987
+ request.signal?.removeEventListener("abort", onAbort);
20988
+ options.hook.releaseAttempt(marker);
19960
20989
  }
19961
20990
  },
19962
- {
19963
- name: "mmc-memory-maintain",
19964
- execute: async (input) => {
19965
- const argument = commandArgument(input, "mmc-memory-maintain");
19966
- const subcommand = argument === "" ? "status" : argument.trim().toLowerCase();
19967
- if (subcommand !== "run" && subcommand !== "status" && subcommand !== "resume") {
19968
- const usage = "Usage: /mmc-memory-maintain [run|status|resume] — status is the default";
19969
- reportUsage(input.sessionID, usage);
19970
- throw new Error(usage);
20991
+ async collect(handle) {
20992
+ const completion = runs.get(handle)?.completion;
20993
+ if (!completion)
20994
+ throw new Error("Hidden completion has no settled output");
20995
+ return completion;
20996
+ },
20997
+ async close(handle, settlement) {
20998
+ if (!handle)
20999
+ return;
21000
+ const run = runs.get(handle);
21001
+ if (!run)
21002
+ return;
21003
+ try {
21004
+ const reusable = !run.retired && run.failed && !run.unsettledFailure;
21005
+ if (!run.completion && (run.failed || !settlement.promptSettled) && !reusable) {
21006
+ retire(run, "hidden-run-failed");
19971
21007
  }
19972
- const reply = await rpc.dispatch("maintenance", {
19973
- sessionId: input.sessionID,
19974
- subcommand
19975
- });
19976
- reportRpcReply(input.sessionID, "Memory maintenance", reply, "Maintenance run started; see /mmc-memory-maintain status for the outcome");
21008
+ } finally {
21009
+ runs.delete(handle);
21010
+ run.releaseRole();
19977
21011
  }
21012
+ await lifecycle.finish(run.child, run.retired);
19978
21013
  }
19979
- ];
21014
+ };
19980
21015
  }
19981
21016
 
19982
- // src/v2/hooks/deleted-session-tombstones.ts
19983
- class DeletedSessionTombstones {
19984
- limit;
19985
- #ids = new Set;
19986
- constructor(limit = 1000) {
19987
- this.limit = limit;
19988
- if (!Number.isSafeInteger(limit) || limit < 1) {
19989
- throw new Error("Deleted-session tombstone limit must be a positive integer");
19990
- }
19991
- }
19992
- add(sessionID) {
19993
- this.#ids.delete(sessionID);
19994
- this.#ids.add(sessionID);
19995
- while (this.#ids.size > this.limit) {
19996
- const oldest = this.#ids.values().next().value;
19997
- if (oldest === undefined)
19998
- break;
19999
- this.#ids.delete(oldest);
20000
- }
20001
- }
20002
- has(sessionID) {
20003
- return this.#ids.has(sessionID);
20004
- }
20005
- clear() {
20006
- this.#ids.clear();
20007
- }
20008
- get size() {
20009
- return this.#ids.size;
21017
+ // src/v2/hooks/channel2.ts
21018
+ import { randomBytes as randomBytes2 } from "node:crypto";
21019
+ var pendingCandidates = new WeakMap;
21020
+ function syntheticCandidates(context, sessionID, stored) {
21021
+ const pending = pendingCandidates.get(context.storage);
21022
+ for (const [key, id] of pending ?? []) {
21023
+ if (!key.startsWith(`${sessionID}/`))
21024
+ continue;
21025
+ if (stored.has(id))
21026
+ pending?.delete(key);
21027
+ else
21028
+ stored.add(id);
20010
21029
  }
21030
+ return stored;
20011
21031
  }
20012
-
20013
- // src/v2/tool-result.ts
20014
- function isToolError(part) {
20015
- const result = part.result;
20016
- return part.resultType === "error" || result?.type === "error" || result !== null && typeof result === "object" && "error" in result;
20017
- }
20018
- function toolErrorText(result) {
20019
- const value = result.value === undefined ? result : result.value;
20020
- return typeof value === "string" ? value : JSON.stringify(value);
20021
- }
20022
- function toolStateContent(state) {
20023
- if (typeof state.output === "string")
20024
- return state.output;
20025
- if (state.status === "error")
20026
- return toolErrorText({ error: state.error, content: state.content ?? [] });
20027
- if (typeof state.content === "string")
20028
- return state.content;
20029
- if (!Array.isArray(state.content))
20030
- return "";
20031
- return state.content.map((part) => {
20032
- if (typeof part === "string")
20033
- return part;
20034
- if (!part || typeof part !== "object")
20035
- return "";
20036
- const value = part;
20037
- if (typeof value.text === "string")
20038
- return value.text;
20039
- if (typeof value.value === "string")
20040
- return value.value;
20041
- return "";
20042
- }).filter(Boolean).join(`
20043
- `);
20044
- }
20045
-
20046
- // src/v2/hooks/payload.ts
20047
- var HEAD_IDS = ["__magic_context_v2_m0__", "__magic_context_v2_m1__"];
20048
- var HOST_CONTENT_TYPES = new Set([
20049
- "text",
20050
- "media",
20051
- "tool-call",
20052
- "tool-result",
20053
- "reasoning",
20054
- "compaction",
20055
- "effort"
20056
- ]);
20057
- function rejectContentPart(message, part, reason) {
20058
- const type = typeof part.type === "string" ? part.type : "<missing>";
20059
- const text = `v2 context omitted a content part the host would reject: type=${type} message=${String(message.info.id ?? "<head>")} reason=${reason}`;
20060
- if (typeof message.info.sessionID === "string")
20061
- sessionLog(message.info.sessionID, text);
20062
- else
20063
- log(text);
20064
- }
20065
- function isHostInstance(value) {
20066
- if (!value || typeof value !== "object" || Array.isArray(value))
20067
- return false;
20068
- const prototype = Object.getPrototypeOf(value);
20069
- return prototype !== Object.prototype && prototype !== null;
20070
- }
20071
- function containsHostInstance(value) {
20072
- if (isHostInstance(value))
20073
- return true;
20074
- if (Array.isArray(value))
20075
- return value.some(containsHostInstance);
20076
- if (value && typeof value === "object")
20077
- return Object.values(value).some(containsHostInstance);
20078
- return false;
21032
+ function clearSyntheticCandidates(context) {
21033
+ pendingCandidates.delete(context.storage);
20079
21034
  }
20080
- function clonePreservingInstances(value) {
20081
- if (isHostInstance(value))
20082
- return value;
20083
- if (Array.isArray(value))
20084
- return value.map(clonePreservingInstances);
20085
- if (value && typeof value === "object") {
20086
- const copy = {};
20087
- for (const [key, entry] of Object.entries(value))
20088
- copy[key] = clonePreservingInstances(entry);
20089
- return copy;
21035
+ async function deliverSynthetic(context, sessionID, text) {
21036
+ const id = `msg_${randomBytes2(12).toString("hex")}`;
21037
+ await context.storage.set(`synthetic/${sessionID}/${id}`, { id });
21038
+ let candidates = pendingCandidates.get(context.storage);
21039
+ if (!candidates) {
21040
+ candidates = new Map;
21041
+ pendingCandidates.set(context.storage, candidates);
20090
21042
  }
20091
- return value;
21043
+ candidates.set(`${sessionID}/${id}`, id);
21044
+ await context.session.synthetic({ sessionID, id, text, delivery: "steer" });
21045
+ return id;
20092
21046
  }
20093
- function contentKey(value) {
20094
- const plain = (entry) => {
20095
- if (ArrayBuffer.isView(entry)) {
20096
- return {
20097
- bytes: Buffer.from(entry.buffer, entry.byteOffset, entry.byteLength).toString("base64")
20098
- };
20099
- }
20100
- if (Array.isArray(entry))
20101
- return entry.map(plain);
20102
- if (entry && typeof entry === "object") {
20103
- return Object.fromEntries(Object.entries(entry).map(([key, nested]) => [key, plain(nested)]));
20104
- }
20105
- return entry;
20106
- };
20107
- return JSON.stringify(plain(value));
21047
+ async function isAdmittedSynthetic(context, sessionID, id) {
21048
+ const record = await context.storage.get(`synthetic/${sessionID}/${id}`);
21049
+ return record !== null && typeof record === "object" && "id" in record && record.id === id;
20108
21050
  }
20109
- function fileContentValue(result) {
20110
- const value = result?.value;
20111
- if (result?.type !== "content" || !Array.isArray(value))
21051
+ async function deliverPendingChannel2(context, db, sessionID, baseline) {
21052
+ if (getChannel2NudgeState(db, sessionID) !== "pending")
20112
21053
  return;
20113
- return value.some((item) => item?.type === "file") ? value : undefined;
21054
+ const evaluation = evaluateChannel2(baseline);
21055
+ if (!evaluation.evaluable || !evaluation.shouldTrigger)
21056
+ return;
21057
+ const token = randomBytes2(16).toString("hex");
21058
+ if (!claimChannel2NudgeState(db, sessionID, token))
21059
+ return;
21060
+ try {
21061
+ await deliverSynthetic(context, sessionID, buildChannel2Reminder(evaluation.reclaimableTokens, reclaimableToolOutputCount(baseline?.baselineParts ?? [])));
21062
+ } catch (error) {
21063
+ casChannel2NudgeClaim(db, sessionID, "pending", token);
21064
+ throw error;
21065
+ }
21066
+ casChannel2NudgeClaim(db, sessionID, "delivered", token);
20114
21067
  }
20115
- function contentValueText(value) {
20116
- return value.filter((item) => item?.type === "text" && typeof item.text === "string").map((item) => item.text).join(`
20117
- `);
21068
+
21069
+ // src/v2/hooks/commands.ts
21070
+ async function registerV2Commands(args) {
21071
+ const domain = args.command;
21072
+ if (!domain || typeof domain.transform !== "function") {
21073
+ log("[magic-context] v2 host exposes no command domain; /mmc-* commands are TUI-only");
21074
+ return false;
21075
+ }
21076
+ const descriptions = getMagicContextBuiltinCommands(args.compactionEnabled);
21077
+ const commands = buildV2Commands(args.rpc, args.directory);
21078
+ try {
21079
+ await domain.transform((editor) => {
21080
+ for (const command of commands) {
21081
+ editor.add({
21082
+ name: command.name,
21083
+ description: descriptions[command.name].description,
21084
+ execute: command.execute
21085
+ });
21086
+ }
21087
+ });
21088
+ } catch (error) {
21089
+ log("[magic-context] v2 command registration failed", error);
21090
+ return false;
21091
+ }
21092
+ log(`[magic-context] registered server-side commands: ${commands.map((command) => command.name).join(" ")}`);
21093
+ return true;
20118
21094
  }
20119
- function contentValueAttachments(value) {
20120
- return value.filter((item) => item?.type === "file").map((item) => ({
20121
- type: "file",
20122
- mime: item.mime,
20123
- url: item.uri,
20124
- ...typeof item.name === "string" ? { filename: item.name } : {}
20125
- }));
21095
+ function commandArgument(input, name) {
21096
+ const raw = typeof input.prompt?.text === "string" ? input.prompt.text.trim() : "";
21097
+ const prefix = `/${name}`;
21098
+ if (raw === prefix)
21099
+ return "";
21100
+ if (raw.startsWith(`${prefix} `))
21101
+ return raw.slice(prefix.length).trim();
21102
+ return raw;
20126
21103
  }
20127
- function rebuildFileContent(value, output) {
20128
- if (isDroppedToolOutput(output))
20129
- return { type: "text", value: output };
20130
- const rebuilt = [];
20131
- let placed = false;
20132
- for (const item of value) {
20133
- if (item?.type !== "text") {
20134
- rebuilt.push(item);
20135
- continue;
20136
- }
20137
- if (placed)
20138
- continue;
20139
- placed = true;
20140
- rebuilt.push({ ...item, text: output });
20141
- }
20142
- if (!placed && output)
20143
- rebuilt.unshift({ type: "text", text: output });
20144
- return { type: "content", value: rebuilt };
21104
+ function reportResult(sessionID, title, message) {
21105
+ pushNotification2("action", { action: "show-result-dialog", title, message }, sessionID);
20145
21106
  }
20146
- function adaptPayload(draft, admittedIDs = new Set) {
20147
- const existingHeads = new Map(draft.messages.filter((m) => HEAD_IDS.some((id) => m.id === id)).map((m) => [m.id, m]));
20148
- const source = draft.messages.filter((m) => !existingHeads.has(m.id));
20149
- const results = new Map;
20150
- const hostParts = new Map;
20151
- const hostPartTypes = new Set;
20152
- for (const message of source) {
20153
- for (const part of message.content) {
20154
- if (part.type !== "tool-call" && part.type !== "tool-result" && part.type !== "tool" && containsHostInstance(part)) {
20155
- const key = contentKey(part);
20156
- if (!hostParts.has(key))
20157
- hostParts.set(key, part);
20158
- hostPartTypes.add(part.type);
20159
- }
20160
- if (part.type === "tool-result" && typeof part.id === "string") {
20161
- const queue = results.get(part.id) ?? [];
20162
- queue.push({ part, message });
20163
- results.set(part.id, queue);
20164
- }
20165
- }
21107
+ function reportUsage(sessionID, message) {
21108
+ pushNotification2("toast", { message, variant: "warning" }, sessionID);
21109
+ }
21110
+ function reportRpcReply(sessionID, title, reply, pending) {
21111
+ if (reply.ok !== true) {
21112
+ const error = typeof reply.error === "string" ? reply.error : `${title} request failed`;
21113
+ pushNotification2("toast", { message: error, variant: "error" }, sessionID);
21114
+ return;
20166
21115
  }
20167
- const paired = new Set;
20168
- const bridges = new Map;
20169
- const originals = new Map;
20170
- const bridgesByMessageID = new Map;
20171
- const bridgesByCarrier = new Map;
20172
- const originalsByID = new Map;
20173
- const bridgesFor = (message) => typeof message.info.id === "string" ? bridgesByMessageID.get(message.info.id) : bridgesByCarrier.get(message);
20174
- const nativeTool = (call, result) => {
20175
- const hostResult = result?.part.result;
20176
- const failed = result !== undefined && isToolError(result.part);
20177
- const value = hostResult?.value;
20178
- const files = fileContentValue(hostResult);
20179
- const output = failed && hostResult ? toolErrorText(hostResult) : files ? contentValueText(files) : typeof value === "string" ? value : value === undefined ? "" : JSON.stringify(value);
20180
- const part = {
20181
- type: "tool",
20182
- callID: call?.id ?? result?.part.id,
20183
- tool: call?.name ?? result?.part.name,
20184
- state: {
20185
- input: structuredClone(call?.input ?? {}),
20186
- status: failed ? "error" : result ? "completed" : "running",
20187
- ...result ? { output } : {},
20188
- ...result && (call?.name ?? result.part.name) === "question" ? { metadata: { userAnswer: true } } : {},
20189
- ...files ? { attachments: contentValueAttachments(files) } : {}
21116
+ if (reply.started === true) {
21117
+ pushNotification2("toast", { message: pending, variant: "info" }, sessionID);
21118
+ return;
21119
+ }
21120
+ reportResult(sessionID, title, typeof reply.message === "string" ? reply.message : "");
21121
+ }
21122
+ function buildV2Commands(rpc, directory) {
21123
+ return [
21124
+ {
21125
+ name: "mmc-status",
21126
+ execute: async (input) => {
21127
+ const detail = await rpc.dispatch("status-detail", {
21128
+ sessionId: input.sessionID,
21129
+ directory
21130
+ });
21131
+ if (typeof detail.error === "string") {
21132
+ throw new Error(`Magic Context status is unavailable: ${detail.error}`);
21133
+ }
21134
+ pushNotification2("action", { action: "show-status-dialog" }, input.sessionID);
20190
21135
  }
20191
- };
20192
- bridges.set(part, {
20193
- call,
20194
- result: result?.part,
20195
- resultMessage: result?.message,
20196
- output,
20197
- files
20198
- });
20199
- if (result)
20200
- paired.add(result.part);
20201
- return part;
20202
- };
20203
- const convertedTool = (source) => {
20204
- const sourceState = source.state && typeof source.state === "object" ? source.state : {};
20205
- const output = toolStateContent(sourceState);
20206
- const { content: _content, ...projectedState } = structuredClone(sourceState);
20207
- const part = {
20208
- type: "tool",
20209
- callID: source.callID ?? source.id,
20210
- tool: source.tool ?? source.name,
20211
- state: { ...projectedState, output }
20212
- };
20213
- bridges.set(part, { native: source, output });
20214
- return part;
20215
- };
20216
- const callParts = new Map;
20217
- for (const message of source) {
20218
- for (const part of message.content) {
20219
- if (part.type === "tool-call") {
20220
- callParts.set(part, nativeTool(part, results.get(String(part.id))?.shift()));
20221
- } else if (part.type === "tool") {
20222
- callParts.set(part, convertedTool(part));
21136
+ },
21137
+ {
21138
+ name: "mmc-recomp",
21139
+ execute: async (input) => {
21140
+ if (isTuiConnected2(input.sessionID)) {
21141
+ pushNotification2("action", { action: "show-recomp-dialog" }, input.sessionID);
21142
+ return;
21143
+ }
21144
+ const reply = await rpc.dispatch("recomp", { sessionId: input.sessionID });
21145
+ if (reply.ok !== true) {
21146
+ throw new Error("Magic Context could not start the history rebuild.");
21147
+ }
20223
21148
  }
20224
- }
20225
- }
20226
- const messages = [];
20227
- for (const message of source) {
20228
- const parts = [];
20229
- for (const content of message.content) {
20230
- if (paired.has(content))
20231
- continue;
20232
- const part = callParts.get(content) ?? (content.type === "tool-result" ? nativeTool(undefined, { part: content, message }) : clonePreservingInstances(content));
20233
- if (message.id && admittedIDs.has(message.id))
20234
- part.synthetic = true;
20235
- parts.push(part);
20236
- }
20237
- if (!parts.length && message.content.length)
20238
- continue;
20239
- const byCallID = new Map;
20240
- for (const part of parts) {
20241
- const bridge = bridges.get(part);
20242
- if (bridge && typeof part.callID === "string")
20243
- byCallID.set(part.callID, bridge);
20244
- }
20245
- if (typeof message.id === "string") {
20246
- bridgesByMessageID.set(message.id, byCallID);
20247
- originalsByID.set(message.id, message);
20248
- }
20249
- const mapped = {
20250
- info: {
20251
- id: message.id,
20252
- sessionID: draft.sessionID,
20253
- role: message.role,
20254
- ...{
20255
- providerID: draft.model.providerID,
20256
- modelID: draft.model.id,
20257
- agent: draft.agent
21149
+ },
21150
+ {
21151
+ name: "mmc-flush",
21152
+ execute: async (input) => {
21153
+ const reply = await rpc.dispatch("flush", { sessionId: input.sessionID });
21154
+ reportRpcReply(input.sessionID, "Flush", reply, "Flush started");
21155
+ }
21156
+ },
21157
+ {
21158
+ name: "mmc-wrapup",
21159
+ execute: async (input) => {
21160
+ const argument = commandArgument(input, "mmc-wrapup");
21161
+ if (argument !== "" && !/^\d+$/.test(argument)) {
21162
+ const usage = "Usage: /mmc-wrapup [messages_to_keep] where messages_to_keep is a positive integer";
21163
+ reportUsage(input.sessionID, usage);
21164
+ throw new Error(usage);
20258
21165
  }
20259
- },
20260
- parts
20261
- };
20262
- originals.set(mapped, message);
20263
- if (typeof message.id !== "string")
20264
- bridgesByCarrier.set(mapped, byCallID);
20265
- messages.push(mapped);
20266
- }
20267
- return {
20268
- messages,
20269
- commit() {
20270
- let head = 0;
20271
- const rendered = [];
20272
- for (const message of messages) {
20273
- const original = originals.get(message) ?? (typeof message.info.id === "string" ? originalsByID.get(message.info.id) : undefined);
20274
- const id = message.info.syntheticHead ? HEAD_IDS[head++] : original?.id;
20275
- const content = [];
20276
- const following = [];
20277
- for (const candidate of message.parts) {
20278
- const part = candidate;
20279
- const bridge = bridges.get(part) ?? (part.type === "tool" && typeof part.callID === "string" ? bridgesFor(message)?.get(part.callID) : undefined);
20280
- if (!bridge) {
20281
- if (part.type === "tool") {
20282
- const state = part.state;
20283
- if (typeof part.callID !== "string" || typeof part.tool !== "string" || !state || typeof state !== "object") {
20284
- rejectContentPart(message, part, "tool has no call ID, name, or state");
20285
- continue;
20286
- }
20287
- content.push({
20288
- type: "tool-call",
20289
- id: part.callID,
20290
- name: part.tool,
20291
- input: state.input
20292
- });
20293
- if (state.status === "completed" || state.status === "error") {
20294
- following.push({
20295
- role: "tool",
20296
- content: [
20297
- {
20298
- type: "tool-result",
20299
- id: part.callID,
20300
- name: part.tool,
20301
- result: {
20302
- type: state.status === "error" ? "error" : "text",
20303
- value: toolStateContent(state)
20304
- }
20305
- }
20306
- ]
20307
- });
20308
- }
20309
- continue;
20310
- }
20311
- if (part.type === "file") {
20312
- const mime = part.mime;
20313
- const url = part.url;
20314
- const prefix = `data:${mime};base64,`;
20315
- if (typeof mime !== "string" || !/^image\/(png|jpeg|gif|webp)$/.test(mime) || typeof url !== "string" || !url.startsWith(prefix)) {
20316
- rejectContentPart(message, part, "file is not an inline supported image");
20317
- continue;
20318
- }
20319
- const asset = hostMediaAsset(url.slice(prefix.length), mime);
20320
- if (typeof asset === "string") {
20321
- rejectContentPart(message, part, `host media unavailable: ${asset}`);
20322
- continue;
20323
- }
20324
- content.push({ type: "media", media: asset });
20325
- continue;
20326
- }
20327
- if (!HOST_CONTENT_TYPES.has(String(part.type))) {
20328
- rejectContentPart(message, part, "unknown host content type");
20329
- continue;
20330
- }
20331
- const { synthetic: _synthetic, ...clean } = part;
20332
- const original = hostPartTypes.has(clean.type) && !containsHostInstance(clean) ? hostParts.get(contentKey(clean)) : undefined;
20333
- content.push(original ?? clean);
20334
- continue;
20335
- }
20336
- const state = part.state;
20337
- if (bridge.native) {
20338
- const native = bridge.native;
20339
- const callID = String(native.id ?? native.callID ?? part.callID);
20340
- const name = String(native.name ?? native.tool ?? part.tool);
20341
- content.push({ type: "tool-call", id: callID, name, input: state.input });
20342
- if (state.status === "completed" || state.status === "error") {
20343
- following.push({
20344
- role: "tool",
20345
- content: [
20346
- {
20347
- type: "tool-result",
20348
- id: callID,
20349
- name,
20350
- result: {
20351
- type: state.status === "error" ? "error" : "text",
20352
- value: state.output
20353
- }
20354
- }
20355
- ]
20356
- });
20357
- }
20358
- continue;
20359
- }
20360
- if (bridge.call)
20361
- content.push({ ...bridge.call, input: state.input });
20362
- if (bridge.result && bridge.resultMessage) {
20363
- const result = {
20364
- ...bridge.result,
20365
- result: state.output === bridge.output ? bridge.result.result : bridge.files && typeof state.output === "string" ? rebuildFileContent(bridge.files, state.output) : {
20366
- type: state.status === "error" ? "error" : "text",
20367
- value: state.output
20368
- }
20369
- };
20370
- if (bridge.resultMessage === original)
20371
- content.push(result);
20372
- else
20373
- following.push({ ...bridge.resultMessage, content: [result] });
20374
- }
21166
+ const messagesToKeep = argument === "" ? 20 : Number.parseInt(argument, 10);
21167
+ if (messagesToKeep <= 0) {
21168
+ const usage = "messages_to_keep must be a positive integer";
21169
+ reportUsage(input.sessionID, usage);
21170
+ throw new Error(usage);
20375
21171
  }
20376
- if (content.length || !original?.content.length) {
20377
- const value = {
20378
- ...original,
20379
- id,
20380
- role: message.info.role ?? "user",
20381
- content
20382
- };
20383
- const existing = id ? existingHeads.get(id) : undefined;
20384
- rendered.push(existing ? Object.assign(existing, { content }) : value);
21172
+ const reply = await rpc.dispatch("wrapup", {
21173
+ sessionId: input.sessionID,
21174
+ messagesToKeep
21175
+ });
21176
+ reportRpcReply(input.sessionID, "Wrapup", reply, "Wrapup started; the summary appears when it finishes");
21177
+ }
21178
+ },
21179
+ {
21180
+ name: "mmc-memory-maintain",
21181
+ execute: async (input) => {
21182
+ const argument = commandArgument(input, "mmc-memory-maintain");
21183
+ const subcommand = argument === "" ? "status" : argument.trim().toLowerCase();
21184
+ if (subcommand !== "run" && subcommand !== "status" && subcommand !== "resume") {
21185
+ const usage = "Usage: /mmc-memory-maintain [run|status|resume] — status is the default";
21186
+ reportUsage(input.sessionID, usage);
21187
+ throw new Error(usage);
20385
21188
  }
20386
- rendered.push(...following);
21189
+ const reply = await rpc.dispatch("maintenance", {
21190
+ sessionId: input.sessionID,
21191
+ subcommand
21192
+ });
21193
+ reportRpcReply(input.sessionID, "Memory maintenance", reply, "Maintenance run started; see /mmc-memory-maintain status for the outcome");
20387
21194
  }
20388
- draft.messages.splice(0, draft.messages.length, ...rendered);
20389
21195
  }
20390
- };
21196
+ ];
21197
+ }
21198
+
21199
+ // src/v2/hooks/deleted-session-tombstones.ts
21200
+ class DeletedSessionTombstones {
21201
+ limit;
21202
+ #ids = new Set;
21203
+ constructor(limit = 1000) {
21204
+ this.limit = limit;
21205
+ if (!Number.isSafeInteger(limit) || limit < 1) {
21206
+ throw new Error("Deleted-session tombstone limit must be a positive integer");
21207
+ }
21208
+ }
21209
+ add(sessionID) {
21210
+ this.#ids.delete(sessionID);
21211
+ this.#ids.add(sessionID);
21212
+ while (this.#ids.size > this.limit) {
21213
+ const oldest = this.#ids.values().next().value;
21214
+ if (oldest === undefined)
21215
+ break;
21216
+ this.#ids.delete(oldest);
21217
+ }
21218
+ }
21219
+ has(sessionID) {
21220
+ return this.#ids.has(sessionID);
21221
+ }
21222
+ clear() {
21223
+ this.#ids.clear();
21224
+ }
21225
+ get size() {
21226
+ return this.#ids.size;
21227
+ }
20391
21228
  }
20392
21229
 
20393
21230
  // src/v2/hooks/generate.ts
@@ -20433,9 +21270,9 @@ function hiddenTerminalError(event) {
20433
21270
  }
20434
21271
 
20435
21272
  // src/v2/hooks/lkg-system.ts
20436
- import { createHash as createHash6 } from "node:crypto";
20437
- function identity(slot) {
20438
- return createHash6("sha256").update(JSON.stringify({
21273
+ import { createHash as createHash7 } from "node:crypto";
21274
+ function identity2(slot) {
21275
+ return createHash7("sha256").update(JSON.stringify({
20439
21276
  capturedAt: slot.capturedAt,
20440
21277
  captureSequence: slot.captureSequence,
20441
21278
  rowVersion: slot.rowVersion,
@@ -20450,14 +21287,14 @@ class V2LkgSystemReplay {
20450
21287
  systems = new BoundedSessionMap(1000);
20451
21288
  capture(sessionId, slot, input, served) {
20452
21289
  this.systems.set(sessionId, {
20453
- slot: identity(slot),
21290
+ slot: identity2(slot),
20454
21291
  input: JSON.stringify(input),
20455
21292
  served: structuredClone(served)
20456
21293
  });
20457
21294
  }
20458
21295
  restore(sessionId, slot, input, target) {
20459
21296
  const saved = this.systems.get(sessionId);
20460
- if (!slot || !saved || saved.slot !== identity(slot) || saved.input !== JSON.stringify(input))
21297
+ if (!slot || !saved || saved.slot !== identity2(slot) || saved.input !== JSON.stringify(input))
20461
21298
  return false;
20462
21299
  target.splice(0, target.length, ...structuredClone(saved.served));
20463
21300
  return true;
@@ -20642,7 +21479,7 @@ function hasRequiredSessionAPI(session) {
20642
21479
  }
20643
21480
 
20644
21481
  // src/features/magic-context/session-project-backfill.ts
20645
- import { randomUUID as randomUUID2 } from "node:crypto";
21482
+ import { randomUUID as randomUUID4 } from "node:crypto";
20646
21483
  import { existsSync as existsSync7 } from "node:fs";
20647
21484
  var LEASE_TTL_MS = 10 * 60 * 1000;
20648
21485
  var SESSION_PAGE_SIZE = 100;
@@ -20784,7 +21621,7 @@ async function runSessionProjectBackfill(db, source, options = {}) {
20784
21621
  const now = options.now ?? Date.now;
20785
21622
  const resolveIdentity = options.resolveIdentity ?? ((directory) => resolveProjectIdentityForSession(directory, options.allowHomeProject));
20786
21623
  const yieldFn = options.yieldFn ?? defaultYieldFn;
20787
- const holderId = options.holderId ?? randomUUID2();
21624
+ const holderId = options.holderId ?? randomUUID4();
20788
21625
  const readPage = createPageReader(source);
20789
21626
  const result = {
20790
21627
  status: "completed",
@@ -21377,7 +22214,7 @@ function resolveCtxExpandMode(args, domain) {
21377
22214
  }
21378
22215
 
21379
22216
  // src/tools/ctx-expand/render.ts
21380
- import { createHash as createHash7 } from "node:crypto";
22217
+ import { createHash as createHash8 } from "node:crypto";
21381
22218
  function isRecord4(value) {
21382
22219
  return value !== null && typeof value === "object" && !Array.isArray(value);
21383
22220
  }
@@ -21466,7 +22303,7 @@ function reasoningOf(part) {
21466
22303
  function renderPartPreview(part, expandTools) {
21467
22304
  if (!isRecord4(part))
21468
22305
  return null;
21469
- const expansion = expandToolPart(part, expandTools);
22306
+ const expansion = expandToolPart(part, expandTools, true);
21470
22307
  if (expansion !== null)
21471
22308
  return ` • tool ${part.tool}: ${expansion}`;
21472
22309
  const text = textOf(part);
@@ -21601,7 +22438,7 @@ function renderItemByTag(db, sessionId, number, textIndexDomain = "part") {
21601
22438
  const index = scoped ? Number(scoped[2]) : 0;
21602
22439
  const piText = message.parts.filter((part) => isRecord4(part) && part.type === "text");
21603
22440
  const part = message.parts[index];
21604
- const matching = derived ? piText.filter((part) => isRecord4(part) && typeof part.text === "string" && createHash7("sha256").update(part.text).digest("hex") === derived[3]) : [];
22441
+ const matching = derived ? piText.filter((part) => isRecord4(part) && typeof part.text === "string" && createHash8("sha256").update(part.text).digest("hex") === derived[3]) : [];
21605
22442
  const selected = derived ? matching[Number(derived[4])] : textIndexDomain === "text" ? piText[index] : part;
21606
22443
  return selected ? renderPartFull(selected) ?? "" : `Tag ${number}'s original text part is no longer in stored history.`;
21607
22444
  }
@@ -22912,6 +23749,9 @@ function persistV2UsageReading(args) {
22912
23749
 
22913
23750
  // src/v2/hooks/context.ts
22914
23751
  var HIDDEN_SESSION_ERROR_GRACE_MS = 50;
23752
+
23753
+ class V2LkgAdmissionReplay extends Error {
23754
+ }
22915
23755
  function isBlockingV2TransformError(error) {
22916
23756
  return error instanceof EmergencyFailClosedError || error instanceof UnresolvedHistoryBoundaryError || error instanceof UnmanagedOverWindowError || error instanceof DegradedPassRefusalError || isFailClosedBlockingError(error);
22917
23757
  }
@@ -23120,6 +23960,8 @@ async function registerContext(context) {
23120
23960
  return;
23121
23961
  }
23122
23962
  const folds = new FoldOwner(context.storage);
23963
+ const nativeFoldMemory = !compactionOff && process.env.MMC_OC2_INVISIBLE_FOLD === "1" ? nativeFoldCache(() => storage.require()) : undefined;
23964
+ const nativeFoldReplay = nativeFoldMemory ? new NativeFoldReplay(nativeFoldMemory, () => openStoreReader()) : undefined;
23123
23965
  setOutputReserveConfig(config.output_reserve);
23124
23966
  const queriedModels = new Set;
23125
23967
  const rawLimits = new Map;
@@ -23151,7 +23993,7 @@ async function registerContext(context) {
23151
23993
  let storageRecoveryAnnounced = false;
23152
23994
  const storageNoticeBySession = new Map;
23153
23995
  const storeStorageNotice = (sessionID, text, what) => {
23154
- withoutSqliteTransformPass(() => context.session.wait({ sessionID }).then(() => deliverSynthetic(context, sessionID, text)).catch((error) => sessionLog(sessionID, `v2 storage ${what} notice could not be delivered:`, error)));
23996
+ withoutSqliteTransformPass(() => Promise.resolve().then(() => context.session.wait({ sessionID })).then(() => deliverSynthetic(context, sessionID, text)).catch((error) => sessionLog(sessionID, `v2 storage ${what} notice could not be delivered:`, error)));
23155
23997
  };
23156
23998
  const noticeStorageRefusal = (sessionID, reason) => {
23157
23999
  const message = formatStorageRefusalNotice(reason);
@@ -23418,6 +24260,14 @@ async function registerContext(context) {
23418
24260
  }
23419
24261
  return unsafe;
23420
24262
  };
24263
+ const hostFolds = nativeFoldReplay && nativeFoldMemory ? new HostFoldPolicy({
24264
+ session: context.session,
24265
+ storage: nativeFoldMemory,
24266
+ openReader: openStoreReader,
24267
+ canReplay: (sessionID, reader) => nativeFoldReplay.canReplay(sessionID, reader),
24268
+ threshold: Number(process.env.MMC_OC2_HOST_FOLD_ROWS ?? 1000),
24269
+ log: sessionLog
24270
+ }) : undefined;
23421
24271
  const usageController = new AbortController;
23422
24272
  const usageDone = (async () => {
23423
24273
  try {
@@ -23428,6 +24278,10 @@ async function registerContext(context) {
23428
24278
  if (!event.data?.sessionID)
23429
24279
  continue;
23430
24280
  const sessionID = event.data.sessionID;
24281
+ if (event.type?.startsWith("session.revert.") || event.type === "session.message.content.updated") {
24282
+ nativeFoldReplay?.onEvent(event);
24283
+ restoredRows.forget(sessionID);
24284
+ }
23431
24285
  if (event.type === "session.error" || event.type === "session.execution.failed") {
23432
24286
  const error = hiddenTerminalError(event);
23433
24287
  if (error !== undefined)
@@ -23453,6 +24307,7 @@ async function registerContext(context) {
23453
24307
  pendingMaterializationSessions.delete(sessionID);
23454
24308
  lastHeuristicsTurnId.delete(sessionID);
23455
24309
  restoredRows.forget(sessionID);
24310
+ await nativeFoldReplay?.forget(sessionID);
23456
24311
  generateReplay.forget(sessionID);
23457
24312
  systemPromptRefreshSessions.delete(sessionID);
23458
24313
  systemPrompt?.clearSession(sessionID);
@@ -23465,11 +24320,14 @@ async function registerContext(context) {
23465
24320
  if (event.type !== "session.execution.succeeded")
23466
24321
  continue;
23467
24322
  const model = liveModels.get(sessionID);
23468
- if (model)
24323
+ if (model) {
23469
24324
  await recordUsage({
23470
24325
  sessionID,
23471
24326
  model: { providerID: model.providerID, id: model.modelID }
23472
24327
  });
24328
+ if (!compactionOff && typeof await nativeFoldReplay?.baseline(sessionID) === "string")
24329
+ hostFolds?.idle(sessionID);
24330
+ }
23473
24331
  }
23474
24332
  } catch (error) {
23475
24333
  if (!usageController.signal.aborted)
@@ -23504,10 +24362,32 @@ async function registerContext(context) {
23504
24362
  }
23505
24363
  if (compactionOff)
23506
24364
  return;
24365
+ if (nativeFoldReplay)
24366
+ rememberHostMedia(draft.messages);
23507
24367
  const reader = openStoreReader();
23508
24368
  try {
23509
24369
  const watermark = reader.latestSequenceForIds(draft.sessionID, draft.messages.flatMap((message) => message.id ? [message.id] : []));
23510
24370
  const running = reader.latestRunningCompaction(draft.sessionID);
24371
+ if (nativeFoldReplay) {
24372
+ try {
24373
+ if (await nativeFoldReplay.canReplay(draft.sessionID, reader)) {
24374
+ const state = getOrCreateSessionMeta(storage.require(), draft.sessionID);
24375
+ const summary = await nativeFoldReplay.baseline(draft.sessionID) ?? state.cachedM0Bytes?.toString("utf8") ?? "<session-history></session-history>";
24376
+ if (await nativeFoldReplay.supply({
24377
+ draft,
24378
+ reader,
24379
+ previousCut: reader.latestCompaction(draft.sessionID),
24380
+ summary
24381
+ })) {
24382
+ draft.result = { summary };
24383
+ return;
24384
+ }
24385
+ }
24386
+ } catch (error) {
24387
+ nativeFoldReplay.invalidate(draft.sessionID, true);
24388
+ sessionLog(draft.sessionID, `v2 host fold: legacy compaction reason=${JSON.stringify(String(error))}`);
24389
+ }
24390
+ }
23511
24391
  const fold = await folds.supply({
23512
24392
  sessionID: draft.sessionID,
23513
24393
  watermark,
@@ -23554,12 +24434,88 @@ async function registerContext(context) {
23554
24434
  withoutSqliteTransformPass(() => warmModelLimitCacheFromCatalog(context));
23555
24435
  agents.set(draft.sessionID, draft.agent);
23556
24436
  applyV2PromptSurfaceTools(draft, promptSurfaceRuntime, config.prompt_surface);
24437
+ const admissionDb = db ?? storage.current();
24438
+ const replayFits = (messages) => {
24439
+ const system = structuredClone(draft.system);
24440
+ if (!admissionDb || !draft.tools || !lkgSystems.restore(draft.sessionID, getSlot(draft.sessionID), draft.system, system))
24441
+ return false;
24442
+ const limit = lkgReplayLimit({
24443
+ db: admissionDb,
24444
+ sessionId: draft.sessionID,
24445
+ model: {
24446
+ providerID: draft.model.providerID,
24447
+ modelID: draft.model.id
24448
+ },
24449
+ modelKey: `${draft.model.providerID}/${draft.model.id}`
24450
+ });
24451
+ if (limit === undefined)
24452
+ return false;
24453
+ let toolDefinitionTokens = 0;
24454
+ for (const tool of Object.values(draft.tools)) {
24455
+ if (!tool || typeof tool.description !== "string" || !tool.input)
24456
+ return false;
24457
+ const schema = JSON.stringify(tool.input);
24458
+ if (!schema)
24459
+ return false;
24460
+ toolDefinitionTokens += estimateTokens(tool.description) + estimateTokens(schema);
24461
+ }
24462
+ return measureLkgReplay({
24463
+ messages,
24464
+ limit,
24465
+ estimate: () => estimateFinalWireInputTokens({
24466
+ messages,
24467
+ toolDefinitionTokens,
24468
+ systemPromptTokens: estimateTokens(JSON.stringify(system)),
24469
+ providerID: draft.model.providerID,
24470
+ modelID: draft.model.id,
24471
+ agentName: draft.agent
24472
+ })
24473
+ }).fit === "under";
24474
+ };
23557
24475
  let postFold = false;
23558
24476
  try {
23559
- const admissionDb = db ?? storage.current();
23560
24477
  if (!compactionOff && admissionDb)
23561
24478
  await withAsyncPrivilegedWriter(admissionDb, () => {
23562
24479
  return;
24480
+ }, {
24481
+ beforeRetry: (_error) => {
24482
+ let replayBlocked = false;
24483
+ const mapped = adaptPayload(draft);
24484
+ try {
24485
+ const overflowDb = db;
24486
+ if (overflowDb !== undefined && overflowDb !== null && (isEmergencyRecoveryArmed(draft.sessionID) || getOverflowState(overflowDb, draft.sessionID).needsEmergencyRecovery)) {
24487
+ replayBlocked = true;
24488
+ sessionLog(draft.sessionID, "lkg_emergency_armed");
24489
+ } else {
24490
+ const keys = resolveLkgModelKeys(mapped.messages);
24491
+ const replay = replayLkg({
24492
+ sessionId: draft.sessionID,
24493
+ messages: mapped.messages,
24494
+ modelKey: keys.modelKey,
24495
+ providerKey: keys.providerKey
24496
+ });
24497
+ if (replay.ok && !replayFits(replay.messages)) {
24498
+ replayBlocked = true;
24499
+ sessionLog(draft.sessionID, "lkg_replay_does_not_fit");
24500
+ } else if (replay.ok) {
24501
+ restoreLkgSystem();
24502
+ mapped.messages.splice(0, mapped.messages.length, ...replay.messages);
24503
+ mapped.commit();
24504
+ sessionLog(draft.sessionID, "lkg_replay_served");
24505
+ throw new V2LkgAdmissionReplay;
24506
+ } else {
24507
+ sessionLog(draft.sessionID, replay.reason);
24508
+ }
24509
+ }
24510
+ } catch (replayError) {
24511
+ if (replayError instanceof V2LkgAdmissionReplay)
24512
+ throw replayError;
24513
+ replayBlocked = true;
24514
+ sessionLog(draft.sessionID, "lkg_replay_unavailable", replayError);
24515
+ }
24516
+ if (replayBlocked)
24517
+ sessionLog(draft.sessionID, "lkg_replay_declined");
24518
+ }
23563
24519
  });
23564
24520
  if (admissionDb)
23565
24521
  hideSubagentTools(draft, admissionDb);
@@ -23714,7 +24670,28 @@ async function registerContext(context) {
23714
24670
  postFold = cut !== undefined;
23715
24671
  if (cut && !incoming)
23716
24672
  throw new Error("The host checkpoint disappeared from the context draft");
23717
- if (cut && incoming) {
24673
+ let nativeRestored;
24674
+ if (cut && nativeFoldReplay && isLocalCheckpoint(cut)) {
24675
+ try {
24676
+ nativeRestored = await nativeFoldReplay.restore(draft.sessionID, cut, `${draft.model.providerID}/${draft.model.id}`, { bounded: true });
24677
+ } catch (error) {
24678
+ nativeFoldReplay.invalidate(draft.sessionID, true);
24679
+ sessionLog(draft.sessionID, "v2 host fold: cache unavailable; restoring host rows", error);
24680
+ nativeRestored = await nativeFoldReplay.restoreRead(draft.sessionID, cut, draft.model);
24681
+ }
24682
+ }
24683
+ if (nativeRestored && nativeFoldReplay?.sourceChanged(draft.sessionID)) {
24684
+ historyRefreshSessions.add(draft.sessionID);
24685
+ pendingMaterializationSessions.add(draft.sessionID);
24686
+ }
24687
+ if (cut && incoming && nativeRestored) {
24688
+ const present = new Set(draft.messages.flatMap((message) => message.id ? [message.id] : []));
24689
+ const hidden = nativeRestored.filter((message) => {
24690
+ const id = nativeRowID(message);
24691
+ return !id || !present.has(id);
24692
+ });
24693
+ draft.messages.splice(0, draft.messages.length, ...hidden, ...draft.messages.filter((message) => message !== incoming));
24694
+ } else if (cut && incoming) {
23718
24695
  const identity = await folds.observe({
23719
24696
  sessionID: draft.sessionID,
23720
24697
  cutSeq: cut.seq,
@@ -23741,6 +24718,14 @@ async function registerContext(context) {
23741
24718
  } finally {
23742
24719
  reader.close();
23743
24720
  }
24721
+ let nativeMessages;
24722
+ if (nativeFoldReplay) {
24723
+ try {
24724
+ nativeMessages = copyNativeInput(draft.messages);
24725
+ } catch {
24726
+ nativeFoldReplay.invalidate(draft.sessionID, true);
24727
+ }
24728
+ }
23744
24729
  const mapped = adaptPayload(draft, admitted);
23745
24730
  beginV2LkgRequest(draft.sessionID, `${draft.model.providerID}/${draft.model.id}`, latestLkgResponseIds.get(draft.sessionID));
23746
24731
  await transform({}, mapped);
@@ -23766,6 +24751,14 @@ ${baseline}
23766
24751
  draft.messages.splice(0, draft.messages.length, checkpoint, ...draft.messages.filter((message) => message !== head));
23767
24752
  }
23768
24753
  }
24754
+ if (nativeMessages && !checkpoint) {
24755
+ try {
24756
+ await nativeFoldReplay?.capture(draft, nativeMessages);
24757
+ } catch (error) {
24758
+ nativeFoldReplay?.invalidate(draft.sessionID, true);
24759
+ sessionLog(draft.sessionID, "v2 host fold: optional capture unavailable", error);
24760
+ }
24761
+ }
23769
24762
  const capturedSlot = getSlot(draft.sessionID);
23770
24763
  if (capturedSlot && (!slotAtEntry || capturedSlot.capturedAt !== slotAtEntry.capturedAt || capturedSlot.captureSequence !== slotAtEntry.captureSequence || capturedSlot.jsonPrefix !== slotAtEntry.jsonPrefix)) {
23771
24764
  lkgSystems.capture(draft.sessionID, capturedSlot, systemAtEntry, draft.system);
@@ -23773,6 +24766,8 @@ ${baseline}
23773
24766
  } catch (error) {
23774
24767
  if (error instanceof V2ContextRefusal)
23775
24768
  throw error;
24769
+ if (error instanceof V2LkgAdmissionReplay)
24770
+ return;
23776
24771
  if (!compactionOff && (isTransientSqliteError(error) || error instanceof StorageBusyRefusalError)) {
23777
24772
  if (isTransientSqliteError(error)) {
23778
24773
  try {
@@ -23800,13 +24795,16 @@ ${baseline}
23800
24795
  modelKey: keys.modelKey,
23801
24796
  providerKey: keys.providerKey
23802
24797
  });
23803
- if (replay.ok) {
24798
+ if (replay.ok && !replayFits(replay.messages)) {
24799
+ sessionLog(draft.sessionID, "lkg_replay_does_not_fit");
24800
+ } else if (replay.ok) {
23804
24801
  restoreLkgSystem();
23805
24802
  replayMapped.messages.splice(0, replayMapped.messages.length, ...replay.messages);
23806
24803
  replayMapped.commit();
23807
24804
  return;
24805
+ } else {
24806
+ sessionLog(draft.sessionID, replay.reason);
23808
24807
  }
23809
- sessionLog(draft.sessionID, replay.reason);
23810
24808
  }
23811
24809
  } catch (replayError) {
23812
24810
  replayBlocked = true;