@cortexkit/opencode-magic-context 0.49.28 → 0.49.30

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 (128) hide show
  1. package/dist/auto-search-worker.js +3 -3
  2. package/dist/chunk-embedding-write-worker.js +1 -1
  3. package/dist/config/commit-retention-recovery.d.ts +9 -0
  4. package/dist/config/commit-retention-recovery.d.ts.map +1 -0
  5. package/dist/config/index.d.ts +2 -1
  6. package/dist/config/index.d.ts.map +1 -1
  7. package/dist/config/live-child-output-cap.d.ts.map +1 -1
  8. package/dist/config/live-run-config.d.ts.map +1 -1
  9. package/dist/config/project-security.d.ts +1 -0
  10. package/dist/config/project-security.d.ts.map +1 -1
  11. package/dist/{conflict-warning-hook-tgnw019g.js → conflict-warning-hook-xgskea1v.js} +3 -3
  12. package/dist/{context-dxfztzsd.js → context-vnfr6d7t.js} +210 -50
  13. package/dist/{embedding-backfill-cwnyr4fj.js → embedding-backfill-mms9nb0h.js} +2 -2
  14. package/dist/features/magic-context/dreamer/evaluate-smart-notes.d.ts.map +1 -1
  15. package/dist/features/magic-context/dreamer/hidden-single-shot.d.ts.map +1 -1
  16. package/dist/features/magic-context/dreamer/map-memories.d.ts.map +1 -1
  17. package/dist/features/magic-context/dreamer/task-executor.d.ts.map +1 -1
  18. package/dist/features/magic-context/dreamer/verify-diff.d.ts.map +1 -1
  19. package/dist/features/magic-context/dreamer/verify.d.ts.map +1 -1
  20. package/dist/features/magic-context/git-commits/indexer.d.ts +2 -0
  21. package/dist/features/magic-context/git-commits/indexer.d.ts.map +1 -1
  22. package/dist/features/magic-context/project-embedding-registry.d.ts +3 -1
  23. package/dist/features/magic-context/project-embedding-registry.d.ts.map +1 -1
  24. package/dist/features/magic-context/smart-notes/compiler.d.ts.map +1 -1
  25. package/dist/features/magic-context/work-metrics.d.ts +5 -3
  26. package/dist/features/magic-context/work-metrics.d.ts.map +1 -1
  27. package/dist/hooks/magic-context/apply-operations.d.ts +2 -0
  28. package/dist/hooks/magic-context/apply-operations.d.ts.map +1 -1
  29. package/dist/hooks/magic-context/compartment-runner-types.d.ts +5 -1
  30. package/dist/hooks/magic-context/compartment-runner-types.d.ts.map +1 -1
  31. package/dist/hooks/magic-context/history-boundary-repair.d.ts +1 -1
  32. package/dist/hooks/magic-context/history-boundary-repair.d.ts.map +1 -1
  33. package/dist/hooks/magic-context/lkg-recovery-prefix.d.ts +3 -1
  34. package/dist/hooks/magic-context/lkg-recovery-prefix.d.ts.map +1 -1
  35. package/dist/hooks/magic-context/lkg-replay.d.ts.map +1 -1
  36. package/dist/hooks/magic-context/lkg-slot.d.ts +7 -0
  37. package/dist/hooks/magic-context/lkg-slot.d.ts.map +1 -1
  38. package/dist/hooks/magic-context/read-session-chunk.d.ts.map +1 -1
  39. package/dist/hooks/magic-context/read-session-db.d.ts +3 -2
  40. package/dist/hooks/magic-context/read-session-db.d.ts.map +1 -1
  41. package/dist/hooks/magic-context/replay-committed-drops.d.ts.map +1 -1
  42. package/dist/hooks/magic-context/strip-content.d.ts +1 -1
  43. package/dist/hooks/magic-context/strip-content.d.ts.map +1 -1
  44. package/dist/hooks/magic-context/transform.d.ts.map +1 -1
  45. package/dist/{index-yzjhx10y.js → index-0fe4q77z.js} +12 -6
  46. package/dist/{index-89k1w6x2.js → index-3jmx3fae.js} +2 -2
  47. package/dist/{index-7gbcg8xv.js → index-4s4zq97n.js} +1 -1
  48. package/dist/{index-31y1mznz.js → index-69gd2scx.js} +4 -4
  49. package/dist/{index-n8qmmd7f.js → index-adr4vfys.js} +3 -3
  50. package/dist/{index-k9jx7ma9.js → index-ekzzw66a.js} +328 -249
  51. package/dist/{index-tvzvjggy.js → index-gkee6p4g.js} +1 -1
  52. package/dist/{index-a2fz9hpa.js → index-gxkhzmjq.js} +4 -2
  53. package/dist/{index-4cpc59jv.js → index-hbt0sbv2.js} +1 -1
  54. package/dist/{index-dcqk0y27.js → index-k0dpkyn7.js} +139 -28
  55. package/dist/{index-t3rbb8wr.js → index-pe6b4bhs.js} +1 -1
  56. package/dist/{index-4ypqzvhf.js → index-vnn5405n.js} +1 -1
  57. package/dist/{index-dzfevacx.js → index-vtz789ex.js} +10 -6
  58. package/dist/{index-fq2p158w.js → index-vzz570j8.js} +13 -7
  59. package/dist/{index-077ht5cq.js → index-waktfbjy.js} +1 -1
  60. package/dist/{index-v0dhhxsq.js → index-y1qwzvxn.js} +5 -5
  61. package/dist/index.d.ts.map +1 -1
  62. package/dist/index.js +26 -30
  63. package/dist/{message-index-bounded-7ayzb2ah.js → message-index-bounded-zq7a5nm6.js} +3 -3
  64. package/dist/migration-worker.js +1 -1
  65. package/dist/plugin/dream-timer.d.ts.map +1 -1
  66. package/dist/plugin/embedding-bootstrap-helpers.d.ts +5 -1
  67. package/dist/plugin/embedding-bootstrap-helpers.d.ts.map +1 -1
  68. package/dist/plugin/hooks/create-session-hooks.d.ts.map +1 -1
  69. package/dist/plugin/rpc-handlers.d.ts.map +1 -1
  70. package/dist/{project-embedding-registry-94nncs5g.js → project-embedding-registry-cg281d9j.js} +1 -1
  71. package/dist/raw-ordinal-warmup-worker.js +2 -2
  72. package/dist/{read-session-chunk-jzb6w9w5.js → read-session-chunk-1ndphmb8.js} +2 -2
  73. package/dist/{recomp-orchestrator-02sa2ngr.js → recomp-orchestrator-w3pjp33d.js} +10 -10
  74. package/dist/{search-archive-q1vw7zg4.js → search-archive-sr07c6aj.js} +3 -3
  75. package/dist/{search-spq6nfyf.js → search-fbaz1m8r.js} +7 -7
  76. package/dist/{send-session-notification-afzzqy5b.js → send-session-notification-vz86nt79.js} +2 -2
  77. package/dist/shared/marker-only-text.d.ts +2 -0
  78. package/dist/shared/marker-only-text.d.ts.map +1 -0
  79. package/dist/{transform-postprocess-phase-6menyyxc.js → transform-postprocess-phase-6ccazq85.js} +10 -10
  80. package/dist/v2/auto-search-worker.js +3 -3
  81. package/dist/v2/chunk-embedding-write-worker.js +1 -1
  82. package/dist/v2/{context-0qhz1nnj.js → context-wx4sfhgr.js} +345 -102
  83. package/dist/v2/{embedding-backfill-rh5dgsva.js → embedding-backfill-35k6czrr.js} +2 -2
  84. package/dist/v2/hidden-child-cleanup.d.ts.map +1 -1
  85. package/dist/v2/hidden-child-native.d.ts.map +1 -1
  86. package/dist/v2/hidden-completion.d.ts.map +1 -1
  87. package/dist/v2/hooks/context.d.ts.map +1 -1
  88. package/dist/v2/hooks/dream-timer.d.ts.map +1 -1
  89. package/dist/v2/hooks/store.d.ts.map +1 -1
  90. package/dist/v2/{message-index-bounded-n09b74vr.js → message-index-bounded-jvgz7vk9.js} +3 -3
  91. package/dist/v2/message-times.d.ts +17 -0
  92. package/dist/v2/message-times.d.ts.map +1 -0
  93. package/dist/v2/migration-worker.js +1 -1
  94. package/dist/v2/{project-embedding-registry-6pak822h.js → project-embedding-registry-p1p10ks7.js} +1 -1
  95. package/dist/v2/raw-ordinal-warmup-worker.js +2 -2
  96. package/dist/v2/{read-session-chunk-vpt69tw9.js → read-session-chunk-djzgm4jg.js} +2 -2
  97. package/dist/v2/{recomp-orchestrator-txsmbnvw.js → recomp-orchestrator-wb28kr9k.js} +10 -10
  98. package/dist/v2/{search-archive-t9bcz4ht.js → search-archive-n3dhns4r.js} +3 -3
  99. package/dist/v2/{search-dcy9b6gd.js → search-q3jjw6zp.js} +7 -7
  100. package/dist/v2/{send-session-notification-vdsgnf4c.js → send-session-notification-x5nzy34v.js} +2 -2
  101. package/dist/v2/{server-txbc3czn.js → server-42nebt63.js} +10 -6
  102. package/dist/v2/{server-94wk1ey3.js → server-835q39kd.js} +45 -5
  103. package/dist/v2/{server-3vhxy2k5.js → server-a7x00tw8.js} +5 -5
  104. package/dist/v2/{server-e3hc93wk.js → server-d01pe8q5.js} +1 -1
  105. package/dist/v2/{server-z2n2xaeh.js → server-hwag0khr.js} +1 -1
  106. package/dist/v2/{server-jj9qye8y.js → server-k33t88h3.js} +97 -25
  107. package/dist/v2/{server-6avtp9jp.js → server-p0snacz3.js} +1 -1
  108. package/dist/v2/{server-z3mk9jdc.js → server-ph300d6m.js} +1 -1
  109. package/dist/v2/{server-6v3cdzsx.js → server-qc915kw2.js} +1 -1
  110. package/dist/v2/{server-xkvxss5g.js → server-rb8m4vry.js} +12 -6
  111. package/dist/v2/{server-zmcrvpm3.js → server-rr4cbkr0.js} +2 -2
  112. package/dist/v2/{server-yqek3s4k.js → server-zh3esb0z.js} +4 -2
  113. package/dist/v2/server.js +3 -3
  114. package/dist/v2/store-reader.d.ts +14 -2
  115. package/dist/v2/store-reader.d.ts.map +1 -1
  116. package/dist/v2/{wrapup-orchestrator-gjkszser.js → wrapup-orchestrator-2t0pdqzm.js} +10 -10
  117. package/dist/{wrapup-orchestrator-n5h5sr1x.js → wrapup-orchestrator-kjmkms5g.js} +11 -11
  118. package/package.json +1 -1
  119. package/src/config/commit-retention-recovery.ts +34 -0
  120. package/src/config/index.ts +22 -2
  121. package/src/config/live-child-output-cap.test.ts +28 -0
  122. package/src/config/live-child-output-cap.ts +2 -0
  123. package/src/config/live-run-config.test.ts +44 -1
  124. package/src/config/live-run-config.ts +8 -1
  125. package/src/config/project-config-trust-boundary.test.ts +57 -0
  126. package/src/config/project-security.ts +6 -2
  127. package/src/shared/marker-only-text.ts +8 -0
  128. package/src/shared/windows-hidden-spawns.test.ts +133 -23
@@ -1,12 +1,13 @@
1
1
  import {
2
2
  getMagicContextBuiltinCommands,
3
3
  readJsoncFile,
4
+ isCommitRetentionPaused,
4
5
  cortexKitUserConfigBasePath,
5
6
  cortexKitProjectConfigBasePath,
6
7
  resolveLegacyConfigSources,
7
8
  getProtectedTokensTierOverrides,
8
9
  loadPluginConfigDetailed
9
- } from "./server-94wk1ey3.js";
10
+ } from "./server-835q39kd.js";
10
11
  import {
11
12
  getHarness2,
12
13
  harnessOwnsOpenCodeStore2
@@ -76,7 +77,6 @@ import {
76
77
  isCompartmentLeaseHeld,
77
78
  queueM0Mutation,
78
79
  getMaxM0MutationId,
79
- getCompartments,
80
80
  getLastCompartmentEndMessage,
81
81
  getLastCompartmentEndMessageId,
82
82
  getUncoveredCompartmentEndsThrough,
@@ -149,6 +149,7 @@ import {
149
149
  noteLkgHealthyPrefix,
150
150
  lkgRecoveryReplayUnproven,
151
151
  lkgRecoveryEntryUnproven,
152
+ lkgInputIdentity,
152
153
  beginLkgPass,
153
154
  visitMessageContentFields,
154
155
  contentSnapshotValue,
@@ -230,6 +231,7 @@ import {
230
231
  normalizeSDKResponse,
231
232
  annotateSubagentInvocationError,
232
233
  failedInvocationStatus,
234
+ emptyTokenTotals,
233
235
  sumTokensFromChildMessages,
234
236
  recordChildInvocation,
235
237
  createPromptAsyncTransport,
@@ -302,7 +304,7 @@ import {
302
304
  startCompartmentAgent,
303
305
  setRecompStarting2,
304
306
  setRecompTerminal2
305
- } from "./server-jj9qye8y.js";
307
+ } from "./server-k33t88h3.js";
306
308
  import {
307
309
  resolveHistorianModel2
308
310
  } from "./server-5kym00ag.js";
@@ -327,7 +329,7 @@ import {
327
329
  openDatabaseAsync,
328
330
  isDatabasePersisted,
329
331
  getDatabasePersistenceError
330
- } from "./server-e3hc93wk.js";
332
+ } from "./server-d01pe8q5.js";
331
333
  import {
332
334
  pruneMissingProjectIdentities,
333
335
  setHomeProjectPermission,
@@ -479,6 +481,7 @@ import {
479
481
  } from "./server-3mz2qh5a.js";
480
482
  import {
481
483
  stableStringify,
484
+ getTableColumnNames,
482
485
  getTemporalDecisions,
483
486
  observeTemporalDecisions,
484
487
  freezeTemporalDecisions,
@@ -500,7 +503,7 @@ import {
500
503
  latestRealUserTurnIdFromOpenCodeDb,
501
504
  getMessageTimesFromOpenCodeDb,
502
505
  findLastAssistantModelFromOpenCodeDb
503
- } from "./server-3vhxy2k5.js";
506
+ } from "./server-a7x00tw8.js";
504
507
  import {
505
508
  expandToolPart,
506
509
  askAnswerLines,
@@ -699,7 +702,7 @@ import {
699
702
  readRawSessionMessageById2,
700
703
  readSessionChunk2,
701
704
  readRawSessionSeedTail2
702
- } from "./server-xkvxss5g.js";
705
+ } from "./server-rb8m4vry.js";
703
706
  import {
704
707
  BoundedSessionMap,
705
708
  recordToolDefinitionSet,
@@ -714,7 +717,7 @@ import {
714
717
  isMessageIndexReconciledThrough,
715
718
  clearIndexedMessages,
716
719
  indexMessagesAfterOrdinal
717
- } from "./server-z2n2xaeh.js";
720
+ } from "./server-hwag0khr.js";
718
721
  import"./server-awr8qa4c.js";
719
722
  import {
720
723
  embedPauseBySession,
@@ -745,7 +748,7 @@ import {
745
748
  embedSessionCompartmentChunks2,
746
749
  getEmbeddingCoverageStatus2,
747
750
  getAutoEmbeddingSessionCoverage2
748
- } from "./server-yqek3s4k.js";
751
+ } from "./server-zh3esb0z.js";
749
752
  import {
750
753
  SubcClient,
751
754
  connectionFileExists,
@@ -822,7 +825,7 @@ import {
822
825
  readGitFileChangeTimesSince,
823
826
  verificationFileExists,
824
827
  normalizeVerificationFiles
825
- } from "./server-z3mk9jdc.js";
828
+ } from "./server-ph300d6m.js";
826
829
  import {
827
830
  deriveTriggerBudget2,
828
831
  deriveHistorianChunkTokens2,
@@ -856,7 +859,7 @@ import {
856
859
  } from "./server-vr4szghm.js";
857
860
  import {
858
861
  cosineSimilarity
859
- } from "./server-6avtp9jp.js";
862
+ } from "./server-p0snacz3.js";
860
863
  import {
861
864
  computeCueContentHash,
862
865
  hasMuralCueColumns,
@@ -893,7 +896,7 @@ import"./server-1bw1wcbp.js";
893
896
  import {
894
897
  flushIgnoredMessages2,
895
898
  sendStatusNotification2
896
- } from "./server-6v3cdzsx.js";
899
+ } from "./server-qc915kw2.js";
897
900
  import {
898
901
  renderSingleStoreMigrationRequiredRefusal,
899
902
  SingleStoreMigrationRequiredError,
@@ -913,14 +916,14 @@ import {
913
916
  resolveMemoriesByIdsForSearch2,
914
917
  unifiedSearch2,
915
918
  formatSearchResults2
916
- } from "./server-txbc3czn.js";
919
+ } from "./server-42nebt63.js";
917
920
  import {
918
921
  resolvePromptContext2
919
922
  } from "./server-fmsr7v69.js";
920
923
  import"./server-kaqs6h31.js";
921
924
  import {
922
925
  renderSearchArchiveOffThread2
923
- } from "./server-zmcrvpm3.js";
926
+ } from "./server-rr4cbkr0.js";
924
927
  import {
925
928
  compareSemverCore
926
929
  } from "./server-84w6rvvf.js";
@@ -3378,6 +3381,26 @@ class EmergencyFailClosedError extends Error {
3378
3381
  }
3379
3382
 
3380
3383
  // src/hooks/magic-context/history-boundary-repair.ts
3384
+ function readStoreBoundaries(db, sessionId) {
3385
+ const columns = getTableColumnNames(db, "compartments");
3386
+ const numbers = ["id", "sequence", "start_message", "end_message", "created_at"];
3387
+ const strings = ["session_id", "start_message_id", "end_message_id", "title", "content"];
3388
+ const predicates = [...numbers, ...strings].every((column) => columns.has(column)) ? [
3389
+ ...numbers.map((column) => `typeof(${column}) IN ('integer', 'real')`),
3390
+ ...strings.map((column) => `typeof(${column}) = 'text'`)
3391
+ ] : ["0"];
3392
+ for (const column of ["p1", "p2", "p3", "p4", "episode_type"]) {
3393
+ if (columns.has(column))
3394
+ predicates.push(`typeof(${column}) IN ('text', 'null')`);
3395
+ }
3396
+ for (const column of ["importance", "legacy"]) {
3397
+ if (columns.has(column))
3398
+ predicates.push(`typeof(${column}) IN ('integer', 'real', 'null')`);
3399
+ }
3400
+ return db.prepare(`SELECT sequence, ${columns.has("end_message_id") ? "end_message_id" : "NULL"} AS endMessageId
3401
+ FROM compartments WHERE session_id = ? AND ${predicates.join(" AND ")}
3402
+ ORDER BY sequence ASC`).all(sessionId);
3403
+ }
3381
3404
  function readBaseline(db, sessionId) {
3382
3405
  const row = db.prepare("SELECT cached_m0_bytes IS NOT NULL AS hasM0, cached_m0_last_baseline_end_message_id AS boundary FROM session_meta WHERE session_id = ?").get(sessionId);
3383
3406
  return {
@@ -3444,7 +3467,7 @@ function dropCompartmentsAfter(db, sessionId, anchor, holderId, activeBranch = f
3444
3467
  }
3445
3468
  function repairMissingHistoryBoundary(args) {
3446
3469
  const { db, sessionId, isInHostStore, scope = "store" } = args;
3447
- const compartments = scope === "active-branch" ? db.prepare("SELECT sequence, COALESCE(end_message_id, '') AS endMessageId FROM compartments WHERE session_id = ? ORDER BY sequence").all(sessionId) : getCompartments(db, sessionId);
3470
+ const compartments = scope === "active-branch" ? db.prepare("SELECT sequence, COALESCE(end_message_id, '') AS endMessageId FROM compartments WHERE session_id = ? ORDER BY sequence").all(sessionId) : readStoreBoundaries(db, sessionId);
3448
3471
  let latestIndex = compartments.length - 1;
3449
3472
  while (latestIndex >= 0 && !compartments[latestIndex]?.endMessageId)
3450
3473
  latestIndex -= 1;
@@ -3488,7 +3511,7 @@ function repairMissingHistoryBoundary(args) {
3488
3511
  let dropped;
3489
3512
  let anchorForDrop = anchor;
3490
3513
  try {
3491
- if (scope === "active-branch" && anchor) {
3514
+ if (anchor) {
3492
3515
  const row = db.prepare("SELECT end_message AS endMessage FROM compartments WHERE session_id = ? AND sequence = ?").get(sessionId, anchor.sequence);
3493
3516
  if (!row)
3494
3517
  return { kind: "unresolved", reason: "busy", missingEndMessageId: missing };
@@ -7520,6 +7543,12 @@ var RECENT_TOOL_SKELETON_WINDOW = 20;
7520
7543
  function buildReplacementContent(tagId) {
7521
7544
  return `[dropped §${tagId}§]`;
7522
7545
  }
7546
+ var FROZEN_TEXT_ANNOTATION_SUFFIX = /(?:\n\n(?:<instruction name="deferred_notes">(?:(?!<\/instruction>)[\s\S])*<\/instruction>|<ctx-search-hint>(?:(?!<\/ctx-search-hint>)[\s\S])*<\/ctx-search-hint>))+$/;
7547
+ function renderDroppedText(tagId, renderedText) {
7548
+ const placeholder = buildReplacementContent(tagId);
7549
+ const annotations = renderedText?.match(FROZEN_TEXT_ANNOTATION_SUFFIX)?.[0] ?? "";
7550
+ return placeholder + annotations;
7551
+ }
7523
7552
  function applyNewToolDrop(target, options) {
7524
7553
  const plan = planNewToolDrop(target, options, !!options.persist);
7525
7554
  if (!plan)
@@ -19284,8 +19313,21 @@ function createTransform(deps) {
19284
19313
  const temporalReplayIds = temporalCandidates ? messages.flatMap((message) => message.info.id ? [message.info.id] : []) : undefined;
19285
19314
  logTransformTiming(sessionId, "findSessionId", tSessionId, `messages=${messages.length}`);
19286
19315
  const tLkgEntry = performance.now();
19287
- const lkgInput = deps.transformMode === "rust" ? [] : projectEntry(sessionId, messages);
19316
+ const lkgInput = deps.transformMode === "rust" ? [] : projectEntry(sessionId, entryOrderForThinkingFit);
19288
19317
  const recovery = deps.compactionOff || deps.transformMode === "rust" ? {} : readLkgRecoveryPrefix(sessionId, lkgInput, messages, deps.db);
19318
+ const recoveryTailSources = [];
19319
+ if (recovery.prefix) {
19320
+ const priorIdentities = new Set(recovery.prefix.inputs.map((input) => input.id));
19321
+ lkgInput.forEach((input, index) => {
19322
+ const identity = lkgInputIdentity(input.id, input.role, index);
19323
+ if (!identity || priorIdentities.has(identity))
19324
+ return;
19325
+ recoveryTailSources.push({
19326
+ identity,
19327
+ pristineSystem: input.id === null && input.role === "system" ? structuredClone(entryOrderForThinkingFit[index]) : undefined
19328
+ });
19329
+ });
19330
+ }
19289
19331
  const persistedUntaggedInputIds = deps.compactionOff || deps.transformMode === "rust" ? [] : readPersistedLkgUntaggedInputIds(deps.db, sessionId);
19290
19332
  const untaggedReplayIds = new Set([
19291
19333
  ...recovery.prefix?.untaggedInputIds ?? [],
@@ -20322,9 +20364,15 @@ Historian previously failed ${historianFailureState.failureCount} time(s), so Ma
20322
20364
  });
20323
20365
  compactionModeTransitionPending.delete(sessionId);
20324
20366
  if (recovery.prefix && !recoveryNormalized) {
20325
- const priorIds = new Set(recovery.prefix.inputs.map((input) => input.id));
20326
- const newIds = new Set(lkgInput.flatMap((input) => input.id && !priorIds.has(input.id) ? [input.id] : []));
20327
- const suffix = messages.filter((message) => message.info.id && newIds.has(message.info.id));
20367
+ const renderedById = new Map;
20368
+ for (const message of messages) {
20369
+ if (!message.info.id)
20370
+ continue;
20371
+ const group = renderedById.get(message.info.id) ?? [];
20372
+ group.push(message);
20373
+ renderedById.set(message.info.id, group);
20374
+ }
20375
+ const suffix = recoveryTailSources.flatMap(({ identity, pristineSystem }) => pristineSystem ? [pristineSystem] : renderedById.get(identity) ?? []);
20328
20376
  messages.splice(0, messages.length, ...JSON.parse(recovery.prefix.json), ...suffix);
20329
20377
  }
20330
20378
  const recoveryReleaseReason = recovery.rebuildReason ?? (recoveryNormalized ? "recovery_tail_normalized" : undefined);
@@ -20781,6 +20829,8 @@ function replayCommittedDrops(db, sessionId, messages) {
20781
20829
  const toolThinking = new Map;
20782
20830
  const batch = new ToolMutationBatch(messages);
20783
20831
  for (const message of messages) {
20832
+ if (message.info.syntheticHead === true)
20833
+ continue;
20784
20834
  if (message.info.role === "user")
20785
20835
  precedingThinking = [];
20786
20836
  const thinking = message.parts.filter(isThinkingPart);
@@ -20814,9 +20864,10 @@ function replayCommittedDrops(db, sessionId, messages) {
20814
20864
  message,
20815
20865
  setContent(content) {
20816
20866
  if (isTextPart(part)) {
20817
- if (part.text === content)
20867
+ const rendered = renderDroppedText(tag.tagNumber, part.text);
20868
+ if (part.text === rendered)
20818
20869
  return false;
20819
- part.text = content;
20870
+ part.text = rendered;
20820
20871
  } else
20821
20872
  message.parts[p] = { type: "text", text: content };
20822
20873
  return true;
@@ -22349,8 +22400,26 @@ WHERE session_id = ?
22349
22400
  AND data IS NOT NULL
22350
22401
  AND (time_created > ? OR (time_created = ? AND id > ?))
22351
22402
  ORDER BY time_created, id`;
22352
- function readAssistantUsageRowsAfter(openCodeDb, sessionId, afterTimeCreated, afterId) {
22353
- const rows = openCodeDb.prepare(ASSISTANT_USAGE_ROWS_AFTER_SQL).all(sessionId, afterTimeCreated, afterTimeCreated, afterId);
22403
+ var V2_ASSISTANT_USAGE_ROWS_AFTER_SQL = `
22404
+ WITH newer AS (
22405
+ SELECT id, seq, data FROM session_message
22406
+ WHERE session_id = ? AND type = 'assistant' AND data IS NOT NULL AND seq > ?
22407
+ UNION ALL
22408
+ SELECT id, seq, data FROM session_message
22409
+ WHERE session_id = ? AND type = 'assistant' AND data IS NOT NULL AND seq = ? AND id > ?
22410
+ )
22411
+ SELECT
22412
+ json_extract(data, '$.agent') AS agent,
22413
+ seq AS time_created,
22414
+ id AS id,
22415
+ COALESCE(json_extract(data, '$.tokens.input'), 0)
22416
+ + COALESCE(json_extract(data, '$.tokens.cache.read'), 0)
22417
+ + COALESCE(json_extract(data, '$.tokens.cache.write'), 0) AS prompt,
22418
+ COALESCE(json_extract(data, '$.tokens.output'), 0) AS output
22419
+ FROM newer
22420
+ ORDER BY seq, id`;
22421
+ function readAssistantUsageRowsAfter(openCodeDb, sessionId, afterTimeCreated, afterId, generation = "v1") {
22422
+ const rows = openCodeDb.prepare(generation === "v2" ? V2_ASSISTANT_USAGE_ROWS_AFTER_SQL : ASSISTANT_USAGE_ROWS_AFTER_SQL).all(...generation === "v2" ? [sessionId, afterTimeCreated, sessionId, afterTimeCreated, afterId] : [sessionId, afterTimeCreated, afterTimeCreated, afterId]);
22354
22423
  return rows.map((r) => ({
22355
22424
  agent: r.agent ?? null,
22356
22425
  timeCreated: Number(r.time_created ?? 0),
@@ -22359,8 +22428,8 @@ function readAssistantUsageRowsAfter(openCodeDb, sessionId, afterTimeCreated, af
22359
22428
  output: Number(r.output ?? 0)
22360
22429
  }));
22361
22430
  }
22362
- function computeOpenCodeWorkMetricsIncremental(openCodeDb, sessionId, carry) {
22363
- const rows = readAssistantUsageRowsAfter(openCodeDb, sessionId, carry.lastTimeCreated, carry.lastId);
22431
+ function computeOpenCodeWorkMetricsIncremental(openCodeDb, sessionId, carry, generation = "v1") {
22432
+ const rows = readAssistantUsageRowsAfter(openCodeDb, sessionId, carry.lastTimeCreated, carry.lastId, generation);
22364
22433
  if (rows.length === 0) {
22365
22434
  return { carry, metrics: metricsFromCarry(carry) };
22366
22435
  }
@@ -22387,28 +22456,28 @@ var EMBEDDING_AFFECTING_KEYS = new Set([
22387
22456
  "embedding.query_instruction",
22388
22457
  "embedding.document_prefix",
22389
22458
  "embedding.fallback_provider",
22390
- "subc",
22459
+ "embedding.local_runtime",
22460
+ "embedding.local_dtype",
22391
22461
  "subc.connection_file",
22392
- "shadow_embedding"
22462
+ "shadow_embedding.enabled",
22463
+ "memory.enabled",
22464
+ "memory.git_commit_indexing.enabled",
22465
+ "allow_home_project"
22393
22466
  ]);
22394
22467
  var LITERAL_CONFIG_TOKEN_RE = /\{(?:env|file):[^}]+\}/;
22395
- function embeddingConfigHasLiteralTokens(embedding) {
22396
- if (!embedding)
22397
- return false;
22398
- for (const value of Object.values(embedding)) {
22468
+ function affectsEmbeddingRegistration(path) {
22469
+ return [...EMBEDDING_AFFECTING_KEYS].some((field) => field === path || field.startsWith(`${path}.`));
22470
+ }
22471
+ function untrustedConfigFieldPaths(detailed) {
22472
+ const paths = (detailed.recoveredFieldPaths ?? detailed.recoveredTopLevelKeys).filter(affectsEmbeddingRegistration);
22473
+ paths.push(...detailed.substitutionFailures.map((failure) => failure.keyPath).filter(affectsEmbeddingRegistration));
22474
+ for (const [key, value] of Object.entries(detailed.config.embedding)) {
22399
22475
  if (typeof value === "string" && LITERAL_CONFIG_TOKEN_RE.test(value)) {
22400
- return true;
22476
+ paths.push(`embedding.${key}`);
22401
22477
  }
22402
22478
  }
22403
- return false;
22479
+ return [...new Set(paths)].sort();
22404
22480
  }
22405
- var EMBEDDING_AFFECTING_TOP_LEVEL_KEYS = new Set([
22406
- "embedding",
22407
- "memory",
22408
- "experimental",
22409
- "subc",
22410
- "shadow_embedding"
22411
- ]);
22412
22481
  var EMBEDDING_WARNING_TERMS = [
22413
22482
  "api_key",
22414
22483
  "endpoint",
@@ -22433,21 +22502,12 @@ function isConfigLoadUntrusted(detailed) {
22433
22502
  return true;
22434
22503
  }
22435
22504
  for (const failure of detailed.substitutionFailures) {
22436
- if (EMBEDDING_AFFECTING_KEYS.has(failure.keyPath)) {
22437
- return true;
22438
- }
22439
22505
  if (failure.keyPath === "<unknown>" && warningLooksEmbeddingRelated(failure.message)) {
22440
22506
  return true;
22441
22507
  }
22442
22508
  }
22443
- for (const recoveredKey of detailed.recoveredTopLevelKeys) {
22444
- if (EMBEDDING_AFFECTING_TOP_LEVEL_KEYS.has(recoveredKey)) {
22445
- return true;
22446
- }
22447
- }
22448
- if (embeddingConfigHasLiteralTokens(detailed.config.embedding)) {
22509
+ if (untrustedConfigFieldPaths(detailed).length > 0)
22449
22510
  return true;
22450
- }
22451
22511
  return false;
22452
22512
  }
22453
22513
  function describeFailure(detailed) {
@@ -22460,8 +22520,9 @@ function describeFailure(detailed) {
22460
22520
  if (detailed.substitutionFailures.length > 0) {
22461
22521
  parts.push(`substitution=${detailed.substitutionFailures.map((failure) => `${failure.source}:${failure.keyPath}`).join(",")}`);
22462
22522
  }
22463
- if (detailed.recoveredTopLevelKeys.length > 0) {
22464
- parts.push(`recovered=${detailed.recoveredTopLevelKeys.join(",")}`);
22523
+ const recovered = detailed.recoveredFieldPaths ?? detailed.recoveredTopLevelKeys;
22524
+ if (recovered.length > 0) {
22525
+ parts.push(`recovered=${recovered.join(",")}`);
22465
22526
  }
22466
22527
  return parts.length > 0 ? parts.join("; ") : detailed.loadOutcome;
22467
22528
  }
@@ -22469,7 +22530,8 @@ function logConfigFailureOnce(projectIdentity, detailed) {
22469
22530
  const signature = sha256Prefix(JSON.stringify({
22470
22531
  outcomes: detailed.sources,
22471
22532
  substitutions: detailed.substitutionFailures.map((failure) => `${failure.source}:${failure.keyPath}:${failure.message}`).sort(),
22472
- recoveredTopLevelKeys: [...detailed.recoveredTopLevelKeys].sort()
22533
+ recoveredTopLevelKeys: [...detailed.recoveredTopLevelKeys].sort(),
22534
+ recoveredFieldPaths: detailed.recoveredFieldPaths?.slice().sort()
22473
22535
  }));
22474
22536
  const existing = loggedFailureSignatures.get(projectIdentity) ?? new Set;
22475
22537
  if (existing.has(signature))
@@ -22485,9 +22547,14 @@ function handleUntrustedLoad(db, projectIdentity, directory, detailed) {
22485
22547
  logConfigFailureOnce(projectIdentity, detailed);
22486
22548
  return true;
22487
22549
  }
22488
- registerProjectInObservationMode2(db, projectIdentity, directory, detailed.config.embedding, describeFailure(detailed));
22550
+ registerProjectInObservationMode2(db, projectIdentity, directory, detailed.config.embedding, describeFailure(detailed), untrustedConfigMemoryMessage(detailed));
22489
22551
  return true;
22490
22552
  }
22553
+ function untrustedConfigMemoryMessage(detailed) {
22554
+ const fields = untrustedConfigFieldPaths(detailed);
22555
+ const cause = fields.length > 0 ? `has invalid embedding or project identity settings: ${fields.join(", ")}` : Object.values(detailed.sources).includes("legacy-config-unmigrated") ? "is awaiting config migration" : Object.values(detailed.sources).some((source) => source === "project-file-parse-error" || source === "project-file-io-error") ? "could not be read or parsed" : "has invalid embedding settings";
22556
+ return `Cross-session memory is off for this project because magic-context.jsonc ${cause}.`;
22557
+ }
22491
22558
 
22492
22559
  // src/plugin/embedding-routing.ts
22493
22560
  var SYNAPSE_PROBE_TTL_MS = 60000;
@@ -23034,13 +23101,15 @@ function runnerStatusFromModule(status) {
23034
23101
  }
23035
23102
  var rustStatusInFlight = new Map;
23036
23103
  function resolveSidebarWorkMetrics(db, sessionId, persistedNewWork, persistedTotalInput) {
23037
- if (!openCodeDbExists()) {
23104
+ const generation = getHarness2() === "opencode2" ? "v2" : "v1";
23105
+ if (!openCodeDbExists(generation)) {
23038
23106
  return { newWorkTokens: persistedNewWork, totalInputTokens: persistedTotalInput };
23039
23107
  }
23040
23108
  try {
23041
- const carry = workMetricsCarryBySession.get(sessionId) ?? emptyWorkMetricsCarry();
23042
- const { carry: nextCarry, metrics } = withReadOnlySessionDb((openCodeDb) => computeOpenCodeWorkMetricsIncremental(openCodeDb, sessionId, carry));
23043
- workMetricsCarryBySession.set(sessionId, nextCarry);
23109
+ const carryKey = `${generation}:${sessionId}`;
23110
+ const carry = workMetricsCarryBySession.get(carryKey) ?? emptyWorkMetricsCarry();
23111
+ const { carry: nextCarry, metrics } = withReadOnlySessionDb((openCodeDb) => computeOpenCodeWorkMetricsIncremental(openCodeDb, sessionId, carry, generation), generation);
23112
+ workMetricsCarryBySession.set(carryKey, nextCarry);
23044
23113
  try {
23045
23114
  setSessionWorkMetrics(db, sessionId, metrics.newWorkTokens, metrics.totalInputTokens);
23046
23115
  } catch {}
@@ -23941,8 +24010,8 @@ function registerRpcHandlers(rpcServer, args) {
23941
24010
  const db = readDatabase();
23942
24011
  if (!db)
23943
24012
  return { ok: false, error: "db unavailable" };
23944
- const { runManagedRecomp } = await importPluginModule(() => import("./recomp-orchestrator-txsmbnvw.js"));
23945
- const { sendIgnoredMessage } = await importPluginModule(() => import("./send-session-notification-vdsgnf4c.js"));
24013
+ const { runManagedRecomp } = await importPluginModule(() => import("./recomp-orchestrator-wb28kr9k.js"));
24014
+ const { sendIgnoredMessage } = await importPluginModule(() => import("./send-session-notification-x5nzy34v.js"));
23946
24015
  log2(`[rpc] recomp requested for session ${sessionId}`);
23947
24016
  if (!args.client && !args.hiddenCompletionExecutor) {
23948
24017
  return {
@@ -24026,7 +24095,7 @@ function registerRpcHandlers(rpcServer, args) {
24026
24095
  const db = readDatabase();
24027
24096
  if (!db)
24028
24097
  return { ok: false, error: "db unavailable" };
24029
- const { runManagedWrapup } = await importPluginModule(() => import("./wrapup-orchestrator-gjkszser.js"));
24098
+ const { runManagedWrapup } = await importPluginModule(() => import("./wrapup-orchestrator-2t0pdqzm.js"));
24030
24099
  const model = liveSessionState.liveModelBySession.get(sessionId);
24031
24100
  const contextLimit = model ? resolveContextLimit(model.providerID, model.modelID, { db, sessionID: sessionId }) : 128000;
24032
24101
  const ctx = {
@@ -26816,6 +26885,7 @@ function createNativeHiddenChildren(host, removeSession, options) {
26816
26885
  const inFlight = removing.get(child.id);
26817
26886
  if (inFlight)
26818
26887
  return inFlight;
26888
+ options.log(`[magic-context] hidden child ${child.id} removing`);
26819
26889
  const done = (async () => {
26820
26890
  try {
26821
26891
  let timer;
@@ -26830,6 +26900,7 @@ function createNativeHiddenChildren(host, removeSession, options) {
26830
26900
  if (timer)
26831
26901
  clearTimeout(timer);
26832
26902
  }
26903
+ options.log(`[magic-context] hidden child ${child.id} removed`);
26833
26904
  } catch (error) {
26834
26905
  if (isSessionNotFound(error))
26835
26906
  return;
@@ -26841,14 +26912,19 @@ function createNativeHiddenChildren(host, removeSession, options) {
26841
26912
  removing.set(child.id, done);
26842
26913
  return done;
26843
26914
  };
26844
- const confirmPlacement = async (sessionID, parentID) => {
26915
+ const noteCreated = (sessionID, role, parentID) => {
26916
+ options.log(`[magic-context] hidden child ${sessionID} created role=${role} parent=${parentID} keep_subagents=${options.keepSubagents}`);
26917
+ };
26918
+ const confirmPlacement = async (sessionID, parentID, role) => {
26845
26919
  let stored;
26846
26920
  try {
26847
26921
  stored = await host.get({ sessionID });
26848
26922
  } catch (error) {
26923
+ noteCreated(sessionID, role, "unknown");
26849
26924
  options.log(`[magic-context] could not read back hidden child ${sessionID} to confirm its parent: ${errorText(error)}`);
26850
26925
  return;
26851
26926
  }
26927
+ noteCreated(sessionID, role, stored.parentID ?? "none");
26852
26928
  const directory = stored.location?.directory;
26853
26929
  if (options.directory !== undefined && directory !== undefined && !sameProjectDirectory(directory, options.directory)) {
26854
26930
  throw new HiddenCompletionRefusal("hidden_prompt_unrecognized", `hidden child ${sessionID} is bound to ${directory}, not to this instance's ${options.directory}. Reopen the parent session in ${directory}, then run /ctx-recomp so its owning instance can rebuild history.`, true);
@@ -26877,11 +26953,13 @@ function createNativeHiddenChildren(host, removeSession, options) {
26877
26953
  };
26878
26954
  if (parentID) {
26879
26955
  try {
26880
- await confirmPlacement(created.id, parentID);
26956
+ await confirmPlacement(created.id, parentID, role);
26881
26957
  } catch (error) {
26882
26958
  await remove(child);
26883
26959
  throw error;
26884
26960
  }
26961
+ } else {
26962
+ noteCreated(created.id, role, "none");
26885
26963
  }
26886
26964
  return child;
26887
26965
  };
@@ -26890,16 +26968,22 @@ function createNativeHiddenChildren(host, removeSession, options) {
26890
26968
  open: create,
26891
26969
  create,
26892
26970
  retire(child) {
26893
- if (!kept(child))
26971
+ if (kept(child)) {
26972
+ options.log(`[magic-context] hidden child ${child.id} kept (keep_subagents)`);
26973
+ } else {
26894
26974
  remove(child);
26975
+ }
26895
26976
  },
26896
26977
  async finish(child, retired) {
26897
26978
  if (retired) {
26898
26979
  await removing.get(child.id);
26899
26980
  return;
26900
26981
  }
26901
- if (!kept(child))
26982
+ if (kept(child)) {
26983
+ options.log(`[magic-context] hidden child ${child.id} kept (keep_subagents)`);
26984
+ } else {
26902
26985
  await remove(child);
26986
+ }
26903
26987
  },
26904
26988
  updateModel: (child, model) => ({ ...child, model }),
26905
26989
  markEverSettled: (child) => ({ ...child, ever_settled: true })
@@ -26946,6 +27030,7 @@ async function cleanupLegacyHiddenChildren(db, remove, note, options = {}) {
26946
27030
  timer = setTimeout(() => reject(new Error("session.remove timed out")), Math.min(options.timeoutMs ?? 1000, Math.max(1, deadline - now())));
26947
27031
  })
26948
27032
  ]);
27033
+ note(`[magic-context] legacy hidden child ${child.id} removed`);
26949
27034
  } catch (error) {
26950
27035
  if (!isSessionNotFound(error))
26951
27036
  throw error;
@@ -27139,6 +27224,16 @@ function toolResultText(result) {
27139
27224
  `);
27140
27225
  return text.length > 0 ? text : undefined;
27141
27226
  }
27227
+ function sumRowUsage(rows) {
27228
+ const count = (value) => typeof value === "number" && Number.isFinite(value) ? value : 0;
27229
+ return rows.reduce((total, row) => ({
27230
+ input: total.input + count(row.data.tokens?.input),
27231
+ output: total.output + count(row.data.tokens?.output),
27232
+ cacheRead: total.cacheRead + count(row.data.tokens?.cache?.read),
27233
+ cacheWrite: total.cacheWrite + count(row.data.tokens?.cache?.write),
27234
+ ...total.reasoning !== undefined || row.data.tokens?.reasoning !== undefined ? { reasoning: (total.reasoning ?? 0) + count(row.data.tokens?.reasoning) } : {}
27235
+ }), { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 });
27236
+ }
27142
27237
  function toolLoopMessages(attempt, rows) {
27143
27238
  const messages = attempt.observedMessages ?? [];
27144
27239
  const results = new Map;
@@ -27331,6 +27426,10 @@ function createLateHiddenExecutor(current) {
27331
27426
  open: (run) => wired().open(run),
27332
27427
  attempt: (handle, request) => wired().attempt(handle, request),
27333
27428
  collect: (handle, limit) => wired().collect(handle, limit),
27429
+ collectPartial: (handle, limit) => {
27430
+ const executor = wired();
27431
+ return executor.collectPartial?.(handle, limit) ?? executor.collect(handle, limit);
27432
+ },
27334
27433
  close: (handle, settlement) => wired().close(handle, settlement)
27335
27434
  };
27336
27435
  }
@@ -27420,9 +27519,32 @@ async function createV2HiddenCompletionExecutor(host, options) {
27420
27519
  });
27421
27520
  run.child = lifecycle.updateModel(run.child, requested);
27422
27521
  };
27522
+ const partialCompletion = (run) => {
27523
+ const attempt = run.attempt;
27524
+ const rows = attempt ? withReader(options.openReader, (reader) => {
27525
+ const latest = reader.latestAssistant(run.child.id);
27526
+ return (reader.assistantSince?.(run.child.id, attempt.baseline) ?? (latest ? [latest] : [])).filter((row) => row.seq > attempt.baseline);
27527
+ }) : [];
27528
+ const usage = sumRowUsage(rows);
27529
+ return {
27530
+ text: rows.map(assistantText).filter(Boolean).join(`
27531
+ `) || null,
27532
+ messages: attempt ? toolLoopMessages(attempt.child, rows) : [],
27533
+ usage,
27534
+ tokenLog: runTokenLog(usage),
27535
+ lengthCapped: false
27536
+ };
27537
+ };
27423
27538
  const retire = (run, reason) => {
27424
27539
  if (run.retired)
27425
27540
  return;
27541
+ if (hiddenToolLoop(run.identity) && !run.completion) {
27542
+ try {
27543
+ run.partialCompletion = partialCompletion(run);
27544
+ } catch (error) {
27545
+ note(`[magic-context] could not read interrupted child output: ${String(error)}`);
27546
+ }
27547
+ }
27426
27548
  lifecycle.retire(run.child, reason);
27427
27549
  run.retired = true;
27428
27550
  };
@@ -27553,6 +27675,8 @@ async function createV2HiddenCompletionExecutor(host, options) {
27553
27675
  shaped: false,
27554
27676
  budget: run.budget
27555
27677
  };
27678
+ run.partialCompletion = undefined;
27679
+ run.attempt = { child: attempt, baseline };
27556
27680
  options.hook.registerAttempt(marker, attempt);
27557
27681
  const deadline = Date.now() + run.identity.timeoutMs;
27558
27682
  const budget = run.budget;
@@ -27688,19 +27812,14 @@ async function createV2HiddenCompletionExecutor(host, options) {
27688
27812
  const tokenNumber = (value) => typeof value === "number" && Number.isFinite(value) ? value : undefined;
27689
27813
  const steps = withReader(options.openReader, (reader) => reader.assistantSince?.(run.child.id, baseline) ?? [row]).filter((step) => step.seq > baseline && step.seq <= row.seq);
27690
27814
  const reportedUsage = steps.some((step) => tokenNumber(step.data.tokens?.input) !== undefined || tokenNumber(step.data.tokens?.output) !== undefined);
27691
- const usage = steps.reduce((total, step) => ({
27692
- input: total.input + (tokenNumber(step.data.tokens?.input) ?? 0),
27693
- output: total.output + (tokenNumber(step.data.tokens?.output) ?? 0),
27694
- cacheRead: total.cacheRead + (tokenNumber(step.data.tokens?.cache?.read) ?? 0),
27695
- cacheWrite: total.cacheWrite + (tokenNumber(step.data.tokens?.cache?.write) ?? 0)
27696
- }), { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 });
27815
+ const usage = sumRowUsage(steps);
27697
27816
  if (request.signal?.aborted || run.retired || Date.now() >= deadline) {
27698
27817
  await interruptAndRetire(run, "prompt-aborted-or-timeout");
27699
27818
  throw new Error(request.signal?.aborted ? "Hidden completion prompt aborted" : "Hidden completion prompt timed out");
27700
27819
  }
27701
27820
  run.completion = {
27702
27821
  text,
27703
- tokenLog: runTokenLog(tokens, run.identity.maxOutputTokens, row.data.finish),
27822
+ tokenLog: runTokenLog(reportedUsage ? usage : tokens, run.identity.maxOutputTokens, row.data.finish),
27704
27823
  ...hiddenToolLoop(run.identity) ? { messages: toolLoopMessages(attempt, steps) } : {},
27705
27824
  reasoning: text ? null : assistantReasoning(row),
27706
27825
  usage: reportedUsage ? usage : meter(system, promptText(request), text ?? ""),
@@ -27749,6 +27868,12 @@ async function createV2HiddenCompletionExecutor(host, options) {
27749
27868
  throw new Error("Hidden completion has no settled output");
27750
27869
  return completion;
27751
27870
  },
27871
+ async collectPartial(handle) {
27872
+ const run = runs.get(handle);
27873
+ if (!run)
27874
+ throw new Error("Hidden completion handle is closed");
27875
+ return run.completion ?? run.partialCompletion ?? partialCompletion(run);
27876
+ },
27752
27877
  async close(handle, settlement) {
27753
27878
  if (!handle)
27754
27879
  return;
@@ -27813,6 +27938,96 @@ class HiddenModelActivity {
27813
27938
  }
27814
27939
  }
27815
27940
 
27941
+ // src/v2/message-times.ts
27942
+ function isSettled(entry, readAt) {
27943
+ return (entry.version.type === "user" || entry.time.completed !== undefined) && typeof entry.version.updated === "number" && Number.isFinite(entry.version.updated) && entry.version.updated <= readAt - 1000;
27944
+ }
27945
+ function sameVersion(a, b) {
27946
+ return a.type === b.type && a.seq === b.seq && a.created === b.created && a.updated === b.updated;
27947
+ }
27948
+
27949
+ class V2MessageTimesCache {
27950
+ capacity;
27951
+ sessions = new Map;
27952
+ constructor(capacity = 64) {
27953
+ this.capacity = capacity;
27954
+ }
27955
+ delete(sessionID) {
27956
+ this.sessions.delete(sessionID);
27957
+ }
27958
+ deleteMessage(sessionID, messageID) {
27959
+ this.sessions.get(sessionID)?.entries.delete(messageID);
27960
+ }
27961
+ clear() {
27962
+ this.sessions.clear();
27963
+ }
27964
+ pass(sessionID) {
27965
+ const previous = this.sessions.get(sessionID);
27966
+ const current = { entries: new Map };
27967
+ this.sessions.delete(sessionID);
27968
+ this.sessions.set(sessionID, current);
27969
+ while (this.sessions.size > this.capacity) {
27970
+ const oldest = this.sessions.keys().next().value;
27971
+ if (oldest === undefined)
27972
+ break;
27973
+ this.sessions.delete(oldest);
27974
+ }
27975
+ const passTimes = new Map;
27976
+ return (reader, ids) => {
27977
+ const missing = [...new Set(ids)].filter((id) => !passTimes.has(id));
27978
+ if (missing.length > 0) {
27979
+ const readAt = Date.now();
27980
+ const identity = reader.hostIdentity();
27981
+ current.identity = identity;
27982
+ const reusable = previous?.identity === identity ? previous.entries : undefined;
27983
+ const known = [];
27984
+ const refresh = [];
27985
+ let first = Infinity;
27986
+ let last = -Infinity;
27987
+ for (const id of missing) {
27988
+ const entry = reusable?.get(id);
27989
+ if (entry && isSettled(entry, readAt)) {
27990
+ known.push(id);
27991
+ first = Math.min(first, entry.version.seq);
27992
+ last = Math.max(last, entry.version.seq);
27993
+ } else
27994
+ refresh.push(id);
27995
+ }
27996
+ const versions = reader.messageTimeVersions(sessionID, known, { first, last });
27997
+ for (const id of known) {
27998
+ const version = versions.get(id);
27999
+ const cached = reusable?.get(id);
28000
+ if (!version) {
28001
+ passTimes.set(id, null);
28002
+ } else if (cached && sameVersion(cached.version, version) && (version.type === "user" || cached.time.completed !== undefined)) {
28003
+ current.entries.set(id, cached);
28004
+ passTimes.set(id, cached.time);
28005
+ } else
28006
+ refresh.push(id);
28007
+ }
28008
+ const times = reader.messageTimes(sessionID, refresh, versions);
28009
+ for (const id of refresh) {
28010
+ const time = times.get(id);
28011
+ const version = versions.get(id);
28012
+ passTimes.set(id, time ?? null);
28013
+ if (time && version) {
28014
+ const entry = { version, time };
28015
+ if (isSettled(entry, readAt))
28016
+ current.entries.set(id, entry);
28017
+ }
28018
+ }
28019
+ }
28020
+ const result = new Map;
28021
+ for (const id of ids) {
28022
+ const time = passTimes.get(id);
28023
+ if (time)
28024
+ result.set(id, { ...time });
28025
+ }
28026
+ return result;
28027
+ };
28028
+ }
28029
+ }
28030
+
27816
28031
  // src/v2/hooks/channel2.ts
27817
28032
  import { randomBytes as randomBytes2 } from "node:crypto";
27818
28033
  var pendingCandidates = new WeakMap;
@@ -28923,7 +29138,7 @@ async function runHiddenSingleShotPrompt(args) {
28923
29138
  let timer;
28924
29139
  try {
28925
29140
  const completion = await Promise.race([
28926
- args.executor.collect(handle, 200),
29141
+ args.executor.collectPartial?.(handle, 200) ?? args.executor.collect(handle, 200),
28927
29142
  new Promise((resolve) => {
28928
29143
  timer = setTimeout(() => resolve(null), 5000);
28929
29144
  })
@@ -30756,6 +30971,7 @@ Remember: output only the JSON object described by the system prompt.`;
30756
30971
  let childSessionId = null;
30757
30972
  let promptSettled = false;
30758
30973
  let invocationRecorded = false;
30974
+ let completionUsage;
30759
30975
  const recordInvocation = (params) => {
30760
30976
  if (!args.db || !args.parentSessionId || invocationRecorded)
30761
30977
  return;
@@ -30769,6 +30985,7 @@ Remember: output only the JSON object described by the system prompt.`;
30769
30985
  startedAt,
30770
30986
  status: params.status,
30771
30987
  messages: params.messages,
30988
+ tokens: args.hiddenCompletionExecutor?.capabilities.harness === "opencode2" ? completionUsage : undefined,
30772
30989
  attemptedModel: args.model,
30773
30990
  configuredModels: args.fallbackModels,
30774
30991
  error: params.error
@@ -30793,11 +31010,15 @@ Remember: output only the JSON object described by the system prompt.`;
30793
31010
  timeoutMs: remainingMs,
30794
31011
  signal: args.signal,
30795
31012
  metadata: { task: "evaluate-smart-notes" },
31013
+ onFailureOutput: (completion) => {
31014
+ completionUsage = completion.usage;
31015
+ },
30796
31016
  parse: parseCompilerOutput
30797
31017
  });
30798
31018
  promptSettled = true;
30799
31019
  response = carried.validated;
30800
31020
  outputMessages = carried.completion.messages;
31021
+ completionUsage = carried.completion.usage;
30801
31022
  } else {
30802
31023
  const client = args.client;
30803
31024
  if (!client) {
@@ -31575,6 +31796,7 @@ async function confirmReadOnly(args, noteId, content, surfaceCondition, leaseSig
31575
31796
  startedAt,
31576
31797
  status: params.status,
31577
31798
  messages: params.messages,
31799
+ tokens: args.hiddenCompletionExecutor?.capabilities.harness === "opencode2" ? params.tokens : undefined,
31578
31800
  attemptedModel: args.model,
31579
31801
  configuredModels: args.fallbackModels,
31580
31802
  error: params.error
@@ -31602,7 +31824,11 @@ async function confirmReadOnly(args, noteId, content, surfaceCondition, leaseSig
31602
31824
  parse: parseConfirmationVerdict
31603
31825
  });
31604
31826
  promptSettled = true;
31605
- recordInvocation({ status: "completed", messages: run.completion.messages });
31827
+ recordInvocation({
31828
+ status: "completed",
31829
+ messages: run.completion.messages,
31830
+ tokens: run.completion.usage
31831
+ });
31606
31832
  return run.validated;
31607
31833
  } finally {
31608
31834
  promptSignal.cleanup();
@@ -32270,7 +32496,8 @@ async function mapOneBatch(args, batch, sliceMs, signal) {
32270
32496
  });
32271
32497
  recordInvocation2(args, startedAt, {
32272
32498
  status: "completed",
32273
- messages: run.completion.messages ?? []
32499
+ messages: run.completion.messages ?? [],
32500
+ tokens: run.completion.usage
32274
32501
  });
32275
32502
  stage = "apply";
32276
32503
  const outcome = await applyParsedBatchMappings(args, batch, run.validated, budgetFinalized, true);
@@ -32345,7 +32572,8 @@ async function mapOneBatch(args, batch, sliceMs, signal) {
32345
32572
  recordInvocation2(args, startedAt, {
32346
32573
  status: failedInvocationStatus(error),
32347
32574
  error,
32348
- messages
32575
+ messages,
32576
+ tokens: failedCompletion?.usage
32349
32577
  });
32350
32578
  if (error instanceof DreamerModuleFailureError)
32351
32579
  throw error;
@@ -32512,6 +32740,7 @@ function recordInvocation2(args, startedAt, params) {
32512
32740
  startedAt,
32513
32741
  status: params.status,
32514
32742
  messages: params.messages,
32743
+ tokens: args.hiddenCompletionExecutor?.capabilities.harness === "opencode2" ? params.tokens : undefined,
32515
32744
  attemptedModel: args.model,
32516
32745
  configuredModels: args.fallbackModels,
32517
32746
  error: params.error
@@ -33790,7 +34019,8 @@ async function git2(root, args) {
33790
34019
  cwd: root,
33791
34020
  timeout: 1e4,
33792
34021
  maxBuffer: MAX_DIFF_BYTES,
33793
- encoding: "utf8"
34022
+ encoding: "utf8",
34023
+ windowsHide: true
33794
34024
  });
33795
34025
  return stdout;
33796
34026
  }
@@ -34432,7 +34662,8 @@ async function verifyOneBatch(args, batch, sliceMs, signal) {
34432
34662
  });
34433
34663
  recordInvocation4(args, startedAt, {
34434
34664
  status: "completed",
34435
- messages: run.completion.messages ?? []
34665
+ messages: run.completion.messages ?? [],
34666
+ tokens: run.completion.usage
34436
34667
  });
34437
34668
  reportUsage(run.completion.messages ?? [], run.childSessionId, run.completion.usage.input + (run.completion.usage.cacheRead ?? 0) + (run.completion.usage.cacheWrite ?? 0));
34438
34669
  return await applyParsedVerifyManifest(args, batch, run.validated, evidence?.head ?? headAtPrompt, budgetFinalized);
@@ -34506,7 +34737,8 @@ async function verifyOneBatch(args, batch, sliceMs, signal) {
34506
34737
  recordInvocation4(args, startedAt, {
34507
34738
  status: failedInvocationStatus(error),
34508
34739
  error,
34509
- messages
34740
+ messages,
34741
+ tokens: failedCompletion?.usage
34510
34742
  });
34511
34743
  if (error instanceof DreamerModuleFailureError || signal.aborted)
34512
34744
  throw error;
@@ -34765,6 +34997,7 @@ function recordInvocation4(args, startedAt, params) {
34765
34997
  startedAt,
34766
34998
  status: params.status,
34767
34999
  messages: params.messages,
35000
+ tokens: args.hiddenCompletionExecutor?.capabilities.harness === "opencode2" ? params.tokens : undefined,
34768
35001
  attemptedModel: args.model,
34769
35002
  configuredModels: args.fallbackModels,
34770
35003
  error: params.error
@@ -34834,6 +35067,15 @@ function classifyFailure(error) {
34834
35067
  const transient = explicitTransient || name === "AbortError" || /abort|lease|timeout|timed out|econn|socket|network|rate.?limit|429|503|overloaded|sqlite_busy|database is locked/.test(combined);
34835
35068
  return { transient, brief };
34836
35069
  }
35070
+ function sumCompletionUsages(usages) {
35071
+ return usages.reduce((total, usage) => ({
35072
+ input: total.input + usage.input,
35073
+ output: total.output + usage.output,
35074
+ cacheRead: total.cacheRead + usage.cacheRead,
35075
+ cacheWrite: total.cacheWrite + usage.cacheWrite,
35076
+ ...total.reasoning !== undefined || usage.reasoning !== undefined ? { reasoning: (total.reasoning ?? 0) + (usage.reasoning ?? 0) } : {}
35077
+ }), emptyTokenTotals());
35078
+ }
34837
35079
  function newIds(beforeIds, afterIds) {
34838
35080
  const before = new Set(beforeIds);
34839
35081
  const out = [];
@@ -35641,6 +35883,7 @@ async function runRetrospectiveTask(config, ctx, helpers) {
35641
35883
  }, ctx.leaseAcquisition);
35642
35884
  let childSessionId = null;
35643
35885
  let hiddenHandle = null;
35886
+ const hiddenUsages = [];
35644
35887
  let promptSettled = false;
35645
35888
  let invocationRecorded = false;
35646
35889
  const recordInvocation = (status, messages, error) => {
@@ -35656,6 +35899,7 @@ async function runRetrospectiveTask(config, ctx, helpers) {
35656
35899
  startedAt: helpers.invocationStartedAt,
35657
35900
  status,
35658
35901
  messages,
35902
+ tokens: deps.hiddenCompletionExecutor?.capabilities.harness === "opencode2" && hiddenUsages.length ? sumCompletionUsages(hiddenUsages) : undefined,
35659
35903
  attemptedModel: config.model,
35660
35904
  configuredModels: config.fallbackModels,
35661
35905
  error
@@ -35741,6 +35985,8 @@ async function runRetrospectiveTask(config, ctx, helpers) {
35741
35985
  }
35742
35986
  });
35743
35987
  promptSettled = true;
35988
+ if (hiddenHandle)
35989
+ hiddenUsages.push(run.output.usage);
35744
35990
  const output = hiddenHandle ? run.output.messages ?? [] : run.output;
35745
35991
  return { ...run, output };
35746
35992
  };
@@ -35911,6 +36157,7 @@ async function runAgenticTask(config, ctx, helpers) {
35911
36157
  let childSessionId = null;
35912
36158
  let promptSettled = false;
35913
36159
  let expiredArchived = 0;
36160
+ const hiddenUsages = [];
35914
36161
  let invocationRecorded = false;
35915
36162
  const recordInvocation = (status, messages, error) => {
35916
36163
  if (!parent || !childSessionId || invocationRecorded)
@@ -35925,6 +36172,7 @@ async function runAgenticTask(config, ctx, helpers) {
35925
36172
  startedAt: invocationStartedAt,
35926
36173
  status,
35927
36174
  messages,
36175
+ tokens: deps.hiddenCompletionExecutor?.capabilities.harness === "opencode2" && hiddenUsages.length ? sumCompletionUsages(hiddenUsages) : undefined,
35928
36176
  attemptedModel: config.model,
35929
36177
  configuredModels: config.fallbackModels,
35930
36178
  error
@@ -36042,6 +36290,7 @@ async function runAgenticTask(config, ctx, helpers) {
36042
36290
  }
36043
36291
  });
36044
36292
  childSessionId = hidden.childSessionId;
36293
+ hiddenUsages.push(hidden.completion.usage);
36045
36294
  run = { output: hidden.completion.messages ?? [], validated: hidden.validated };
36046
36295
  promptSettled = true;
36047
36296
  } else {
@@ -37256,7 +37505,8 @@ async function sweepGitCommits(args) {
37256
37505
  try {
37257
37506
  const result = await indexCommitsForProject(db, projectIdentity, directory, {
37258
37507
  sinceDays: gitCommitIndexing.since_days,
37259
- maxCommits: gitCommitIndexing.max_commits
37508
+ maxCommits: gitCommitIndexing.max_commits,
37509
+ skipRetention: isCommitRetentionPaused(gitCommitIndexing)
37260
37510
  });
37261
37511
  if (result.nonIndexable) {
37262
37512
  if (!parkGitSweepNonIndexable(db, projectIdentity, holderId)) {
@@ -37341,11 +37591,7 @@ function registerV2DreamScheduleTimer(args) {
37341
37591
  embeddingConfig: config.embedding,
37342
37592
  transformMode: config.transform_mode,
37343
37593
  moduleClient: createDreamTimerModuleClient(args.rustModeModuleClient),
37344
- gitCommitIndexing: gitCommitIndexing?.enabled ? {
37345
- enabled: true,
37346
- since_days: gitCommitIndexing.since_days,
37347
- max_commits: gitCommitIndexing.max_commits
37348
- } : undefined,
37594
+ gitCommitIndexing: gitCommitIndexing?.enabled ? gitCommitIndexing : undefined,
37349
37595
  ensureRegistered: args.ensureRegistered ?? ensureProjectRegisteredFromOpenCodeDirectory
37350
37596
  }).catch((error) => {
37351
37597
  log2(`[magic-context] v2 dream timer registration failed (continuing without it): ${error}`);
@@ -38414,7 +38660,7 @@ function projectRawMessages(rows, ordinalFor) {
38414
38660
  const message = {
38415
38661
  id: row.id,
38416
38662
  ordinal: ordinalFor(row, index),
38417
- role: row.type === "assistant" ? "assistant" : "user",
38663
+ role: row.type === "assistant" ? "assistant" : row.type === "system" ? "system" : "user",
38418
38664
  createdAt: row.time_created ?? row.data.time?.created,
38419
38665
  parts: row.type === "assistant" ? (row.data.content ?? []).map((part) => {
38420
38666
  if (part.type !== "tool")
@@ -51102,7 +51348,7 @@ function createCtxMemoryTool(deps) {
51102
51348
  const memoryOwnedByTool = (memory) => visibility.owned(memory);
51103
51349
  const embeddingSnapshot = getProjectEmbeddingSnapshot2(projectPath);
51104
51350
  if (embeddingSnapshot ? !embeddingSnapshot.features.memoryEnabled : deps.memoryEnabled === false) {
51105
- return getDisabledMessage();
51351
+ return embeddingSnapshot?.memoryDisabledReason ?? getDisabledMessage();
51106
51352
  }
51107
51353
  if (args.action === "write") {
51108
51354
  const content = args.content?.trim();
@@ -53134,6 +53380,7 @@ function coveredInstructionRows(reader, sessionID, throughSeq, model) {
53134
53380
  async function registerContext(context) {
53135
53381
  const directory = context.location.directory;
53136
53382
  const config = loadPluginConfigDetailed(directory).config;
53383
+ log2(`[magic-context] OpenCode 2 keep_subagents=${config.keep_subagents === true}`);
53137
53384
  setHomeProjectPermission(config.allow_home_project);
53138
53385
  if (!config.enabled)
53139
53386
  return;
@@ -53266,6 +53513,7 @@ async function registerContext(context) {
53266
53513
  });
53267
53514
  let hiddenAgentsReady;
53268
53515
  const readerPool = new V2StoreReaderPool;
53516
+ const messageTimesCache = new V2MessageTimesCache;
53269
53517
  const openStoreReader = () => readerPool.open(gaDatabasePath(getDataDir(), process.env.OPENCODE_CHANNEL ?? "latest"));
53270
53518
  const createHiddenExecutor = async (database) => {
53271
53519
  await cleanupLegacyOnce(database);
@@ -53629,6 +53877,12 @@ async function registerContext(context) {
53629
53877
  if (event.type?.startsWith("session.revert.") || event.type === "session.message.content.updated") {
53630
53878
  nativeFoldReplay?.onEvent(event);
53631
53879
  restoredRows.forget(sessionID);
53880
+ messageTimesCache.delete(sessionID);
53881
+ }
53882
+ if (event.type === "session.step.started" || event.type === "session.step.ended" || event.type === "session.step.failed") {
53883
+ const messageID = event.data.assistantMessageID;
53884
+ if (typeof messageID === "string")
53885
+ messageTimesCache.deleteMessage(sessionID, messageID);
53632
53886
  }
53633
53887
  if (event.type === "session.error" || event.type === "session.execution.failed") {
53634
53888
  const error = hiddenTerminalError(event);
@@ -53667,6 +53921,7 @@ async function registerContext(context) {
53667
53921
  rawProviders.get(sessionID)?.();
53668
53922
  rawProviders.delete(sessionID);
53669
53923
  usage.delete(sessionID);
53924
+ messageTimesCache.delete(sessionID);
53670
53925
  hiddenSessionErrors.delete(sessionID);
53671
53926
  storageNoticeBySession.delete(sessionID);
53672
53927
  liveModels.delete(sessionID);
@@ -53961,22 +54216,9 @@ async function registerContext(context) {
53961
54216
  }
53962
54217
  await dropStorageNotices(draft.messages, isMagicContextSynthetic);
53963
54218
  const hostMessagesAtEntry = [...draft.messages];
53964
- const passTimes = new Map;
54219
+ const cachedTimes = messageTimesCache.pass(draft.sessionID);
53965
54220
  const readTimes = (reader, messages) => {
53966
- const ids = timeIds(messages);
53967
- const missing = ids.filter((id) => !passTimes.has(id));
53968
- if (missing.length > 0) {
53969
- const read = reader.messageTimes(draft.sessionID, missing);
53970
- for (const id of missing)
53971
- passTimes.set(id, read.get(id) ?? null);
53972
- }
53973
- const times = new Map;
53974
- for (const id of ids) {
53975
- const time = passTimes.get(id);
53976
- if (time)
53977
- times.set(id, time);
53978
- }
53979
- return times;
54221
+ return cachedTimes(reader, timeIds(messages));
53980
54222
  };
53981
54223
  liveModels.set(draft.sessionID, {
53982
54224
  providerID: draft.model.providerID,
@@ -54501,6 +54743,7 @@ async function registerContext(context) {
54501
54743
  }, 0));
54502
54744
  return {
54503
54745
  async dispose() {
54746
+ messageTimesCache.clear();
54504
54747
  usageController.abort();
54505
54748
  await hiddenCompletionExecutor?.dispose();
54506
54749
  await usageDone;