@cortexkit/opencode-magic-context 0.21.4 → 0.21.6

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 (40) hide show
  1. package/README.md +1 -1
  2. package/dist/agents/permissions.d.ts +142 -0
  3. package/dist/agents/permissions.d.ts.map +1 -0
  4. package/dist/config/index.d.ts.map +1 -1
  5. package/dist/config/schema/agent-overrides.d.ts +12 -12
  6. package/dist/config/schema/magic-context.d.ts +87 -87
  7. package/dist/config/variable.d.ts +9 -7
  8. package/dist/config/variable.d.ts.map +1 -1
  9. package/dist/features/magic-context/key-files/project-key-files.d.ts.map +1 -1
  10. package/dist/features/magic-context/migrations.d.ts +18 -0
  11. package/dist/features/magic-context/migrations.d.ts.map +1 -1
  12. package/dist/features/magic-context/storage-db.d.ts.map +1 -1
  13. package/dist/features/magic-context/storage-meta-persisted.d.ts +17 -0
  14. package/dist/features/magic-context/storage-meta-persisted.d.ts.map +1 -1
  15. package/dist/features/magic-context/storage-meta.d.ts +1 -1
  16. package/dist/features/magic-context/storage-meta.d.ts.map +1 -1
  17. package/dist/features/magic-context/storage-notes.d.ts +6 -2
  18. package/dist/features/magic-context/storage-notes.d.ts.map +1 -1
  19. package/dist/features/magic-context/storage-tags.d.ts.map +1 -1
  20. package/dist/features/magic-context/storage.d.ts +1 -1
  21. package/dist/features/magic-context/storage.d.ts.map +1 -1
  22. package/dist/hooks/magic-context/compartment-trigger.d.ts +2 -2
  23. package/dist/hooks/magic-context/compartment-trigger.d.ts.map +1 -1
  24. package/dist/hooks/magic-context/strip-content.d.ts.map +1 -1
  25. package/dist/index.d.ts.map +1 -1
  26. package/dist/index.js +186 -60
  27. package/dist/plugin/rpc-handlers.d.ts +1 -1
  28. package/dist/plugin/rpc-handlers.d.ts.map +1 -1
  29. package/dist/shared/jsonc-parser.d.ts +1 -0
  30. package/dist/shared/jsonc-parser.d.ts.map +1 -1
  31. package/dist/shared/rpc-types.d.ts +10 -0
  32. package/dist/shared/rpc-types.d.ts.map +1 -1
  33. package/dist/tools/ctx-note/tools.d.ts.map +1 -1
  34. package/dist/tui/data/context-db.d.ts.map +1 -1
  35. package/package.json +1 -1
  36. package/src/shared/jsonc-parser.ts +1 -1
  37. package/src/shared/rpc-types.ts +10 -0
  38. package/src/tui/data/context-db.ts +1 -0
  39. package/src/tui/index.tsx +8 -3
  40. package/src/tui/slots/sidebar-content.tsx +14 -2
package/dist/index.js CHANGED
@@ -156280,7 +156280,7 @@ function promoteRecompStaging(db, sessionId) {
156280
156280
  insertFactRows(db, sessionId, staging.facts, now);
156281
156281
  db.prepare("DELETE FROM recomp_compartments WHERE session_id = ?").run(sessionId);
156282
156282
  db.prepare("DELETE FROM recomp_facts WHERE session_id = ?").run(sessionId);
156283
- db.prepare("UPDATE session_meta SET memory_block_cache = '' WHERE session_id = ?").run(sessionId);
156283
+ db.prepare("UPDATE session_meta SET memory_block_cache = '', memory_block_ids = '' WHERE session_id = ?").run(sessionId);
156284
156284
  return { compartments: staging.compartments, facts: staging.facts };
156285
156285
  })();
156286
156286
  }
@@ -157705,8 +157705,10 @@ function deleteOrphanProjectKeyFiles(db, now = Date.now()) {
157705
157705
  if (existsSync10(row.projectPath))
157706
157706
  continue;
157707
157707
  try {
157708
- db.prepare("DELETE FROM project_key_files WHERE project_path = ?").run(row.projectPath);
157709
- db.prepare("DELETE FROM project_key_files_version WHERE project_path = ?").run(row.projectPath);
157708
+ db.transaction(() => {
157709
+ db.prepare("DELETE FROM project_key_files WHERE project_path = ?").run(row.projectPath);
157710
+ db.prepare("DELETE FROM project_key_files_version WHERE project_path = ?").run(row.projectPath);
157711
+ })();
157710
157712
  deletedProjects++;
157711
157713
  } catch (error51) {
157712
157714
  log(`[key-files] orphan GC failed for ${row.projectPath}:`, error51);
@@ -158254,6 +158256,12 @@ function getNoteById(db, noteId) {
158254
158256
  const row = db.prepare("SELECT * FROM notes WHERE id = ?").get(noteId);
158255
158257
  return isNoteRow(row) ? toNote(row) : null;
158256
158258
  }
158259
+ function noteBelongsToScope(note, scope) {
158260
+ if (note.type === "session") {
158261
+ return note.sessionId === scope.sessionId;
158262
+ }
158263
+ return note.projectPath === scope.projectPath;
158264
+ }
158257
158265
  function buildStatusClause(status) {
158258
158266
  if (status === undefined) {
158259
158267
  return null;
@@ -158315,9 +158323,9 @@ function getPendingSmartNotes(db, projectPath) {
158315
158323
  function getReadySmartNotes(db, projectPath) {
158316
158324
  return getSmartNotes(db, projectPath, "ready");
158317
158325
  }
158318
- function updateNote(db, noteId, updates) {
158326
+ function updateNote(db, noteId, updates, scope) {
158319
158327
  const existing = getNoteById(db, noteId);
158320
- if (!existing) {
158328
+ if (!existing || !noteBelongsToScope(existing, scope)) {
158321
158329
  return null;
158322
158330
  }
158323
158331
  const now = Date.now();
@@ -158364,7 +158372,11 @@ function updateNote(db, noteId, updates) {
158364
158372
  const result = db.prepare(`UPDATE notes SET ${sets.join(", ")} WHERE id = ? RETURNING *`).get(...params);
158365
158373
  return isNoteRow(result) ? toNote(result) : null;
158366
158374
  }
158367
- function dismissNote(db, noteId) {
158375
+ function dismissNote(db, noteId, scope) {
158376
+ const existing = getNoteById(db, noteId);
158377
+ if (!existing || !noteBelongsToScope(existing, scope)) {
158378
+ return false;
158379
+ }
158368
158380
  const result = db.prepare("UPDATE notes SET status = 'dismissed', updated_at = ? WHERE id = ? AND status != 'dismissed'").run(Date.now(), noteId);
158369
158381
  return result.changes > 0;
158370
158382
  }
@@ -160472,7 +160484,7 @@ function getCurrentVersion(db) {
160472
160484
  const row = db.prepare("SELECT MAX(version) as version FROM schema_migrations").get();
160473
160485
  return row?.version ?? 0;
160474
160486
  }
160475
- function isSiblingMigrationConflict(error51, version2) {
160487
+ function isSiblingMigrationConflict(db, error51, version2) {
160476
160488
  if (!(error51 instanceof Error))
160477
160489
  return false;
160478
160490
  const code = error51.code;
@@ -160484,7 +160496,8 @@ function isSiblingMigrationConflict(error51, version2) {
160484
160496
  return false;
160485
160497
  if (!msg.toLowerCase().includes("version"))
160486
160498
  return false;
160487
- return true;
160499
+ const confirmed = db.prepare("SELECT 1 FROM schema_migrations WHERE version = ?").get(version2);
160500
+ return confirmed != null;
160488
160501
  }
160489
160502
  function runMigrations(db) {
160490
160503
  ensureMigrationsTable(db);
@@ -160505,7 +160518,7 @@ function runMigrations(db) {
160505
160518
  log(`[migrations] applied v${migration.version}: ${migration.description}`);
160506
160519
  migrationIndex += 1;
160507
160520
  } catch (error51) {
160508
- if (isSiblingMigrationConflict(error51, migration.version)) {
160521
+ if (isSiblingMigrationConflict(db, error51, migration.version)) {
160509
160522
  log(`[migrations] v${migration.version} already applied by sibling instance — resuming with re-read version`);
160510
160523
  const reReadVersion = getCurrentVersion(db);
160511
160524
  if (reReadVersion <= currentVersion) {
@@ -160911,6 +160924,16 @@ var init_migrations = __esm(async () => {
160911
160924
  WHERE auto_search_hint_decisions IS NULL
160912
160925
  `);
160913
160926
  }
160927
+ },
160928
+ {
160929
+ version: 18,
160930
+ description: "Add pending_pi_compaction_marker_state column for Pi deferred marker drain",
160931
+ up: (db) => {
160932
+ const cols = db.prepare("PRAGMA table_info(session_meta)").all();
160933
+ if (!cols.some((c) => c.name === "pending_pi_compaction_marker_state")) {
160934
+ db.exec("ALTER TABLE session_meta ADD COLUMN pending_pi_compaction_marker_state TEXT");
160935
+ }
160936
+ }
160914
160937
  }
160915
160938
  ];
160916
160939
  });
@@ -161442,6 +161465,11 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
161442
161465
  -- Excluded from healNullTextColumns. Readers filter IS NOT NULL AND
161443
161466
  -- != empty-string defensively. Plan v6 section 3.
161444
161467
  pending_compaction_marker_state TEXT,
161468
+ -- pending_pi_compaction_marker_state: intentionally NULLABLE without a
161469
+ -- default. Absence of a deferred Pi-native marker is SQL NULL; presence
161470
+ -- is a valid JSON blob written via setPendingPiCompactionMarkerState.
161471
+ -- Excluded from healNullTextColumns.
161472
+ pending_pi_compaction_marker_state TEXT,
161445
161473
  -- deferred_execute_state: intentionally NULLABLE without a default.
161446
161474
  -- Absence is SQL NULL; presence is a JSON blob written via
161447
161475
  -- setDeferredExecutePendingIfAbsent. Excluded from healNullTextColumns.
@@ -161538,6 +161566,7 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
161538
161566
  ensureColumn(db, "session_meta", "detected_context_limit", "INTEGER DEFAULT 0");
161539
161567
  ensureColumn(db, "session_meta", "needs_emergency_recovery", "INTEGER DEFAULT 0");
161540
161568
  ensureColumn(db, "session_meta", "pending_compaction_marker_state", "TEXT");
161569
+ ensureColumn(db, "session_meta", "pending_pi_compaction_marker_state", "TEXT");
161541
161570
  ensureColumn(db, "session_meta", "deferred_execute_state", "TEXT");
161542
161571
  ensureColumn(db, "tags", "harness", "TEXT NOT NULL DEFAULT 'opencode'");
161543
161572
  ensureColumn(db, "pending_ops", "harness", "TEXT NOT NULL DEFAULT 'opencode'");
@@ -162613,22 +162642,24 @@ function updateTagMessageId(db, sessionId, tagId, messageId) {
162613
162642
  getUpdateTagMessageIdStatement(db).run(messageId, sessionId, tagId);
162614
162643
  }
162615
162644
  function deleteTagsByMessageId(db, sessionId, messageId) {
162616
- const escapedMessageId = escapeLikePattern(messageId);
162617
- const textPartPattern = `${escapedMessageId}:p%`;
162618
- const filePartPattern = `${escapedMessageId}:file%`;
162619
- const messageScopedTags = getTagNumbersByMessageIdStatement(db).all(sessionId, messageId, textPartPattern, filePartPattern).filter(isTagNumberRow).map((row) => row.tag_number);
162620
- const ownerScopedTagNumbers = getOwnerScopedToolTagNumbers(db, sessionId, messageId);
162621
- if (messageScopedTags.length === 0 && ownerScopedTagNumbers.length === 0) {
162622
- return [];
162623
- }
162624
- if (messageScopedTags.length > 0) {
162625
- getDeleteTagsByMessageIdStatement(db).run(sessionId, messageId, textPartPattern, filePartPattern);
162626
- }
162627
- if (ownerScopedTagNumbers.length > 0) {
162628
- deleteToolTagsByOwner(db, sessionId, messageId);
162629
- }
162630
- const merged = new Set([...messageScopedTags, ...ownerScopedTagNumbers]);
162631
- return Array.from(merged).sort((a, b) => a - b);
162645
+ return db.transaction(() => {
162646
+ const escapedMessageId = escapeLikePattern(messageId);
162647
+ const textPartPattern = `${escapedMessageId}:p%`;
162648
+ const filePartPattern = `${escapedMessageId}:file%`;
162649
+ const messageScopedTags = getTagNumbersByMessageIdStatement(db).all(sessionId, messageId, textPartPattern, filePartPattern).filter(isTagNumberRow).map((row) => row.tag_number);
162650
+ const ownerScopedTagNumbers = getOwnerScopedToolTagNumbers(db, sessionId, messageId);
162651
+ if (messageScopedTags.length === 0 && ownerScopedTagNumbers.length === 0) {
162652
+ return [];
162653
+ }
162654
+ if (messageScopedTags.length > 0) {
162655
+ getDeleteTagsByMessageIdStatement(db).run(sessionId, messageId, textPartPattern, filePartPattern);
162656
+ }
162657
+ if (ownerScopedTagNumbers.length > 0) {
162658
+ deleteToolTagsByOwner(db, sessionId, messageId);
162659
+ }
162660
+ const merged = new Set([...messageScopedTags, ...ownerScopedTagNumbers]);
162661
+ return Array.from(merged).sort((a, b) => a - b);
162662
+ })();
162632
162663
  }
162633
162664
  function getOwnerScopedToolTagNumbers(db, sessionId, ownerMsgId) {
162634
162665
  let stmt = getOwnerScopedToolTagNumbersStatements.get(db);
@@ -166409,6 +166440,32 @@ var init_tui_config = __esm(() => {
166409
166440
  import_comment_json4 = __toESM(require_src2(), 1);
166410
166441
  PLUGIN_ENTRY = `${PLUGIN_NAME}@latest`;
166411
166442
  });
166443
+ // src/agents/permissions.ts
166444
+ function buildAllowOnlyPermission(allowedTools) {
166445
+ const permission = { "*": "deny" };
166446
+ for (const tool of allowedTools) {
166447
+ permission[tool] = "allow";
166448
+ }
166449
+ return permission;
166450
+ }
166451
+ var HISTORIAN_ALLOWED_TOOLS = ["read", "aft_outline", "aft_zoom"];
166452
+ var DREAMER_ALLOWED_TOOLS = [
166453
+ "read",
166454
+ "grep",
166455
+ "glob",
166456
+ "bash",
166457
+ "aft_outline",
166458
+ "aft_zoom",
166459
+ "ctx_memory",
166460
+ "ctx_search",
166461
+ "ctx_note"
166462
+ ];
166463
+ var SIDEKICK_ALLOWED_TOOLS = [
166464
+ "ctx_search",
166465
+ "ctx_memory",
166466
+ "aft_outline",
166467
+ "aft_zoom"
166468
+ ];
166412
166469
  // src/config/index.ts
166413
166470
  init_jsonc_parser();
166414
166471
  init_magic_context();
@@ -166417,6 +166474,7 @@ import { homedir as homedir2 } from "node:os";
166417
166474
  import { join } from "node:path";
166418
166475
 
166419
166476
  // src/config/variable.ts
166477
+ init_jsonc_parser();
166420
166478
  import { existsSync as existsSync2, readFileSync as readFileSync2 } from "node:fs";
166421
166479
  import { homedir } from "node:os";
166422
166480
  import { dirname, isAbsolute, resolve } from "node:path";
@@ -166425,6 +166483,21 @@ var FILE_PATTERN = /\{file:([^}]+)\}/g;
166425
166483
  function substituteConfigVariables(input) {
166426
166484
  const warnings = [];
166427
166485
  let text = input.text;
166486
+ if (input.isProjectConfig) {
166487
+ const hasEnvTokens = ENV_PATTERN.test(text);
166488
+ const hasFileTokens = FILE_PATTERN.test(text);
166489
+ ENV_PATTERN.lastIndex = 0;
166490
+ FILE_PATTERN.lastIndex = 0;
166491
+ if (hasEnvTokens || hasFileTokens) {
166492
+ const tokenTypes = [
166493
+ hasEnvTokens ? "{env:}" : undefined,
166494
+ hasFileTokens ? "{file:}" : undefined
166495
+ ].filter(Boolean).join(" and ");
166496
+ warnings.push(`Project-level config no longer supports ${tokenTypes} tokens for security reasons; leaving tokens literal. Move secret expansion to user-level config.`);
166497
+ }
166498
+ return { text, warnings };
166499
+ }
166500
+ text = stripJsonComments(text);
166428
166501
  text = text.replace(ENV_PATTERN, (_, rawName) => {
166429
166502
  const varName = rawName.trim();
166430
166503
  const value = varName ? process.env[varName] : undefined;
@@ -166432,7 +166505,7 @@ function substituteConfigVariables(input) {
166432
166505
  warnings.push(`Environment variable ${varName} is not set (referenced via {env:${varName}}); using empty string`);
166433
166506
  return "";
166434
166507
  }
166435
- return value;
166508
+ return JSON.stringify(value).slice(1, -1);
166436
166509
  });
166437
166510
  const fileMatches = Array.from(text.matchAll(FILE_PATTERN));
166438
166511
  if (fileMatches.length === 0) {
@@ -166487,13 +166560,17 @@ function getUserConfigBasePath() {
166487
166560
  function getProjectConfigBasePath(directory) {
166488
166561
  return join(directory, ".opencode", CONFIG_FILE_BASENAME);
166489
166562
  }
166490
- function loadConfigFile(configPath) {
166563
+ function loadConfigFile(configPath, isProjectConfig = false) {
166491
166564
  try {
166492
166565
  if (!existsSync3(configPath)) {
166493
166566
  return null;
166494
166567
  }
166495
166568
  const rawText = readFileSync3(configPath, "utf-8");
166496
- const substituted = substituteConfigVariables({ text: rawText, configPath });
166569
+ const substituted = substituteConfigVariables({
166570
+ text: rawText,
166571
+ configPath,
166572
+ isProjectConfig
166573
+ });
166497
166574
  return {
166498
166575
  config: parseJsonc(substituted.text),
166499
166576
  warnings: substituted.warnings.map((w) => `${configPath}: ${w}`)
@@ -166521,7 +166598,11 @@ function loadConfigFileDetailed(configPath, source) {
166521
166598
  };
166522
166599
  }
166523
166600
  try {
166524
- const substituted = substituteConfigVariables({ text: rawText, configPath });
166601
+ const substituted = substituteConfigVariables({
166602
+ text: rawText,
166603
+ configPath,
166604
+ isProjectConfig: source === "project"
166605
+ });
166525
166606
  return {
166526
166607
  config: parseJsonc(substituted.text),
166527
166608
  warnings: substituted.warnings.map((w) => `${configPath}: ${w}`),
@@ -166693,7 +166774,7 @@ function loadPluginConfig(directory) {
166693
166774
  const dotOpenCodeDetected = detectConfigFile(getProjectConfigBasePath(directory));
166694
166775
  const projectDetected = rootDetected.format !== "none" ? rootDetected : dotOpenCodeDetected;
166695
166776
  const userLoaded = userDetected.format === "none" ? null : loadConfigFile(userDetected.path);
166696
- const projectLoaded = projectDetected.format === "none" ? null : loadConfigFile(projectDetected.path);
166777
+ const projectLoaded = projectDetected.format === "none" ? null : loadConfigFile(projectDetected.path, true);
166697
166778
  const allWarnings = [];
166698
166779
  let mergedRaw = {};
166699
166780
  if (userLoaded) {
@@ -170812,8 +170893,7 @@ var FORCE_MATERIALIZE_PERCENTAGE = 85;
170812
170893
  function getProactiveCompartmentTriggerPercentage(executeThresholdPercentage) {
170813
170894
  return Math.max(0, executeThresholdPercentage - PROACTIVE_TRIGGER_OFFSET_PERCENTAGE);
170814
170895
  }
170815
- function estimateProjectedPostDropPercentage(db, sessionId, usage, autoDropToolAge, protectedTags, clearReasoningAge, clearedReasoningThroughTag, dropToolStructure = true) {
170816
- const activeTags = getTagsBySession(db, sessionId).filter((tag) => tag.status === "active");
170896
+ function estimateProjectedPostDropPercentage(db, sessionId, usage, activeTags, autoDropToolAge, protectedTags, clearReasoningAge, clearedReasoningThroughTag, dropToolStructure = true) {
170817
170897
  const totalActiveBytes = activeTags.reduce((sum, tag) => sum + tag.byteSize + tag.reasoningByteSize, 0);
170818
170898
  if (totalActiveBytes === 0)
170819
170899
  return null;
@@ -170900,15 +170980,24 @@ function getUnsummarizedTailInfo(db, sessionId, triggerBudget) {
170900
170980
  }
170901
170981
  });
170902
170982
  }
170903
- function checkCompartmentTrigger(db, sessionId, sessionMeta, usage, _previousPercentage, executeThresholdPercentage, triggerBudget, autoDropToolAge, protectedTagCount, clearReasoningAge, dropToolStructure = true, commitClusterTrigger) {
170983
+ function checkCompartmentTrigger(db, sessionId, sessionMeta, usage, _previousPercentage, executeThresholdPercentage, triggerBudget, autoDropToolAge, protectedTagCount, clearReasoningAge, dropToolStructure = true, commitClusterTrigger, preloadedActiveTags) {
170904
170984
  if (sessionMeta.compartmentInProgress) {
170985
+ sessionLog(sessionId, `compartment trigger: skipped — historian already in progress (usage=${usage.percentage.toFixed(1)}%)`);
170905
170986
  return { shouldFire: false };
170906
170987
  }
170907
170988
  const tailInfo = getUnsummarizedTailInfo(db, sessionId, triggerBudget);
170908
170989
  if (!tailInfo.hasNewRawHistory) {
170990
+ try {
170991
+ const lastCompartmentEnd = getLastCompartmentEndMessage(db, sessionId);
170992
+ const rawMessageCount = getRawSessionMessageCount(sessionId);
170993
+ const protectedTailStart = getProtectedTailStartOrdinal(sessionId);
170994
+ sessionLog(sessionId, `compartment trigger: skipped — no new raw history (usage=${usage.percentage.toFixed(1)}% nextStartOrdinal=${tailInfo.nextStartOrdinal} lastCompartmentEnd=${lastCompartmentEnd} rawMessageCount=${rawMessageCount} protectedTailStart=${protectedTailStart})`);
170995
+ } catch (error51) {
170996
+ sessionLog(sessionId, `compartment trigger: skipped — no new raw history (usage=${usage.percentage.toFixed(1)}% nextStartOrdinal=${tailInfo.nextStartOrdinal} diagnostic-collection-failed: ${error51 instanceof Error ? error51.message : String(error51)})`);
170997
+ }
170909
170998
  return { shouldFire: false };
170910
170999
  }
170911
- const projectedPostDropPercentage = estimateProjectedPostDropPercentage(db, sessionId, usage, autoDropToolAge, protectedTagCount, clearReasoningAge, sessionMeta.clearedReasoningThroughTag, dropToolStructure);
171000
+ const projectedPostDropPercentage = estimateProjectedPostDropPercentage(db, sessionId, usage, preloadedActiveTags ?? getActiveTagsBySession(db, sessionId), autoDropToolAge, protectedTagCount, clearReasoningAge, sessionMeta.clearedReasoningThroughTag, dropToolStructure);
170912
171001
  const relativePostDropTarget = executeThresholdPercentage * POST_DROP_TARGET_RATIO;
170913
171002
  if (usage.percentage >= FORCE_COMPARTMENT_PERCENTAGE) {
170914
171003
  if (projectedPostDropPercentage !== null && projectedPostDropPercentage <= relativePostDropTarget) {
@@ -170930,6 +171019,7 @@ function checkCompartmentTrigger(db, sessionId, sessionMeta, usage, _previousPer
170930
171019
  }
170931
171020
  const proactiveTriggerPercentage = getProactiveCompartmentTriggerPercentage(executeThresholdPercentage);
170932
171021
  if (usage.percentage < proactiveTriggerPercentage) {
171022
+ sessionLog(sessionId, `compartment trigger: not firing at ${usage.percentage.toFixed(1)}% — below proactive floor (${proactiveTriggerPercentage}%)`);
170933
171023
  return { shouldFire: false };
170934
171024
  }
170935
171025
  if (projectedPostDropPercentage !== null && projectedPostDropPercentage <= relativePostDropTarget) {
@@ -172029,6 +172119,8 @@ function stripSystemInjectedMessages(messages, protectedTailStart, providerID) {
172029
172119
  const msg = messages[i];
172030
172120
  if (msg.parts.length === 0)
172031
172121
  continue;
172122
+ if (msg.info.role === "user")
172123
+ continue;
172032
172124
  if (msg.parts.length === 1 && isSentinel(msg.parts[0]))
172033
172125
  continue;
172034
172126
  let hasContentPart = false;
@@ -174427,12 +174519,6 @@ async function runPostTransformPhase(args) {
174427
174519
  didMutateFromPendingOperations = true;
174428
174520
  }
174429
174521
  logTransformTiming(args.sessionId, "applyHeuristicCleanup", t5, `droppedTools=${cleanup.droppedTools} deduplicatedTools=${cleanup.deduplicatedTools} droppedInjections=${cleanup.droppedInjections} compressedTextTags=${cleanup.compressedTextTags}`);
174430
- if (args.watermark > 0) {
174431
- const t6 = performance.now();
174432
- truncateErroredTools(args.messages, args.watermark, args.messageTagNumbers);
174433
- stripProcessedImages(args.messages, args.watermark, args.messageTagNumbers);
174434
- logTransformTiming(args.sessionId, "watermarkCleanup", t6);
174435
- }
174436
174522
  const t7 = performance.now();
174437
174523
  const clearedReasoning = clearOldReasoning(args.messages, args.reasoningByMessage, args.messageTagNumbers, args.clearReasoningAge);
174438
174524
  stripClearedReasoning(args.messages);
@@ -174476,6 +174562,12 @@ async function runPostTransformPhase(args) {
174476
174562
  deferredMaterializedSuccessfully = true;
174477
174563
  heuristicsRanSuccessfully = true;
174478
174564
  }
174565
+ if (args.watermark > 0) {
174566
+ const tWatermarkCleanup = performance.now();
174567
+ truncateErroredTools(args.messages, args.watermark, args.messageTagNumbers);
174568
+ stripProcessedImages(args.messages, args.watermark, args.messageTagNumbers);
174569
+ logTransformTiming(args.sessionId, "watermarkCleanup", tWatermarkCleanup);
174570
+ }
174479
174571
  if (shouldApplyPendingOps) {
174480
174572
  pendingOpsRanSuccessfully = true;
174481
174573
  }
@@ -177175,7 +177267,7 @@ function resolveConfigValue(cfg, key, modelKey, defaultValue) {
177175
177267
  }
177176
177268
  return defaultValue;
177177
177269
  }
177178
- function buildSidebarSnapshot(db, sessionId, directory, liveSessionState, injectionBudgetTokens) {
177270
+ function buildSidebarSnapshot(db, sessionId, directory, liveSessionState, injectionBudgetTokens, config2) {
177179
177271
  const empty = {
177180
177272
  sessionId,
177181
177273
  usagePercentage: 0,
@@ -177199,7 +177291,8 @@ function buildSidebarSnapshot(db, sessionId, directory, liveSessionState, inject
177199
177291
  memoryTokens: 0,
177200
177292
  conversationTokens: 0,
177201
177293
  toolCallTokens: 0,
177202
- toolDefinitionTokens: 0
177294
+ toolDefinitionTokens: 0,
177295
+ executeThreshold: 65
177203
177296
  };
177204
177297
  try {
177205
177298
  const projectIdentity = resolveProjectIdentity(directory);
@@ -177318,6 +177411,18 @@ ${c.content}
177318
177411
  }
177319
177412
  }
177320
177413
  const contextLimit = activeProviderID && activeModelID ? resolveContextLimit(activeProviderID, activeModelID, { db, sessionID: sessionId }) : 0;
177414
+ let executeThreshold = 65;
177415
+ if (config2) {
177416
+ const modelKey = activeProviderID && activeModelID ? `${activeProviderID}/${activeModelID}` : undefined;
177417
+ const pctCfg = config2.execute_threshold_percentage;
177418
+ const tokensCfg = config2.execute_threshold_tokens;
177419
+ const thresholdDetail = resolveExecuteThresholdDetail(pctCfg ?? 65, modelKey, 65, {
177420
+ tokensConfig: tokensCfg,
177421
+ contextLimit: contextLimit || undefined,
177422
+ sessionId
177423
+ });
177424
+ executeThreshold = thresholdDetail.percentage;
177425
+ }
177321
177426
  const calibration = resolveModelCalibration(activeProviderID, activeModelID);
177322
177427
  const calibrated = calibrateBuckets({
177323
177428
  inputTokens,
@@ -177353,7 +177458,8 @@ ${c.content}
177353
177458
  memoryTokens: calibrated.memoryTokens,
177354
177459
  conversationTokens: calibrated.conversationTokens,
177355
177460
  toolCallTokens: calibrated.toolCallTokens,
177356
- toolDefinitionTokens: calibrated.toolDefinitionTokens
177461
+ toolDefinitionTokens: calibrated.toolDefinitionTokens,
177462
+ executeThreshold
177357
177463
  };
177358
177464
  return applyStickySnapshotCache(sessionId, fresh);
177359
177465
  } catch (err) {
@@ -177362,7 +177468,7 @@ ${c.content}
177362
177468
  }
177363
177469
  }
177364
177470
  function buildStatusDetail(db, sessionId, directory, modelKey, config2, liveSessionState, injectionBudgetTokens) {
177365
- const base = buildSidebarSnapshot(db, sessionId, directory, liveSessionState, injectionBudgetTokens);
177471
+ const base = buildSidebarSnapshot(db, sessionId, directory, liveSessionState, injectionBudgetTokens, config2);
177366
177472
  const detail = {
177367
177473
  ...base,
177368
177474
  tagCounter: 0,
@@ -177475,7 +177581,7 @@ function registerRpcHandlers(rpcServer, args) {
177475
177581
  const db = getDb();
177476
177582
  if (!db || !sessionId)
177477
177583
  return { error: "unavailable" };
177478
- return buildSidebarSnapshot(db, sessionId, dir, liveSessionState, injectionBudgetTokens);
177584
+ return buildSidebarSnapshot(db, sessionId, dir, liveSessionState, injectionBudgetTokens, rawConfig);
177479
177585
  });
177480
177586
  rpcServer.handle("status-detail", async (params) => {
177481
177587
  const sessionId = String(params.sessionId ?? "");
@@ -178064,8 +178170,14 @@ function createCtxNoteTool(deps) {
178064
178170
  if (typeof noteId !== "number") {
178065
178171
  return "Error: 'note_id' is required when action is 'dismiss'.";
178066
178172
  }
178067
- const dismissed = dismissNote(deps.db, noteId);
178068
- return dismissed ? `Note #${noteId} dismissed.` : `Note #${noteId} not found or already dismissed.`;
178173
+ if (!projectIdentity) {
178174
+ return "Error: Could not resolve project identity for note dismiss.";
178175
+ }
178176
+ const dismissed = dismissNote(deps.db, noteId, {
178177
+ projectPath: projectIdentity,
178178
+ sessionId
178179
+ });
178180
+ return dismissed ? `Note #${noteId} dismissed.` : `Error: Note #${noteId} not found in your session/project or already dismissed.`;
178069
178181
  }
178070
178182
  if (action === "update") {
178071
178183
  const noteId = args.note_id;
@@ -178080,9 +178192,15 @@ function createCtxNoteTool(deps) {
178080
178192
  if (!updates.content && !updates.surfaceCondition) {
178081
178193
  return "Error: Provide 'content' and/or 'surface_condition' to update.";
178082
178194
  }
178083
- const updated = updateNote(deps.db, noteId, updates);
178195
+ if (!projectIdentity) {
178196
+ return "Error: Could not resolve project identity for note update.";
178197
+ }
178198
+ const updated = updateNote(deps.db, noteId, updates, {
178199
+ projectPath: projectIdentity,
178200
+ sessionId
178201
+ });
178084
178202
  if (!updated) {
178085
- return `Note #${noteId} not found or has no compatible fields to update.`;
178203
+ return `Error: Note #${noteId} not found in your session/project or has no compatible fields to update.`;
178086
178204
  }
178087
178205
  const parts = [];
178088
178206
  if (updates.content)
@@ -178843,13 +178961,21 @@ var plugin = async (ctx) => {
178843
178961
  await hooks.magicContext?.["experimental.text.complete"]?.(input, output);
178844
178962
  },
178845
178963
  config: async (config2) => {
178846
- const buildHiddenAgentConfig = (agentId, prompt, overrides) => ({
178847
- prompt,
178848
- ...getAgentFallbackModels(agentId) ? { fallback_models: getAgentFallbackModels(agentId) } : {},
178849
- ...overrides ?? {},
178850
- mode: "subagent",
178851
- hidden: true
178852
- });
178964
+ const buildHiddenAgentConfig = (agentId, prompt, allowedTools, overrides) => {
178965
+ const { permission: overridePermission, ...restOverrides } = overrides ?? {};
178966
+ const basePermission = buildAllowOnlyPermission(allowedTools);
178967
+ return {
178968
+ prompt,
178969
+ ...getAgentFallbackModels(agentId) ? { fallback_models: getAgentFallbackModels(agentId) } : {},
178970
+ ...restOverrides,
178971
+ permission: {
178972
+ ...basePermission,
178973
+ ...overridePermission ?? {}
178974
+ },
178975
+ mode: "subagent",
178976
+ hidden: true
178977
+ };
178978
+ };
178853
178979
  const commandConfig = {
178854
178980
  ...config2.command ?? {},
178855
178981
  ...getMagicContextBuiltinCommands(),
@@ -178882,10 +179008,10 @@ var plugin = async (ctx) => {
178882
179008
  })() : undefined;
178883
179009
  config2.agent = {
178884
179010
  ...config2.agent ?? {},
178885
- [DREAMER_AGENT]: buildHiddenAgentConfig(DREAMER_AGENT, DREAMER_SYSTEM_PROMPT, dreamerAgentOverrides),
178886
- [HISTORIAN_AGENT]: buildHiddenAgentConfig(HISTORIAN_AGENT, pluginConfig.dreamer?.user_memories?.enabled ? COMPARTMENT_AGENT_SYSTEM_PROMPT + USER_OBSERVATIONS_APPENDIX : COMPARTMENT_AGENT_SYSTEM_PROMPT, historianAgentOverrides),
178887
- [HISTORIAN_EDITOR_AGENT]: buildHiddenAgentConfig(HISTORIAN_EDITOR_AGENT, HISTORIAN_EDITOR_SYSTEM_PROMPT, historianAgentOverrides),
178888
- [SIDEKICK_AGENT]: buildHiddenAgentConfig(SIDEKICK_AGENT, SIDEKICK_SYSTEM_PROMPT, sidekickAgentOverrides)
179011
+ [DREAMER_AGENT]: buildHiddenAgentConfig(DREAMER_AGENT, DREAMER_SYSTEM_PROMPT, DREAMER_ALLOWED_TOOLS, dreamerAgentOverrides),
179012
+ [HISTORIAN_AGENT]: buildHiddenAgentConfig(HISTORIAN_AGENT, pluginConfig.dreamer?.user_memories?.enabled ? COMPARTMENT_AGENT_SYSTEM_PROMPT + USER_OBSERVATIONS_APPENDIX : COMPARTMENT_AGENT_SYSTEM_PROMPT, HISTORIAN_ALLOWED_TOOLS, historianAgentOverrides),
179013
+ [HISTORIAN_EDITOR_AGENT]: buildHiddenAgentConfig(HISTORIAN_EDITOR_AGENT, HISTORIAN_EDITOR_SYSTEM_PROMPT, HISTORIAN_ALLOWED_TOOLS, historianAgentOverrides),
179014
+ [SIDEKICK_AGENT]: buildHiddenAgentConfig(SIDEKICK_AGENT, SIDEKICK_SYSTEM_PROMPT, SIDEKICK_ALLOWED_TOOLS, sidekickAgentOverrides)
178889
179015
  };
178890
179016
  }
178891
179017
  };
@@ -7,7 +7,7 @@ import { type ContextDatabase as Database } from "../features/magic-context/stor
7
7
  import type { LiveSessionState } from "../hooks/magic-context/live-session-state";
8
8
  import type { MagicContextRpcServer } from "../shared/rpc-server";
9
9
  import type { SidebarSnapshot, StatusDetail } from "../shared/rpc-types";
10
- export declare function buildSidebarSnapshot(db: Database, sessionId: string, directory: string, liveSessionState?: LiveSessionState, injectionBudgetTokens?: number): SidebarSnapshot;
10
+ export declare function buildSidebarSnapshot(db: Database, sessionId: string, directory: string, liveSessionState?: LiveSessionState, injectionBudgetTokens?: number, config?: Record<string, unknown>): SidebarSnapshot;
11
11
  export declare function buildStatusDetail(db: Database, sessionId: string, directory: string, modelKey?: string, config?: Record<string, unknown>, liveSessionState?: LiveSessionState, injectionBudgetTokens?: number): StatusDetail;
12
12
  /**
13
13
  * Register all RPC handlers on the server.
@@ -1 +1 @@
1
- {"version":3,"file":"rpc-handlers.d.ts","sourceRoot":"","sources":["../../src/plugin/rpc-handlers.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AAGzE,OAAO,EAAE,KAAK,eAAe,IAAI,QAAQ,EAAgB,MAAM,mCAAmC,CAAC;AAWnG,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,2CAA2C,CAAC;AASlF,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAClE,OAAO,KAAK,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAmDzE,wBAAgB,oBAAoB,CAChC,EAAE,EAAE,QAAQ,EACZ,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,gBAAgB,CAAC,EAAE,gBAAgB,EACnC,qBAAqB,CAAC,EAAE,MAAM,GAC/B,eAAe,CAgTjB;AAED,wBAAgB,iBAAiB,CAC7B,EAAE,EAAE,QAAQ,EACZ,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,QAAQ,CAAC,EAAE,MAAM,EACjB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChC,gBAAgB,CAAC,EAAE,gBAAgB,EACnC,qBAAqB,CAAC,EAAE,MAAM,GAC/B,YAAY,CAsKd;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAC/B,SAAS,EAAE,qBAAqB,EAChC,IAAI,EAAE;IACF,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,kBAAkB,CAAC;IAC3B,MAAM,EAAE,OAAO,CAAC;IAChB,gBAAgB,EAAE,gBAAgB,CAAC;CACtC,GACF,IAAI,CAuIN"}
1
+ {"version":3,"file":"rpc-handlers.d.ts","sourceRoot":"","sources":["../../src/plugin/rpc-handlers.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AAGzE,OAAO,EAAE,KAAK,eAAe,IAAI,QAAQ,EAAgB,MAAM,mCAAmC,CAAC;AAWnG,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,2CAA2C,CAAC;AASlF,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAClE,OAAO,KAAK,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAmDzE,wBAAgB,oBAAoB,CAChC,EAAE,EAAE,QAAQ,EACZ,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,gBAAgB,CAAC,EAAE,gBAAgB,EACnC,qBAAqB,CAAC,EAAE,MAAM,EAK9B,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACjC,eAAe,CA6UjB;AAED,wBAAgB,iBAAiB,CAC7B,EAAE,EAAE,QAAQ,EACZ,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,QAAQ,CAAC,EAAE,MAAM,EACjB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChC,gBAAgB,CAAC,EAAE,gBAAgB,EACnC,qBAAqB,CAAC,EAAE,MAAM,GAC/B,YAAY,CAuKd;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAC/B,SAAS,EAAE,qBAAqB,EAChC,IAAI,EAAE;IACF,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,kBAAkB,CAAC;IAC3B,MAAM,EAAE,OAAO,CAAC;IAChB,gBAAgB,EAAE,gBAAgB,CAAC;CACtC,GACF,IAAI,CAwIN"}
@@ -1,3 +1,4 @@
1
+ export declare function stripJsonComments(content: string): string;
1
2
  export declare function parseJsonc<T = unknown>(content: string): T;
2
3
  export declare function readJsoncFile<T = unknown>(filePath: string): T | null;
3
4
  export declare function detectConfigFile(basePath: string): {
@@ -1 +1 @@
1
- {"version":3,"file":"jsonc-parser.d.ts","sourceRoot":"","sources":["../../src/shared/jsonc-parser.ts"],"names":[],"mappings":"AA4GA,wBAAgB,UAAU,CAAC,CAAC,GAAG,OAAO,EAAE,OAAO,EAAE,MAAM,GAAG,CAAC,CAG1D;AAED,wBAAgB,aAAa,CAAC,CAAC,GAAG,OAAO,EAAE,QAAQ,EAAE,MAAM,GAAG,CAAC,GAAG,IAAI,CAMrE;AAED,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG;IAChD,MAAM,EAAE,MAAM,GAAG,OAAO,GAAG,MAAM,CAAC;IAClC,IAAI,EAAE,MAAM,CAAC;CAChB,CAaA"}
1
+ {"version":3,"file":"jsonc-parser.d.ts","sourceRoot":"","sources":["../../src/shared/jsonc-parser.ts"],"names":[],"mappings":"AAEA,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CA6DzD;AA6CD,wBAAgB,UAAU,CAAC,CAAC,GAAG,OAAO,EAAE,OAAO,EAAE,MAAM,GAAG,CAAC,CAG1D;AAED,wBAAgB,aAAa,CAAC,CAAC,GAAG,OAAO,EAAE,QAAQ,EAAE,MAAM,GAAG,CAAC,GAAG,IAAI,CAMrE;AAED,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG;IAChD,MAAM,EAAE,MAAM,GAAG,OAAO,GAAG,MAAM,CAAC;IAClC,IAAI,EAAE,MAAM,CAAC;CAChB,CAaA"}
@@ -44,6 +44,16 @@ export interface SidebarSnapshot {
44
44
  * shows this as "Tool Definitions".
45
45
  */
46
46
  toolDefinitionTokens: number;
47
+ /**
48
+ * Effective execute-threshold percentage for this session's active model,
49
+ * after per-model resolution and the tokens→percentage conversion (when
50
+ * `execute_threshold_tokens` applies). Surfaces in the sidebar / status
51
+ * dialog header alongside `usagePercentage` so users can see how close
52
+ * the session is to triggering compaction. Defaults to `65` when no live
53
+ * model is known yet — matches the runtime fallback used by the
54
+ * scheduler and transform paths.
55
+ */
56
+ executeThreshold: number;
47
57
  }
48
58
  export interface StatusDetail extends SidebarSnapshot {
49
59
  tagCounter: number;
@@ -1 +1 @@
1
- {"version":3,"file":"rpc-types.d.ts","sourceRoot":"","sources":["../../src/shared/rpc-types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,eAAe;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,gBAAgB,EAAE,MAAM,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,gBAAgB,EAAE,MAAM,CAAC;IACzB,eAAe,EAAE,MAAM,CAAC;IACxB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,qBAAqB,EAAE,OAAO,CAAC;IAC/B,gBAAgB,EAAE,MAAM,CAAC;IACzB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,kBAAkB,EAAE,MAAM,CAAC;IAC3B;;;;OAIG;IACH,cAAc,EAAE,MAAM,CAAC;IACvB;;;;;;;OAOG;IACH,oBAAoB,EAAE,MAAM,CAAC;CAChC;AAED,MAAM,WAAW,YAAa,SAAQ,eAAe;IACjD,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,gBAAgB,EAAE,MAAM,CAAC;IACzB,eAAe,EAAE,MAAM,CAAC;IACxB,aAAa,EAAE,MAAM,CAAC;IACtB,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,UAAU,EAAE,OAAO,CAAC;IACpB,UAAU,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACxD,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,gBAAgB,EAAE,MAAM,CAAC;IACzB,YAAY,EAAE,OAAO,CAAC;IACtB,gBAAgB,EAAE,MAAM,CAAC;IACzB;;;;OAIG;IACH,oBAAoB,EAAE,YAAY,GAAG,QAAQ,CAAC;IAC9C;;;OAGG;IACH,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,iBAAiB,EAAE,MAAM,CAAC;IAC1B,aAAa,EAAE,MAAM,CAAC;IACtB,uBAAuB,EAAE,MAAM,CAAC;IAChC,cAAc,EAAE,MAAM,CAAC;IACvB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;CACnC;AAED,MAAM,WAAW,sBAAsB;IACnC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB"}
1
+ {"version":3,"file":"rpc-types.d.ts","sourceRoot":"","sources":["../../src/shared/rpc-types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,eAAe;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,gBAAgB,EAAE,MAAM,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,gBAAgB,EAAE,MAAM,CAAC;IACzB,eAAe,EAAE,MAAM,CAAC;IACxB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,qBAAqB,EAAE,OAAO,CAAC;IAC/B,gBAAgB,EAAE,MAAM,CAAC;IACzB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,kBAAkB,EAAE,MAAM,CAAC;IAC3B;;;;OAIG;IACH,cAAc,EAAE,MAAM,CAAC;IACvB;;;;;;;OAOG;IACH,oBAAoB,EAAE,MAAM,CAAC;IAC7B;;;;;;;;OAQG;IACH,gBAAgB,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,YAAa,SAAQ,eAAe;IACjD,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,gBAAgB,EAAE,MAAM,CAAC;IACzB,eAAe,EAAE,MAAM,CAAC;IACxB,aAAa,EAAE,MAAM,CAAC;IACtB,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,UAAU,EAAE,OAAO,CAAC;IACpB,UAAU,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACxD,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,gBAAgB,EAAE,MAAM,CAAC;IACzB,YAAY,EAAE,OAAO,CAAC;IACtB,gBAAgB,EAAE,MAAM,CAAC;IACzB;;;;OAIG;IACH,oBAAoB,EAAE,YAAY,GAAG,QAAQ,CAAC;IAC9C;;;OAGG;IACH,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,iBAAiB,EAAE,MAAM,CAAC;IAC1B,aAAa,EAAE,MAAM,CAAC;IACtB,uBAAuB,EAAE,MAAM,CAAC;IAChC,cAAc,EAAE,MAAM,CAAC;IACvB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;CACnC;AAED,MAAM,WAAW,sBAAsB;IACnC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB"}
@@ -1 +1 @@
1
- {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../../../src/tools/ctx-note/tools.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,cAAc,EAAQ,MAAM,qBAAqB,CAAC;AAWhE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAIpD,MAAM,WAAW,eAAe;IAC5B,EAAE,EAAE,QAAQ,CAAC;IACb,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB;;;;;OAKG;IACH,kBAAkB,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,MAAM,CAAC;CACtD;AA+ND,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAIxF"}
1
+ {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../../../src/tools/ctx-note/tools.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,cAAc,EAAQ,MAAM,qBAAqB,CAAC;AAWhE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAIpD,MAAM,WAAW,eAAe;IAC5B,EAAE,EAAE,QAAQ,CAAC;IACb,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB;;;;;OAKG;IACH,kBAAkB,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,MAAM,CAAC;CACtD;AA2OD,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAIxF"}
@@ -1 +1 @@
1
- {"version":3,"file":"context-db.d.ts","sourceRoot":"","sources":["../../../src/tui/data/context-db.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAA0B,eAAe,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAEpG,YAAY,EAAE,eAAe,EAAE,YAAY,EAAE,CAAC;AAc9C,2DAA2D;AAC3D,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAGrD;AAED,+BAA+B;AAC/B,wBAAgB,QAAQ,IAAI,IAAI,CAI/B;AAuFD,sDAAsD;AACtD,wBAAsB,mBAAmB,CACrC,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,GAClB,OAAO,CAAC,eAAe,CAAC,CA4B1B;AAED,wDAAwD;AACxD,wBAAsB,gBAAgB,CAClC,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,QAAQ,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC,YAAY,CAAC,CA4CvB;AAED,qCAAqC;AACrC,wBAAsB,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAQ5E;AAED,6CAA6C;AAC7C,wBAAsB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAQvE;AAED,MAAM,WAAW,UAAU;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,yDAAyD;AACzD,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC,CAqBhE"}
1
+ {"version":3,"file":"context-db.d.ts","sourceRoot":"","sources":["../../../src/tui/data/context-db.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAA0B,eAAe,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAEpG,YAAY,EAAE,eAAe,EAAE,YAAY,EAAE,CAAC;AAc9C,2DAA2D;AAC3D,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAGrD;AAED,+BAA+B;AAC/B,wBAAgB,QAAQ,IAAI,IAAI,CAI/B;AAwFD,sDAAsD;AACtD,wBAAsB,mBAAmB,CACrC,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,GAClB,OAAO,CAAC,eAAe,CAAC,CA4B1B;AAED,wDAAwD;AACxD,wBAAsB,gBAAgB,CAClC,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,QAAQ,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC,YAAY,CAAC,CA4CvB;AAED,qCAAqC;AACrC,wBAAsB,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAQ5E;AAED,6CAA6C;AAC7C,wBAAsB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAQvE;AAED,MAAM,WAAW,UAAU;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,yDAAyD;AACzD,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC,CAqBhE"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cortexkit/opencode-magic-context",
3
- "version": "0.21.4",
3
+ "version": "0.21.6",
4
4
  "type": "module",
5
5
  "description": "OpenCode plugin for Magic Context — cross-session memory and context management",
6
6
  "main": "dist/index.js",
@@ -1,6 +1,6 @@
1
1
  import { existsSync, readFileSync } from "node:fs";
2
2
 
3
- function stripJsonComments(content: string): string {
3
+ export function stripJsonComments(content: string): string {
4
4
  let result = "";
5
5
  let inString = false;
6
6
  let escaped = false;
@@ -45,6 +45,16 @@ export interface SidebarSnapshot {
45
45
  * shows this as "Tool Definitions".
46
46
  */
47
47
  toolDefinitionTokens: number;
48
+ /**
49
+ * Effective execute-threshold percentage for this session's active model,
50
+ * after per-model resolution and the tokens→percentage conversion (when
51
+ * `execute_threshold_tokens` applies). Surfaces in the sidebar / status
52
+ * dialog header alongside `usagePercentage` so users can see how close
53
+ * the session is to triggering compaction. Defaults to `65` when no live
54
+ * model is known yet — matches the runtime fallback used by the
55
+ * scheduler and transform paths.
56
+ */
57
+ executeThreshold: number;
48
58
  }
49
59
 
50
60
  export interface StatusDetail extends SidebarSnapshot {
@@ -58,6 +58,7 @@ const EMPTY_SNAPSHOT: SidebarSnapshot = {
58
58
  conversationTokens: 0,
59
59
  toolCallTokens: 0,
60
60
  toolDefinitionTokens: 0,
61
+ executeThreshold: 65,
61
62
  };
62
63
 
63
64
  /**
package/src/tui/index.tsx CHANGED
@@ -290,11 +290,16 @@ const StatusDialog = (props: { api: TuiPluginApi; s: StatusDetail }) => {
290
290
  <text fg={t().textMuted}>v{packageJson.version}</text>
291
291
  </box>
292
292
 
293
- {/* Context summary line */}
293
+ {/* Context summary line. Mirrors the sidebar header layout
294
+ ("47.5% / 65% 475K / 1.0M") so users can recognize the
295
+ same shape in the status dialog. The execute threshold tells
296
+ them how close they are to compaction triggering. */}
294
297
  <box flexDirection="row" justifyContent="space-between" width="100%">
295
- <text fg={t().text}>Context</text>
296
298
  <text fg={s().usagePercentage >= 80 ? t().error : s().usagePercentage >= 65 ? t().warning : t().accent}>
297
- <b>{s().usagePercentage.toFixed(1)}%</b> · {fmt(s().inputTokens)} / {contextLimit() > 0 ? fmt(contextLimit()) : "?"} tokens
299
+ <b>{s().usagePercentage.toFixed(1)}%</b> / {s().executeThreshold}%
300
+ </text>
301
+ <text fg={s().usagePercentage >= 80 ? t().error : s().usagePercentage >= 65 ? t().warning : t().accent}>
302
+ {fmt(s().inputTokens)} / {contextLimit() > 0 ? fmt(contextLimit()) : "?"} tokens
298
303
  </text>
299
304
  </box>
300
305