@cortexkit/pi-magic-context 0.17.1 → 0.18.0

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.
package/dist/index.js CHANGED
@@ -158111,6 +158111,25 @@ var MIGRATIONS = [
158111
158111
  WHERE type = 'tool' AND tool_owner_message_id IS NULL;
158112
158112
  `);
158113
158113
  }
158114
+ },
158115
+ {
158116
+ version: 11,
158117
+ description: "Add todo state synthesis columns to session_meta",
158118
+ up: (db) => {
158119
+ const cols = db.prepare("PRAGMA table_info(session_meta)").all();
158120
+ if (!cols.some((c) => c.name === "last_todo_state")) {
158121
+ db.exec("ALTER TABLE session_meta ADD COLUMN last_todo_state TEXT DEFAULT ''");
158122
+ }
158123
+ if (!cols.some((c) => c.name === "todo_synthetic_call_id")) {
158124
+ db.exec("ALTER TABLE session_meta ADD COLUMN todo_synthetic_call_id TEXT DEFAULT ''");
158125
+ }
158126
+ if (!cols.some((c) => c.name === "todo_synthetic_anchor_message_id")) {
158127
+ db.exec("ALTER TABLE session_meta ADD COLUMN todo_synthetic_anchor_message_id TEXT DEFAULT ''");
158128
+ }
158129
+ if (!cols.some((c) => c.name === "todo_synthetic_state_json")) {
158130
+ db.exec("ALTER TABLE session_meta ADD COLUMN todo_synthetic_state_json TEXT DEFAULT ''");
158131
+ }
158132
+ }
158114
158133
  }
158115
158134
  ];
158116
158135
  function ensureMigrationsTable(db) {
@@ -158180,13 +158199,16 @@ function runMigrations(db) {
158180
158199
 
158181
158200
  // ../plugin/src/features/magic-context/tool-definition-tokens.ts
158182
158201
  var measurements = new Map;
158202
+ var fingerprints = new Map;
158183
158203
  var persistenceDb = null;
158204
+ var cachedInsertStmt = null;
158184
158205
  function keyFor(providerID, modelID, agentName) {
158185
158206
  const agent = agentName && agentName.length > 0 ? agentName : "default";
158186
158207
  return `${providerID}/${modelID}/${agent}`;
158187
158208
  }
158188
158209
  function setDatabase(db) {
158189
158210
  persistenceDb = db;
158211
+ cachedInsertStmt = null;
158190
158212
  }
158191
158213
  function loadToolDefinitionMeasurements(db) {
158192
158214
  let rows = [];
@@ -158682,6 +158704,10 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
158682
158704
  note_nudge_trigger_message_id TEXT DEFAULT '',
158683
158705
  note_nudge_sticky_text TEXT DEFAULT '',
158684
158706
  note_nudge_sticky_message_id TEXT DEFAULT '',
158707
+ last_todo_state TEXT DEFAULT '',
158708
+ todo_synthetic_call_id TEXT DEFAULT '',
158709
+ todo_synthetic_anchor_message_id TEXT DEFAULT '',
158710
+ todo_synthetic_state_json TEXT DEFAULT '',
158685
158711
  is_subagent INTEGER DEFAULT 0,
158686
158712
  last_context_percentage REAL DEFAULT 0,
158687
158713
  last_input_tokens INTEGER DEFAULT 0,
@@ -158746,6 +158772,10 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
158746
158772
  ensureColumn(db, "session_meta", "note_nudge_trigger_message_id", "TEXT DEFAULT ''");
158747
158773
  ensureColumn(db, "session_meta", "note_nudge_sticky_text", "TEXT DEFAULT ''");
158748
158774
  ensureColumn(db, "session_meta", "note_nudge_sticky_message_id", "TEXT DEFAULT ''");
158775
+ ensureColumn(db, "session_meta", "last_todo_state", "TEXT DEFAULT ''");
158776
+ ensureColumn(db, "session_meta", "todo_synthetic_call_id", "TEXT DEFAULT ''");
158777
+ ensureColumn(db, "session_meta", "todo_synthetic_anchor_message_id", "TEXT DEFAULT ''");
158778
+ ensureColumn(db, "session_meta", "todo_synthetic_state_json", "TEXT DEFAULT ''");
158749
158779
  ensureColumn(db, "session_meta", "note_last_read_at", "INTEGER DEFAULT 0");
158750
158780
  ensureColumn(db, "session_meta", "times_execute_threshold_reached", "INTEGER DEFAULT 0");
158751
158781
  ensureColumn(db, "session_meta", "compartment_in_progress", "INTEGER DEFAULT 0");
@@ -158810,6 +158840,10 @@ function healNullTextColumns(db) {
158810
158840
  ["note_nudge_trigger_message_id", ""],
158811
158841
  ["note_nudge_sticky_text", ""],
158812
158842
  ["note_nudge_sticky_message_id", ""],
158843
+ ["last_todo_state", ""],
158844
+ ["todo_synthetic_call_id", ""],
158845
+ ["todo_synthetic_anchor_message_id", ""],
158846
+ ["todo_synthetic_state_json", ""],
158813
158847
  ["system_prompt_hash", ""],
158814
158848
  ["stripped_placeholder_ids", ""],
158815
158849
  ["memory_block_cache", ""],
@@ -158903,7 +158937,8 @@ var META_COLUMNS = {
158903
158937
  systemPromptTokens: "system_prompt_tokens",
158904
158938
  conversationTokens: "conversation_tokens",
158905
158939
  toolCallTokens: "tool_call_tokens",
158906
- clearedReasoningThroughTag: "cleared_reasoning_through_tag"
158940
+ clearedReasoningThroughTag: "cleared_reasoning_through_tag",
158941
+ lastTodoState: "last_todo_state"
158907
158942
  };
158908
158943
  var BOOLEAN_META_KEYS = new Set(["isSubagent", "compartmentInProgress"]);
158909
158944
  function isStringOrNull(value) {
@@ -158916,7 +158951,7 @@ function isSessionMetaRow(row) {
158916
158951
  if (row === null || typeof row !== "object")
158917
158952
  return false;
158918
158953
  const r = row;
158919
- 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.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);
158954
+ 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.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);
158920
158955
  }
158921
158956
  function getDefaultSessionMeta(sessionId) {
158922
158957
  return {
@@ -158936,7 +158971,8 @@ function getDefaultSessionMeta(sessionId) {
158936
158971
  systemPromptTokens: 0,
158937
158972
  conversationTokens: 0,
158938
158973
  toolCallTokens: 0,
158939
- clearedReasoningThroughTag: 0
158974
+ clearedReasoningThroughTag: 0,
158975
+ lastTodoState: ""
158940
158976
  };
158941
158977
  }
158942
158978
  function ensureSessionMetaRow(db, sessionId) {
@@ -158948,6 +158984,7 @@ function toSessionMeta(row) {
158948
158984
  const transformErrorRaw = typeof row.last_transform_error === "string" ? row.last_transform_error : "";
158949
158985
  const cacheTtlRaw = typeof row.cache_ttl === "string" && row.cache_ttl.length > 0 ? row.cache_ttl : "5m";
158950
158986
  const systemPromptHashRaw = row.system_prompt_hash == null ? "" : row.system_prompt_hash;
158987
+ const lastTodoStateRaw = typeof row.last_todo_state === "string" ? row.last_todo_state : "";
158951
158988
  const numOrZero = (value) => typeof value === "number" ? value : 0;
158952
158989
  return {
158953
158990
  sessionId: row.session_id,
@@ -158966,7 +159003,8 @@ function toSessionMeta(row) {
158966
159003
  systemPromptTokens: numOrZero(row.system_prompt_tokens),
158967
159004
  conversationTokens: numOrZero(row.conversation_tokens),
158968
159005
  toolCallTokens: numOrZero(row.tool_call_tokens),
158969
- clearedReasoningThroughTag: numOrZero(row.cleared_reasoning_through_tag)
159006
+ clearedReasoningThroughTag: numOrZero(row.cleared_reasoning_through_tag),
159007
+ lastTodoState: lastTodoStateRaw
158970
159008
  };
158971
159009
  }
158972
159010
 
@@ -159182,7 +159220,7 @@ function resolveIsSubagentFromOpenCodeDb(sessionId) {
159182
159220
 
159183
159221
  // ../plugin/src/features/magic-context/storage-meta-session.ts
159184
159222
  function getOrCreateSessionMeta(db, sessionId) {
159185
- const result = db.prepare("SELECT session_id, last_response_time, cache_ttl, counter, last_nudge_tokens, last_nudge_band, last_transform_error, is_subagent, last_context_percentage, last_input_tokens, times_execute_threshold_reached, compartment_in_progress, system_prompt_hash, system_prompt_tokens, conversation_tokens, tool_call_tokens, cleared_reasoning_through_tag FROM session_meta WHERE session_id = ?").get(sessionId);
159223
+ const result = db.prepare("SELECT session_id, last_response_time, cache_ttl, counter, last_nudge_tokens, last_nudge_band, last_transform_error, is_subagent, last_context_percentage, last_input_tokens, times_execute_threshold_reached, compartment_in_progress, system_prompt_hash, system_prompt_tokens, conversation_tokens, tool_call_tokens, cleared_reasoning_through_tag, last_todo_state FROM session_meta WHERE session_id = ?").get(sessionId);
159186
159224
  if (isSessionMetaRow(result)) {
159187
159225
  return toSessionMeta(result);
159188
159226
  }
@@ -159748,14 +159786,118 @@ function expandFallbackChain(chain) {
159748
159786
  }
159749
159787
  return models;
159750
159788
  }
159789
+ function getAgentFallbackModels(agent) {
159790
+ const requirement = AGENT_MODEL_REQUIREMENTS[agent];
159791
+ if (!requirement)
159792
+ return;
159793
+ return expandFallbackChain(requirement.fallbackChain);
159794
+ }
159751
159795
 
159752
159796
  // ../plugin/src/shared/models-dev-cache.ts
159753
159797
  init_data_path();
159754
- init_logger();
159755
159798
  import { createHash as createHash3 } from "node:crypto";
159756
159799
  import { existsSync as existsSync4, readFileSync } from "node:fs";
159757
159800
  import { homedir as homedir2, platform } from "node:os";
159758
159801
  import { join as join8 } from "node:path";
159802
+
159803
+ // ../plugin/src/shared/jsonc-parser.ts
159804
+ function stripJsonComments(content) {
159805
+ let result = "";
159806
+ let inString = false;
159807
+ let escaped = false;
159808
+ let inLineComment = false;
159809
+ let inBlockComment = false;
159810
+ for (let index = 0;index < content.length; index += 1) {
159811
+ const char = content[index];
159812
+ const next = content[index + 1];
159813
+ if (inLineComment) {
159814
+ if (char === `
159815
+ `) {
159816
+ inLineComment = false;
159817
+ result += char;
159818
+ }
159819
+ continue;
159820
+ }
159821
+ if (inBlockComment) {
159822
+ if (char === "*" && next === "/") {
159823
+ inBlockComment = false;
159824
+ index += 1;
159825
+ }
159826
+ continue;
159827
+ }
159828
+ if (inString) {
159829
+ result += char;
159830
+ if (escaped) {
159831
+ escaped = false;
159832
+ } else if (char === "\\") {
159833
+ escaped = true;
159834
+ } else if (char === '"') {
159835
+ inString = false;
159836
+ }
159837
+ continue;
159838
+ }
159839
+ if (char === '"') {
159840
+ inString = true;
159841
+ result += char;
159842
+ continue;
159843
+ }
159844
+ if (char === "/" && next === "/") {
159845
+ inLineComment = true;
159846
+ index += 1;
159847
+ continue;
159848
+ }
159849
+ if (char === "/" && next === "*") {
159850
+ inBlockComment = true;
159851
+ index += 1;
159852
+ continue;
159853
+ }
159854
+ result += char;
159855
+ }
159856
+ return result;
159857
+ }
159858
+ function stripTrailingCommas(content) {
159859
+ let result = "";
159860
+ let inString = false;
159861
+ let escaped = false;
159862
+ for (let index = 0;index < content.length; index += 1) {
159863
+ const char = content[index];
159864
+ if (inString) {
159865
+ result += char;
159866
+ if (escaped) {
159867
+ escaped = false;
159868
+ } else if (char === "\\") {
159869
+ escaped = true;
159870
+ } else if (char === '"') {
159871
+ inString = false;
159872
+ }
159873
+ continue;
159874
+ }
159875
+ if (char === '"') {
159876
+ inString = true;
159877
+ result += char;
159878
+ continue;
159879
+ }
159880
+ if (char === ",") {
159881
+ let lookahead = index + 1;
159882
+ while (lookahead < content.length && /\s/.test(content[lookahead] ?? "")) {
159883
+ lookahead += 1;
159884
+ }
159885
+ const next = content[lookahead];
159886
+ if (next === "}" || next === "]") {
159887
+ continue;
159888
+ }
159889
+ }
159890
+ result += char;
159891
+ }
159892
+ return result;
159893
+ }
159894
+ function parseJsonc(content) {
159895
+ const normalized = stripTrailingCommas(stripJsonComments(content));
159896
+ return JSON.parse(normalized);
159897
+ }
159898
+
159899
+ // ../plugin/src/shared/models-dev-cache.ts
159900
+ init_logger();
159759
159901
  var RELOAD_INTERVAL_MS = 5 * 60 * 1000;
159760
159902
  var apiCache = null;
159761
159903
  var recentlySeenApiSizes = new Set;
@@ -159830,9 +159972,7 @@ function loadModelsDevMetadataFromFile() {
159830
159972
  try {
159831
159973
  const configPath = getOpencodeConfigPath();
159832
159974
  if (configPath && existsSync4(configPath)) {
159833
- let raw = readFileSync(configPath, "utf-8");
159834
- raw = raw.replace(/"(?:[^"\\]|\\.)*"|\/\/.*$/gm, (match) => match.startsWith('"') ? match : "");
159835
- const config2 = JSON.parse(raw);
159975
+ const config2 = parseJsonc(readFileSync(configPath, "utf-8"));
159836
159976
  if (config2.provider && typeof config2.provider === "object") {
159837
159977
  for (const [providerId, provider2] of Object.entries(config2.provider)) {
159838
159978
  if (!provider2?.models || typeof provider2.models !== "object")
@@ -160771,6 +160911,53 @@ init_logger();
160771
160911
 
160772
160912
  // ../plugin/src/shared/model-suggestion-retry.ts
160773
160913
  init_logger();
160914
+
160915
+ // ../plugin/src/shared/resolve-fallbacks.ts
160916
+ function resolveFallbackChain(agentName, userFallbacks) {
160917
+ const userList = normalizeUserFallbacks(userFallbacks);
160918
+ if (userList.length > 0) {
160919
+ return dedupe(userList.filter(isValidModelSpec));
160920
+ }
160921
+ const builtin = getAgentFallbackModels(agentName);
160922
+ if (!builtin || builtin.length === 0)
160923
+ return [];
160924
+ return dedupe(builtin.filter(isValidModelSpec));
160925
+ }
160926
+ function normalizeUserFallbacks(userFallbacks) {
160927
+ if (!userFallbacks)
160928
+ return [];
160929
+ if (typeof userFallbacks === "string") {
160930
+ const trimmed = userFallbacks.trim();
160931
+ return trimmed ? [trimmed] : [];
160932
+ }
160933
+ return userFallbacks.map((s) => s.trim()).filter((s) => s.length > 0);
160934
+ }
160935
+ function isValidModelSpec(spec) {
160936
+ const slash = spec.indexOf("/");
160937
+ return slash > 0 && slash < spec.length - 1;
160938
+ }
160939
+ function dedupe(list) {
160940
+ const seen = new Set;
160941
+ const out = [];
160942
+ for (const item of list) {
160943
+ if (seen.has(item))
160944
+ continue;
160945
+ seen.add(item);
160946
+ out.push(item);
160947
+ }
160948
+ return out;
160949
+ }
160950
+ function parseProviderModel(spec) {
160951
+ const slash = spec.indexOf("/");
160952
+ if (slash < 1 || slash >= spec.length - 1)
160953
+ return null;
160954
+ return {
160955
+ providerID: spec.slice(0, slash).trim(),
160956
+ modelID: spec.slice(slash + 1).trim()
160957
+ };
160958
+ }
160959
+
160960
+ // ../plugin/src/shared/model-suggestion-retry.ts
160774
160961
  function extractMessage(error51) {
160775
160962
  if (typeof error51 === "string")
160776
160963
  return error51;
@@ -160825,6 +161012,9 @@ function parseModelSuggestion(error51) {
160825
161012
  };
160826
161013
  }
160827
161014
  async function promptWithTimeout(client, args, timeoutMs, signal) {
161015
+ if (signal?.aborted) {
161016
+ throw new Error("prompt aborted by external signal");
161017
+ }
160828
161018
  const controller = new AbortController;
160829
161019
  const timeout = setTimeout(() => controller.abort(), timeoutMs);
160830
161020
  const onExternalAbort = () => controller.abort();
@@ -160847,16 +161037,39 @@ async function promptWithTimeout(client, args, timeoutMs, signal) {
160847
161037
  signal?.removeEventListener("abort", onExternalAbort);
160848
161038
  }
160849
161039
  }
160850
- async function promptSyncWithModelSuggestionRetry(client, args, options = {}) {
160851
- const timeoutMs = options.timeoutMs ?? 300000;
161040
+ function isNonRetryable(error51, externalSignal) {
161041
+ if (externalSignal?.aborted)
161042
+ return true;
161043
+ if (error51 instanceof Error) {
161044
+ if (error51.name === "AbortError")
161045
+ return true;
161046
+ if (error51.message === "prompt aborted by external signal")
161047
+ return true;
161048
+ if (/^prompt timed out after \d+ms$/.test(error51.message))
161049
+ return true;
161050
+ }
161051
+ if (detectOverflow(error51).isOverflow)
161052
+ return true;
161053
+ return false;
161054
+ }
161055
+ function shortErr(error51) {
161056
+ if (error51 instanceof Error) {
161057
+ return error51.name && error51.name !== "Error" ? `${error51.name}: ${error51.message}` : error51.message;
161058
+ }
161059
+ return extractMessage(error51);
161060
+ }
161061
+ async function attemptOnce(client, args, timeoutMs, signal, callContext, label) {
160852
161062
  try {
160853
- await promptWithTimeout(client, args, timeoutMs, options.signal);
161063
+ await promptWithTimeout(client, args, timeoutMs, signal);
161064
+ return;
160854
161065
  } catch (error51) {
161066
+ if (isNonRetryable(error51, signal))
161067
+ throw error51;
160855
161068
  const suggestion = parseModelSuggestion(error51);
160856
161069
  if (!suggestion || !args.body.model) {
160857
161070
  throw error51;
160858
161071
  }
160859
- log("[model-suggestion-retry] Model not found, retrying with suggestion", {
161072
+ log(`[${callContext}] ${label}: model not found, retrying with suggestion`, {
160860
161073
  original: `${suggestion.providerID}/${suggestion.modelID}`,
160861
161074
  suggested: suggestion.suggestion
160862
161075
  });
@@ -160869,9 +161082,55 @@ async function promptSyncWithModelSuggestionRetry(client, args, options = {}) {
160869
161082
  modelID: suggestion.suggestion
160870
161083
  }
160871
161084
  }
160872
- }, timeoutMs, options.signal);
161085
+ }, timeoutMs, signal);
160873
161086
  }
160874
161087
  }
161088
+ async function promptSyncWithModelSuggestionRetry(client, args, options = {}) {
161089
+ const timeoutMs = options.timeoutMs ?? 300000;
161090
+ const callContext = options.callContext ?? "subagent";
161091
+ const fallbacks = options.fallbackModels ?? [];
161092
+ const explicitPrimaryLabel = args.body.model?.providerID && args.body.model.modelID ? `${args.body.model.providerID}/${args.body.model.modelID}` : "primary";
161093
+ let lastError = null;
161094
+ try {
161095
+ await attemptOnce(client, args, timeoutMs, options.signal, callContext, explicitPrimaryLabel);
161096
+ return;
161097
+ } catch (error51) {
161098
+ lastError = error51;
161099
+ if (isNonRetryable(error51, options.signal))
161100
+ throw error51;
161101
+ if (fallbacks.length === 0) {
161102
+ throw error51;
161103
+ }
161104
+ log(`[${callContext}] primary (${explicitPrimaryLabel}) failed: ${shortErr(error51)}; trying ${fallbacks.length} fallback(s)`);
161105
+ }
161106
+ for (let i = 0;i < fallbacks.length; i += 1) {
161107
+ const parsed = parseProviderModel(fallbacks[i]);
161108
+ if (!parsed) {
161109
+ log(`[${callContext}] skipping invalid fallback spec: ${fallbacks[i]}`);
161110
+ continue;
161111
+ }
161112
+ const label = `${parsed.providerID}/${parsed.modelID}`;
161113
+ const attemptArgs = {
161114
+ ...args,
161115
+ body: { ...args.body, model: parsed }
161116
+ };
161117
+ try {
161118
+ await attemptOnce(client, attemptArgs, timeoutMs, options.signal, callContext, label);
161119
+ log(`[${callContext}] fallback succeeded with ${label} (attempt ${i + 2}/${fallbacks.length + 1})`);
161120
+ return;
161121
+ } catch (error51) {
161122
+ lastError = error51;
161123
+ if (isNonRetryable(error51, options.signal))
161124
+ throw error51;
161125
+ const remaining = fallbacks.length - i - 1;
161126
+ if (remaining > 0) {
161127
+ log(`[${callContext}] ${label} failed: ${shortErr(error51)}; ${remaining} fallback(s) left`);
161128
+ }
161129
+ }
161130
+ }
161131
+ log(`[${callContext}] all models exhausted; tried: ${[explicitPrimaryLabel, ...fallbacks].join(", ")}; last error: ${shortErr(lastError)}`);
161132
+ throw lastError ?? new Error("All fallback models failed");
161133
+ }
160875
161134
  // ../plugin/src/shared/normalize-sdk-response.ts
160876
161135
  function normalizeSDKResponse(response, fallback, options) {
160877
161136
  if (response === null || response === undefined) {
@@ -162049,7 +162308,12 @@ If no promotions are warranted, return empty arrays. Always consume reviewed can
162049
162308
  system: DREAMER_SYSTEM_PROMPT,
162050
162309
  parts: [{ type: "text", text: prompt, synthetic: true }]
162051
162310
  }
162052
- }, { timeoutMs: Math.min(remainingMs, 5 * 60 * 1000), signal: abortController.signal });
162311
+ }, {
162312
+ timeoutMs: Math.min(remainingMs, 5 * 60 * 1000),
162313
+ signal: abortController.signal,
162314
+ fallbackModels: args.fallbackModels,
162315
+ callContext: "dreamer:user-memories"
162316
+ });
162053
162317
  const messagesResponse = await args.client.session.messages({
162054
162318
  path: { id: agentSessionId },
162055
162319
  query: { directory: args.sessionDirectory }
@@ -162108,7 +162372,8 @@ If no promotions are warranted, return empty arrays. Always consume reviewed can
162108
162372
  }
162109
162373
  return result;
162110
162374
  } catch (error51) {
162111
- log(`[dreamer] user-memories: review failed: ${getErrorMessage(error51)}`);
162375
+ const errorDescription = describeError(error51);
162376
+ log(`[dreamer] user-memories: review failed: ${errorDescription.brief}`, errorDescription.stackHead ? { stackHead: errorDescription.stackHead } : undefined);
162112
162377
  return result;
162113
162378
  } finally {
162114
162379
  clearInterval(leaseInterval);
@@ -162140,6 +162405,7 @@ function insertDreamRun(db, run) {
162140
162405
 
162141
162406
  // ../plugin/src/features/magic-context/dreamer/runner.ts
162142
162407
  var dreamProjectDirectories = new Map;
162408
+ var CIRCUIT_BREAKER_THRESHOLD = 3;
162143
162409
  function registerDreamProjectDirectory(projectIdentity, directory) {
162144
162410
  dreamProjectDirectories.set(projectIdentity, directory);
162145
162411
  }
@@ -162156,6 +162422,25 @@ function countNewIds(beforeIds, afterIds) {
162156
162422
  }
162157
162423
  return count;
162158
162424
  }
162425
+ function getCircuitBreakerSignature(error51, brief) {
162426
+ if (error51 instanceof Error && error51.name && error51.name !== "Error") {
162427
+ return error51.name;
162428
+ }
162429
+ const namedError = error51;
162430
+ if (namedError && typeof namedError === "object" && typeof namedError.name === "string" && namedError.name.length > 0 && namedError.name !== "Error") {
162431
+ return namedError.name;
162432
+ }
162433
+ return brief.split(":")[0]?.trim().split(/\s+/)[0] || brief || "unknown";
162434
+ }
162435
+ function shouldSkipCircuitBreaker(error51, brief) {
162436
+ const namedError = error51;
162437
+ const name2 = error51 instanceof Error ? error51.name : namedError && typeof namedError === "object" && typeof namedError.name === "string" ? namedError.name : "";
162438
+ const combined = `${name2} ${brief}`.toLowerCase();
162439
+ return name2 === "AbortError" || combined.includes("lease");
162440
+ }
162441
+ function logWithStackHead(message, stackHead) {
162442
+ log(message, stackHead ? { stackHead } : undefined);
162443
+ }
162159
162444
  function getOpenCodeDbPath2() {
162160
162445
  return join9(getDataDir(), "opencode", "opencode.db");
162161
162446
  }
@@ -162261,7 +162546,12 @@ async function identifyKeyFilesForSession(args) {
162261
162546
  system: KEY_FILES_SYSTEM_PROMPT,
162262
162547
  parts: [{ type: "text", text: prompt, synthetic: true }]
162263
162548
  }
162264
- }, { timeoutMs: Math.min(remainingMs, 300000), signal: abortController.signal });
162549
+ }, {
162550
+ timeoutMs: Math.min(remainingMs, 300000),
162551
+ signal: abortController.signal,
162552
+ fallbackModels: args.fallbackModels,
162553
+ callContext: `dreamer:key-files:${args.sessionId.slice(0, 12)}`
162554
+ });
162265
162555
  const messagesResponse = await args.client.session.messages({
162266
162556
  path: { id: agentSessionId },
162267
162557
  query: { directory: args.sessionDirectory }
@@ -162334,6 +162624,7 @@ async function identifyKeyFiles(args) {
162334
162624
  parentSessionId: args.parentSessionId,
162335
162625
  sessionDirectory: args.sessionDirectory,
162336
162626
  holderId: args.holderId,
162627
+ fallbackModels: args.fallbackModels,
162337
162628
  deadline: args.deadline,
162338
162629
  sessionId,
162339
162630
  config: args.config
@@ -162387,6 +162678,9 @@ async function runDream(args) {
162387
162678
  const deadline = startedAt + args.maxRuntimeMinutes * 60 * 1000;
162388
162679
  const lastDreamAt = getDreamState(args.db, `last_dream_at:${args.projectIdentity}`) ?? getDreamState(args.db, "last_dream_at");
162389
162680
  log(`[dreamer] last dream at: ${lastDreamAt ?? "never"} (project=${args.projectIdentity})`);
162681
+ let lastErrorSignature = null;
162682
+ let consecutiveSameErrorFailures = 0;
162683
+ let circuitBreakerTripped = false;
162390
162684
  try {
162391
162685
  for (const taskName of args.tasks) {
162392
162686
  if (Date.now() > deadline) {
@@ -162447,7 +162741,9 @@ async function runDream(args) {
162447
162741
  }
162448
162742
  }, {
162449
162743
  timeoutMs: args.taskTimeoutMinutes * 60 * 1000,
162450
- signal: taskAbortController.signal
162744
+ signal: taskAbortController.signal,
162745
+ fallbackModels: args.fallbackModels,
162746
+ callContext: `dreamer:${taskName}`
162451
162747
  });
162452
162748
  const messagesResponse = await args.client.session.messages({
162453
162749
  path: { id: agentSessionId },
@@ -162467,16 +162763,40 @@ async function runDream(args) {
162467
162763
  durationMs,
162468
162764
  result: taskResult
162469
162765
  });
162766
+ lastErrorSignature = null;
162767
+ consecutiveSameErrorFailures = 0;
162470
162768
  } catch (error51) {
162471
162769
  const durationMs = Date.now() - taskStartedAt;
162472
- const errorMsg = getErrorMessage(error51);
162473
- log(`[dreamer] task ${taskName}: failed after ${(durationMs / 1000).toFixed(1)}s — ${errorMsg}`);
162770
+ const errorDescription = describeError(error51);
162771
+ logWithStackHead(`[dreamer] task ${taskName}: failed after ${(durationMs / 1000).toFixed(1)}s — ${errorDescription.brief}`, errorDescription.stackHead);
162474
162772
  result.tasks.push({
162475
162773
  name: taskName,
162476
162774
  durationMs,
162477
162775
  result: null,
162478
- error: errorMsg
162776
+ error: errorDescription.brief
162479
162777
  });
162778
+ if (shouldSkipCircuitBreaker(error51, errorDescription.brief)) {
162779
+ lastErrorSignature = null;
162780
+ consecutiveSameErrorFailures = 0;
162781
+ } else {
162782
+ const signature = getCircuitBreakerSignature(error51, errorDescription.brief);
162783
+ if (signature === lastErrorSignature) {
162784
+ consecutiveSameErrorFailures += 1;
162785
+ } else {
162786
+ lastErrorSignature = signature;
162787
+ consecutiveSameErrorFailures = 1;
162788
+ }
162789
+ if (consecutiveSameErrorFailures >= CIRCUIT_BREAKER_THRESHOLD) {
162790
+ circuitBreakerTripped = true;
162791
+ log(`[dreamer] circuit breaker: ${consecutiveSameErrorFailures} consecutive ${signature} failures — aborting remaining tasks`);
162792
+ result.tasks.push({
162793
+ name: "circuit-breaker",
162794
+ durationMs: 0,
162795
+ result: "",
162796
+ error: `Aborted remaining tasks: ${consecutiveSameErrorFailures} consecutive ${signature} failures. Configure dreamer model/fallback_models in magic-context.jsonc.`
162797
+ });
162798
+ }
162799
+ }
162480
162800
  } finally {
162481
162801
  clearInterval(leaseRenewalInterval);
162482
162802
  if (agentSessionId) {
@@ -162488,8 +162808,20 @@ async function runDream(args) {
162488
162808
  });
162489
162809
  }
162490
162810
  }
162811
+ if (circuitBreakerTripped) {
162812
+ break;
162813
+ }
162814
+ }
162815
+ if (circuitBreakerTripped) {
162816
+ log("[dreamer] circuit breaker: skipping post-task phases");
162817
+ result.tasks.push({
162818
+ name: "post-task-phases",
162819
+ durationMs: 0,
162820
+ result: "",
162821
+ error: "Skipped post-task phases after circuit breaker tripped; configure dreamer model/fallback_models in magic-context.jsonc."
162822
+ });
162491
162823
  }
162492
- if (args.experimentalUserMemories?.enabled && Date.now() <= deadline) {
162824
+ if (!circuitBreakerTripped && args.experimentalUserMemories?.enabled && Date.now() <= deadline) {
162493
162825
  const umStart = Date.now();
162494
162826
  try {
162495
162827
  const reviewResult = await reviewUserMemories({
@@ -162499,7 +162831,8 @@ async function runDream(args) {
162499
162831
  sessionDirectory: args.sessionDirectory,
162500
162832
  holderId,
162501
162833
  deadline,
162502
- promotionThreshold: args.experimentalUserMemories.promotionThreshold
162834
+ promotionThreshold: args.experimentalUserMemories.promotionThreshold,
162835
+ fallbackModels: args.fallbackModels
162503
162836
  });
162504
162837
  const umOutput = `promoted=${reviewResult.promoted} merged=${reviewResult.merged} dismissed=${reviewResult.dismissed} consumed=${reviewResult.candidatesConsumed}`;
162505
162838
  if (reviewResult.promoted > 0 || reviewResult.merged > 0 || reviewResult.dismissed > 0) {
@@ -162511,16 +162844,17 @@ async function runDream(args) {
162511
162844
  result: umOutput
162512
162845
  });
162513
162846
  } catch (error51) {
162514
- log(`[dreamer] user-memory review failed: ${getErrorMessage(error51)}`);
162847
+ const errorDescription = describeError(error51);
162848
+ logWithStackHead(`[dreamer] user-memory review failed: ${errorDescription.brief}`, errorDescription.stackHead);
162515
162849
  result.tasks.push({
162516
162850
  name: "user memories",
162517
162851
  durationMs: Date.now() - umStart,
162518
162852
  result: "",
162519
- error: getErrorMessage(error51)
162853
+ error: errorDescription.brief
162520
162854
  });
162521
162855
  }
162522
162856
  }
162523
- if (Date.now() <= deadline) {
162857
+ if (!circuitBreakerTripped && Date.now() <= deadline) {
162524
162858
  try {
162525
162859
  await evaluateSmartNotes({
162526
162860
  db: args.db,
@@ -162530,13 +162864,15 @@ async function runDream(args) {
162530
162864
  sessionDirectory: args.sessionDirectory,
162531
162865
  holderId,
162532
162866
  deadline,
162533
- result
162867
+ result,
162868
+ fallbackModels: args.fallbackModels
162534
162869
  });
162535
162870
  } catch (error51) {
162536
- log(`[dreamer] smart note evaluation failed: ${getErrorMessage(error51)}`);
162871
+ const errorDescription = describeError(error51);
162872
+ logWithStackHead(`[dreamer] smart note evaluation failed: ${errorDescription.brief}`, errorDescription.stackHead);
162537
162873
  }
162538
162874
  }
162539
- if (args.experimentalPinKeyFiles?.enabled && Date.now() <= deadline) {
162875
+ if (!circuitBreakerTripped && args.experimentalPinKeyFiles?.enabled && Date.now() <= deadline) {
162540
162876
  const kfStart = Date.now();
162541
162877
  try {
162542
162878
  await identifyKeyFiles({
@@ -162547,7 +162883,8 @@ async function runDream(args) {
162547
162883
  sessionDirectory: args.sessionDirectory ?? args.projectIdentity,
162548
162884
  holderId,
162549
162885
  deadline,
162550
- config: args.experimentalPinKeyFiles
162886
+ config: args.experimentalPinKeyFiles,
162887
+ fallbackModels: args.fallbackModels
162551
162888
  });
162552
162889
  result.tasks.push({
162553
162890
  name: "key files",
@@ -162555,12 +162892,13 @@ async function runDream(args) {
162555
162892
  result: "completed"
162556
162893
  });
162557
162894
  } catch (error51) {
162558
- log(`[key-files] identification phase failed: ${getErrorMessage(error51)}`);
162895
+ const errorDescription = describeError(error51);
162896
+ logWithStackHead(`[key-files] identification phase failed: ${errorDescription.brief}`, errorDescription.stackHead);
162559
162897
  result.tasks.push({
162560
162898
  name: "key files",
162561
162899
  durationMs: Date.now() - kfStart,
162562
162900
  result: "",
162563
- error: getErrorMessage(error51)
162901
+ error: errorDescription.brief
162564
162902
  });
162565
162903
  }
162566
162904
  }
@@ -162595,7 +162933,13 @@ async function runDream(args) {
162595
162933
  smartNotesPending: result.smartNotesPending,
162596
162934
  memoryChanges: persistedMemoryChanges
162597
162935
  });
162598
- const POST_TASK_NAMES = new Set(["smart-notes", "user memories", "key files"]);
162936
+ const POST_TASK_NAMES = new Set([
162937
+ "smart-notes",
162938
+ "user memories",
162939
+ "key files",
162940
+ "post-task-phases",
162941
+ "circuit-breaker"
162942
+ ]);
162599
162943
  const hasSuccessfulTask = result.tasks.some((t) => !t.error && !POST_TASK_NAMES.has(t.name));
162600
162944
  if (hasSuccessfulTask) {
162601
162945
  setDreamState(args.db, `last_dream_at:${args.projectIdentity}`, String(result.finishedAt));
@@ -162674,7 +163018,12 @@ Only include notes whose conditions you could definitively evaluate. Skip notes
162674
163018
  system: DREAMER_SYSTEM_PROMPT,
162675
163019
  parts: [{ type: "text", text: evaluationPrompt, synthetic: true }]
162676
163020
  }
162677
- }, { timeoutMs: Math.min(remainingMs, 300000), signal: abortController.signal });
163021
+ }, {
163022
+ timeoutMs: Math.min(remainingMs, 300000),
163023
+ signal: abortController.signal,
163024
+ fallbackModels: args.fallbackModels,
163025
+ callContext: "dreamer:smart-notes"
163026
+ });
162678
163027
  const messagesResponse = await args.client.session.messages({
162679
163028
  path: { id: agentSessionId },
162680
163029
  query: { directory: args.sessionDirectory ?? args.projectIdentity }
@@ -162733,15 +163082,15 @@ Only include notes whose conditions you could definitively evaluate. Skip notes
162733
163082
  });
162734
163083
  } catch (error51) {
162735
163084
  const durationMs = Date.now() - taskStartedAt;
162736
- const errorMsg = getErrorMessage(error51);
163085
+ const errorDescription = describeError(error51);
162737
163086
  args.result.smartNotesSurfaced = 0;
162738
163087
  args.result.smartNotesPending = pendingNotes.length;
162739
- log(`[dreamer] smart notes: failed after ${(durationMs / 1000).toFixed(1)}s — ${errorMsg}`);
163088
+ logWithStackHead(`[dreamer] smart notes: failed after ${(durationMs / 1000).toFixed(1)}s — ${errorDescription.brief}`, errorDescription.stackHead);
162740
163089
  args.result.tasks.push({
162741
163090
  name: "smart-notes",
162742
163091
  durationMs,
162743
163092
  result: null,
162744
- error: errorMsg
163093
+ error: errorDescription.brief
162745
163094
  });
162746
163095
  } finally {
162747
163096
  clearInterval(leaseInterval);
@@ -162774,7 +163123,8 @@ async function processDreamQueue(args) {
162774
163123
  maxRuntimeMinutes: args.maxRuntimeMinutes,
162775
163124
  sessionDirectory: projectDirectory,
162776
163125
  experimentalUserMemories: args.experimentalUserMemories,
162777
- experimentalPinKeyFiles: args.experimentalPinKeyFiles
163126
+ experimentalPinKeyFiles: args.experimentalPinKeyFiles,
163127
+ fallbackModels: args.fallbackModels
162778
163128
  });
162779
163129
  } catch (error51) {
162780
163130
  log(`[dreamer] runDream threw for ${entry.projectIdentity}: ${getErrorMessage(error51)}`);
@@ -163498,7 +163848,8 @@ async function sweepProject(reg, origin) {
163498
163848
  maxRuntimeMinutes: reg.dreamerConfig.max_runtime_minutes,
163499
163849
  experimentalUserMemories: reg.experimentalUserMemories,
163500
163850
  experimentalPinKeyFiles: reg.experimentalPinKeyFiles,
163501
- projectIdentity: registrationIdentity
163851
+ projectIdentity: registrationIdentity,
163852
+ fallbackModels: resolveFallbackChain(DREAMER_AGENT, reg.dreamerConfig.fallback_models)
163502
163853
  });
163503
163854
  } catch (error51) {
163504
163855
  log(`[dreamer] timer-triggered queue processing failed for ${reg.directory}:`, error51);
@@ -165296,8 +165647,9 @@ function tagTranscript(sessionId, transcript, tagger, db, options = {}) {
165296
165647
  continue;
165297
165648
  const messageId = message.info.id;
165298
165649
  let textOrdinal = 0;
165299
- for (let partIndex = 0;partIndex < message.parts.length; partIndex += 1) {
165300
- const part = message.parts[partIndex];
165650
+ const parts = message.parts;
165651
+ for (let partIndex = 0;partIndex < parts.length; partIndex += 1) {
165652
+ const part = parts[partIndex];
165301
165653
  if (part === undefined)
165302
165654
  continue;
165303
165655
  if (part.kind === "text") {
@@ -166264,7 +166616,7 @@ var DEDUP_SAFE_TOOLS = new Set([
166264
166616
  "mcp_lsp_prepare_rename"
166265
166617
  ]);
166266
166618
  function buildPiToolFingerprints(messages) {
166267
- const fingerprints = new Map;
166619
+ const fingerprints2 = new Map;
166268
166620
  for (const message of messages) {
166269
166621
  if (!message || typeof message !== "object")
166270
166622
  continue;
@@ -166295,10 +166647,10 @@ function buildPiToolFingerprints(messages) {
166295
166647
  } catch {
166296
166648
  continue;
166297
166649
  }
166298
- fingerprints.set(p.id, `${p.name}:${serialized}`);
166650
+ fingerprints2.set(p.id, `${p.name}:${serialized}`);
166299
166651
  }
166300
166652
  }
166301
- return fingerprints;
166653
+ return fingerprints2;
166302
166654
  }
166303
166655
  function collectStaleReduceCallIds(messages, messageIdToMaxTag, toolAgeCutoff) {
166304
166656
  const staleCallIds = new Set;
@@ -170396,7 +170748,8 @@ async function runCompressorPass2(args) {
170396
170748
  targetTokens,
170397
170749
  outputCount,
170398
170750
  outputDepth,
170399
- historianTimeoutMs
170751
+ historianTimeoutMs,
170752
+ fallbackModels
170400
170753
  } = args;
170401
170754
  const prompt = buildCompressorPrompt(compartments, currentTokens, targetTokens, outputDepth, outputCount);
170402
170755
  let agentSessionId = null;
@@ -170418,7 +170771,11 @@ async function runCompressorPass2(args) {
170418
170771
  agent: HISTORIAN_AGENT2,
170419
170772
  parts: [{ type: "text", text: prompt, synthetic: true }]
170420
170773
  }
170421
- }, { timeoutMs: historianTimeoutMs ?? DEFAULT_HISTORIAN_TIMEOUT_MS });
170774
+ }, {
170775
+ timeoutMs: historianTimeoutMs ?? DEFAULT_HISTORIAN_TIMEOUT_MS,
170776
+ fallbackModels,
170777
+ callContext: "compressor"
170778
+ });
170422
170779
  const messagesResponse = await client.session.messages({
170423
170780
  path: { id: agentSessionId },
170424
170781
  query: { directory }
@@ -170556,7 +170913,8 @@ async function runHistorianPrompt(args) {
170556
170913
  timeoutMs,
170557
170914
  dumpLabel,
170558
170915
  modelOverride,
170559
- agentId = HISTORIAN_AGENT
170916
+ agentId = HISTORIAN_AGENT,
170917
+ fallbackModels
170560
170918
  } = args;
170561
170919
  let agentSessionId = null;
170562
170920
  try {
@@ -170583,7 +170941,11 @@ async function runHistorianPrompt(args) {
170583
170941
  ...modelOverride ? { model: modelOverride } : {},
170584
170942
  parts: [{ type: "text", text: prompt, synthetic: true }]
170585
170943
  }
170586
- }, { timeoutMs: timeoutMs ?? DEFAULT_HISTORIAN_TIMEOUT_MS });
170944
+ }, {
170945
+ timeoutMs: timeoutMs ?? DEFAULT_HISTORIAN_TIMEOUT_MS,
170946
+ fallbackModels: modelOverride ? undefined : fallbackModels,
170947
+ callContext: agentId === HISTORIAN_EDITOR_AGENT ? "historian:editor" : "historian"
170948
+ });
170587
170949
  sessionLog(parentSessionId, `historian: prompt completed (attempt ${retryIndex + 1}/${MAX_HISTORIAN_RETRIES + 1})`);
170588
170950
  break;
170589
170951
  } catch (error51) {
@@ -171039,6 +171401,7 @@ Historian pass ${passCount + 1}, attempt ${passAttempt} started for messages ${c
171039
171401
  dumpLabelBase: `partial-recomp-${sessionId}-${chunk.startIndex}-${chunk.endIndex}-pass-${passCount + 1}`,
171040
171402
  timeoutMs: historianTimeoutMs,
171041
171403
  fallbackModelId: deps.fallbackModelId,
171404
+ fallbackModels: deps.fallbackModels,
171042
171405
  twoPass: deps.historianTwoPass,
171043
171406
  callbacks: {
171044
171407
  onRepairRetry: async (error51) => {
@@ -171241,6 +171604,7 @@ Historian pass ${passCount + 1}, attempt ${passAttempt} started for messages ${c
171241
171604
  dumpLabelBase: `recomp-${sessionId}-${chunk.startIndex}-${chunk.endIndex}-pass-${passCount + 1}`,
171242
171605
  timeoutMs: historianTimeoutMs,
171243
171606
  fallbackModelId: deps.fallbackModelId,
171607
+ fallbackModels: deps.fallbackModels,
171244
171608
  twoPass: deps.historianTwoPass,
171245
171609
  callbacks: {
171246
171610
  onRepairRetry: async (error51) => {
@@ -171338,6 +171702,7 @@ Nothing was written.`;
171338
171702
  directory: sessionDirectory,
171339
171703
  historyBudgetTokens: deps.historyBudgetTokens,
171340
171704
  historianTimeoutMs,
171705
+ fallbackModels: deps.fallbackModels,
171341
171706
  minCompartmentRatio: deps.compressorMinCompartmentRatio,
171342
171707
  maxMergeDepth: deps.compressorMaxMergeDepth
171343
171708
  });
@@ -171874,7 +172239,7 @@ import {
171874
172239
  // package.json
171875
172240
  var package_default = {
171876
172241
  name: "@cortexkit/pi-magic-context",
171877
- version: "0.17.1",
172242
+ version: "0.18.0",
171878
172243
  type: "module",
171879
172244
  description: "Pi coding agent extension for Magic Context — cross-session memory and context management",
171880
172245
  main: "dist/index.js",
@@ -24343,6 +24343,25 @@ var MIGRATIONS = [
24343
24343
  WHERE type = 'tool' AND tool_owner_message_id IS NULL;
24344
24344
  `);
24345
24345
  }
24346
+ },
24347
+ {
24348
+ version: 11,
24349
+ description: "Add todo state synthesis columns to session_meta",
24350
+ up: (db) => {
24351
+ const cols = db.prepare("PRAGMA table_info(session_meta)").all();
24352
+ if (!cols.some((c) => c.name === "last_todo_state")) {
24353
+ db.exec("ALTER TABLE session_meta ADD COLUMN last_todo_state TEXT DEFAULT ''");
24354
+ }
24355
+ if (!cols.some((c) => c.name === "todo_synthetic_call_id")) {
24356
+ db.exec("ALTER TABLE session_meta ADD COLUMN todo_synthetic_call_id TEXT DEFAULT ''");
24357
+ }
24358
+ if (!cols.some((c) => c.name === "todo_synthetic_anchor_message_id")) {
24359
+ db.exec("ALTER TABLE session_meta ADD COLUMN todo_synthetic_anchor_message_id TEXT DEFAULT ''");
24360
+ }
24361
+ if (!cols.some((c) => c.name === "todo_synthetic_state_json")) {
24362
+ db.exec("ALTER TABLE session_meta ADD COLUMN todo_synthetic_state_json TEXT DEFAULT ''");
24363
+ }
24364
+ }
24346
24365
  }
24347
24366
  ];
24348
24367
  function ensureMigrationsTable(db) {
@@ -157004,13 +157023,16 @@ function mergeCommitHashes(existing, next) {
157004
157023
 
157005
157024
  // ../plugin/src/features/magic-context/tool-definition-tokens.ts
157006
157025
  var measurements = new Map;
157026
+ var fingerprints = new Map;
157007
157027
  var persistenceDb = null;
157028
+ var cachedInsertStmt = null;
157008
157029
  function keyFor(providerID, modelID, agentName) {
157009
157030
  const agent = agentName && agentName.length > 0 ? agentName : "default";
157010
157031
  return `${providerID}/${modelID}/${agent}`;
157011
157032
  }
157012
157033
  function setDatabase(db) {
157013
157034
  persistenceDb = db;
157035
+ cachedInsertStmt = null;
157014
157036
  }
157015
157037
  function loadToolDefinitionMeasurements(db) {
157016
157038
  let rows = [];
@@ -157506,6 +157528,10 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
157506
157528
  note_nudge_trigger_message_id TEXT DEFAULT '',
157507
157529
  note_nudge_sticky_text TEXT DEFAULT '',
157508
157530
  note_nudge_sticky_message_id TEXT DEFAULT '',
157531
+ last_todo_state TEXT DEFAULT '',
157532
+ todo_synthetic_call_id TEXT DEFAULT '',
157533
+ todo_synthetic_anchor_message_id TEXT DEFAULT '',
157534
+ todo_synthetic_state_json TEXT DEFAULT '',
157509
157535
  is_subagent INTEGER DEFAULT 0,
157510
157536
  last_context_percentage REAL DEFAULT 0,
157511
157537
  last_input_tokens INTEGER DEFAULT 0,
@@ -157570,6 +157596,10 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
157570
157596
  ensureColumn(db, "session_meta", "note_nudge_trigger_message_id", "TEXT DEFAULT ''");
157571
157597
  ensureColumn(db, "session_meta", "note_nudge_sticky_text", "TEXT DEFAULT ''");
157572
157598
  ensureColumn(db, "session_meta", "note_nudge_sticky_message_id", "TEXT DEFAULT ''");
157599
+ ensureColumn(db, "session_meta", "last_todo_state", "TEXT DEFAULT ''");
157600
+ ensureColumn(db, "session_meta", "todo_synthetic_call_id", "TEXT DEFAULT ''");
157601
+ ensureColumn(db, "session_meta", "todo_synthetic_anchor_message_id", "TEXT DEFAULT ''");
157602
+ ensureColumn(db, "session_meta", "todo_synthetic_state_json", "TEXT DEFAULT ''");
157573
157603
  ensureColumn(db, "session_meta", "note_last_read_at", "INTEGER DEFAULT 0");
157574
157604
  ensureColumn(db, "session_meta", "times_execute_threshold_reached", "INTEGER DEFAULT 0");
157575
157605
  ensureColumn(db, "session_meta", "compartment_in_progress", "INTEGER DEFAULT 0");
@@ -157634,6 +157664,10 @@ function healNullTextColumns(db) {
157634
157664
  ["note_nudge_trigger_message_id", ""],
157635
157665
  ["note_nudge_sticky_text", ""],
157636
157666
  ["note_nudge_sticky_message_id", ""],
157667
+ ["last_todo_state", ""],
157668
+ ["todo_synthetic_call_id", ""],
157669
+ ["todo_synthetic_anchor_message_id", ""],
157670
+ ["todo_synthetic_state_json", ""],
157637
157671
  ["system_prompt_hash", ""],
157638
157672
  ["stripped_placeholder_ids", ""],
157639
157673
  ["memory_block_cache", ""],
@@ -163995,7 +164029,8 @@ var META_COLUMNS = {
163995
164029
  systemPromptTokens: "system_prompt_tokens",
163996
164030
  conversationTokens: "conversation_tokens",
163997
164031
  toolCallTokens: "tool_call_tokens",
163998
- clearedReasoningThroughTag: "cleared_reasoning_through_tag"
164032
+ clearedReasoningThroughTag: "cleared_reasoning_through_tag",
164033
+ lastTodoState: "last_todo_state"
163999
164034
  };
164000
164035
  var BOOLEAN_META_KEYS = new Set(["isSubagent", "compartmentInProgress"]);
164001
164036
  function isStringOrNull(value) {
@@ -164008,7 +164043,7 @@ function isSessionMetaRow(row) {
164008
164043
  if (row === null || typeof row !== "object")
164009
164044
  return false;
164010
164045
  const r = row;
164011
- 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.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);
164046
+ 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.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);
164012
164047
  }
164013
164048
  function getDefaultSessionMeta(sessionId) {
164014
164049
  return {
@@ -164028,7 +164063,8 @@ function getDefaultSessionMeta(sessionId) {
164028
164063
  systemPromptTokens: 0,
164029
164064
  conversationTokens: 0,
164030
164065
  toolCallTokens: 0,
164031
- clearedReasoningThroughTag: 0
164066
+ clearedReasoningThroughTag: 0,
164067
+ lastTodoState: ""
164032
164068
  };
164033
164069
  }
164034
164070
  function ensureSessionMetaRow(db, sessionId) {
@@ -164040,6 +164076,7 @@ function toSessionMeta(row) {
164040
164076
  const transformErrorRaw = typeof row.last_transform_error === "string" ? row.last_transform_error : "";
164041
164077
  const cacheTtlRaw = typeof row.cache_ttl === "string" && row.cache_ttl.length > 0 ? row.cache_ttl : "5m";
164042
164078
  const systemPromptHashRaw = row.system_prompt_hash == null ? "" : row.system_prompt_hash;
164079
+ const lastTodoStateRaw = typeof row.last_todo_state === "string" ? row.last_todo_state : "";
164043
164080
  const numOrZero = (value) => typeof value === "number" ? value : 0;
164044
164081
  return {
164045
164082
  sessionId: row.session_id,
@@ -164058,7 +164095,8 @@ function toSessionMeta(row) {
164058
164095
  systemPromptTokens: numOrZero(row.system_prompt_tokens),
164059
164096
  conversationTokens: numOrZero(row.conversation_tokens),
164060
164097
  toolCallTokens: numOrZero(row.tool_call_tokens),
164061
- clearedReasoningThroughTag: numOrZero(row.cleared_reasoning_through_tag)
164098
+ clearedReasoningThroughTag: numOrZero(row.cleared_reasoning_through_tag),
164099
+ lastTodoState: lastTodoStateRaw
164062
164100
  };
164063
164101
  }
164064
164102
 
@@ -164274,7 +164312,7 @@ function resolveIsSubagentFromOpenCodeDb(sessionId) {
164274
164312
 
164275
164313
  // ../plugin/src/features/magic-context/storage-meta-session.ts
164276
164314
  function getOrCreateSessionMeta(db, sessionId) {
164277
- const result = db.prepare("SELECT session_id, last_response_time, cache_ttl, counter, last_nudge_tokens, last_nudge_band, last_transform_error, is_subagent, last_context_percentage, last_input_tokens, times_execute_threshold_reached, compartment_in_progress, system_prompt_hash, system_prompt_tokens, conversation_tokens, tool_call_tokens, cleared_reasoning_through_tag FROM session_meta WHERE session_id = ?").get(sessionId);
164315
+ const result = db.prepare("SELECT session_id, last_response_time, cache_ttl, counter, last_nudge_tokens, last_nudge_band, last_transform_error, is_subagent, last_context_percentage, last_input_tokens, times_execute_threshold_reached, compartment_in_progress, system_prompt_hash, system_prompt_tokens, conversation_tokens, tool_call_tokens, cleared_reasoning_through_tag, last_todo_state FROM session_meta WHERE session_id = ?").get(sessionId);
164278
164316
  if (isSessionMetaRow(result)) {
164279
164317
  return toSessionMeta(result);
164280
164318
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cortexkit/pi-magic-context",
3
- "version": "0.17.1",
3
+ "version": "0.18.0",
4
4
  "type": "module",
5
5
  "description": "Pi coding agent extension for Magic Context — cross-session memory and context management",
6
6
  "main": "dist/index.js",