@cortexkit/opencode-magic-context 0.43.0 → 0.43.2

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 (102) hide show
  1. package/dist/{announcement-8mgn61fw.js → announcement-1a8bvswd.js} +2 -1
  2. package/dist/{conflict-warning-hook-t2vb0wnx.js → conflict-warning-hook-hyk9y29x.js} +6 -4
  3. package/dist/{derive-budgets-0sg5vp61.js → derive-budgets-b8ybssh9.js} +3 -2
  4. package/dist/features/magic-context/dreamer/classify.d.ts +12 -0
  5. package/dist/features/magic-context/dreamer/classify.d.ts.map +1 -1
  6. package/dist/features/magic-context/dreamer/hidden-single-shot.d.ts +7 -4
  7. package/dist/features/magic-context/dreamer/hidden-single-shot.d.ts.map +1 -1
  8. package/dist/features/magic-context/dreamer/map-memories.d.ts +3 -1
  9. package/dist/features/magic-context/dreamer/map-memories.d.ts.map +1 -1
  10. package/dist/features/magic-context/dreamer/refresh-primers.d.ts +3 -1
  11. package/dist/features/magic-context/dreamer/refresh-primers.d.ts.map +1 -1
  12. package/dist/features/magic-context/dreamer/task-executor.d.ts.map +1 -1
  13. package/dist/features/magic-context/dreamer/verify.d.ts +4 -1
  14. package/dist/features/magic-context/dreamer/verify.d.ts.map +1 -1
  15. package/dist/features/magic-context/memory/verification-paths.d.ts.map +1 -1
  16. package/dist/features/magic-context/store-generation-rebase.d.ts +62 -1
  17. package/dist/features/magic-context/store-generation-rebase.d.ts.map +1 -1
  18. package/dist/hooks/auto-update-checker/checker.d.ts +1 -0
  19. package/dist/hooks/auto-update-checker/checker.d.ts.map +1 -1
  20. package/dist/hooks/magic-context/command-handler.d.ts.map +1 -1
  21. package/dist/hooks/magic-context/compartment-runner-incremental.d.ts +6 -0
  22. package/dist/hooks/magic-context/compartment-runner-incremental.d.ts.map +1 -1
  23. package/dist/hooks/magic-context/compartment-runner-validation.d.ts +7 -0
  24. package/dist/hooks/magic-context/compartment-runner-validation.d.ts.map +1 -1
  25. package/dist/hooks/magic-context/compartment-trigger.d.ts +2 -1
  26. package/dist/hooks/magic-context/compartment-trigger.d.ts.map +1 -1
  27. package/dist/hooks/magic-context/ctx-reduce-availability.d.ts +60 -8
  28. package/dist/hooks/magic-context/ctx-reduce-availability.d.ts.map +1 -1
  29. package/dist/hooks/magic-context/hook.d.ts +3 -1
  30. package/dist/hooks/magic-context/hook.d.ts.map +1 -1
  31. package/dist/hooks/magic-context/lkg-slot.d.ts +1 -0
  32. package/dist/hooks/magic-context/lkg-slot.d.ts.map +1 -1
  33. package/dist/hooks/magic-context/rust-mode-transform.d.ts +2 -0
  34. package/dist/hooks/magic-context/rust-mode-transform.d.ts.map +1 -1
  35. package/dist/hooks/magic-context/send-session-notification.d.ts +1 -0
  36. package/dist/hooks/magic-context/send-session-notification.d.ts.map +1 -1
  37. package/dist/hooks/magic-context/system-prompt-hash.d.ts +9 -0
  38. package/dist/hooks/magic-context/system-prompt-hash.d.ts.map +1 -1
  39. package/dist/hooks/magic-context/transform-postprocess-phase.d.ts.map +1 -1
  40. package/dist/hooks/magic-context/transform.d.ts.map +1 -1
  41. package/dist/{index-8w1skpnm.js → index-0ccmyzbj.js} +6 -6
  42. package/dist/{index-ntbmt6rq.js → index-4b30nf6z.js} +1 -1
  43. package/dist/{index-rpz2me0v.js → index-6j8th2hd.js} +2 -2
  44. package/dist/{index-99sfbrrf.js → index-6w9p73jz.js} +1 -1
  45. package/dist/{index-4ftb5hcq.js → index-6z9g64js.js} +7 -1
  46. package/dist/{index-9skq8m9y.js → index-9r1cbh9e.js} +1 -1
  47. package/dist/{index-ykg9sdzz.js → index-bmzt6xgy.js} +3 -3
  48. package/dist/{safe-notification-target-fepvcbsj.js → index-febg06dy.js} +6 -7
  49. package/dist/{index-d0dh7v0f.js → index-g6hpfkqa.js} +361 -118
  50. package/dist/{index-rvwvdq59.js → index-jgnag7sa.js} +38 -4
  51. package/dist/{index-w2ety11c.js → index-pa67brzn.js} +3 -3
  52. package/dist/{index-ygwdyntq.js → index-tdrv6nd0.js} +6 -4
  53. package/dist/{index-qp20p2py.js → index-wgzyeyf5.js} +1 -1
  54. package/dist/index.d.ts.map +1 -1
  55. package/dist/index.js +801 -240
  56. package/dist/{message-time-backfill-gzjer78y.js → message-time-backfill-0ccvyk9n.js} +3 -2
  57. package/dist/plugin/hooks/create-session-hooks.d.ts.map +1 -1
  58. package/dist/{read-session-chunk-ec3jkvhg.js → read-session-chunk-53a7qbrh.js} +4 -3
  59. package/dist/{recomp-orchestrator-6akjp11f.js → recomp-orchestrator-adsgqgse.js} +9 -7
  60. package/dist/safe-notification-target-vrkjrbgb.js +10 -0
  61. package/dist/{send-session-notification-f6gwkesy.js → send-session-notification-e28r4xx2.js} +7 -3
  62. package/dist/shared/data-path.d.ts.map +1 -1
  63. package/dist/shared/model-suggestion-retry.d.ts.map +1 -1
  64. package/dist/shared/opencode-db-path.d.ts.map +1 -1
  65. package/dist/shared/test-fake-executable.d.ts +38 -0
  66. package/dist/shared/test-fake-executable.d.ts.map +1 -0
  67. package/dist/shared/test-temp-dir.d.ts +1 -1
  68. package/dist/shared/test-temp-dir.d.ts.map +1 -1
  69. package/dist/shared/user-facing-codes.d.ts +10 -0
  70. package/dist/shared/user-facing-codes.d.ts.map +1 -1
  71. package/dist/{task-config-ex4nt0q0.js → task-config-mgf5nsh3.js} +1 -1
  72. package/dist/v2/hidden-completion.d.ts.map +1 -1
  73. package/dist/v2/hooks/context.d.ts.map +1 -1
  74. package/dist/v2/hooks/hidden-child.d.ts +6 -0
  75. package/dist/v2/hooks/hidden-child.d.ts.map +1 -1
  76. package/dist/v2/hooks/payload.d.ts.map +1 -1
  77. package/dist/v2/hooks/refusal.d.ts +9 -1
  78. package/dist/v2/hooks/refusal.d.ts.map +1 -1
  79. package/dist/v2/hooks/restore-rows.d.ts +29 -0
  80. package/dist/v2/hooks/restore-rows.d.ts.map +1 -0
  81. package/dist/v2/hooks/types.d.ts +1 -0
  82. package/dist/v2/hooks/types.d.ts.map +1 -1
  83. package/dist/v2/hooks/update-check.d.ts +8 -0
  84. package/dist/v2/hooks/update-check.d.ts.map +1 -1
  85. package/dist/v2/host-service.d.ts +1 -1
  86. package/dist/v2/host-service.d.ts.map +1 -1
  87. package/dist/v2/server.js +1171 -366
  88. package/dist/v2/store-reader.d.ts +8 -0
  89. package/dist/v2/store-reader.d.ts.map +1 -1
  90. package/dist/wrapup-orchestrator-8xzbpvm8.js +18 -0
  91. package/package.json +2 -1
  92. package/src/features/magic-context/dreamer/task-registry.ts +1 -1
  93. package/src/shared/data-path.ts +6 -6
  94. package/src/shared/model-suggestion-retry.test.ts +43 -0
  95. package/src/shared/model-suggestion-retry.ts +17 -0
  96. package/src/shared/opencode-db-path.test.ts +18 -0
  97. package/src/shared/opencode-db-path.ts +5 -2
  98. package/src/shared/test-fake-executable.test.ts +54 -0
  99. package/src/shared/test-fake-executable.ts +110 -0
  100. package/src/shared/test-temp-dir.ts +3 -0
  101. package/src/shared/user-facing-codes.ts +11 -0
  102. package/dist/wrapup-orchestrator-5akc87gr.js +0 -16
package/dist/v2/server.js CHANGED
@@ -1675,8 +1675,15 @@ function getHarness() {
1675
1675
  }
1676
1676
  var currentHarness = "opencode", harnessLocked = false;
1677
1677
 
1678
+ // src/shared/test-temp-dir.ts
1679
+ var STALE_TEMP_DIR_AGE_MS, registeredTempDirs;
1680
+ var init_test_temp_dir = __esm(() => {
1681
+ STALE_TEMP_DIR_AGE_MS = 60 * 60 * 1000;
1682
+ registeredTempDirs = new Set;
1683
+ });
1684
+
1678
1685
  // src/shared/data-path.ts
1679
- import { existsSync as existsSync2, mkdirSync, mkdtempSync, readFileSync as readFileSync2, writeFileSync } from "node:fs";
1686
+ import { existsSync as existsSync2, mkdirSync, readFileSync as readFileSync2, writeFileSync } from "node:fs";
1680
1687
  import * as os from "node:os";
1681
1688
  import * as path from "node:path";
1682
1689
  function getDataDir() {
@@ -1764,7 +1771,9 @@ function getLegacyOpenCodeMagicContextStorageDir() {
1764
1771
  return path.join(getOpenCodeStorageDir(), "plugin", "magic-context");
1765
1772
  }
1766
1773
  var GITIGNORE_GUARD_OPEN = "# >>> cortexkit:magic-context", GITIGNORE_GUARD_CLOSE = "# <<< cortexkit:magic-context";
1767
- var init_data_path = () => {};
1774
+ var init_data_path = __esm(() => {
1775
+ init_test_temp_dir();
1776
+ });
1768
1777
 
1769
1778
  // src/shared/harness-provider-map.ts
1770
1779
  function remapProviderPrefix(ref, map) {
@@ -8994,7 +9003,7 @@ var init_task_registry = __esm(() => {
8994
9003
  "maintain-docs": {
8995
9004
  requiresTools: true,
8996
9005
  transport: "tool-loop",
8997
- toolLoopPurpose: "needs file read and write tools to update project documentation"
9006
+ toolLoopPurpose: "needs read-only file tools to investigate documentation corrections"
8998
9007
  },
8999
9008
  "evaluate-smart-notes": { requiresTools: false, transport: "single-shot" },
9000
9009
  "review-user-memories": { requiresTools: false, transport: "single-shot" },
@@ -15440,7 +15449,7 @@ var HOST_UNSERVED_ROW = "hostUnservedRow";
15440
15449
  // src/shared/opencode-db-path.ts
15441
15450
  import { existsSync as existsSync8, readdirSync, statSync as statSync7 } from "node:fs";
15442
15451
  import { homedir as homedir8 } from "node:os";
15443
- import { isAbsolute as isAbsolute4, join as join8 } from "node:path";
15452
+ import { isAbsolute as isAbsolute4, join as join8, resolve as resolve4 } from "node:path";
15444
15453
  function openCodeDataDir(env = process.env, dataHome) {
15445
15454
  return join8(dataHome ?? env.XDG_DATA_HOME ?? join8(homedir8(), ".local", "share"), "opencode");
15446
15455
  }
@@ -15520,7 +15529,7 @@ function resolveV2Fresh(dataDir, channel, env) {
15520
15529
  const filename = sourceOpenCodeDatabaseFilename("v2", channel, env);
15521
15530
  const explicit = env.OPENCODE_DB !== undefined;
15522
15531
  return {
15523
- path: filename === ":memory:" ? filename : join8(dataDir, filename),
15532
+ path: filename === ":memory:" ? filename : resolve4(dataDir, filename),
15524
15533
  source: explicit ? "OPENCODE_DB" : env.OPENCODE_CHANNEL ? "channel" : "default",
15525
15534
  channel: explicit ? null : channel
15526
15535
  };
@@ -18005,6 +18014,8 @@ function hasCountableParts(message) {
18005
18014
  case "step-start":
18006
18015
  case "step-finish":
18007
18016
  return true;
18017
+ case "file":
18018
+ return typeof p.url === "string" && p.url.startsWith("data:image/");
18008
18019
  default:
18009
18020
  return false;
18010
18021
  }
@@ -25201,9 +25212,22 @@ function visitMessageContentFields(value, visitor) {
25201
25212
  }
25202
25213
  return visitor.field(LKG_SNAPSHOT_UNDEFINED);
25203
25214
  }
25215
+ function contentSnapshotValue(value) {
25216
+ if (!value || typeof value !== "object")
25217
+ return value;
25218
+ const message = value;
25219
+ const info = message.info;
25220
+ const summary = info?.summary;
25221
+ if (!Array.isArray(message.parts) || info?.role !== "user" || summary === null || typeof summary !== "object" || Array.isArray(summary) || Object.keys(summary).length !== 1 || !Array.isArray(summary.diffs) || summary.diffs.length !== 0)
25222
+ return value;
25223
+ return {
25224
+ ...message,
25225
+ info: Object.fromEntries(Object.entries(info).filter(([key]) => key !== "summary"))
25226
+ };
25227
+ }
25204
25228
  function messageContentFields(message) {
25205
25229
  const fields = [];
25206
- const complete = visitMessageContentFields(message, {
25230
+ const complete = visitMessageContentFields(contentSnapshotValue(message), {
25207
25231
  field(value) {
25208
25232
  fields.push(value);
25209
25233
  return true;
@@ -25269,7 +25293,7 @@ function lkgContentFields(value) {
25269
25293
  fields.push(LKG_SNAPSHOT_UNDEFINED);
25270
25294
  };
25271
25295
  try {
25272
- visit(value);
25296
+ visit(contentSnapshotValue(value));
25273
25297
  return fields;
25274
25298
  } catch {
25275
25299
  return null;
@@ -26109,7 +26133,7 @@ import {
26109
26133
  statSync as statSync9,
26110
26134
  unlinkSync as unlinkSync2
26111
26135
  } from "node:fs";
26112
- import { basename as basename3, dirname as dirname6, join as join9, resolve as resolve4 } from "node:path";
26136
+ import { basename as basename3, dirname as dirname6, join as join9, resolve as resolve5 } from "node:path";
26113
26137
  function getSchemaFenceRejection() {
26114
26138
  return lastSchemaFenceRejection;
26115
26139
  }
@@ -26426,7 +26450,7 @@ function isDefaultSharedDatabasePath(dbPath) {
26426
26450
  if (!process.env.XDG_DATA_HOME && (process.env.MAGIC_CONTEXT_TEST_DATA_DIR || false)) {
26427
26451
  return false;
26428
26452
  }
26429
- return resolve4(dbPath) === resolve4(join9(getMagicContextStorageDir(), "context.db"));
26453
+ return resolve5(dbPath) === resolve5(join9(getMagicContextStorageDir(), "context.db"));
26430
26454
  }
26431
26455
  function migrationBlockingPiPids(dbPath, discovery, discoveredPiPids) {
26432
26456
  if (isDefaultSharedDatabasePath(dbPath))
@@ -28992,6 +29016,7 @@ function emptyOutcome(status, generation, previousGeneration) {
28992
29016
  previousGeneration,
28993
29017
  compartmentsRebased: 0,
28994
29018
  compartmentsUnresolved: 0,
29019
+ compartmentsDerived: 0,
28995
29020
  compartmentsResolvedAgain: 0,
28996
29021
  recompCompartmentsRebased: 0,
28997
29022
  recompCompartmentsUnresolved: 0,
@@ -29045,6 +29070,12 @@ function readCoordinateRebaseNotice(db, sessionId) {
29045
29070
  if (record.generation !== "v1" && record.generation !== "v2")
29046
29071
  return null;
29047
29072
  const count = (value) => typeof value === "number" && Number.isFinite(value) ? value : 0;
29073
+ const ranges = (value) => Array.isArray(value) ? value.flatMap((entry) => {
29074
+ if (!entry || typeof entry !== "object")
29075
+ return [];
29076
+ const { sequence, start, end } = entry;
29077
+ return typeof sequence === "number" && typeof start === "number" && typeof end === "number" ? [{ sequence, start, end }] : [];
29078
+ }) : [];
29048
29079
  return {
29049
29080
  generation: record.generation,
29050
29081
  previousGeneration: record.previousGeneration === "v1" || record.previousGeneration === "v2" ? record.previousGeneration : null,
@@ -29053,7 +29084,10 @@ function readCoordinateRebaseNotice(db, sessionId) {
29053
29084
  discardedReductions: count(record.discardedReductions),
29054
29085
  droppedDepthRows: count(record.droppedDepthRows),
29055
29086
  healedGaps: count(record.healedGaps),
29056
- narrativeGaps: count(record.narrativeGaps)
29087
+ narrativeGaps: count(record.narrativeGaps),
29088
+ derivedCompartments: ranges(record.derivedCompartments),
29089
+ unresolvedCompartmentRanges: ranges(record.unresolvedCompartmentRanges),
29090
+ neighbourRecoveryAt: typeof record.neighbourRecoveryAt === "number" && Number.isFinite(record.neighbourRecoveryAt) ? record.neighbourRecoveryAt : null
29057
29091
  };
29058
29092
  } catch {
29059
29093
  return null;
@@ -29090,36 +29124,62 @@ function readCompartmentRows(db, table, sessionId) {
29090
29124
  return db.prepare(`SELECT id, sequence, start_message, end_message, start_message_id, end_message_id, rebase_status
29091
29125
  FROM ${table} WHERE session_id = ? ORDER BY sequence ASC`).all(sessionId).filter(isCompartmentCoordinateRow);
29092
29126
  }
29127
+ function resolveAnchor(messageId, resolveOrdinal) {
29128
+ return messageId && messageId.length > 0 ? resolveOrdinal(messageId) : undefined;
29129
+ }
29093
29130
  function planCompartments(rows, table, projection) {
29094
- return rows.map((row) => {
29095
- const previousStatus = row.rebase_status === "unresolved" ? "unresolved" : "ok";
29096
- const startId = row.start_message_id ?? "";
29097
- const endId = row.end_message_id ?? "";
29098
- const start = startId.length > 0 ? projection.ordinalById.get(startId) : undefined;
29099
- const end = endId.length > 0 ? projection.ordinalById.get(endId) : undefined;
29100
- if (start === undefined || end === undefined) {
29101
- return {
29102
- table,
29103
- id: row.id,
29104
- previousStart: row.start_message,
29105
- previousEnd: row.end_message,
29106
- start: row.start_message,
29107
- end: row.end_message,
29108
- status: "unresolved",
29109
- previousStatus
29110
- };
29111
- }
29112
- return {
29131
+ const resolveOrdinal = (messageId) => projection.ordinalById.get(messageId);
29132
+ return recoverFromNeighbours(rows, table, rows.map((row) => ({
29133
+ start: resolveAnchor(row.start_message_id, resolveOrdinal),
29134
+ end: resolveAnchor(row.end_message_id, resolveOrdinal)
29135
+ })));
29136
+ }
29137
+ function recoverFromNeighbours(rows, table, known) {
29138
+ const plans = rows.map((row, index) => {
29139
+ const own = known[index] ?? { start: undefined, end: undefined };
29140
+ const previousEnd = index === 0 ? 0 : known[index - 1]?.end;
29141
+ const nextStart = index === rows.length - 1 ? undefined : known[index + 1]?.start;
29142
+ const start = own.start ?? (previousEnd === undefined ? undefined : previousEnd + 1);
29143
+ const end = own.end ?? (nextStart === undefined ? undefined : nextStart - 1);
29144
+ const base = {
29113
29145
  table,
29114
29146
  id: row.id,
29147
+ sequence: row.sequence,
29115
29148
  previousStart: row.start_message,
29116
29149
  previousEnd: row.end_message,
29117
- start,
29118
- end,
29119
- status: "ok",
29120
- previousStatus
29150
+ previousStatus: row.rebase_status === "unresolved" ? "unresolved" : "ok"
29151
+ };
29152
+ if (start !== undefined && end !== undefined && start <= end) {
29153
+ return {
29154
+ ...base,
29155
+ start,
29156
+ end,
29157
+ status: "ok",
29158
+ derived: own.start === undefined || own.end === undefined
29159
+ };
29160
+ }
29161
+ return {
29162
+ ...base,
29163
+ start: start ?? row.start_message,
29164
+ end: end ?? row.end_message,
29165
+ status: "unresolved",
29166
+ derived: false
29121
29167
  };
29122
29168
  });
29169
+ for (let index = 0;index < plans.length; index += 1) {
29170
+ const plan = plans[index];
29171
+ if (plan?.status !== "unresolved")
29172
+ continue;
29173
+ const previous = plans[index - 1];
29174
+ const next = plans[index + 1];
29175
+ if (previous?.status === "ok" && plan.start <= previous.end) {
29176
+ plan.start = previous.end + 1;
29177
+ }
29178
+ if (next?.status === "ok" && plan.end >= next.start) {
29179
+ plan.end = next.start - 1;
29180
+ }
29181
+ }
29182
+ return plans;
29123
29183
  }
29124
29184
  function healNonNarrativeCompartmentGaps(plans, projection) {
29125
29185
  let healed = 0;
@@ -29150,7 +29210,10 @@ function healNonNarrativeCompartmentGaps(plans, projection) {
29150
29210
  return { healed, narrative };
29151
29211
  }
29152
29212
  function compartmentPlanChanges(plan) {
29153
- return plan.status !== plan.previousStatus || plan.status === "ok" && (plan.start !== plan.previousStart || plan.end !== plan.previousEnd);
29213
+ return plan.status !== plan.previousStatus || plan.start !== plan.previousStart || plan.end !== plan.previousEnd;
29214
+ }
29215
+ function rangeNotes(plans, predicate) {
29216
+ return plans.filter((plan) => plan.table === "compartments" && predicate(plan)).map((plan) => ({ sequence: plan.sequence, start: plan.start, end: plan.end }));
29154
29217
  }
29155
29218
  function planNotes(db, sessionId, projection) {
29156
29219
  const rows = db.prepare("SELECT id, anchor_ordinal, anchor_block_id FROM notes WHERE session_id = ? AND anchor_ordinal IS NOT NULL").all(sessionId);
@@ -29236,7 +29299,14 @@ function rebaseSessionCoordinates(args) {
29236
29299
  }
29237
29300
  const previousGeneration = readCoordinateGeneration(db, sessionId);
29238
29301
  if (previousGeneration === generation) {
29239
- return emptyOutcome("unchanged", generation, previousGeneration);
29302
+ const outcome = emptyOutcome("unchanged", generation, previousGeneration);
29303
+ const repair = repairStampedSessionOnce(db, sessionId, args.readMessages);
29304
+ if (repair !== null && repair.rowsRewritten > 0) {
29305
+ outcome.status = "repaired";
29306
+ outcome.compartmentsDerived = repair.derived.length;
29307
+ outcome.compartmentsUnresolved = repair.unresolved.length;
29308
+ }
29309
+ return outcome;
29240
29310
  }
29241
29311
  const impliedGeneration = previousGeneration ?? generationImpliedByHarness(db, sessionId) ?? generation;
29242
29312
  if (impliedGeneration === generation) {
@@ -29300,6 +29370,8 @@ function rebaseSessionCoordinates(args) {
29300
29370
  if (plan.table === "compartments") {
29301
29371
  outcome.compartmentsRebased += rebased;
29302
29372
  outcome.compartmentsUnresolved += unresolved;
29373
+ if (rebased === 1 && plan.derived)
29374
+ outcome.compartmentsDerived += 1;
29303
29375
  if (rebased === 1 && plan.previousStatus === "unresolved")
29304
29376
  outcome.compartmentsResolvedAgain += 1;
29305
29377
  } else {
@@ -29356,7 +29428,10 @@ function rebaseSessionCoordinates(args) {
29356
29428
  discardedReductions: outcome.queuedReductionsDiscarded,
29357
29429
  droppedDepthRows: outcome.compressionDepthRowsDropped,
29358
29430
  healedGaps: outcome.healedGaps,
29359
- narrativeGaps: outcome.narrativeGaps
29431
+ narrativeGaps: outcome.narrativeGaps,
29432
+ derivedCompartments: rangeNotes(compartmentPlans, (plan) => plan.status === "ok" && plan.derived),
29433
+ unresolvedCompartmentRanges: rangeNotes(compartmentPlans, (plan) => plan.status === "unresolved"),
29434
+ neighbourRecoveryAt: Date.now()
29360
29435
  });
29361
29436
  db.exec("COMMIT");
29362
29437
  committed = true;
@@ -29374,10 +29449,114 @@ function rebaseSessionCoordinates(args) {
29374
29449
  sessionLog(sessionId, formatRebaseLogLine(outcome, performance.now() - startedAt));
29375
29450
  return outcome;
29376
29451
  }
29452
+ function recoverUnresolvedCompartments(args) {
29453
+ const { db, sessionId } = args;
29454
+ const rows = readCompartmentRows(db, "compartments", sessionId);
29455
+ const result = { rowsRewritten: 0, derived: [], unresolved: [] };
29456
+ if (!rows.some((row) => row.rebase_status === "unresolved"))
29457
+ return result;
29458
+ const known = rows.map((row) => {
29459
+ if (row.rebase_status !== "unresolved") {
29460
+ return { start: row.start_message, end: row.end_message };
29461
+ }
29462
+ return {
29463
+ start: resolveAnchor(row.start_message_id, args.resolveOrdinal),
29464
+ end: resolveAnchor(row.end_message_id, args.resolveOrdinal)
29465
+ };
29466
+ });
29467
+ const plans = recoverFromNeighbours(rows, "compartments", known);
29468
+ const wasUnresolved = (plan) => plan.previousStatus === "unresolved";
29469
+ result.derived = rangeNotes(plans, (plan) => wasUnresolved(plan) && plan.status === "ok" && plan.derived);
29470
+ result.unresolved = rangeNotes(plans, (plan) => plan.status === "unresolved");
29471
+ const changed = plans.filter(compartmentPlanChanges);
29472
+ const now = Date.now();
29473
+ db.exec("BEGIN IMMEDIATE");
29474
+ let committed = false;
29475
+ try {
29476
+ for (const plan of changed) {
29477
+ db.prepare("UPDATE compartments SET start_message = ?, end_message = ?, rebase_status = ? WHERE id = ?").run(plan.start, plan.end, plan.status, plan.id);
29478
+ }
29479
+ const previous = readCoordinateRebaseNotice(db, sessionId);
29480
+ const generation = previous?.generation ?? readCoordinateGeneration(db, sessionId);
29481
+ if (generation !== null) {
29482
+ const derivedSequences = new Set(result.derived.map((note) => note.sequence));
29483
+ const notice = {
29484
+ generation,
29485
+ previousGeneration: previous?.previousGeneration ?? null,
29486
+ at: previous?.at ?? now,
29487
+ unresolvedCompartments: result.unresolved.length,
29488
+ discardedReductions: previous?.discardedReductions ?? 0,
29489
+ droppedDepthRows: previous?.droppedDepthRows ?? 0,
29490
+ healedGaps: previous?.healedGaps ?? 0,
29491
+ narrativeGaps: previous?.narrativeGaps ?? 0,
29492
+ derivedCompartments: [
29493
+ ...(previous?.derivedCompartments ?? []).filter((note) => !derivedSequences.has(note.sequence)),
29494
+ ...result.derived
29495
+ ],
29496
+ unresolvedCompartmentRanges: result.unresolved,
29497
+ neighbourRecoveryAt: now
29498
+ };
29499
+ ensureSessionMetaRow(db, sessionId);
29500
+ db.prepare("UPDATE session_meta SET coordinate_rebase_notice = ? WHERE session_id = ?").run(JSON.stringify(notice), sessionId);
29501
+ }
29502
+ db.exec("COMMIT");
29503
+ committed = true;
29504
+ } finally {
29505
+ if (!committed) {
29506
+ try {
29507
+ db.exec("ROLLBACK");
29508
+ } catch {}
29509
+ }
29510
+ }
29511
+ result.rowsRewritten = changed.length;
29512
+ sessionLog(sessionId, `INFO compartment neighbour recovery (${args.reason}) rows_rewritten=${changed.length} ` + `derived=${result.derived.map((note) => `${note.start}-${note.end}`).join(",") || "none"} ` + `unresolved=${result.unresolved.map((note) => `${note.start}-${note.end}`).join(",") || "none"}`);
29513
+ return result;
29514
+ }
29515
+ function unresolvedRowBreaksTiling(rows) {
29516
+ let expectedStart = 1;
29517
+ for (let index = 0;index < rows.length; index += 1) {
29518
+ const row = rows[index];
29519
+ if (!row)
29520
+ continue;
29521
+ const broken = row.start_message !== expectedStart || row.end_message < row.start_message;
29522
+ const touchesUnresolved = row.rebase_status === "unresolved" || rows[index - 1]?.rebase_status === "unresolved";
29523
+ if (broken && touchesUnresolved)
29524
+ return true;
29525
+ expectedStart = row.end_message + 1;
29526
+ }
29527
+ return false;
29528
+ }
29529
+ function repairStampedSessionOnce(db, sessionId, readMessages) {
29530
+ let checked = repairCheckedSessions.get(db);
29531
+ if (!checked) {
29532
+ checked = new Set;
29533
+ repairCheckedSessions.set(db, checked);
29534
+ }
29535
+ if (checked.has(sessionId))
29536
+ return null;
29537
+ checked.add(sessionId);
29538
+ const rows = readCompartmentRows(db, "compartments", sessionId);
29539
+ if (!rows.some((row) => row.rebase_status === "unresolved"))
29540
+ return null;
29541
+ if (readCoordinateRebaseNotice(db, sessionId)?.neighbourRecoveryAt != null)
29542
+ return null;
29543
+ if (!unresolvedRowBreaksTiling(rows))
29544
+ return null;
29545
+ let ordinalById = null;
29546
+ return recoverUnresolvedCompartments({
29547
+ db,
29548
+ sessionId,
29549
+ resolveOrdinal: (messageId) => {
29550
+ ordinalById ??= buildProjection(readMessages(sessionId)).ordinalById;
29551
+ return ordinalById.get(messageId);
29552
+ },
29553
+ reason: "stamped-session repair"
29554
+ });
29555
+ }
29377
29556
  function formatRebaseLogLine(outcome, elapsedMs) {
29378
29557
  const rowsRewritten = outcome.compartmentsRebased + outcome.recompCompartmentsRebased + outcome.notesRebased + outcome.notesCleared + (outcome.priorBoundaryRebased ? 1 : 0) + (outcome.recompPartialRangeRebased ? 1 : 0);
29379
29558
  const unresolved = outcome.compartmentsUnresolved + outcome.recompCompartmentsUnresolved;
29380
- return `INFO store-generation-rebase ${outcome.previousGeneration ?? "unrecorded"}->${outcome.generation} ` + `rows_rewritten=${rowsRewritten} unresolved=${unresolved} ` + `index_rows_rebuilt=${outcome.indexRowsRebuilt} drops_discarded=${outcome.queuedReductionsDiscarded} ` + `healed_gaps=${outcome.healedGaps} narrative_gaps=${outcome.narrativeGaps} ` + `ms=${Math.round(elapsedMs)} ` + `(chunk_windows_deleted=${outcome.chunkEmbeddingsDeleted} depth_rows_dropped=${outcome.compressionDepthRowsDropped} ` + `part_tags_folded=${outcome.partTagsFolded} lkg_slots_dropped=${outcome.lkgSlotsDropped} ` + `frozen_part_entries_dropped=${outcome.frozenPartEntriesDropped})`;
29559
+ return `INFO store-generation-rebase ${outcome.previousGeneration ?? "unrecorded"}->${outcome.generation} ` + `rows_rewritten=${rowsRewritten} unresolved=${unresolved} derived=${outcome.compartmentsDerived} ` + `index_rows_rebuilt=${outcome.indexRowsRebuilt} drops_discarded=${outcome.queuedReductionsDiscarded} ` + `healed_gaps=${outcome.healedGaps} narrative_gaps=${outcome.narrativeGaps} ` + `ms=${Math.round(elapsedMs)} ` + `(chunk_windows_deleted=${outcome.chunkEmbeddingsDeleted} depth_rows_dropped=${outcome.compressionDepthRowsDropped} ` + `part_tags_folded=${outcome.partTagsFolded} lkg_slots_dropped=${outcome.lkgSlotsDropped} ` + `frozen_part_entries_dropped=${outcome.frozenPartEntriesDropped})`;
29381
29560
  }
29382
29561
  function planPriorBoundary(db, sessionId, plans) {
29383
29562
  const row = db.prepare("SELECT prior_boundary_ordinal FROM session_meta WHERE session_id = ?").get(sessionId);
@@ -29421,11 +29600,13 @@ function indexDisagreesWithProjection(db, sessionId, projection) {
29421
29600
  )`, sessionId);
29422
29601
  return orphanedMapRows > 0;
29423
29602
  }
29603
+ var repairCheckedSessions;
29424
29604
  var init_store_generation_rebase = __esm(async () => {
29425
29605
  init_logger();
29426
29606
  init_storage_meta_shared();
29427
29607
  init_storage_tags();
29428
29608
  await init_message_index();
29609
+ repairCheckedSessions = new WeakMap;
29429
29610
  });
29430
29611
 
29431
29612
  // src/hooks/magic-context/derive-budgets.ts
@@ -73985,7 +74166,12 @@ async function runGit(cwd, args) {
73985
74166
  encoding: "utf8"
73986
74167
  });
73987
74168
  return String(result.stdout);
73988
- } catch {
74169
+ } catch (error) {
74170
+ if (error.killed || error.code === "ETIMEDOUT") {
74171
+ throw new Error(`Git verification command timed out after ${GIT_TIMEOUT_MS2}ms`, {
74172
+ cause: error
74173
+ });
74174
+ }
73989
74175
  return null;
73990
74176
  }
73991
74177
  }
@@ -74408,6 +74594,45 @@ var init_note_nudger = __esm(() => {
74408
74594
  lastDeliveredAt = new Map;
74409
74595
  });
74410
74596
 
74597
+ // src/shared/safe-notification-target.ts
74598
+ function isDefaultSessionTitle(title) {
74599
+ return DEFAULT_TITLE_RE.test(title);
74600
+ }
74601
+ async function readSessionTitle(client, sessionId) {
74602
+ try {
74603
+ const c = client;
74604
+ if (typeof c.session?.get !== "function")
74605
+ return null;
74606
+ const raw = await Promise.resolve(c.session.get({ path: { id: sessionId } }));
74607
+ const obj = raw;
74608
+ const title = obj && typeof obj === "object" ? obj.data?.title ?? obj.title : undefined;
74609
+ return typeof title === "string" ? title : null;
74610
+ } catch {
74611
+ return null;
74612
+ }
74613
+ }
74614
+ async function waitForSafeNotificationTarget(client, sessionId, options) {
74615
+ const attempts = Math.max(1, options?.attempts ?? 4);
74616
+ const delayMs = options?.delayMs ?? 15000;
74617
+ for (let attempt = 0;attempt < attempts; attempt += 1) {
74618
+ const title = await readSessionTitle(client, sessionId);
74619
+ if (title === null)
74620
+ return "safe";
74621
+ if (!isDefaultSessionTitle(title))
74622
+ return "safe";
74623
+ if (attempt < attempts - 1) {
74624
+ await new Promise((resolve) => setTimeout(resolve, delayMs));
74625
+ }
74626
+ }
74627
+ log(`[magic-context] notification skipped: session ${sessionId} still has its default title (would suppress title generation); will retry on a later startup`);
74628
+ return "skip";
74629
+ }
74630
+ var DEFAULT_TITLE_RE;
74631
+ var init_safe_notification_target = __esm(() => {
74632
+ init_logger();
74633
+ DEFAULT_TITLE_RE = /^(New session - |Child session - )\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/;
74634
+ });
74635
+
74411
74636
  // src/shared/rpc-notifications.ts
74412
74637
  function registerNotificationSink(sink) {
74413
74638
  sinks.add(sink);
@@ -74508,45 +74733,6 @@ var init_rpc_notifications = __esm(() => {
74508
74733
  sinks = new Set;
74509
74734
  });
74510
74735
 
74511
- // src/shared/safe-notification-target.ts
74512
- function isDefaultSessionTitle(title) {
74513
- return DEFAULT_TITLE_RE.test(title);
74514
- }
74515
- async function readSessionTitle(client, sessionId) {
74516
- try {
74517
- const c = client;
74518
- if (typeof c.session?.get !== "function")
74519
- return null;
74520
- const raw = await Promise.resolve(c.session.get({ path: { id: sessionId } }));
74521
- const obj = raw;
74522
- const title = obj && typeof obj === "object" ? obj.data?.title ?? obj.title : undefined;
74523
- return typeof title === "string" ? title : null;
74524
- } catch {
74525
- return null;
74526
- }
74527
- }
74528
- async function waitForSafeNotificationTarget(client, sessionId, options) {
74529
- const attempts = Math.max(1, options?.attempts ?? 4);
74530
- const delayMs = options?.delayMs ?? 15000;
74531
- for (let attempt = 0;attempt < attempts; attempt += 1) {
74532
- const title = await readSessionTitle(client, sessionId);
74533
- if (title === null)
74534
- return "safe";
74535
- if (!isDefaultSessionTitle(title))
74536
- return "safe";
74537
- if (attempt < attempts - 1) {
74538
- await new Promise((resolve) => setTimeout(resolve, delayMs));
74539
- }
74540
- }
74541
- log(`[magic-context] notification skipped: session ${sessionId} still has its default title (would suppress title generation); will retry on a later startup`);
74542
- return "skip";
74543
- }
74544
- var DEFAULT_TITLE_RE;
74545
- var init_safe_notification_target = __esm(() => {
74546
- init_logger();
74547
- DEFAULT_TITLE_RE = /^(New session - |Child session - )\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/;
74548
- });
74549
-
74550
74736
  // src/shared/prompt-context.ts
74551
74737
  function isRecord6(value) {
74552
74738
  return typeof value === "object" && value !== null;
@@ -74908,6 +75094,7 @@ async function sendStatusNotification(_client, sessionId, text, params) {
74908
75094
  var MAX_QUEUED_IGNORED_NOTIFICATIONS = 16, queuedIgnoredNotifications, flushingIgnoredNotifications, idleSessions, lastDeliveredText, activityEpoch, defaultHoldDetector = (sessionId) => !idleSessions.has(sessionId) || shouldHoldIgnoredNotification(sessionId), holdDetector, notificationServerUrl, noticeDeleter, notificationDiagnosticObserverForTests;
74909
75095
  var init_send_session_notification = __esm(async () => {
74910
75096
  init_logger();
75097
+ init_safe_notification_target();
74911
75098
  await init_read_session_db();
74912
75099
  queuedIgnoredNotifications = new Map;
74913
75100
  flushingIgnoredNotifications = new Set;
@@ -75052,6 +75239,74 @@ var init_storage_user_memory = __esm(() => {
75052
75239
  USER_MEMORY_CANDIDATE_TTL_MS = 30 * 24 * 60 * 60 * 1000;
75053
75240
  });
75054
75241
 
75242
+ // src/shared/assistant-message-extractor.ts
75243
+ function asSessionMessage(value) {
75244
+ if (!isRecord3(value))
75245
+ return null;
75246
+ const info = value.info;
75247
+ const parts = value.parts;
75248
+ return {
75249
+ info: isRecord3(info) ? {
75250
+ role: typeof info.role === "string" ? info.role : undefined,
75251
+ time: isRecord3(info.time) ? {
75252
+ created: typeof info.time.created === "number" ? info.time.created : undefined
75253
+ } : undefined,
75254
+ error: info.error,
75255
+ finish: typeof info.finish === "string" ? info.finish : typeof info.finish_reason === "string" ? info.finish_reason : typeof info.finishReason === "string" ? info.finishReason : undefined
75256
+ } : undefined,
75257
+ parts
75258
+ };
75259
+ }
75260
+ function getCreatedTime(message) {
75261
+ return message.info?.time?.created ?? 0;
75262
+ }
75263
+ function getTextParts(message) {
75264
+ if (!Array.isArray(message.parts))
75265
+ return [];
75266
+ return message.parts.filter((part) => isRecord3(part)).map((part) => ({
75267
+ type: typeof part.type === "string" ? part.type : undefined,
75268
+ text: typeof part.text === "string" ? part.text : undefined
75269
+ })).filter((part) => part.type === "text" && Boolean(part.text));
75270
+ }
75271
+ function getLatestAssistantMessage(messages) {
75272
+ if (!Array.isArray(messages) || messages.length === 0)
75273
+ return null;
75274
+ return messages.map(asSessionMessage).filter((message) => message !== null).filter((message) => message.info?.role === "assistant").sort((a, b) => getCreatedTime(b) - getCreatedTime(a))[0] ?? null;
75275
+ }
75276
+ function extractLatestAssistantText(messages) {
75277
+ const latest = getLatestAssistantMessage(messages);
75278
+ if (!latest)
75279
+ return null;
75280
+ return getTextParts(latest).map((part) => part.text).join(`
75281
+ `) || null;
75282
+ }
75283
+ function extractLatestAssistantFailure(messages) {
75284
+ const latest = getLatestAssistantMessage(messages);
75285
+ if (!latest || latest.info?.error === undefined || latest.info.error === null)
75286
+ return null;
75287
+ return {
75288
+ error: latest.info.error,
75289
+ finish: latest.info.finish ?? null
75290
+ };
75291
+ }
75292
+ function hasLengthCappedOutput(value) {
75293
+ if (Array.isArray(value))
75294
+ return value.some((item) => hasLengthCappedOutput(item));
75295
+ if (!isRecord3(value))
75296
+ return false;
75297
+ if (value.length_capped === true || value.lengthCapped === true)
75298
+ return true;
75299
+ const finishReason = value.finish_reason ?? value.finishReason ?? value.finish ?? (value.type === "step-finish" ? value.reason : undefined) ?? value.stopReason;
75300
+ if (typeof finishReason === "string") {
75301
+ const normalized = finishReason.toLowerCase();
75302
+ if (normalized === "length" || normalized === "max_tokens" || normalized === "max_output_tokens") {
75303
+ return true;
75304
+ }
75305
+ }
75306
+ return Object.values(value).some((item) => hasLengthCappedOutput(item));
75307
+ }
75308
+ var init_assistant_message_extractor = () => {};
75309
+
75055
75310
  // src/shared/resolve-fallbacks.ts
75056
75311
  function parseProviderModel(spec) {
75057
75312
  const slash = spec.indexOf("/");
@@ -75343,6 +75598,17 @@ async function attemptAndValidate(client, args, timeoutMs, signal, callContext,
75343
75598
  };
75344
75599
  }
75345
75600
  try {
75601
+ if (!extractLatestAssistantText(output)) {
75602
+ const assistantFailure = extractLatestAssistantFailure(output);
75603
+ if (assistantFailure) {
75604
+ const error = new Error(`Host recorded assistant error: ${String(assistantFailure.error)}`);
75605
+ Object.assign(error, {
75606
+ name: "DreamerProviderOutputFailureError",
75607
+ transient: true
75608
+ });
75609
+ throw error;
75610
+ }
75611
+ }
75346
75612
  const validated = await options.validateOutput(output, attempt);
75347
75613
  return { output, validated, attempt };
75348
75614
  } catch (error) {
@@ -75429,6 +75695,7 @@ async function promptSyncWithValidatedOutputRetry(client, args, options) {
75429
75695
  var ABORT_CALL_TIMEOUT_MS = 3000, promptFailureDetails;
75430
75696
  var init_model_suggestion_retry = __esm(() => {
75431
75697
  init_overflow_detection();
75698
+ init_assistant_message_extractor();
75432
75699
  init_logger();
75433
75700
  init_redaction();
75434
75701
  promptFailureDetails = new WeakMap;
@@ -75463,14 +75730,14 @@ var CTX_REDUCE_LIGHT_DESCRIPTION = `Stamp an item as no longer needed for the wo
75463
75730
 
75464
75731
  // src/shared/prompt-surface-runtime.ts
75465
75732
  import { existsSync as existsSync12, readFileSync as readFileSync12, statSync as statSync12 } from "node:fs";
75466
- import { dirname as dirname8, isAbsolute as isAbsolute5, resolve as resolve5 } from "node:path";
75733
+ import { dirname as dirname8, isAbsolute as isAbsolute5, resolve as resolve6 } from "node:path";
75467
75734
  function promptSurfaceHashMaterial(systemContent, preset = "full") {
75468
75735
  return preset === "full" ? systemContent : `${systemContent}
75469
75736
  \x00magic-context-prompt-surface:${preset}`;
75470
75737
  }
75471
75738
  function resolveUserConfigDirectory(options) {
75472
75739
  if (options.userConfigDirectory)
75473
- return resolve5(options.userConfigDirectory);
75740
+ return resolve6(options.userConfigDirectory);
75474
75741
  const sharedBase = cortexKitUserConfigBasePath();
75475
75742
  const shared = detectConfigFile(sharedBase);
75476
75743
  if (shared.format !== "none")
@@ -75497,7 +75764,7 @@ function createPromptSurfaceRuntime(options) {
75497
75764
  const readGuidanceOverride = (configuredPath) => {
75498
75765
  if (!configuredPath)
75499
75766
  return;
75500
- const path = isAbsolute5(configuredPath) ? configuredPath : resolve5(userConfigDirectory, configuredPath);
75767
+ const path = isAbsolute5(configuredPath) ? configuredPath : resolve6(userConfigDirectory, configuredPath);
75501
75768
  let content;
75502
75769
  try {
75503
75770
  if (!statSync12(path).isFile()) {
@@ -75647,6 +75914,11 @@ var init_user_facing_codes = __esm(() => {
75647
75914
  sentence: "Some finished background sessions could not be removed from this host.",
75648
75915
  action: "They are removed automatically the next time Magic Context runs inside a registered OpenCode service."
75649
75916
  },
75917
+ historian_saved_history_misaligned: {
75918
+ code: "MC-H03",
75919
+ sentence: "History compression is paused because this session's saved summaries no longer line up with its messages.",
75920
+ action: "Run /ctx-recomp to rebuild them."
75921
+ },
75650
75922
  recomp_unavailable: {
75651
75923
  code: "MC-R01",
75652
75924
  sentence: "History compression could not be rebuilt.",
@@ -75817,6 +76089,11 @@ var init_user_facing_codes = __esm(() => {
75817
76089
  sentence: "History compression is paused while the engine syncs.",
75818
76090
  action: "Retry in a moment."
75819
76091
  },
76092
+ history_compression_needs_message: {
76093
+ code: "MC-C12",
76094
+ sentence: "History compression has not seen this session since Magic Context reconnected.",
76095
+ action: "Send a message in this session first, then run /ctx-wrapup again."
76096
+ },
75820
76097
  context_service_unavailable: {
75821
76098
  code: "MC-C10",
75822
76099
  sentence: "Magic Context is temporarily unavailable.",
@@ -77636,74 +77913,6 @@ var init_subagent_token_capture = __esm(() => {
77636
77913
  init_logger();
77637
77914
  });
77638
77915
 
77639
- // src/shared/assistant-message-extractor.ts
77640
- function asSessionMessage(value) {
77641
- if (!isRecord3(value))
77642
- return null;
77643
- const info = value.info;
77644
- const parts = value.parts;
77645
- return {
77646
- info: isRecord3(info) ? {
77647
- role: typeof info.role === "string" ? info.role : undefined,
77648
- time: isRecord3(info.time) ? {
77649
- created: typeof info.time.created === "number" ? info.time.created : undefined
77650
- } : undefined,
77651
- error: info.error,
77652
- finish: typeof info.finish === "string" ? info.finish : typeof info.finish_reason === "string" ? info.finish_reason : typeof info.finishReason === "string" ? info.finishReason : undefined
77653
- } : undefined,
77654
- parts
77655
- };
77656
- }
77657
- function getCreatedTime(message) {
77658
- return message.info?.time?.created ?? 0;
77659
- }
77660
- function getTextParts(message) {
77661
- if (!Array.isArray(message.parts))
77662
- return [];
77663
- return message.parts.filter((part) => isRecord3(part)).map((part) => ({
77664
- type: typeof part.type === "string" ? part.type : undefined,
77665
- text: typeof part.text === "string" ? part.text : undefined
77666
- })).filter((part) => part.type === "text" && Boolean(part.text));
77667
- }
77668
- function getLatestAssistantMessage(messages) {
77669
- if (!Array.isArray(messages) || messages.length === 0)
77670
- return null;
77671
- return messages.map(asSessionMessage).filter((message) => message !== null).filter((message) => message.info?.role === "assistant").sort((a, b) => getCreatedTime(b) - getCreatedTime(a))[0] ?? null;
77672
- }
77673
- function extractLatestAssistantText(messages) {
77674
- const latest = getLatestAssistantMessage(messages);
77675
- if (!latest)
77676
- return null;
77677
- return getTextParts(latest).map((part) => part.text).join(`
77678
- `) || null;
77679
- }
77680
- function extractLatestAssistantFailure(messages) {
77681
- const latest = getLatestAssistantMessage(messages);
77682
- if (!latest || latest.info?.error === undefined || latest.info.error === null)
77683
- return null;
77684
- return {
77685
- error: latest.info.error,
77686
- finish: latest.info.finish ?? null
77687
- };
77688
- }
77689
- function hasLengthCappedOutput(value) {
77690
- if (Array.isArray(value))
77691
- return value.some((item) => hasLengthCappedOutput(item));
77692
- if (!isRecord3(value))
77693
- return false;
77694
- if (value.length_capped === true || value.lengthCapped === true)
77695
- return true;
77696
- const finishReason = value.finish_reason ?? value.finishReason ?? value.finish ?? (value.type === "step-finish" ? value.reason : undefined) ?? value.stopReason;
77697
- if (typeof finishReason === "string") {
77698
- const normalized = finishReason.toLowerCase();
77699
- if (normalized === "length" || normalized === "max_tokens" || normalized === "max_output_tokens") {
77700
- return true;
77701
- }
77702
- }
77703
- return Object.values(value).some((item) => hasLengthCappedOutput(item));
77704
- }
77705
- var init_assistant_message_extractor = () => {};
77706
-
77707
77916
  // src/shared/keep-subagents.ts
77708
77917
  function shouldKeepSubagents() {
77709
77918
  return keepSubagents;
@@ -78014,6 +78223,14 @@ function buildHistorianFailureNotice(failureCount, _lastError) {
78014
78223
  return [heading, "", renderUserFacingFailure("historian_unavailable")].join(`
78015
78224
  `);
78016
78225
  }
78226
+ function buildStoredCompartmentsInvalidNotice() {
78227
+ return [
78228
+ "## Magic Context — History compression",
78229
+ "",
78230
+ renderUserFacingFailure("historian_saved_history_misaligned")
78231
+ ].join(`
78232
+ `);
78233
+ }
78017
78234
  function buildHistorianRepairPrompt(originalPrompt, previousOutput, validationError, language) {
78018
78235
  const prompt = [
78019
78236
  originalPrompt,
@@ -84697,6 +84914,12 @@ function v2NonNarrativeStoredGapRanges(db, sessionId, compartments) {
84697
84914
  }
84698
84915
  return safeRanges;
84699
84916
  }
84917
+ function storedCompartmentFailureBackingOff(db, sessionId, validationError, now = Date.now()) {
84918
+ if (getHistorianFailureState(db, sessionId).lastError !== validationError)
84919
+ return false;
84920
+ const failedAt = loadProtectedTailMeta(db, sessionId).historianDrainFailureAt;
84921
+ return failedAt > 0 && failedAt <= now && now - failedAt < STORED_COMPARTMENT_FAILURE_BACKOFF_MS;
84922
+ }
84700
84923
  function shouldSuppressHistorianAlert(sessionId) {
84701
84924
  const lastAlert = lastHistorianAlertBySession.get(sessionId);
84702
84925
  if (lastAlert && Date.now() - lastAlert < HISTORIAN_ALERT_COOLDOWN_MS) {
@@ -84819,13 +85042,37 @@ async function runCompartmentAgent(deps) {
84819
85042
  }
84820
85043
  return;
84821
85044
  }
84822
- const priorCompartments = getCompartments(db, sessionId);
84823
- const existingValidationError = validateStoredCompartments(priorCompartments, v2NonNarrativeStoredGapRanges(db, sessionId, priorCompartments));
85045
+ let priorCompartments = getCompartments(db, sessionId);
85046
+ let existingValidationError = validateStoredCompartments(priorCompartments, v2NonNarrativeStoredGapRanges(db, sessionId, priorCompartments));
85047
+ const unresolvedInvolved = existingValidationError !== null && priorCompartments.some((compartment) => compartment.rebaseStatus === "unresolved");
85048
+ if (unresolvedInvolved && existingValidationError && storedCompartmentFailureBackingOff(db, sessionId, existingValidationError)) {
85049
+ sessionLog(sessionId, `historian no-op: stored compartments still invalid ("${existingValidationError}"); backing off`);
85050
+ telemetry.status = "noop";
85051
+ telemetry.failureReason = `existing-validation backoff: ${existingValidationError}`;
85052
+ return;
85053
+ }
85054
+ if (unresolvedInvolved && existingValidationError) {
85055
+ const recovery = recoverUnresolvedCompartments({
85056
+ db,
85057
+ sessionId,
85058
+ resolveOrdinal: (messageId) => readRawSessionMessageOrdinalById(sessionId, messageId) ?? undefined,
85059
+ reason: `historian pre-run check failed: ${existingValidationError}`
85060
+ });
85061
+ if (recovery.rowsRewritten > 0) {
85062
+ priorCompartments = getCompartments(db, sessionId);
85063
+ existingValidationError = validateStoredCompartments(priorCompartments, v2NonNarrativeStoredGapRanges(db, sessionId, priorCompartments));
85064
+ }
85065
+ }
84824
85066
  if (existingValidationError) {
84825
85067
  sessionLog(sessionId, `historian failure: source=existing-validation reason="${existingValidationError}"`);
84826
85068
  const failCount = incrementHistorianFailure(db, sessionId, existingValidationError);
84827
85069
  telemetry.failureReason = `existing-validation: ${existingValidationError}`;
84828
- await notifyHistorianIssue(buildHistorianFailureNotice(failCount, existingValidationError));
85070
+ if (unresolvedInvolved) {
85071
+ retainDrainReservationForRetryThrottle = true;
85072
+ await notifyHistorianIssue(buildStoredCompartmentsInvalidNotice());
85073
+ } else {
85074
+ await notifyHistorianIssue(buildHistorianFailureNotice(failCount, existingValidationError));
85075
+ }
84829
85076
  return;
84830
85077
  }
84831
85078
  const offset = priorCompartments.length > 0 ? priorCompartments[priorCompartments.length - 1].endMessage + 1 : 1;
@@ -85308,7 +85555,7 @@ ${chunkText}`,
85308
85555
  cleanupHistorianStateFile(stateFilePath);
85309
85556
  }
85310
85557
  }
85311
- var inconsistentProducerWindows, HISTORIAN_ALERT_COOLDOWN_MS, lastHistorianAlertBySession;
85558
+ var inconsistentProducerWindows, HISTORIAN_ALERT_COOLDOWN_MS, lastHistorianAlertBySession, STORED_COMPARTMENT_FAILURE_BACKOFF_MS;
85312
85559
  var init_compartment_runner_incremental = __esm(async () => {
85313
85560
  init_compartment_embedding();
85314
85561
  init_compartment_events();
@@ -85351,6 +85598,7 @@ var init_compartment_runner_incremental = __esm(async () => {
85351
85598
  inconsistentProducerWindows = new Set;
85352
85599
  HISTORIAN_ALERT_COOLDOWN_MS = 60 * 1000;
85353
85600
  lastHistorianAlertBySession = new Map;
85601
+ STORED_COMPARTMENT_FAILURE_BACKOFF_MS = 30 * 60 * 1000;
85354
85602
  });
85355
85603
 
85356
85604
  // src/hooks/magic-context/compartment-runner-recomp.ts
@@ -106952,6 +107200,8 @@ var TODOWRITE_TOOL = "todowrite";
106952
107200
  var availabilityBySession = new BoundedSessionMap(1000);
106953
107201
  var permissionDeniedBySession = new BoundedSessionMap(2000);
106954
107202
  var ctxReducePermissionDenyLogged = new BoundedSessionMap(1000);
107203
+ var ctxReduceSpawnPermissionDenied = new BoundedSessionMap(1000);
107204
+ var ctxReduceSpawnPermissionReads = new Map;
106955
107205
  function permissionCacheKey(toolName, sessionId) {
106956
107206
  return `${toolName}\x00${sessionId}`;
106957
107207
  }
@@ -106970,6 +107220,12 @@ function verdictFromToolsMap(tools, toolName) {
106970
107220
  return false;
106971
107221
  return null;
106972
107222
  }
107223
+ function unfrozenVerdict(sessionId, toolName, mapVerdict) {
107224
+ if (toolName === CTX_REDUCE_TOOL && ctxReduceSpawnPermissionDenied.get(sessionId) === true) {
107225
+ return false;
107226
+ }
107227
+ return mapVerdict ?? true;
107228
+ }
106973
107229
  function resolveToolAvailabilityFromMessages(sessionId, toolName, messages) {
106974
107230
  if (toolName === CTX_REDUCE_TOOL && !ctxReduceRegisteredGlobally) {
106975
107231
  return { callable: false, frozen: true };
@@ -106981,7 +107237,7 @@ function resolveToolAvailabilityFromMessages(sessionId, toolName, messages) {
106981
107237
  for (const message of messages) {
106982
107238
  if (message.info?.role !== "user")
106983
107239
  continue;
106984
- const verdict = verdictFromToolsMap(message.info.tools, toolName) ?? true;
107240
+ const verdict = unfrozenVerdict(sessionId, toolName, verdictFromToolsMap(message.info.tools, toolName));
106985
107241
  availabilityBySession.set(key, verdict);
106986
107242
  return { callable: verdict, frozen: true };
106987
107243
  }
@@ -107004,7 +107260,7 @@ function resolveToolAvailability(sessionId, toolName) {
107004
107260
  if (!row)
107005
107261
  return { callable: true, frozen: false };
107006
107262
  const verdict = row.tools === null ? null : verdictFromToolsMap(JSON.parse(row.tools), toolName);
107007
- const resolved = verdict ?? true;
107263
+ const resolved = unfrozenVerdict(sessionId, toolName, verdict);
107008
107264
  availabilityBySession.set(key, resolved);
107009
107265
  return { callable: resolved, frozen: true };
107010
107266
  } catch (error) {
@@ -107120,6 +107376,58 @@ async function resolveToolPermissionDenied(client, sessionId, toolName, activeAg
107120
107376
  permissionDeniedBySession.set(permissionCacheKey(toolName, sessionId), denied);
107121
107377
  return denied;
107122
107378
  }
107379
+ function primeCtxReduceSpawnPermission(client, sessionId, spawnAgent) {
107380
+ if (!ctxReduceSpawnPermissionReadNeeded(sessionId))
107381
+ return Promise.resolve();
107382
+ const inFlight = ctxReduceSpawnPermissionReads.get(sessionId);
107383
+ if (inFlight)
107384
+ return inFlight;
107385
+ const read = (async () => {
107386
+ try {
107387
+ const denied = await resolveToolPermissionDenied(client, sessionId, CTX_REDUCE_TOOL, spawnAgent);
107388
+ ctxReduceSpawnPermissionDenied.set(sessionId, denied);
107389
+ if (denied) {
107390
+ sessionLog(sessionId, `ctx_reduce permission is denied for agent=${spawnAgent ?? "(session default)"}; session freezes without ctx_reduce tags, guidance, or nudges`);
107391
+ }
107392
+ } catch (error) {
107393
+ sessionLog(sessionId, "ctx_reduce permission read before freeze failed (fail-open):", error);
107394
+ } finally {
107395
+ ctxReduceSpawnPermissionReads.delete(sessionId);
107396
+ }
107397
+ })();
107398
+ ctxReduceSpawnPermissionReads.set(sessionId, read);
107399
+ return read;
107400
+ }
107401
+ function ctxReduceSpawnPermissionReadNeeded(sessionId) {
107402
+ return ctxReduceRegisteredGlobally && availabilityBySession.get(cacheKey2(CTX_REDUCE_TOOL, sessionId)) === undefined && ctxReduceSpawnPermissionDenied.get(sessionId) === undefined;
107403
+ }
107404
+ function spawnAgentFromMessages(messages) {
107405
+ for (const message of messages) {
107406
+ if (message.info?.role !== "user")
107407
+ continue;
107408
+ const agent = message.info.agent;
107409
+ return typeof agent === "string" && agent.length > 0 ? agent : undefined;
107410
+ }
107411
+ return;
107412
+ }
107413
+ function spawnAgentFromOpenCodeDb(sessionId) {
107414
+ if (!openCodeDbExists())
107415
+ return { persisted: false };
107416
+ try {
107417
+ const row = withReadOnlySessionDb((db) => db.prepare(`SELECT json_extract(data, '$.agent') AS agent FROM message
107418
+ WHERE session_id = ? AND json_extract(data, '$.role') = 'user'
107419
+ ORDER BY time_created ASC LIMIT 1`).get(sessionId));
107420
+ if (!row)
107421
+ return { persisted: false };
107422
+ return {
107423
+ persisted: true,
107424
+ agent: typeof row.agent === "string" && row.agent.length > 0 ? row.agent : undefined
107425
+ };
107426
+ } catch (error) {
107427
+ sessionLog(sessionId, "ctx_reduce spawn agent read failed:", error);
107428
+ return { persisted: false };
107429
+ }
107430
+ }
107123
107431
  function todowritePermissionDenied(client, sessionId, activeAgent) {
107124
107432
  return resolveToolPermissionDenied(client, sessionId, TODOWRITE_TOOL, activeAgent);
107125
107433
  }
@@ -108022,9 +108330,26 @@ init_window_geometry();
108022
108330
  init_compartment_storage();
108023
108331
  init_session_decision_calibration();
108024
108332
  init_logger();
108333
+ await init_storage();
108334
+
108335
+ // src/hooks/magic-context/cache-busting-signals.ts
108336
+ function canConsumeDeferredOnThisPass(args) {
108337
+ if (args.justAwaitedPublication)
108338
+ return true;
108339
+ return args.schedulerDecision === "execute" || args.contextPercentage >= (args.forceMaterializationPercentage ?? escalationBands(65).forceMaterializationPercentage);
108340
+ }
108341
+ function hasReclaimRide(signals) {
108342
+ return signals.hardFold || signals.force || signals.explicitFlush || signals.publishedHistory;
108343
+ }
108344
+ var RECLAIM_RIDE_NAMES = ["hardFold", "force", "explicitFlush", "publishedHistory"];
108345
+ function reclaimRideLabel(signals) {
108346
+ const active = RECLAIM_RIDE_NAMES.filter((name) => signals[name]);
108347
+ return `ride=${active.length > 0 ? active.join("+") : "none"}`;
108348
+ }
108349
+
108350
+ // src/hooks/magic-context/compartment-trigger.ts
108025
108351
  init_read_session_true_raw_tokens();
108026
108352
  await __promiseAll([
108027
- init_storage(),
108028
108353
  init_protected_tail_boundary(),
108029
108354
  init_read_session_chunk()
108030
108355
  ]);
@@ -108204,7 +108529,7 @@ function getUnsummarizedTailInfo(db, sessionId, triggerBudget, usage, executeThr
108204
108529
  function formatProjectedPostDropPercentage(value) {
108205
108530
  return value === null ? "none" : `${value.toFixed(1)}%`;
108206
108531
  }
108207
- function checkCompartmentTrigger(db, sessionId, sessionMeta, usage, _previousPercentage, executeThresholdPercentage, triggerBudget, clearReasoningAge, commitClusterTrigger, preloadedActiveTags, contextLimit, inMemoryTail, taggerFloorOverride, reasoningProjection) {
108532
+ function checkCompartmentTrigger(db, sessionId, sessionMeta, usage, _previousPercentage, executeThresholdPercentage, triggerBudget, clearReasoningAge, commitClusterTrigger, preloadedActiveTags, contextLimit, inMemoryTail, taggerFloorOverride, reasoningProjection, reclaimRide) {
108208
108533
  if (sessionMeta.compartmentInProgress) {
108209
108534
  sessionLog(sessionId, `compartment trigger: skipped — historian already in progress (usage=${usage.percentage.toFixed(1)}%)`);
108210
108535
  return { shouldFire: false };
@@ -108262,10 +108587,12 @@ function checkCompartmentTrigger(db, sessionId, sessionMeta, usage, _previousPer
108262
108587
  const canClearReasoning = reasoningProjection?.canClearReasoning ?? modelAcceptsEmptyContent(reasoningProjection?.providerID);
108263
108588
  const projectedPostDropPercentage = estimateProjectedPostDropPercentage(db, sessionId, usage, preloadedActiveTags ?? getActiveTagsBySession(db, sessionId), clearReasoningAge, sessionMeta.clearedReasoningThroughTag, canClearReasoning);
108264
108589
  const relativePostDropTarget = executeThresholdPercentage * POST_DROP_TARGET_RATIO;
108590
+ const rideLabel = reclaimRide ? reclaimRideLabel(reclaimRide) : "ride=none";
108591
+ const dropsCanLand = reclaimRide !== undefined && hasReclaimRide(reclaimRide);
108265
108592
  const forceMaterializationPercentage = escalationBands(executeThresholdPercentage).forceMaterializationPercentage;
108266
108593
  if (usage.percentage >= forceMaterializationPercentage) {
108267
- if (projectedPostDropPercentage !== null && projectedPostDropPercentage <= relativePostDropTarget) {
108268
- sessionLog(sessionId, `historian redundancy skip: summarizer not needed this pass — force band is ${forceMaterializationPercentage}%; queued/automatic drops are projected to reclaim to ${projectedPostDropPercentage.toFixed(1)}% (target ${relativePostDropTarget.toFixed(1)}%) on the next eligible execute pass`);
108594
+ if (dropsCanLand && projectedPostDropPercentage !== null && projectedPostDropPercentage <= relativePostDropTarget) {
108595
+ sessionLog(sessionId, `historian redundancy skip: summarizer not needed this pass — force band is ${forceMaterializationPercentage}%; queued/automatic drops are projected to reclaim to ${projectedPostDropPercentage.toFixed(1)}% (target ${relativePostDropTarget.toFixed(1)}%) on this pass (${rideLabel})`);
108269
108596
  return { shouldFire: false };
108270
108597
  }
108271
108598
  sessionLog(sessionId, `compartment trigger: force-firing at ${usage.percentage.toFixed(1)}% (projected post-drop ${formatProjectedPostDropPercentage(projectedPostDropPercentage)})`);
@@ -108325,8 +108652,8 @@ function checkCompartmentTrigger(db, sessionId, sessionMeta, usage, _previousPer
108325
108652
  sessionLog(sessionId, `compartment trigger: not firing at ${usage.percentage.toFixed(1)}% — below proactive floor (${proactiveTriggerPercentage}%)`);
108326
108653
  return { shouldFire: false };
108327
108654
  }
108328
- if (projectedPostDropPercentage !== null && projectedPostDropPercentage <= relativePostDropTarget) {
108329
- sessionLog(sessionId, `historian redundancy skip: summarizer not needed this pass — usage is ${usage.percentage.toFixed(1)}%; queued/automatic drops are projected to reclaim to ${projectedPostDropPercentage.toFixed(1)}% (target ${relativePostDropTarget.toFixed(1)}%) on the next eligible execute pass`);
108655
+ if (dropsCanLand && projectedPostDropPercentage !== null && projectedPostDropPercentage <= relativePostDropTarget) {
108656
+ sessionLog(sessionId, `historian redundancy skip: summarizer not needed this pass — usage is ${usage.percentage.toFixed(1)}%; queued/automatic drops are projected to reclaim to ${projectedPostDropPercentage.toFixed(1)}% (target ${relativePostDropTarget.toFixed(1)}%) on this pass (${rideLabel})`);
108330
108657
  return { shouldFire: false };
108331
108658
  }
108332
108659
  if (!tailInfo.hasProtectedEligibleHead || !tailInfo.isMeaningful) {
@@ -108869,6 +109196,12 @@ function createSystemPromptHashHandler(deps) {
108869
109196
  sessionLog(sessionId, "system-prompt-hash session meta load failed:", error);
108870
109197
  }
108871
109198
  const isSubagentSession = sessionMetaEarly?.isSubagent === true;
109199
+ if (deps.client && ctxReduceSpawnPermissionReadNeeded(sessionId)) {
109200
+ const spawn = spawnAgentFromOpenCodeDb(sessionId);
109201
+ if (spawn.persisted) {
109202
+ await primeCtxReduceSpawnPermission(deps.client, sessionId, spawn.agent);
109203
+ }
109204
+ }
108872
109205
  const availability = resolveCtxReduceAvailability(sessionId);
108873
109206
  const ctxReduceCallable = availability.callable;
108874
109207
  const subagentReduceMode = isSubagentSession && ctxReduceCallable;
@@ -109081,21 +109414,6 @@ init_harness_provider_map();
109081
109414
  init_logger();
109082
109415
  init_models_dev_cache();
109083
109416
 
109084
- // src/hooks/magic-context/cache-busting-signals.ts
109085
- function canConsumeDeferredOnThisPass(args) {
109086
- if (args.justAwaitedPublication)
109087
- return true;
109088
- return args.schedulerDecision === "execute" || args.contextPercentage >= (args.forceMaterializationPercentage ?? escalationBands(65).forceMaterializationPercentage);
109089
- }
109090
- function hasReclaimRide(signals) {
109091
- return signals.hardFold || signals.force || signals.explicitFlush || signals.publishedHistory;
109092
- }
109093
- var RECLAIM_RIDE_NAMES = ["hardFold", "force", "explicitFlush", "publishedHistory"];
109094
- function reclaimRideLabel(signals) {
109095
- const active = RECLAIM_RIDE_NAMES.filter((name) => signals[name]);
109096
- return `ride=${active.length > 0 ? active.join("+") : "none"}`;
109097
- }
109098
-
109099
109417
  // src/hooks/magic-context/caveman-cleanup.ts
109100
109418
  init_shared();
109101
109419
  await init_storage();
@@ -115888,7 +116206,7 @@ function rustCaptureDigests(inputs, prior, acceptedInputs) {
115888
116206
  }
115889
116207
  function messageMatchesContentSnapshot(message, snapshot) {
115890
116208
  let fieldIndex = 0;
115891
- const matched = visitMessageContentFields(message, {
116209
+ const matched = visitMessageContentFields(contentSnapshotValue(message), {
115892
116210
  field(value) {
115893
116211
  if (!Object.is(value, snapshot.fields[fieldIndex]))
115894
116212
  return false;
@@ -116143,6 +116461,7 @@ function ensureState(states, sessionId) {
116143
116461
  if (!state) {
116144
116462
  state = {
116145
116463
  initialized: false,
116464
+ baselineSystemHashOmitted: false,
116146
116465
  consecutiveFailures: 0,
116147
116466
  passCount: 0,
116148
116467
  parked: false,
@@ -117104,6 +117423,7 @@ function createRustModeTransform(deps, options) {
117104
117423
  }
117105
117424
  }
117106
117425
  timings.preflight = performance.now() - passStartedAt;
117426
+ resolveCtxReduceAvailabilityFromMessages(sessionId, messages);
117107
117427
  const reduceAvailability = resolveCtxReduceAvailability(sessionId);
117108
117428
  resolveTodowriteAvailabilityFromMessages(sessionId, messages);
117109
117429
  const todoAvailability = resolveTodowriteAvailability(sessionId);
@@ -117175,6 +117495,8 @@ function createRustModeTransform(deps, options) {
117175
117495
  }
117176
117496
  const effectiveFloor = protectionFloorResolution.floor;
117177
117497
  const historianRun = deps.resolveHistorianRun?.();
117498
+ const observedSystemHash = sessionMeta.systemPromptHash ?? "";
117499
+ const rustSystemHash = state.baselineSystemHashOmitted && sessionMeta.cachedM0SystemHash === observedSystemHash ? "" : observedSystemHash;
117178
117500
  const passInputs = {
117179
117501
  now_ms: requestObservedAtMs,
117180
117502
  model_key: modelKey,
@@ -117196,7 +117518,7 @@ function createRustModeTransform(deps, options) {
117196
117518
  caveman_min_chars: deps.cavemanTextCompression?.minChars ?? 500,
117197
117519
  cache_ttl: sessionMeta.cacheTtl,
117198
117520
  is_subagent: sessionMeta.isSubagent,
117199
- system_prompt_hash: sessionMeta.systemPromptHash ?? "",
117521
+ system_prompt_hash: rustSystemHash,
117200
117522
  upgrade_state: readUpgradeState(deps.db, sessionId),
117201
117523
  tool_present: toolPresent,
117202
117524
  todo_tool_present: false,
@@ -117471,7 +117793,7 @@ function createRustModeTransform(deps, options) {
117471
117793
  modelKey: modelKey ?? null,
117472
117794
  providerId: model?.providerID ?? null,
117473
117795
  variant: deps.variantBySession?.get(sessionId),
117474
- systemPromptHash: sessionMeta.systemPromptHash ?? "",
117796
+ systemPromptHash: rustSystemHash,
117475
117797
  upgradeState: String(passInputs.upgrade_state ?? "")
117476
117798
  };
117477
117799
  let body = buildTransformBody({
@@ -117905,6 +118227,9 @@ function createRustModeTransform(deps, options) {
117905
118227
  state.ordinalContinuationBase = ordinalContinuationBase;
117906
118228
  }
117907
118229
  if (!stateSyncRetryBusy) {
118230
+ if (!state.initialized && !observedSystemHash) {
118231
+ state.baselineSystemHashOmitted = true;
118232
+ }
117908
118233
  state.initialized = true;
117909
118234
  state.seedPassPending = false;
117910
118235
  }
@@ -118701,6 +119026,9 @@ function createTransform(deps) {
118701
119026
  passOutcome.record("compaction-mode-transition-failure");
118702
119027
  sessionLog(sessionId, "compaction mode transition failed (retrying next pass):", error);
118703
119028
  }
119029
+ if (deps.client !== undefined && !compactionOff) {
119030
+ await primeCtxReduceSpawnPermission(deps.client, sessionId, spawnAgentFromMessages(messages));
119031
+ }
118704
119032
  if (deps.transformMode === "rust") {
118705
119033
  if (!rustModeTransform) {
118706
119034
  sessionLog(sessionId, "rust transform unavailable; using raw passthrough");
@@ -119033,7 +119361,12 @@ Historian previously failed ${historianFailureState.failureCount} time(s), so Ma
119033
119361
  const tTrigger = performance.now();
119034
119362
  try {
119035
119363
  const inMemoryTail = buildTriggerInMemoryTail(db, sessionId, extractInMemoryMessageViews(messages));
119036
- const triggerResult = checkCompartmentTrigger(db, sessionId, sessionMeta, boundaryUsageForProtectedTail, sessionMeta.lastContextPercentage, boundaryExecuteThreshold, deriveTriggerBudget(boundaryContextLimit, boundaryExecuteThreshold), deps.clearReasoningAge, historianRun?.commitClusterTrigger ?? deps.commitClusterTrigger, undefined, boundaryContextLimit, inMemoryTail, taggerFloor, { providerID: resolvedProviderID });
119364
+ const triggerResult = checkCompartmentTrigger(db, sessionId, sessionMeta, boundaryUsageForProtectedTail, sessionMeta.lastContextPercentage, boundaryExecuteThreshold, deriveTriggerBudget(boundaryContextLimit, boundaryExecuteThreshold), deps.clearReasoningAge, historianRun?.commitClusterTrigger ?? deps.commitClusterTrigger, undefined, boundaryContextLimit, inMemoryTail, taggerFloor, { providerID: resolvedProviderID }, {
119365
+ hardFold: false,
119366
+ force: contextUsageEarly.percentage >= forceMaterializationPercentage && (contextUsageEarly.percentage >= 95 || getEmergencyInputSample(db, sessionId) === 0),
119367
+ explicitFlush: deps.pendingMaterializationSessions.has(sessionId),
119368
+ publishedHistory: isCacheBusting
119369
+ });
119037
119370
  if (triggerResult.shouldFire) {
119038
119371
  sessionLog(sessionId, `compartment trigger: firing (reason=${triggerResult.reason})`);
119039
119372
  updateSessionMeta(db, sessionId, { compartmentInProgress: true });
@@ -121720,7 +122053,7 @@ import { join as join15 } from "node:path";
121720
122053
 
121721
122054
  // src/shared/opencode-config-dir.ts
121722
122055
  import { homedir as homedir9 } from "node:os";
121723
- import { join as join14, resolve as resolve6 } from "node:path";
122056
+ import { join as join14, resolve as resolve7 } from "node:path";
121724
122057
  function resolveHomeDir() {
121725
122058
  return process.env.HOME?.trim() || homedir9();
121726
122059
  }
@@ -121732,7 +122065,7 @@ function getOpenCodeGlobalConfigDir() {
121732
122065
  }
121733
122066
  function getEnvConfigDir() {
121734
122067
  const envConfigDir = process.env.OPENCODE_CONFIG_DIR?.trim();
121735
- return envConfigDir ? resolve6(envConfigDir) : undefined;
122068
+ return envConfigDir ? resolve7(envConfigDir) : undefined;
121736
122069
  }
121737
122070
  function getOpenCodeConfigDirs() {
121738
122071
  const dirs = [getOpenCodeGlobalConfigDir(), join14(resolveHomeDir(), ".opencode")];
@@ -122771,9 +123104,33 @@ init_tag_content_primitives();
122771
123104
  var HIDDEN_HISTORIAN_AGENT = "historian";
122772
123105
  var HIDDEN_DREAMER_AGENT = "dreamer-classifier";
122773
123106
  var HIDDEN_CURATE_AGENT = DREAMER_AGENT;
123107
+ var READ_TOOLS = ["read", "grep", "glob"];
123108
+ var AGENT_TOOLS = {
123109
+ [HIDDEN_HISTORIAN_AGENT]: [],
123110
+ [HIDDEN_DREAMER_AGENT]: [],
123111
+ [HIDDEN_CURATE_AGENT]: ["ctx_memory", "ctx_memory_list"],
123112
+ [DREAMER_MEMORY_MAPPER_AGENT]: READ_TOOLS,
123113
+ [DREAMER_PRIMER_INVESTIGATOR_AGENT]: [...READ_TOOLS, "ctx_search"],
123114
+ [DREAMER_RETROSPECTIVE_AGENT]: ["ctx_search"]
123115
+ };
123116
+ var AGENT_STEPS = {
123117
+ [HIDDEN_CURATE_AGENT]: 150,
123118
+ [DREAMER_MEMORY_MAPPER_AGENT]: 60,
123119
+ [DREAMER_DOCS_AGENT]: 60,
123120
+ [DREAMER_PRIMER_INVESTIGATOR_AGENT]: 40,
123121
+ [DREAMER_RETROSPECTIVE_AGENT]: 40
123122
+ };
123123
+ function hiddenAgentFor(identity) {
123124
+ if (identity.kind === "dreamer-task" && identity.agent === DREAMER_DOCS_AGENT)
123125
+ return DREAMER_MEMORY_MAPPER_AGENT;
123126
+ return identity.kind === "dreamer-task" && AGENT_TOOLS[identity.agent] ? identity.agent : identity.kind === "dreamer-task" ? HIDDEN_DREAMER_AGENT : HIDDEN_HISTORIAN_AGENT;
123127
+ }
123128
+ function hiddenToolLoop(identity) {
123129
+ return identity.kind === "dreamer-task" && AGENT_STEPS[identity.agent] !== undefined;
123130
+ }
122774
123131
  async function registerHiddenChildAgents(agent) {
122775
123132
  await agent.transform((editor) => {
122776
- for (const id of [HIDDEN_HISTORIAN_AGENT, HIDDEN_DREAMER_AGENT, HIDDEN_CURATE_AGENT]) {
123133
+ for (const id of Object.keys(AGENT_TOOLS)) {
122777
123134
  editor.update(id, (config) => {
122778
123135
  config.system = "Magic Context hidden completion carrier.";
122779
123136
  config.description = "Internal Magic Context hidden completion carrier.";
@@ -122782,16 +123139,14 @@ async function registerHiddenChildAgents(agent) {
122782
123139
  config.request.settings = {};
122783
123140
  config.request.headers = {};
122784
123141
  config.request.body = {};
123142
+ config.steps = AGENT_STEPS[id];
122785
123143
  config.permissions = [
122786
123144
  { action: "*", resource: "*", effect: "deny" },
122787
- ...id === HIDDEN_CURATE_AGENT ? [
122788
- { action: "tool", resource: "ctx_memory", effect: "allow" },
122789
- {
122790
- action: "tool",
122791
- resource: "ctx_memory_list",
122792
- effect: "allow"
122793
- }
122794
- ] : []
123145
+ ...(AGENT_TOOLS[id] ?? []).map((tool) => ({
123146
+ action: tool,
123147
+ resource: "*",
123148
+ effect: "allow"
123149
+ }))
122795
123150
  ];
122796
123151
  });
122797
123152
  }
@@ -122836,15 +123191,21 @@ function calibratedParts(attempt) {
122836
123191
  class HiddenChildHook {
122837
123192
  childIDs = new Set;
122838
123193
  attempts = new Map;
123194
+ active = new Map;
122839
123195
  registerChild(sessionID) {
122840
123196
  this.childIDs.add(sessionID);
122841
123197
  }
122842
123198
  registerAttempt(marker, attempt) {
122843
123199
  this.registerChild(attempt.childSessionId);
123200
+ attempt.marker = marker;
122844
123201
  this.attempts.set(marker, attempt);
122845
123202
  }
122846
123203
  releaseAttempt(marker) {
123204
+ const attempt = this.attempts.get(marker);
122847
123205
  this.attempts.delete(marker);
123206
+ if (attempt && this.active.get(attempt.childSessionId) === attempt) {
123207
+ this.active.delete(attempt.childSessionId);
123208
+ }
122848
123209
  }
122849
123210
  owns(sessionID) {
122850
123211
  return this.childIDs.has(sessionID);
@@ -122855,19 +123216,43 @@ class HiddenChildHook {
122855
123216
  const raw = newestUserText(draft);
122856
123217
  const stripped = raw === undefined ? undefined : stripWellFormedLeadingTagPrefix(raw);
122857
123218
  const attempt = (raw !== undefined ? this.attempts.get(raw) : undefined) ?? (stripped && stripped !== raw ? this.attempts.get(stripped) : undefined);
122858
- if (!attempt || attempt.childSessionId !== draft.sessionID) {
123219
+ const current = this.active.get(draft.sessionID);
123220
+ const selected = attempt ?? current;
123221
+ if (!selected || selected.childSessionId !== draft.sessionID || attempt && current && current !== attempt) {
122859
123222
  throw new HiddenCompletionRefusal("hidden_prompt_unrecognized", "Refusing an unregistered prompt on a Magic Context hidden-run session", true);
122860
123223
  }
122861
- if (attempt.request.signal?.aborted) {
123224
+ if (selected.request.signal?.aborted) {
122862
123225
  throw new Error("Hidden completion prompt aborted");
122863
123226
  }
122864
- const system = typeof attempt.request.body.system === "string" ? attempt.request.body.system : attempt.identity.system;
123227
+ if (!selected.shaped) {
123228
+ if (!attempt)
123229
+ throw new HiddenCompletionRefusal("hidden_prompt_unrecognized", "Hidden child first step requires a registered marker", true);
123230
+ this.active.set(draft.sessionID, selected);
123231
+ }
123232
+ const steps = (selected.steps ?? 0) + 1;
123233
+ const cap = AGENT_STEPS[selected.identity.agent];
123234
+ if (cap !== undefined && steps > cap) {
123235
+ throw new Error(`Hidden agent exceeded its ${cap}-step limit`);
123236
+ }
123237
+ selected.steps = steps;
123238
+ const system = typeof selected.request.body.system === "string" ? selected.request.body.system : selected.identity.system;
122865
123239
  draft.system = [{ type: "text", text: system }];
122866
- draft.messages = [{ role: "user", content: calibratedParts(attempt) }];
122867
- draft.options = authoredOptions(attempt);
122868
- const dreamerTools = attempt.identity.agent === DREAMER_AGENT ? Object.fromEntries(["ctx_memory", "ctx_memory_list"].flatMap((id) => draft.tools[id] ? [[id, draft.tools[id]]] : [])) : {};
122869
- draft.tools = dreamerTools;
122870
- attempt.shaped = true;
123240
+ if (!selected.shaped) {
123241
+ draft.messages = [{ role: "user", content: calibratedParts(selected) }];
123242
+ } else {
123243
+ const first = draft.messages[0];
123244
+ const firstText = first && newestUserText({ ...draft, messages: [first] });
123245
+ const normalized = firstText === undefined ? undefined : stripWellFormedLeadingTagPrefix(firstText);
123246
+ if (normalized !== selected.marker) {
123247
+ throw new HiddenCompletionRefusal("hidden_prompt_unrecognized", "Hidden child history does not begin with this run's registered marker", true);
123248
+ }
123249
+ draft.messages[0] = { ...first, content: calibratedParts(selected) };
123250
+ }
123251
+ draft.options = authoredOptions(selected);
123252
+ const allowed = AGENT_TOOLS[hiddenAgentFor(selected.identity)] ?? [];
123253
+ draft.tools = Object.fromEntries(allowed.flatMap((id) => draft.tools[id] ? [[id, draft.tools[id]]] : []));
123254
+ selected.observedMessages = draft.messages;
123255
+ selected.shaped = true;
122871
123256
  return true;
122872
123257
  }
122873
123258
  }
@@ -122949,9 +123334,9 @@ function resolveOwnerHostService(owner, env = process.env, pid = process.pid) {
122949
123334
  }
122950
123335
  return own;
122951
123336
  }
122952
- async function removeHostSession(sessionID, owner, env = process.env) {
123337
+ async function removeHostSession(sessionID, owner, env = process.env, fetchSession = fetch) {
122953
123338
  const service = resolveOwnerHostService(owner, env);
122954
- const response = await fetch(`${service.url}/api/session/${encodeURIComponent(sessionID)}`, {
123339
+ const response = await fetchSession(`${service.url}/api/session/${encodeURIComponent(sessionID)}`, {
122955
123340
  method: "DELETE",
122956
123341
  headers: service.headers,
122957
123342
  signal: AbortSignal.timeout(60000)
@@ -123153,6 +123538,37 @@ function settledProviderError(row) {
123153
123538
  function successfulReusableAssistant(row) {
123154
123539
  return row !== undefined && (typeof row.data.finish === "string" || assistantOutcome(row) === "succeeded") && row.data.error === undefined && row.data.tokens !== undefined;
123155
123540
  }
123541
+ function toolLoopMessages(attempt) {
123542
+ const messages = attempt.observedMessages ?? [];
123543
+ const results = new Map;
123544
+ for (const message of messages) {
123545
+ if (message.role !== "tool")
123546
+ continue;
123547
+ for (const part of message.content) {
123548
+ if (part.type !== "tool-result" || typeof part.id !== "string")
123549
+ continue;
123550
+ const result = part.result;
123551
+ results.set(part.id, { status: result?.type === "error" ? "error" : "completed" });
123552
+ }
123553
+ }
123554
+ return messages.flatMap((message) => {
123555
+ if (message.role !== "assistant")
123556
+ return [];
123557
+ const parts = message.content.flatMap((part) => {
123558
+ if (part.type !== "tool-call" || typeof part.id !== "string" || typeof part.name !== "string")
123559
+ return [];
123560
+ const result = results.get(part.id);
123561
+ return [
123562
+ {
123563
+ type: "tool",
123564
+ tool: part.name,
123565
+ state: { status: result?.status ?? "pending", input: part.input }
123566
+ }
123567
+ ];
123568
+ });
123569
+ return parts.length ? [{ info: { role: "assistant" }, parts }] : [];
123570
+ });
123571
+ }
123156
123572
  function assistantText(row) {
123157
123573
  const text = (row.data.content ?? []).flatMap((part) => part.type === "text" && typeof part.text === "string" ? [part.text] : []).join("");
123158
123574
  return text.length > 0 ? text : null;
@@ -123404,7 +123820,7 @@ async function createV2HiddenCompletionExecutor(host, options) {
123404
123820
  }
123405
123821
  };
123406
123822
  return {
123407
- capabilities: { tools: false, harness: "opencode2" },
123823
+ capabilities: { tools: true, harness: "opencode2" },
123408
123824
  async open(identity) {
123409
123825
  const role = roleFor(identity);
123410
123826
  const releaseRole = await acquireRole(role);
@@ -123413,6 +123829,10 @@ async function createV2HiddenCompletionExecutor(host, options) {
123413
123829
  await options.ensureAgent?.();
123414
123830
  const head = await resolveHead(identity);
123415
123831
  let active = store.read().active[role];
123832
+ if (active && hiddenToolLoop(identity)) {
123833
+ retireChild(active, "fresh-tool-loop-run");
123834
+ active = undefined;
123835
+ }
123416
123836
  if (active && active.generation !== generation) {
123417
123837
  retireChild(active, "host-generation-changed");
123418
123838
  active = undefined;
@@ -123435,7 +123855,7 @@ async function createV2HiddenCompletionExecutor(host, options) {
123435
123855
  const title = roleTitle(role);
123436
123856
  const created = await host.create({
123437
123857
  title,
123438
- agent: roleAgent(role),
123858
+ agent: hiddenToolLoop(identity) ? hiddenAgentFor(identity) : roleAgent(role),
123439
123859
  model: {
123440
123860
  providerID: head.providerID,
123441
123861
  id: head.modelID,
@@ -123493,6 +123913,7 @@ async function createV2HiddenCompletionExecutor(host, options) {
123493
123913
  await switchChildModel(run, requested);
123494
123914
  const baseline = withReader(options.openReader, (reader) => reader.latestSequence(run.child.id));
123495
123915
  const marker = `mc:hidden:${crypto.randomUUID()}:${crypto.randomUUID()}`;
123916
+ run.completion = undefined;
123496
123917
  const attempt = {
123497
123918
  childSessionId: run.child.id,
123498
123919
  identity: run.identity,
@@ -123552,6 +123973,7 @@ async function createV2HiddenCompletionExecutor(host, options) {
123552
123973
  }
123553
123974
  run.completion = {
123554
123975
  text,
123976
+ ...hiddenToolLoop(run.identity) ? { messages: toolLoopMessages(attempt) } : {},
123555
123977
  reasoning: null,
123556
123978
  usage: reportedInput !== undefined || reportedOutput !== undefined ? {
123557
123979
  input: reportedInput ?? 0,
@@ -123596,7 +124018,9 @@ async function createV2HiddenCompletionExecutor(host, options) {
123596
124018
  return;
123597
124019
  try {
123598
124020
  const reusable = run.failed && !run.unsettledFailure;
123599
- if (!run.completion && (run.failed || !settlement.promptSettled) && !reusable) {
124021
+ if (hiddenToolLoop(run.identity)) {
124022
+ retire(run, settlement.promptSettled ? "tool-loop-settled" : "tool-loop-failed");
124023
+ } else if (!run.completion && (run.failed || !settlement.promptSettled) && !reusable) {
123600
124024
  retire(run, "hidden-run-failed");
123601
124025
  }
123602
124026
  } finally {
@@ -123876,6 +124300,17 @@ class V2StoreReader {
123876
124300
  range(sessionID, after, through) {
123877
124301
  return trackDecodeOperation("range", () => through <= after ? [] : this.all(sessionID, after, undefined, through));
123878
124302
  }
124303
+ spanRowStamps(sessionID, after, through) {
124304
+ if (!Number.isSafeInteger(after) || !Number.isSafeInteger(through))
124305
+ throw new Error("Invalid seq span");
124306
+ const rows = this.db.prepare(`SELECT seq, id, time_updated AS updated, length(CAST(data AS BLOB)) AS bytes
124307
+ FROM session_message WHERE session_id = ? AND seq > ? AND seq <= ?
124308
+ ORDER BY seq ASC`).all(sessionID, after, through);
124309
+ const stamps = new Map;
124310
+ for (const row of rows)
124311
+ stamps.set(row.seq, `${row.id}\x00${row.updated ?? ""}\x00${row.bytes ?? ""}`);
124312
+ return stamps;
124313
+ }
123879
124314
  rawRowsThrough(sessionID, throughSeq, limit) {
123880
124315
  return trackDecodeOperation("rawRowsThrough", () => {
123881
124316
  if (!Number.isSafeInteger(throughSeq))
@@ -125137,13 +125572,13 @@ async function runHiddenSingleShotPrompt(args) {
125137
125572
  throw new Error(`${args.callContext} returned length-capped output`);
125138
125573
  }
125139
125574
  const text = completion.text;
125140
- if (!text)
125575
+ if (!text && !args.allowEmpty)
125141
125576
  throw new Error(`${args.callContext} returned no output`);
125142
- return args.parse(text);
125577
+ return args.parse(text ?? "", completion);
125143
125578
  }
125144
125579
  });
125145
125580
  promptSettled = true;
125146
- return { validated: run.validated, completion: run.output };
125581
+ return { validated: run.validated, completion: run.output, childSessionId: handle.id };
125147
125582
  } finally {
125148
125583
  await args.executor.close(handle, {
125149
125584
  promptSettled,
@@ -125891,8 +126326,11 @@ async function classifyOneChunk(args, chunk, anchors, sliceMs, signal) {
125891
126326
  anchors
125892
126327
  });
125893
126328
  if (moduleRoute) {
125894
- const run = await runClassifyThroughModule(args, chunk, anchors, signal);
125895
- recordInvocation(args, startedAt, { status: "completed" });
126329
+ const { accounting, ...run } = await runClassifyThroughModule(args, chunk, anchors, signal);
126330
+ recordInvocation(args, startedAt, {
126331
+ status: "completed",
126332
+ moduleAccounting: accounting
126333
+ });
125896
126334
  return run;
125897
126335
  }
125898
126336
  const executor = resolveHiddenCompletionExecutor(args.hiddenCompletionExecutor, args.client, args.db, args.sessionDirectory, "classify-memories");
@@ -125994,7 +126432,7 @@ async function runClassifyThroughModule(args, chunk, anchors, signal) {
125994
126432
  task: "classify",
125995
126433
  command_id: `classify:${args.moduleCommandId ?? Date.now()}:${createHash29("sha256").update(chunk.map((candidate) => candidate.id).join(",")).digest("hex").slice(0, 24)}`,
125996
126434
  authority_generation: args.moduleAuthorityGeneration,
125997
- ...resolvedModelChain.length > 0 ? { model_chain: resolvedModelChain } : {},
126435
+ model_chain: resolvedModelChain,
125998
126436
  payload: {
125999
126437
  prompt_body: prompt,
126000
126438
  items: chunk.map((candidate) => ({
@@ -126015,6 +126453,7 @@ async function runClassifyThroughModule(args, chunk, anchors, signal) {
126015
126453
  if (result.truncated === true) {
126016
126454
  throw new Error("classify returned length-capped output");
126017
126455
  }
126456
+ const accounting = moduleClassifyAccounting(result);
126018
126457
  const parsed = validateClassifyManifest(manifestText, new Set(chunk.map((candidate) => candidate.id)));
126019
126458
  const rows = parsed.map((entry) => {
126020
126459
  const candidate = chunk.find((item) => item.id === entry.id);
@@ -126087,7 +126526,39 @@ async function runClassifyThroughModule(args, chunk, anchors, signal) {
126087
126526
  throw new Error(`module accepted unknown memory ${moduleId}`);
126088
126527
  return candidate.contextMemory.id;
126089
126528
  });
126090
- return { classified: acceptedContextIds.length, changed: acceptedContextIds.length };
126529
+ return {
126530
+ classified: acceptedContextIds.length,
126531
+ changed: acceptedContextIds.length,
126532
+ accounting
126533
+ };
126534
+ }
126535
+ function nonNegativeCount(value) {
126536
+ return typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : 0;
126537
+ }
126538
+ function moduleClassifyAccounting(result) {
126539
+ const accounting = {};
126540
+ const usage = result.usage;
126541
+ if (usage && typeof usage === "object") {
126542
+ const record = usage;
126543
+ accounting.tokens = {
126544
+ input: nonNegativeCount(record.input),
126545
+ output: nonNegativeCount(record.output),
126546
+ cacheRead: nonNegativeCount(record.cache_read),
126547
+ cacheWrite: nonNegativeCount(record.cache_write)
126548
+ };
126549
+ }
126550
+ const diagnostics = result.diagnostics;
126551
+ const model = diagnostics && typeof diagnostics === "object" ? diagnostics.model : undefined;
126552
+ if (typeof model === "string") {
126553
+ const parsed = parseProviderModel(model);
126554
+ if (parsed) {
126555
+ accounting.providerId = parsed.providerID;
126556
+ accounting.modelId = parsed.modelID;
126557
+ } else if (model.trim()) {
126558
+ accounting.modelId = model.trim();
126559
+ }
126560
+ }
126561
+ return accounting;
126091
126562
  }
126092
126563
  function applyClassifications(args, chunk, manifestText) {
126093
126564
  const byId = new Map(chunk.map((m) => [m.id, m]));
@@ -126132,6 +126603,11 @@ function recordInvocation(args, startedAt, params) {
126132
126603
  providerId: params.completion.providerId,
126133
126604
  modelId: params.completion.modelId
126134
126605
  } : {},
126606
+ ...params.moduleAccounting ? {
126607
+ tokens: params.moduleAccounting.tokens,
126608
+ providerId: params.moduleAccounting.providerId,
126609
+ modelId: params.moduleAccounting.modelId
126610
+ } : {},
126135
126611
  error: params.error
126136
126612
  });
126137
126613
  }
@@ -126226,7 +126702,7 @@ import { createHash as createHash30 } from "node:crypto";
126226
126702
  import {
126227
126703
  existsSync as existsSync16,
126228
126704
  mkdirSync as mkdirSync11,
126229
- mkdtempSync as mkdtempSync2,
126705
+ mkdtempSync,
126230
126706
  readdirSync as readdirSync6,
126231
126707
  readFileSync as readFileSync16,
126232
126708
  realpathSync as realpathSync4,
@@ -126333,7 +126809,7 @@ function protectedBytes(text) {
126333
126809
  ].map((match) => match[0]);
126334
126810
  }
126335
126811
  function diff(name, before, after) {
126336
- const dir = mkdtempSync2(join17(tmpdir2(), "mc-doc-diff-"));
126812
+ const dir = mkdtempSync(join17(tmpdir2(), "mc-doc-diff-"));
126337
126813
  try {
126338
126814
  writeFileSync8(join17(dir, "before"), before);
126339
126815
  writeFileSync8(join17(dir, "after"), after);
@@ -128305,8 +128781,36 @@ async function mapOneBatch(args, batch, sliceMs, signal) {
128305
128781
  let promptSettled = false;
128306
128782
  const startedAt = Date.now();
128307
128783
  try {
128784
+ const prompt = buildMapMemoriesPrompt(args.projectIdentity, batch);
128785
+ if (args.hiddenCompletionExecutor) {
128786
+ const run = await runHiddenSingleShotPrompt({
128787
+ executor: args.hiddenCompletionExecutor,
128788
+ parentSessionId: args.parentSessionId,
128789
+ sessionDirectory: args.sessionDirectory,
128790
+ agent: DREAMER_MEMORY_MAPPER_AGENT,
128791
+ system: MAP_MEMORIES_SYSTEM_PROMPT,
128792
+ prompt,
128793
+ title: "magic-context-dream-map-memories",
128794
+ callContext: "dreamer:map-memories",
128795
+ model: args.model,
128796
+ fallbackModels: args.fallbackModels,
128797
+ timeoutMs: sliceMs,
128798
+ signal,
128799
+ parse: (text) => validateMapMemoriesManifest(text, new Set(batch.map((memory) => memory.id)))
128800
+ });
128801
+ recordInvocation2(args, startedAt, {
128802
+ status: "completed",
128803
+ messages: run.completion.messages ?? []
128804
+ });
128805
+ const outcome = await applyParsedBatchMappings(args, batch, run.validated);
128806
+ const returnedIds = new Set(run.validated.map((entry) => entry.id));
128807
+ return { ...outcome, requeue: batch.filter((memory) => !returnedIds.has(memory.id)) };
128808
+ }
128809
+ const client = args.client;
128810
+ if (!client)
128811
+ throw new Error("map-memories requires a client or hidden completion executor");
128308
128812
  const createResponse = await createChildSessionWithFence({
128309
- client: args.client,
128813
+ client,
128310
128814
  db: args.db,
128311
128815
  parentSessionId: args.parentSessionId,
128312
128816
  title: "magic-context-dream-map-memories",
@@ -128318,8 +128822,7 @@ async function mapOneBatch(args, batch, sliceMs, signal) {
128318
128822
  agentSessionId = typeof created?.id === "string" ? created.id : null;
128319
128823
  if (!agentSessionId)
128320
128824
  throw new Error("Could not create map-memories session.");
128321
- const prompt = buildMapMemoriesPrompt(args.projectIdentity, batch);
128322
- const run = await promptSyncWithValidatedOutputRetry(args.client, {
128825
+ const run = await promptSyncWithValidatedOutputRetry(client, {
128323
128826
  path: { id: agentSessionId },
128324
128827
  query: { directory: args.sessionDirectory },
128325
128828
  body: {
@@ -128334,7 +128837,7 @@ async function mapOneBatch(args, batch, sliceMs, signal) {
128334
128837
  fallbackModels: args.fallbackModels,
128335
128838
  callContext: "dreamer:map-memories",
128336
128839
  fetchOutput: async () => {
128337
- const messagesResponse = await args.client.session.messages({
128840
+ const messagesResponse = await client.session.messages({
128338
128841
  path: { id: agentSessionId },
128339
128842
  query: { directory: args.sessionDirectory, limit: 100 }
128340
128843
  });
@@ -128377,15 +128880,16 @@ async function mapOneBatch(args, batch, sliceMs, signal) {
128377
128880
  }
128378
128881
  };
128379
128882
  } finally {
128380
- await teardownChildSession({
128381
- client: args.client,
128382
- sessionId: agentSessionId,
128383
- sessionDirectory: args.sessionDirectory,
128384
- promptSettled,
128385
- privacySensitive: true,
128386
- context: "[dreamer] map-memories",
128387
- log
128388
- });
128883
+ if (agentSessionId && args.client)
128884
+ await teardownChildSession({
128885
+ client: args.client,
128886
+ sessionId: agentSessionId,
128887
+ sessionDirectory: args.sessionDirectory,
128888
+ promptSettled,
128889
+ privacySensitive: true,
128890
+ context: "[dreamer] map-memories",
128891
+ log
128892
+ });
128389
128893
  }
128390
128894
  }
128391
128895
  async function applyParsedBatchMappings(args, batch, parsed) {
@@ -129001,8 +129505,41 @@ async function refreshOnePrimer(args, primer, sliceMs, signal) {
129001
129505
  let promptSettled = false;
129002
129506
  const startedAt = Date.now();
129003
129507
  try {
129508
+ const prompt = buildInvestigationPrompt(primer, seed.kind, seed.orientation, seed.prePost);
129509
+ if (args.hiddenCompletionExecutor) {
129510
+ const run = await runHiddenSingleShotPrompt({
129511
+ executor: args.hiddenCompletionExecutor,
129512
+ parentSessionId: args.parentSessionId,
129513
+ sessionDirectory: args.sessionDirectory,
129514
+ agent: DREAMER_PRIMER_INVESTIGATOR_AGENT,
129515
+ system: PRIMER_INVESTIGATOR_SYSTEM_PROMPT,
129516
+ prompt,
129517
+ title: "magic-context-dream-refresh-primers",
129518
+ callContext: "dreamer:refresh-primers",
129519
+ model: args.model,
129520
+ fallbackModels: args.fallbackModels,
129521
+ language: args.language,
129522
+ timeoutMs: sliceMs,
129523
+ signal,
129524
+ parse: (text) => parseAnswer([{ info: { role: "assistant" }, parts: [{ type: "text", text }] }], primer.answer)
129525
+ });
129526
+ recordInvocation3(args, startedAt, {
129527
+ status: "completed",
129528
+ messages: run.completion.messages ?? []
129529
+ });
129530
+ const answer = run.validated.trim();
129531
+ if (!answer || investigationToolCallCount(run.completion.messages ?? []) === 0)
129532
+ return false;
129533
+ runLeaseGuardedWrite(args.db, args.holderId, args.leaseKey, () => {
129534
+ updatePrimerAnswer(args.db, primer.id, answer);
129535
+ });
129536
+ return true;
129537
+ }
129538
+ const client = args.client;
129539
+ if (!client)
129540
+ throw new Error("refresh-primers requires a client or hidden completion executor");
129004
129541
  const createResponse = await createChildSessionWithFence({
129005
- client: args.client,
129542
+ client,
129006
129543
  db: args.db,
129007
129544
  parentSessionId: args.parentSessionId,
129008
129545
  title: "magic-context-dream-refresh-primers",
@@ -129014,8 +129551,7 @@ async function refreshOnePrimer(args, primer, sliceMs, signal) {
129014
129551
  agentSessionId = typeof created?.id === "string" ? created.id : null;
129015
129552
  if (!agentSessionId)
129016
129553
  throw new Error("Could not create primer refresh session.");
129017
- const prompt = buildInvestigationPrompt(primer, seed.kind, seed.orientation, seed.prePost);
129018
- const run = await promptSyncWithValidatedOutputRetry(args.client, {
129554
+ const run = await promptSyncWithValidatedOutputRetry(client, {
129019
129555
  path: { id: agentSessionId },
129020
129556
  query: { directory: args.sessionDirectory },
129021
129557
  body: {
@@ -129030,7 +129566,7 @@ async function refreshOnePrimer(args, primer, sliceMs, signal) {
129030
129566
  fallbackModels: args.fallbackModels,
129031
129567
  callContext: "dreamer:refresh-primers",
129032
129568
  fetchOutput: async () => {
129033
- const messagesResponse = await args.client.session.messages({
129569
+ const messagesResponse = await client.session.messages({
129034
129570
  path: { id: agentSessionId },
129035
129571
  query: { directory: args.sessionDirectory, limit: 100 }
129036
129572
  });
@@ -129059,15 +129595,16 @@ async function refreshOnePrimer(args, primer, sliceMs, signal) {
129059
129595
  recordInvocation3(args, startedAt, { status: failedInvocationStatus(error), error });
129060
129596
  throw error;
129061
129597
  } finally {
129062
- await teardownChildSession({
129063
- client: args.client,
129064
- sessionId: agentSessionId,
129065
- sessionDirectory: args.sessionDirectory,
129066
- promptSettled,
129067
- privacySensitive: true,
129068
- context: "[dreamer] refresh-primers",
129069
- log
129070
- });
129598
+ if (agentSessionId && args.client)
129599
+ await teardownChildSession({
129600
+ client: args.client,
129601
+ sessionId: agentSessionId,
129602
+ sessionDirectory: args.sessionDirectory,
129603
+ promptSettled,
129604
+ privacySensitive: true,
129605
+ context: "[dreamer] refresh-primers",
129606
+ log
129607
+ });
129071
129608
  }
129072
129609
  }
129073
129610
  function originSessionIdForPrimer(args, primer) {
@@ -129757,8 +130294,40 @@ async function verifyOneBatch(args, batch, sliceMs, signal) {
129757
130294
  let promptSettled = false;
129758
130295
  const startedAt = Date.now();
129759
130296
  try {
130297
+ const prompt = buildVerifyPrompt(args.projectIdentity, batch);
130298
+ if (args.hiddenCompletionExecutor) {
130299
+ const run = await runHiddenSingleShotPrompt({
130300
+ executor: args.hiddenCompletionExecutor,
130301
+ parentSessionId: args.parentSessionId,
130302
+ sessionDirectory: args.sessionDirectory,
130303
+ agent: DREAMER_MEMORY_MAPPER_AGENT,
130304
+ system: VERIFY_SYSTEM_PROMPT,
130305
+ prompt,
130306
+ title: "magic-context-dream-verify",
130307
+ callContext: "dreamer:verify",
130308
+ model: args.model,
130309
+ fallbackModels: args.fallbackModels,
130310
+ language: args.language,
130311
+ timeoutMs: sliceMs,
130312
+ signal,
130313
+ parse: (text) => {
130314
+ const providerFailure = providerOutputFailureFromInvalidManifest([], text);
130315
+ if (providerFailure)
130316
+ throw providerFailure;
130317
+ return validateVerifyManifest(text, new Set(batch.map((memory) => memory.id)));
130318
+ }
130319
+ });
130320
+ recordInvocation4(args, startedAt, {
130321
+ status: "completed",
130322
+ messages: run.completion.messages ?? []
130323
+ });
130324
+ return applyParsedVerifyManifest(args, batch, run.validated);
130325
+ }
130326
+ const client = args.client;
130327
+ if (!client)
130328
+ throw new Error("verify requires a client or hidden completion executor");
129760
130329
  const createResponse = await createChildSessionWithFence({
129761
- client: args.client,
130330
+ client,
129762
130331
  db: args.db,
129763
130332
  parentSessionId: args.parentSessionId,
129764
130333
  title: "magic-context-dream-verify",
@@ -129770,8 +130339,7 @@ async function verifyOneBatch(args, batch, sliceMs, signal) {
129770
130339
  agentSessionId = typeof created?.id === "string" ? created.id : null;
129771
130340
  if (!agentSessionId)
129772
130341
  throw new Error("Could not create verify session.");
129773
- const prompt = buildVerifyPrompt(args.projectIdentity, batch);
129774
- const run = await promptSyncWithValidatedOutputRetry(args.client, {
130342
+ const run = await promptSyncWithValidatedOutputRetry(client, {
129775
130343
  path: { id: agentSessionId },
129776
130344
  query: { directory: args.sessionDirectory },
129777
130345
  body: {
@@ -129786,7 +130354,7 @@ async function verifyOneBatch(args, batch, sliceMs, signal) {
129786
130354
  fallbackModels: args.fallbackModels,
129787
130355
  callContext: "dreamer:verify",
129788
130356
  fetchOutput: async () => {
129789
- const messagesResponse = await args.client.session.messages({
130357
+ const messagesResponse = await client.session.messages({
129790
130358
  path: { id: agentSessionId },
129791
130359
  query: { directory: args.sessionDirectory, limit: 100 }
129792
130360
  });
@@ -129827,15 +130395,16 @@ async function verifyOneBatch(args, batch, sliceMs, signal) {
129827
130395
  providerFailure
129828
130396
  };
129829
130397
  } finally {
129830
- await teardownChildSession({
129831
- client: args.client,
129832
- sessionId: agentSessionId,
129833
- sessionDirectory: args.sessionDirectory,
129834
- promptSettled,
129835
- privacySensitive: true,
129836
- context: "[dreamer] verify",
129837
- log
129838
- });
130398
+ if (agentSessionId && args.client)
130399
+ await teardownChildSession({
130400
+ client: args.client,
130401
+ sessionId: agentSessionId,
130402
+ sessionDirectory: args.sessionDirectory,
130403
+ promptSettled,
130404
+ privacySensitive: true,
130405
+ context: "[dreamer] verify",
130406
+ log
130407
+ });
129839
130408
  }
129840
130409
  }
129841
130410
  async function applyParsedVerifyManifest(args, batch, parsed) {
@@ -130003,6 +130572,8 @@ async function applyParsedVerifyManifest(args, batch, parsed) {
130003
130572
  async function normalizeFiles(args, rawFiles) {
130004
130573
  if (rawFiles.length === 0)
130005
130574
  return [];
130575
+ if (args.normalizeFiles)
130576
+ return args.normalizeFiles(rawFiles);
130006
130577
  const normalized = await normalizeVerificationFiles({
130007
130578
  cwd: args.sessionDirectory,
130008
130579
  files: rawFiles
@@ -130336,7 +130907,8 @@ function createDreamTaskExecutor(deps) {
130336
130907
  if (config.task === "map-memories") {
130337
130908
  const result = await mapMemories({
130338
130909
  db,
130339
- client: requireDreamClient(deps.client),
130910
+ client: deps.client,
130911
+ hiddenCompletionExecutor: deps.hiddenCompletionExecutor,
130340
130912
  projectIdentity,
130341
130913
  parentSessionId: parent,
130342
130914
  sessionDirectory: deps.sessionDirectory,
@@ -130373,7 +130945,8 @@ function createDreamTaskExecutor(deps) {
130373
130945
  const memoryBefore = getMemoryCountsByStatus(db, projectIdentity);
130374
130946
  const result = await runVerify({
130375
130947
  db,
130376
- client: requireDreamClient(deps.client),
130948
+ client: deps.client,
130949
+ hiddenCompletionExecutor: deps.hiddenCompletionExecutor,
130377
130950
  projectIdentity,
130378
130951
  parentSessionId: parent,
130379
130952
  sessionDirectory: deps.sessionDirectory,
@@ -130474,7 +131047,8 @@ function createDreamTaskExecutor(deps) {
130474
131047
  if (config.task === "refresh-primers") {
130475
131048
  const result = await refreshPrimers({
130476
131049
  db,
130477
- client: requireDreamClient(deps.client),
131050
+ client: deps.client,
131051
+ hiddenCompletionExecutor: deps.hiddenCompletionExecutor,
130478
131052
  projectIdentity,
130479
131053
  parentSessionId: parent,
130480
131054
  sessionDirectory: deps.sessionDirectory,
@@ -130742,24 +131316,45 @@ async function runRetrospectiveTask(config, ctx, helpers) {
130742
131316
  abortController.abort();
130743
131317
  }, ctx.leaseAcquisition);
130744
131318
  let childSessionId = null;
131319
+ let hiddenHandle = null;
130745
131320
  let promptSettled = false;
130746
131321
  try {
130747
- const createResponse = await createChildSessionWithFence({
130748
- client: requireDreamClient(deps.client),
130749
- db,
130750
- parentSessionId: parent ?? undefined,
130751
- title: "magic-context-dream-retrospective",
130752
- directory: deps.sessionDirectory
130753
- });
130754
- const created = normalizeSDKResponse(createResponse, null, { preferResponseOnMissingData: true });
130755
- childSessionId = typeof created?.id === "string" ? created.id : null;
130756
- if (!childSessionId)
130757
- throw new Error("Retrospective could not create its child session.");
131322
+ if (deps.hiddenCompletionExecutor) {
131323
+ hiddenHandle = await deps.hiddenCompletionExecutor.open({
131324
+ parentSessionId: parent ?? undefined,
131325
+ agent: DREAMER_RETROSPECTIVE_AGENT,
131326
+ kind: "dreamer-task",
131327
+ system: FRICTION_GATE_SYSTEM_PROMPT,
131328
+ model: config.model,
131329
+ configuredModels: [
131330
+ ...config.model ? [config.model] : [],
131331
+ ...config.fallbackModels ?? []
131332
+ ],
131333
+ timeoutMs: Math.max(1, deadline - Date.now()),
131334
+ title: "magic-context-dream-retrospective",
131335
+ directory: deps.sessionDirectory
131336
+ });
131337
+ childSessionId = hiddenHandle.id;
131338
+ } else {
131339
+ const createResponse = await createChildSessionWithFence({
131340
+ client: requireDreamClient(deps.client),
131341
+ db,
131342
+ parentSessionId: parent ?? undefined,
131343
+ title: "magic-context-dream-retrospective",
131344
+ directory: deps.sessionDirectory
131345
+ });
131346
+ const created = normalizeSDKResponse(createResponse, null, { preferResponseOnMissingData: true });
131347
+ childSessionId = typeof created?.id === "string" ? created.id : null;
131348
+ if (!childSessionId)
131349
+ throw new Error("Retrospective could not create its child session.");
131350
+ }
130758
131351
  const sessionId = childSessionId;
131352
+ if (!sessionId)
131353
+ throw new Error("Retrospective could not create its child session.");
130759
131354
  const runChildTurn = async (system, userText) => {
130760
131355
  const remainingMs = Math.max(0, deadline - Date.now());
130761
131356
  promptSettled = false;
130762
- const run = await promptSyncWithValidatedOutputRetry(requireDreamClient(deps.client), {
131357
+ const run = await promptSyncWithValidatedOutputRetry(deps.hiddenCompletionExecutor ? undefined : requireDreamClient(deps.client), {
130763
131358
  path: { id: sessionId },
130764
131359
  query: { directory: deps.sessionDirectory },
130765
131360
  body: {
@@ -130773,7 +131368,13 @@ async function runRetrospectiveTask(config, ctx, helpers) {
130773
131368
  signal: abortController.signal,
130774
131369
  fallbackModels: config.fallbackModels,
130775
131370
  callContext: "dreamer:retrospective",
131371
+ ...hiddenHandle && deps.hiddenCompletionExecutor ? {
131372
+ transport: Object.assign((request) => deps.hiddenCompletionExecutor?.attempt(hiddenHandle, request) ?? Promise.reject(new Error("Hidden transport unavailable")), { childSessionId: hiddenHandle.childSessionId })
131373
+ } : {},
130776
131374
  fetchOutput: async () => {
131375
+ if (hiddenHandle && deps.hiddenCompletionExecutor) {
131376
+ return deps.hiddenCompletionExecutor.collect(hiddenHandle, 50);
131377
+ }
130777
131378
  const messagesResponse = await requireDreamClient(deps.client).session.messages({
130778
131379
  path: { id: sessionId },
130779
131380
  query: { directory: deps.sessionDirectory, limit: 50 }
@@ -130783,14 +131384,15 @@ async function runRetrospectiveTask(config, ctx, helpers) {
130783
131384
  });
130784
131385
  },
130785
131386
  validateOutput: (outputMessages) => {
130786
- const text = extractLatestAssistantText(outputMessages);
131387
+ const text = hiddenHandle ? outputMessages.text : extractLatestAssistantText(outputMessages);
130787
131388
  if (!text)
130788
131389
  throw new Error("Retrospective child returned no output.");
130789
131390
  return text;
130790
131391
  }
130791
131392
  });
130792
131393
  promptSettled = true;
130793
- return run;
131394
+ const output = hiddenHandle ? run.output.messages ?? [] : run.output;
131395
+ return { ...run, output };
130794
131396
  };
130795
131397
  const finish = (run, watermark) => {
130796
131398
  if (parent && run) {
@@ -130920,15 +131522,23 @@ async function runRetrospectiveTask(config, ctx, helpers) {
130920
131522
  });
130921
131523
  } finally {
130922
131524
  heartbeat.stop();
130923
- await teardownChildSession({
130924
- client: requireDreamClient(deps.client),
130925
- sessionId: childSessionId,
130926
- sessionDirectory: deps.sessionDirectory,
130927
- promptSettled,
130928
- privacySensitive: true,
130929
- context: "[dreamer] retrospective",
130930
- log
130931
- });
131525
+ if (hiddenHandle && deps.hiddenCompletionExecutor) {
131526
+ await deps.hiddenCompletionExecutor.close(hiddenHandle, {
131527
+ promptSettled,
131528
+ privacySensitive: true,
131529
+ context: "[dreamer] retrospective",
131530
+ log
131531
+ });
131532
+ } else
131533
+ await teardownChildSession({
131534
+ client: requireDreamClient(deps.client),
131535
+ sessionId: childSessionId,
131536
+ sessionDirectory: deps.sessionDirectory,
131537
+ promptSettled,
131538
+ privacySensitive: true,
131539
+ context: "[dreamer] retrospective",
131540
+ log
131541
+ });
130932
131542
  }
130933
131543
  }
130934
131544
  async function runAgenticTask(config, ctx, helpers) {
@@ -131002,72 +131612,107 @@ async function runAgenticTask(config, ctx, helpers) {
131002
131612
  docsCurrentTokens: maintainDocsSnapshot ? Math.ceil([...maintainDocsSnapshot.values()].join("").length / 3.5) : 0,
131003
131613
  curate: curateMemories && curateCategory ? { category: curateCategory, memories: curateMemories } : undefined
131004
131614
  });
131005
- const createResponse = await createChildSessionWithFence({
131006
- client: requireDreamClient(deps.client),
131007
- db,
131008
- parentSessionId: parent ?? undefined,
131009
- title: `magic-context-dream-${task}`,
131010
- directory: docsDir
131011
- });
131012
- const created = normalizeSDKResponse(createResponse, null, {
131013
- preferResponseOnMissingData: true
131014
- });
131015
- childSessionId = typeof created?.id === "string" ? created.id : null;
131016
- if (!childSessionId)
131017
- throw new Error("Dreamer could not create its child session.");
131018
- const sessionId = childSessionId;
131019
- const remainingMs = Math.max(0, deadline - Date.now());
131020
- const run = await promptSyncWithValidatedOutputRetry(requireDreamClient(deps.client), {
131021
- path: { id: sessionId },
131022
- query: { directory: docsDir },
131023
- body: {
131615
+ let run;
131616
+ if (deps.hiddenCompletionExecutor) {
131617
+ const hidden = await runHiddenSingleShotPrompt({
131618
+ executor: deps.hiddenCompletionExecutor,
131619
+ parentSessionId: parent ?? undefined,
131620
+ sessionDirectory: docsDir,
131024
131621
  agent: task === "maintain-docs" ? DREAMER_DOCS_AGENT : DREAMER_AGENT,
131025
- system: task === "maintain-docs" ? MAINTAIN_DOCS_SYSTEM_PROMPT : withContentLanguageDirective(CURATE_SYSTEM_PROMPT, config.language ?? deps.language),
131026
- ...modelBodyField(config.model),
131027
- parts: [{ type: "text", text: taskPrompt, synthetic: true }]
131028
- }
131029
- }, {
131030
- timeoutMs: Math.min(remainingMs, config.timeoutMinutes * 60 * 1000),
131031
- signal: abortController.signal,
131032
- fallbackModels: config.fallbackModels,
131033
- callContext: `dreamer:${task}`,
131034
- fetchOutput: async () => {
131035
- const messagesResponse = await requireDreamClient(deps.client).session.messages({
131036
- path: { id: sessionId },
131037
- query: {
131038
- directory: docsDir,
131039
- ...task === "curate" ? {} : { limit: 50 }
131622
+ system: task === "maintain-docs" ? MAINTAIN_DOCS_SYSTEM_PROMPT : CURATE_SYSTEM_PROMPT,
131623
+ prompt: taskPrompt,
131624
+ title: `magic-context-dream-${task}`,
131625
+ callContext: `dreamer:${task}`,
131626
+ allowEmpty: task === "curate",
131627
+ model: config.model,
131628
+ fallbackModels: config.fallbackModels,
131629
+ language: task === "curate" ? config.language ?? deps.language : undefined,
131630
+ timeoutMs: Math.min(Math.max(0, deadline - Date.now()), config.timeoutMinutes * 60 * 1000),
131631
+ signal: abortController.signal,
131632
+ parse: (text, completion) => {
131633
+ if (task !== "curate")
131634
+ return text;
131635
+ const memoryOperations = inspectCurateMemoryOperations(completion.messages);
131636
+ if (text)
131637
+ validateCurateAssistantText(text);
131638
+ if (memoryOperations.totalCalls > 0 && memoryOperations.completedActions.length === 0)
131639
+ throw new Error("Curate returned no completed ctx_memory tool result.");
131640
+ if (!text && memoryOperations.completedActions.length === 0)
131641
+ throw new Error("Dreamer returned no assistant output.");
131642
+ return { text: text || null, memoryOperations };
131643
+ }
131644
+ });
131645
+ childSessionId = hidden.childSessionId;
131646
+ run = { output: hidden.completion.messages ?? [], validated: hidden.validated };
131647
+ promptSettled = true;
131648
+ } else {
131649
+ const createResponse = await createChildSessionWithFence({
131650
+ client: requireDreamClient(deps.client),
131651
+ db,
131652
+ parentSessionId: parent ?? undefined,
131653
+ title: `magic-context-dream-${task}`,
131654
+ directory: docsDir
131655
+ });
131656
+ const created = normalizeSDKResponse(createResponse, null, {
131657
+ preferResponseOnMissingData: true
131658
+ });
131659
+ childSessionId = typeof created?.id === "string" ? created.id : null;
131660
+ if (!childSessionId)
131661
+ throw new Error("Dreamer could not create its child session.");
131662
+ const sessionId = childSessionId;
131663
+ const remainingMs = Math.max(0, deadline - Date.now());
131664
+ run = await promptSyncWithValidatedOutputRetry(requireDreamClient(deps.client), {
131665
+ path: { id: sessionId },
131666
+ query: { directory: docsDir },
131667
+ body: {
131668
+ agent: task === "maintain-docs" ? DREAMER_DOCS_AGENT : DREAMER_AGENT,
131669
+ system: task === "maintain-docs" ? MAINTAIN_DOCS_SYSTEM_PROMPT : withContentLanguageDirective(CURATE_SYSTEM_PROMPT, config.language ?? deps.language),
131670
+ ...modelBodyField(config.model),
131671
+ parts: [{ type: "text", text: taskPrompt, synthetic: true }]
131672
+ }
131673
+ }, {
131674
+ timeoutMs: Math.min(remainingMs, config.timeoutMinutes * 60 * 1000),
131675
+ signal: abortController.signal,
131676
+ fallbackModels: config.fallbackModels,
131677
+ callContext: `dreamer:${task}`,
131678
+ fetchOutput: async () => {
131679
+ const messagesResponse = await requireDreamClient(deps.client).session.messages({
131680
+ path: { id: sessionId },
131681
+ query: {
131682
+ directory: docsDir,
131683
+ ...task === "curate" ? {} : { limit: 50 }
131684
+ }
131685
+ });
131686
+ return normalizeSDKResponse(messagesResponse, [], {
131687
+ preferResponseOnMissingData: true
131688
+ });
131689
+ },
131690
+ validateOutput: (messages) => {
131691
+ const text = extractLatestAssistantText(messages);
131692
+ if (task !== "curate") {
131693
+ if (!text)
131694
+ throw new Error("Dreamer returned no assistant output.");
131695
+ return text;
131696
+ }
131697
+ const memoryOperations = inspectCurateMemoryOperations(messages);
131698
+ if (text)
131699
+ validateCurateAssistantText(text);
131700
+ if (memoryOperations.completedActions.length > 0) {
131701
+ return { text, memoryOperations };
131040
131702
  }
131041
- });
131042
- return normalizeSDKResponse(messagesResponse, [], {
131043
- preferResponseOnMissingData: true
131044
- });
131045
- },
131046
- validateOutput: (messages) => {
131047
- const text = extractLatestAssistantText(messages);
131048
- if (task !== "curate") {
131049
131703
  if (!text)
131050
131704
  throw new Error("Dreamer returned no assistant output.");
131051
- return text;
131052
- }
131053
- const memoryOperations = inspectCurateMemoryOperations(messages);
131054
- if (text)
131055
- validateCurateAssistantText(text);
131056
- if (memoryOperations.completedActions.length > 0) {
131705
+ if (memoryOperations.totalCalls > 0) {
131706
+ throw new Error("Curate returned no completed ctx_memory tool result.");
131707
+ }
131057
131708
  return { text, memoryOperations };
131058
131709
  }
131059
- if (!text)
131060
- throw new Error("Dreamer returned no assistant output.");
131061
- if (memoryOperations.totalCalls > 0) {
131062
- throw new Error("Curate returned no completed ctx_memory tool result.");
131063
- }
131064
- return { text, memoryOperations };
131065
- }
131066
- });
131067
- promptSettled = true;
131710
+ });
131711
+ promptSettled = true;
131712
+ }
131068
131713
  if (leaseLost)
131069
131714
  throw new Error("Dream lease lost during task");
131070
- const curateRefused = task === "curate" ? takeCurateSafetyRefusalCount(sessionId) : 0;
131715
+ const curateRefused = task === "curate" ? takeCurateSafetyRefusalCount(childSessionId ?? "") : 0;
131071
131716
  if (curateRefused > 0) {
131072
131717
  helpers.reportProgress(curateRefused, curateRefused);
131073
131718
  log(`[dreamer] curate safety summary: refused=${curateRefused}`);
@@ -131137,15 +131782,16 @@ async function runAgenticTask(config, ctx, helpers) {
131137
131782
  heartbeat.stop();
131138
131783
  if (childSessionId)
131139
131784
  takeCurateSafetyRefusalCount(childSessionId);
131140
- await teardownChildSession({
131141
- client: requireDreamClient(deps.client),
131142
- sessionId: childSessionId,
131143
- sessionDirectory: docsDir,
131144
- promptSettled,
131145
- privacySensitive: true,
131146
- context: `[dreamer] ${task}`,
131147
- log
131148
- });
131785
+ if (!deps.hiddenCompletionExecutor)
131786
+ await teardownChildSession({
131787
+ client: requireDreamClient(deps.client),
131788
+ sessionId: childSessionId,
131789
+ sessionDirectory: docsDir,
131790
+ promptSettled,
131791
+ privacySensitive: true,
131792
+ context: `[dreamer] ${task}`,
131793
+ log
131794
+ });
131149
131795
  }
131150
131796
  }
131151
131797
 
@@ -131598,7 +132244,25 @@ async function warmModelLimitCacheFromCatalog(context, options = {}) {
131598
132244
  }
131599
132245
 
131600
132246
  // src/v2/hooks/payload.ts
132247
+ init_logger();
131601
132248
  var HEAD_IDS = ["__magic_context_v2_m0__", "__magic_context_v2_m1__"];
132249
+ var HOST_CONTENT_TYPES = new Set([
132250
+ "text",
132251
+ "media",
132252
+ "tool-call",
132253
+ "tool-result",
132254
+ "reasoning",
132255
+ "compaction",
132256
+ "effort"
132257
+ ]);
132258
+ function rejectContentPart(message, part, reason) {
132259
+ const type = typeof part.type === "string" ? part.type : "<missing>";
132260
+ const text = `v2 context omitted a content part the host would reject: type=${type} message=${String(message.info.id ?? "<head>")} reason=${reason}`;
132261
+ if (typeof message.info.sessionID === "string")
132262
+ sessionLog(message.info.sessionID, text);
132263
+ else
132264
+ log(text);
132265
+ }
131602
132266
  function isHostInstance(value) {
131603
132267
  if (!value || typeof value !== "object" || Array.isArray(value))
131604
132268
  return false;
@@ -131789,6 +132453,56 @@ function adaptPayload(draft, admittedIDs = new Set) {
131789
132453
  const part = candidate;
131790
132454
  const bridge = bridges.get(part) ?? (part.type === "tool" && typeof part.callID === "string" ? bridgesFor(message)?.get(part.callID) : undefined);
131791
132455
  if (!bridge) {
132456
+ if (part.type === "tool") {
132457
+ const state = part.state;
132458
+ if (typeof part.callID !== "string" || typeof part.tool !== "string" || !state || typeof state !== "object") {
132459
+ rejectContentPart(message, part, "tool has no call ID, name, or state");
132460
+ continue;
132461
+ }
132462
+ content.push({
132463
+ type: "tool-call",
132464
+ id: part.callID,
132465
+ name: part.tool,
132466
+ input: state.input
132467
+ });
132468
+ if (state.status === "completed" || state.status === "error") {
132469
+ following.push({
132470
+ role: "tool",
132471
+ content: [
132472
+ {
132473
+ type: "tool-result",
132474
+ id: part.callID,
132475
+ name: part.tool,
132476
+ result: {
132477
+ type: state.status === "error" ? "error" : "text",
132478
+ value: toolStateContent(state)
132479
+ }
132480
+ }
132481
+ ]
132482
+ });
132483
+ }
132484
+ continue;
132485
+ }
132486
+ if (part.type === "file") {
132487
+ const mime = part.mime;
132488
+ const url = part.url;
132489
+ const prefix = `data:${mime};base64,`;
132490
+ if (typeof mime !== "string" || !/^image\/(png|jpeg|gif|webp)$/.test(mime) || typeof url !== "string" || !url.startsWith(prefix)) {
132491
+ rejectContentPart(message, part, "file is not an inline supported image");
132492
+ continue;
132493
+ }
132494
+ const asset = hostMediaAsset(url.slice(prefix.length), mime);
132495
+ if (typeof asset === "string") {
132496
+ rejectContentPart(message, part, `host media unavailable: ${asset}`);
132497
+ continue;
132498
+ }
132499
+ content.push({ type: "media", media: asset });
132500
+ continue;
132501
+ }
132502
+ if (!HOST_CONTENT_TYPES.has(String(part.type))) {
132503
+ rejectContentPart(message, part, "unknown host content type");
132504
+ continue;
132505
+ }
131792
132506
  const { synthetic: _synthetic, ...clean } = part;
131793
132507
  const original = hostPartTypes.has(clean.type) && !containsHostInstance(clean) ? hostParts.get(contentKey(clean)) : undefined;
131794
132508
  content.push(original ?? clean);
@@ -131796,14 +132510,23 @@ function adaptPayload(draft, admittedIDs = new Set) {
131796
132510
  }
131797
132511
  const state = part.state;
131798
132512
  if (bridge.native) {
131799
- const sourceState = bridge.native.state && typeof bridge.native.state === "object" ? bridge.native.state : {};
131800
- const nextState = { ...sourceState, input: state.input };
131801
- if (sourceState.content !== undefined) {
131802
- nextState.content = state.output === bridge.output ? sourceState.content : [{ type: "text", text: state.output }];
131803
- } else {
131804
- nextState.output = state.output;
132513
+ const native = bridge.native;
132514
+ const callID = String(native.id ?? native.callID ?? part.callID);
132515
+ const name = String(native.name ?? native.tool ?? part.tool);
132516
+ content.push({ type: "tool-call", id: callID, name, input: state.input });
132517
+ if (state.status === "completed" || state.status === "error") {
132518
+ following.push({
132519
+ role: "tool",
132520
+ content: [
132521
+ {
132522
+ type: "tool-result",
132523
+ id: callID,
132524
+ name,
132525
+ result: { type: "text", value: state.output }
132526
+ }
132527
+ ]
132528
+ });
131805
132529
  }
131806
- content.push({ ...bridge.native, state: nextState });
131807
132530
  continue;
131808
132531
  }
131809
132532
  if (bridge.call)
@@ -131857,13 +132580,18 @@ class V2ContextRefusal extends Error {
131857
132580
  this.name = "V2ContextRefusal";
131858
132581
  }
131859
132582
  }
131860
- async function interruptBeforeProvider(session, sessionID) {
132583
+ var INTERRUPT_CONFIRMATION_TIMEOUT_MS = 2000;
132584
+ var systemTimers = {
132585
+ setTimeout: (callback, ms) => setTimeout(callback, ms),
132586
+ clearTimeout: (handle) => clearTimeout(handle)
132587
+ };
132588
+ async function interruptBeforeProvider(session, sessionID, timers = systemTimers) {
131861
132589
  let timer;
131862
132590
  try {
131863
132591
  const result = await Promise.race([
131864
132592
  session.interrupt({ sessionID }),
131865
132593
  new Promise((_, reject) => {
131866
- timer = setTimeout(() => reject(new Error("interrupt exceeded 2000 ms")), 2000);
132594
+ timer = timers.setTimeout(() => reject(new Error(`interrupt exceeded ${INTERRUPT_CONFIRMATION_TIMEOUT_MS} ms`)), INTERRUPT_CONFIRMATION_TIMEOUT_MS);
131867
132595
  })
131868
132596
  ]);
131869
132597
  if (result.interrupted !== true)
@@ -131871,10 +132599,80 @@ async function interruptBeforeProvider(session, sessionID) {
131871
132599
  } catch (cause) {
131872
132600
  throw new V2ContextRefusal(undefined, { cause });
131873
132601
  } finally {
131874
- clearTimeout(timer);
132602
+ if (timer !== undefined)
132603
+ timers.clearTimeout(timer);
131875
132604
  }
131876
132605
  }
131877
132606
 
132607
+ // src/v2/hooks/restore-rows.ts
132608
+ class RestoredRowCache {
132609
+ capacity;
132610
+ sessions = new Map;
132611
+ constructor(capacity = 16) {
132612
+ this.capacity = capacity;
132613
+ }
132614
+ rows(reader, sessionID, after, through) {
132615
+ if (through <= after)
132616
+ return [];
132617
+ const kept = this.sessions.get(sessionID) ?? new Map;
132618
+ const stamps = reader.spanRowStamps(sessionID, after, through);
132619
+ const runs = [];
132620
+ let previous = after;
132621
+ let open;
132622
+ for (const [seq, stamp] of stamps) {
132623
+ if (kept.get(seq)?.stamp === stamp) {
132624
+ open = undefined;
132625
+ } else if (open) {
132626
+ open.through = seq;
132627
+ } else {
132628
+ open = { after: previous, through: seq };
132629
+ runs.push(open);
132630
+ }
132631
+ previous = seq;
132632
+ }
132633
+ const fresh = new Map;
132634
+ for (const run of runs)
132635
+ for (const row of readPages(reader, sessionID, run.after, run.through))
132636
+ fresh.set(row.seq, row);
132637
+ const next = new Map;
132638
+ const rows = [];
132639
+ for (const [seq, stamp] of stamps) {
132640
+ const row = fresh.get(seq) ?? kept.get(seq)?.row;
132641
+ if (!row)
132642
+ continue;
132643
+ next.set(seq, { stamp, row });
132644
+ rows.push(row);
132645
+ }
132646
+ this.sessions.delete(sessionID);
132647
+ this.sessions.set(sessionID, next);
132648
+ while (this.sessions.size > this.capacity) {
132649
+ const oldest = this.sessions.keys().next().value;
132650
+ if (oldest === undefined)
132651
+ break;
132652
+ this.sessions.delete(oldest);
132653
+ }
132654
+ return structuredClone(rows);
132655
+ }
132656
+ forget(sessionID) {
132657
+ this.sessions.delete(sessionID);
132658
+ }
132659
+ clear() {
132660
+ this.sessions.clear();
132661
+ }
132662
+ }
132663
+ function readPages(reader, sessionID, after, through) {
132664
+ const rows = [];
132665
+ let cursor = after;
132666
+ while (cursor < through) {
132667
+ const page = reader.page(sessionID, { after: cursor, through, limit: 100 });
132668
+ rows.push(...page.rows);
132669
+ if (page.rows.length < 100 || page.cursor === undefined)
132670
+ break;
132671
+ cursor = page.cursor;
132672
+ }
132673
+ return rows;
132674
+ }
132675
+
131878
132676
  // src/hooks/magic-context/live-session-state.ts
131879
132677
  function createLiveSessionState() {
131880
132678
  return {
@@ -145711,7 +146509,7 @@ import { isAbsolute as isAbsolute7 } from "node:path";
145711
146509
  // ../retina-local-fs/src/path-fence.ts
145712
146510
  import { lstat as lstat2, readlink, realpath as realpath2 } from "node:fs/promises";
145713
146511
  import { homedir as homedir12 } from "node:os";
145714
- import { basename as basename4, dirname as dirname10, isAbsolute as isAbsolute6, join as join20, relative, resolve as resolve7, sep } from "node:path";
146512
+ import { basename as basename4, dirname as dirname10, isAbsolute as isAbsolute6, join as join20, relative, resolve as resolve8, sep } from "node:path";
145715
146513
 
145716
146514
  // ../retina-local-fs/src/errors.ts
145717
146515
  class ProviderError extends Error {
@@ -145727,7 +146525,7 @@ class ProviderError extends Error {
145727
146525
  async function resolveAndFenceProviderPath(configuredPath, options) {
145728
146526
  const { home, dataDirectory } = await resolveFenceRoots(options);
145729
146527
  const expanded = configuredPath.startsWith("~/") ? join20(home, configuredPath.slice(2)) : configuredPath === "~" ? home : configuredPath;
145730
- const absolute = isAbsolute6(expanded) ? resolve7(expanded) : resolve7(options.cwd ?? process.cwd(), expanded);
146528
+ const absolute = isAbsolute6(expanded) ? resolve8(expanded) : resolve8(options.cwd ?? process.cwd(), expanded);
145731
146529
  const canonical = await canonicalPath(absolute, options.allowMissing);
145732
146530
  if (isFencedPath(canonical, home, dataDirectory)) {
145733
146531
  throw new ProviderError("fenced_path", `Refusing fenced path: ${canonical}`);
@@ -145735,14 +146533,14 @@ async function resolveAndFenceProviderPath(configuredPath, options) {
145735
146533
  return canonical;
145736
146534
  }
145737
146535
  async function resolveFenceRoots(options) {
145738
- const configuredHomePath = resolve7(options.homeDirectory ?? process.env.HOME ?? homedir12());
146536
+ const configuredHomePath = resolve8(options.homeDirectory ?? process.env.HOME ?? homedir12());
145739
146537
  let home;
145740
146538
  try {
145741
146539
  home = await realpath2(configuredHomePath);
145742
146540
  } catch (error) {
145743
146541
  throw fsError(configuredHomePath, error);
145744
146542
  }
145745
- const configuredDataDirectory = resolve7(options.dataDirectory ?? process.env.XDG_DATA_HOME ?? join20(home, ".local", "share"));
146543
+ const configuredDataDirectory = resolve8(options.dataDirectory ?? process.env.XDG_DATA_HOME ?? join20(home, ".local", "share"));
145746
146544
  const dataDirectory = await canonicalPath(configuredDataDirectory, true);
145747
146545
  return { home, dataDirectory };
145748
146546
  }
@@ -145760,7 +146558,7 @@ async function canonicalPath(path, allowMissing) {
145760
146558
  const metadata = await lstat2(candidate);
145761
146559
  if (metadata.isSymbolicLink()) {
145762
146560
  const target = await readlink(candidate);
145763
- const resolvedTarget = resolve7(dirname10(candidate), target);
146561
+ const resolvedTarget = resolve8(dirname10(candidate), target);
145764
146562
  return canonicalPath(join20(resolvedTarget, ...suffix), true);
145765
146563
  }
145766
146564
  } catch (candidateError) {
@@ -145784,8 +146582,8 @@ async function canonicalPath(path, allowMissing) {
145784
146582
  }
145785
146583
  }
145786
146584
  }
145787
- function isFencedPath(canonicalPath, homeDirectory, dataDirectory = process.env.XDG_DATA_HOME ?? join20(resolve7(homeDirectory), ".local", "share")) {
145788
- const cortexkitRoot = join20(resolve7(dataDirectory), "cortexkit");
146585
+ function isFencedPath(canonicalPath, homeDirectory, dataDirectory = process.env.XDG_DATA_HOME ?? join20(resolve8(homeDirectory), ".local", "share")) {
146586
+ const cortexkitRoot = join20(resolve8(dataDirectory), "cortexkit");
145789
146587
  const relativeToCortexkit = relative(cortexkitRoot, canonicalPath);
145790
146588
  const insideCortexkit = relativeToCortexkit !== "" && relativeToCortexkit !== ".." && !relativeToCortexkit.startsWith(`..${sep}`) && !isAbsolute6(relativeToCortexkit);
145791
146589
  const parts = insideCortexkit ? relativeToCortexkit.split(sep) : [];
@@ -147258,6 +148056,7 @@ async function registerContext(context) {
147258
148056
  const historyRefreshSessions = new Set;
147259
148057
  const pendingMaterializationSessions = new Set;
147260
148058
  const lastHeuristicsTurnId = new Map;
148059
+ const restoredRows = new RestoredRowCache;
147261
148060
  const rawProviders = new Map;
147262
148061
  let passDuties;
147263
148062
  let toolDuties;
@@ -147418,6 +148217,7 @@ async function registerContext(context) {
147418
148217
  historyRefreshSessions.delete(sessionID);
147419
148218
  pendingMaterializationSessions.delete(sessionID);
147420
148219
  lastHeuristicsTurnId.delete(sessionID);
148220
+ restoredRows.forget(sessionID);
147421
148221
  systemPromptRefreshSessions.delete(sessionID);
147422
148222
  systemPrompt?.clearSession(sessionID);
147423
148223
  tagger.cleanup(sessionID);
@@ -147642,7 +148442,7 @@ async function registerContext(context) {
147642
148442
  const servedBoundary = boundaryID ? servedBoundaryRow(reader, draft.sessionID, boundaryID) : null;
147643
148443
  const boundary = servedBoundary?.seq ?? reader.sequenceForId(draft.sessionID, boundaryID) ?? (reader.earliestSequence(draft.sessionID) ?? 0) - 1;
147644
148444
  const present = new Set(draft.messages.map((message) => message.id));
147645
- const restored = reader.range(draft.sessionID, boundary, cut.seq).filter((row) => !present.has(row.id)).flatMap((row) => restoreRow(row, draft.model, hostUsesMediaAssets() ? {
148445
+ const restored = restoredRows.rows(reader, draft.sessionID, boundary, cut.seq).filter((row) => !present.has(row.id)).flatMap((row) => restoreRow(row, draft.model, hostUsesMediaAssets() ? {
147646
148446
  asset: hostMediaAsset,
147647
148447
  unavailable: (detail) => sessionLog(draft.sessionID, `v2 restore: attachment replaced by a note row=${detail.rowID} name=${JSON.stringify(detail.name ?? null)} mediaType=${detail.mediaType} reason=${JSON.stringify(detail.reason)}`)
147648
148448
  } : undefined));
@@ -147795,6 +148595,7 @@ ${baseline}
147795
148595
  for (const release of rawProviders.values())
147796
148596
  release();
147797
148597
  rawProviders.clear();
148598
+ restoredRows.clear();
147798
148599
  }
147799
148600
  };
147800
148601
  }
@@ -147857,7 +148658,7 @@ async function getLatestVersion(channel = "latest", options = {}) {
147857
148658
  try {
147858
148659
  if (options.signal?.aborted)
147859
148660
  return null;
147860
- const response = await fetch(buildRegistryUrl(options.registryUrl ?? NPM_REGISTRY_URL), {
148661
+ const response = await (options.fetch ?? fetch)(buildRegistryUrl(options.registryUrl ?? NPM_REGISTRY_URL), {
147861
148662
  signal: controller.signal,
147862
148663
  headers: { Accept: "application/json" }
147863
148664
  });
@@ -147895,6 +148696,9 @@ function packageInfo() {
147895
148696
  directory = parent;
147896
148697
  }
147897
148698
  }
148699
+ function formatUpdateAvailableMessage(latest, current) {
148700
+ return `Magic Context ${latest} is available (running ${current}). To install it, open /plugins, select Magic Context and press ctrl+u, or run \`opencode plugin update\`. A version-pinned plugin entry must be changed in your OpenCode config instead.`;
148701
+ }
147898
148702
  function startUpdateChecks(context, check = (signal) => {
147899
148703
  return packageInfo().development ? Promise.resolve(null) : getLatestVersion("latest", { signal });
147900
148704
  }) {
@@ -147909,10 +148713,11 @@ function startUpdateChecks(context, check = (signal) => {
147909
148713
  continue;
147910
148714
  await context.storage.set("version-check-at", Date.now());
147911
148715
  const latest = await check(controller.signal);
147912
- const comparison = latest ? compareSemverCore(latest, packageInfo().version) : null;
147913
- if (!controller.signal.aborted && comparison !== null && comparison > 0) {
148716
+ const current = packageInfo().version;
148717
+ const comparison = latest ? compareSemverCore(latest, current) : null;
148718
+ if (latest && !controller.signal.aborted && comparison !== null && comparison > 0) {
147914
148719
  pushNotification("toast", {
147915
- message: `Magic Context ${latest} is available. Update the plugin to install it.`,
148720
+ message: formatUpdateAvailableMessage(latest, current),
147916
148721
  variant: "info"
147917
148722
  });
147918
148723
  }