@cortexkit/opencode-magic-context 0.22.2 → 0.22.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/dist/config/schema/magic-context.d.ts +7 -0
  2. package/dist/config/schema/magic-context.d.ts.map +1 -1
  3. package/dist/features/magic-context/dreamer/runner.d.ts.map +1 -1
  4. package/dist/features/magic-context/git-commits/git-log-reader.d.ts +8 -0
  5. package/dist/features/magic-context/git-commits/git-log-reader.d.ts.map +1 -1
  6. package/dist/features/magic-context/git-commits/indexer.d.ts.map +1 -1
  7. package/dist/features/magic-context/key-files/aft-availability.d.ts.map +1 -1
  8. package/dist/features/magic-context/key-files/identify-key-files.d.ts.map +1 -1
  9. package/dist/features/magic-context/memory/memory-migration.d.ts.map +1 -1
  10. package/dist/features/magic-context/migrations.d.ts.map +1 -1
  11. package/dist/features/magic-context/sidekick/agent.d.ts.map +1 -1
  12. package/dist/features/magic-context/storage-db.d.ts +1 -1
  13. package/dist/features/magic-context/storage-db.d.ts.map +1 -1
  14. package/dist/features/magic-context/storage-meta-session.d.ts.map +1 -1
  15. package/dist/features/magic-context/storage-meta-shared.d.ts +7 -1
  16. package/dist/features/magic-context/storage-meta-shared.d.ts.map +1 -1
  17. package/dist/features/magic-context/tool-definition-tokens.d.ts +21 -0
  18. package/dist/features/magic-context/tool-definition-tokens.d.ts.map +1 -1
  19. package/dist/features/magic-context/types.d.ts +4 -0
  20. package/dist/features/magic-context/types.d.ts.map +1 -1
  21. package/dist/features/magic-context/user-memory/review-user-memories.d.ts.map +1 -1
  22. package/dist/hooks/magic-context/compartment-runner-historian.d.ts.map +1 -1
  23. package/dist/hooks/magic-context/event-handler.d.ts +7 -0
  24. package/dist/hooks/magic-context/event-handler.d.ts.map +1 -1
  25. package/dist/hooks/magic-context/event-payloads.d.ts +7 -0
  26. package/dist/hooks/magic-context/event-payloads.d.ts.map +1 -1
  27. package/dist/hooks/magic-context/hook.d.ts.map +1 -1
  28. package/dist/hooks/magic-context/inject-compartments.d.ts +41 -0
  29. package/dist/hooks/magic-context/inject-compartments.d.ts.map +1 -1
  30. package/dist/hooks/magic-context/live-session-state.d.ts +12 -0
  31. package/dist/hooks/magic-context/live-session-state.d.ts.map +1 -1
  32. package/dist/hooks/magic-context/system-prompt-hash.d.ts +9 -0
  33. package/dist/hooks/magic-context/system-prompt-hash.d.ts.map +1 -1
  34. package/dist/hooks/magic-context/tag-content-primitives.d.ts +23 -0
  35. package/dist/hooks/magic-context/tag-content-primitives.d.ts.map +1 -1
  36. package/dist/hooks/magic-context/temporal-awareness.d.ts.map +1 -1
  37. package/dist/hooks/magic-context/text-complete.d.ts +23 -0
  38. package/dist/hooks/magic-context/text-complete.d.ts.map +1 -1
  39. package/dist/hooks/magic-context/tool-drop-target.d.ts.map +1 -1
  40. package/dist/hooks/magic-context/transform-postprocess-phase.d.ts +2 -1
  41. package/dist/hooks/magic-context/transform-postprocess-phase.d.ts.map +1 -1
  42. package/dist/hooks/magic-context/transform.d.ts +17 -0
  43. package/dist/hooks/magic-context/transform.d.ts.map +1 -1
  44. package/dist/index.d.ts.map +1 -1
  45. package/dist/index.js +353 -96
  46. package/dist/plugin/hooks/create-session-hooks.d.ts.map +1 -1
  47. package/dist/shared/keep-subagents.d.ts +7 -0
  48. package/dist/shared/keep-subagents.d.ts.map +1 -0
  49. package/package.json +1 -1
  50. package/src/shared/keep-subagents.test.ts +39 -0
  51. package/src/shared/keep-subagents.ts +33 -0
package/dist/index.js CHANGED
@@ -14968,6 +14968,7 @@ var init_magic_context = __esm(() => {
14968
14968
  model: DEFAULT_LOCAL_EMBEDDING_MODEL
14969
14969
  }).describe("Embedding provider configuration"),
14970
14970
  temporal_awareness: exports_external.boolean().default(true).describe('Inject wall-clock gap markers (<!-- +Xm -->) between user messages where > 5 min elapsed since the previous message, and add start/end date attributes on compartments. Gives the agent a sense of session pacing and "how long ago" across multi-day sessions. Graduated from experimental.temporal_awareness; default: true (set false to opt out).'),
14971
+ keep_subagents: exports_external.boolean().default(false).describe("Debug: keep the child sessions Magic Context spawns for its own subagents (historian, dreamer, sidekick, memory-migration) instead of deleting them on success. Useful for short-term inspection/data collection — their full transcript (prompt, tool calls, token usage, output) stays in the host session store. Kept sessions accumulate until manually cleared; leave false for normal use. Requires a restart to take effect."),
14971
14972
  caveman_text_compression: exports_external.object({
14972
14973
  enabled: exports_external.boolean().default(false).describe("Apply deterministic caveman-style text compression to old conversation text. Only active when ctx_reduce_enabled=false. Compresses user/assistant text in oldest-first tiers: ultra (oldest 20%), full, lite, untouched (newest 40%)."),
14973
14974
  min_chars: exports_external.number().min(100).max(1e4).default(500).describe("Text parts shorter than this (characters) stay untouched. Min 100, max 10000. Default: 500.")
@@ -15746,6 +15747,15 @@ function extractLatestAssistantText(messages) {
15746
15747
  }
15747
15748
  var init_assistant_message_extractor = () => {};
15748
15749
 
15750
+ // src/shared/keep-subagents.ts
15751
+ function setKeepSubagents(value) {
15752
+ keepSubagents = value === true;
15753
+ }
15754
+ function shouldKeepSubagents() {
15755
+ return keepSubagents;
15756
+ }
15757
+ var keepSubagents = false;
15758
+
15749
15759
  // src/features/magic-context/compartment-lease.ts
15750
15760
  function acquireCompartmentLease(db, sessionId, holderId) {
15751
15761
  const acquiredAt = Date.now();
@@ -15832,7 +15842,7 @@ function isSessionMetaRow(row) {
15832
15842
  if (row === null || typeof row !== "object")
15833
15843
  return false;
15834
15844
  const r = row;
15835
- return typeof r.session_id === "string" && typeof r.last_response_time === "number" && isStringOrNull(r.cache_ttl) && typeof r.counter === "number" && typeof r.last_nudge_tokens === "number" && isStringOrNull(r.last_nudge_band) && isStringOrNull(r.last_transform_error) && typeof r.is_subagent === "number" && typeof r.last_context_percentage === "number" && typeof r.last_input_tokens === "number" && isNumberOrNull(r.observed_safe_input_tokens) && isNumberOrNull(r.cache_alert_sent) && isNumberOrNull(r.times_execute_threshold_reached) && isNumberOrNull(r.compartment_in_progress) && (r.system_prompt_hash === null || typeof r.system_prompt_hash === "string" || typeof r.system_prompt_hash === "number") && isNumberOrNull(r.system_prompt_tokens) && isNumberOrNull(r.conversation_tokens) && isNumberOrNull(r.tool_call_tokens) && isNumberOrNull(r.cleared_reasoning_through_tag) && isStringOrNull(r.last_todo_state) && isBlobOrNull(r.cached_m0_bytes) && isBlobOrNull(r.cached_m1_bytes) && isNumberOrNull(r.cached_m0_project_memory_epoch) && isNumberOrNull(r.cached_m0_project_user_profile_version) && isNumberOrNull(r.cached_m0_max_compartment_seq) && isNumberOrNull(r.cached_m0_max_memory_id) && isNumberOrNull(r.cached_m0_max_mutation_id) && isNumberOrNull(r.cached_m0_max_memory_mutation_id) && isStringOrNull(r.cached_m0_project_docs_hash) && isNumberOrNull(r.cached_m0_materialized_at) && isNumberOrNull(r.cached_m0_session_facts_version) && isStringOrNull(r.cached_m0_upgrade_state) && isStringOrNull(r.last_observed_model_key) && isNumberOrNull(r.upgrade_reminded_at) && isNumberOrNull(r.pi_stable_id_scheme);
15845
+ return typeof r.session_id === "string" && typeof r.last_response_time === "number" && isStringOrNull(r.cache_ttl) && typeof r.counter === "number" && typeof r.last_nudge_tokens === "number" && isStringOrNull(r.last_nudge_band) && isStringOrNull(r.last_transform_error) && typeof r.is_subagent === "number" && typeof r.last_context_percentage === "number" && typeof r.last_input_tokens === "number" && isNumberOrNull(r.observed_safe_input_tokens) && isNumberOrNull(r.cache_alert_sent) && isNumberOrNull(r.times_execute_threshold_reached) && isNumberOrNull(r.compartment_in_progress) && (r.system_prompt_hash === null || typeof r.system_prompt_hash === "string" || typeof r.system_prompt_hash === "number") && isNumberOrNull(r.system_prompt_tokens) && isNumberOrNull(r.conversation_tokens) && isNumberOrNull(r.tool_call_tokens) && isNumberOrNull(r.cleared_reasoning_through_tag) && isStringOrNull(r.last_todo_state) && isBlobOrNull(r.cached_m0_bytes) && isBlobOrNull(r.cached_m1_bytes) && isNumberOrNull(r.cached_m0_project_memory_epoch) && isNumberOrNull(r.cached_m0_project_user_profile_version) && isNumberOrNull(r.cached_m0_max_compartment_seq) && isNumberOrNull(r.cached_m0_max_memory_id) && isNumberOrNull(r.cached_m0_max_mutation_id) && isNumberOrNull(r.cached_m0_max_memory_mutation_id) && isStringOrNull(r.cached_m0_project_docs_hash) && isNumberOrNull(r.cached_m0_materialized_at) && isNumberOrNull(r.cached_m0_session_facts_version) && isStringOrNull(r.cached_m0_upgrade_state) && isStringOrNull(r.cached_m0_system_hash) && isStringOrNull(r.cached_m0_tool_set_hash) && isStringOrNull(r.cached_m0_model_key) && isStringOrNull(r.last_observed_model_key) && isNumberOrNull(r.upgrade_reminded_at) && isNumberOrNull(r.pi_stable_id_scheme);
15836
15846
  }
15837
15847
  function getDefaultSessionMeta(sessionId) {
15838
15848
  return {
@@ -15868,6 +15878,9 @@ function getDefaultSessionMeta(sessionId) {
15868
15878
  cachedM0MaterializedAt: null,
15869
15879
  cachedM0SessionFactsVersion: null,
15870
15880
  cachedM0UpgradeState: null,
15881
+ cachedM0SystemHash: null,
15882
+ cachedM0ToolSetHash: null,
15883
+ cachedM0ModelKey: null,
15871
15884
  lastObservedModelKey: null,
15872
15885
  upgradeRemindedAt: null,
15873
15886
  piStableIdScheme: null
@@ -15919,6 +15932,9 @@ function toSessionMeta(row) {
15919
15932
  cachedM0MaterializedAt: numOrNull(row.cached_m0_materialized_at),
15920
15933
  cachedM0SessionFactsVersion: numOrNull(row.cached_m0_session_facts_version),
15921
15934
  cachedM0UpgradeState: stringOrNull(row.cached_m0_upgrade_state),
15935
+ cachedM0SystemHash: stringOrNull(row.cached_m0_system_hash),
15936
+ cachedM0ToolSetHash: stringOrNull(row.cached_m0_tool_set_hash),
15937
+ cachedM0ModelKey: stringOrNull(row.cached_m0_model_key),
15922
15938
  lastObservedModelKey: stringOrNull(row.last_observed_model_key),
15923
15939
  upgradeRemindedAt: numOrNull(row.upgrade_reminded_at),
15924
15940
  piStableIdScheme: numOrNull(row.pi_stable_id_scheme)
@@ -15938,8 +15954,11 @@ function persistCachedM0(db, sessionId, payload) {
15938
15954
  cached_m0_project_docs_hash = ?,
15939
15955
  cached_m0_materialized_at = ?,
15940
15956
  cached_m0_session_facts_version = ?,
15941
- cached_m0_upgrade_state = ?
15942
- WHERE session_id = ?`).run(Buffer2.from(payload.m0Bytes), payload.projectMemoryEpoch, payload.projectUserProfileVersion, payload.maxCompartmentSeq, payload.maxMemoryId, payload.maxMutationId, payload.maxMemoryMutationId ?? null, payload.m1Bytes ? Buffer2.from(payload.m1Bytes) : null, payload.projectDocsHash, payload.materializedAt, payload.sessionFactsVersion, payload.upgradeState, sessionId);
15957
+ cached_m0_upgrade_state = ?,
15958
+ cached_m0_system_hash = ?,
15959
+ cached_m0_tool_set_hash = ?,
15960
+ cached_m0_model_key = ?
15961
+ WHERE session_id = ?`).run(Buffer2.from(payload.m0Bytes), payload.projectMemoryEpoch, payload.projectUserProfileVersion, payload.maxCompartmentSeq, payload.maxMemoryId, payload.maxMutationId, payload.maxMemoryMutationId ?? null, payload.m1Bytes ? Buffer2.from(payload.m1Bytes) : null, payload.projectDocsHash, payload.materializedAt, payload.sessionFactsVersion, payload.upgradeState, payload.systemHash ?? "", payload.toolSetHash ?? "", payload.modelKey ?? "", sessionId);
15943
15962
  }
15944
15963
  function clearCachedM0M1(db, sessionId) {
15945
15964
  ensureSessionMetaRow(db, sessionId);
@@ -15957,6 +15976,9 @@ function clearCachedM0M1(db, sessionId) {
15957
15976
  ["cached_m0_materialized_at", null],
15958
15977
  ["cached_m0_session_facts_version", null],
15959
15978
  ["cached_m0_upgrade_state", null],
15979
+ ["cached_m0_system_hash", null],
15980
+ ["cached_m0_tool_set_hash", null],
15981
+ ["cached_m0_model_key", null],
15960
15982
  ["cached_m0_last_baseline_end_message_id", null],
15961
15983
  ["memory_block_cache", ""],
15962
15984
  ["memory_block_count", 0],
@@ -16009,6 +16031,9 @@ var init_storage_meta_shared = __esm(() => {
16009
16031
  "cached_m0_materialized_at",
16010
16032
  "cached_m0_session_facts_version",
16011
16033
  "cached_m0_upgrade_state",
16034
+ "cached_m0_system_hash",
16035
+ "cached_m0_tool_set_hash",
16036
+ "cached_m0_model_key",
16012
16037
  "last_observed_model_key",
16013
16038
  "upgrade_reminded_at",
16014
16039
  "pi_stable_id_scheme"
@@ -16045,6 +16070,9 @@ var init_storage_meta_shared = __esm(() => {
16045
16070
  cachedM0MaterializedAt: "cached_m0_materialized_at",
16046
16071
  cachedM0SessionFactsVersion: "cached_m0_session_facts_version",
16047
16072
  cachedM0UpgradeState: "cached_m0_upgrade_state",
16073
+ cachedM0SystemHash: "cached_m0_system_hash",
16074
+ cachedM0ToolSetHash: "cached_m0_tool_set_hash",
16075
+ cachedM0ModelKey: "cached_m0_model_key",
16048
16076
  lastObservedModelKey: "last_observed_model_key",
16049
16077
  upgradeRemindedAt: "upgrade_reminded_at",
16050
16078
  piStableIdScheme: "pi_stable_id_scheme"
@@ -149158,14 +149186,45 @@ function readRawSessionMessageByIdFromDb(db, sessionId, messageId) {
149158
149186
  }
149159
149187
 
149160
149188
  // src/hooks/magic-context/tag-content-primitives.ts
149189
+ function stripWellFormedLeadingTagPrefix(value) {
149190
+ return value.replace(/^(\u00a7\d+\u00a7\s*)+/, "");
149191
+ }
149192
+ function stripCompleteTagPairsGlobally(value) {
149193
+ return value.replace(COMPLETE_TAG_PAIR_GLOBAL_REGEX, "");
149194
+ }
149195
+ function stripMalformedTagNotationGlobally(value) {
149196
+ return value.replace(MALFORMED_TAG_GLOBAL_REGEX, "");
149197
+ }
149198
+ function stripTagSectionCharacters(value) {
149199
+ return value.replace(STRAY_SECTION_CHAR_REGEX, "");
149200
+ }
149201
+ function stripPersistedAssistantText(value) {
149202
+ let text = stripWellFormedLeadingTagPrefix(value);
149203
+ text = stripCompleteTagPairsGlobally(text);
149204
+ text = stripMalformedTagNotationGlobally(text);
149205
+ text = stripTagSectionCharacters(text);
149206
+ return text.trim();
149207
+ }
149161
149208
  function byteSize(value) {
149162
149209
  return encoder.encode(value).length;
149163
149210
  }
149164
149211
  function stripTagPrefix(value) {
149165
- let stripped = value.replace(MALFORMED_TAG_PREFIX_REGEX, "");
149166
- stripped = stripped.replace(TAG_PREFIX_REGEX, "");
149212
+ let stripped = value;
149213
+ for (let pass = 0;pass < 8; pass++) {
149214
+ const prev = stripped;
149215
+ stripped = stripped.replace(MALFORMED_TAG_PREFIX_REGEX, "");
149216
+ stripped = stripped.replace(TAG_PREFIX_REGEX, "");
149217
+ if (stripped === prev)
149218
+ break;
149219
+ }
149167
149220
  return stripped;
149168
149221
  }
149222
+ function peelLeadingMcTagNotation(value) {
149223
+ const body = stripTagPrefix(value);
149224
+ if (body === value)
149225
+ return { tagPrefix: "", body };
149226
+ return { tagPrefix: value.slice(0, value.length - body.length), body };
149227
+ }
149169
149228
  function prependTag(tagId, value) {
149170
149229
  const stripped = stripTagPrefix(value);
149171
149230
  return `§${tagId}§ ${stripped}`;
@@ -149176,11 +149235,14 @@ function isThinkingPart(part) {
149176
149235
  const candidate = part;
149177
149236
  return candidate.type === "thinking" || candidate.type === "reasoning";
149178
149237
  }
149179
- var encoder, TAG_PREFIX_REGEX, MALFORMED_TAG_PREFIX_REGEX;
149238
+ var encoder, TAG_PREFIX_REGEX, MALFORMED_TAG_PREFIX_REGEX, COMPLETE_TAG_PAIR_GLOBAL_REGEX, MALFORMED_TAG_GLOBAL_REGEX, STRAY_SECTION_CHAR_REGEX;
149180
149239
  var init_tag_content_primitives = __esm(() => {
149181
149240
  encoder = new TextEncoder;
149182
149241
  TAG_PREFIX_REGEX = /^(?:§\d+§\s*)+/;
149183
149242
  MALFORMED_TAG_PREFIX_REGEX = /^(?:§\d+">§(?:\d+§)?\s*)+/;
149243
+ COMPLETE_TAG_PAIR_GLOBAL_REGEX = /\u00a7\d+\u00a7/g;
149244
+ MALFORMED_TAG_GLOBAL_REGEX = /\u00a7\d+">(?:\u00a7(?:\d+\u00a7)?)?/g;
149245
+ STRAY_SECTION_CHAR_REGEX = /\u00a7/g;
149184
149246
  });
149185
149247
 
149186
149248
  // src/hooks/magic-context/tag-part-guards.ts
@@ -149308,7 +149370,9 @@ function hasMeaningfulPart(part) {
149308
149370
  return false;
149309
149371
  const type = part.type;
149310
149372
  if (type === "text") {
149311
- return typeof part.text === "string" && part.text.trim().length > 0;
149373
+ if (typeof part.text !== "string")
149374
+ return false;
149375
+ return stripTagPrefix(part.text).trim().length > 0;
149312
149376
  }
149313
149377
  if (typeof type !== "string")
149314
149378
  return false;
@@ -149424,6 +149488,7 @@ function createToolDropTarget(compositeKey, thinkingParts, index, batch) {
149424
149488
  }
149425
149489
  var DROP_PREFIX = "[dropped", IGNORE_PART_TYPES, TRUNCATION_SENTINEL = "...[truncated]";
149426
149490
  var init_tool_drop_target = __esm(() => {
149491
+ init_tag_content_primitives();
149427
149492
  IGNORE_PART_TYPES = new Set([
149428
149493
  "thinking",
149429
149494
  "reasoning",
@@ -150076,6 +150141,18 @@ function keyFor(providerID, modelID, agentName) {
150076
150141
  function fingerprintFor(description, parameters) {
150077
150142
  return createHash3("sha256").update(description).update("\x00").update(stableStringify(parameters)).digest("hex");
150078
150143
  }
150144
+ function getCurrentToolSetHash(providerID, modelID, agentName) {
150145
+ const key = keyFor(providerID, modelID, agentName);
150146
+ const inner = fingerprints.get(key);
150147
+ if (!inner || inner.size === 0)
150148
+ return "";
150149
+ const parts = [];
150150
+ for (const [toolID, fp] of inner)
150151
+ parts.push(`${toolID}\x00${fp}`);
150152
+ parts.sort();
150153
+ return createHash3("sha256").update(parts.join(`
150154
+ `)).digest("hex");
150155
+ }
150079
150156
  function setDatabase(db) {
150080
150157
  persistenceDb = db;
150081
150158
  cachedInsertStmt = null;
@@ -150869,6 +150946,9 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
150869
150946
  cached_m0_materialized_at INTEGER,
150870
150947
  cached_m0_session_facts_version INTEGER,
150871
150948
  cached_m0_upgrade_state TEXT,
150949
+ cached_m0_system_hash TEXT,
150950
+ cached_m0_tool_set_hash TEXT,
150951
+ cached_m0_model_key TEXT,
150872
150952
  cached_m0_last_baseline_end_message_id TEXT,
150873
150953
  upgrade_reminded_at INTEGER,
150874
150954
  pi_stable_id_scheme INTEGER
@@ -151060,6 +151140,9 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
151060
151140
  ensureColumn(db, "session_meta", "cached_m0_materialized_at", "INTEGER");
151061
151141
  ensureColumn(db, "session_meta", "cached_m0_session_facts_version", "INTEGER");
151062
151142
  ensureColumn(db, "session_meta", "cached_m0_upgrade_state", "TEXT");
151143
+ ensureColumn(db, "session_meta", "cached_m0_system_hash", "TEXT");
151144
+ ensureColumn(db, "session_meta", "cached_m0_tool_set_hash", "TEXT");
151145
+ ensureColumn(db, "session_meta", "cached_m0_model_key", "TEXT");
151063
151146
  ensureColumn(db, "session_meta", "cached_m0_last_baseline_end_message_id", "TEXT");
151064
151147
  ensureColumn(db, "session_meta", "upgrade_reminded_at", "INTEGER");
151065
151148
  db.exec(`
@@ -151264,7 +151347,7 @@ function getDatabasePersistenceError(db) {
151264
151347
  return null;
151265
151348
  return persistenceErrorByDatabase.get(db) ?? null;
151266
151349
  }
151267
- var databases, persistenceByDatabase, persistenceErrorByDatabase, lastSchemaFenceRejection = null, LATEST_SUPPORTED_VERSION = 29, sqlitePragmaConfig;
151350
+ var databases, persistenceByDatabase, persistenceErrorByDatabase, lastSchemaFenceRejection = null, LATEST_SUPPORTED_VERSION = 30, sqlitePragmaConfig;
151268
151351
  var init_storage_db = __esm(async () => {
151269
151352
  init_data_path();
151270
151353
  init_logger();
@@ -152087,6 +152170,28 @@ var init_migrations = __esm(async () => {
152087
152170
  db.exec("ALTER TABLE notes ADD COLUMN anchor_ordinal INTEGER");
152088
152171
  }
152089
152172
  }
152173
+ },
152174
+ {
152175
+ version: 30,
152176
+ description: "HARD-bust m[0] markers: cached system/tool-set/model identity",
152177
+ up: (db) => {
152178
+ const hasSessionMeta = db.prepare("SELECT 1 FROM sqlite_master WHERE type='table' AND name='session_meta' LIMIT 1").get();
152179
+ if (!hasSessionMeta)
152180
+ return;
152181
+ ensureColumn(db, "session_meta", "cached_m0_system_hash", "TEXT");
152182
+ ensureColumn(db, "session_meta", "cached_m0_tool_set_hash", "TEXT");
152183
+ ensureColumn(db, "session_meta", "cached_m0_model_key", "TEXT");
152184
+ const columns = new Set(db.prepare("PRAGMA table_info(session_meta)").all().map((column) => column.name));
152185
+ if (columns.has("cached_m0_bytes")) {
152186
+ db.prepare(`UPDATE session_meta SET
152187
+ cached_m0_bytes = NULL,
152188
+ cached_m1_bytes = NULL,
152189
+ cached_m0_materialized_at = NULL,
152190
+ cached_m0_system_hash = NULL,
152191
+ cached_m0_tool_set_hash = NULL,
152192
+ cached_m0_model_key = NULL`).run();
152193
+ }
152194
+ }
152090
152195
  }
152091
152196
  ];
152092
152197
  LATEST_MIGRATION_VERSION = MIGRATIONS.reduce((max, m) => Math.max(max, m.version), 0);
@@ -153005,6 +153110,9 @@ var init_storage_meta_session = __esm(async () => {
153005
153110
  cached_m0_materialized_at: "NULL AS cached_m0_materialized_at",
153006
153111
  cached_m0_session_facts_version: "NULL AS cached_m0_session_facts_version",
153007
153112
  cached_m0_upgrade_state: "NULL AS cached_m0_upgrade_state",
153113
+ cached_m0_system_hash: "NULL AS cached_m0_system_hash",
153114
+ cached_m0_tool_set_hash: "NULL AS cached_m0_tool_set_hash",
153115
+ cached_m0_model_key: "NULL AS cached_m0_model_key",
153008
153116
  last_observed_model_key: "NULL AS last_observed_model_key",
153009
153117
  upgrade_reminded_at: "NULL AS upgrade_reminded_at"
153010
153118
  };
@@ -162981,25 +163089,56 @@ var init_conflict_warning_hook = __esm(() => {
162981
163089
  // src/features/magic-context/key-files/aft-availability.ts
162982
163090
  import { existsSync as existsSync12, readFileSync as readFileSync10 } from "node:fs";
162983
163091
  import { homedir as homedir8 } from "node:os";
162984
- import { join as join14 } from "node:path";
163092
+ import { isAbsolute as isAbsolute3, join as join14, resolve as resolve5 } from "node:path";
163093
+ import { fileURLToPath as fileURLToPath2 } from "node:url";
162985
163094
  function parseConfig(path6) {
162986
163095
  if (!existsSync12(path6))
162987
163096
  return null;
162988
163097
  return import_comment_json3.parse(readFileSync10(path6, "utf-8"));
162989
163098
  }
162990
- function entryMatchesAft(entry) {
163099
+ function stringMentionsAft(value) {
163100
+ return AFT_NAME_NEEDLES.some((needle) => value.includes(needle));
163101
+ }
163102
+ function resolveLocalEntryPackageName(value, configDir) {
163103
+ let dir = null;
163104
+ if (value.startsWith("file://")) {
163105
+ try {
163106
+ dir = fileURLToPath2(value);
163107
+ } catch {
163108
+ return null;
163109
+ }
163110
+ } else if (value.startsWith("~/")) {
163111
+ dir = join14(homedir8(), value.slice(2));
163112
+ } else if (value.startsWith("/") || value.startsWith("./") || value.startsWith("../")) {
163113
+ dir = isAbsolute3(value) ? value : resolve5(configDir, value);
163114
+ } else {
163115
+ return null;
163116
+ }
163117
+ try {
163118
+ const pkg = JSON.parse(readFileSync10(join14(dir, "package.json"), "utf-8"));
163119
+ return typeof pkg.name === "string" ? pkg.name : null;
163120
+ } catch {
163121
+ return null;
163122
+ }
163123
+ }
163124
+ function entryMatchesAft(entry, configDir) {
162991
163125
  const value = Array.isArray(entry) ? entry[0] : entry;
162992
- return typeof value === "string" && (value.includes("@cortexkit/aft") || value.includes("aft-opencode") || value.includes("aft-pi"));
163126
+ if (typeof value !== "string")
163127
+ return false;
163128
+ if (stringMentionsAft(value))
163129
+ return true;
163130
+ const name2 = resolveLocalEntryPackageName(value, configDir);
163131
+ return name2 != null && stringMentionsAft(name2);
162993
163132
  }
162994
- function hasAftInArray(value) {
162995
- return Array.isArray(value) && value.some(entryMatchesAft);
163133
+ function hasAftInArray(value, configDir) {
163134
+ return Array.isArray(value) && value.some((entry) => entryMatchesAft(entry, configDir));
162996
163135
  }
162997
- function hasAftAtKeys(value, keys) {
163136
+ function hasAftAtKeys(value, keys, configDir) {
162998
163137
  if (!value || typeof value !== "object")
162999
163138
  return false;
163000
163139
  const record2 = value;
163001
163140
  for (const key of keys) {
163002
- if (hasAftInArray(record2[key]))
163141
+ if (hasAftInArray(record2[key], configDir))
163003
163142
  return true;
163004
163143
  }
163005
163144
  return false;
@@ -163016,7 +163155,8 @@ function getAftAvailability() {
163016
163155
  for (const path6 of opencodePaths) {
163017
163156
  try {
163018
163157
  const config2 = parseConfig(path6);
163019
- if (hasAftAtKeys(config2, ["plugin", "plugins", "mcp", "mcp_servers"])) {
163158
+ const configDir = join14(path6, "..");
163159
+ if (hasAftAtKeys(config2, ["plugin", "plugins", "mcp", "mcp_servers"], configDir)) {
163020
163160
  opencode = true;
163021
163161
  break;
163022
163162
  }
@@ -163026,12 +163166,13 @@ function getAftAvailability() {
163026
163166
  for (const path6 of piPaths) {
163027
163167
  try {
163028
163168
  const config2 = parseConfig(path6);
163029
- if (hasAftAtKeys(config2, ["packages", "extensions"])) {
163169
+ const configDir = join14(path6, "..");
163170
+ if (hasAftAtKeys(config2, ["packages", "extensions"], configDir)) {
163030
163171
  pi = true;
163031
163172
  break;
163032
163173
  }
163033
163174
  const agent = config2?.agent;
163034
- if (hasAftAtKeys(agent, ["packages", "extensions"])) {
163175
+ if (hasAftAtKeys(agent, ["packages", "extensions"], configDir)) {
163035
163176
  pi = true;
163036
163177
  break;
163037
163178
  }
@@ -163048,9 +163189,10 @@ function getAftAvailability() {
163048
163189
  function isAftAvailable() {
163049
163190
  return getAftAvailability().available;
163050
163191
  }
163051
- var import_comment_json3, overrideAvailability = null;
163192
+ var import_comment_json3, overrideAvailability = null, AFT_NAME_NEEDLES;
163052
163193
  var init_aft_availability = __esm(() => {
163053
163194
  import_comment_json3 = __toESM(require_src2(), 1);
163195
+ AFT_NAME_NEEDLES = ["@cortexkit/aft", "aft-opencode", "aft-pi"];
163054
163196
  });
163055
163197
 
163056
163198
  // src/features/magic-context/memory/storage-memory-embeddings.ts
@@ -163735,7 +163877,7 @@ async function acquireModelLoadLock(lockPath) {
163735
163877
  if (Date.now() - waitStart > MAX_LOCK_WAIT_MS) {
163736
163878
  throw new Error(`[magic-context] embedding-load lock wait exceeded ${MAX_LOCK_WAIT_MS}ms; another process is still loading the model. Skipping this init attempt to avoid an unsynchronized native load.`);
163737
163879
  }
163738
- await new Promise((resolve6) => setTimeout(resolve6, LOCK_POLL_MS));
163880
+ await new Promise((resolve7) => setTimeout(resolve7, LOCK_POLL_MS));
163739
163881
  }
163740
163882
  }
163741
163883
  }
@@ -163904,7 +164046,7 @@ class LocalEmbeddingProvider {
163904
164046
  }
163905
164047
  const delayMs = 300 * attempt + Math.floor(Math.random() * 200);
163906
164048
  log(`[magic-context] embedding model load attempt ${attempt}/${MAX_ATTEMPTS} failed transiently, retrying in ${delayMs}ms`);
163907
- await new Promise((resolve6) => setTimeout(resolve6, delayMs));
164049
+ await new Promise((resolve7) => setTimeout(resolve7, delayMs));
163908
164050
  }
163909
164051
  }
163910
164052
  if (this.pipeline) {
@@ -163932,8 +164074,8 @@ class LocalEmbeddingProvider {
163932
164074
  if (this.inFlight === 0) {
163933
164075
  return Promise.resolve();
163934
164076
  }
163935
- return new Promise((resolve6) => {
163936
- this.inFlightWaiters.push(resolve6);
164077
+ return new Promise((resolve7) => {
164078
+ this.inFlightWaiters.push(resolve7);
163937
164079
  });
163938
164080
  }
163939
164081
  finishInFlight() {
@@ -164920,7 +165062,7 @@ async function refreshModelLimitsFromApi(client, options) {
164920
165062
  if (ok)
164921
165063
  return;
164922
165064
  if (attempt < attempts) {
164923
- await new Promise((resolve6) => setTimeout(resolve6, delayMs));
165065
+ await new Promise((resolve7) => setTimeout(resolve7, delayMs));
164924
165066
  }
164925
165067
  }
164926
165068
  }
@@ -165906,12 +166048,12 @@ async function runHistorianPrompt(args) {
165906
166048
  error: `Historian failed while processing this session: ${desc.brief}`
165907
166049
  };
165908
166050
  } finally {
165909
- if (agentSessionId && outcomeOk) {
166051
+ if (agentSessionId && outcomeOk && !shouldKeepSubagents()) {
165910
166052
  await client.session.delete({ path: { id: agentSessionId } }).catch((e) => {
165911
166053
  sessionLog(parentSessionId, "compartment agent: session cleanup failed", getErrorMessage(e));
165912
166054
  });
165913
- } else if (agentSessionId && !outcomeOk) {
165914
- sessionLog(parentSessionId, `historian: KEEPING failed child session ${agentSessionId} for debugging (not deleted)`);
166055
+ } else if (agentSessionId && (!outcomeOk || shouldKeepSubagents())) {
166056
+ sessionLog(parentSessionId, `historian: KEEPING child session ${agentSessionId} (${outcomeOk ? "keep_subagents" : "failed"}) — not deleted`);
165915
166057
  }
165916
166058
  }
165917
166059
  }
@@ -165990,8 +166132,8 @@ function isTransientHistorianPromptError(message) {
165990
166132
  ].some((token) => normalized.includes(token));
165991
166133
  }
165992
166134
  function sleep(ms) {
165993
- return new Promise((resolve6) => {
165994
- setTimeout(resolve6, ms);
166135
+ return new Promise((resolve7) => {
166136
+ setTimeout(resolve7, ms);
165995
166137
  });
165996
166138
  }
165997
166139
  function cleanupHistorianDump(sessionId, dumpPath) {
@@ -166690,9 +166832,7 @@ function injectTemporalMarkers(messages) {
166690
166832
  if (prefix && Array.isArray(msg.parts)) {
166691
166833
  const target = findFirstVisibleTextPart(msg.parts);
166692
166834
  if (target && typeof target.text === "string") {
166693
- const tagMatch = target.text.match(/^(?:§\d+§\s*)+/);
166694
- const tagPrefix = tagMatch ? tagMatch[0] : "";
166695
- const body = target.text.slice(tagPrefix.length);
166835
+ const { tagPrefix, body } = peelLeadingMcTagNotation(target.text);
166696
166836
  if (!TEMPORAL_MARKER_PATTERN.test(body)) {
166697
166837
  target.text = tagPrefix + prefix + body;
166698
166838
  injected++;
@@ -166707,6 +166847,7 @@ function injectTemporalMarkers(messages) {
166707
166847
  }
166708
166848
  var TEMPORAL_AWARENESS_THRESHOLD_SECONDS = 300, SECONDS_PER_MINUTE = 60, SECONDS_PER_HOUR, SECONDS_PER_DAY, SECONDS_PER_WEEK, TEMPORAL_MARKER_PATTERN;
166709
166849
  var init_temporal_awareness = __esm(() => {
166850
+ init_tag_content_primitives();
166710
166851
  SECONDS_PER_HOUR = 60 * 60;
166711
166852
  SECONDS_PER_DAY = 24 * 60 * 60;
166712
166853
  SECONDS_PER_WEEK = 7 * 24 * 60 * 60;
@@ -167001,12 +167142,6 @@ function getMaxCompartmentSeq(db, sessionId) {
167001
167142
  const row = cachedStatement(maxCompartmentSeqStatements, db, "SELECT COALESCE(MAX(sequence), -1) AS s FROM compartments WHERE session_id = ?").get(sessionId);
167002
167143
  return numberFromRow(row, "s");
167003
167144
  }
167004
- function normalizeCachedMaxCompartmentSeq(db, sessionId, stored) {
167005
- if (stored === 0 && getMaxCompartmentSeq(db, sessionId) === EMPTY_MAX_COMPARTMENT_SEQ) {
167006
- return EMPTY_MAX_COMPARTMENT_SEQ;
167007
- }
167008
- return stored;
167009
- }
167010
167145
  function getMaxMemoryId(db, projectPath) {
167011
167146
  if (!projectPath)
167012
167147
  return 0;
@@ -167030,6 +167165,7 @@ function getGlobalUserProfileVersion(db) {
167030
167165
  }
167031
167166
  function readCurrentM0SnapshotMarkers(args) {
167032
167167
  const projectDirectory = args.projectDirectory ?? args.projectPath ?? "";
167168
+ const hard = args.hardSignals ?? EMPTY_HARD_SIGNALS;
167033
167169
  return {
167034
167170
  projectMemoryEpoch: getProjectMemoryEpoch(args.db, args.projectPath),
167035
167171
  projectUserProfileVersion: getGlobalUserProfileVersion(args.db),
@@ -167040,7 +167176,10 @@ function readCurrentM0SnapshotMarkers(args) {
167040
167176
  projectDocsHash: projectDirectory ? computeProjectDocsHash(projectDirectory) : "",
167041
167177
  materializedAt: Date.now(),
167042
167178
  sessionFactsVersion: getSessionFactsVersion(args.db, args.sessionId),
167043
- upgradeState: getUpgradeState(args.db, args.sessionId)
167179
+ upgradeState: getUpgradeState(args.db, args.sessionId),
167180
+ systemHash: hard.systemHash,
167181
+ toolSetHash: hard.toolSetHash,
167182
+ modelKey: hard.modelKey
167044
167183
  };
167045
167184
  }
167046
167185
  function snapshotMarkersFromCachedM0(state) {
@@ -167070,7 +167209,10 @@ function snapshotMarkersFromCachedM0(state) {
167070
167209
  projectDocsHash: state.cachedM0ProjectDocsHash ?? "",
167071
167210
  materializedAt: state.cachedM0MaterializedAt ?? 0,
167072
167211
  sessionFactsVersion: state.cachedM0SessionFactsVersion,
167073
- upgradeState: state.cachedM0UpgradeState
167212
+ upgradeState: state.cachedM0UpgradeState,
167213
+ systemHash: state.cachedM0SystemHash ?? "",
167214
+ toolSetHash: state.cachedM0ToolSetHash ?? "",
167215
+ modelKey: state.cachedM0ModelKey ?? ""
167074
167216
  };
167075
167217
  }
167076
167218
  function mustMaterialize(args) {
@@ -167078,16 +167220,22 @@ function mustMaterialize(args) {
167078
167220
  return { value: true, reason: "first_render" };
167079
167221
  if (!args.state.cachedM1Bytes)
167080
167222
  return { value: true, reason: "cached_m1_missing" };
167223
+ const hard = args.hardSignals ?? EMPTY_HARD_SIGNALS;
167081
167224
  const current = readCurrentM0SnapshotMarkers(args);
167082
- if (args.state.cachedM0ProjectMemoryEpoch !== current.projectMemoryEpoch) {
167083
- return { value: true, reason: "project_memory_epoch" };
167225
+ if (hard.modelKey !== "" && hard.modelKey !== (args.state.cachedM0ModelKey ?? "")) {
167226
+ return { value: true, reason: "model_change" };
167227
+ }
167228
+ if (hard.systemHash !== "" && hard.systemHash !== (args.state.cachedM0SystemHash ?? "")) {
167229
+ return { value: true, reason: "system_hash" };
167230
+ }
167231
+ if (hard.toolSetHash !== "" && hard.toolSetHash !== (args.state.cachedM0ToolSetHash ?? "")) {
167232
+ return { value: true, reason: "tool_set_hash" };
167084
167233
  }
167085
- if (args.state.cachedM0ProjectUserProfileVersion !== current.projectUserProfileVersion) {
167086
- return { value: true, reason: "project_user_profile_version" };
167234
+ if (hard.cacheExpired && hard.lastResponseTime > 0 && hard.lastResponseTime > (args.state.cachedM0MaterializedAt ?? 0)) {
167235
+ return { value: true, reason: "ttl_idle" };
167087
167236
  }
167088
- const cachedMaxSeq = args.state.cachedM0MaxCompartmentSeq === null ? null : normalizeCachedMaxCompartmentSeq(args.db, args.sessionId, args.state.cachedM0MaxCompartmentSeq);
167089
- if (cachedMaxSeq !== current.maxCompartmentSeq) {
167090
- return { value: true, reason: "max_compartment_seq" };
167237
+ if (args.state.cachedM0ProjectMemoryEpoch !== current.projectMemoryEpoch) {
167238
+ return { value: true, reason: "project_memory_epoch" };
167091
167239
  }
167092
167240
  if (args.state.cachedM0MaxMutationId !== current.maxMutationId) {
167093
167241
  return { value: true, reason: "max_mutation_id" };
@@ -167276,6 +167424,9 @@ function applyMarkersToState(state, m0Bytes, markers, m1Bytes) {
167276
167424
  state.cachedM0MaterializedAt = markers.materializedAt;
167277
167425
  state.cachedM0SessionFactsVersion = markers.sessionFactsVersion;
167278
167426
  state.cachedM0UpgradeState = markers.upgradeState;
167427
+ state.cachedM0SystemHash = markers.systemHash;
167428
+ state.cachedM0ToolSetHash = markers.toolSetHash;
167429
+ state.cachedM0ModelKey = markers.modelKey;
167279
167430
  state.snapshotMarkers = markers;
167280
167431
  }
167281
167432
  function historySliceTokens(m0Text) {
@@ -167300,7 +167451,8 @@ function materializeM0(options) {
167300
167451
  db: options.db,
167301
167452
  sessionId: options.sessionId,
167302
167453
  projectPath,
167303
- projectDirectory
167454
+ projectDirectory,
167455
+ hardSignals: options.hardSignals
167304
167456
  });
167305
167457
  docs = projectDirectory ? readProjectDocsCanonical(projectDirectory) : { renderedBlock: "", canonicalHash: "" };
167306
167458
  snapshotMarkers.projectDocsHash = docs.canonicalHash;
@@ -167366,7 +167518,10 @@ function materializeM0(options) {
167366
167518
  projectDocsHash: phase3ProjectDocsHash,
167367
167519
  materializedAt: Date.now(),
167368
167520
  sessionFactsVersion: getSessionFactsVersion(options.db, options.sessionId),
167369
- upgradeState: getUpgradeState(options.db, options.sessionId)
167521
+ upgradeState: getUpgradeState(options.db, options.sessionId),
167522
+ systemHash: snapshotMarkers.systemHash,
167523
+ toolSetHash: snapshotMarkers.toolSetHash,
167524
+ modelKey: snapshotMarkers.modelKey
167370
167525
  };
167371
167526
  const stale = current.projectMemoryEpoch !== snapshotMarkers.projectMemoryEpoch || current.projectUserProfileVersion !== snapshotMarkers.projectUserProfileVersion || current.maxCompartmentSeq !== snapshotMarkers.maxCompartmentSeq || current.maxMutationId !== snapshotMarkers.maxMutationId || current.maxMemoryMutationId !== snapshotMarkers.maxMemoryMutationId || current.projectDocsHash !== snapshotMarkers.projectDocsHash || current.sessionFactsVersion !== snapshotMarkers.sessionFactsVersion || current.upgradeState !== snapshotMarkers.upgradeState;
167372
167527
  if (stale) {
@@ -167388,7 +167543,10 @@ function materializeM0(options) {
167388
167543
  projectDocsHash: snapshotMarkers.projectDocsHash,
167389
167544
  materializedAt: snapshotMarkers.materializedAt,
167390
167545
  sessionFactsVersion: snapshotMarkers.sessionFactsVersion,
167391
- upgradeState: snapshotMarkers.upgradeState
167546
+ upgradeState: snapshotMarkers.upgradeState,
167547
+ systemHash: snapshotMarkers.systemHash,
167548
+ toolSetHash: snapshotMarkers.toolSetHash,
167549
+ modelKey: snapshotMarkers.modelKey
167392
167550
  });
167393
167551
  options.db.prepare("UPDATE session_meta SET memory_block_count = ?, memory_block_ids = ? WHERE session_id = ?").run(renderedMemoryIds.length, JSON.stringify(renderedMemoryIds), options.sessionId);
167394
167552
  options.db.exec("COMMIT");
@@ -167547,6 +167705,9 @@ function readCachedM0M1Row(db, sessionId) {
167547
167705
  cached_m0_materialized_at,
167548
167706
  cached_m0_session_facts_version,
167549
167707
  cached_m0_upgrade_state,
167708
+ cached_m0_system_hash,
167709
+ cached_m0_tool_set_hash,
167710
+ cached_m0_model_key,
167550
167711
  memory_block_ids
167551
167712
  FROM session_meta
167552
167713
  WHERE session_id = ?`).get(sessionId);
@@ -167578,11 +167739,14 @@ function markersFromCachedRow(row) {
167578
167739
  projectDocsHash: row.cached_m0_project_docs_hash ?? "",
167579
167740
  materializedAt: row.cached_m0_materialized_at ?? 0,
167580
167741
  sessionFactsVersion: row.cached_m0_session_facts_version,
167581
- upgradeState: row.cached_m0_upgrade_state
167742
+ upgradeState: row.cached_m0_upgrade_state,
167743
+ systemHash: row.cached_m0_system_hash ?? "",
167744
+ toolSetHash: row.cached_m0_tool_set_hash ?? "",
167745
+ modelKey: row.cached_m0_model_key ?? ""
167582
167746
  };
167583
167747
  }
167584
167748
  function cachedRowMatchesState(row, state) {
167585
- return bufferEqualsNullable(row.cached_m0_bytes, state.cachedM0Bytes) && row.cached_m0_project_memory_epoch === state.cachedM0ProjectMemoryEpoch && row.cached_m0_project_user_profile_version === state.cachedM0ProjectUserProfileVersion && row.cached_m0_max_compartment_seq === state.cachedM0MaxCompartmentSeq && row.cached_m0_max_memory_id === state.cachedM0MaxMemoryId && row.cached_m0_max_mutation_id === state.cachedM0MaxMutationId && row.cached_m0_max_memory_mutation_id === state.cachedM0MaxMemoryMutationId && (row.cached_m0_project_docs_hash ?? "") === (state.cachedM0ProjectDocsHash ?? "") && row.cached_m0_materialized_at === state.cachedM0MaterializedAt && row.cached_m0_session_facts_version === state.cachedM0SessionFactsVersion && (row.cached_m0_upgrade_state ?? null) === (state.cachedM0UpgradeState ?? null);
167749
+ return bufferEqualsNullable(row.cached_m0_bytes, state.cachedM0Bytes) && row.cached_m0_project_memory_epoch === state.cachedM0ProjectMemoryEpoch && row.cached_m0_project_user_profile_version === state.cachedM0ProjectUserProfileVersion && row.cached_m0_max_compartment_seq === state.cachedM0MaxCompartmentSeq && row.cached_m0_max_memory_id === state.cachedM0MaxMemoryId && row.cached_m0_max_mutation_id === state.cachedM0MaxMutationId && row.cached_m0_max_memory_mutation_id === state.cachedM0MaxMemoryMutationId && (row.cached_m0_project_docs_hash ?? "") === (state.cachedM0ProjectDocsHash ?? "") && row.cached_m0_materialized_at === state.cachedM0MaterializedAt && row.cached_m0_session_facts_version === state.cachedM0SessionFactsVersion && (row.cached_m0_upgrade_state ?? null) === (state.cachedM0UpgradeState ?? null) && (row.cached_m0_system_hash ?? "") === (state.cachedM0SystemHash ?? "") && (row.cached_m0_tool_set_hash ?? "") === (state.cachedM0ToolSetHash ?? "") && (row.cached_m0_model_key ?? "") === (state.cachedM0ModelKey ?? "");
167586
167750
  }
167587
167751
  function applyCachedRowToState(state, row) {
167588
167752
  const markers = markersFromCachedRow(row);
@@ -167601,6 +167765,9 @@ function applyCachedRowToState(state, row) {
167601
167765
  state.cachedM0MaterializedAt = markers.materializedAt;
167602
167766
  state.cachedM0SessionFactsVersion = markers.sessionFactsVersion;
167603
167767
  state.cachedM0UpgradeState = markers.upgradeState;
167768
+ state.cachedM0SystemHash = markers.systemHash;
167769
+ state.cachedM0ToolSetHash = markers.toolSetHash;
167770
+ state.cachedM0ModelKey = markers.modelKey;
167604
167771
  state.snapshotMarkers = markers;
167605
167772
  }
167606
167773
  function replayCachedM1(state) {
@@ -167717,7 +167884,8 @@ function injectM0M1(options) {
167717
167884
  sessionId: options.sessionId,
167718
167885
  state: options.state,
167719
167886
  projectPath: options.projectPath,
167720
- projectDirectory: options.projectDirectory
167887
+ projectDirectory: options.projectDirectory,
167888
+ hardSignals: options.hardSignals
167721
167889
  });
167722
167890
  let rematerialized = false;
167723
167891
  let contentionExhausted = false;
@@ -167775,7 +167943,10 @@ function injectM0M1(options) {
167775
167943
  m1Text = replayCachedM1(options.state);
167776
167944
  }
167777
167945
  const M0_DRIFT_RATIO_FLOOR = 2000;
167778
- if (!rematerialized && !contentionExhausted && m1Recomputed && options.isCacheBustingPass && (memoryUpdateCount > 40 || m1Text !== M1_EMPTY_PLACEHOLDER && m0Text.length >= M0_DRIFT_RATIO_FLOOR && m1Text.length > m0Text.length * 0.15)) {
167946
+ const M1_ABSOLUTE_CAP_RATIO = 0.2;
167947
+ const m1AbsoluteBudget = (options.historyBudgetTokens ?? DEFAULT_HISTORY_BUDGET_TOKENS) * M1_ABSOLUTE_CAP_RATIO;
167948
+ const m1OverAbsoluteCap = m1Text !== M1_EMPTY_PLACEHOLDER && estimateTokens(m1Text) > m1AbsoluteBudget;
167949
+ if (!rematerialized && !contentionExhausted && m1Recomputed && options.isCacheBustingPass && (memoryUpdateCount > 40 || m1OverAbsoluteCap || m1Text !== M1_EMPTY_PLACEHOLDER && m0Text.length >= M0_DRIFT_RATIO_FLOOR && m1Text.length > m0Text.length * 0.15)) {
167779
167950
  try {
167780
167951
  const refolded = materializeWithRetry(options);
167781
167952
  applyMarkersToState(options.state, refolded.m0Bytes, refolded.snapshotMarkers, refolded.m1Bytes);
@@ -167799,7 +167970,7 @@ function injectM0M1(options) {
167799
167970
  m1Text
167800
167971
  };
167801
167972
  }
167802
- var INJECTION_CACHE_MAX = 100, injectionCache, CONSTRAINT_KEYWORDS, MaterializeContentionError, RenderM1InvalidMarkersError, DEFAULT_HISTORY_BUDGET_TOKENS = 60000, DEFAULT_MEMORY_BUDGET_TOKENS = 8000, MEMORY_BLOCK_WRAPPER_TOKENS = 6, DEFAULT_USER_PROFILE_BUDGET_TOKENS = 4000, M0_EMPTY_BODY = "<session-history></session-history>", M1_EMPTY_PLACEHOLDER = "<session-history-since>(no new content since last materialization)</session-history-since>", maxCompartmentSeqStatements, maxMemoryIdStatements, legacyCompartmentCountStatements, m0CompartmentStatements, newCompartmentStatements, EMPTY_MAX_COMPARTMENT_SEQ = -1;
167973
+ var INJECTION_CACHE_MAX = 100, injectionCache, CONSTRAINT_KEYWORDS, EMPTY_HARD_SIGNALS, MaterializeContentionError, RenderM1InvalidMarkersError, DEFAULT_HISTORY_BUDGET_TOKENS = 60000, DEFAULT_MEMORY_BUDGET_TOKENS = 8000, MEMORY_BLOCK_WRAPPER_TOKENS = 6, DEFAULT_USER_PROFILE_BUDGET_TOKENS = 4000, M0_EMPTY_BODY = "<session-history></session-history>", M1_EMPTY_PLACEHOLDER = "<session-history-since>(no new content since last materialization)</session-history-since>", maxCompartmentSeqStatements, maxMemoryIdStatements, legacyCompartmentCountStatements, m0CompartmentStatements, newCompartmentStatements;
167803
167974
  var init_inject_compartments = __esm(async () => {
167804
167975
  init_compartment_storage();
167805
167976
  init_constants();
@@ -167815,6 +167986,13 @@ var init_inject_compartments = __esm(async () => {
167815
167986
  ]);
167816
167987
  injectionCache = new BoundedSessionMap(INJECTION_CACHE_MAX);
167817
167988
  CONSTRAINT_KEYWORDS = /\b(must|never|always|cannot|should not|must not)\b/i;
167989
+ EMPTY_HARD_SIGNALS = {
167990
+ systemHash: "",
167991
+ toolSetHash: "",
167992
+ modelKey: "",
167993
+ cacheExpired: false,
167994
+ lastResponseTime: 0
167995
+ };
167818
167996
  MaterializeContentionError = class MaterializeContentionError extends Error {
167819
167997
  retries;
167820
167998
  reason;
@@ -171220,6 +171398,10 @@ async function runMemoryMigration(deps) {
171220
171398
  const cleanupChildSession = async (sid) => {
171221
171399
  if (!sid)
171222
171400
  return;
171401
+ if (shouldKeepSubagents()) {
171402
+ sessionLog(parentSessionId, `memory-migration: KEEPING child session ${sid} (keep_subagents)`);
171403
+ return;
171404
+ }
171223
171405
  await client.session.delete({ path: { id: sid } }).catch((e) => {
171224
171406
  sessionLog(parentSessionId, `memory-migration: child cleanup failed: ${String(e)}`);
171225
171407
  });
@@ -172785,7 +172967,7 @@ async function runSidekick(deps) {
172785
172967
  }
172786
172968
  return null;
172787
172969
  } finally {
172788
- if (agentSessionId) {
172970
+ if (agentSessionId && !shouldKeepSubagents()) {
172789
172971
  await deps.client.session.delete({
172790
172972
  path: { id: agentSessionId }
172791
172973
  }).catch((error51) => {
@@ -173623,7 +173805,8 @@ function createLiveSessionState() {
173623
173805
  pendingMaterializationSessions: new Set,
173624
173806
  deferredMaterializationSessions: new Set,
173625
173807
  sessionDirectoryBySession: new Map,
173626
- recompProgressBySession: new Map
173808
+ recompProgressBySession: new Map,
173809
+ internalChildSessions: new Set
173627
173810
  };
173628
173811
  }
173629
173812
 
@@ -173836,13 +174019,14 @@ init_shared();
173836
174019
  init_assistant_message_extractor();
173837
174020
  init_logger();
173838
174021
  import { readFileSync as readFileSync11 } from "node:fs";
173839
- import { isAbsolute as isAbsolute3, join as join15, relative as relative2 } from "node:path";
174022
+ import { isAbsolute as isAbsolute4, join as join15, relative as relative2 } from "node:path";
174023
+ init_subagent_token_capture();
173840
174024
  init_aft_availability();
173841
174025
  init_project_key_files();
173842
174026
 
173843
174027
  // src/features/magic-context/key-files/read-history.ts
173844
174028
  import { realpathSync as realpathSync3 } from "node:fs";
173845
- import { relative, resolve as resolve5 } from "node:path";
174029
+ import { relative, resolve as resolve6 } from "node:path";
173846
174030
  function toMs(value) {
173847
174031
  if (typeof value === "number" && Number.isFinite(value))
173848
174032
  return value;
@@ -173879,7 +174063,7 @@ function coalesceRanges(ranges) {
173879
174063
  }
173880
174064
  function normalizeProjectRelativePath(projectPath, filePath) {
173881
174065
  const root = realpathSync3(projectPath);
173882
- const abs = filePath.startsWith("/") ? resolve5(filePath) : resolve5(root, filePath);
174066
+ const abs = filePath.startsWith("/") ? resolve6(filePath) : resolve6(root, filePath);
173883
174067
  let real = abs;
173884
174068
  try {
173885
174069
  real = realpathSync3(abs);
@@ -174247,11 +174431,13 @@ async function runKeyFilesLlm(args) {
174247
174431
  const text = extractLatestAssistantText(messages);
174248
174432
  if (!text)
174249
174433
  throw new Error("Dreamer returned no key-files output.");
174250
- return text;
174434
+ return { text, messages };
174251
174435
  } finally {
174252
- await args.client.session.delete({ path: { id: agentSessionId } }).catch(() => {
174253
- return;
174254
- });
174436
+ if (!shouldKeepSubagents()) {
174437
+ await args.client.session.delete({ path: { id: agentSessionId } }).catch(() => {
174438
+ return;
174439
+ });
174440
+ }
174255
174441
  }
174256
174442
  }
174257
174443
  async function runKeyFilesTask(args) {
@@ -174297,9 +174483,27 @@ async function runKeyFilesTask(args) {
174297
174483
  log(`[key-files] lease renewal threw: ${getErrorMessage(error51)}`);
174298
174484
  }
174299
174485
  }, 60000);
174486
+ let invocationRecorded = false;
174487
+ const llmStartedAt = Date.now();
174488
+ const recordKeyFilesInvocation = (params) => {
174489
+ if (!args.parentSessionId || invocationRecorded)
174490
+ return;
174491
+ invocationRecorded = true;
174492
+ recordChildInvocation({
174493
+ db: args.db,
174494
+ parentSessionId: args.parentSessionId,
174495
+ harness: getHarness(),
174496
+ subagent: "dreamer",
174497
+ task: "key files",
174498
+ startedAt: llmStartedAt,
174499
+ status: params.status,
174500
+ messages: params.messages,
174501
+ error: params.error
174502
+ });
174503
+ };
174300
174504
  try {
174301
174505
  try {
174302
- const raw = await runKeyFilesLlm({
174506
+ const { text: raw, messages: llmMessages } = await runKeyFilesLlm({
174303
174507
  client: args.client,
174304
174508
  parentSessionId: args.parentSessionId,
174305
174509
  projectPath,
@@ -174307,8 +174511,10 @@ async function runKeyFilesTask(args) {
174307
174511
  deadline: args.deadline,
174308
174512
  fallbackModels: args.fallbackModels
174309
174513
  });
174514
+ recordKeyFilesInvocation({ status: "completed", messages: llmMessages });
174310
174515
  validated = validateLlmOutput(raw, args.config, projectPath, new Set(candidates.map((candidate) => candidate.path)));
174311
174516
  } catch (error51) {
174517
+ recordKeyFilesInvocation({ status: "failed", error: error51 });
174312
174518
  log(`[key-files] LLM validation failed: ${getErrorMessage(error51)}`);
174313
174519
  throw error51;
174314
174520
  }
@@ -174407,7 +174613,8 @@ If no promotions are warranted, return empty arrays. Always consume reviewed can
174407
174613
  db: args.db,
174408
174614
  parentSessionId: args.parentSessionId,
174409
174615
  harness: "opencode",
174410
- subagent: "user_memory_review",
174616
+ subagent: "dreamer",
174617
+ task: "user memories",
174411
174618
  startedAt,
174412
174619
  status: params.status,
174413
174620
  messages: params.messages,
@@ -174531,7 +174738,7 @@ If no promotions are warranted, return empty arrays. Always consume reviewed can
174531
174738
  return result;
174532
174739
  } finally {
174533
174740
  clearInterval(leaseInterval);
174534
- if (agentSessionId) {
174741
+ if (agentSessionId && !shouldKeepSubagents()) {
174535
174742
  await args.client.session.delete({
174536
174743
  path: { id: agentSessionId },
174537
174744
  query: { directory: args.sessionDirectory }
@@ -174854,14 +175061,14 @@ async function runDream(args) {
174854
175061
  }
174855
175062
  } finally {
174856
175063
  clearInterval(leaseRenewalInterval);
174857
- if (agentSessionId && !taskFailed) {
175064
+ if (agentSessionId && !taskFailed && !shouldKeepSubagents()) {
174858
175065
  await args.client.session.delete({
174859
175066
  path: { id: agentSessionId }
174860
175067
  }).catch((error51) => {
174861
175068
  log("[dreamer] failed to delete child session:", error51);
174862
175069
  });
174863
- } else if (agentSessionId && taskFailed) {
174864
- log(`[dreamer] KEEPING failed child session ${agentSessionId} for task ${taskName} (debugging)`);
175070
+ } else if (agentSessionId && (taskFailed || shouldKeepSubagents())) {
175071
+ log(`[dreamer] KEEPING child session ${agentSessionId} for task ${taskName} (${taskFailed ? "failed" : "keep_subagents"})`);
174865
175072
  }
174866
175073
  }
174867
175074
  if (lostLease) {
@@ -175146,7 +175353,7 @@ Only include notes whose conditions you could definitively evaluate against exte
175146
175353
  parts: [{ type: "text", text: evaluationPrompt, synthetic: true }]
175147
175354
  }
175148
175355
  }, {
175149
- timeoutMs: Math.min(remainingMs, 300000),
175356
+ timeoutMs: Math.min(remainingMs, 5 * 60 * 1000),
175150
175357
  signal: abortController.signal,
175151
175358
  fallbackModels: args.fallbackModels,
175152
175359
  callContext: "dreamer:smart-notes"
@@ -175222,7 +175429,7 @@ Only include notes whose conditions you could definitively evaluate against exte
175222
175429
  });
175223
175430
  } finally {
175224
175431
  clearInterval(leaseInterval);
175225
- if (agentSessionId) {
175432
+ if (agentSessionId && !shouldKeepSubagents()) {
175226
175433
  await args.client.session.delete({
175227
175434
  path: { id: agentSessionId }
175228
175435
  }).catch(() => {});
@@ -175233,14 +175440,14 @@ var MAX_LEASE_RETRIES = 3;
175233
175440
  async function processDreamQueue(args) {
175234
175441
  const maxRuntimeMs = args.maxRuntimeMinutes * 60 * 1000;
175235
175442
  if (!hasActiveDreamLease(args.db)) {
175236
- clearStaleEntries(args.db, maxRuntimeMs + 1800000, args.projectIdentity);
175443
+ clearStaleEntries(args.db, maxRuntimeMs + 30 * 60 * 1000, args.projectIdentity);
175237
175444
  }
175238
175445
  const entry = dequeueNext(args.db, args.projectIdentity);
175239
175446
  if (!entry) {
175240
175447
  return null;
175241
175448
  }
175242
175449
  const projectDirectory = args.sessionDirectoryOverride ?? resolveDreamSessionDirectory(entry.projectIdentity);
175243
- log(`[dreamer] dequeued project ${entry.projectIdentity} (dir=${projectDirectory}), starting dream run`);
175450
+ log(`[dreamer] dequeued project ${entry.projectIdentity}, starting dream run`);
175244
175451
  let result;
175245
175452
  try {
175246
175453
  result = await runDream({
@@ -175364,6 +175571,7 @@ async function readGitCommits(directory, options = {}) {
175364
175571
  if (revision.startsWith("-")) {
175365
175572
  throw new Error(`readGitCommits: refusing revision that looks like an option: "${revision}"`);
175366
175573
  }
175574
+ const projectLabel = options.projectIdentity ?? "<project>";
175367
175575
  const args = [
175368
175576
  "log",
175369
175577
  revision,
@@ -175386,11 +175594,11 @@ async function readGitCommits(directory, options = {}) {
175386
175594
  stdout = result.stdout;
175387
175595
  } catch (error51) {
175388
175596
  const message = error51 instanceof Error ? error51.message : String(error51);
175389
- log(`[git-commits] readGitCommits failed at cwd=${directory}: ${message.slice(0, 500)}`);
175597
+ log(`[git-commits] readGitCommits failed for ${projectLabel}: ${message.slice(0, 500)}`);
175390
175598
  return [];
175391
175599
  }
175392
175600
  if (stdout.trim().length === 0) {
175393
- log(`[git-commits] readGitCommits returned empty stdout at cwd=${directory} (sinceMs=${options.sinceMs ?? "none"} args=${args.slice(0, 4).join(" ")})`);
175601
+ log(`[git-commits] readGitCommits returned empty stdout for ${projectLabel} (sinceMs=${options.sinceMs ?? "none"} args=${args.slice(0, 4).join(" ")})`);
175394
175602
  }
175395
175603
  return parseGitLogOutput(stdout);
175396
175604
  }
@@ -175576,7 +175784,8 @@ async function indexCommitsForProject(db, projectPath, directory, options) {
175576
175784
  const sinceMs = latestIndexed !== null ? Math.max(latestIndexed - 60000, Date.now() - options.sinceDays * MS_PER_DAY) : Date.now() - options.sinceDays * MS_PER_DAY;
175577
175785
  const commits = await readGitCommits(directory, {
175578
175786
  sinceMs,
175579
- maxCommits: options.maxCommits
175787
+ maxCommits: options.maxCommits,
175788
+ projectIdentity: projectPath
175580
175789
  });
175581
175790
  result.scanned = commits.length;
175582
175791
  if (commits.length === 0) {
@@ -175821,7 +176030,7 @@ async function startDreamScheduleTimer(args) {
175821
176030
  const isNewRegistration = !registeredProjects.has(args.directory);
175822
176031
  registeredProjects.set(args.directory, args);
175823
176032
  if (isNewRegistration) {
175824
- log(`[dreamer] registered project ${args.directory} (dreaming=${dreamingEnabled} embeddings=${embeddingSweepEnabled} commits=${commitIndexingEnabled}; total=${registeredProjects.size})`);
176033
+ log(`[dreamer] registered project ${args.projectIdentity} (dreaming=${dreamingEnabled} embeddings=${embeddingSweepEnabled} commits=${commitIndexingEnabled}; total=${registeredProjects.size})`);
175825
176034
  }
175826
176035
  if (!activeTimer) {
175827
176036
  log(`[dreamer] started independent schedule timer (every ${DREAM_TIMER_INTERVAL_MS / 60000}m)`);
@@ -175836,7 +176045,7 @@ async function startDreamScheduleTimer(args) {
175836
176045
  }
175837
176046
  return () => {
175838
176047
  registeredProjects.delete(args.directory);
175839
- log(`[dreamer] unregistered project ${args.directory} (remaining=${registeredProjects.size})`);
176048
+ log(`[dreamer] unregistered project ${args.projectIdentity} (remaining=${registeredProjects.size})`);
175840
176049
  if (registeredProjects.size === 0 && activeTimer) {
175841
176050
  clearInterval(activeTimer);
175842
176051
  activeTimer = null;
@@ -175884,7 +176093,7 @@ async function sweepProject(reg, origin, db, gitCommitEnabled = getProjectEmbedd
175884
176093
  return;
175885
176094
  }
175886
176095
  try {
175887
- log(`[dreamer] timer tick (${origin}) ${reg.directory} — checking schedule window "${reg.dreamerConfig.schedule}"`);
176096
+ log(`[dreamer] timer tick (${origin}) ${reg.projectIdentity} — checking schedule window "${reg.dreamerConfig.schedule}"`);
175888
176097
  checkScheduleAndEnqueue(db, reg.dreamerConfig.schedule, reg.projectIdentity);
175889
176098
  await processDreamQueue({
175890
176099
  db,
@@ -175899,7 +176108,7 @@ async function sweepProject(reg, origin, db, gitCommitEnabled = getProjectEmbedd
175899
176108
  fallbackModels: resolveFallbackChain(DREAMER_AGENT, reg.dreamerConfig.fallback_models)
175900
176109
  });
175901
176110
  } catch (error51) {
175902
- log(`[dreamer] timer-triggered queue processing failed for ${reg.directory}:`, error51);
176111
+ log(`[dreamer] timer-triggered queue processing failed for ${reg.projectIdentity}:`, error51);
175903
176112
  }
175904
176113
  }
175905
176114
  function startGitSweepLeaseRenewal(db, projectIdentity, holderId) {
@@ -175921,12 +176130,12 @@ async function sweepGitCommits(args) {
175921
176130
  const lease2 = acquireGitSweepLease(db, projectIdentity, holderId);
175922
176131
  if (!lease2.acquired) {
175923
176132
  const reason = lease2.reason === "cooldown_active" ? `cooldown active until ${lease2.nextAllowedAt}` : `lease held by ${lease2.leaseHolder ?? "another holder"} until ${lease2.leaseExpiresAt ?? "unknown"}`;
175924
- log(`[git-commits] sweep skipped for ${projectIdentity} (${directory}): ${reason}`);
176133
+ log(`[git-commits] sweep skipped for ${projectIdentity}: ${reason}`);
175925
176134
  return;
175926
176135
  }
175927
176136
  const startedAt = Date.now();
175928
176137
  const stopRenewal = startGitSweepLeaseRenewal(db, projectIdentity, holderId);
175929
- log(`[git-commits] sweep starting for ${directory} (project=${projectIdentity} sinceDays=${gitCommitIndexing.since_days} maxCommits=${gitCommitIndexing.max_commits})`);
176138
+ log(`[git-commits] sweep starting for ${projectIdentity} (sinceDays=${gitCommitIndexing.since_days} maxCommits=${gitCommitIndexing.max_commits})`);
175930
176139
  try {
175931
176140
  const result = await indexCommitsForProject(db, projectIdentity, directory, {
175932
176141
  sinceDays: gitCommitIndexing.since_days,
@@ -175946,7 +176155,7 @@ async function sweepGitCommits(args) {
175946
176155
  } catch (error51) {
175947
176156
  releaseGitSweepLease(db, projectIdentity, holderId);
175948
176157
  const elapsedMs = Date.now() - startedAt;
175949
- log(`[git-commits] sweep failed for ${directory} after ${elapsedMs}ms: ${error51 instanceof Error ? error51.message : String(error51)}`);
176158
+ log(`[git-commits] sweep failed for ${projectIdentity} after ${elapsedMs}ms: ${error51 instanceof Error ? error51.message : String(error51)}`);
175950
176159
  } finally {
175951
176160
  stopRenewal();
175952
176161
  }
@@ -176590,6 +176799,7 @@ function createTagger() {
176590
176799
  // src/hooks/magic-context/hook.ts
176591
176800
  init_magic_context();
176592
176801
  init_project_identity();
176802
+ init_tool_definition_tokens();
176593
176803
  await init_storage();
176594
176804
  init_logger();
176595
176805
  init_resolve_fallbacks();
@@ -177460,7 +177670,8 @@ function getSessionCreatedInfo(properties) {
177460
177670
  id: info.id,
177461
177671
  parentID: info.parentID,
177462
177672
  providerID: typeof info.providerID === "string" ? info.providerID : undefined,
177463
- modelID: typeof info.modelID === "string" ? info.modelID : undefined
177673
+ modelID: typeof info.modelID === "string" ? info.modelID : undefined,
177674
+ title: typeof info.title === "string" ? info.title : undefined
177464
177675
  };
177465
177676
  }
177466
177677
  function getMessageUpdatedAssistantInfo(properties) {
@@ -178570,7 +178781,7 @@ async function runCompartmentPhase(args) {
178570
178781
  async function awaitCompartmentRun(activeRun, reason) {
178571
178782
  sessionLog(args.sessionId, reason);
178572
178783
  const timeoutMs = args.historianTimeoutMs ?? 120000;
178573
- const timeout = new Promise((resolve6) => setTimeout(() => resolve6("timeout"), timeoutMs));
178784
+ const timeout = new Promise((resolve7) => setTimeout(() => resolve7("timeout"), timeoutMs));
178574
178785
  const result = await Promise.race([activeRun.promise.then(() => "done"), timeout]);
178575
178786
  if (result === "timeout") {
178576
178787
  sessionLog(args.sessionId, `transform: compartment await timed out after ${timeoutMs}ms — proceeding without waiting`);
@@ -180053,10 +180264,10 @@ var AUTO_SEARCH_TIMEOUT_MS = 3000;
180053
180264
  async function unifiedSearchWithTimeout(db, sessionId, projectPath, prompt, options, timeoutMs) {
180054
180265
  const controller = new AbortController;
180055
180266
  let timer;
180056
- const timeoutPromise = new Promise((resolve6) => {
180267
+ const timeoutPromise = new Promise((resolve7) => {
180057
180268
  timer = setTimeout(() => {
180058
180269
  controller.abort();
180059
- resolve6(null);
180270
+ resolve7(null);
180060
180271
  }, timeoutMs);
180061
180272
  });
180062
180273
  try {
@@ -180750,7 +180961,8 @@ async function runPostTransformPhase(args) {
180750
180961
  memoryInjectionBudgetTokens: args.m0M1.memoryInjectionBudgetTokens,
180751
180962
  historyBudgetTokens: args.m0M1.historyBudgetTokens,
180752
180963
  keyFiles: args.m0M1.keyFiles,
180753
- isCacheBustingPass
180964
+ isCacheBustingPass,
180965
+ hardSignals: args.m0M1.hardSignals
180754
180966
  });
180755
180967
  if (result.injected) {
180756
180968
  sessionLog(args.sessionId, `transform: injected m[0]/m[1] (rematerialized=${result.m0RematerializedThisPass}, reason=${result.decision.reason ?? "cache_hit"})`);
@@ -181124,6 +181336,10 @@ function createTransform(deps) {
181124
181336
  return;
181125
181337
  }
181126
181338
  logTransformTiming(sessionId, "getOrCreateSessionMeta", tMeta);
181339
+ if (deps.internalChildSessions?.has(sessionId)) {
181340
+ sessionLog(sessionId, "transform skipped (internal magic-context child session)");
181341
+ return;
181342
+ }
181127
181343
  const reducedMode = sessionMeta.isSubagent;
181128
181344
  const fullFeatureMode = !reducedMode;
181129
181345
  let sessionDirectory = deps.directory ?? "";
@@ -181494,6 +181710,22 @@ Historian previously failed ${historianFailureState.failureCount} time(s), so Ma
181494
181710
  const compartmentInProgress = compartmentPhase.compartmentInProgress;
181495
181711
  sessionMeta = { ...sessionMeta, compartmentInProgress };
181496
181712
  logTransformTiming(sessionId, "compartmentPhase", tCompartmentPhase);
181713
+ const hardModel = deps.liveModelBySession?.get(sessionId);
181714
+ const hardModelKey = hardModel ? `${hardModel.providerID}/${hardModel.modelID}` : "";
181715
+ const hardToolSetHash = deps.getToolSetHash?.(sessionId) ?? "";
181716
+ const hardSystemHash = typeof sessionMeta.systemPromptHash === "string" ? sessionMeta.systemPromptHash : "";
181717
+ let hardTtlMs = 5 * 60 * 1000;
181718
+ try {
181719
+ hardTtlMs = parseCacheTtl(sessionMeta.cacheTtl);
181720
+ } catch {}
181721
+ const hardCacheExpired = sessionMeta.lastResponseTime > 0 && Date.now() - sessionMeta.lastResponseTime >= hardTtlMs;
181722
+ const m0HardSignals = {
181723
+ systemHash: hardSystemHash,
181724
+ toolSetHash: hardToolSetHash,
181725
+ modelKey: hardModelKey,
181726
+ cacheExpired: hardCacheExpired,
181727
+ lastResponseTime: sessionMeta.lastResponseTime
181728
+ };
181497
181729
  const lateActiveRunBlocksMaterialization = getActiveCompartmentRun(sessionId) !== undefined && contextUsageEarly.percentage < FORCE_MATERIALIZE_PERCENTAGE;
181498
181730
  const canConsumeDeferredLate = canConsumeDeferredOnThisPass({
181499
181731
  schedulerDecision: midTurnAdjustedSchedulerDecision,
@@ -181557,7 +181789,8 @@ Historian previously failed ${historianFailureState.failureCount} time(s), so Ma
181557
181789
  keyFiles: {
181558
181790
  enabled: deps.experimentalPinKeyFiles === true,
181559
181791
  tokenBudget: deps.experimentalPinKeyFilesTokenBudget ?? 1e4
181560
- }
181792
+ },
181793
+ hardSignals: m0HardSignals
181561
181794
  }
181562
181795
  });
181563
181796
  logTransformTiming(sessionId, "postTransformPhase", tPostProcess);
@@ -181719,6 +181952,7 @@ function truncateHistorianEmergencyError(error51) {
181719
181952
 
181720
181953
  // src/hooks/magic-context/event-handler.ts
181721
181954
  var CONTEXT_USAGE_TTL_MS = 60 * 60 * 1000;
181955
+ var INTERNAL_CHILD_TITLE_PREFIX = "magic-context-";
181722
181956
  function formatTokens(value) {
181723
181957
  return value.toLocaleString();
181724
181958
  }
@@ -181783,6 +182017,10 @@ function createEventHandler2(deps) {
181783
182017
  if (!info) {
181784
182018
  return;
181785
182019
  }
182020
+ if (deps.internalChildSessions && info.parentID.length > 0 && typeof info.title === "string" && info.title.startsWith(INTERNAL_CHILD_TITLE_PREFIX)) {
182021
+ deps.internalChildSessions.add(info.id);
182022
+ sessionLog(info.id, `marked internal magic-context child (title="${info.title}") — exempt from transform + injection`);
182023
+ }
181786
182024
  try {
181787
182025
  const modelKey = resolveModelKey(info.providerID, info.modelID);
181788
182026
  updateSessionMeta(deps.db, info.id, {
@@ -182199,11 +182437,10 @@ await __promiseAll([
182199
182437
  ]);
182200
182438
 
182201
182439
  // src/hooks/magic-context/text-complete.ts
182202
- var LEADING_TAG_PREFIX_REGEX = /^(\u00a7\d+\u00a7\s*)+/;
182203
- var SECTION_CHAR_REGEX = /\u00a7/g;
182440
+ init_tag_content_primitives();
182204
182441
  function createTextCompleteHandler() {
182205
182442
  return async (_input, output) => {
182206
- output.text = output.text.replace(LEADING_TAG_PREFIX_REGEX, "").replace(SECTION_CHAR_REGEX, "");
182443
+ output.text = stripPersistedAssistantText(output.text);
182207
182444
  };
182208
182445
  }
182209
182446
 
@@ -182547,6 +182784,9 @@ function clearSystemPromptHashSession(sessionId, handleMaps) {
182547
182784
  function isInternalOpenCodeAgent(systemPromptContent) {
182548
182785
  return systemPromptContent.includes("You are a title generator. You output ONLY a thread title.") || systemPromptContent.includes("Summarize what was done in this conversation. Write like a pull request description.") || systemPromptContent.includes("You are an anchored context summarization assistant for coding sessions.");
182549
182786
  }
182787
+ function isMagicContextInternalAgent(systemPromptContent) {
182788
+ return systemPromptContent.includes("You are Historian — the hippocampus of a long-running coding agent.") || systemPromptContent.includes("You are a memory maintenance agent for the magic-context system.") || systemPromptContent.includes("You are Sidekick, a focused memory-retrieval subagent for an AI coding assistant.") || systemPromptContent.includes("You are a file importance evaluator. Given read statistics about files");
182789
+ }
182550
182790
  function createSystemPromptHashHandler(deps) {
182551
182791
  const stickyDateBySession = new Map;
182552
182792
  const handler = async (input, output) => {
@@ -182559,6 +182799,10 @@ function createSystemPromptHashHandler(deps) {
182559
182799
  sessionLog(sessionId, "system-prompt-hash skipped (OpenCode internal agent: title/summary/compaction)");
182560
182800
  return;
182561
182801
  }
182802
+ if (deps.internalChildSessions?.has(sessionId) || isMagicContextInternalAgent(fullPromptForDetection)) {
182803
+ sessionLog(sessionId, "system-prompt-hash skipped (Magic Context internal child: historian/dreamer/sidekick/migration)");
182804
+ return;
182805
+ }
182562
182806
  const injectionEnabled = deps.injectionEnabled !== false;
182563
182807
  const skipSignatures = deps.injectionSkipSignatures ?? [];
182564
182808
  if (!injectionEnabled) {
@@ -182817,6 +183061,7 @@ function createMagicContextHook(deps) {
182817
183061
  const liveModelBySession = deps.liveSessionState?.liveModelBySession ?? new Map;
182818
183062
  const agentBySession = deps.liveSessionState?.agentBySession ?? new Map;
182819
183063
  const sessionDirectoryBySession = deps.liveSessionState?.sessionDirectoryBySession ?? new Map;
183064
+ const internalChildSessions = deps.liveSessionState?.internalChildSessions ?? new Set;
182820
183065
  const recompProgressBySession = deps.liveSessionState?.recompProgressBySession ?? new Map;
182821
183066
  const recentReduceBySession = new Map;
182822
183067
  const toolUsageSinceUserTurn = new Map;
@@ -182848,7 +183093,8 @@ function createMagicContextHook(deps) {
182848
183093
  pendingMaterializationSessions,
182849
183094
  deferredMaterializationSessions,
182850
183095
  sessionDirectoryBySession,
182851
- recompProgressBySession
183096
+ recompProgressBySession,
183097
+ internalChildSessions
182852
183098
  },
182853
183099
  directory: deps.directory,
182854
183100
  historianChunkTokens: getHistorianChunkTokens(),
@@ -182893,6 +183139,7 @@ function createMagicContextHook(deps) {
182893
183139
  deferredMaterializationSessions,
182894
183140
  lastHeuristicsTurnId,
182895
183141
  commitSeenLastPass,
183142
+ internalChildSessions,
182896
183143
  client: deps.client,
182897
183144
  directory: deps.directory,
182898
183145
  memoryConfig: deps.config.memory ? {
@@ -182912,6 +183159,12 @@ function createMagicContextHook(deps) {
182912
183159
  const model = liveModelBySession.get(sessionId);
182913
183160
  return resolveModelKey(model?.providerID, model?.modelID);
182914
183161
  },
183162
+ getToolSetHash: (sessionId) => {
183163
+ const model = liveModelBySession.get(sessionId);
183164
+ if (!model)
183165
+ return "";
183166
+ return getCurrentToolSetHash(model.providerID, model.modelID, agentBySession.get(sessionId));
183167
+ },
182915
183168
  getFallbackModelId: (sessionId) => {
182916
183169
  const model = liveModelBySession.get(sessionId);
182917
183170
  return model ? `${model.providerID}/${model.modelID}` : undefined;
@@ -182944,6 +183197,7 @@ function createMagicContextHook(deps) {
182944
183197
  tagger: deps.tagger,
182945
183198
  db,
182946
183199
  client: deps.client,
183200
+ internalChildSessions,
182947
183201
  getNotificationParams: (sessionId) => getLiveNotificationParams(sessionId, liveModelBySession, variantBySession, agentBySession),
182948
183202
  nudgePlacements,
182949
183203
  onSessionCacheInvalidated: (sessionId) => {
@@ -182961,6 +183215,7 @@ function createMagicContextHook(deps) {
182961
183215
  recompProgressBySession.delete(sessionId);
182962
183216
  recentReduceBySession.delete(sessionId);
182963
183217
  toolUsageSinceUserTurn.delete(sessionId);
183218
+ internalChildSessions.delete(sessionId);
182964
183219
  }
182965
183220
  });
182966
183221
  const runDreamQueueInBackground = () => {
@@ -183071,6 +183326,7 @@ function createMagicContextHook(deps) {
183071
183326
  injectionSkipSignatures: deps.config.system_prompt_injection?.skip_signatures ?? [
183072
183327
  "<!-- magic-context: skip -->"
183073
183328
  ],
183329
+ internalChildSessions,
183074
183330
  experimentalUserMemories: deps.config.dreamer?.user_memories?.enabled,
183075
183331
  experimentalPinKeyFiles: deps.config.dreamer?.pin_key_files?.enabled ?? false,
183076
183332
  experimentalPinKeyFilesTokenBudget: deps.config.dreamer?.pin_key_files?.token_budget,
@@ -185238,7 +185494,7 @@ class MagicContextRpcServer {
185238
185494
  this.handlers.set(method, handler);
185239
185495
  }
185240
185496
  async start() {
185241
- return new Promise((resolve6, reject) => {
185497
+ return new Promise((resolve7, reject) => {
185242
185498
  const server = createServer((req, res) => this.dispatch(req, res));
185243
185499
  server.on("error", (err) => {
185244
185500
  log(`[rpc] server error: ${err.message}`);
@@ -185268,7 +185524,7 @@ class MagicContextRpcServer {
185268
185524
  } catch (err) {
185269
185525
  log(`[rpc] failed to write port file: ${err}`);
185270
185526
  }
185271
- resolve6(this.port);
185527
+ resolve7(this.port);
185272
185528
  });
185273
185529
  server.unref();
185274
185530
  });
@@ -185361,6 +185617,7 @@ var plugin = async (ctx) => {
185361
185617
  cacheSizeMb: pluginConfig.sqlite.cache_size_mb,
185362
185618
  mmapSizeMb: pluginConfig.sqlite.mmap_size_mb
185363
185619
  });
185620
+ setKeepSubagents(pluginConfig.keep_subagents === true);
185364
185621
  const autoUpdateAbort = new AbortController;
185365
185622
  process.once("exit", () => {
185366
185623
  autoUpdateAbort.abort();