@cortexkit/opencode-magic-context 0.22.3 → 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 (34) 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/key-files/aft-availability.d.ts.map +1 -1
  5. package/dist/features/magic-context/key-files/identify-key-files.d.ts.map +1 -1
  6. package/dist/features/magic-context/memory/memory-migration.d.ts.map +1 -1
  7. package/dist/features/magic-context/migrations.d.ts.map +1 -1
  8. package/dist/features/magic-context/sidekick/agent.d.ts.map +1 -1
  9. package/dist/features/magic-context/storage-db.d.ts +1 -1
  10. package/dist/features/magic-context/storage-db.d.ts.map +1 -1
  11. package/dist/features/magic-context/storage-meta-session.d.ts.map +1 -1
  12. package/dist/features/magic-context/storage-meta-shared.d.ts +7 -1
  13. package/dist/features/magic-context/storage-meta-shared.d.ts.map +1 -1
  14. package/dist/features/magic-context/tool-definition-tokens.d.ts +21 -0
  15. package/dist/features/magic-context/tool-definition-tokens.d.ts.map +1 -1
  16. package/dist/features/magic-context/types.d.ts +4 -0
  17. package/dist/features/magic-context/types.d.ts.map +1 -1
  18. package/dist/features/magic-context/user-memory/review-user-memories.d.ts.map +1 -1
  19. package/dist/hooks/magic-context/compartment-runner-historian.d.ts.map +1 -1
  20. package/dist/hooks/magic-context/hook.d.ts.map +1 -1
  21. package/dist/hooks/magic-context/inject-compartments.d.ts +41 -0
  22. package/dist/hooks/magic-context/inject-compartments.d.ts.map +1 -1
  23. package/dist/hooks/magic-context/transform-postprocess-phase.d.ts +2 -1
  24. package/dist/hooks/magic-context/transform-postprocess-phase.d.ts.map +1 -1
  25. package/dist/hooks/magic-context/transform.d.ts +8 -0
  26. package/dist/hooks/magic-context/transform.d.ts.map +1 -1
  27. package/dist/index.d.ts.map +1 -1
  28. package/dist/index.js +268 -72
  29. package/dist/plugin/hooks/create-session-hooks.d.ts.map +1 -1
  30. package/dist/shared/keep-subagents.d.ts +7 -0
  31. package/dist/shared/keep-subagents.d.ts.map +1 -0
  32. package/package.json +1 -1
  33. package/src/shared/keep-subagents.test.ts +39 -0
  34. 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"
@@ -150113,6 +150141,18 @@ function keyFor(providerID, modelID, agentName) {
150113
150141
  function fingerprintFor(description, parameters) {
150114
150142
  return createHash3("sha256").update(description).update("\x00").update(stableStringify(parameters)).digest("hex");
150115
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
+ }
150116
150156
  function setDatabase(db) {
150117
150157
  persistenceDb = db;
150118
150158
  cachedInsertStmt = null;
@@ -150906,6 +150946,9 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
150906
150946
  cached_m0_materialized_at INTEGER,
150907
150947
  cached_m0_session_facts_version INTEGER,
150908
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,
150909
150952
  cached_m0_last_baseline_end_message_id TEXT,
150910
150953
  upgrade_reminded_at INTEGER,
150911
150954
  pi_stable_id_scheme INTEGER
@@ -151097,6 +151140,9 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
151097
151140
  ensureColumn(db, "session_meta", "cached_m0_materialized_at", "INTEGER");
151098
151141
  ensureColumn(db, "session_meta", "cached_m0_session_facts_version", "INTEGER");
151099
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");
151100
151146
  ensureColumn(db, "session_meta", "cached_m0_last_baseline_end_message_id", "TEXT");
151101
151147
  ensureColumn(db, "session_meta", "upgrade_reminded_at", "INTEGER");
151102
151148
  db.exec(`
@@ -151301,7 +151347,7 @@ function getDatabasePersistenceError(db) {
151301
151347
  return null;
151302
151348
  return persistenceErrorByDatabase.get(db) ?? null;
151303
151349
  }
151304
- var databases, persistenceByDatabase, persistenceErrorByDatabase, lastSchemaFenceRejection = null, LATEST_SUPPORTED_VERSION = 29, sqlitePragmaConfig;
151350
+ var databases, persistenceByDatabase, persistenceErrorByDatabase, lastSchemaFenceRejection = null, LATEST_SUPPORTED_VERSION = 30, sqlitePragmaConfig;
151305
151351
  var init_storage_db = __esm(async () => {
151306
151352
  init_data_path();
151307
151353
  init_logger();
@@ -152124,6 +152170,28 @@ var init_migrations = __esm(async () => {
152124
152170
  db.exec("ALTER TABLE notes ADD COLUMN anchor_ordinal INTEGER");
152125
152171
  }
152126
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
+ }
152127
152195
  }
152128
152196
  ];
152129
152197
  LATEST_MIGRATION_VERSION = MIGRATIONS.reduce((max, m) => Math.max(max, m.version), 0);
@@ -153042,6 +153110,9 @@ var init_storage_meta_session = __esm(async () => {
153042
153110
  cached_m0_materialized_at: "NULL AS cached_m0_materialized_at",
153043
153111
  cached_m0_session_facts_version: "NULL AS cached_m0_session_facts_version",
153044
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",
153045
153116
  last_observed_model_key: "NULL AS last_observed_model_key",
153046
153117
  upgrade_reminded_at: "NULL AS upgrade_reminded_at"
153047
153118
  };
@@ -163018,25 +163089,56 @@ var init_conflict_warning_hook = __esm(() => {
163018
163089
  // src/features/magic-context/key-files/aft-availability.ts
163019
163090
  import { existsSync as existsSync12, readFileSync as readFileSync10 } from "node:fs";
163020
163091
  import { homedir as homedir8 } from "node:os";
163021
- 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";
163022
163094
  function parseConfig(path6) {
163023
163095
  if (!existsSync12(path6))
163024
163096
  return null;
163025
163097
  return import_comment_json3.parse(readFileSync10(path6, "utf-8"));
163026
163098
  }
163027
- 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) {
163028
163125
  const value = Array.isArray(entry) ? entry[0] : entry;
163029
- 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);
163030
163132
  }
163031
- function hasAftInArray(value) {
163032
- return Array.isArray(value) && value.some(entryMatchesAft);
163133
+ function hasAftInArray(value, configDir) {
163134
+ return Array.isArray(value) && value.some((entry) => entryMatchesAft(entry, configDir));
163033
163135
  }
163034
- function hasAftAtKeys(value, keys) {
163136
+ function hasAftAtKeys(value, keys, configDir) {
163035
163137
  if (!value || typeof value !== "object")
163036
163138
  return false;
163037
163139
  const record2 = value;
163038
163140
  for (const key of keys) {
163039
- if (hasAftInArray(record2[key]))
163141
+ if (hasAftInArray(record2[key], configDir))
163040
163142
  return true;
163041
163143
  }
163042
163144
  return false;
@@ -163053,7 +163155,8 @@ function getAftAvailability() {
163053
163155
  for (const path6 of opencodePaths) {
163054
163156
  try {
163055
163157
  const config2 = parseConfig(path6);
163056
- if (hasAftAtKeys(config2, ["plugin", "plugins", "mcp", "mcp_servers"])) {
163158
+ const configDir = join14(path6, "..");
163159
+ if (hasAftAtKeys(config2, ["plugin", "plugins", "mcp", "mcp_servers"], configDir)) {
163057
163160
  opencode = true;
163058
163161
  break;
163059
163162
  }
@@ -163063,12 +163166,13 @@ function getAftAvailability() {
163063
163166
  for (const path6 of piPaths) {
163064
163167
  try {
163065
163168
  const config2 = parseConfig(path6);
163066
- if (hasAftAtKeys(config2, ["packages", "extensions"])) {
163169
+ const configDir = join14(path6, "..");
163170
+ if (hasAftAtKeys(config2, ["packages", "extensions"], configDir)) {
163067
163171
  pi = true;
163068
163172
  break;
163069
163173
  }
163070
163174
  const agent = config2?.agent;
163071
- if (hasAftAtKeys(agent, ["packages", "extensions"])) {
163175
+ if (hasAftAtKeys(agent, ["packages", "extensions"], configDir)) {
163072
163176
  pi = true;
163073
163177
  break;
163074
163178
  }
@@ -163085,9 +163189,10 @@ function getAftAvailability() {
163085
163189
  function isAftAvailable() {
163086
163190
  return getAftAvailability().available;
163087
163191
  }
163088
- var import_comment_json3, overrideAvailability = null;
163192
+ var import_comment_json3, overrideAvailability = null, AFT_NAME_NEEDLES;
163089
163193
  var init_aft_availability = __esm(() => {
163090
163194
  import_comment_json3 = __toESM(require_src2(), 1);
163195
+ AFT_NAME_NEEDLES = ["@cortexkit/aft", "aft-opencode", "aft-pi"];
163091
163196
  });
163092
163197
 
163093
163198
  // src/features/magic-context/memory/storage-memory-embeddings.ts
@@ -163772,7 +163877,7 @@ async function acquireModelLoadLock(lockPath) {
163772
163877
  if (Date.now() - waitStart > MAX_LOCK_WAIT_MS) {
163773
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.`);
163774
163879
  }
163775
- await new Promise((resolve6) => setTimeout(resolve6, LOCK_POLL_MS));
163880
+ await new Promise((resolve7) => setTimeout(resolve7, LOCK_POLL_MS));
163776
163881
  }
163777
163882
  }
163778
163883
  }
@@ -163941,7 +164046,7 @@ class LocalEmbeddingProvider {
163941
164046
  }
163942
164047
  const delayMs = 300 * attempt + Math.floor(Math.random() * 200);
163943
164048
  log(`[magic-context] embedding model load attempt ${attempt}/${MAX_ATTEMPTS} failed transiently, retrying in ${delayMs}ms`);
163944
- await new Promise((resolve6) => setTimeout(resolve6, delayMs));
164049
+ await new Promise((resolve7) => setTimeout(resolve7, delayMs));
163945
164050
  }
163946
164051
  }
163947
164052
  if (this.pipeline) {
@@ -163969,8 +164074,8 @@ class LocalEmbeddingProvider {
163969
164074
  if (this.inFlight === 0) {
163970
164075
  return Promise.resolve();
163971
164076
  }
163972
- return new Promise((resolve6) => {
163973
- this.inFlightWaiters.push(resolve6);
164077
+ return new Promise((resolve7) => {
164078
+ this.inFlightWaiters.push(resolve7);
163974
164079
  });
163975
164080
  }
163976
164081
  finishInFlight() {
@@ -164957,7 +165062,7 @@ async function refreshModelLimitsFromApi(client, options) {
164957
165062
  if (ok)
164958
165063
  return;
164959
165064
  if (attempt < attempts) {
164960
- await new Promise((resolve6) => setTimeout(resolve6, delayMs));
165065
+ await new Promise((resolve7) => setTimeout(resolve7, delayMs));
164961
165066
  }
164962
165067
  }
164963
165068
  }
@@ -165943,12 +166048,12 @@ async function runHistorianPrompt(args) {
165943
166048
  error: `Historian failed while processing this session: ${desc.brief}`
165944
166049
  };
165945
166050
  } finally {
165946
- if (agentSessionId && outcomeOk) {
166051
+ if (agentSessionId && outcomeOk && !shouldKeepSubagents()) {
165947
166052
  await client.session.delete({ path: { id: agentSessionId } }).catch((e) => {
165948
166053
  sessionLog(parentSessionId, "compartment agent: session cleanup failed", getErrorMessage(e));
165949
166054
  });
165950
- } else if (agentSessionId && !outcomeOk) {
165951
- 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`);
165952
166057
  }
165953
166058
  }
165954
166059
  }
@@ -166027,8 +166132,8 @@ function isTransientHistorianPromptError(message) {
166027
166132
  ].some((token) => normalized.includes(token));
166028
166133
  }
166029
166134
  function sleep(ms) {
166030
- return new Promise((resolve6) => {
166031
- setTimeout(resolve6, ms);
166135
+ return new Promise((resolve7) => {
166136
+ setTimeout(resolve7, ms);
166032
166137
  });
166033
166138
  }
166034
166139
  function cleanupHistorianDump(sessionId, dumpPath) {
@@ -167037,12 +167142,6 @@ function getMaxCompartmentSeq(db, sessionId) {
167037
167142
  const row = cachedStatement(maxCompartmentSeqStatements, db, "SELECT COALESCE(MAX(sequence), -1) AS s FROM compartments WHERE session_id = ?").get(sessionId);
167038
167143
  return numberFromRow(row, "s");
167039
167144
  }
167040
- function normalizeCachedMaxCompartmentSeq(db, sessionId, stored) {
167041
- if (stored === 0 && getMaxCompartmentSeq(db, sessionId) === EMPTY_MAX_COMPARTMENT_SEQ) {
167042
- return EMPTY_MAX_COMPARTMENT_SEQ;
167043
- }
167044
- return stored;
167045
- }
167046
167145
  function getMaxMemoryId(db, projectPath) {
167047
167146
  if (!projectPath)
167048
167147
  return 0;
@@ -167066,6 +167165,7 @@ function getGlobalUserProfileVersion(db) {
167066
167165
  }
167067
167166
  function readCurrentM0SnapshotMarkers(args) {
167068
167167
  const projectDirectory = args.projectDirectory ?? args.projectPath ?? "";
167168
+ const hard = args.hardSignals ?? EMPTY_HARD_SIGNALS;
167069
167169
  return {
167070
167170
  projectMemoryEpoch: getProjectMemoryEpoch(args.db, args.projectPath),
167071
167171
  projectUserProfileVersion: getGlobalUserProfileVersion(args.db),
@@ -167076,7 +167176,10 @@ function readCurrentM0SnapshotMarkers(args) {
167076
167176
  projectDocsHash: projectDirectory ? computeProjectDocsHash(projectDirectory) : "",
167077
167177
  materializedAt: Date.now(),
167078
167178
  sessionFactsVersion: getSessionFactsVersion(args.db, args.sessionId),
167079
- 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
167080
167183
  };
167081
167184
  }
167082
167185
  function snapshotMarkersFromCachedM0(state) {
@@ -167106,7 +167209,10 @@ function snapshotMarkersFromCachedM0(state) {
167106
167209
  projectDocsHash: state.cachedM0ProjectDocsHash ?? "",
167107
167210
  materializedAt: state.cachedM0MaterializedAt ?? 0,
167108
167211
  sessionFactsVersion: state.cachedM0SessionFactsVersion,
167109
- upgradeState: state.cachedM0UpgradeState
167212
+ upgradeState: state.cachedM0UpgradeState,
167213
+ systemHash: state.cachedM0SystemHash ?? "",
167214
+ toolSetHash: state.cachedM0ToolSetHash ?? "",
167215
+ modelKey: state.cachedM0ModelKey ?? ""
167110
167216
  };
167111
167217
  }
167112
167218
  function mustMaterialize(args) {
@@ -167114,16 +167220,22 @@ function mustMaterialize(args) {
167114
167220
  return { value: true, reason: "first_render" };
167115
167221
  if (!args.state.cachedM1Bytes)
167116
167222
  return { value: true, reason: "cached_m1_missing" };
167223
+ const hard = args.hardSignals ?? EMPTY_HARD_SIGNALS;
167117
167224
  const current = readCurrentM0SnapshotMarkers(args);
167118
- if (args.state.cachedM0ProjectMemoryEpoch !== current.projectMemoryEpoch) {
167119
- 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" };
167120
167230
  }
167121
- if (args.state.cachedM0ProjectUserProfileVersion !== current.projectUserProfileVersion) {
167122
- return { value: true, reason: "project_user_profile_version" };
167231
+ if (hard.toolSetHash !== "" && hard.toolSetHash !== (args.state.cachedM0ToolSetHash ?? "")) {
167232
+ return { value: true, reason: "tool_set_hash" };
167123
167233
  }
167124
- const cachedMaxSeq = args.state.cachedM0MaxCompartmentSeq === null ? null : normalizeCachedMaxCompartmentSeq(args.db, args.sessionId, args.state.cachedM0MaxCompartmentSeq);
167125
- if (cachedMaxSeq !== current.maxCompartmentSeq) {
167126
- return { value: true, reason: "max_compartment_seq" };
167234
+ if (hard.cacheExpired && hard.lastResponseTime > 0 && hard.lastResponseTime > (args.state.cachedM0MaterializedAt ?? 0)) {
167235
+ return { value: true, reason: "ttl_idle" };
167236
+ }
167237
+ if (args.state.cachedM0ProjectMemoryEpoch !== current.projectMemoryEpoch) {
167238
+ return { value: true, reason: "project_memory_epoch" };
167127
167239
  }
167128
167240
  if (args.state.cachedM0MaxMutationId !== current.maxMutationId) {
167129
167241
  return { value: true, reason: "max_mutation_id" };
@@ -167312,6 +167424,9 @@ function applyMarkersToState(state, m0Bytes, markers, m1Bytes) {
167312
167424
  state.cachedM0MaterializedAt = markers.materializedAt;
167313
167425
  state.cachedM0SessionFactsVersion = markers.sessionFactsVersion;
167314
167426
  state.cachedM0UpgradeState = markers.upgradeState;
167427
+ state.cachedM0SystemHash = markers.systemHash;
167428
+ state.cachedM0ToolSetHash = markers.toolSetHash;
167429
+ state.cachedM0ModelKey = markers.modelKey;
167315
167430
  state.snapshotMarkers = markers;
167316
167431
  }
167317
167432
  function historySliceTokens(m0Text) {
@@ -167336,7 +167451,8 @@ function materializeM0(options) {
167336
167451
  db: options.db,
167337
167452
  sessionId: options.sessionId,
167338
167453
  projectPath,
167339
- projectDirectory
167454
+ projectDirectory,
167455
+ hardSignals: options.hardSignals
167340
167456
  });
167341
167457
  docs = projectDirectory ? readProjectDocsCanonical(projectDirectory) : { renderedBlock: "", canonicalHash: "" };
167342
167458
  snapshotMarkers.projectDocsHash = docs.canonicalHash;
@@ -167402,7 +167518,10 @@ function materializeM0(options) {
167402
167518
  projectDocsHash: phase3ProjectDocsHash,
167403
167519
  materializedAt: Date.now(),
167404
167520
  sessionFactsVersion: getSessionFactsVersion(options.db, options.sessionId),
167405
- 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
167406
167525
  };
167407
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;
167408
167527
  if (stale) {
@@ -167424,7 +167543,10 @@ function materializeM0(options) {
167424
167543
  projectDocsHash: snapshotMarkers.projectDocsHash,
167425
167544
  materializedAt: snapshotMarkers.materializedAt,
167426
167545
  sessionFactsVersion: snapshotMarkers.sessionFactsVersion,
167427
- upgradeState: snapshotMarkers.upgradeState
167546
+ upgradeState: snapshotMarkers.upgradeState,
167547
+ systemHash: snapshotMarkers.systemHash,
167548
+ toolSetHash: snapshotMarkers.toolSetHash,
167549
+ modelKey: snapshotMarkers.modelKey
167428
167550
  });
167429
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);
167430
167552
  options.db.exec("COMMIT");
@@ -167583,6 +167705,9 @@ function readCachedM0M1Row(db, sessionId) {
167583
167705
  cached_m0_materialized_at,
167584
167706
  cached_m0_session_facts_version,
167585
167707
  cached_m0_upgrade_state,
167708
+ cached_m0_system_hash,
167709
+ cached_m0_tool_set_hash,
167710
+ cached_m0_model_key,
167586
167711
  memory_block_ids
167587
167712
  FROM session_meta
167588
167713
  WHERE session_id = ?`).get(sessionId);
@@ -167614,11 +167739,14 @@ function markersFromCachedRow(row) {
167614
167739
  projectDocsHash: row.cached_m0_project_docs_hash ?? "",
167615
167740
  materializedAt: row.cached_m0_materialized_at ?? 0,
167616
167741
  sessionFactsVersion: row.cached_m0_session_facts_version,
167617
- 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 ?? ""
167618
167746
  };
167619
167747
  }
167620
167748
  function cachedRowMatchesState(row, state) {
167621
- 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 ?? "");
167622
167750
  }
167623
167751
  function applyCachedRowToState(state, row) {
167624
167752
  const markers = markersFromCachedRow(row);
@@ -167637,6 +167765,9 @@ function applyCachedRowToState(state, row) {
167637
167765
  state.cachedM0MaterializedAt = markers.materializedAt;
167638
167766
  state.cachedM0SessionFactsVersion = markers.sessionFactsVersion;
167639
167767
  state.cachedM0UpgradeState = markers.upgradeState;
167768
+ state.cachedM0SystemHash = markers.systemHash;
167769
+ state.cachedM0ToolSetHash = markers.toolSetHash;
167770
+ state.cachedM0ModelKey = markers.modelKey;
167640
167771
  state.snapshotMarkers = markers;
167641
167772
  }
167642
167773
  function replayCachedM1(state) {
@@ -167753,7 +167884,8 @@ function injectM0M1(options) {
167753
167884
  sessionId: options.sessionId,
167754
167885
  state: options.state,
167755
167886
  projectPath: options.projectPath,
167756
- projectDirectory: options.projectDirectory
167887
+ projectDirectory: options.projectDirectory,
167888
+ hardSignals: options.hardSignals
167757
167889
  });
167758
167890
  let rematerialized = false;
167759
167891
  let contentionExhausted = false;
@@ -167811,7 +167943,10 @@ function injectM0M1(options) {
167811
167943
  m1Text = replayCachedM1(options.state);
167812
167944
  }
167813
167945
  const M0_DRIFT_RATIO_FLOOR = 2000;
167814
- 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)) {
167815
167950
  try {
167816
167951
  const refolded = materializeWithRetry(options);
167817
167952
  applyMarkersToState(options.state, refolded.m0Bytes, refolded.snapshotMarkers, refolded.m1Bytes);
@@ -167835,7 +167970,7 @@ function injectM0M1(options) {
167835
167970
  m1Text
167836
167971
  };
167837
167972
  }
167838
- 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;
167839
167974
  var init_inject_compartments = __esm(async () => {
167840
167975
  init_compartment_storage();
167841
167976
  init_constants();
@@ -167851,6 +167986,13 @@ var init_inject_compartments = __esm(async () => {
167851
167986
  ]);
167852
167987
  injectionCache = new BoundedSessionMap(INJECTION_CACHE_MAX);
167853
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
+ };
167854
167996
  MaterializeContentionError = class MaterializeContentionError extends Error {
167855
167997
  retries;
167856
167998
  reason;
@@ -171256,6 +171398,10 @@ async function runMemoryMigration(deps) {
171256
171398
  const cleanupChildSession = async (sid) => {
171257
171399
  if (!sid)
171258
171400
  return;
171401
+ if (shouldKeepSubagents()) {
171402
+ sessionLog(parentSessionId, `memory-migration: KEEPING child session ${sid} (keep_subagents)`);
171403
+ return;
171404
+ }
171259
171405
  await client.session.delete({ path: { id: sid } }).catch((e) => {
171260
171406
  sessionLog(parentSessionId, `memory-migration: child cleanup failed: ${String(e)}`);
171261
171407
  });
@@ -172821,7 +172967,7 @@ async function runSidekick(deps) {
172821
172967
  }
172822
172968
  return null;
172823
172969
  } finally {
172824
- if (agentSessionId) {
172970
+ if (agentSessionId && !shouldKeepSubagents()) {
172825
172971
  await deps.client.session.delete({
172826
172972
  path: { id: agentSessionId }
172827
172973
  }).catch((error51) => {
@@ -173873,13 +174019,14 @@ init_shared();
173873
174019
  init_assistant_message_extractor();
173874
174020
  init_logger();
173875
174021
  import { readFileSync as readFileSync11 } from "node:fs";
173876
- 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();
173877
174024
  init_aft_availability();
173878
174025
  init_project_key_files();
173879
174026
 
173880
174027
  // src/features/magic-context/key-files/read-history.ts
173881
174028
  import { realpathSync as realpathSync3 } from "node:fs";
173882
- import { relative, resolve as resolve5 } from "node:path";
174029
+ import { relative, resolve as resolve6 } from "node:path";
173883
174030
  function toMs(value) {
173884
174031
  if (typeof value === "number" && Number.isFinite(value))
173885
174032
  return value;
@@ -173916,7 +174063,7 @@ function coalesceRanges(ranges) {
173916
174063
  }
173917
174064
  function normalizeProjectRelativePath(projectPath, filePath) {
173918
174065
  const root = realpathSync3(projectPath);
173919
- const abs = filePath.startsWith("/") ? resolve5(filePath) : resolve5(root, filePath);
174066
+ const abs = filePath.startsWith("/") ? resolve6(filePath) : resolve6(root, filePath);
173920
174067
  let real = abs;
173921
174068
  try {
173922
174069
  real = realpathSync3(abs);
@@ -174284,11 +174431,13 @@ async function runKeyFilesLlm(args) {
174284
174431
  const text = extractLatestAssistantText(messages);
174285
174432
  if (!text)
174286
174433
  throw new Error("Dreamer returned no key-files output.");
174287
- return text;
174434
+ return { text, messages };
174288
174435
  } finally {
174289
- await args.client.session.delete({ path: { id: agentSessionId } }).catch(() => {
174290
- return;
174291
- });
174436
+ if (!shouldKeepSubagents()) {
174437
+ await args.client.session.delete({ path: { id: agentSessionId } }).catch(() => {
174438
+ return;
174439
+ });
174440
+ }
174292
174441
  }
174293
174442
  }
174294
174443
  async function runKeyFilesTask(args) {
@@ -174334,9 +174483,27 @@ async function runKeyFilesTask(args) {
174334
174483
  log(`[key-files] lease renewal threw: ${getErrorMessage(error51)}`);
174335
174484
  }
174336
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
+ };
174337
174504
  try {
174338
174505
  try {
174339
- const raw = await runKeyFilesLlm({
174506
+ const { text: raw, messages: llmMessages } = await runKeyFilesLlm({
174340
174507
  client: args.client,
174341
174508
  parentSessionId: args.parentSessionId,
174342
174509
  projectPath,
@@ -174344,8 +174511,10 @@ async function runKeyFilesTask(args) {
174344
174511
  deadline: args.deadline,
174345
174512
  fallbackModels: args.fallbackModels
174346
174513
  });
174514
+ recordKeyFilesInvocation({ status: "completed", messages: llmMessages });
174347
174515
  validated = validateLlmOutput(raw, args.config, projectPath, new Set(candidates.map((candidate) => candidate.path)));
174348
174516
  } catch (error51) {
174517
+ recordKeyFilesInvocation({ status: "failed", error: error51 });
174349
174518
  log(`[key-files] LLM validation failed: ${getErrorMessage(error51)}`);
174350
174519
  throw error51;
174351
174520
  }
@@ -174444,7 +174613,8 @@ If no promotions are warranted, return empty arrays. Always consume reviewed can
174444
174613
  db: args.db,
174445
174614
  parentSessionId: args.parentSessionId,
174446
174615
  harness: "opencode",
174447
- subagent: "user_memory_review",
174616
+ subagent: "dreamer",
174617
+ task: "user memories",
174448
174618
  startedAt,
174449
174619
  status: params.status,
174450
174620
  messages: params.messages,
@@ -174568,7 +174738,7 @@ If no promotions are warranted, return empty arrays. Always consume reviewed can
174568
174738
  return result;
174569
174739
  } finally {
174570
174740
  clearInterval(leaseInterval);
174571
- if (agentSessionId) {
174741
+ if (agentSessionId && !shouldKeepSubagents()) {
174572
174742
  await args.client.session.delete({
174573
174743
  path: { id: agentSessionId },
174574
174744
  query: { directory: args.sessionDirectory }
@@ -174891,14 +175061,14 @@ async function runDream(args) {
174891
175061
  }
174892
175062
  } finally {
174893
175063
  clearInterval(leaseRenewalInterval);
174894
- if (agentSessionId && !taskFailed) {
175064
+ if (agentSessionId && !taskFailed && !shouldKeepSubagents()) {
174895
175065
  await args.client.session.delete({
174896
175066
  path: { id: agentSessionId }
174897
175067
  }).catch((error51) => {
174898
175068
  log("[dreamer] failed to delete child session:", error51);
174899
175069
  });
174900
- } else if (agentSessionId && taskFailed) {
174901
- 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"})`);
174902
175072
  }
174903
175073
  }
174904
175074
  if (lostLease) {
@@ -175183,7 +175353,7 @@ Only include notes whose conditions you could definitively evaluate against exte
175183
175353
  parts: [{ type: "text", text: evaluationPrompt, synthetic: true }]
175184
175354
  }
175185
175355
  }, {
175186
- timeoutMs: Math.min(remainingMs, 300000),
175356
+ timeoutMs: Math.min(remainingMs, 5 * 60 * 1000),
175187
175357
  signal: abortController.signal,
175188
175358
  fallbackModels: args.fallbackModels,
175189
175359
  callContext: "dreamer:smart-notes"
@@ -175259,7 +175429,7 @@ Only include notes whose conditions you could definitively evaluate against exte
175259
175429
  });
175260
175430
  } finally {
175261
175431
  clearInterval(leaseInterval);
175262
- if (agentSessionId) {
175432
+ if (agentSessionId && !shouldKeepSubagents()) {
175263
175433
  await args.client.session.delete({
175264
175434
  path: { id: agentSessionId }
175265
175435
  }).catch(() => {});
@@ -175270,7 +175440,7 @@ var MAX_LEASE_RETRIES = 3;
175270
175440
  async function processDreamQueue(args) {
175271
175441
  const maxRuntimeMs = args.maxRuntimeMinutes * 60 * 1000;
175272
175442
  if (!hasActiveDreamLease(args.db)) {
175273
- clearStaleEntries(args.db, maxRuntimeMs + 1800000, args.projectIdentity);
175443
+ clearStaleEntries(args.db, maxRuntimeMs + 30 * 60 * 1000, args.projectIdentity);
175274
175444
  }
175275
175445
  const entry = dequeueNext(args.db, args.projectIdentity);
175276
175446
  if (!entry) {
@@ -176629,6 +176799,7 @@ function createTagger() {
176629
176799
  // src/hooks/magic-context/hook.ts
176630
176800
  init_magic_context();
176631
176801
  init_project_identity();
176802
+ init_tool_definition_tokens();
176632
176803
  await init_storage();
176633
176804
  init_logger();
176634
176805
  init_resolve_fallbacks();
@@ -178610,7 +178781,7 @@ async function runCompartmentPhase(args) {
178610
178781
  async function awaitCompartmentRun(activeRun, reason) {
178611
178782
  sessionLog(args.sessionId, reason);
178612
178783
  const timeoutMs = args.historianTimeoutMs ?? 120000;
178613
- const timeout = new Promise((resolve6) => setTimeout(() => resolve6("timeout"), timeoutMs));
178784
+ const timeout = new Promise((resolve7) => setTimeout(() => resolve7("timeout"), timeoutMs));
178614
178785
  const result = await Promise.race([activeRun.promise.then(() => "done"), timeout]);
178615
178786
  if (result === "timeout") {
178616
178787
  sessionLog(args.sessionId, `transform: compartment await timed out after ${timeoutMs}ms — proceeding without waiting`);
@@ -180093,10 +180264,10 @@ var AUTO_SEARCH_TIMEOUT_MS = 3000;
180093
180264
  async function unifiedSearchWithTimeout(db, sessionId, projectPath, prompt, options, timeoutMs) {
180094
180265
  const controller = new AbortController;
180095
180266
  let timer;
180096
- const timeoutPromise = new Promise((resolve6) => {
180267
+ const timeoutPromise = new Promise((resolve7) => {
180097
180268
  timer = setTimeout(() => {
180098
180269
  controller.abort();
180099
- resolve6(null);
180270
+ resolve7(null);
180100
180271
  }, timeoutMs);
180101
180272
  });
180102
180273
  try {
@@ -180790,7 +180961,8 @@ async function runPostTransformPhase(args) {
180790
180961
  memoryInjectionBudgetTokens: args.m0M1.memoryInjectionBudgetTokens,
180791
180962
  historyBudgetTokens: args.m0M1.historyBudgetTokens,
180792
180963
  keyFiles: args.m0M1.keyFiles,
180793
- isCacheBustingPass
180964
+ isCacheBustingPass,
180965
+ hardSignals: args.m0M1.hardSignals
180794
180966
  });
180795
180967
  if (result.injected) {
180796
180968
  sessionLog(args.sessionId, `transform: injected m[0]/m[1] (rematerialized=${result.m0RematerializedThisPass}, reason=${result.decision.reason ?? "cache_hit"})`);
@@ -181538,6 +181710,22 @@ Historian previously failed ${historianFailureState.failureCount} time(s), so Ma
181538
181710
  const compartmentInProgress = compartmentPhase.compartmentInProgress;
181539
181711
  sessionMeta = { ...sessionMeta, compartmentInProgress };
181540
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
+ };
181541
181729
  const lateActiveRunBlocksMaterialization = getActiveCompartmentRun(sessionId) !== undefined && contextUsageEarly.percentage < FORCE_MATERIALIZE_PERCENTAGE;
181542
181730
  const canConsumeDeferredLate = canConsumeDeferredOnThisPass({
181543
181731
  schedulerDecision: midTurnAdjustedSchedulerDecision,
@@ -181601,7 +181789,8 @@ Historian previously failed ${historianFailureState.failureCount} time(s), so Ma
181601
181789
  keyFiles: {
181602
181790
  enabled: deps.experimentalPinKeyFiles === true,
181603
181791
  tokenBudget: deps.experimentalPinKeyFilesTokenBudget ?? 1e4
181604
- }
181792
+ },
181793
+ hardSignals: m0HardSignals
181605
181794
  }
181606
181795
  });
181607
181796
  logTransformTiming(sessionId, "postTransformPhase", tPostProcess);
@@ -182970,6 +183159,12 @@ function createMagicContextHook(deps) {
182970
183159
  const model = liveModelBySession.get(sessionId);
182971
183160
  return resolveModelKey(model?.providerID, model?.modelID);
182972
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
+ },
182973
183168
  getFallbackModelId: (sessionId) => {
182974
183169
  const model = liveModelBySession.get(sessionId);
182975
183170
  return model ? `${model.providerID}/${model.modelID}` : undefined;
@@ -185299,7 +185494,7 @@ class MagicContextRpcServer {
185299
185494
  this.handlers.set(method, handler);
185300
185495
  }
185301
185496
  async start() {
185302
- return new Promise((resolve6, reject) => {
185497
+ return new Promise((resolve7, reject) => {
185303
185498
  const server = createServer((req, res) => this.dispatch(req, res));
185304
185499
  server.on("error", (err) => {
185305
185500
  log(`[rpc] server error: ${err.message}`);
@@ -185329,7 +185524,7 @@ class MagicContextRpcServer {
185329
185524
  } catch (err) {
185330
185525
  log(`[rpc] failed to write port file: ${err}`);
185331
185526
  }
185332
- resolve6(this.port);
185527
+ resolve7(this.port);
185333
185528
  });
185334
185529
  server.unref();
185335
185530
  });
@@ -185422,6 +185617,7 @@ var plugin = async (ctx) => {
185422
185617
  cacheSizeMb: pluginConfig.sqlite.cache_size_mb,
185423
185618
  mmapSizeMb: pluginConfig.sqlite.mmap_size_mb
185424
185619
  });
185620
+ setKeepSubagents(pluginConfig.keep_subagents === true);
185425
185621
  const autoUpdateAbort = new AbortController;
185426
185622
  process.once("exit", () => {
185427
185623
  autoUpdateAbort.abort();