@cortexkit/opencode-magic-context 0.42.2 → 0.42.4

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 (126) hide show
  1. package/README.md +3 -1
  2. package/dist/{announcement-3c1vertn.js → announcement-8mgn61fw.js} +1 -1
  3. package/dist/{conflict-warning-hook-6p3xqeac.js → conflict-warning-hook-jyj54gbe.js} +4 -4
  4. package/dist/{derive-budgets-s2pgnnm4.js → derive-budgets-v1fkhjjr.js} +2 -2
  5. package/dist/features/magic-context/compaction-marker.d.ts +4 -10
  6. package/dist/features/magic-context/compaction-marker.d.ts.map +1 -1
  7. package/dist/features/magic-context/context-authority.d.ts +13 -0
  8. package/dist/features/magic-context/context-authority.d.ts.map +1 -1
  9. package/dist/features/magic-context/dreamer/classify.d.ts +3 -1
  10. package/dist/features/magic-context/dreamer/classify.d.ts.map +1 -1
  11. package/dist/features/magic-context/dreamer/task-executor.d.ts +6 -2
  12. package/dist/features/magic-context/dreamer/task-executor.d.ts.map +1 -1
  13. package/dist/features/magic-context/dreamer/task-registry.d.ts +3 -0
  14. package/dist/features/magic-context/dreamer/task-registry.d.ts.map +1 -1
  15. package/dist/features/magic-context/mural/compress-cues.d.ts +3 -1
  16. package/dist/features/magic-context/mural/compress-cues.d.ts.map +1 -1
  17. package/dist/features/magic-context/transform-decision-log.d.ts +4 -0
  18. package/dist/features/magic-context/transform-decision-log.d.ts.map +1 -1
  19. package/dist/hooks/magic-context/apply-operations.d.ts +4 -1
  20. package/dist/hooks/magic-context/apply-operations.d.ts.map +1 -1
  21. package/dist/hooks/magic-context/caveman-cleanup.d.ts +4 -0
  22. package/dist/hooks/magic-context/caveman-cleanup.d.ts.map +1 -1
  23. package/dist/hooks/magic-context/compartment-runner-historian.d.ts +5 -2
  24. package/dist/hooks/magic-context/compartment-runner-historian.d.ts.map +1 -1
  25. package/dist/hooks/magic-context/compartment-runner-incremental.d.ts +2 -2
  26. package/dist/hooks/magic-context/compartment-runner-incremental.d.ts.map +1 -1
  27. package/dist/hooks/magic-context/compartment-runner-types.d.ts +61 -2
  28. package/dist/hooks/magic-context/compartment-runner-types.d.ts.map +1 -1
  29. package/dist/hooks/magic-context/compartment-runner.d.ts +2 -2
  30. package/dist/hooks/magic-context/compartment-runner.d.ts.map +1 -1
  31. package/dist/hooks/magic-context/dropped-token-estimate.d.ts +20 -0
  32. package/dist/hooks/magic-context/dropped-token-estimate.d.ts.map +1 -0
  33. package/dist/hooks/magic-context/heuristic-cleanup.d.ts +2 -0
  34. package/dist/hooks/magic-context/heuristic-cleanup.d.ts.map +1 -1
  35. package/dist/hooks/magic-context/hook.d.ts +2 -2
  36. package/dist/hooks/magic-context/hook.d.ts.map +1 -1
  37. package/dist/hooks/magic-context/module-transport.d.ts +4 -1
  38. package/dist/hooks/magic-context/module-transport.d.ts.map +1 -1
  39. package/dist/hooks/magic-context/read-session-db.d.ts.map +1 -1
  40. package/dist/hooks/magic-context/read-session-raw.d.ts +4 -4
  41. package/dist/hooks/magic-context/read-session-raw.d.ts.map +1 -1
  42. package/dist/hooks/magic-context/rust-mode-transform.d.ts +2 -0
  43. package/dist/hooks/magic-context/rust-mode-transform.d.ts.map +1 -1
  44. package/dist/hooks/magic-context/transform-compartment-phase.d.ts +3 -0
  45. package/dist/hooks/magic-context/transform-compartment-phase.d.ts.map +1 -1
  46. package/dist/hooks/magic-context/transform-postprocess-phase.d.ts +8 -0
  47. package/dist/hooks/magic-context/transform-postprocess-phase.d.ts.map +1 -1
  48. package/dist/hooks/magic-context/transform.d.ts +21 -0
  49. package/dist/hooks/magic-context/transform.d.ts.map +1 -1
  50. package/dist/{index-jmtjh2d3.js → index-1ar7b3e9.js} +3 -3
  51. package/dist/{index-3fe78beq.js → index-4ftb5hcq.js} +9 -1
  52. package/dist/{index-may8skc8.js → index-bkg2fdj1.js} +15 -1
  53. package/dist/{index-36wd1d6k.js → index-d8mgqezq.js} +2 -2
  54. package/dist/{index-xdtge3y2.js → index-f9gem5cr.js} +2 -2
  55. package/dist/{index-953x7a79.js → index-faay035c.js} +248 -88
  56. package/dist/{index-1974jvn3.js → index-jkrqhc7y.js} +2 -2
  57. package/dist/{index-3wzdwt6p.js → index-ntbmt6rq.js} +1 -1
  58. package/dist/{index-nqgjwfzn.js → index-p474rw9p.js} +3 -3
  59. package/dist/{index-dkv2dn46.js → index-qp20p2py.js} +1 -1
  60. package/dist/index.d.ts +4 -1
  61. package/dist/index.d.ts.map +1 -1
  62. package/dist/index.js +1442 -127
  63. package/dist/plugin/hooks/create-session-hooks.d.ts.map +1 -1
  64. package/dist/plugin/rpc-handlers.d.ts +18 -0
  65. package/dist/plugin/rpc-handlers.d.ts.map +1 -1
  66. package/dist/plugin/rust-tool-backends.d.ts +3 -1
  67. package/dist/plugin/rust-tool-backends.d.ts.map +1 -1
  68. package/dist/{recomp-orchestrator-5g8f5rhy.js → recomp-orchestrator-c4sa354a.js} +6 -6
  69. package/dist/{safe-notification-target-q9z81zt3.js → safe-notification-target-fepvcbsj.js} +1 -1
  70. package/dist/{send-session-notification-1qeqkswb.js → send-session-notification-xnypkxpx.js} +3 -3
  71. package/dist/shared/harness.d.ts +2 -1
  72. package/dist/shared/harness.d.ts.map +1 -1
  73. package/dist/shared/model-suggestion-retry.d.ts +5 -1
  74. package/dist/shared/model-suggestion-retry.d.ts.map +1 -1
  75. package/dist/shared/prompt-surface-runtime.d.ts.map +1 -1
  76. package/dist/shared/rpc-types.d.ts +13 -0
  77. package/dist/shared/rpc-types.d.ts.map +1 -1
  78. package/dist/shared/status-detail-text.d.ts.map +1 -1
  79. package/dist/shared/status-summary.d.ts.map +1 -1
  80. package/dist/shared/user-facing-codes.d.ts +10 -0
  81. package/dist/shared/user-facing-codes.d.ts.map +1 -1
  82. package/dist/{storage-meta-session-e6g0mmec.js → storage-meta-session-x3j0q9qy.js} +3 -3
  83. package/dist/{task-config-hnv93r7p.js → task-config-ys0arma5.js} +1 -1
  84. package/dist/tools/ctx-memory/tools.d.ts.map +1 -1
  85. package/dist/tools/ctx-note/tools.d.ts.map +1 -1
  86. package/dist/v2/fold/markers.d.ts +7 -0
  87. package/dist/v2/fold/markers.d.ts.map +1 -0
  88. package/dist/v2/fold/owner.d.ts +40 -0
  89. package/dist/v2/fold/owner.d.ts.map +1 -0
  90. package/dist/v2/fold/restore.d.ts +11 -0
  91. package/dist/v2/fold/restore.d.ts.map +1 -0
  92. package/dist/v2/hidden-completion.d.ts +20 -0
  93. package/dist/v2/hidden-completion.d.ts.map +1 -0
  94. package/dist/v2/hooks/channel2.d.ts +8 -0
  95. package/dist/v2/hooks/channel2.d.ts.map +1 -0
  96. package/dist/v2/hooks/context.d.ts +7 -0
  97. package/dist/v2/hooks/context.d.ts.map +1 -0
  98. package/dist/v2/hooks/dream-trigger.d.ts +19 -0
  99. package/dist/v2/hooks/dream-trigger.d.ts.map +1 -0
  100. package/dist/v2/hooks/payload.d.ts +12 -0
  101. package/dist/v2/hooks/payload.d.ts.map +1 -0
  102. package/dist/v2/hooks/refusal.d.ts +7 -0
  103. package/dist/v2/hooks/refusal.d.ts.map +1 -0
  104. package/dist/v2/hooks/store.d.ts +6 -0
  105. package/dist/v2/hooks/store.d.ts.map +1 -0
  106. package/dist/v2/hooks/types.d.ts +90 -0
  107. package/dist/v2/hooks/types.d.ts.map +1 -0
  108. package/dist/v2/hooks/update-check.d.ts +10 -0
  109. package/dist/v2/hooks/update-check.d.ts.map +1 -0
  110. package/dist/v2/server.d.ts +8 -0
  111. package/dist/v2/server.d.ts.map +1 -0
  112. package/dist/v2/server.js +118588 -0
  113. package/dist/v2/store-reader.d.ts +65 -0
  114. package/dist/v2/store-reader.d.ts.map +1 -0
  115. package/index.js +1 -0
  116. package/package.json +10 -4
  117. package/src/features/magic-context/dreamer/task-registry.ts +19 -0
  118. package/src/shared/harness.ts +2 -1
  119. package/src/shared/model-suggestion-retry.ts +66 -14
  120. package/src/shared/prompt-surface-runtime.ts +5 -1
  121. package/src/shared/rpc-types.ts +13 -0
  122. package/src/shared/status-detail-text.test.ts +26 -0
  123. package/src/shared/status-detail-text.ts +11 -0
  124. package/src/shared/status-summary.ts +2 -0
  125. package/src/shared/user-facing-codes.test.ts +1 -1
  126. package/src/shared/user-facing-codes.ts +10 -0
package/dist/index.js CHANGED
@@ -5,7 +5,7 @@ import {
5
5
  sessionLog,
6
6
  getLoggerDiagnostics,
7
7
  flushLogger
8
- } from "./index-dkv2dn46.js";
8
+ } from "./index-qp20p2py.js";
9
9
  import {
10
10
  withContentLanguageDirective,
11
11
  buildPrimaryLanguageDirective,
@@ -71,6 +71,7 @@ import {
71
71
  checksumAuthoritySeedRows,
72
72
  prepareAuthority,
73
73
  drainAuthority,
74
+ getMemoryMirrorStatus,
74
75
  applyMirroredNoteCompileFields,
75
76
  drainMirrorPages,
76
77
  pullMemoryMirrorOnce,
@@ -191,6 +192,7 @@ import {
191
192
  isToolPartWithOutput,
192
193
  isFilePart,
193
194
  buildFileSourceContent,
195
+ assertExecutableToolInput,
194
196
  createDroppedInputToolExecuteBeforeHook,
195
197
  isEditTool,
196
198
  partHasCompletedResult,
@@ -359,6 +361,7 @@ import {
359
361
  replaceSourceContent,
360
362
  getSourceContents,
361
363
  createChildSessionWithFence,
364
+ HiddenCompletionRefusal,
362
365
  detectThinkingBindingMismatch,
363
366
  isFable51ThinkingBindingModel,
364
367
  detectOverflow,
@@ -472,6 +475,7 @@ import {
472
475
  verificationFileExists,
473
476
  normalizeVerificationFiles,
474
477
  recordChildInvocation,
478
+ createV1HiddenCompletionExecutor,
475
479
  USER_MEMORY_CANDIDATE_TTL_MS,
476
480
  insertUserMemoryCandidates,
477
481
  getUserMemoryCandidates,
@@ -522,6 +526,7 @@ import {
522
526
  mustMaterialize,
523
527
  trimMemoriesToBudgetV2,
524
528
  renderMemoryBlockV2,
529
+ materializeM0,
525
530
  prepareCachedM0M1Replay,
526
531
  hasCompleteCachedM0M1,
527
532
  injectM0M1,
@@ -542,7 +547,7 @@ import {
542
547
  setRecompTerminal2,
543
548
  runManagedRecomp2,
544
549
  runManagedUpgrade2
545
- } from "./index-953x7a79.js";
550
+ } from "./index-faay035c.js";
546
551
  import {
547
552
  stripJsonComments,
548
553
  isPrototypePollutionKey,
@@ -568,7 +573,7 @@ import {
568
573
  deriveHistorianChunkTokens2,
569
574
  resolveKnownHistorianContextLimit2,
570
575
  resolveHistorianContextLimit2
571
- } from "./index-xdtge3y2.js";
576
+ } from "./index-f9gem5cr.js";
572
577
  import {
573
578
  resolveOpenCodeDbPath,
574
579
  openCodeDbPathExists,
@@ -589,7 +594,7 @@ import {
589
594
  assistantAwaitingTools,
590
595
  getMessageTimesFromOpenCodeDb,
591
596
  findLastAssistantModelFromOpenCodeDb
592
- } from "./index-1974jvn3.js";
597
+ } from "./index-jkrqhc7y.js";
593
598
  import {
594
599
  getErrorMessage,
595
600
  describeError,
@@ -598,13 +603,13 @@ import {
598
603
  clearIgnoredMessages2,
599
604
  observeIgnoredNotificationEvent2,
600
605
  sendStatusNotification2
601
- } from "./index-nqgjwfzn.js";
606
+ } from "./index-p474rw9p.js";
602
607
  import {
603
608
  detectConflicts,
604
609
  resolveCompactionForBoot,
605
610
  sendConflictWarning2,
606
611
  cleanupConflictWarnings2
607
- } from "./index-36wd1d6k.js";
612
+ } from "./index-d8mgqezq.js";
608
613
  import {
609
614
  resolveHistorianModel2,
610
615
  resolveOpenCodeAgentOverrides2,
@@ -612,6 +617,7 @@ import {
612
617
  } from "./index-7k55qm8a.js";
613
618
  import {
614
619
  CANONICAL_DREAM_TASKS,
620
+ DREAM_TASK_CAPABILITIES,
615
621
  formatDreamTaskBacklogs,
616
622
  processedDreamTaskItems,
617
623
  leaseKindFor,
@@ -620,7 +626,7 @@ import {
620
626
  compareTaskOrder,
621
627
  buildDreamTaskRuntimeConfigs2,
622
628
  userMemoryCollectionEnabled2
623
- } from "./index-may8skc8.js";
629
+ } from "./index-bkg2fdj1.js";
624
630
  import {
625
631
  logSlowWriteTransaction,
626
632
  getOrCreateSessionMeta2,
@@ -630,7 +636,7 @@ import {
630
636
  retryPendingSessionCleanups2,
631
637
  retryPendingRustSessionCleanupsForProject2,
632
638
  clearSession2
633
- } from "./index-jmtjh2d3.js";
639
+ } from "./index-1ar7b3e9.js";
634
640
  import {
635
641
  registerNotificationSink2,
636
642
  pushNotification2,
@@ -646,7 +652,7 @@ import {
646
652
  ANNOUNCEMENT_FOOTER2,
647
653
  markAnnouncementSeen2,
648
654
  shouldShowAnnouncement2
649
- } from "./index-3wzdwt6p.js";
655
+ } from "./index-ntbmt6rq.js";
650
656
  import {
651
657
  resolvePromptContext2
652
658
  } from "./index-fmsr7v69.js";
@@ -656,12 +662,13 @@ import {
656
662
  modelRefLookupOrder
657
663
  } from "./index-avwt563y.js";
658
664
  import {
665
+ setHarness,
659
666
  getHarness,
660
667
  getDataDir,
661
668
  getOpenCodeStorageDir,
662
669
  getMagicContextStorageResolution,
663
670
  getMagicContextStorageDir
664
- } from "./index-3fe78beq.js";
671
+ } from "./index-4ftb5hcq.js";
665
672
  import {
666
673
  __toESM,
667
674
  __commonJS
@@ -12174,7 +12181,7 @@ var SERIAL_LANE_MAX_WAITERS = 16;
12174
12181
  var SERIAL_LANE_MAX_WAITERS_PER_SESSION = 8;
12175
12182
  var SERIAL_LANE_MIN_REMAINING_MS = 25;
12176
12183
  var CANONICAL_ROOT_CACHE_MAX_ENTRIES = 256;
12177
- function getDefaultConnectionFile() {
12184
+ function getDefaultSubcConnectionFile() {
12178
12185
  return join5(getDataDir(), "cortexkit", "run", "subc-connection.json");
12179
12186
  }
12180
12187
  function errorChainSome(error, predicate) {
@@ -12289,7 +12296,7 @@ class SubcModuleTransport {
12289
12296
  return capabilities;
12290
12297
  }
12291
12298
  constructor(connectionFile, moduleId = DEFAULT_MODULE_ID, requestTimeoutMs = MODULE_SEND_TIMEOUT_MS, routeSessionPrefix = "") {
12292
- this.connectionFile = connectionFile ?? getDefaultConnectionFile();
12299
+ this.connectionFile = connectionFile;
12293
12300
  this.moduleId = moduleId;
12294
12301
  this.requestTimeoutMs = requestTimeoutMs;
12295
12302
  this.routeSessionPrefix = routeSessionPrefix;
@@ -12567,8 +12574,8 @@ class SubcModuleTransport {
12567
12574
  }
12568
12575
  async authorityStatus(args) {
12569
12576
  this.authorityProjectRoot = args.project;
12570
- const { projectRoot, ...body } = args;
12571
- const response = await this.authorityRequest(args.project, projectRoot ?? this.bindRootForAuthority(), "authority.status", body);
12577
+ const { projectRoot, sessionId, ...body } = args;
12578
+ const response = await this.authorityRequest(sessionId ?? args.project, projectRoot ?? this.bindRootForAuthority(), "authority.status", body);
12572
12579
  return { authority: response.authority ?? null };
12573
12580
  }
12574
12581
  async authorityPrepare(args) {
@@ -13418,7 +13425,7 @@ function normalizeOpenCodeRows(db, sessionId, rows) {
13418
13425
  const placeholders = messageIds.map(() => "?").join(", ");
13419
13426
  const partRows = db.prepare(`SELECT message_id, data
13420
13427
  FROM part
13421
- WHERE session_id = ?
13428
+ WHERE +session_id = ?
13422
13429
  AND likelihood(message_id IN (${placeholders}), 0.000001)
13423
13430
  ORDER BY time_created ASC, id ASC`).all(sessionId, ...messageIds);
13424
13431
  const partsByMessageId = new Map;
@@ -14041,6 +14048,8 @@ function isTimeoutClassError(error) {
14041
14048
  }
14042
14049
  async function compressOneChunk(args, chunk, sliceMs, signal) {
14043
14050
  let agentSessionId = null;
14051
+ let handle = null;
14052
+ const executor = args.hiddenCompletionExecutor ?? createV1HiddenCompletionExecutor(args.client, args.db, args.sessionDirectory);
14044
14053
  let promptSettled = false;
14045
14054
  const startedAt = Date.now();
14046
14055
  try {
@@ -14048,19 +14057,22 @@ async function compressOneChunk(args, chunk, sliceMs, signal) {
14048
14057
  projectPath: args.projectIdentity,
14049
14058
  memories: chunk.map(toPromptMemory)
14050
14059
  });
14051
- const createResponse = await createChildSessionWithFence({
14052
- client: args.client,
14053
- db: args.db,
14060
+ handle = await executor.open({
14054
14061
  parentSessionId: args.parentSessionId,
14062
+ agent: DREAMER_CLASSIFIER_AGENT,
14063
+ kind: "dreamer-task",
14064
+ system: COMPRESS_CUES_SYSTEM_PROMPT,
14065
+ model: args.model,
14066
+ configuredModels: [...args.model ? [args.model] : [], ...args.fallbackModels ?? []],
14067
+ timeoutMs: sliceMs,
14055
14068
  title: "magic-context-dream-compress-cues",
14056
- directory: args.sessionDirectory
14057
- });
14058
- const created = normalizeSDKResponse(createResponse, null, {
14059
- preferResponseOnMissingData: true
14069
+ directory: args.sessionDirectory,
14070
+ metadata: { task: "compress-cues" }
14060
14071
  });
14061
- agentSessionId = typeof created?.id === "string" ? created.id : null;
14072
+ agentSessionId = handle.id || null;
14062
14073
  if (!agentSessionId)
14063
14074
  throw new Error("Could not create compress-cues session.");
14075
+ const opened = handle;
14064
14076
  const run = await promptSyncWithValidatedOutputRetry(args.client, {
14065
14077
  path: { id: agentSessionId },
14066
14078
  query: { directory: args.sessionDirectory },
@@ -14071,24 +14083,18 @@ async function compressOneChunk(args, chunk, sliceMs, signal) {
14071
14083
  parts: [{ type: "text", text: prompt, synthetic: true }]
14072
14084
  }
14073
14085
  }, {
14086
+ transport: Object.assign((request) => executor.attempt(opened, request), { childSessionId: opened.childSessionId }),
14074
14087
  timeoutMs: sliceMs,
14075
14088
  signal,
14076
14089
  fallbackModels: args.fallbackModels,
14077
14090
  callContext: "dreamer:compress-cues",
14078
- fetchOutput: async () => {
14079
- const messagesResponse = await args.client.session.messages({
14080
- path: { id: agentSessionId },
14081
- query: { directory: args.sessionDirectory, limit: 50 }
14082
- });
14083
- return normalizeSDKResponse(messagesResponse, [], {
14084
- preferResponseOnMissingData: true
14085
- });
14086
- },
14087
- validateOutput: (messages) => {
14088
- if (hasLengthCappedOutput(messages)) {
14091
+ fetchOutput: () => executor.collect(opened, 50),
14092
+ validateOutput: (completion) => {
14093
+ const messages = completion.messages ?? [];
14094
+ if (completion.lengthCapped) {
14089
14095
  throw new Error("compress-cues returned length-capped output");
14090
14096
  }
14091
- const text = extractLatestAssistantText(messages);
14097
+ const text = completion.text;
14092
14098
  if (!text)
14093
14099
  throw new Error("compress-cues returned no output");
14094
14100
  try {
@@ -14103,11 +14109,25 @@ async function compressOneChunk(args, chunk, sliceMs, signal) {
14103
14109
  }
14104
14110
  });
14105
14111
  promptSettled = true;
14112
+ if (args.hiddenCompletionExecutor && args.parentSessionId) {
14113
+ recordChildInvocation({
14114
+ db: args.db,
14115
+ parentSessionId: args.parentSessionId,
14116
+ harness: executor.capabilities.harness,
14117
+ subagent: "dreamer",
14118
+ task: "compress-cues",
14119
+ startedAt,
14120
+ status: "completed",
14121
+ tokens: run.output.usage,
14122
+ providerId: run.output.providerId,
14123
+ modelId: run.output.modelId
14124
+ });
14125
+ }
14106
14126
  return args.moduleRoute ? await applyCuesThroughModule(args, chunk, run.validated, signal) : applyCues(args, chunk, run.validated);
14107
14127
  } catch (error) {
14108
14128
  const desc = describeError(error);
14109
14129
  log(`[dreamer] compress-cues chunk failed: ${desc.brief}`, desc.stackHead ? { stackHead: desc.stackHead } : undefined);
14110
- if (signal.aborted || error instanceof DreamerProviderOutputFailureError)
14130
+ if (signal.aborted || error instanceof HiddenCompletionRefusal || error instanceof DreamerProviderOutputFailureError)
14111
14131
  throw error;
14112
14132
  return {
14113
14133
  compressed: 0,
@@ -14119,10 +14139,7 @@ async function compressOneChunk(args, chunk, sliceMs, signal) {
14119
14139
  }
14120
14140
  };
14121
14141
  } finally {
14122
- await teardownChildSession({
14123
- client: args.client,
14124
- sessionId: agentSessionId,
14125
- sessionDirectory: args.sessionDirectory,
14142
+ await executor.close(handle, {
14126
14143
  promptSettled,
14127
14144
  privacySensitive: true,
14128
14145
  context: "[dreamer] compress-cues",
@@ -14777,6 +14794,8 @@ async function runClassify(args) {
14777
14794
  }
14778
14795
  async function classifyOneChunk(args, chunk, anchors, sliceMs, signal) {
14779
14796
  let agentSessionId = null;
14797
+ let handle = null;
14798
+ const executor = args.hiddenCompletionExecutor ?? createV1HiddenCompletionExecutor(args.client, args.db, args.sessionDirectory);
14780
14799
  let promptSettled = false;
14781
14800
  const startedAt = Date.now();
14782
14801
  const moduleRoute = isModuleRoute(args);
@@ -14791,19 +14810,22 @@ async function classifyOneChunk(args, chunk, anchors, sliceMs, signal) {
14791
14810
  recordInvocation(args, startedAt, { status: "completed" });
14792
14811
  return run;
14793
14812
  }
14794
- const createResponse = await createChildSessionWithFence({
14795
- client: args.client,
14796
- db: args.db,
14813
+ handle = await executor.open({
14797
14814
  parentSessionId: args.parentSessionId,
14815
+ agent: DREAMER_CLASSIFIER_AGENT,
14816
+ kind: "dreamer-task",
14817
+ system: withContentLanguageDirective(CLASSIFY_SYSTEM_PROMPT, args.language),
14818
+ model: args.model,
14819
+ configuredModels: [...args.model ? [args.model] : [], ...args.fallbackModels ?? []],
14820
+ timeoutMs: sliceMs,
14798
14821
  title: "magic-context-dream-classify",
14799
- directory: args.sessionDirectory
14800
- });
14801
- const created = normalizeSDKResponse(createResponse, null, {
14802
- preferResponseOnMissingData: true
14822
+ directory: args.sessionDirectory,
14823
+ metadata: { task: "classify-memories" }
14803
14824
  });
14804
- agentSessionId = typeof created?.id === "string" ? created.id : null;
14825
+ agentSessionId = handle.id || null;
14805
14826
  if (!agentSessionId)
14806
14827
  throw new Error("Could not create classify session.");
14828
+ const opened = handle;
14807
14829
  const run = await promptSyncWithValidatedOutputRetry(args.client, {
14808
14830
  path: { id: agentSessionId },
14809
14831
  query: { directory: args.sessionDirectory },
@@ -14814,24 +14836,18 @@ async function classifyOneChunk(args, chunk, anchors, sliceMs, signal) {
14814
14836
  parts: [{ type: "text", text: prompt, synthetic: true }]
14815
14837
  }
14816
14838
  }, {
14839
+ transport: Object.assign((request) => executor.attempt(opened, request), { childSessionId: opened.childSessionId }),
14817
14840
  timeoutMs: sliceMs,
14818
14841
  signal,
14819
14842
  fallbackModels: args.fallbackModels,
14820
14843
  callContext: "dreamer:classify-memories",
14821
- fetchOutput: async () => {
14822
- const messagesResponse = await args.client.session.messages({
14823
- path: { id: agentSessionId },
14824
- query: { directory: args.sessionDirectory, limit: 50 }
14825
- });
14826
- return normalizeSDKResponse(messagesResponse, [], {
14827
- preferResponseOnMissingData: true
14828
- });
14829
- },
14830
- validateOutput: (messages) => {
14831
- if (hasLengthCappedOutput(messages)) {
14844
+ fetchOutput: () => executor.collect(opened, 50),
14845
+ validateOutput: (completion) => {
14846
+ const messages = completion.messages ?? [];
14847
+ if (completion.lengthCapped) {
14832
14848
  throw new Error("classify returned length-capped output");
14833
14849
  }
14834
- const text = extractLatestAssistantText(messages);
14850
+ const text = completion.text;
14835
14851
  if (!text)
14836
14852
  throw new Error("classify returned no output");
14837
14853
  try {
@@ -14846,21 +14862,22 @@ async function classifyOneChunk(args, chunk, anchors, sliceMs, signal) {
14846
14862
  }
14847
14863
  });
14848
14864
  promptSettled = true;
14849
- recordInvocation(args, startedAt, { status: "completed", messages: run.output });
14865
+ recordInvocation(args, startedAt, {
14866
+ status: "completed",
14867
+ messages: run.output.messages,
14868
+ completion: run.output
14869
+ });
14850
14870
  return applyClassifications(args, chunk.map((candidate) => candidate.contextMemory), run.validated);
14851
14871
  } catch (error) {
14852
14872
  const failure = moduleRoute ? new ClassifyModuleFailureError("module", error) : error;
14853
14873
  const desc = describeError(failure);
14854
14874
  log(`[dreamer] classify chunk failed: ${desc.brief}`, desc.stackHead ? { stackHead: desc.stackHead } : undefined);
14855
14875
  recordInvocation(args, startedAt, { status: "failed", error: failure });
14856
- if (moduleRoute || signal.aborted || failure instanceof DreamerProviderOutputFailureError || getPromptFailureDetail(failure)?.failureClass !== "parse_failed" && getPromptFailureDetail(failure) !== null)
14876
+ if (moduleRoute || failure instanceof HiddenCompletionRefusal || signal.aborted || failure instanceof DreamerProviderOutputFailureError || getPromptFailureDetail(failure)?.failureClass !== "parse_failed" && getPromptFailureDetail(failure) !== null)
14857
14877
  throw failure;
14858
14878
  return { classified: 0, changed: 0 };
14859
14879
  } finally {
14860
- await teardownChildSession({
14861
- client: args.client,
14862
- sessionId: agentSessionId,
14863
- sessionDirectory: args.sessionDirectory,
14880
+ await executor.close(handle, {
14864
14881
  promptSettled,
14865
14882
  privacySensitive: true,
14866
14883
  context: "[dreamer] classify",
@@ -15014,12 +15031,17 @@ function recordInvocation(args, startedAt, params) {
15014
15031
  recordChildInvocation({
15015
15032
  db: args.db,
15016
15033
  parentSessionId: args.parentSessionId,
15017
- harness: "opencode",
15034
+ harness: args.hiddenCompletionExecutor?.capabilities.harness ?? "opencode",
15018
15035
  subagent: "dreamer",
15019
15036
  task: "classify-memories",
15020
15037
  startedAt,
15021
15038
  status: params.status,
15022
15039
  messages: params.messages,
15040
+ ...params.completion && !params.completion.messages ? {
15041
+ tokens: params.completion.usage,
15042
+ providerId: params.completion.providerId,
15043
+ modelId: params.completion.modelId
15044
+ } : {},
15023
15045
  error: params.error
15024
15046
  });
15025
15047
  }
@@ -19156,7 +19178,7 @@ function dreamRunFailureDetail(error) {
19156
19178
  }
19157
19179
  const described = describeError(error);
19158
19180
  const message = described.brief;
19159
- const providerFailure = error instanceof Error && error.name === "DreamerProviderOutputFailureError";
19181
+ const providerFailure = error instanceof HiddenCompletionRefusal || error instanceof Error && error.name === "DreamerProviderOutputFailureError";
19160
19182
  return {
19161
19183
  failure_class: providerFailure ? "provider_error" : /no models?|model chain is empty/i.test(message) ? "no_models" : "unknown",
19162
19184
  model_attempted: null,
@@ -19246,13 +19268,20 @@ function formatCurateMemoryOperations(actions) {
19246
19268
  const noun = actions.length === 1 ? "operation" : "operations";
19247
19269
  return `curate: ${actions.length} memory ${noun} applied${actionDetail ? ` (${actionDetail})` : ""}`;
19248
19270
  }
19271
+ function requireDreamClient(client) {
19272
+ if (!client)
19273
+ throw new HiddenCompletionRefusal("hidden_tools_unsupported", "This dream task requires the child-session tool transport", true);
19274
+ return client;
19275
+ }
19249
19276
  function createDreamTaskExecutor(deps) {
19250
19277
  let parentSessionIdPromise;
19251
19278
  const resolveParentSessionId = () => {
19279
+ if (deps.hiddenCompletionExecutor)
19280
+ return Promise.resolve(deps.parentSessionId);
19252
19281
  if (!parentSessionIdPromise) {
19253
19282
  parentSessionIdPromise = (async () => {
19254
19283
  try {
19255
- const listResponse = await deps.client.session.list({
19284
+ const listResponse = await requireDreamClient(deps.client).session.list({
19256
19285
  query: { directory: deps.sessionDirectory }
19257
19286
  });
19258
19287
  const sessions = normalizeSDKResponse(listResponse, [], { preferResponseOnMissingData: true });
@@ -19366,6 +19395,9 @@ function createDreamTaskExecutor(deps) {
19366
19395
  return writtenIds.length || deletedIds.length || archivedIds.length || mergedIds.length ? changes : null;
19367
19396
  }
19368
19397
  try {
19398
+ if (deps.hiddenCompletionExecutor?.capabilities.tools === false && DREAM_TASK_CAPABILITIES[config.task].requiresTools) {
19399
+ throw new HiddenCompletionRefusal("hidden_tools_unsupported", `${config.task} requires tools; opencode2 hidden completions have no tool loop`, true);
19400
+ }
19369
19401
  if (config.task === "compress-cues") {
19370
19402
  if (deps.mural?.enabled !== true) {
19371
19403
  log("[dreamer] compress-cues: skipped (mural is not enabled)");
@@ -19375,6 +19407,7 @@ function createDreamTaskExecutor(deps) {
19375
19407
  const result = await runCompressCues({
19376
19408
  db,
19377
19409
  client: deps.client,
19410
+ hiddenCompletionExecutor: deps.hiddenCompletionExecutor,
19378
19411
  projectIdentity,
19379
19412
  parentSessionId: parent,
19380
19413
  sessionDirectory: deps.sessionDirectory,
@@ -19399,7 +19432,7 @@ function createDreamTaskExecutor(deps) {
19399
19432
  if (config.task === "review-user-memories") {
19400
19433
  const result = await reviewUserMemories({
19401
19434
  db,
19402
- client: deps.client,
19435
+ client: requireDreamClient(deps.client),
19403
19436
  parentSessionId: parent,
19404
19437
  sessionDirectory: deps.sessionDirectory,
19405
19438
  holderId,
@@ -19418,7 +19451,7 @@ function createDreamTaskExecutor(deps) {
19418
19451
  if (config.task === "map-memories") {
19419
19452
  const result = await mapMemories({
19420
19453
  db,
19421
- client: deps.client,
19454
+ client: requireDreamClient(deps.client),
19422
19455
  projectIdentity,
19423
19456
  parentSessionId: parent,
19424
19457
  sessionDirectory: deps.sessionDirectory,
@@ -19455,7 +19488,7 @@ function createDreamTaskExecutor(deps) {
19455
19488
  const memoryBefore = getMemoryCountsByStatus(db, projectIdentity);
19456
19489
  const result = await runVerify({
19457
19490
  db,
19458
- client: deps.client,
19491
+ client: requireDreamClient(deps.client),
19459
19492
  projectIdentity,
19460
19493
  parentSessionId: parent,
19461
19494
  sessionDirectory: deps.sessionDirectory,
@@ -19513,6 +19546,7 @@ function createDreamTaskExecutor(deps) {
19513
19546
  const result = await runClassify({
19514
19547
  db,
19515
19548
  client: deps.client,
19549
+ hiddenCompletionExecutor: deps.hiddenCompletionExecutor,
19516
19550
  projectIdentity,
19517
19551
  parentSessionId: parent,
19518
19552
  sessionDirectory: deps.sessionDirectory,
@@ -19538,7 +19572,7 @@ function createDreamTaskExecutor(deps) {
19538
19572
  if (config.task === "promote-primers") {
19539
19573
  const result = await promotePrimers({
19540
19574
  db,
19541
- client: deps.client,
19575
+ client: requireDreamClient(deps.client),
19542
19576
  projectIdentity,
19543
19577
  sessionDirectory: deps.sessionDirectory,
19544
19578
  holderId,
@@ -19555,7 +19589,7 @@ function createDreamTaskExecutor(deps) {
19555
19589
  if (config.task === "refresh-primers") {
19556
19590
  const result = await refreshPrimers({
19557
19591
  db,
19558
- client: deps.client,
19592
+ client: requireDreamClient(deps.client),
19559
19593
  projectIdentity,
19560
19594
  parentSessionId: parent,
19561
19595
  sessionDirectory: deps.sessionDirectory,
@@ -19576,7 +19610,7 @@ function createDreamTaskExecutor(deps) {
19576
19610
  if (config.task === "evaluate-smart-notes") {
19577
19611
  const result = await evaluateSmartNotes({
19578
19612
  db,
19579
- client: deps.client,
19613
+ client: requireDreamClient(deps.client),
19580
19614
  projectIdentity,
19581
19615
  parentSessionId: parent,
19582
19616
  sessionDirectory: deps.sessionDirectory,
@@ -19743,7 +19777,7 @@ async function runRetrospectiveTask(config, ctx, helpers) {
19743
19777
  let promptSettled = false;
19744
19778
  try {
19745
19779
  const createResponse = await createChildSessionWithFence({
19746
- client: deps.client,
19780
+ client: requireDreamClient(deps.client),
19747
19781
  db,
19748
19782
  parentSessionId: parent ?? undefined,
19749
19783
  title: "magic-context-dream-retrospective",
@@ -19757,7 +19791,7 @@ async function runRetrospectiveTask(config, ctx, helpers) {
19757
19791
  const runChildTurn = async (system, userText) => {
19758
19792
  const remainingMs = Math.max(0, deadline - Date.now());
19759
19793
  promptSettled = false;
19760
- const run = await promptSyncWithValidatedOutputRetry(deps.client, {
19794
+ const run = await promptSyncWithValidatedOutputRetry(requireDreamClient(deps.client), {
19761
19795
  path: { id: sessionId },
19762
19796
  query: { directory: deps.sessionDirectory },
19763
19797
  body: {
@@ -19772,7 +19806,7 @@ async function runRetrospectiveTask(config, ctx, helpers) {
19772
19806
  fallbackModels: config.fallbackModels,
19773
19807
  callContext: "dreamer:retrospective",
19774
19808
  fetchOutput: async () => {
19775
- const messagesResponse = await deps.client.session.messages({
19809
+ const messagesResponse = await requireDreamClient(deps.client).session.messages({
19776
19810
  path: { id: sessionId },
19777
19811
  query: { directory: deps.sessionDirectory, limit: 50 }
19778
19812
  });
@@ -19897,7 +19931,7 @@ async function runRetrospectiveTask(config, ctx, helpers) {
19897
19931
  } finally {
19898
19932
  heartbeat.stop();
19899
19933
  await teardownChildSession({
19900
- client: deps.client,
19934
+ client: requireDreamClient(deps.client),
19901
19935
  sessionId: childSessionId,
19902
19936
  sessionDirectory: deps.sessionDirectory,
19903
19937
  promptSettled,
@@ -19960,7 +19994,7 @@ async function runAgenticTask(config, ctx, helpers) {
19960
19994
  curate: curateMemories ? { memories: curateMemories } : undefined
19961
19995
  });
19962
19996
  const createResponse = await createChildSessionWithFence({
19963
- client: deps.client,
19997
+ client: requireDreamClient(deps.client),
19964
19998
  db,
19965
19999
  parentSessionId: parent ?? undefined,
19966
20000
  title: `magic-context-dream-${task}`,
@@ -19974,7 +20008,7 @@ async function runAgenticTask(config, ctx, helpers) {
19974
20008
  throw new Error("Dreamer could not create its child session.");
19975
20009
  const sessionId = childSessionId;
19976
20010
  const remainingMs = Math.max(0, deadline - Date.now());
19977
- const run = await promptSyncWithValidatedOutputRetry(deps.client, {
20011
+ const run = await promptSyncWithValidatedOutputRetry(requireDreamClient(deps.client), {
19978
20012
  path: { id: sessionId },
19979
20013
  query: { directory: docsDir },
19980
20014
  body: {
@@ -19989,7 +20023,7 @@ async function runAgenticTask(config, ctx, helpers) {
19989
20023
  fallbackModels: config.fallbackModels,
19990
20024
  callContext: `dreamer:${task}`,
19991
20025
  fetchOutput: async () => {
19992
- const messagesResponse = await deps.client.session.messages({
20026
+ const messagesResponse = await requireDreamClient(deps.client).session.messages({
19993
20027
  path: { id: sessionId },
19994
20028
  query: {
19995
20029
  directory: docsDir,
@@ -20064,7 +20098,7 @@ async function runAgenticTask(config, ctx, helpers) {
20064
20098
  if (childSessionId)
20065
20099
  takeCurateSafetyRefusalCount(childSessionId);
20066
20100
  await teardownChildSession({
20067
- client: deps.client,
20101
+ client: requireDreamClient(deps.client),
20068
20102
  sessionId: childSessionId,
20069
20103
  sessionDirectory: docsDir,
20070
20104
  promptSettled,
@@ -24972,6 +25006,10 @@ function statusSummaryFromDetail(detail) {
24972
25006
  if ((detail.loggerDiagnostics?.swallowedWriteCount ?? 0) > 0) {
24973
25007
  warnings.push("status_log_unavailable");
24974
25008
  }
25009
+ if (detail.memoryMirror?.stalled)
25010
+ warnings.push("memory_mirror_stalled");
25011
+ if (detail.memoryAuthorityMismatch)
25012
+ warnings.push("memory_authority_mismatch");
24975
25013
  return {
24976
25014
  inputTokens: detail.inputTokens,
24977
25015
  usableContextTokens: detail.contextLimit,
@@ -25108,6 +25146,9 @@ function formatStatusDiagnosticsMarkdown(detail) {
25108
25146
  `- **${formatCacheTtlDisplay({ value: detail.cacheTtl, source: detail.cacheTtlSource ?? "session", modelKey: detail.cacheTtlModelKey })}**; ${formatCacheLane(detail)}`,
25109
25147
  `- **Historian:** ${[historianState, ...historianDetails].join("; ")}`,
25110
25148
  ...detail.hostBackendsModuleSide ? [`- ${RUST_MODE_HOST_PATHS_LINE}`] : [],
25149
+ ...detail.memoryMirror ? [
25150
+ `- **Memory mirror:** cursor ${formatCount2(detail.memoryMirror.cursor)} / ${detail.memoryMirror.feedHead === null ? "unknown" : formatCount2(detail.memoryMirror.feedHead)}; ${formatCount2(detail.memoryMirror.liveRows)} live rows; ${detail.memoryMirror.stalled ? `stalled (${detail.memoryMirror.code})` : "advancing or caught up"}`
25151
+ ] : [],
25111
25152
  `- **Memory:** ${formatCount2(detail.memoryCount)} active; ${formatCount2(detail.memoryBlockCount)} injected`,
25112
25153
  `- **Tags:** ${formatCount2(detail.activeTags)} active, ${formatCount2(detail.droppedTags)} dropped; ${formatCount2(detail.pendingOpsCount)} pending drops`,
25113
25154
  `- **Execute threshold:** ${detail.executeThreshold.toFixed(1)}%${detail.executeThresholdClamped ? " (clamped)" : ""}`
@@ -25118,6 +25159,12 @@ function formatStatusDiagnosticsMarkdown(detail) {
25118
25159
  if (detail.lastTransformError) {
25119
25160
  lines.push(`- **Warning:** ${renderUserFacingFailure("transform_update_failed")}`);
25120
25161
  }
25162
+ if (detail.memoryMirror?.stalled) {
25163
+ lines.push(`- **Warning:** ${renderUserFacingFailure("memory_mirror_stalled")}`);
25164
+ }
25165
+ if (detail.memoryAuthorityMismatch) {
25166
+ lines.push(`- **Warning:** ${renderUserFacingFailure("memory_authority_mismatch")}`);
25167
+ }
25121
25168
  return lines.join(`
25122
25169
  `);
25123
25170
  }
@@ -29005,9 +29052,16 @@ function buildSidebarSnapshotRpcResponse(db, sessionId, directory, liveSessionSt
29005
29052
  }
29006
29053
  function buildStatusDetail(db, sessionId, directory, modelKey, config, liveSessionState, injectionBudgetTokens, moduleStatus, compactionEnabled = true) {
29007
29054
  const base = buildSidebarSnapshot(db, sessionId, directory, liveSessionState, injectionBudgetTokens, config, moduleStatus, compactionEnabled);
29055
+ const rustMode = config?.transform_mode === "rust";
29056
+ const projectIdentity = rustMode ? resolveProjectIdentity(directory) : null;
29057
+ const moduleMemoryAuthority = moduleStatus?.authority?.memories;
29058
+ const moduleMemoryState = moduleMemoryAuthority?.state;
29059
+ const moduleFeedHead = moduleStatus?.memory_mirror?.feed_head;
29008
29060
  const detail = {
29009
29061
  ...base,
29010
- hostBackendsModuleSide: config?.transform_mode === "rust",
29062
+ hostBackendsModuleSide: rustMode,
29063
+ memoryMirror: rustMode ? getMemoryMirrorStatus(db, moduleFeedHead) : undefined,
29064
+ memoryAuthorityMismatch: rustMode && moduleStatus?.authority !== undefined && projectIdentity !== null && getAuthorityManagedMarker(db, projectIdentity) !== null && (moduleMemoryState === "TS" || moduleMemoryAuthority === null),
29011
29065
  activeProfile: typeof config?.profile === "string" ? config.profile : null,
29012
29066
  tagCounter: 0,
29013
29067
  activeTags: 0,
@@ -29461,9 +29515,9 @@ function registerRpcHandlers(rpcServer, args) {
29461
29515
  return { count: buildCompartmentCount(db, sessionId, moduleStatus) };
29462
29516
  });
29463
29517
  const buildManagedCtx = async (db) => {
29464
- const { deriveHistorianChunkTokens, resolveHistorianContextLimit } = await import("./derive-budgets-s2pgnnm4.js");
29518
+ const { deriveHistorianChunkTokens, resolveHistorianContextLimit } = await import("./derive-budgets-v1fkhjjr.js");
29465
29519
  const { resolveHistorianModel } = await import("./model-resolution-dxatzjde.js");
29466
- const { userMemoryCollectionEnabled } = await import("./task-config-hnv93r7p.js");
29520
+ const { userMemoryCollectionEnabled } = await import("./task-config-ys0arma5.js");
29467
29521
  const DEFAULT_HISTORIAN_TIMEOUT_MS = 600000;
29468
29522
  const historianModel = resolveHistorianModel(config, "opencode");
29469
29523
  return {
@@ -29494,8 +29548,8 @@ function registerRpcHandlers(rpcServer, args) {
29494
29548
  const db = getDb();
29495
29549
  if (!db)
29496
29550
  return { ok: false, error: "db unavailable" };
29497
- const { runManagedRecomp } = await import("./recomp-orchestrator-5g8f5rhy.js");
29498
- const { sendIgnoredMessage } = await import("./send-session-notification-1qeqkswb.js");
29551
+ const { runManagedRecomp } = await import("./recomp-orchestrator-c4sa354a.js");
29552
+ const { sendIgnoredMessage } = await import("./send-session-notification-xnypkxpx.js");
29499
29553
  log(`[rpc] recomp requested for session ${sessionId}`);
29500
29554
  const ctx = await buildManagedCtx(db);
29501
29555
  runManagedRecomp(ctx, sessionId).then((message) => {
@@ -29513,8 +29567,8 @@ function registerRpcHandlers(rpcServer, args) {
29513
29567
  const db = getDb();
29514
29568
  if (!db)
29515
29569
  return { ok: false, error: "db unavailable" };
29516
- const { runManagedUpgrade } = await import("./recomp-orchestrator-5g8f5rhy.js");
29517
- const { sendIgnoredMessage } = await import("./send-session-notification-1qeqkswb.js");
29570
+ const { runManagedUpgrade } = await import("./recomp-orchestrator-c4sa354a.js");
29571
+ const { sendIgnoredMessage } = await import("./send-session-notification-xnypkxpx.js");
29518
29572
  log(`[rpc] session-upgrade requested for session ${sessionId}`);
29519
29573
  const ctx = await buildManagedCtx(db);
29520
29574
  runManagedUpgrade(ctx, sessionId).then((message) => {
@@ -29530,7 +29584,7 @@ function registerRpcHandlers(rpcServer, args) {
29530
29584
  if (!db)
29531
29585
  return { ok: false, error: "db unavailable" };
29532
29586
  try {
29533
- const { updateSessionMeta } = await import("./storage-meta-session-e6g0mmec.js");
29587
+ const { updateSessionMeta } = await import("./storage-meta-session-x3j0q9qy.js");
29534
29588
  updateSessionMeta(db, sessionId, { upgradeRemindedAt: Date.now() });
29535
29589
  return { ok: true };
29536
29590
  } catch (error) {
@@ -30179,7 +30233,8 @@ function applyCavemanCleanup(sessionId, db, targets, tags, config) {
30179
30233
  compressedToLite: 0,
30180
30234
  compressedToFull: 0,
30181
30235
  compressedToUltra: 0,
30182
- mutatedTextTags: 0
30236
+ mutatedTextTags: 0,
30237
+ textReductions: []
30183
30238
  };
30184
30239
  if (!config.enabled)
30185
30240
  return result;
@@ -30219,9 +30274,15 @@ function applyCavemanCleanup(sessionId, db, targets, tags, config) {
30219
30274
  const target = targets.get(tag.tagNumber);
30220
30275
  if (!target)
30221
30276
  continue;
30277
+ const priorContent = target.getContent?.();
30222
30278
  const didMutate = target.setContent(compressed);
30223
- if (didMutate)
30279
+ if (didMutate) {
30224
30280
  result.mutatedTextTags += 1;
30281
+ result.textReductions.push({
30282
+ tagNumber: tag.tagNumber,
30283
+ removedCharacters: Math.max(0, (priorContent?.length ?? originalText.length) - compressed.length)
30284
+ });
30285
+ }
30225
30286
  updateCavemanDepth(db, sessionId, tag.tagNumber, targetDepth);
30226
30287
  if (targetDepth === DEPTH_LITE)
30227
30288
  result.compressedToLite += 1;
@@ -32018,6 +32079,73 @@ function dropStaleReduceCalls(messages, frozenIds, options = {}) {
32018
32079
  return { didDrop, newlyStrippedIds };
32019
32080
  }
32020
32081
 
32082
+ // src/hooks/magic-context/dropped-token-estimate.ts
32083
+ var TAG_QUERY_CHUNK_SIZE = 900;
32084
+ var ESTIMATED_CHARACTERS_PER_TOKEN = 3.5;
32085
+ function estimateCharacters(characters) {
32086
+ return Math.ceil(Math.max(0, characters) / ESTIMATED_CHARACTERS_PER_TOKEN);
32087
+ }
32088
+ function persistedCountOrByteEstimate(count, bytes) {
32089
+ return typeof count === "number" && Number.isFinite(count) ? Math.max(0, count) : estimateCharacters(bytes);
32090
+ }
32091
+ function loadPersistedTagTokenCounts(db, sessionId, tagNumbers) {
32092
+ const countsByTag = new Map;
32093
+ for (let offset = 0;offset < tagNumbers.length; offset += TAG_QUERY_CHUNK_SIZE) {
32094
+ const chunk = tagNumbers.slice(offset, offset + TAG_QUERY_CHUNK_SIZE);
32095
+ const placeholders = chunk.map(() => "?").join(",");
32096
+ const rows = db.prepare(`SELECT tag_number AS tagNumber,
32097
+ type,
32098
+ byte_size AS byteSize,
32099
+ input_byte_size AS inputByteSize,
32100
+ reasoning_byte_size AS reasoningByteSize,
32101
+ token_count AS tokenCount,
32102
+ input_token_count AS inputTokenCount,
32103
+ reasoning_token_count AS reasoningTokenCount
32104
+ FROM tags
32105
+ WHERE session_id = ? AND tag_number IN (${placeholders})`).all(sessionId, ...chunk);
32106
+ for (const row of rows)
32107
+ countsByTag.set(row.tagNumber, row);
32108
+ }
32109
+ return countsByTag;
32110
+ }
32111
+ function estimateDroppedTokensFromTagReductions(db, sessionId, reductions) {
32112
+ if (reductions.length === 0)
32113
+ return 0;
32114
+ const structuralByTag = new Map;
32115
+ const partialCharactersByTag = new Map;
32116
+ for (const reduction of reductions) {
32117
+ if (reduction.mode === "partial") {
32118
+ partialCharactersByTag.set(reduction.tagNumber, (partialCharactersByTag.get(reduction.tagNumber) ?? 0) + Math.max(0, reduction.removedCharacters));
32119
+ continue;
32120
+ }
32121
+ const prior = structuralByTag.get(reduction.tagNumber);
32122
+ if (!prior || reduction.mode === "full") {
32123
+ structuralByTag.set(reduction.tagNumber, reduction);
32124
+ }
32125
+ }
32126
+ const tagNumbers = [...new Set([...structuralByTag.keys(), ...partialCharactersByTag.keys()])];
32127
+ const countsByTag = loadPersistedTagTokenCounts(db, sessionId, tagNumbers);
32128
+ let total = 0;
32129
+ for (const [tagNumber, reduction] of structuralByTag) {
32130
+ const row = countsByTag.get(tagNumber);
32131
+ if (!row)
32132
+ continue;
32133
+ total += persistedCountOrByteEstimate(row.tokenCount, row.byteSize);
32134
+ if (reduction.mode === "full") {
32135
+ total += persistedCountOrByteEstimate(row.reasoningTokenCount, row.reasoningByteSize);
32136
+ if (row.type === "tool") {
32137
+ total += persistedCountOrByteEstimate(row.inputTokenCount, row.inputByteSize);
32138
+ }
32139
+ }
32140
+ }
32141
+ for (const [tagNumber, removedCharacters] of partialCharactersByTag) {
32142
+ if (structuralByTag.has(tagNumber) || !countsByTag.has(tagNumber))
32143
+ continue;
32144
+ total += estimateCharacters(removedCharacters);
32145
+ }
32146
+ return Math.max(0, Math.round(total));
32147
+ }
32148
+
32021
32149
  // src/hooks/magic-context/fold-execution-gate.ts
32022
32150
  function foldExecutesThisPass(foldDue, materialized) {
32023
32151
  return foldDue && materialized;
@@ -32088,6 +32216,7 @@ function applyHeuristicCleanup(sessionId, db, targets, messageTagNumbers, config
32088
32216
  let emergencyReclaimedTokens = 0;
32089
32217
  let deduplicatedTools = 0;
32090
32218
  let droppedInjections = 0;
32219
+ const droppedTokenReductions = [];
32091
32220
  if (config.emergency) {
32092
32221
  const emergency = config.emergency;
32093
32222
  const priorInputSample = getEmergencyInputSample(db, sessionId);
@@ -32123,6 +32252,10 @@ function applyHeuristicCleanup(sessionId, db, targets, messageTagNumbers, config
32123
32252
  updateTagDropMode(db, sessionId, tag.tagNumber, skeleton ? "truncated" : "full");
32124
32253
  droppedTools++;
32125
32254
  emergencyDroppedTools++;
32255
+ droppedTokenReductions.push({
32256
+ tagNumber: tag.tagNumber,
32257
+ mode: result === "removed" ? "full" : "truncated"
32258
+ });
32126
32259
  emergencyReclaimedTokens += estimateEmergencyDropReclaimTokens(tag);
32127
32260
  }
32128
32261
  }
@@ -32157,12 +32290,18 @@ function applyHeuristicCleanup(sessionId, db, targets, messageTagNumbers, config
32157
32290
  const strippedSource = stripTagPrefix(stripped);
32158
32291
  if (strippedSource.trim().length === 0) {
32159
32292
  const dropResult = target.drop?.() ?? "absent";
32160
- const didReplace = dropResult === "absent" ? target.setContent(`[dropped §${tag.tagNumber}§]`) : false;
32293
+ const replacement = `[dropped §${tag.tagNumber}§]`;
32294
+ const didReplace = dropResult === "absent" ? target.setContent(replacement) : false;
32161
32295
  if (dropResult === "removed" || dropResult === "absent") {
32162
32296
  replaceSourceContent(db, sessionId, tag.tagNumber, "");
32163
32297
  updateTagStatus(db, sessionId, tag.tagNumber, "dropped");
32164
32298
  if (dropResult === "removed" || didReplace) {
32165
32299
  droppedInjections++;
32300
+ droppedTokenReductions.push(dropResult === "removed" ? { tagNumber: tag.tagNumber, mode: "full" } : {
32301
+ tagNumber: tag.tagNumber,
32302
+ mode: "partial",
32303
+ removedCharacters: Math.max(0, content.length - replacement.length)
32304
+ });
32166
32305
  }
32167
32306
  }
32168
32307
  } else {
@@ -32170,6 +32309,11 @@ function applyHeuristicCleanup(sessionId, db, targets, messageTagNumbers, config
32170
32309
  if (didSet) {
32171
32310
  replaceSourceContent(db, sessionId, tag.tagNumber, strippedSource);
32172
32311
  droppedInjections++;
32312
+ droppedTokenReductions.push({
32313
+ tagNumber: tag.tagNumber,
32314
+ mode: "partial",
32315
+ removedCharacters: Math.max(0, content.length - stripped.length)
32316
+ });
32173
32317
  }
32174
32318
  }
32175
32319
  }
@@ -32209,6 +32353,10 @@ function applyHeuristicCleanup(sessionId, db, targets, messageTagNumbers, config
32209
32353
  updateTagStatus(db, sessionId, tag.tagNumber, "dropped");
32210
32354
  if (result === "removed" || result === "truncated") {
32211
32355
  deduplicatedTools++;
32356
+ droppedTokenReductions.push({
32357
+ tagNumber: tag.tagNumber,
32358
+ mode: result === "removed" ? "full" : "truncated"
32359
+ });
32212
32360
  }
32213
32361
  }
32214
32362
  }
@@ -32227,6 +32375,10 @@ function applyHeuristicCleanup(sessionId, db, targets, messageTagNumbers, config
32227
32375
  });
32228
32376
  compressedTextTags = cavemanResult.compressedToLite + cavemanResult.compressedToFull + cavemanResult.compressedToUltra;
32229
32377
  mutatedTextTags = cavemanResult.mutatedTextTags;
32378
+ droppedTokenReductions.push(...cavemanResult.textReductions.map((reduction) => ({
32379
+ ...reduction,
32380
+ mode: "partial"
32381
+ })));
32230
32382
  }
32231
32383
  return {
32232
32384
  droppedTools,
@@ -32235,7 +32387,8 @@ function applyHeuristicCleanup(sessionId, db, targets, messageTagNumbers, config
32235
32387
  emergencyDroppedTools,
32236
32388
  emergencyReclaimedTokens,
32237
32389
  compressedTextTags,
32238
- mutatedTextTags
32390
+ mutatedTextTags,
32391
+ droppedTokenReductions
32239
32392
  };
32240
32393
  }
32241
32394
  function extractToolInfo(part) {
@@ -32475,7 +32628,7 @@ var RECENT_TOOL_SKELETON_WINDOW = 20;
32475
32628
  function buildReplacementContent(tagId) {
32476
32629
  return `[dropped §${tagId}§]`;
32477
32630
  }
32478
- function applyPendingOperations(sessionId, db, targets, protectedTagIds, preloadedTags, preloadedPendingOps, syntheticPendingOps = [], editMarkerTagIds = new Set) {
32631
+ function applyPendingOperations(sessionId, db, targets, protectedTagIds, preloadedTags, preloadedPendingOps, syntheticPendingOps = [], editMarkerTagIds = new Set, onTagReduced) {
32479
32632
  let didMutateMessage = false;
32480
32633
  let admitted = false;
32481
32634
  let startedAt = 0;
@@ -32484,6 +32637,7 @@ function applyPendingOperations(sessionId, db, targets, protectedTagIds, preload
32484
32637
  admitted = true;
32485
32638
  startedAt = performance.now();
32486
32639
  const tags = preloadedTags ?? getTagsBySession(db, sessionId);
32640
+ const tagById = new Map(tags.map((tag) => [tag.tagNumber, tag]));
32487
32641
  const tagStatusById = new Map(tags.map((tag) => [tag.tagNumber, tag.status]));
32488
32642
  const tagTypeById = new Map(tags.map((tag) => [tag.tagNumber, tag.type]));
32489
32643
  const pendingOps = preloadedPendingOps ?? getPendingOps(db, sessionId);
@@ -32516,6 +32670,7 @@ function applyPendingOperations(sessionId, db, targets, protectedTagIds, preload
32516
32670
  continue;
32517
32671
  }
32518
32672
  didMutateMessage = true;
32673
+ onTagReduced?.({ tagNumber: pendingOp.tagId, mode: "edit_marker" });
32519
32674
  updateTagDropMode(db, sessionId, pendingOp.tagId, "edit_marker");
32520
32675
  shouldPersistDrop = true;
32521
32676
  } else if (skeletonWindow.has(pendingOp.tagId)) {
@@ -32525,6 +32680,7 @@ function applyPendingOperations(sessionId, db, targets, protectedTagIds, preload
32525
32680
  }
32526
32681
  if (truncResult === "truncated") {
32527
32682
  didMutateMessage = true;
32683
+ onTagReduced?.({ tagNumber: pendingOp.tagId, mode: "truncated" });
32528
32684
  }
32529
32685
  updateTagDropMode(db, sessionId, pendingOp.tagId, "truncated");
32530
32686
  shouldPersistDrop = true;
@@ -32535,14 +32691,24 @@ function applyPendingOperations(sessionId, db, targets, protectedTagIds, preload
32535
32691
  }
32536
32692
  if (dropResult === "removed") {
32537
32693
  didMutateMessage = true;
32694
+ onTagReduced?.({ tagNumber: pendingOp.tagId, mode: "full" });
32538
32695
  }
32539
32696
  updateTagDropMode(db, sessionId, pendingOp.tagId, "full");
32540
32697
  shouldPersistDrop = true;
32541
32698
  }
32542
32699
  } else if (target) {
32543
- const changed = target.setContent(buildReplacementContent(pendingOp.tagId));
32544
- if (changed)
32700
+ const replacement = buildReplacementContent(pendingOp.tagId);
32701
+ const priorContent = target.getContent?.();
32702
+ const changed = target.setContent(replacement);
32703
+ if (changed) {
32545
32704
  didMutateMessage = true;
32705
+ const originalCharacters = typeof priorContent === "string" ? priorContent.length : tagById.get(pendingOp.tagId)?.byteSize ?? replacement.length;
32706
+ onTagReduced?.({
32707
+ tagNumber: pendingOp.tagId,
32708
+ mode: "partial",
32709
+ removedCharacters: Math.max(0, originalCharacters - replacement.length)
32710
+ });
32711
+ }
32546
32712
  shouldPersistDrop = true;
32547
32713
  } else if (!synthetic) {
32548
32714
  shouldPersistDrop = true;
@@ -33530,6 +33696,10 @@ function clearPendingCompactionMarkerAfterSuccessfulDrain(args) {
33530
33696
  sessionLog(args.sessionId, "compaction-marker drain: CAS-clear failed but no pending blob remains; another drain already cleared it");
33531
33697
  return "cas-lost-already-cleared";
33532
33698
  }
33699
+ var defaultCompactionMarkerStrategy = {
33700
+ applyDeferred: applyDeferredCompactionMarker,
33701
+ reconcile: reconcileMarkerRepresentation
33702
+ };
33533
33703
  async function abortSessionFailClosed(client, sessionId) {
33534
33704
  if (typeof client.session?.abort !== "function") {
33535
33705
  throw new Error("OpenCode session.abort is unavailable");
@@ -33753,7 +33923,7 @@ async function runPostTransformPhase(args) {
33753
33923
  let heuristicOrReasoningDidMutate = false;
33754
33924
  let droppedCount = 0;
33755
33925
  let droppedTokens = 0;
33756
- const tokensBeforeReductions = isCacheBustingPass || shouldApplyPendingOps ? estimateTokens(JSON.stringify(args.messages)) : 0;
33926
+ const droppedTokenReductions = [];
33757
33927
  let emergencyReclaimedTokens = 0;
33758
33928
  let emergency = false;
33759
33929
  let m0M1InjectedThisPass = false;
@@ -33775,7 +33945,7 @@ async function runPostTransformPhase(args) {
33775
33945
  const applyReason = isExplicitFlush ? "explicit_flush" : deferredMaterialize ? "deferred_materialization" : foldExecutedThisPass && args.schedulerDecision !== "execute" ? `m0_hard_fold (drain folded into executed m[0] bust, scheduler=${args.schedulerDecision})` : `scheduler_execute (scheduler=${args.schedulerDecision})`;
33776
33946
  sessionLog(args.sessionId, `pending ops WILL APPLY — reason=${applyReason}, pendingOps=${formatPendingOpsDepth()}, context=${args.contextUsage.percentage.toFixed(1)}%`);
33777
33947
  const tApply = performance.now();
33778
- pendingOpsDidMutate = applyPendingOperations(args.sessionId, args.db, args.targets, args.contextUsage.percentage >= 95 ? newestCtxReduceTagNumbers(getTagsBySession(args.db, args.sessionId)) : args.protectedTagIds, undefined, pendingOps);
33948
+ pendingOpsDidMutate = applyPendingOperations(args.sessionId, args.db, args.targets, args.contextUsage.percentage >= 95 ? newestCtxReduceTagNumbers(getTagsBySession(args.db, args.sessionId)) : args.protectedTagIds, undefined, pendingOps, [], new Set, (reduction) => droppedTokenReductions.push(reduction));
33779
33949
  if (pendingOpsDidMutate) {
33780
33950
  rideSignals.agentDrop = true;
33781
33951
  isCacheBustingPass = hasReclaimRide(rideSignals);
@@ -33828,7 +33998,11 @@ async function runPostTransformPhase(args) {
33828
33998
  emergencyDroppedTools: cleanup.emergencyDroppedTools,
33829
33999
  emergencyReclaimedTokens: cleanup.emergencyReclaimedTokens,
33830
34000
  compressedTextTags: cleanup.compressedTextTags + ridingCleanup.compressedTextTags,
33831
- mutatedTextTags: cleanup.mutatedTextTags + ridingCleanup.mutatedTextTags
34001
+ mutatedTextTags: cleanup.mutatedTextTags + ridingCleanup.mutatedTextTags,
34002
+ droppedTokenReductions: [
34003
+ ...cleanup.droppedTokenReductions,
34004
+ ...ridingCleanup.droppedTokenReductions
34005
+ ]
33832
34006
  };
33833
34007
  routineCleanupApplied = true;
33834
34008
  }
@@ -33840,6 +34014,7 @@ async function runPostTransformPhase(args) {
33840
34014
  droppedCount += cleanup.droppedTools + cleanup.deduplicatedTools + cleanup.droppedInjections + cleanup.mutatedTextTags;
33841
34015
  emergency ||= cleanup.emergencyDroppedTools > 0;
33842
34016
  emergencyReclaimedTokens += cleanup.emergencyReclaimedTokens;
34017
+ droppedTokenReductions.push(...cleanup.droppedTokenReductions);
33843
34018
  const t7 = performance.now();
33844
34019
  const clearedReasoning = routineCleanupApplied && canUseEmptySentinels ? clearOldReasoning(args.messages, args.reasoningByMessage, args.messageTagNumbers, args.clearReasoningAge) : 0;
33845
34020
  if (routineCleanupApplied && canUseEmptySentinels) {
@@ -33927,7 +34102,7 @@ async function runPostTransformPhase(args) {
33927
34102
  }
33928
34103
  autoReclaimTargetCount = syntheticPendingOps.length;
33929
34104
  if (syntheticPendingOps.length > 0) {
33930
- autoReclaimDidMutate = applyPendingOperations(args.sessionId, args.db, args.targets, args.protectedTagIds, undefined, [], syntheticPendingOps, editMarkerTagIds);
34105
+ autoReclaimDidMutate = applyPendingOperations(args.sessionId, args.db, args.targets, args.protectedTagIds, undefined, [], syntheticPendingOps, editMarkerTagIds, (reduction) => droppedTokenReductions.push(reduction));
33931
34106
  if (autoReclaimDidMutate) {
33932
34107
  droppedCount += syntheticPendingOps.length;
33933
34108
  autoReclaimDidMutateThisPass = true;
@@ -33965,7 +34140,7 @@ async function runPostTransformPhase(args) {
33965
34140
  updateSessionMeta2(args.db, args.sessionId, { lastTransformError: getErrorMessage(error) });
33966
34141
  }
33967
34142
  if (isCacheBustingPass) {
33968
- droppedTokens = Math.max(0, tokensBeforeReductions - estimateTokens(JSON.stringify(args.messages)));
34143
+ droppedTokens = estimateDroppedTokensFromTagReductions(args.db, args.sessionId, droppedTokenReductions);
33969
34144
  }
33970
34145
  const replaySnapshot = !compactionOff ? loadPostprocessReplaySnapshot(args.db, args.sessionId) : undefined;
33971
34146
  if (canUseEmptySentinels && !compactionOff && replaySnapshot) {
@@ -34131,7 +34306,7 @@ async function runPostTransformPhase(args) {
34131
34306
  suppressV12HistoryDrain = true;
34132
34307
  sessionLog(args.sessionId, `compaction-marker drain: pending ordinal ${pending.ordinal} is newer than consumed boundary ${args.pendingCompartmentInjection?.compartmentEndMessage ?? "<none>"}; preserving deferred history refresh signal`);
34133
34308
  } else {
34134
- const outcome = applyDeferredCompactionMarker(args.db, args.sessionId, pending, args.sessionDirectory);
34309
+ const outcome = (args.compactionMarkerStrategy ?? defaultCompactionMarkerStrategy).applyDeferred(args.db, args.sessionId, pending, args.sessionDirectory);
34135
34310
  switch (outcome.kind) {
34136
34311
  case "applied":
34137
34312
  case "already-current":
@@ -34156,7 +34331,7 @@ async function runPostTransformPhase(args) {
34156
34331
  }
34157
34332
  }
34158
34333
  if (!compactionOff) {
34159
- reconcileMarkerRepresentation(args.messages, persistedCompactionMarkerState, {
34334
+ (args.compactionMarkerStrategy ?? defaultCompactionMarkerStrategy).reconcile(args.messages, persistedCompactionMarkerState, {
34160
34335
  db: args.db,
34161
34336
  sessionId: args.sessionId,
34162
34337
  tagger: args.tagger,
@@ -34848,6 +35023,10 @@ function responseValue(response) {
34848
35023
  throw new Error("module transform returned a non-object response");
34849
35024
  }
34850
35025
  function mirrorProjectionKey(response) {
35026
+ const memoryMirrorHead = response.memory_mirror_head;
35027
+ if (typeof memoryMirrorHead === "number" && Number.isSafeInteger(memoryMirrorHead) && memoryMirrorHead >= 0) {
35028
+ return JSON.stringify(["memory-feed", memoryMirrorHead]);
35029
+ }
34851
35030
  const rowVersion = response.row_version;
34852
35031
  if (typeof rowVersion !== "number" || !Number.isSafeInteger(rowVersion) || rowVersion < 0) {
34853
35032
  return null;
@@ -36940,7 +37119,7 @@ async function runCompartmentPhaseImpl(args) {
36940
37119
  sessionLog(args.sessionId, `transform: skipping compartment start, no eligible history before protected tail (beyond ${lastObservedCompartmentEnd})`);
36941
37120
  updateSessionMeta2(args.db, args.sessionId, { compartmentInProgress: false });
36942
37121
  compartmentInProgress = false;
36943
- } else if (!args.client) {
37122
+ } else if (!args.client && !args.hiddenCompletionExecutor) {
36944
37123
  sessionLog(args.sessionId, "transform: cannot start compartment agent without client");
36945
37124
  updateSessionMeta2(args.db, args.sessionId, { compartmentInProgress: false });
36946
37125
  compartmentInProgress = false;
@@ -36948,6 +37127,8 @@ async function runCompartmentPhaseImpl(args) {
36948
37127
  sessionLog(args.sessionId, "transform: compartmentInProgress flag set, starting agent");
36949
37128
  startCompartmentAgent({
36950
37129
  client: args.client,
37130
+ hiddenCompletionExecutor: args.hiddenCompletionExecutor,
37131
+ compactionMarkerStrategy: args.compactionMarkerStrategy,
36951
37132
  db: args.db,
36952
37133
  sessionId: args.sessionId,
36953
37134
  historianChunkTokens: args.historianChunkTokens,
@@ -36976,10 +37157,12 @@ async function runCompartmentPhaseImpl(args) {
36976
37157
  let awaitedCompartmentRun = false;
36977
37158
  if (historianRunnable && args.canRunCompartments && !args.skipAwaitForThisPass && args.contextUsage.percentage >= BLOCK_UNTIL_DONE_PERCENTAGE) {
36978
37159
  let activeRun = getActiveCompartmentRun(args.sessionId);
36979
- if (!activeRun && hasEligibleHistoryForCompartment() && args.client) {
37160
+ if (!activeRun && hasEligibleHistoryForCompartment() && (args.client || args.hiddenCompletionExecutor)) {
36980
37161
  sessionLog(args.sessionId, `transform: 95% reached (${args.contextUsage.percentage.toFixed(1)}%), force-starting compartment agent and blocking`);
36981
37162
  startCompartmentAgent({
36982
37163
  client: args.client,
37164
+ hiddenCompletionExecutor: args.hiddenCompletionExecutor,
37165
+ compactionMarkerStrategy: args.compactionMarkerStrategy,
36983
37166
  db: args.db,
36984
37167
  sessionId: args.sessionId,
36985
37168
  historianChunkTokens: args.historianChunkTokens,
@@ -37214,7 +37397,16 @@ function scheduleTsAuthorityRecovery(args) {
37214
37397
  }
37215
37398
  });
37216
37399
  }
37400
+ function resolveTransformHostSeams(deps) {
37401
+ return {
37402
+ hostRawMessages: deps.hostRawMessages ?? readRawSessionMessages,
37403
+ hostProtectedTailBoundary: deps.hostProtectedTailBoundary ?? resolveOpenCodeProtectedTailBoundary,
37404
+ hostModelFallback: deps.hostModelFallback ?? findLastAssistantModelFromOpenCodeDb,
37405
+ hostRefuse: deps.hostRefuse ?? abortSessionFailClosed
37406
+ };
37407
+ }
37217
37408
  function createTransform(deps) {
37409
+ const host = resolveTransformHostSeams(deps);
37218
37410
  const loadedSessions = new Set;
37219
37411
  const rustModeTransform = deps.transformMode === "rust" && deps.rustModeModuleClient ? createRustModeTransform(deps, {
37220
37412
  moduleClient: deps.rustModeModuleClient,
@@ -37250,7 +37442,7 @@ function createTransform(deps) {
37250
37442
  logTransformTiming(sessionId, "findSessionId", startTime, `messages=${messages.length}`);
37251
37443
  const db = deps.db;
37252
37444
  if (deps.client !== undefined) {
37253
- scheduleReconciliation(db, sessionId, readRawSessionMessages);
37445
+ scheduleReconciliation(db, sessionId, host.hostRawMessages);
37254
37446
  }
37255
37447
  const tUserMsg = performance.now();
37256
37448
  const currentTurnId = findLastUserMessageId(messages);
@@ -37353,7 +37545,7 @@ function createTransform(deps) {
37353
37545
  }
37354
37546
  const compartmentDirectory = sessionDirectory;
37355
37547
  const historianRunnable = deps.historianRunnable !== false;
37356
- const canRunCompartments = fullFeatureMode && !compactionOff && historianRunnable && deps.client !== undefined && compartmentDirectory.length > 0;
37548
+ const canRunCompartments = fullFeatureMode && !compactionOff && historianRunnable && (deps.client !== undefined || deps.hiddenCompletionExecutor !== undefined) && compartmentDirectory.length > 0;
37357
37549
  const fallbackModelId = deps.getFallbackModelId?.(sessionId);
37358
37550
  const tModelDetect = performance.now();
37359
37551
  const persistedUsageBeforeResets = contextUsagePassSnapshot(sessionMeta).persistedUsage;
@@ -37458,7 +37650,7 @@ function createTransform(deps) {
37458
37650
  }
37459
37651
  let modelForBudget = deps.liveModelBySession?.get(sessionId);
37460
37652
  if (!modelForBudget) {
37461
- const recovered = findLastAssistantModelFromOpenCodeDb(sessionId);
37653
+ const recovered = host.hostModelFallback(sessionId);
37462
37654
  if (recovered) {
37463
37655
  modelForBudget = recovered;
37464
37656
  deps.liveModelBySession?.set(sessionId, recovered);
@@ -37514,7 +37706,7 @@ function createTransform(deps) {
37514
37706
  if (!canRunCompartments)
37515
37707
  return null;
37516
37708
  if (_boundarySnapshotCache === undefined || emergencyTailScale) {
37517
- const snapshot = resolveOpenCodeProtectedTailBoundary({
37709
+ const snapshot = host.hostProtectedTailBoundary({
37518
37710
  db,
37519
37711
  sessionId: resolvedSessionId,
37520
37712
  mode: "transform-force",
@@ -37546,7 +37738,7 @@ function createTransform(deps) {
37546
37738
  boundarySnapshot = getRunnableBoundaryForCompartment(scale);
37547
37739
  }
37548
37740
  if (false) {}
37549
- if (!canRunCompartments || !deps.client || !boundarySnapshot || !hasRunnableCompartmentWindow(boundarySnapshot)) {
37741
+ if (!canRunCompartments || !deps.client && !deps.hiddenCompletionExecutor || !boundarySnapshot || !hasRunnableCompartmentWindow(boundarySnapshot)) {
37550
37742
  return false;
37551
37743
  }
37552
37744
  if (getActiveCompartmentRun(sessionId)) {
@@ -37555,6 +37747,8 @@ function createTransform(deps) {
37555
37747
  updateSessionMeta2(db, sessionId, { compartmentInProgress: true });
37556
37748
  startCompartmentAgent({
37557
37749
  client: deps.client,
37750
+ hiddenCompletionExecutor: deps.hiddenCompletionExecutor,
37751
+ compactionMarkerStrategy: deps.compactionMarkerStrategy,
37558
37752
  db,
37559
37753
  sessionId,
37560
37754
  historianChunkTokens: deps.getHistorianChunkTokens?.() ?? 20000,
@@ -37761,6 +37955,8 @@ Historian previously failed ${historianFailureState.failureCount} time(s), so Ma
37761
37955
  const rawGetNotifParams = deps.getNotificationParams;
37762
37956
  const tCompartmentPhase = performance.now();
37763
37957
  const compartmentPhase = await runCompartmentPhase({
37958
+ hiddenCompletionExecutor: deps.hiddenCompletionExecutor,
37959
+ compactionMarkerStrategy: deps.compactionMarkerStrategy,
37764
37960
  canRunCompartments,
37765
37961
  fullFeatureMode,
37766
37962
  compactionOff,
@@ -37871,6 +38067,7 @@ Historian previously failed ${historianFailureState.failureCount} time(s), so Ma
37871
38067
  const protectedCutoff = protectionWindow.cutoff;
37872
38068
  const tPostProcess = performance.now();
37873
38069
  const postTransformResult = await runPostTransformPhase({
38070
+ compactionMarkerStrategy: deps.compactionMarkerStrategy ?? defaultCompactionMarkerStrategy,
37874
38071
  sessionId,
37875
38072
  db,
37876
38073
  messages,
@@ -37988,7 +38185,7 @@ Historian previously failed ${historianFailureState.failureCount} time(s), so Ma
37988
38185
  throw new EmergencyFailClosedError(`Emergency recovery notification was ${notification}`);
37989
38186
  }
37990
38187
  try {
37991
- await abortSessionFailClosed(deps.client, sessionId);
38188
+ await host.hostRefuse(deps.client, sessionId);
37992
38189
  } catch (error) {
37993
38190
  sessionLog(sessionId, "transform: emergency fail-closed abort failed; refusing to return a sendable prompt:", getErrorMessage(error));
37994
38191
  throw new EmergencyFailClosedError("Emergency recovery abort failed", {
@@ -39785,7 +39982,7 @@ function createMagicContextHook(deps) {
39785
39982
  };
39786
39983
  const rustMemorySyncRequestedSessions = new Set;
39787
39984
  const authorityRecoveryModuleClient = deps.rustModeModuleClient ?? (() => {
39788
- const transport = new SubcModuleTransport(deps.config.subc?.connection_file);
39985
+ const transport = new SubcModuleTransport(deps.config.subc?.connection_file ?? getDefaultSubcConnectionFile());
39789
39986
  const client = {
39790
39987
  call: (args) => transport.call(args),
39791
39988
  stateSyncCapabilities: (args) => transport.stateSyncCapabilities(args),
@@ -39839,13 +40036,14 @@ function createMagicContextHook(deps) {
39839
40036
  const syncModuleNotes = () => syncModuleDomain("notes");
39840
40037
  const syncModuleMemories = () => syncModuleDomain("memories");
39841
40038
  const rustToolBackends = deps.config.transform_mode === "rust" && rustModeModuleClient ? {
39842
- authorityState: async ({ projectPath, projectRoot, domain }) => {
40039
+ authorityState: async ({ projectPath, projectRoot, sessionId, domain }) => {
39843
40040
  if (!rustModeModuleClient.authorityStatus)
39844
40041
  return null;
39845
40042
  const result = await rustModeModuleClient.authorityStatus({
39846
40043
  context_store_uuid: ensureContextStoreUuid(db),
39847
40044
  project: projectPath,
39848
40045
  projectRoot,
40046
+ sessionId,
39849
40047
  domain
39850
40048
  });
39851
40049
  return result.authority?.state ?? null;
@@ -39930,7 +40128,8 @@ function createMagicContextHook(deps) {
39930
40128
  content,
39931
40129
  category,
39932
40130
  ids,
39933
- reason
40131
+ reason,
40132
+ limit
39934
40133
  }) => {
39935
40134
  const response = await rustModeModuleClient.call({
39936
40135
  sessionId,
@@ -39945,6 +40144,7 @@ function createMagicContextHook(deps) {
39945
40144
  category,
39946
40145
  ids,
39947
40146
  reason,
40147
+ limit,
39948
40148
  memory_project: memoryProject
39949
40149
  }
39950
40150
  }
@@ -41070,6 +41270,9 @@ function memoryAuthorityRefusal(args) {
41070
41270
  const isMutation = args.action !== undefined && ["write", "update", "archive", "merge"].includes(args.action);
41071
41271
  return renderCapabilityRefusal(isMutation ? "memory_write" : "memory_access");
41072
41272
  }
41273
+ function memoryAuthorityMismatchRefusal() {
41274
+ return renderUserFacingFailure("memory_authority_mismatch");
41275
+ }
41073
41276
  function moduleMemoryText(response, args) {
41074
41277
  let value = response;
41075
41278
  if (value !== null && typeof value === "object" && "result" in value) {
@@ -41339,13 +41542,14 @@ function createCtxMemoryTool(deps) {
41339
41542
  }) : { skip: null, successor: null };
41340
41543
  if (curatePreflight.skip)
41341
41544
  return curatePreflight.skip;
41342
- if (args.action !== "list") {
41545
+ {
41343
41546
  const marker = getAuthorityManagedMarker(deps.db, projectPath);
41344
41547
  let authorityState = null;
41345
41548
  try {
41346
41549
  authorityState = await deps.rustToolBackends?.authorityState?.({
41347
41550
  projectPath,
41348
41551
  projectRoot: toolContext.directory,
41552
+ sessionId: toolContext.sessionID,
41349
41553
  domain: "memories"
41350
41554
  }) ?? null;
41351
41555
  } catch (error) {
@@ -41382,7 +41586,8 @@ function createCtxMemoryTool(deps) {
41382
41586
  content: moduleArgs.content,
41383
41587
  category: moduleArgs.category,
41384
41588
  ids: moduleArgs.ids,
41385
- reason: moduleArgs.reason
41589
+ reason: moduleArgs.reason,
41590
+ limit: moduleArgs.action === "list" ? normalizeLimit2(moduleArgs.limit) : undefined
41386
41591
  }), moduleArgs);
41387
41592
  return text ?? memoryAuthorityRefusal(args);
41388
41593
  } catch (error) {
@@ -41393,6 +41598,9 @@ function createCtxMemoryTool(deps) {
41393
41598
  return memoryAuthorityRefusal(args);
41394
41599
  }
41395
41600
  }
41601
+ if (marker && (authorityState === null || authorityState === "TS")) {
41602
+ return memoryAuthorityMismatchRefusal();
41603
+ }
41396
41604
  if (marker || authorityState === "PREPARING" || authorityState === "DRAINING") {
41397
41605
  return memoryAuthorityRefusal(args);
41398
41606
  }
@@ -42417,6 +42625,7 @@ function createCtxNoteTool(deps) {
42417
42625
  notesAuthority = await deps.rustToolBackends.authorityState({
42418
42626
  projectPath: projectIdentity,
42419
42627
  projectRoot: toolContext.directory,
42628
+ sessionId,
42420
42629
  domain: "notes"
42421
42630
  });
42422
42631
  } catch (error) {
@@ -43383,6 +43592,1111 @@ function json(body, status = 200) {
43383
43592
  });
43384
43593
  }
43385
43594
 
43595
+ // src/v2/fold/markers.ts
43596
+ var v2CompactionMarkerStrategy = {
43597
+ setPending: () => {},
43598
+ publish: () => false,
43599
+ applyDeferred: () => ({ kind: "already-current" }),
43600
+ reconcile: () => false
43601
+ };
43602
+
43603
+ // src/v2/fold/owner.ts
43604
+ import { createHash as createHash15 } from "node:crypto";
43605
+ var foldDigest = (value) => createHash15("sha256").update(value).digest("hex");
43606
+
43607
+ class FoldOwner {
43608
+ storage;
43609
+ pending = new Map;
43610
+ constructor(storage) {
43611
+ this.storage = storage;
43612
+ }
43613
+ async serial(sessionID, operation) {
43614
+ const previous = this.pending.get(sessionID) ?? Promise.resolve();
43615
+ const next = previous.catch(() => {}).then(operation);
43616
+ this.pending.set(sessionID, next);
43617
+ try {
43618
+ return await next;
43619
+ } finally {
43620
+ if (this.pending.get(sessionID) === next)
43621
+ this.pending.delete(sessionID);
43622
+ }
43623
+ }
43624
+ key(sessionID) {
43625
+ return `fold/v1/${sessionID}`;
43626
+ }
43627
+ async read(sessionID) {
43628
+ return await this.storage.get(this.key(sessionID));
43629
+ }
43630
+ async supply(args) {
43631
+ return this.serial(args.sessionID, async () => {
43632
+ const previous = await this.read(args.sessionID);
43633
+ const same = previous && (args.runningCut !== undefined ? previous.cutSeq === args.runningCut : previous.cutSeq === undefined && previous.watermark === args.watermark);
43634
+ if (same)
43635
+ return previous;
43636
+ const submitted = args.materialize();
43637
+ const next = {
43638
+ watermark: args.watermark,
43639
+ cutSeq: args.runningCut,
43640
+ submitted,
43641
+ submittedSha: foldDigest(submitted)
43642
+ };
43643
+ await this.storage.set(this.key(args.sessionID), next);
43644
+ return next;
43645
+ });
43646
+ }
43647
+ async observe(args) {
43648
+ return this.serial(args.sessionID, async () => {
43649
+ let state = await this.read(args.sessionID);
43650
+ const renderedSha = foldDigest(JSON.stringify(args.rendered));
43651
+ if (!state) {
43652
+ args.onHard("boot_recovery");
43653
+ state = {
43654
+ watermark: args.cutSeq,
43655
+ submitted: args.summary,
43656
+ submittedSha: foldDigest(args.summary),
43657
+ reason: "boot_recovery"
43658
+ };
43659
+ }
43660
+ const reason = args.cutSeq < state.watermark ? "host_cut_before_watermark" : state.submittedSha !== foldDigest(args.summary) || state.renderedSha && state.renderedSha !== renderedSha ? "host_rerender" : undefined;
43661
+ if (reason && state.rejectedSha !== renderedSha) {
43662
+ args.onHard(reason);
43663
+ state.reason = reason;
43664
+ state.rejectedSha = renderedSha;
43665
+ }
43666
+ if (state.cutSeq === undefined && args.cutSeq >= state.watermark)
43667
+ state.cutSeq = args.cutSeq;
43668
+ if (!state.rendered && reason !== "host_cut_before_watermark") {
43669
+ state.rendered = structuredClone(args.rendered);
43670
+ state.renderedSha = renderedSha;
43671
+ state.renderedSummary = args.summary;
43672
+ }
43673
+ await this.storage.set(this.key(args.sessionID), state);
43674
+ return state;
43675
+ });
43676
+ }
43677
+ }
43678
+
43679
+ // src/v2/fold/restore.ts
43680
+ import { fileURLToPath as fileURLToPath2 } from "node:url";
43681
+ var imageMimes = new Set(["image/png", "image/jpeg", "image/gif", "image/webp"]);
43682
+ function attachmentParts(files) {
43683
+ const seen = new Map;
43684
+ return files.flatMap((file) => {
43685
+ if (imageMimes.has(file.mime) && file.source.type === "inline" && file.mention?.text) {
43686
+ const key = JSON.stringify([
43687
+ file.mime,
43688
+ file.name ?? null,
43689
+ file.description ?? null,
43690
+ file.mention.text
43691
+ ]);
43692
+ const payloads = seen.get(key) ?? new Set;
43693
+ if (payloads.has(file.data))
43694
+ return [];
43695
+ payloads.add(file.data);
43696
+ seen.set(key, payloads);
43697
+ }
43698
+ const uri = file.source.type === "uri" ? file.source.uri : undefined;
43699
+ const location = uri?.startsWith("file:") ? fileURLToPath2(uri) : undefined;
43700
+ if (file.mime === "text/plain" || file.mime === "application/x-directory") {
43701
+ const directory = file.mime === "application/x-directory";
43702
+ return [
43703
+ {
43704
+ type: "text",
43705
+ text: `
43706
+
43707
+ ${[
43708
+ directory ? `Attached directory: ${location ?? file.name ?? uri ?? "directory"}` : `Attached file: ${file.name ?? uri ?? "inline attachment"}`,
43709
+ file.description === undefined ? undefined : `Description: ${file.description}`,
43710
+ directory && !file.data.length ? undefined : "",
43711
+ directory && !file.data.length ? undefined : Buffer.from(file.data, "base64").toString("utf8")
43712
+ ].filter((line) => line !== undefined).join(`
43713
+ `)}`,
43714
+ metadata: {
43715
+ attachment: {
43716
+ source: file.source,
43717
+ name: file.name,
43718
+ description: file.description
43719
+ }
43720
+ }
43721
+ }
43722
+ ];
43723
+ }
43724
+ if (!imageMimes.has(file.mime) && file.mime !== "application/pdf")
43725
+ return [];
43726
+ return [
43727
+ ...location ? [{ type: "text", text: `Attached file: ${location}` }] : [],
43728
+ {
43729
+ type: "media",
43730
+ mediaType: file.mime,
43731
+ data: file.data,
43732
+ filename: file.name,
43733
+ metadata: file.description === undefined ? undefined : { description: file.description }
43734
+ }
43735
+ ];
43736
+ });
43737
+ }
43738
+ function restoreRow(row, model) {
43739
+ const data = row.data;
43740
+ const make = (role, content, metadata = data.metadata) => ({
43741
+ id: row.id,
43742
+ role,
43743
+ content,
43744
+ ...metadata === undefined ? {} : { metadata }
43745
+ });
43746
+ if (row.type === "user") {
43747
+ const skills = data.skills ?? [];
43748
+ const content = [
43749
+ ...skills.flatMap((skill) => skill.text === undefined ? [] : [{ type: "text", text: skill.text }]),
43750
+ ...data.text ? [{ type: "text", text: data.text }] : [],
43751
+ ...attachmentParts(data.files ?? [])
43752
+ ];
43753
+ return content.length ? [
43754
+ make("user", content, {
43755
+ ...data.metadata ?? {},
43756
+ ...data.agents?.length ? { agents: data.agents } : {}
43757
+ })
43758
+ ] : [];
43759
+ }
43760
+ if (["synthetic", "skill", "system"].includes(row.type))
43761
+ return [
43762
+ make(row.type === "system" ? "system" : "user", [
43763
+ { type: "text", text: data.text ?? "" }
43764
+ ])
43765
+ ];
43766
+ if (row.type === "location-switched")
43767
+ return [
43768
+ make("user", [
43769
+ {
43770
+ type: "text",
43771
+ text: `The working directory has been changed to ${data.location.directory}.`
43772
+ }
43773
+ ])
43774
+ ];
43775
+ if (row.type === "shell")
43776
+ return data.metadata?.background === true ? [] : [
43777
+ make("user", [
43778
+ {
43779
+ type: "text",
43780
+ text: `The following shell command was executed by the user:
43781
+
43782
+ Command:
43783
+ ${data.command}
43784
+
43785
+ Output:
43786
+ ${data.output?.output ?? ""}`
43787
+ }
43788
+ ])
43789
+ ];
43790
+ if (row.type !== "assistant")
43791
+ return [];
43792
+ const previousModel = data.model;
43793
+ const sameProvider = previousModel?.providerID === model.providerID;
43794
+ const sameModel = sameProvider && previousModel?.id === model.id;
43795
+ const reuse = sameModel && data.error === undefined;
43796
+ const metadata = (state) => state === undefined ? undefined : { [model.providerID]: state };
43797
+ const content = [];
43798
+ const results = [];
43799
+ for (const part of data.content ?? []) {
43800
+ if (part.type === "text") {
43801
+ if (part.text !== "")
43802
+ content.push({
43803
+ type: "text",
43804
+ text: part.text,
43805
+ providerMetadata: reuse ? metadata(part.state) : undefined
43806
+ });
43807
+ continue;
43808
+ }
43809
+ if (part.type === "reasoning") {
43810
+ if (part.text !== "" || reuse && part.state !== undefined)
43811
+ content.push({
43812
+ type: reuse || data.error === undefined ? "reasoning" : "text",
43813
+ text: part.text,
43814
+ providerMetadata: reuse ? metadata(part.state) : undefined
43815
+ });
43816
+ continue;
43817
+ }
43818
+ const state = part.state;
43819
+ const completed = state.status === "completed" || state.status === "error";
43820
+ const toolReuse = reuse || sameModel && part.executed === true && completed;
43821
+ let input = state.input;
43822
+ if (state.status === "streaming" && typeof input === "string") {
43823
+ try {
43824
+ input = JSON.parse(input);
43825
+ } catch {}
43826
+ }
43827
+ content.push({
43828
+ type: "tool-call",
43829
+ id: part.id,
43830
+ name: part.name,
43831
+ input,
43832
+ providerExecuted: part.executed,
43833
+ providerMetadata: toolReuse ? metadata(part.providerState) : undefined
43834
+ });
43835
+ if (!completed)
43836
+ continue;
43837
+ const toolContent = state.content ?? [];
43838
+ const single = toolContent.length === 1 ? toolContent[0] : undefined;
43839
+ const result = {
43840
+ type: "tool-result",
43841
+ id: part.id,
43842
+ name: part.name,
43843
+ providerExecuted: part.executed,
43844
+ providerMetadata: toolReuse ? metadata(part.providerResultState ?? part.providerState) : sameProvider ? metadata(part.providerResultState) : undefined,
43845
+ result: state.status === "error" ? { error: state.error, content: toolContent } : single?.type === "text" ? { type: "text", value: single.text } : { type: "content", value: toolContent },
43846
+ ...state.status === "error" ? { resultType: "error" } : {}
43847
+ };
43848
+ if (part.executed === true)
43849
+ content.push(result);
43850
+ else
43851
+ results.push({ role: "tool", content: [result] });
43852
+ }
43853
+ return [...content.length ? [make("assistant", content)] : [], ...results];
43854
+ }
43855
+
43856
+ // src/v2/hidden-completion.ts
43857
+ function meter(system, prompt, text) {
43858
+ return {
43859
+ input: estimateTokens(system) + estimateTokens(prompt),
43860
+ output: estimateTokens(text),
43861
+ cacheRead: 0,
43862
+ cacheWrite: 0
43863
+ };
43864
+ }
43865
+ async function createV2HiddenCompletionExecutor(host, currentModel) {
43866
+ const runs = new WeakMap;
43867
+ const pending = new Map;
43868
+ const modelKey = (model) => `${model.providerID}/${model.modelID}`;
43869
+ const requireModel = async (sessionID) => {
43870
+ const model = sessionID ? await currentModel(sessionID) : null;
43871
+ if (!model)
43872
+ throw new HiddenCompletionRefusal("hidden_model_unsupported", "Hidden completion requires an existing session with a resolved current model", true);
43873
+ return model;
43874
+ };
43875
+ const refuseModel = (requested, actual, terminal = false) => {
43876
+ throw new HiddenCompletionRefusal("hidden_model_unsupported", `Hidden completion model ${requested} is unavailable on opencode2; use the session model ${actual} in historian.model or dreaming task model configuration, or unset the configured model`, terminal);
43877
+ };
43878
+ await host.hook("generate", async (draft) => {
43879
+ const last = draft.messages.at(-1);
43880
+ if (last?.role !== "user" || last.content.length !== 1)
43881
+ return;
43882
+ const part = last.content[0];
43883
+ if (part?.type !== "text" || typeof part.text !== "string")
43884
+ return;
43885
+ const attempt = pending.get(part.text);
43886
+ if (!attempt || draft.sessionID !== attempt.run.identity.parentSessionId)
43887
+ return;
43888
+ const actual = `${draft.model.providerID}/${draft.model.id}`;
43889
+ if (modelKey(attempt.model) !== actual)
43890
+ refuseModel(modelKey(attempt.model), actual);
43891
+ if (attempt.request.signal?.aborted)
43892
+ throw new Error("Hidden completion prompt aborted");
43893
+ const body = attempt.request.body;
43894
+ if (typeof body.variant === "string" && body.variant !== draft.model.variant) {
43895
+ refuseModel(`${actual} (${body.variant})`, `${actual} (${draft.model.variant ?? "default variant"})`);
43896
+ }
43897
+ const parts = body.parts;
43898
+ if (!Array.isArray(parts) || parts.some((item) => item.type !== "text" || typeof item.text !== "string")) {
43899
+ throw new HiddenCompletionRefusal("hidden_prompt_unrecognized", "Hidden completion accepts text-only calibrated prompts", true);
43900
+ }
43901
+ draft.system = [
43902
+ {
43903
+ type: "text",
43904
+ text: typeof body.system === "string" ? body.system : attempt.run.identity.system
43905
+ }
43906
+ ];
43907
+ draft.messages = [
43908
+ { role: "user", content: parts.map((item) => ({ type: "text", text: item.text })) }
43909
+ ];
43910
+ draft.tools = {};
43911
+ if (attempt.run.identity.maxOutputTokens !== undefined)
43912
+ draft.options.maxOutputTokens = attempt.run.identity.maxOutputTokens;
43913
+ attempt.shaped = true;
43914
+ });
43915
+ return {
43916
+ capabilities: { tools: false, harness: "opencode2" },
43917
+ async open(identity) {
43918
+ const model = await requireModel(identity.parentSessionId);
43919
+ const configured = (identity.configuredModels ?? (identity.model ? [identity.model] : [])).map(toModelEntry).filter((entry) => entry !== undefined);
43920
+ if (configured.length && !configured.some((entry) => entry.model === modelKey(model))) {
43921
+ refuseModel(configured.map((entry) => entry.model).join(", "), modelKey(model), true);
43922
+ }
43923
+ const handle = { id: `mc:hidden:${crypto.randomUUID()}` };
43924
+ runs.set(handle, { identity });
43925
+ return handle;
43926
+ },
43927
+ async attempt(handle, request) {
43928
+ const run = runs.get(handle);
43929
+ if (!run)
43930
+ throw new Error("Unknown hidden completion run");
43931
+ const sessionID = run.identity.parentSessionId;
43932
+ const actual = await requireModel(sessionID);
43933
+ if (sessionID === undefined)
43934
+ throw new Error("Hidden completion session id missing");
43935
+ const requested = request.body.model ?? actual;
43936
+ if (modelKey(requested) !== modelKey(actual))
43937
+ refuseModel(modelKey(requested), modelKey(actual));
43938
+ if (request.signal?.aborted)
43939
+ throw new Error("Hidden completion prompt aborted");
43940
+ const marker = `${handle.id}:${crypto.randomUUID()}`;
43941
+ const state = { run, request, model: actual, shaped: false };
43942
+ pending.set(marker, state);
43943
+ try {
43944
+ const generation = host.generate({ sessionID, prompt: marker }, { signal: request.signal });
43945
+ const result = await new Promise((resolve, reject) => {
43946
+ const abort = () => reject(new Error("Hidden completion prompt aborted"));
43947
+ request.signal?.addEventListener("abort", abort, { once: true });
43948
+ generation.then(resolve, reject).finally(() => {
43949
+ request.signal?.removeEventListener("abort", abort);
43950
+ pending.delete(marker);
43951
+ });
43952
+ if (request.signal?.aborted)
43953
+ abort();
43954
+ });
43955
+ if (!state.shaped)
43956
+ throw new HiddenCompletionRefusal("hidden_prompt_unrecognized", "Host did not dispatch the hidden generate hook", true);
43957
+ const prompt = request.body.parts.map((part) => part.text).join(`
43958
+ `);
43959
+ const system = typeof request.body.system === "string" ? request.body.system : run.identity.system;
43960
+ const usage = meter(system, prompt, result.text);
43961
+ usage.input += run.usage?.input ?? 0;
43962
+ usage.output += run.usage?.output ?? 0;
43963
+ run.usage = usage;
43964
+ run.completion = {
43965
+ text: result.text,
43966
+ usage,
43967
+ lengthCapped: false,
43968
+ providerId: actual.providerID,
43969
+ modelId: actual.modelID
43970
+ };
43971
+ } finally {
43972
+ if (!request.signal?.aborted)
43973
+ pending.delete(marker);
43974
+ }
43975
+ },
43976
+ async collect(handle) {
43977
+ const completion = runs.get(handle)?.completion;
43978
+ if (!completion)
43979
+ throw new Error("Hidden completion has no settled output");
43980
+ return completion;
43981
+ },
43982
+ async close() {}
43983
+ };
43984
+ }
43985
+
43986
+ // src/v2/store-reader.ts
43987
+ import { join as join11 } from "node:path";
43988
+ function sourceDatabaseFilename(channel, env = process.env) {
43989
+ return env.OPENCODE_DB ?? (["latest", "dev", "beta", "next", "prod"].includes(channel) || env.OPENCODE_DISABLE_CHANNEL_DB === "1" || env.OPENCODE_DISABLE_CHANNEL_DB === "true" ? "opencode.db" : `opencode-${channel.replace(/[^a-zA-Z0-9._-]/g, "")}.db`);
43990
+ }
43991
+ function gaDatabasePath(dataHome, channel = "latest", env = process.env) {
43992
+ const filename = sourceDatabaseFilename(channel, env);
43993
+ return filename === ":memory:" ? filename : join11(dataHome, "opencode", filename);
43994
+ }
43995
+ function decode(row) {
43996
+ const data = JSON.parse(row.data);
43997
+ if (!data || typeof data !== "object" || Array.isArray(data)) {
43998
+ throw new Error(`Invalid session_message data at seq ${row.seq}`);
43999
+ }
44000
+ if (row.type === "idle" && !["succeeded", "failed", "interrupted"].includes(String(data.outcome))) {
44001
+ throw new Error(`Invalid idle outcome at seq ${row.seq}`);
44002
+ }
44003
+ return { ...row, data };
44004
+ }
44005
+
44006
+ class V2StoreReader {
44007
+ db;
44008
+ constructor(path) {
44009
+ this.db = new Database(path, { readonly: true, fileMustExist: true });
44010
+ }
44011
+ close() {
44012
+ this.db.close();
44013
+ }
44014
+ page(sessionID, options = {}) {
44015
+ const limit = options.limit ?? 100;
44016
+ if (!Number.isSafeInteger(limit) || limit < 1 || limit > 1e4)
44017
+ throw new Error("Invalid page limit");
44018
+ const after = options.after ?? -1;
44019
+ if (!Number.isSafeInteger(after))
44020
+ throw new Error("Invalid seq cursor");
44021
+ const rows = this.db.prepare(`SELECT id, session_id, type, seq, data FROM session_message
44022
+ WHERE session_id = ? AND seq > ? ${options.type ? "AND type = ?" : ""}
44023
+ ORDER BY seq ASC LIMIT ?`).all(...options.type ? [sessionID, after, options.type, limit] : [sessionID, after, limit]).map(decode);
44024
+ return { rows, cursor: rows.at(-1)?.seq };
44025
+ }
44026
+ latestCompaction(sessionID) {
44027
+ const row = this.db.prepare(`SELECT id, session_id, type, seq, data FROM session_message
44028
+ WHERE session_id = ? AND type = 'compaction' AND json_extract(data, '$.status') = 'completed'
44029
+ ORDER BY seq DESC LIMIT 1`).get(sessionID);
44030
+ return row ? decode(row) : undefined;
44031
+ }
44032
+ idleRows(sessionID, after = -1) {
44033
+ return this.all(sessionID, after, "idle");
44034
+ }
44035
+ window(sessionID) {
44036
+ return this.db.transaction(() => {
44037
+ const cut = this.latestCompaction(sessionID);
44038
+ return this.all(sessionID, cut ? cut.seq - 1 : -1);
44039
+ })();
44040
+ }
44041
+ history(sessionID) {
44042
+ return this.all(sessionID, -1);
44043
+ }
44044
+ all(sessionID, after, type) {
44045
+ const rows = [];
44046
+ for (;; ) {
44047
+ const page = this.page(sessionID, { after, type });
44048
+ rows.push(...page.rows);
44049
+ if (page.rows.length < 100 || page.cursor === undefined)
44050
+ return rows;
44051
+ after = page.cursor;
44052
+ }
44053
+ }
44054
+ }
44055
+
44056
+ // src/v2/hooks/channel2.ts
44057
+ import { randomBytes as randomBytes2 } from "node:crypto";
44058
+ async function deliverSynthetic(context, sessionID, text) {
44059
+ const id = `msg_${randomBytes2(12).toString("hex")}`;
44060
+ await context.storage.set(`synthetic/${sessionID}/${id}`, { id });
44061
+ await context.session.synthetic({ sessionID, id, text, delivery: "steer" });
44062
+ return id;
44063
+ }
44064
+ async function isAdmittedSynthetic(context, sessionID, id) {
44065
+ const record = await context.storage.get(`synthetic/${sessionID}/${id}`);
44066
+ return record !== null && typeof record === "object" && "id" in record && record.id === id;
44067
+ }
44068
+ async function deliverPendingChannel2(context, db, sessionID, baseline) {
44069
+ if (getChannel2NudgeState(db, sessionID) !== "pending")
44070
+ return;
44071
+ const evaluation = evaluateChannel2(baseline);
44072
+ if (!evaluation.evaluable || !evaluation.shouldTrigger)
44073
+ return;
44074
+ const token = randomBytes2(16).toString("hex");
44075
+ if (!claimChannel2NudgeState(db, sessionID, token))
44076
+ return;
44077
+ try {
44078
+ await deliverSynthetic(context, sessionID, buildChannel2Reminder(evaluation.reclaimableTokens, reclaimableToolOutputCount(baseline?.baselineParts ?? [])));
44079
+ } catch (error) {
44080
+ casChannel2NudgeClaim(db, sessionID, "pending", token);
44081
+ throw error;
44082
+ }
44083
+ casChannel2NudgeClaim(db, sessionID, "delivered", token);
44084
+ }
44085
+
44086
+ // src/v2/hooks/dream-trigger.ts
44087
+ function startDreamTrigger(context, args) {
44088
+ const controller = new AbortController;
44089
+ const done = (async () => {
44090
+ try {
44091
+ for await (const value of context.event.subscribe({ signal: controller.signal })) {
44092
+ if (controller.signal.aborted)
44093
+ break;
44094
+ const event = value;
44095
+ if (event.type !== "session.execution.succeeded" || !event.data?.sessionID)
44096
+ continue;
44097
+ const db = openDatabase();
44098
+ if (!db)
44099
+ continue;
44100
+ try {
44101
+ await runDueTasksForProject({
44102
+ db,
44103
+ projectIdentity: args.projectIdentity(),
44104
+ tasks: buildDreamTaskRuntimeConfigs2(args.config, "opencode", args.language, args.mural?.model),
44105
+ executor: createDreamTaskExecutor({
44106
+ hiddenCompletionExecutor: args.executor,
44107
+ parentSessionId: event.data.sessionID,
44108
+ sessionDirectory: context.location.directory,
44109
+ openOpenCodeDb: () => null,
44110
+ language: args.language,
44111
+ mural: args.mural
44112
+ })
44113
+ });
44114
+ } catch (error) {
44115
+ console.warn("[magic-context] v2 dream scheduling failed", error);
44116
+ }
44117
+ }
44118
+ } catch (error) {
44119
+ if (!controller.signal.aborted)
44120
+ console.warn("[magic-context] v2 dream event subscription failed", error);
44121
+ }
44122
+ })();
44123
+ return {
44124
+ async dispose() {
44125
+ controller.abort();
44126
+ await done;
44127
+ }
44128
+ };
44129
+ }
44130
+
44131
+ // src/v2/hooks/payload.ts
44132
+ var HEAD_IDS = ["__magic_context_v2_m0__", "__magic_context_v2_m1__"];
44133
+ function adaptPayload(draft, admittedIDs = new Set) {
44134
+ const existingHeads = new Map(draft.messages.filter((m) => HEAD_IDS.some((id) => m.id === id)).map((m) => [m.id, m]));
44135
+ const source = draft.messages.filter((m) => !existingHeads.has(m.id));
44136
+ const results = new Map;
44137
+ for (const message of source) {
44138
+ for (const part of message.content) {
44139
+ if (part.type === "tool-result" && typeof part.id === "string") {
44140
+ const queue = results.get(part.id) ?? [];
44141
+ queue.push({ part, message });
44142
+ results.set(part.id, queue);
44143
+ }
44144
+ }
44145
+ }
44146
+ const paired = new Set;
44147
+ const bridges = new Map;
44148
+ const originals = new Map;
44149
+ const nativeTool = (call, result) => {
44150
+ const value = result?.part.result?.value;
44151
+ const output = typeof value === "string" ? value : value === undefined ? "" : JSON.stringify(value);
44152
+ const part = {
44153
+ type: "tool",
44154
+ callID: call?.id ?? result?.part.id,
44155
+ tool: call?.name ?? result?.part.name,
44156
+ state: {
44157
+ input: structuredClone(call?.input ?? {}),
44158
+ status: result ? "completed" : "running",
44159
+ ...result ? { output } : {}
44160
+ }
44161
+ };
44162
+ bridges.set(part, { call, result: result?.part, resultMessage: result?.message, output });
44163
+ if (result)
44164
+ paired.add(result.part);
44165
+ return part;
44166
+ };
44167
+ const callParts = new Map;
44168
+ for (const message of source) {
44169
+ for (const part of message.content) {
44170
+ if (part.type === "tool-call")
44171
+ callParts.set(part, nativeTool(part, results.get(String(part.id))?.shift()));
44172
+ }
44173
+ }
44174
+ const messages = [];
44175
+ for (const message of source) {
44176
+ const parts = [];
44177
+ for (const content of message.content) {
44178
+ if (paired.has(content))
44179
+ continue;
44180
+ const part = callParts.get(content) ?? (content.type === "tool-result" ? nativeTool(undefined, { part: content, message }) : structuredClone(content));
44181
+ if (message.id && admittedIDs.has(message.id))
44182
+ part.synthetic = true;
44183
+ parts.push(part);
44184
+ }
44185
+ if (!parts.length && message.content.length)
44186
+ continue;
44187
+ const mapped = {
44188
+ info: {
44189
+ id: message.id,
44190
+ sessionID: draft.sessionID,
44191
+ role: message.role,
44192
+ ...{
44193
+ providerID: draft.model.providerID,
44194
+ modelID: draft.model.id,
44195
+ agent: draft.agent,
44196
+ tools: draft.tools
44197
+ }
44198
+ },
44199
+ parts
44200
+ };
44201
+ originals.set(mapped, message);
44202
+ messages.push(mapped);
44203
+ }
44204
+ return {
44205
+ messages,
44206
+ commit() {
44207
+ let head = 0;
44208
+ const rendered = [];
44209
+ for (const message of messages) {
44210
+ const original = originals.get(message);
44211
+ const id = message.info.syntheticHead ? HEAD_IDS[head++] : original?.id;
44212
+ const content = [];
44213
+ const following = [];
44214
+ for (const candidate of message.parts) {
44215
+ const part = candidate;
44216
+ const bridge = bridges.get(part);
44217
+ if (!bridge) {
44218
+ const { synthetic: _synthetic, ...clean } = part;
44219
+ content.push(clean);
44220
+ continue;
44221
+ }
44222
+ const state = part.state;
44223
+ if (bridge.call)
44224
+ content.push({ ...bridge.call, input: state.input });
44225
+ if (bridge.result && bridge.resultMessage) {
44226
+ const result = {
44227
+ ...bridge.result,
44228
+ result: state.output === bridge.output ? bridge.result.result : { type: "text", value: state.output }
44229
+ };
44230
+ if (bridge.resultMessage === original)
44231
+ content.push(result);
44232
+ else
44233
+ following.push({ ...bridge.resultMessage, content: [result] });
44234
+ }
44235
+ }
44236
+ if (content.length || !original?.content.length) {
44237
+ const value = {
44238
+ ...original,
44239
+ id,
44240
+ role: message.info.role ?? "user",
44241
+ content
44242
+ };
44243
+ const existing = id ? existingHeads.get(id) : undefined;
44244
+ rendered.push(existing ? Object.assign(existing, { content }) : value);
44245
+ }
44246
+ rendered.push(...following);
44247
+ }
44248
+ draft.messages.splice(0, draft.messages.length, ...rendered);
44249
+ }
44250
+ };
44251
+ }
44252
+
44253
+ // src/v2/hooks/refusal.ts
44254
+ class V2ContextRefusal extends Error {
44255
+ constructor(message = "Context full — /ctx-flush or /clear to continue.", options) {
44256
+ super(message, options);
44257
+ this.name = "V2ContextRefusal";
44258
+ }
44259
+ }
44260
+ async function interruptBeforeProvider(session, sessionID) {
44261
+ let timer;
44262
+ try {
44263
+ const result = await Promise.race([
44264
+ session.interrupt({ sessionID }),
44265
+ new Promise((_, reject) => {
44266
+ timer = setTimeout(() => reject(new Error("interrupt exceeded 2000 ms")), 2000);
44267
+ })
44268
+ ]);
44269
+ if (result.interrupted !== true)
44270
+ throw new Error("interrupt arrived after the turn became idle");
44271
+ } catch (cause) {
44272
+ throw new V2ContextRefusal(undefined, { cause });
44273
+ } finally {
44274
+ clearTimeout(timer);
44275
+ }
44276
+ }
44277
+
44278
+ // src/v2/hooks/store.ts
44279
+ var isRawRow = (row) => ["user", "synthetic", "assistant", "skill", "shell", "system"].includes(row.type);
44280
+ function rawMessages(rows, history = rows) {
44281
+ const ordinals = new Map(history.filter(isRawRow).map((row, index) => [row.id, index + 1]));
44282
+ return rows.filter(isRawRow).map((row) => ({
44283
+ id: row.id,
44284
+ ordinal: ordinals.get(row.id),
44285
+ role: row.type === "assistant" ? "assistant" : "user",
44286
+ createdAt: row.data.time?.created,
44287
+ parts: row.type === "assistant" ? (row.data.content ?? []).map((part) => {
44288
+ if (part.type !== "tool")
44289
+ return { ...part };
44290
+ const state = part.state;
44291
+ const content = state.content;
44292
+ return {
44293
+ type: "tool",
44294
+ tool: part.name,
44295
+ callID: part.id,
44296
+ state: {
44297
+ ...state,
44298
+ output: content?.filter((p) => p.type === "text").map((p) => p.text).join(`
44299
+ `) ?? ""
44300
+ }
44301
+ };
44302
+ }) : [{ type: "text", text: row.data.text ?? "" }]
44303
+ }));
44304
+ }
44305
+
44306
+ // src/v2/hooks/context.ts
44307
+ function createHostSeams(context, read, liveModels) {
44308
+ return {
44309
+ hostRawMessages: read,
44310
+ hostProtectedTailBoundary: (args) => resolveOpenCodeProtectedTailBoundary({
44311
+ ...args,
44312
+ cacheNamespace: `opencode2:${args.sessionId}`
44313
+ }),
44314
+ hostModelFallback: (sessionID) => liveModels.get(sessionID) ?? null,
44315
+ hostRefuse: (_client, sessionID) => interruptBeforeProvider(context.session, sessionID)
44316
+ };
44317
+ }
44318
+ async function registerContext(context) {
44319
+ const directory = context.location.directory;
44320
+ const config = loadPluginConfigDetailed(directory).config;
44321
+ if (!config.enabled || !isCompactionEnabled(config))
44322
+ return;
44323
+ const folds = new FoldOwner(context.storage);
44324
+ const limits = new Map;
44325
+ const queriedModels = new Set;
44326
+ const liveModels = new Map;
44327
+ const hostGenerate = context.session.generate?.bind(context.session);
44328
+ const hiddenCompletionExecutor = hostGenerate ? await createV2HiddenCompletionExecutor({
44329
+ hook: (name, callback) => context.session.hook(name, callback),
44330
+ generate: (input, options) => hostGenerate(input, options)
44331
+ }, (sessionID) => liveModels.get(sessionID) ?? null) : undefined;
44332
+ const dreamTrigger = hiddenCompletionExecutor && config.dreamer && !config.dreamer.disable ? startDreamTrigger(context, {
44333
+ config: config.dreamer,
44334
+ executor: hiddenCompletionExecutor,
44335
+ projectIdentity: () => resolveProjectIdentity(directory) ?? directory,
44336
+ language: config.language,
44337
+ mural: config.mural
44338
+ }) : undefined;
44339
+ const historianModels = resolveHistorianModel2(config, "opencode");
44340
+ const usage = new Map;
44341
+ const channel1 = new Map;
44342
+ const variants = new Map;
44343
+ const agents = new Map;
44344
+ const historyRefreshSessions = new Set;
44345
+ const pendingMaterializationSessions = new Set;
44346
+ const lastHeuristicsTurnId = new Map;
44347
+ const rawProviders = new Map;
44348
+ let passDuties;
44349
+ let toolDuties;
44350
+ await context.tool.hook("execute.before", (draft) => assertExecutableToolInput(draft.input));
44351
+ await context.tool.hook("execute.after", async (draft) => {
44352
+ if (!db || draft.status !== "completed")
44353
+ return;
44354
+ try {
44355
+ toolDuties ??= createToolExecuteAfterHook({ db, channel1StateBySession: channel1 });
44356
+ const content = draft.result?.content;
44357
+ const text = typeof content === "string" ? content : Array.isArray(content) ? content.filter((part) => part.type === "text").map((part) => part.text).join(`
44358
+ `) : "";
44359
+ const output = { output: text };
44360
+ await toolDuties({ ...draft, args: draft.input }, output);
44361
+ if (draft.result && output.output !== text) {
44362
+ if (typeof content === "string")
44363
+ draft.result.content = output.output;
44364
+ else if (Array.isArray(content) && output.output.startsWith(text))
44365
+ content.push({ type: "text", text: output.output.slice(text.length) });
44366
+ }
44367
+ const baseline = channel1.get(draft.sessionID);
44368
+ await deliverPendingChannel2(context, db, draft.sessionID, baseline);
44369
+ } catch (error) {
44370
+ console.warn("[magic-context] v2 Channel 2 delivery deferred", error);
44371
+ }
44372
+ });
44373
+ const read = (sessionID) => {
44374
+ const reader = new V2StoreReader(gaDatabasePath(getDataDir(), process.env.OPENCODE_CHANNEL ?? "latest"));
44375
+ try {
44376
+ return rawMessages(reader.history(sessionID));
44377
+ } finally {
44378
+ reader.close();
44379
+ }
44380
+ };
44381
+ const pagedRead = Object.assign(read, {
44382
+ readPage: (sessionID, after, limit, watermark) => read(sessionID).filter((m) => m.ordinal > after && m.ordinal <= watermark).slice(0, limit),
44383
+ getCount: (sessionID) => read(sessionID).length
44384
+ });
44385
+ let transform;
44386
+ let db;
44387
+ const refuseIfUnsafe = async (draft) => {
44388
+ let unsafe = false;
44389
+ try {
44390
+ db ??= openDatabase();
44391
+ if (!db || !isDatabasePersisted(db))
44392
+ throw new Error("context storage is not durable");
44393
+ getOrCreateSessionMeta2(db, draft.sessionID);
44394
+ const reader = new V2StoreReader(gaDatabasePath(getDataDir(), process.env.OPENCODE_CHANNEL ?? "latest"));
44395
+ try {
44396
+ const latest = reader.history(draft.sessionID).filter((row) => row.type === "assistant").at(-1);
44397
+ const tokens = latest?.data.tokens;
44398
+ const modelKey = `${draft.model.providerID}/${draft.model.id}`;
44399
+ if (!queriedModels.has(modelKey)) {
44400
+ const catalog = await context.catalog.model.list({
44401
+ location: context.location
44402
+ });
44403
+ for (const model of catalog.data)
44404
+ limits.set(`${model.providerID}/${model.id}`, model.limit.context);
44405
+ queriedModels.add(modelKey);
44406
+ }
44407
+ const limit = limits.get(modelKey);
44408
+ if (tokens && limit && Number.isFinite(limit) && limit > 0) {
44409
+ const inputTokens = tokens.input + tokens.cache.read + tokens.cache.write;
44410
+ unsafe = inputTokens / limit >= 0.95;
44411
+ const completed = latest?.data.time?.completed;
44412
+ if (typeof completed === "number")
44413
+ updateSessionMeta2(db, draft.sessionID, { lastResponseTime: completed });
44414
+ usage.set(draft.sessionID, {
44415
+ usage: { inputTokens, percentage: inputTokens / limit * 100 },
44416
+ hasUsageTokens: true,
44417
+ updatedAt: Date.now()
44418
+ });
44419
+ }
44420
+ } finally {
44421
+ reader.close();
44422
+ }
44423
+ } catch {
44424
+ unsafe = true;
44425
+ }
44426
+ if (unsafe)
44427
+ await interruptBeforeProvider(context.session, draft.sessionID);
44428
+ return unsafe;
44429
+ };
44430
+ const materialize = (draft) => {
44431
+ db ??= openDatabase();
44432
+ if (!db || !isDatabasePersisted(db))
44433
+ throw new Error("context storage is not durable");
44434
+ const state = getOrCreateSessionMeta2(db, draft.sessionID);
44435
+ return materializeM0({
44436
+ db,
44437
+ sessionId: draft.sessionID,
44438
+ state,
44439
+ projectPath: resolveProjectIdentity(directory) ?? directory,
44440
+ projectDirectory: directory,
44441
+ memoryEnabled: config.memory.enabled,
44442
+ memoryInjectionBudgetTokens: config.memory.injection_budget_tokens,
44443
+ hardSignals: {
44444
+ systemHash: foldDigest(JSON.stringify(draft.system)),
44445
+ toolSetHash: "",
44446
+ modelKey: `${draft.model.providerID}/${draft.model.id}`,
44447
+ cacheExpired: false,
44448
+ lastResponseTime: state.lastResponseTime
44449
+ }
44450
+ }).m0Text;
44451
+ };
44452
+ await context.session.hook("compaction", async (draft) => {
44453
+ const reader = new V2StoreReader(gaDatabasePath(getDataDir(), process.env.OPENCODE_CHANNEL ?? "latest"));
44454
+ try {
44455
+ const rows = reader.history(draft.sessionID);
44456
+ const ids = new Set(draft.messages.map((message) => message.id));
44457
+ const watermark = Math.max(-1, ...rows.filter((row) => ids.has(row.id)).map((row) => row.seq));
44458
+ const running = rows.filter((row) => row.type === "compaction" && row.data.status === "running").at(-1);
44459
+ const fold = await folds.supply({
44460
+ sessionID: draft.sessionID,
44461
+ watermark,
44462
+ runningCut: running?.seq,
44463
+ materialize: () => materialize(draft)
44464
+ });
44465
+ draft.result = { summary: fold.submitted };
44466
+ } catch (cause) {
44467
+ await interruptBeforeProvider(context.session, draft.sessionID);
44468
+ throw new V2ContextRefusal("Magic Context could not preserve the host checkpoint.", {
44469
+ cause
44470
+ });
44471
+ } finally {
44472
+ reader.close();
44473
+ }
44474
+ });
44475
+ await context.session.hook("context", async (draft) => {
44476
+ let postFold = false;
44477
+ try {
44478
+ if (await refuseIfUnsafe(draft))
44479
+ return;
44480
+ if (!db)
44481
+ return;
44482
+ const storage = db;
44483
+ updateSessionMeta2(db, draft.sessionID, {
44484
+ systemPromptHash: foldDigest(JSON.stringify(draft.system))
44485
+ });
44486
+ await preloadTokenizer();
44487
+ passDuties ??= createChatMessageHook({
44488
+ db,
44489
+ liveModelBySession: liveModels,
44490
+ variantBySession: variants,
44491
+ agentBySession: agents,
44492
+ historyRefreshSessions,
44493
+ pendingMaterializationSessions,
44494
+ lastHeuristicsTurnId,
44495
+ systemPromptRefreshSessions: new Set,
44496
+ cacheTtlConfig: config.cache_ttl,
44497
+ upgradeReminder: (sessionID) => maybeSendUpgradeReminder({
44498
+ db: storage,
44499
+ client: undefined,
44500
+ getNotificationParams: () => ({}),
44501
+ sendStatusNotification: async (_client, id, text) => {
44502
+ pushNotification2("toast", { message: text, variant: "info" }, id);
44503
+ return "queued";
44504
+ }
44505
+ }, sessionID)
44506
+ });
44507
+ await passDuties({
44508
+ sessionID: draft.sessionID,
44509
+ agent: draft.agent,
44510
+ variant: draft.model.variant,
44511
+ model: { providerID: draft.model.providerID, modelID: draft.model.id }
44512
+ });
44513
+ if (!rawProviders.has(draft.sessionID))
44514
+ rawProviders.set(draft.sessionID, setRawMessageProvider(draft.sessionID, {
44515
+ readMessages: () => read(draft.sessionID)
44516
+ }));
44517
+ transform ??= createTransform({
44518
+ db,
44519
+ tagger: createTagger(),
44520
+ scheduler: createScheduler({
44521
+ executeThresholdPercentage: config.execute_threshold_percentage
44522
+ }),
44523
+ contextUsageMap: usage,
44524
+ protectedTokens: config.protected_tokens,
44525
+ protectedTokenTierOverrides: getProtectedTokensTierOverrides(config),
44526
+ executeThresholdPercentage: config.execute_threshold_percentage,
44527
+ liveModelBySession: liveModels,
44528
+ channel1StateBySession: channel1,
44529
+ historyRefreshSessions,
44530
+ pendingMaterializationSessions,
44531
+ lastHeuristicsTurnId,
44532
+ variantBySession: variants,
44533
+ clearReasoningAge: config.clear_reasoning_age,
44534
+ directory,
44535
+ projectPath: directory,
44536
+ hiddenCompletionExecutor,
44537
+ historianRunnable: hiddenCompletionExecutor !== undefined && config.historian?.disable !== true,
44538
+ historianModel: historianModels.primary,
44539
+ fallbackModels: historianModels.fallbacks,
44540
+ historianTimeoutMs: config.historian_timeout_ms,
44541
+ historianMaxOutputTokens: config.historian?.maxTokens,
44542
+ historianTwoPass: config.historian?.two_pass,
44543
+ compactionMarkerStrategy: v2CompactionMarkerStrategy,
44544
+ memoryConfig: {
44545
+ enabled: config.memory.enabled,
44546
+ injectionBudgetTokens: config.memory.injection_budget_tokens,
44547
+ autoPromote: config.memory.auto_promote
44548
+ },
44549
+ ...createHostSeams(context, pagedRead, liveModels)
44550
+ });
44551
+ const admitted = new Set;
44552
+ for (const message of draft.messages) {
44553
+ if (message.id && await isAdmittedSynthetic(context, draft.sessionID, message.id))
44554
+ admitted.add(message.id);
44555
+ }
44556
+ const reader = new V2StoreReader(gaDatabasePath(getDataDir(), process.env.OPENCODE_CHANNEL ?? "latest"));
44557
+ let checkpoint;
44558
+ let submitted;
44559
+ try {
44560
+ const cut = reader.latestCompaction(draft.sessionID);
44561
+ const incoming = cut && draft.messages.find((message) => message.id === cut.id);
44562
+ postFold = cut !== undefined;
44563
+ if (cut && !incoming)
44564
+ throw new Error("The host checkpoint disappeared from the context draft");
44565
+ if (cut && incoming) {
44566
+ const identity = await folds.observe({
44567
+ sessionID: draft.sessionID,
44568
+ cutSeq: cut.seq,
44569
+ summary: cut.data.summary ?? "",
44570
+ rendered: incoming,
44571
+ onHard: (reason) => {
44572
+ console.warn(`[magic-context] HARD reason=${reason} session=${draft.sessionID}`);
44573
+ materialize(draft);
44574
+ pendingMaterializationSessions.add(draft.sessionID);
44575
+ }
44576
+ });
44577
+ checkpoint = structuredClone(identity.rendered ?? incoming);
44578
+ submitted = identity.rendered ? identity.renderedSummary ?? identity.submitted : cut.data.summary ?? "";
44579
+ const all = reader.history(draft.sessionID);
44580
+ const boundaryID = db.prepare("SELECT cached_m0_last_baseline_end_message_id AS id FROM session_meta WHERE session_id = ?").get(draft.sessionID)?.id;
44581
+ const boundary = all.find((row) => row.id === boundaryID)?.seq ?? -1;
44582
+ const present = new Set(draft.messages.map((message) => message.id));
44583
+ const restored = all.filter((row) => row.seq > boundary && row.seq <= cut.seq && !present.has(row.id)).flatMap((row) => restoreRow(row, draft.model));
44584
+ draft.messages.splice(0, draft.messages.length, ...restored, ...draft.messages.filter((message) => message !== incoming));
44585
+ }
44586
+ } finally {
44587
+ reader.close();
44588
+ }
44589
+ const mapped = adaptPayload(draft, admitted);
44590
+ await transform({}, mapped);
44591
+ mapped.commit();
44592
+ if (checkpoint && submitted !== undefined) {
44593
+ const head = draft.messages.find((message) => message.id === HEAD_IDS[0]);
44594
+ const baseline = head?.content.find((part) => part.type === "text")?.text;
44595
+ if (typeof baseline === "string") {
44596
+ for (const part of checkpoint.content)
44597
+ if (part.type === "text" && typeof part.text === "string") {
44598
+ part.text = part.text.replace(`<summary>
44599
+ ${submitted}
44600
+ </summary>`, `<summary>
44601
+ ${baseline}
44602
+ </summary>`);
44603
+ }
44604
+ const volatile = draft.messages.find((message) => message.id === HEAD_IDS[1]);
44605
+ if (volatile && head)
44606
+ volatile.content.push(...head.content.filter((part) => part.type !== "text"));
44607
+ draft.messages.splice(0, draft.messages.length, checkpoint, ...draft.messages.filter((message) => message !== head));
44608
+ }
44609
+ }
44610
+ } catch (error) {
44611
+ if (error instanceof V2ContextRefusal)
44612
+ throw error;
44613
+ if (postFold) {
44614
+ await interruptBeforeProvider(context.session, draft.sessionID);
44615
+ throw new V2ContextRefusal("Magic Context could not restore the unarchived host history.", { cause: error });
44616
+ }
44617
+ console.warn("[magic-context] v2 context unavailable", error);
44618
+ }
44619
+ });
44620
+ return {
44621
+ async dispose() {
44622
+ await dreamTrigger?.dispose();
44623
+ for (const release of rawProviders.values())
44624
+ release();
44625
+ rawProviders.clear();
44626
+ }
44627
+ };
44628
+ }
44629
+
44630
+ // src/v2/hooks/update-check.ts
44631
+ import { existsSync as existsSync13, readFileSync as readFileSync7 } from "node:fs";
44632
+ import { dirname as dirname8, join as join12 } from "node:path";
44633
+ import { fileURLToPath as fileURLToPath3 } from "node:url";
44634
+ function packageInfo() {
44635
+ let directory = dirname8(fileURLToPath3(import.meta.url));
44636
+ for (;; ) {
44637
+ try {
44638
+ const pkg = JSON.parse(readFileSync7(join12(directory, "package.json"), "utf8"));
44639
+ if (pkg.name === "@cortexkit/opencode-magic-context" && typeof pkg.version === "string") {
44640
+ return {
44641
+ version: pkg.version,
44642
+ development: existsSync13(join12(directory, "src/v2/server.ts"))
44643
+ };
44644
+ }
44645
+ } catch {}
44646
+ const parent = dirname8(directory);
44647
+ if (parent === directory)
44648
+ throw new Error("Magic Context package manifest is unavailable");
44649
+ directory = parent;
44650
+ }
44651
+ }
44652
+ function startUpdateChecks(context, check = (signal) => {
44653
+ return packageInfo().development ? Promise.resolve(null) : getLatestVersion("latest", { signal });
44654
+ }) {
44655
+ const controller = new AbortController;
44656
+ const done = (async () => {
44657
+ try {
44658
+ for await (const _event of context.event.subscribe({ signal: controller.signal })) {
44659
+ if (controller.signal.aborted)
44660
+ break;
44661
+ const last = await context.storage.get("version-check-at");
44662
+ if (typeof last === "number" && Date.now() - last < 60 * 60 * 1000)
44663
+ continue;
44664
+ await context.storage.set("version-check-at", Date.now());
44665
+ const latest = await check(controller.signal);
44666
+ const comparison = latest ? compareSemverCore(latest, packageInfo().version) : null;
44667
+ if (!controller.signal.aborted && comparison !== null && comparison > 0) {
44668
+ pushNotification2("toast", {
44669
+ message: `Magic Context ${latest} is available. Update the plugin to install it.`,
44670
+ variant: "info"
44671
+ });
44672
+ }
44673
+ }
44674
+ } catch (error) {
44675
+ if (!controller.signal.aborted)
44676
+ console.warn("[magic-context] v2 update check unavailable", error);
44677
+ }
44678
+ })();
44679
+ return {
44680
+ done,
44681
+ async dispose() {
44682
+ controller.abort();
44683
+ await done;
44684
+ }
44685
+ };
44686
+ }
44687
+
44688
+ // src/v2/server.ts
44689
+ async function setup(context) {
44690
+ setHarness("opencode2");
44691
+ const duties = await registerContext(context);
44692
+ const checks = loadPluginConfigDetailed(context.location.directory).config.auto_update === false ? undefined : startUpdateChecks(context);
44693
+ console.info("[magic-context] @cortexkit/opencode-magic-context v2 setup");
44694
+ return async () => {
44695
+ await checks?.dispose();
44696
+ await duties?.dispose();
44697
+ };
44698
+ }
44699
+
43386
44700
  // src/index.ts
43387
44701
  var BOOT_SERVER_DEADLINE_MS = 15000;
43388
44702
  var RESOLVED_CONFIG_TIMEOUT_MS = 2000;
@@ -43435,7 +44749,7 @@ var server = async (ctx) => {
43435
44749
  if (hasBannerEntries)
43436
44750
  setTimeout(async () => {
43437
44751
  try {
43438
- const { sendStatusNotification } = await import("./send-session-notification-1qeqkswb.js");
44752
+ const { sendStatusNotification } = await import("./send-session-notification-xnypkxpx.js");
43439
44753
  const clientWithSessions = ctx.client;
43440
44754
  const sessions = await Promise.resolve(clientWithSessions.session?.list?.()).catch(() => null);
43441
44755
  const sessionList = Array.isArray(sessions) ? sessions : sessions?.data;
@@ -43452,7 +44766,7 @@ var server = async (ctx) => {
43452
44766
  log(`[magic-context] opencode_db_missing path=${openCodeDbResolution.path} source=${openCodeDbResolution.source}`);
43453
44767
  setTimeout(async () => {
43454
44768
  try {
43455
- const { sendStatusNotification } = await import("./send-session-notification-1qeqkswb.js");
44769
+ const { sendStatusNotification } = await import("./send-session-notification-xnypkxpx.js");
43456
44770
  const clientWithSessions = ctx.client;
43457
44771
  const sessions = await Promise.resolve(clientWithSessions.session?.list?.()).catch(() => null);
43458
44772
  const sessionList = Array.isArray(sessions) ? sessions : sessions?.data;
@@ -43484,9 +44798,9 @@ var server = async (ctx) => {
43484
44798
  }
43485
44799
  conflictMs = performance.now() - conflictStartedAt;
43486
44800
  const liveSessionState = createLiveSessionState();
43487
- const rustModeModuleTransport = pluginConfig.transform_mode === "rust" ? new SubcModuleTransport(pluginConfig.subc?.connection_file) : undefined;
44801
+ const rustModeModuleTransport = pluginConfig.transform_mode === "rust" ? new SubcModuleTransport(pluginConfig.subc?.connection_file ?? getDefaultSubcConnectionFile()) : undefined;
43488
44802
  const rustModeModuleClient = rustModeModuleTransport;
43489
- const sessionCleanupModuleClient = pluginConfig.enabled ? rustModeModuleTransport ?? new SubcModuleTransport(pluginConfig.subc?.connection_file) : undefined;
44803
+ const sessionCleanupModuleClient = pluginConfig.enabled ? rustModeModuleTransport ?? new SubcModuleTransport(pluginConfig.subc?.connection_file ?? getDefaultSubcConnectionFile()) : undefined;
43490
44804
  const hooksPhase = await runBootPhaseWithinBudget(bootBudget, "hooks", () => createSessionHooksAsync({
43491
44805
  ctx,
43492
44806
  pluginConfig,
@@ -43698,12 +45012,12 @@ var server = async (ctx) => {
43698
45012
  {
43699
45013
  const fence = getSchemaFenceRejection();
43700
45014
  if (fence) {
43701
- import("./conflict-warning-hook-6p3xqeac.js").then(({ sendSchemaFenceWarning }) => sendSchemaFenceWarning(ctx.client, ctx.directory, fence));
45015
+ import("./conflict-warning-hook-jyj54gbe.js").then(({ sendSchemaFenceWarning }) => sendSchemaFenceWarning(ctx.client, ctx.directory, fence));
43702
45016
  }
43703
45017
  }
43704
45018
  const serverUrl = ctx.serverUrl;
43705
45019
  const serverUrlStr = serverUrl instanceof URL ? serverUrl.toString().replace(/\/$/, "") : typeof serverUrl === "string" ? serverUrl.replace(/\/$/, "") : undefined;
43706
- import("./send-session-notification-1qeqkswb.js").then(({ setNotificationServerUrl }) => {
45020
+ import("./send-session-notification-xnypkxpx.js").then(({ setNotificationServerUrl }) => {
43707
45021
  setNotificationServerUrl(serverUrlStr);
43708
45022
  });
43709
45023
  if (conflictResult?.hasConflict) {
@@ -43717,7 +45031,7 @@ var server = async (ctx) => {
43717
45031
  }
43718
45032
  if (pluginConfig.enabled && !conflictResult?.hasConflict) {
43719
45033
  setTimeout(() => {
43720
- import("./announcement-3c1vertn.js").then(({
45034
+ import("./announcement-8mgn61fw.js").then(({
43721
45035
  shouldShowAnnouncement,
43722
45036
  ANNOUNCEMENT_VERSION,
43723
45037
  ANNOUNCEMENT_FEATURES,
@@ -43726,7 +45040,7 @@ var server = async (ctx) => {
43726
45040
  }) => {
43727
45041
  if (!shouldShowAnnouncement())
43728
45042
  return;
43729
- return import("./conflict-warning-hook-6p3xqeac.js").then(({ sendStartupAnnouncement }) => sendStartupAnnouncement(ctx.client, ctx.directory, ANNOUNCEMENT_VERSION, ANNOUNCEMENT_FEATURES, ANNOUNCEMENT_FOOTER, markAnnouncementSeen));
45043
+ return import("./conflict-warning-hook-jyj54gbe.js").then(({ sendStartupAnnouncement }) => sendStartupAnnouncement(ctx.client, ctx.directory, ANNOUNCEMENT_VERSION, ANNOUNCEMENT_FEATURES, ANNOUNCEMENT_FOOTER, markAnnouncementSeen));
43730
45044
  }).catch(() => {});
43731
45045
  }, 8000);
43732
45046
  }
@@ -43882,7 +45196,8 @@ var server = async (ctx) => {
43882
45196
  };
43883
45197
  var plugin = {
43884
45198
  id: "opencode-magic-context",
43885
- server
45199
+ server,
45200
+ setup
43886
45201
  };
43887
45202
  var src_default = plugin;
43888
45203
  export {