@cortexkit/opencode-magic-context 0.21.5 → 0.21.7

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 (63) 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/agent-disable.d.ts +26 -0
  5. package/dist/config/agent-disable.d.ts.map +1 -0
  6. package/dist/config/index.d.ts.map +1 -1
  7. package/dist/config/schema/agent-overrides.d.ts +12 -12
  8. package/dist/config/schema/magic-context.d.ts +87 -93
  9. package/dist/config/schema/magic-context.d.ts.map +1 -1
  10. package/dist/features/magic-context/compartment-lease.d.ts +14 -0
  11. package/dist/features/magic-context/compartment-lease.d.ts.map +1 -0
  12. package/dist/features/magic-context/compartment-storage.d.ts +5 -1
  13. package/dist/features/magic-context/compartment-storage.d.ts.map +1 -1
  14. package/dist/features/magic-context/compression-depth-storage.d.ts +2 -1
  15. package/dist/features/magic-context/compression-depth-storage.d.ts.map +1 -1
  16. package/dist/features/magic-context/migrations.d.ts.map +1 -1
  17. package/dist/features/magic-context/storage-db.d.ts.map +1 -1
  18. package/dist/features/magic-context/storage-meta-persisted.d.ts.map +1 -1
  19. package/dist/features/magic-context/storage-meta-session.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/auto-search-runner.d.ts.map +1 -1
  23. package/dist/hooks/magic-context/compartment-runner-compressor.d.ts +4 -0
  24. package/dist/hooks/magic-context/compartment-runner-compressor.d.ts.map +1 -1
  25. package/dist/hooks/magic-context/compartment-runner-incremental.d.ts.map +1 -1
  26. package/dist/hooks/magic-context/compartment-runner-partial-recomp.d.ts.map +1 -1
  27. package/dist/hooks/magic-context/compartment-runner-recomp.d.ts.map +1 -1
  28. package/dist/hooks/magic-context/compartment-runner-types.d.ts +2 -0
  29. package/dist/hooks/magic-context/compartment-runner-types.d.ts.map +1 -1
  30. package/dist/hooks/magic-context/compartment-runner.d.ts +5 -0
  31. package/dist/hooks/magic-context/compartment-runner.d.ts.map +1 -1
  32. package/dist/hooks/magic-context/hook.d.ts.map +1 -1
  33. package/dist/hooks/magic-context/transform-compartment-phase.d.ts +2 -2
  34. package/dist/hooks/magic-context/transform-compartment-phase.d.ts.map +1 -1
  35. package/dist/hooks/magic-context/transform-postprocess-phase.d.ts +1 -0
  36. package/dist/hooks/magic-context/transform-postprocess-phase.d.ts.map +1 -1
  37. package/dist/hooks/magic-context/transform.d.ts +2 -0
  38. package/dist/hooks/magic-context/transform.d.ts.map +1 -1
  39. package/dist/index.d.ts.map +1 -1
  40. package/dist/index.js +680 -188
  41. package/dist/plugin/conflict-warning-hook.d.ts +10 -0
  42. package/dist/plugin/conflict-warning-hook.d.ts.map +1 -1
  43. package/dist/plugin/dream-timer.d.ts.map +1 -1
  44. package/dist/plugin/hooks/create-session-hooks.d.ts.map +1 -1
  45. package/dist/plugin/rpc-handlers.d.ts +1 -1
  46. package/dist/plugin/rpc-handlers.d.ts.map +1 -1
  47. package/dist/plugin/tool-registry.d.ts.map +1 -1
  48. package/dist/shared/announcement.d.ts +55 -0
  49. package/dist/shared/announcement.d.ts.map +1 -0
  50. package/dist/shared/format-threshold.d.ts +24 -0
  51. package/dist/shared/format-threshold.d.ts.map +1 -0
  52. package/dist/shared/rpc-types.d.ts +10 -0
  53. package/dist/shared/rpc-types.d.ts.map +1 -1
  54. package/dist/tui/data/context-db.d.ts +14 -0
  55. package/dist/tui/data/context-db.d.ts.map +1 -1
  56. package/package.json +1 -1
  57. package/src/shared/announcement.test.ts +143 -0
  58. package/src/shared/announcement.ts +97 -0
  59. package/src/shared/format-threshold.ts +28 -0
  60. package/src/shared/rpc-types.ts +10 -0
  61. package/src/tui/data/context-db.ts +44 -0
  62. package/src/tui/index.tsx +75 -6
  63. package/src/tui/slots/sidebar-content.tsx +24 -3
package/dist/index.js CHANGED
@@ -14858,7 +14858,6 @@ var init_magic_context = __esm(() => {
14858
14858
  ];
14859
14859
  PiThinkingLevelSchema = exports_external.enum(["off", "minimal", "low", "medium", "high", "xhigh"]).optional();
14860
14860
  DreamerConfigSchema = AgentOverrideConfigSchema.merge(exports_external.object({
14861
- enabled: exports_external.boolean().default(false),
14862
14861
  schedule: exports_external.string().default("02:00-06:00"),
14863
14862
  max_runtime_minutes: exports_external.number().min(10).default(120),
14864
14863
  tasks: exports_external.array(DreamingTaskSchema).default(DEFAULT_DREAMER_TASKS),
@@ -14876,7 +14875,6 @@ var init_magic_context = __esm(() => {
14876
14875
  thinking_level: PiThinkingLevelSchema
14877
14876
  }));
14878
14877
  SidekickConfigSchema = AgentOverrideConfigSchema.extend({
14879
- enabled: exports_external.boolean().default(false),
14880
14878
  timeout_ms: exports_external.number().default(30000),
14881
14879
  system_prompt: exports_external.string().optional(),
14882
14880
  thinking_level: PiThinkingLevelSchema
@@ -156094,6 +156092,106 @@ var require_src2 = __commonJS((exports, module) => {
156094
156092
  };
156095
156093
  });
156096
156094
 
156095
+ // src/features/magic-context/compartment-lease.ts
156096
+ function acquireCompartmentLease(db, sessionId, holderId) {
156097
+ const acquiredAt = Date.now();
156098
+ const expiresAt = acquiredAt + COMPARTMENT_LEASE_TTL_MS;
156099
+ const result = db.prepare(`INSERT INTO compartment_state_lease (session_id, holder_id, acquired_at, expires_at)
156100
+ VALUES (?, ?, ?, ?)
156101
+ ON CONFLICT(session_id) DO UPDATE SET
156102
+ holder_id = excluded.holder_id,
156103
+ acquired_at = excluded.acquired_at,
156104
+ expires_at = excluded.expires_at
156105
+ WHERE compartment_state_lease.holder_id = excluded.holder_id
156106
+ OR compartment_state_lease.expires_at <= ?`).run(sessionId, holderId, acquiredAt, expiresAt, acquiredAt);
156107
+ if (result.changes !== 1) {
156108
+ return null;
156109
+ }
156110
+ return { sessionId, holderId, acquiredAt, expiresAt };
156111
+ }
156112
+ function renewCompartmentLease(db, sessionId, holderId) {
156113
+ const now = Date.now();
156114
+ const expiresAt = now + COMPARTMENT_LEASE_TTL_MS;
156115
+ const result = db.prepare(`UPDATE compartment_state_lease
156116
+ SET expires_at = ?, acquired_at = ?
156117
+ WHERE session_id = ? AND holder_id = ? AND expires_at > ?`).run(expiresAt, now, sessionId, holderId, now);
156118
+ return result.changes === 1;
156119
+ }
156120
+ function releaseCompartmentLease(db, sessionId, holderId) {
156121
+ db.prepare("DELETE FROM compartment_state_lease WHERE session_id = ? AND holder_id = ?").run(sessionId, holderId);
156122
+ }
156123
+ function isCompartmentLeaseHeld(db, sessionId, holderId) {
156124
+ const row = db.prepare("SELECT 1 FROM compartment_state_lease WHERE session_id = ? AND holder_id = ? AND expires_at > ?").get(sessionId, holderId, Date.now());
156125
+ return row != null;
156126
+ }
156127
+ var COMPARTMENT_LEASE_TTL_MS, COMPARTMENT_LEASE_RENEWAL_MS;
156128
+ var init_compartment_lease = __esm(() => {
156129
+ COMPARTMENT_LEASE_TTL_MS = 5 * 60 * 1000;
156130
+ COMPARTMENT_LEASE_RENEWAL_MS = 60 * 1000;
156131
+ });
156132
+
156133
+ // src/features/magic-context/compression-depth-storage.ts
156134
+ function getIncrementDepthStatement(db) {
156135
+ let stmt = incrementDepthStatements.get(db);
156136
+ if (!stmt) {
156137
+ stmt = db.prepare("INSERT INTO compression_depth (session_id, message_ordinal, depth, harness) VALUES (?, ?, 1, ?) ON CONFLICT(session_id, message_ordinal) DO UPDATE SET depth = depth + 1");
156138
+ incrementDepthStatements.set(db, stmt);
156139
+ }
156140
+ return stmt;
156141
+ }
156142
+ function getTotalDepthStatement(db) {
156143
+ let stmt = totalDepthStatements.get(db);
156144
+ if (!stmt) {
156145
+ stmt = db.prepare("SELECT COALESCE(SUM(depth), 0) AS total_depth FROM compression_depth WHERE session_id = ? AND message_ordinal BETWEEN ? AND ?");
156146
+ totalDepthStatements.set(db, stmt);
156147
+ }
156148
+ return stmt;
156149
+ }
156150
+ function getClearDepthStatement(db) {
156151
+ let stmt = clearDepthStatements.get(db);
156152
+ if (!stmt) {
156153
+ stmt = db.prepare("DELETE FROM compression_depth WHERE session_id = ?");
156154
+ clearDepthStatements.set(db, stmt);
156155
+ }
156156
+ return stmt;
156157
+ }
156158
+ function incrementCompressionDepth(db, sessionId, startOrdinal, endOrdinal) {
156159
+ if (endOrdinal < startOrdinal) {
156160
+ return;
156161
+ }
156162
+ db.transaction(() => {
156163
+ const stmt = getIncrementDepthStatement(db);
156164
+ for (let ordinal = startOrdinal;ordinal <= endOrdinal; ordinal += 1) {
156165
+ stmt.run(sessionId, ordinal, getHarness());
156166
+ }
156167
+ })();
156168
+ }
156169
+ function getAverageCompressionDepth(db, sessionId, startOrdinal, endOrdinal) {
156170
+ if (endOrdinal < startOrdinal) {
156171
+ return 0;
156172
+ }
156173
+ const row = getTotalDepthStatement(db).get(sessionId, startOrdinal, endOrdinal);
156174
+ const totalDepth = typeof row?.total_depth === "number" ? row.total_depth : 0;
156175
+ const messageCount = endOrdinal - startOrdinal + 1;
156176
+ return totalDepth / messageCount;
156177
+ }
156178
+ function clearCompressionDepth(db, sessionId) {
156179
+ getClearDepthStatement(db).run(sessionId);
156180
+ }
156181
+ function clearCompressionDepthRange(db, sessionId, startOrdinal, endOrdinal) {
156182
+ if (endOrdinal < startOrdinal) {
156183
+ return;
156184
+ }
156185
+ db.prepare("DELETE FROM compression_depth WHERE session_id = ? AND message_ordinal BETWEEN ? AND ?").run(sessionId, startOrdinal, endOrdinal);
156186
+ }
156187
+ var incrementDepthStatements, totalDepthStatements, maxDepthStatements, clearDepthStatements;
156188
+ var init_compression_depth_storage = __esm(() => {
156189
+ incrementDepthStatements = new WeakMap;
156190
+ totalDepthStatements = new WeakMap;
156191
+ maxDepthStatements = new WeakMap;
156192
+ clearDepthStatements = new WeakMap;
156193
+ });
156194
+
156097
156195
  // src/features/magic-context/compartment-storage.ts
156098
156196
  function getInsertCompartmentStatement(db) {
156099
156197
  let stmt = insertCompartmentStatements.get(db);
@@ -156201,6 +156299,38 @@ function replaceAllCompartmentState(db, sessionId, compartments, facts) {
156201
156299
  db.prepare("UPDATE session_meta SET memory_block_cache = '', memory_block_ids = '' WHERE session_id = ?").run(sessionId);
156202
156300
  })();
156203
156301
  }
156302
+ function replaceAllCompartmentStateAndBumpDepth(db, holderId, sessionId, compartments, facts, depthStartOrdinal, depthEndOrdinal) {
156303
+ const now = Date.now();
156304
+ db.exec("BEGIN IMMEDIATE");
156305
+ let finished = false;
156306
+ try {
156307
+ if (!isCompartmentLeaseHeld(db, sessionId, holderId)) {
156308
+ db.exec("ROLLBACK");
156309
+ finished = true;
156310
+ return false;
156311
+ }
156312
+ db.prepare("DELETE FROM compartments WHERE session_id = ?").run(sessionId);
156313
+ db.prepare("DELETE FROM session_facts WHERE session_id = ?").run(sessionId);
156314
+ insertCompartmentRows(db, sessionId, compartments, now);
156315
+ insertFactRows(db, sessionId, facts, now);
156316
+ db.prepare("UPDATE session_meta SET memory_block_cache = '', memory_block_ids = '' WHERE session_id = ?").run(sessionId);
156317
+ if (depthEndOrdinal >= depthStartOrdinal) {
156318
+ const stmt = getIncrementDepthStatement(db);
156319
+ for (let ordinal = depthStartOrdinal;ordinal <= depthEndOrdinal; ordinal += 1) {
156320
+ stmt.run(sessionId, ordinal, getHarness());
156321
+ }
156322
+ }
156323
+ db.exec("COMMIT");
156324
+ finished = true;
156325
+ return true;
156326
+ } finally {
156327
+ if (!finished) {
156328
+ try {
156329
+ db.exec("ROLLBACK");
156330
+ } catch {}
156331
+ }
156332
+ }
156333
+ }
156204
156334
  function buildCompartmentBlock(compartments, facts, memoryBlock, dateRanges) {
156205
156335
  const lines = [];
156206
156336
  if (memoryBlock) {
@@ -156268,12 +156398,37 @@ function getRecompStaging(db, sessionId) {
156268
156398
  lastEndMessage: lastEnd
156269
156399
  };
156270
156400
  }
156271
- function promoteRecompStaging(db, sessionId) {
156401
+ function promoteRecompStaging(db, sessionId, holderId) {
156272
156402
  const now = Date.now();
156273
- return db.transaction(() => {
156403
+ if (!holderId) {
156404
+ return db.transaction(() => {
156405
+ const staging = getRecompStaging(db, sessionId);
156406
+ if (!staging || staging.compartments.length === 0)
156407
+ return null;
156408
+ db.prepare("DELETE FROM compartments WHERE session_id = ?").run(sessionId);
156409
+ db.prepare("DELETE FROM session_facts WHERE session_id = ?").run(sessionId);
156410
+ insertCompartmentRows(db, sessionId, staging.compartments, now);
156411
+ insertFactRows(db, sessionId, staging.facts, now);
156412
+ db.prepare("DELETE FROM recomp_compartments WHERE session_id = ?").run(sessionId);
156413
+ db.prepare("DELETE FROM recomp_facts WHERE session_id = ?").run(sessionId);
156414
+ db.prepare("UPDATE session_meta SET memory_block_cache = '', memory_block_ids = '' WHERE session_id = ?").run(sessionId);
156415
+ return { compartments: staging.compartments, facts: staging.facts };
156416
+ })();
156417
+ }
156418
+ db.exec("BEGIN IMMEDIATE");
156419
+ let finished = false;
156420
+ try {
156421
+ if (!isCompartmentLeaseHeld(db, sessionId, holderId)) {
156422
+ db.exec("ROLLBACK");
156423
+ finished = true;
156424
+ return null;
156425
+ }
156274
156426
  const staging = getRecompStaging(db, sessionId);
156275
- if (!staging || staging.compartments.length === 0)
156427
+ if (!staging || staging.compartments.length === 0) {
156428
+ db.exec("ROLLBACK");
156429
+ finished = true;
156276
156430
  return null;
156431
+ }
156277
156432
  db.prepare("DELETE FROM compartments WHERE session_id = ?").run(sessionId);
156278
156433
  db.prepare("DELETE FROM session_facts WHERE session_id = ?").run(sessionId);
156279
156434
  insertCompartmentRows(db, sessionId, staging.compartments, now);
@@ -156281,8 +156436,16 @@ function promoteRecompStaging(db, sessionId) {
156281
156436
  db.prepare("DELETE FROM recomp_compartments WHERE session_id = ?").run(sessionId);
156282
156437
  db.prepare("DELETE FROM recomp_facts WHERE session_id = ?").run(sessionId);
156283
156438
  db.prepare("UPDATE session_meta SET memory_block_cache = '', memory_block_ids = '' WHERE session_id = ?").run(sessionId);
156439
+ db.exec("COMMIT");
156440
+ finished = true;
156284
156441
  return { compartments: staging.compartments, facts: staging.facts };
156285
- })();
156442
+ } finally {
156443
+ if (!finished) {
156444
+ try {
156445
+ db.exec("ROLLBACK");
156446
+ } catch {}
156447
+ }
156448
+ }
156286
156449
  }
156287
156450
  function invalidateAllMemoryBlockCaches(db) {
156288
156451
  try {
@@ -156336,6 +156499,8 @@ function escapeXmlContent(s) {
156336
156499
  }
156337
156500
  var insertCompartmentStatements, insertFactStatements;
156338
156501
  var init_compartment_storage = __esm(() => {
156502
+ init_compartment_lease();
156503
+ init_compression_depth_storage();
156339
156504
  insertCompartmentStatements = new WeakMap;
156340
156505
  insertFactStatements = new WeakMap;
156341
156506
  });
@@ -156911,6 +157076,7 @@ var init_conflict_detector = __esm(() => {
156911
157076
  var exports_conflict_warning_hook = {};
156912
157077
  __export(exports_conflict_warning_hook, {
156913
157078
  sendTuiSetupNotification: () => sendTuiSetupNotification,
157079
+ sendStartupAnnouncement: () => sendStartupAnnouncement,
156914
157080
  sendConflictWarning: () => sendConflictWarning,
156915
157081
  cleanupConflictWarnings: () => cleanupConflictWarnings
156916
157082
  });
@@ -157194,7 +157360,46 @@ async function sendTuiSetupNotification(client, directory, serverUrl) {
157194
157360
  } catch {}
157195
157361
  }, 1000);
157196
157362
  }
157197
- var CONFLICT_WARNING_MARKER = "⚠️ Magic Context is disabled due to conflicting configuration:", ENABLED_MARKER = "✨ Magic Context is now enabled", TUI_SETUP_MARKER = "\uD83D\uDCCA Magic Context sidebar configured", cachedDesktopStateByDir;
157363
+ async function sendStartupAnnouncement(client, directory, version2, features, footer, markSeen) {
157364
+ if (!version2 || features.length === 0)
157365
+ return;
157366
+ const { sessionId } = getDesktopState(directory);
157367
+ if (!sessionId) {
157368
+ return;
157369
+ }
157370
+ const bullets = features.map((line) => ` • ${line}`).join(`
157371
+ `);
157372
+ const sections = [`${ANNOUNCEMENT_MARKER} v${version2}:`, "", bullets];
157373
+ if (footer && footer.trim().length > 0) {
157374
+ sections.push("", footer);
157375
+ }
157376
+ const text = sections.join(`
157377
+ `);
157378
+ log(`[magic-context] sending startup announcement for v${version2} to session ${sessionId}`);
157379
+ try {
157380
+ const c = client;
157381
+ const promptInput = {
157382
+ path: { id: sessionId },
157383
+ body: {
157384
+ noReply: true,
157385
+ parts: [{ type: "text", text, ignored: true }]
157386
+ }
157387
+ };
157388
+ if (typeof c.session?.prompt === "function") {
157389
+ await Promise.resolve(c.session.prompt(promptInput));
157390
+ } else if (typeof c.session?.promptAsync === "function") {
157391
+ await c.session.promptAsync(promptInput);
157392
+ } else {
157393
+ log("[magic-context] announcement: session prompt API unavailable");
157394
+ return;
157395
+ }
157396
+ } catch (error51) {
157397
+ log(`[magic-context] announcement: failed to send: ${error51 instanceof Error ? error51.message : String(error51)}`);
157398
+ return;
157399
+ }
157400
+ markSeen(version2);
157401
+ }
157402
+ var CONFLICT_WARNING_MARKER = "⚠️ Magic Context is disabled due to conflicting configuration:", ENABLED_MARKER = "✨ Magic Context is now enabled", TUI_SETUP_MARKER = "\uD83D\uDCCA Magic Context sidebar configured", ANNOUNCEMENT_MARKER = "✨ Magic Context — what's new in", cachedDesktopStateByDir;
157198
157403
  var init_conflict_warning_hook = __esm(() => {
157199
157404
  init_conflict_detector();
157200
157405
  init_logger();
@@ -159519,68 +159724,6 @@ var init_storage_memory_fts = __esm(() => {
159519
159724
  searchStatements = new WeakMap;
159520
159725
  });
159521
159726
 
159522
- // src/features/magic-context/compression-depth-storage.ts
159523
- function getIncrementDepthStatement(db) {
159524
- let stmt = incrementDepthStatements.get(db);
159525
- if (!stmt) {
159526
- stmt = db.prepare("INSERT INTO compression_depth (session_id, message_ordinal, depth, harness) VALUES (?, ?, 1, ?) ON CONFLICT(session_id, message_ordinal) DO UPDATE SET depth = depth + 1");
159527
- incrementDepthStatements.set(db, stmt);
159528
- }
159529
- return stmt;
159530
- }
159531
- function getTotalDepthStatement(db) {
159532
- let stmt = totalDepthStatements.get(db);
159533
- if (!stmt) {
159534
- stmt = db.prepare("SELECT COALESCE(SUM(depth), 0) AS total_depth FROM compression_depth WHERE session_id = ? AND message_ordinal BETWEEN ? AND ?");
159535
- totalDepthStatements.set(db, stmt);
159536
- }
159537
- return stmt;
159538
- }
159539
- function getClearDepthStatement(db) {
159540
- let stmt = clearDepthStatements.get(db);
159541
- if (!stmt) {
159542
- stmt = db.prepare("DELETE FROM compression_depth WHERE session_id = ?");
159543
- clearDepthStatements.set(db, stmt);
159544
- }
159545
- return stmt;
159546
- }
159547
- function incrementCompressionDepth(db, sessionId, startOrdinal, endOrdinal) {
159548
- if (endOrdinal < startOrdinal) {
159549
- return;
159550
- }
159551
- db.transaction(() => {
159552
- const stmt = getIncrementDepthStatement(db);
159553
- for (let ordinal = startOrdinal;ordinal <= endOrdinal; ordinal += 1) {
159554
- stmt.run(sessionId, ordinal, getHarness());
159555
- }
159556
- })();
159557
- }
159558
- function getAverageCompressionDepth(db, sessionId, startOrdinal, endOrdinal) {
159559
- if (endOrdinal < startOrdinal) {
159560
- return 0;
159561
- }
159562
- const row = getTotalDepthStatement(db).get(sessionId, startOrdinal, endOrdinal);
159563
- const totalDepth = typeof row?.total_depth === "number" ? row.total_depth : 0;
159564
- const messageCount = endOrdinal - startOrdinal + 1;
159565
- return totalDepth / messageCount;
159566
- }
159567
- function clearCompressionDepth(db, sessionId) {
159568
- getClearDepthStatement(db).run(sessionId);
159569
- }
159570
- function clearCompressionDepthRange(db, sessionId, startOrdinal, endOrdinal) {
159571
- if (endOrdinal < startOrdinal) {
159572
- return;
159573
- }
159574
- db.prepare("DELETE FROM compression_depth WHERE session_id = ? AND message_ordinal BETWEEN ? AND ?").run(sessionId, startOrdinal, endOrdinal);
159575
- }
159576
- var incrementDepthStatements, totalDepthStatements, maxDepthStatements, clearDepthStatements;
159577
- var init_compression_depth_storage = __esm(() => {
159578
- incrementDepthStatements = new WeakMap;
159579
- totalDepthStatements = new WeakMap;
159580
- maxDepthStatements = new WeakMap;
159581
- clearDepthStatements = new WeakMap;
159582
- });
159583
-
159584
159727
  // src/hooks/magic-context/read-session-db.ts
159585
159728
  import { join as join16 } from "node:path";
159586
159729
  function getOpenCodeDbPath2() {
@@ -160934,6 +161077,22 @@ var init_migrations = __esm(async () => {
160934
161077
  db.exec("ALTER TABLE session_meta ADD COLUMN pending_pi_compaction_marker_state TEXT");
160935
161078
  }
160936
161079
  }
161080
+ },
161081
+ {
161082
+ version: 19,
161083
+ description: "Add compartment state lease table",
161084
+ up: (db) => {
161085
+ db.exec(`
161086
+ CREATE TABLE IF NOT EXISTS compartment_state_lease (
161087
+ session_id TEXT PRIMARY KEY NOT NULL,
161088
+ holder_id TEXT NOT NULL,
161089
+ acquired_at INTEGER NOT NULL,
161090
+ expires_at INTEGER NOT NULL
161091
+ );
161092
+ CREATE INDEX IF NOT EXISTS idx_compartment_state_lease_expires
161093
+ ON compartment_state_lease(expires_at);
161094
+ `);
161095
+ }
160937
161096
  }
160938
161097
  ];
160939
161098
  });
@@ -161274,6 +161433,15 @@ function initializeDatabase(db) {
161274
161433
  );
161275
161434
  CREATE INDEX IF NOT EXISTS idx_compartments_session ON compartments(session_id);
161276
161435
 
161436
+ CREATE TABLE IF NOT EXISTS compartment_state_lease (
161437
+ session_id TEXT PRIMARY KEY NOT NULL,
161438
+ holder_id TEXT NOT NULL,
161439
+ acquired_at INTEGER NOT NULL,
161440
+ expires_at INTEGER NOT NULL
161441
+ );
161442
+ CREATE INDEX IF NOT EXISTS idx_compartment_state_lease_expires
161443
+ ON compartment_state_lease(expires_at);
161444
+
161277
161445
  CREATE TABLE IF NOT EXISTS compression_depth (
161278
161446
  session_id TEXT NOT NULL,
161279
161447
  message_ordinal INTEGER NOT NULL,
@@ -162406,6 +162574,7 @@ function clearSession(db, sessionId) {
162406
162574
  db.prepare("DELETE FROM compartments WHERE session_id = ?").run(sessionId);
162407
162575
  clearCompressionDepth(db, sessionId);
162408
162576
  db.prepare("DELETE FROM session_facts WHERE session_id = ?").run(sessionId);
162577
+ db.prepare("DELETE FROM compartment_state_lease WHERE session_id = ?").run(sessionId);
162409
162578
  db.prepare("DELETE FROM notes WHERE session_id = ? AND type = 'session'").run(sessionId);
162410
162579
  db.prepare("DELETE FROM recomp_compartments WHERE session_id = ?").run(sessionId);
162411
162580
  db.prepare("DELETE FROM recomp_facts WHERE session_id = ?").run(sessionId);
@@ -164543,6 +164712,12 @@ async function executePartialRecompInternal(deps, range) {
164543
164712
  getNotificationParams
164544
164713
  } = deps;
164545
164714
  const notifParams = () => getNotificationParams?.() ?? {};
164715
+ const holderId = deps.compartmentLeaseHolderId;
164716
+ if (!holderId) {
164717
+ return `## Magic Recomp — Failed
164718
+
164719
+ Could not acquire the compartment-state lease for this session.`;
164720
+ }
164546
164721
  updateSessionMeta(db, sessionId, { compartmentInProgress: true });
164547
164722
  try {
164548
164723
  let promoteFinal = function() {
@@ -164579,7 +164754,7 @@ async function executePartialRecompInternal(deps, range) {
164579
164754
  return null;
164580
164755
  }
164581
164756
  saveRecompStagingPass(db, sessionId, passCount + 1, merged, currentFacts);
164582
- const promoted = promoteRecompStaging(db, sessionId);
164757
+ const promoted = promoteRecompStaging(db, sessionId, holderId);
164583
164758
  if (!promoted) {
164584
164759
  log("[magic-context] partial recomp promote returned null");
164585
164760
  return null;
@@ -165349,6 +165524,10 @@ function cavemanLevelForDepth(outputDepth) {
165349
165524
  }
165350
165525
  async function runCompressionPassIfNeeded(deps) {
165351
165526
  const { db, sessionId, historyBudgetTokens } = deps;
165527
+ if (deps.historianRunnable === false) {
165528
+ sessionLog(sessionId, "compressor: skipped because historian.disable=true");
165529
+ return false;
165530
+ }
165352
165531
  const minCompartmentRatio = deps.minCompartmentRatio ?? DEFAULT_COMPRESSOR_MIN_COMPARTMENT_RATIO;
165353
165532
  const maxMergeDepth = deps.maxMergeDepth ?? DEFAULT_COMPRESSOR_MAX_MERGE_DEPTH;
165354
165533
  const compartments = getCompartments(db, sessionId);
@@ -165435,7 +165614,8 @@ ${c.content}
165435
165614
  originalStart: selectedCompartments[0].startMessage,
165436
165615
  originalEnd: selectedCompartments[selectedCompartments.length - 1].endMessage,
165437
165616
  facts,
165438
- logLabel: `depth-5 title-only collapse (${selectedCompartments.length} → ${selectedCompartments.length})`
165617
+ logLabel: `depth-5 title-only collapse (${selectedCompartments.length} → ${selectedCompartments.length})`,
165618
+ holderId: deps.compartmentLeaseHolderId
165439
165619
  });
165440
165620
  }
165441
165621
  try {
@@ -165465,7 +165645,8 @@ ${c.content}
165465
165645
  originalStart: selectedCompartments[0].startMessage,
165466
165646
  originalEnd: selectedCompartments[selectedCompartments.length - 1].endMessage,
165467
165647
  facts,
165468
- logLabel: `depth-${outputDepth} (${selectedCompartments.length} → ${finalCompressed.length})`
165648
+ logLabel: `depth-${outputDepth} (${selectedCompartments.length} → ${finalCompressed.length})`,
165649
+ holderId: deps.compartmentLeaseHolderId
165469
165650
  });
165470
165651
  } catch (error51) {
165471
165652
  sessionLog(sessionId, "compressor: unexpected error:", getErrorMessage(error51));
@@ -165590,7 +165771,8 @@ function finalizeCompression(args) {
165590
165771
  originalStart,
165591
165772
  originalEnd,
165592
165773
  facts,
165593
- logLabel
165774
+ logLabel,
165775
+ holderId
165594
165776
  } = args;
165595
165777
  const compressedStart = compressed[0].startMessage;
165596
165778
  const compressedEnd = compressed[compressed.length - 1].endMessage;
@@ -165641,8 +165823,16 @@ function finalizeCompression(args) {
165641
165823
  content: c.content
165642
165824
  }))
165643
165825
  ];
165644
- replaceAllCompartmentState(db, sessionId, allCompartments, facts.map((f) => ({ category: f.category, content: f.content })));
165645
- incrementCompressionDepth(db, sessionId, originalStart, originalEnd);
165826
+ const factInputs = facts.map((f) => ({ category: f.category, content: f.content }));
165827
+ const published = holderId ? replaceAllCompartmentStateAndBumpDepth(db, holderId, sessionId, allCompartments, factInputs, originalStart, originalEnd) : (() => {
165828
+ replaceAllCompartmentState(db, sessionId, allCompartments, factInputs);
165829
+ incrementCompressionDepth(db, sessionId, originalStart, originalEnd);
165830
+ return true;
165831
+ })();
165832
+ if (!published) {
165833
+ sessionLog(sessionId, "compressor: publish skipped because compartment lease is no longer held");
165834
+ return false;
165835
+ }
165646
165836
  sessionLog(sessionId, `compressor: completed ${logLabel}`);
165647
165837
  return true;
165648
165838
  }
@@ -165897,7 +166087,19 @@ No new compartments or facts were written. Check the historian model/output and
165897
166087
  const deferMarkerApplication = deps.preserveInjectionCacheUntilConsumed === true;
165898
166088
  const lastCompartmentEnd = lastNewEnd;
165899
166089
  const lastNewEndMessageId = newCompartments[newCompartments.length - 1]?.endMessageId;
165900
- db.transaction(() => {
166090
+ const holderId = deps.compartmentLeaseHolderId;
166091
+ if (!holderId) {
166092
+ sessionLog(sessionId, "historian publish skipped: missing compartment lease holder");
166093
+ return;
166094
+ }
166095
+ let published = false;
166096
+ db.exec("BEGIN IMMEDIATE");
166097
+ try {
166098
+ if (!isCompartmentLeaseHeld(db, sessionId, holderId)) {
166099
+ db.exec("ROLLBACK");
166100
+ sessionLog(sessionId, "historian publish skipped: compartment lease no longer held");
166101
+ return;
166102
+ }
165901
166103
  appendCompartments(db, sessionId, newCompartments);
165902
166104
  replaceSessionFacts(db, sessionId, validatedPass.facts ?? []);
165903
166105
  clearHistorianFailureState(db, sessionId);
@@ -165909,7 +166111,15 @@ No new compartments or facts were written. Check the historian model/output and
165909
166111
  publishedAt: Date.now()
165910
166112
  });
165911
166113
  }
165912
- })();
166114
+ db.exec("COMMIT");
166115
+ published = true;
166116
+ } finally {
166117
+ if (!published) {
166118
+ try {
166119
+ db.exec("ROLLBACK");
166120
+ } catch {}
166121
+ }
166122
+ }
165913
166123
  if (deps.preserveInjectionCacheUntilConsumed !== true) {
165914
166124
  clearInjectionCache(sessionId);
165915
166125
  }
@@ -165977,6 +166187,7 @@ var init_compartment_runner_incremental = __esm(async () => {
165977
166187
  init_compartment_storage();
165978
166188
  init_historian_state_file();
165979
166189
  init_historian_state_file();
166190
+ init_compartment_lease();
165980
166191
  init_memory();
165981
166192
  init_project_identity();
165982
166193
  init_storage_memory();
@@ -166013,6 +166224,12 @@ async function executeContextRecompInternal(deps) {
166013
166224
  getNotificationParams
166014
166225
  } = deps;
166015
166226
  const notifParams = () => getNotificationParams?.() ?? {};
166227
+ const holderId = deps.compartmentLeaseHolderId;
166228
+ if (!holderId) {
166229
+ return `## Magic Recomp — Skipped
166230
+
166231
+ Could not acquire the compartment-state lease for this session.`;
166232
+ }
166016
166233
  let currentStateFilePath;
166017
166234
  updateSessionMeta(db, sessionId, { compartmentInProgress: true });
166018
166235
  try {
@@ -166049,7 +166266,7 @@ Found ${existingStaging.compartments.length} staged compartment(s) from ${existi
166049
166266
  if (mergedError)
166050
166267
  return null;
166051
166268
  saveRecompStagingPass(db, sessionId, passCount, candidateCompartments, candidateFacts);
166052
- const promoted2 = promoteRecompStaging(db, sessionId);
166269
+ const promoted2 = promoteRecompStaging(db, sessionId, holderId);
166053
166270
  if (!promoted2)
166054
166271
  return null;
166055
166272
  clearCompressionDepth(db, sessionId);
@@ -166200,10 +166417,12 @@ Recomp completed ${passCount} pass${passCount === 1 ? "" : "es"} but produced an
166200
166417
  Nothing was written.`;
166201
166418
  }
166202
166419
  saveRecompStagingPass(db, sessionId, passCount, candidateCompartments, candidateFacts);
166203
- const promoted = promoteRecompStaging(db, sessionId);
166420
+ const promoted = promoteRecompStaging(db, sessionId, holderId);
166204
166421
  if (!promoted) {
166205
- replaceAllCompartmentState(db, sessionId, candidateCompartments, candidateFacts);
166206
- clearRecompStaging(db, sessionId);
166422
+ sessionLog(sessionId, "recomp publish skipped: compartment lease no longer held");
166423
+ return `## Magic Recomp — Skipped
166424
+
166425
+ Another process acquired the compartment-state lease before recomp could publish. No state was written.`;
166207
166426
  }
166208
166427
  clearCompressionDepth(db, sessionId);
166209
166428
  if (deps.preserveInjectionCacheUntilConsumed !== true) {
@@ -166262,6 +166481,7 @@ var init_compartment_runner_recomp = __esm(async () => {
166262
166481
  init_project_identity();
166263
166482
  init_storage_memory();
166264
166483
  init_shared();
166484
+ init_logger();
166265
166485
  init_compartment_prompt();
166266
166486
  init_compartment_runner_state_xml();
166267
166487
  init_send_session_notification();
@@ -166286,6 +166506,7 @@ __export(exports_compartment_runner, {
166286
166506
  registerActiveCompartmentRun: () => registerActiveCompartmentRun,
166287
166507
  markActiveCompartmentRunPublished: () => markActiveCompartmentRunPublished,
166288
166508
  getActiveCompartmentRun: () => getActiveCompartmentRun,
166509
+ executeContextRecompWithResult: () => executeContextRecompWithResult,
166289
166510
  executeContextRecomp: () => executeContextRecomp
166290
166511
  });
166291
166512
  function getActiveCompartmentRun(sessionId) {
@@ -166319,30 +166540,59 @@ function withPublishedCallback(deps) {
166319
166540
  }
166320
166541
  };
166321
166542
  }
166543
+ function startLeaseRenewal(deps, holderId) {
166544
+ return setInterval(() => {
166545
+ if (!renewCompartmentLease(deps.db, deps.sessionId, holderId)) {
166546
+ sessionLog(deps.sessionId, "compartment lease renewal failed; publish will be skipped if holder is stale");
166547
+ }
166548
+ }, COMPARTMENT_LEASE_RENEWAL_MS);
166549
+ }
166322
166550
  function startCompartmentAgent(deps) {
166323
166551
  const existing = activeRuns.get(deps.sessionId);
166324
166552
  if (existing) {
166325
166553
  return;
166326
166554
  }
166327
- const runnerDeps = withPublishedCallback(deps);
166555
+ const holderId = crypto.randomUUID();
166556
+ const lease2 = acquireCompartmentLease(deps.db, deps.sessionId, holderId);
166557
+ if (!lease2) {
166558
+ sessionLog(deps.sessionId, "compartment agent skipped: compartment lease held by another process");
166559
+ return;
166560
+ }
166561
+ const renewal = startLeaseRenewal(deps, holderId);
166562
+ const runnerDeps = withPublishedCallback({ ...deps, compartmentLeaseHolderId: holderId });
166328
166563
  const promise2 = runCompartmentAgent(runnerDeps).catch((err) => {
166329
166564
  sessionLog(deps.sessionId, "compartment agent: unhandled rejection:", err);
166330
166565
  try {
166331
166566
  updateSessionMeta(deps.db, deps.sessionId, { compartmentInProgress: false });
166332
166567
  } catch {}
166333
166568
  }).finally(() => {
166569
+ clearInterval(renewal);
166570
+ releaseCompartmentLease(deps.db, deps.sessionId, holderId);
166334
166571
  if (activeRuns.get(deps.sessionId)?.promise === promise2) {
166335
166572
  activeRuns.delete(deps.sessionId);
166336
166573
  }
166337
166574
  });
166338
166575
  activeRuns.set(deps.sessionId, { promise: promise2, published: false });
166339
166576
  }
166340
- async function executeContextRecomp(deps, options = {}) {
166577
+ async function executeContextRecompWithResult(deps, options = {}) {
166341
166578
  const { sessionId } = deps;
166342
166579
  if (activeRuns.has(sessionId)) {
166343
- return "## Magic Recomp\n\nHistorian is already running for this session. Wait for it to finish, then try `/ctx-recomp` again.";
166580
+ return {
166581
+ message: "## Magic Recomp\n\nHistorian is already running for this session. Wait for it to finish, then try `/ctx-recomp` again.",
166582
+ published: false
166583
+ };
166584
+ }
166585
+ const holderId = crypto.randomUUID();
166586
+ const lease2 = acquireCompartmentLease(deps.db, sessionId, holderId);
166587
+ if (!lease2) {
166588
+ sessionLog(sessionId, "recomp skipped: compartment lease held by another process");
166589
+ return {
166590
+ message: "## Magic Recomp\n\nAnother process is already mutating compartment state for this session. Wait for it to finish, then try `/ctx-recomp` again.",
166591
+ published: false
166592
+ };
166344
166593
  }
166345
- const runnerDeps = withPublishedCallback(deps);
166594
+ const renewal = startLeaseRenewal(deps, holderId);
166595
+ const runnerDeps = withPublishedCallback({ ...deps, compartmentLeaseHolderId: holderId });
166346
166596
  const promise2 = options.range ? executePartialRecompInternal(runnerDeps, options.range) : executeContextRecompInternal(runnerDeps);
166347
166597
  const wrappedPromise = promise2.then(() => {
166348
166598
  return;
@@ -166351,15 +166601,25 @@ async function executeContextRecomp(deps, options = {}) {
166351
166601
  });
166352
166602
  activeRuns.set(sessionId, { promise: wrappedPromise, published: false });
166353
166603
  try {
166354
- return await promise2;
166604
+ const message = await promise2;
166605
+ return {
166606
+ message,
166607
+ published: activeRuns.get(sessionId)?.published === true
166608
+ };
166355
166609
  } finally {
166610
+ clearInterval(renewal);
166611
+ releaseCompartmentLease(deps.db, sessionId, holderId);
166356
166612
  if (activeRuns.get(sessionId)?.promise === wrappedPromise) {
166357
166613
  activeRuns.delete(sessionId);
166358
166614
  }
166359
166615
  }
166360
166616
  }
166617
+ async function executeContextRecomp(deps, options = {}) {
166618
+ return (await executeContextRecompWithResult(deps, options)).message;
166619
+ }
166361
166620
  var activeRuns;
166362
166621
  var init_compartment_runner = __esm(async () => {
166622
+ init_compartment_lease();
166363
166623
  init_logger();
166364
166624
  await __promiseAll([
166365
166625
  init_storage_meta(),
@@ -166371,13 +166631,65 @@ var init_compartment_runner = __esm(async () => {
166371
166631
  activeRuns = new Map;
166372
166632
  });
166373
166633
 
166634
+ // src/shared/announcement.ts
166635
+ var exports_announcement = {};
166636
+ __export(exports_announcement, {
166637
+ shouldShowAnnouncement: () => shouldShowAnnouncement,
166638
+ readLastAnnouncedVersion: () => readLastAnnouncedVersion,
166639
+ markAnnouncementSeen: () => markAnnouncementSeen,
166640
+ ANNOUNCEMENT_VERSION: () => ANNOUNCEMENT_VERSION,
166641
+ ANNOUNCEMENT_FOOTER: () => ANNOUNCEMENT_FOOTER,
166642
+ ANNOUNCEMENT_FEATURES: () => ANNOUNCEMENT_FEATURES
166643
+ });
166644
+ import * as fs2 from "node:fs";
166645
+ import * as path5 from "node:path";
166646
+ function getStateFilePath() {
166647
+ return path5.join(getMagicContextStorageDir(), STATE_FILENAME);
166648
+ }
166649
+ function readLastAnnouncedVersion() {
166650
+ try {
166651
+ const file2 = getStateFilePath();
166652
+ if (!fs2.existsSync(file2))
166653
+ return "";
166654
+ return fs2.readFileSync(file2, "utf-8").trim();
166655
+ } catch {
166656
+ return "";
166657
+ }
166658
+ }
166659
+ function markAnnouncementSeen(version2) {
166660
+ if (!version2)
166661
+ return;
166662
+ try {
166663
+ const dir = getMagicContextStorageDir();
166664
+ fs2.mkdirSync(dir, { recursive: true });
166665
+ fs2.writeFileSync(getStateFilePath(), version2);
166666
+ } catch {}
166667
+ }
166668
+ function shouldShowAnnouncement() {
166669
+ if (!ANNOUNCEMENT_VERSION || ANNOUNCEMENT_FEATURES.length === 0)
166670
+ return false;
166671
+ return readLastAnnouncedVersion() !== ANNOUNCEMENT_VERSION;
166672
+ }
166673
+ var ANNOUNCEMENT_VERSION = "0.21.7", ANNOUNCEMENT_FEATURES, ANNOUNCEMENT_FOOTER = "Join us on Discord: https://discord.gg/F2uWxjGnU", STATE_FILENAME = "last_announced_version";
166674
+ var init_announcement = __esm(() => {
166675
+ init_data_path();
166676
+ ANNOUNCEMENT_FEATURES = [
166677
+ "Pi parity sweep: 44 audit findings fixed, including a critical SHIP-BLOCKER where /ctx-flush did not drain the pending Pi compaction queue.",
166678
+ "Pi historian recovery fix: empty/no-op historian returns now clear emergency recovery so sessions cannot loop forever at 95%.",
166679
+ "trimPiMessagesToBoundary now sweeps non-contiguous tool-result orphans, fixing provider 400s after compaction in long Pi sessions.",
166680
+ "Hidden subagent tool isolation: historian, dreamer, and sidekick can no longer spawn subagents or run unsafe tools.",
166681
+ "TUI sidebar and /ctx-status header now show execute threshold inline: '47.5% / 65%' on the left, '475K / 1.0M' on the right.",
166682
+ "doctor --issue now caps GitHub issue bodies at ~60KB with a dedicated 'Recent errors' section so reports stay submittable."
166683
+ ];
166684
+ });
166685
+
166374
166686
  // src/shared/tui-config.ts
166375
166687
  var exports_tui_config = {};
166376
166688
  __export(exports_tui_config, {
166377
166689
  ensureTuiPluginEntry: () => ensureTuiPluginEntry
166378
166690
  });
166379
- import { existsSync as existsSync16, mkdirSync as mkdirSync9, readFileSync as readFileSync15, writeFileSync as writeFileSync8 } from "node:fs";
166380
- import { dirname as dirname9, join as join27 } from "node:path";
166691
+ import { existsSync as existsSync17, mkdirSync as mkdirSync10, readFileSync as readFileSync16, writeFileSync as writeFileSync9 } from "node:fs";
166692
+ import { dirname as dirname9, join as join28 } from "node:path";
166381
166693
  function isMagicContextEntry(entry) {
166382
166694
  if (!entry)
166383
166695
  return false;
@@ -166391,11 +166703,11 @@ function isMagicContextEntry(entry) {
166391
166703
  }
166392
166704
  function resolveTuiConfigPath() {
166393
166705
  const configDir = getOpenCodeConfigPaths({ binary: "opencode" }).configDir;
166394
- const jsoncPath = join27(configDir, "tui.jsonc");
166395
- const jsonPath = join27(configDir, "tui.json");
166396
- if (existsSync16(jsoncPath))
166706
+ const jsoncPath = join28(configDir, "tui.jsonc");
166707
+ const jsonPath = join28(configDir, "tui.json");
166708
+ if (existsSync17(jsoncPath))
166397
166709
  return jsoncPath;
166398
- if (existsSync16(jsonPath))
166710
+ if (existsSync17(jsonPath))
166399
166711
  return jsonPath;
166400
166712
  return jsonPath;
166401
166713
  }
@@ -166403,8 +166715,8 @@ function ensureTuiPluginEntry() {
166403
166715
  try {
166404
166716
  const configPath = resolveTuiConfigPath();
166405
166717
  let config2 = {};
166406
- if (existsSync16(configPath)) {
166407
- const raw = readFileSync15(configPath, "utf-8");
166718
+ if (existsSync17(configPath)) {
166719
+ const raw = readFileSync16(configPath, "utf-8");
166408
166720
  config2 = import_comment_json4.parse(raw) ?? {};
166409
166721
  }
166410
166722
  const plugins = Array.isArray(config2.plugin) ? config2.plugin.filter((p) => typeof p === "string") : [];
@@ -166423,8 +166735,8 @@ function ensureTuiPluginEntry() {
166423
166735
  plugins.push(PLUGIN_ENTRY);
166424
166736
  }
166425
166737
  config2.plugin = plugins;
166426
- mkdirSync9(dirname9(configPath), { recursive: true });
166427
- writeFileSync8(configPath, `${import_comment_json4.stringify(config2, null, 2)}
166738
+ mkdirSync10(dirname9(configPath), { recursive: true });
166739
+ writeFileSync9(configPath, `${import_comment_json4.stringify(config2, null, 2)}
166428
166740
  `);
166429
166741
  log(`[magic-context] updated TUI plugin entry in ${configPath}`);
166430
166742
  return true;
@@ -166440,13 +166752,97 @@ var init_tui_config = __esm(() => {
166440
166752
  import_comment_json4 = __toESM(require_src2(), 1);
166441
166753
  PLUGIN_ENTRY = `${PLUGIN_NAME}@latest`;
166442
166754
  });
166755
+ // src/agents/permissions.ts
166756
+ function buildAllowOnlyPermission(allowedTools) {
166757
+ const permission = { "*": "deny" };
166758
+ for (const tool of allowedTools) {
166759
+ permission[tool] = "allow";
166760
+ }
166761
+ return permission;
166762
+ }
166763
+ var HISTORIAN_ALLOWED_TOOLS = ["read", "aft_outline", "aft_zoom"];
166764
+ var DREAMER_ALLOWED_TOOLS = [
166765
+ "read",
166766
+ "grep",
166767
+ "glob",
166768
+ "bash",
166769
+ "aft_outline",
166770
+ "aft_zoom",
166771
+ "ctx_memory",
166772
+ "ctx_search",
166773
+ "ctx_note"
166774
+ ];
166775
+ var SIDEKICK_ALLOWED_TOOLS = [
166776
+ "ctx_search",
166777
+ "ctx_memory",
166778
+ "aft_outline",
166779
+ "aft_zoom"
166780
+ ];
166443
166781
  // src/config/index.ts
166444
166782
  init_jsonc_parser();
166445
- init_magic_context();
166446
166783
  import { existsSync as existsSync3, readFileSync as readFileSync3 } from "node:fs";
166447
166784
  import { homedir as homedir2 } from "node:os";
166448
166785
  import { join } from "node:path";
166449
166786
 
166787
+ // src/config/agent-disable.ts
166788
+ function isDreamerRunnable(config) {
166789
+ return !!config.dreamer && config.dreamer.disable !== true;
166790
+ }
166791
+ function isSidekickRunnable(config) {
166792
+ return !!config.sidekick && config.sidekick.disable !== true;
166793
+ }
166794
+ function isHistorianRunnable(config) {
166795
+ return config.historian?.disable !== true;
166796
+ }
166797
+ function clonePlainObject(value) {
166798
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
166799
+ return;
166800
+ }
166801
+ return { ...value };
166802
+ }
166803
+ function migrateLegacyEnabledForAgent(args) {
166804
+ const agent = clonePlainObject(args.patched[args.agentName]);
166805
+ if (!agent || !("enabled" in agent))
166806
+ return;
166807
+ const enabled = agent.enabled;
166808
+ const disable = agent.disable;
166809
+ delete agent.enabled;
166810
+ if (args.agentName === "historian") {
166811
+ args.warnings.push('Removed invalid "historian.enabled" in-memory (run doctor to persist).');
166812
+ args.patched.historian = agent;
166813
+ return;
166814
+ }
166815
+ if (args.agentName === "dreamer") {
166816
+ if (disable !== true && enabled === false) {
166817
+ agent.disable = true;
166818
+ args.warnings.push('Migrated "dreamer.enabled=false" → "dreamer.disable=true" in-memory (run doctor to persist). This now also disables manual /ctx-dream; for manual-only remove disable and set schedule="".');
166819
+ }
166820
+ args.patched.dreamer = agent;
166821
+ return;
166822
+ }
166823
+ if (disable !== true && enabled === false) {
166824
+ agent.disable = true;
166825
+ args.warnings.push('Migrated "sidekick.enabled=false" → "sidekick.disable=true" in-memory (run doctor to persist).');
166826
+ }
166827
+ args.patched.sidekick = agent;
166828
+ }
166829
+ function migrateLegacyAgentEnabledInMemory(rawConfig, warnings) {
166830
+ const shouldPatch = ["dreamer", "sidekick", "historian"].some((key) => {
166831
+ const agent = rawConfig[key];
166832
+ return typeof agent === "object" && agent !== null && !Array.isArray(agent) && "enabled" in agent;
166833
+ });
166834
+ if (!shouldPatch)
166835
+ return rawConfig;
166836
+ const patched = { ...rawConfig };
166837
+ migrateLegacyEnabledForAgent({ patched, agentName: "dreamer", warnings });
166838
+ migrateLegacyEnabledForAgent({ patched, agentName: "sidekick", warnings });
166839
+ migrateLegacyEnabledForAgent({ patched, agentName: "historian", warnings });
166840
+ return patched;
166841
+ }
166842
+
166843
+ // src/config/index.ts
166844
+ init_magic_context();
166845
+
166450
166846
  // src/config/variable.ts
166451
166847
  init_jsonc_parser();
166452
166848
  import { existsSync as existsSync2, readFileSync as readFileSync2 } from "node:fs";
@@ -166690,7 +167086,8 @@ function migrateLegacyExperimental(rawConfig, warnings) {
166690
167086
  }
166691
167087
  function parsePluginConfig(rawConfig, recoveredTopLevelKeys = []) {
166692
167088
  const preMigrationWarnings = [];
166693
- const migrated = migrateLegacyExperimental(rawConfig, preMigrationWarnings);
167089
+ const migratedExperimental = migrateLegacyExperimental(rawConfig, preMigrationWarnings);
167090
+ const migrated = migrateLegacyAgentEnabledInMemory(migratedExperimental, preMigrationWarnings);
166694
167091
  const parsed = MagicContextConfigSchema.safeParse(migrated);
166695
167092
  const disabledHooks = Array.isArray(rawConfig.disabled_hooks) ? rawConfig.disabled_hooks.filter((value) => typeof value === "string") : undefined;
166696
167093
  const command = typeof rawConfig.command === "object" && rawConfig.command !== null ? rawConfig.command : undefined;
@@ -170093,7 +170490,7 @@ async function startDreamScheduleTimer(args) {
170093
170490
  const db = openDatabase();
170094
170491
  await args.ensureRegistered(args.directory, db);
170095
170492
  const snapshot = getProjectEmbeddingSnapshot(args.projectIdentity);
170096
- const dreamingEnabled = Boolean(args.dreamerConfig?.enabled && args.dreamerConfig.schedule?.trim());
170493
+ const dreamingEnabled = Boolean(args.dreamerConfig && args.dreamerConfig.disable !== true && args.dreamerConfig.schedule?.trim());
170097
170494
  const embeddingSweepEnabled = snapshot?.enabled ?? false;
170098
170495
  const commitIndexingEnabled = snapshot?.gitCommitEnabled ?? false;
170099
170496
  if (!dreamingEnabled && !embeddingSweepEnabled && !commitIndexingEnabled) {
@@ -170149,7 +170546,7 @@ function runTick(origin) {
170149
170546
  })();
170150
170547
  }
170151
170548
  async function sweepProject(reg, origin, db = openDatabase(), gitCommitEnabled = getProjectEmbeddingSnapshot(reg.projectIdentity)?.gitCommitEnabled === true) {
170152
- const dreamingEnabled = Boolean(reg.dreamerConfig?.enabled && reg.dreamerConfig.schedule?.trim());
170549
+ const dreamingEnabled = Boolean(reg.dreamerConfig && reg.dreamerConfig.disable !== true && reg.dreamerConfig.schedule?.trim());
170153
170550
  if (gitCommitEnabled && reg.gitCommitIndexing) {
170154
170551
  await sweepGitCommits({
170155
170552
  directory: reg.directory,
@@ -170792,7 +171189,6 @@ function createTagger() {
170792
171189
  cleanup
170793
171190
  };
170794
171191
  }
170795
-
170796
171192
  // src/hooks/magic-context/hook.ts
170797
171193
  init_magic_context();
170798
171194
  init_project_identity();
@@ -172456,6 +172852,7 @@ init_temporal_awareness();
172456
172852
 
172457
172853
  // src/hooks/magic-context/transform-compartment-phase.ts
172458
172854
  init_magic_context();
172855
+ init_compartment_lease();
172459
172856
  init_compartment_storage();
172460
172857
  init_logger();
172461
172858
  await __promiseAll([
@@ -172487,11 +172884,12 @@ async function runCompartmentPhase(args) {
172487
172884
  let published = false;
172488
172885
  let justAwaitedPublication = false;
172489
172886
  let rebuiltHistoryThisPass = false;
172887
+ const historianRunnable = args.historianRunnable !== false;
172490
172888
  let lastCompartmentEnd = null;
172491
172889
  let rawMessageCount = null;
172492
172890
  let cachedProtectedTailStart = null;
172493
172891
  function hasNewRawHistoryForCompartment() {
172494
- if (!args.fullFeatureMode)
172892
+ if (!args.fullFeatureMode || !historianRunnable)
172495
172893
  return false;
172496
172894
  if (lastCompartmentEnd === null) {
172497
172895
  lastCompartmentEnd = getLastCompartmentEndMessage(args.db, args.resolvedSessionId);
@@ -172529,7 +172927,12 @@ async function runCompartmentPhase(args) {
172529
172927
  }
172530
172928
  return "completed";
172531
172929
  }
172532
- if (args.canRunCompartments && args.sessionMeta.compartmentInProgress && !getActiveCompartmentRun(args.sessionId)) {
172930
+ if (!historianRunnable && args.sessionMeta.compartmentInProgress) {
172931
+ sessionLog(args.sessionId, "transform: historian disabled; clearing stale compartmentInProgress flag");
172932
+ updateSessionMeta(args.db, args.sessionId, { compartmentInProgress: false });
172933
+ compartmentInProgress = false;
172934
+ }
172935
+ if (historianRunnable && args.canRunCompartments && args.sessionMeta.compartmentInProgress && !getActiveCompartmentRun(args.sessionId)) {
172533
172936
  if (!hasEligibleHistoryForCompartment()) {
172534
172937
  sessionLog(args.sessionId, `transform: skipping compartment start, no eligible history before protected tail (beyond ${lastCompartmentEnd ?? -1})`);
172535
172938
  updateSessionMeta(args.db, args.sessionId, { compartmentInProgress: false });
@@ -172565,7 +172968,7 @@ async function runCompartmentPhase(args) {
172565
172968
  }
172566
172969
  }
172567
172970
  let awaitedCompartmentRun = false;
172568
- if (args.canRunCompartments && !args.skipAwaitForThisPass && args.contextUsage.percentage >= BLOCK_UNTIL_DONE_PERCENTAGE) {
172971
+ if (historianRunnable && args.canRunCompartments && !args.skipAwaitForThisPass && args.contextUsage.percentage >= BLOCK_UNTIL_DONE_PERCENTAGE) {
172569
172972
  let activeRun = getActiveCompartmentRun(args.sessionId);
172570
172973
  if (!activeRun && hasEligibleHistoryForCompartment() && args.client) {
172571
172974
  sessionLog(args.sessionId, `transform: 95% reached (${args.contextUsage.percentage.toFixed(1)}%), force-starting compartment agent and blocking`);
@@ -172609,19 +173012,41 @@ async function runCompartmentPhase(args) {
172609
173012
  }
172610
173013
  }
172611
173014
  }
172612
- if (args.safeForBackgroundCompression && !args.suppressBackgroundCompressionThisPass && args.historyBudgetTokens && args.historyBudgetTokens > 0 && args.client && !compartmentInProgress && !awaitedCompartmentRun && !isCompressorOnCooldown(args.sessionId, args.compressorCooldownMs ?? DEFAULT_COMPRESSOR_COOLDOWN_MS)) {
172613
- markCompressorRun(args.sessionId);
172614
- const compressorPromise = runCompressionPassIfNeeded({
172615
- client: args.client,
172616
- db: args.db,
172617
- sessionId: args.sessionId,
172618
- directory: args.compartmentDirectory,
172619
- historyBudgetTokens: args.historyBudgetTokens,
172620
- historianTimeoutMs: args.historianTimeoutMs,
172621
- fallbackModels: args.fallbackModels,
172622
- minCompartmentRatio: args.compressorMinCompartmentRatio,
172623
- maxMergeDepth: args.compressorMaxMergeDepth
172624
- }).then((compressed) => {
173015
+ if (historianRunnable && args.safeForBackgroundCompression && args.historyBudgetTokens && args.historyBudgetTokens > 0 && args.client && !compartmentInProgress && !awaitedCompartmentRun && !isCompressorOnCooldown(args.sessionId, args.compressorCooldownMs ?? DEFAULT_COMPRESSOR_COOLDOWN_MS)) {
173016
+ const client = args.client;
173017
+ const historyBudgetTokens = args.historyBudgetTokens;
173018
+ const holderId = crypto.randomUUID();
173019
+ const compressorPromise = (async () => {
173020
+ const lease2 = acquireCompartmentLease(args.db, args.sessionId, holderId);
173021
+ if (!lease2) {
173022
+ sessionLog(args.sessionId, "independent compressor skipped: compartment lease held by another process");
173023
+ return false;
173024
+ }
173025
+ markCompressorRun(args.sessionId);
173026
+ const renewal = setInterval(() => {
173027
+ if (!renewCompartmentLease(args.db, args.sessionId, holderId)) {
173028
+ sessionLog(args.sessionId, "independent compressor lease renewal failed; publish will be skipped if holder is stale");
173029
+ }
173030
+ }, COMPARTMENT_LEASE_RENEWAL_MS);
173031
+ try {
173032
+ return await runCompressionPassIfNeeded({
173033
+ client,
173034
+ db: args.db,
173035
+ sessionId: args.sessionId,
173036
+ directory: args.compartmentDirectory,
173037
+ historyBudgetTokens,
173038
+ historianTimeoutMs: args.historianTimeoutMs,
173039
+ fallbackModels: args.fallbackModels,
173040
+ minCompartmentRatio: args.compressorMinCompartmentRatio,
173041
+ maxMergeDepth: args.compressorMaxMergeDepth,
173042
+ historianRunnable,
173043
+ compartmentLeaseHolderId: holderId
173044
+ });
173045
+ } finally {
173046
+ clearInterval(renewal);
173047
+ releaseCompartmentLease(args.db, args.sessionId, holderId);
173048
+ }
173049
+ })().then((compressed) => {
172625
173050
  if (compressed) {
172626
173051
  markActiveCompartmentRunPublished(args.sessionId);
172627
173052
  published = true;
@@ -173871,6 +174296,7 @@ ${trimmedBody}…
173871
174296
  }
173872
174297
 
173873
174298
  // src/hooks/magic-context/auto-search-runner.ts
174299
+ init_read_session_formatting();
173874
174300
  var AUTO_SEARCH_TIMEOUT_MS = 3000;
173875
174301
  async function unifiedSearchWithTimeout(db, sessionId, projectPath, prompt, options, timeoutMs) {
173876
174302
  const controller = new AbortController;
@@ -173899,10 +174325,12 @@ function collectUserPromptParts(message) {
173899
174325
  let collected = "";
173900
174326
  for (const part of message.parts) {
173901
174327
  const p = part;
173902
- if (p.type === "text" && typeof p.text === "string") {
173903
- collected += (collected.length > 0 ? `
174328
+ if (p.type !== "text" || typeof p.text !== "string")
174329
+ continue;
174330
+ if (p.ignored === true)
174331
+ continue;
174332
+ collected += (collected.length > 0 ? `
173904
174333
  ` : "") + p.text;
173905
- }
173906
174334
  }
173907
174335
  return collected;
173908
174336
  }
@@ -173945,11 +174373,8 @@ function findLatestMeaningfulUserMessage(messages) {
173945
174373
  continue;
173946
174374
  if (typeof msg.info.id !== "string")
173947
174375
  continue;
173948
- for (const part of msg.parts) {
173949
- const p = part;
173950
- if (p.type === "text" && typeof p.text === "string" && p.text.trim().length > 0) {
173951
- return msg;
173952
- }
174376
+ if (hasMeaningfulUserText(msg.parts)) {
174377
+ return msg;
173953
174378
  }
173954
174379
  }
173955
174380
  return null;
@@ -174429,8 +174854,10 @@ function resetDegradedCacheCount(sessionId) {
174429
174854
  }
174430
174855
  async function runPostTransformPhase(args) {
174431
174856
  let didMutateFromPendingOperations = false;
174432
- const isExplicitFlush = args.pendingMaterializationSessions.has(args.sessionId);
174433
- const deferredMaterializationWasPending = args.deferredMaterializationSessions.has(args.sessionId);
174857
+ const pendingMaterializationAtPassStart = args.pendingMaterializationSessions.has(args.sessionId);
174858
+ const deferredMaterializationAtPassStart = args.deferredMaterializationSessions.has(args.sessionId);
174859
+ const isExplicitFlush = pendingMaterializationAtPassStart;
174860
+ const deferredMaterializationWasPending = deferredMaterializationAtPassStart;
174434
174861
  const alreadyRanThisTurn = args.currentTurnId !== null && args.lastHeuristicsTurnId.get(args.sessionId) === args.currentTurnId;
174435
174862
  const forceMaterialization = args.fullFeatureMode && args.contextUsage.percentage >= args.forceMaterializationPercentage;
174436
174863
  const activeCompartmentRun = args.canRunCompartments ? getActiveCompartmentRun(args.sessionId) : undefined;
@@ -174516,7 +174943,9 @@ async function runPostTransformPhase(args) {
174516
174943
  }
174517
174944
  }
174518
174945
  logTransformTiming(args.sessionId, "clearOldReasoning", t7);
174519
- args.pendingMaterializationSessions.delete(args.sessionId);
174946
+ if (pendingMaterializationAtPassStart) {
174947
+ args.pendingMaterializationSessions.delete(args.sessionId);
174948
+ }
174520
174949
  if (args.currentTurnId) {
174521
174950
  args.lastHeuristicsTurnId.set(args.sessionId, args.currentTurnId);
174522
174951
  }
@@ -174721,7 +175150,7 @@ async function runPostTransformPhase(args) {
174721
175150
  }
174722
175151
  }
174723
175152
  let suppressV12HistoryDrain = false;
174724
- if (historyWasConsumedThisPass && args.deferredHistoryRefreshSessions.has(args.sessionId)) {
175153
+ if (historyWasConsumedThisPass && args.deferredHistoryWasPendingAtPassStart) {
174725
175154
  const pending = getPendingCompactionMarkerState(args.db, args.sessionId);
174726
175155
  if (pending) {
174727
175156
  const outcome = applyDeferredCompactionMarker(args.db, args.sessionId, pending, args.sessionDirectory);
@@ -174738,11 +175167,11 @@ async function runPostTransformPhase(args) {
174738
175167
  }
174739
175168
  }
174740
175169
  }
174741
- const deferredHistoryDrainEligible = historyWasConsumedThisPass && !suppressV12HistoryDrain;
175170
+ const deferredHistoryDrainEligible = historyWasConsumedThisPass && args.deferredHistoryWasPendingAtPassStart && !suppressV12HistoryDrain;
174742
175171
  if (deferredHistoryDrainEligible) {
174743
175172
  args.deferredHistoryRefreshSessions.delete(args.sessionId);
174744
175173
  }
174745
- if (explicitMaterializedSuccessfully || deferredMaterializedSuccessfully) {
175174
+ if ((explicitMaterializedSuccessfully || deferredMaterializedSuccessfully) && deferredMaterializationAtPassStart) {
174746
175175
  args.deferredMaterializationSessions.delete(args.sessionId);
174747
175176
  }
174748
175177
  const workExecutedSuccessfully = explicitMaterializedSuccessfully || deferredMaterializedSuccessfully || heuristicsRanSuccessfully || pendingOpsRanSuccessfully;
@@ -174909,7 +175338,8 @@ function createTransform(deps) {
174909
175338
  } catch {}
174910
175339
  }
174911
175340
  const compartmentDirectory = sessionDirectory;
174912
- const canRunCompartments = fullFeatureMode && deps.client !== undefined && compartmentDirectory.length > 0;
175341
+ const historianRunnable = deps.historianRunnable !== false;
175342
+ const canRunCompartments = fullFeatureMode && historianRunnable && deps.client !== undefined && compartmentDirectory.length > 0;
174913
175343
  const fallbackModelId = deps.getFallbackModelId?.(sessionId);
174914
175344
  const tModelDetect = performance.now();
174915
175345
  if (deps.liveModelBySession) {
@@ -175001,6 +175431,7 @@ function createTransform(deps) {
175001
175431
  }
175002
175432
  sessionLog(sessionId, `[boundary-exec] base=${schedulerDecisionEarly} bypass=${bypassReason} midTurn=${midTurn} effective=${midTurnAdjustedSchedulerDecision} sideEffect=${sideEffect}`);
175003
175433
  const historyRefreshExplicitBeforePrepare = deps.historyRefreshSessions.has(sessionId);
175434
+ const deferredHistoryWasPendingAtPassStart = deferredHistoryRefreshSessions.has(sessionId);
175004
175435
  const earlyActiveRunBlocksMaterialization = (getActiveCompartmentRun(sessionId) !== undefined || sessionMeta.compartmentInProgress) && contextUsageEarly.percentage < FORCE_MATERIALIZE_PERCENTAGE;
175005
175436
  const canConsumeDeferredEarly = canConsumeDeferredOnThisPass({
175006
175437
  schedulerDecision: midTurnAdjustedSchedulerDecision,
@@ -175008,9 +175439,8 @@ function createTransform(deps) {
175008
175439
  justAwaitedPublication: false,
175009
175440
  activeRunBlocksMaterialization: earlyActiveRunBlocksMaterialization
175010
175441
  });
175011
- const consumingDeferredEarly = canConsumeDeferredEarly && deferredHistoryRefreshSessions.has(sessionId);
175442
+ const consumingDeferredEarly = canConsumeDeferredEarly && deferredHistoryWasPendingAtPassStart;
175012
175443
  const isCacheBusting = historyRefreshExplicitBeforePrepare || consumingDeferredEarly;
175013
- const historyBustThisPass = isCacheBusting;
175014
175444
  if (historianFailureState.failureCount === 0) {
175015
175445
  lastEmergencyNotificationCount.delete(sessionId);
175016
175446
  }
@@ -175204,6 +175634,7 @@ Historian previously failed ${historianFailureState.failureCount} time(s), so ma
175204
175634
  const compartmentPhase = await runCompartmentPhase({
175205
175635
  canRunCompartments,
175206
175636
  fullFeatureMode,
175637
+ historianRunnable,
175207
175638
  sessionMeta,
175208
175639
  contextUsage,
175209
175640
  client: deps.client,
@@ -175221,8 +175652,7 @@ Historian previously failed ${historianFailureState.failureCount} time(s), so ma
175221
175652
  projectPath: projectIdentity,
175222
175653
  injectionBudgetTokens: deps.memoryConfig?.injectionBudgetTokens,
175223
175654
  getNotificationParams: rawGetNotifParams ? () => rawGetNotifParams(sessionId) : undefined,
175224
- safeForBackgroundCompression: isCacheBusting || midTurnAdjustedSchedulerDecision === "execute",
175225
- suppressBackgroundCompressionThisPass: historyBustThisPass,
175655
+ safeForBackgroundCompression: historianRunnable && (isCacheBusting || midTurnAdjustedSchedulerDecision === "execute"),
175226
175656
  deferredHistoryRefreshSessions,
175227
175657
  skipAwaitForThisPass: skipCompartmentAwaitForThisPass,
175228
175658
  experimentalUserMemories: deps.experimentalUserMemories,
@@ -175271,6 +175701,7 @@ Historian previously failed ${historianFailureState.failureCount} time(s), so ma
175271
175701
  phaseJustAwaitedPublication: compartmentPhase.justAwaitedPublication,
175272
175702
  compartmentInProgress,
175273
175703
  historyRefreshExplicitBeforePrepare,
175704
+ deferredHistoryWasPendingAtPassStart,
175274
175705
  compartmentInjectionRebuiltFromDb: pendingCompartmentInjection?.rebuiltFromDb === true,
175275
175706
  rebuiltHistoryFromInitialPrepare,
175276
175707
  historyRebuiltThisPass,
@@ -176652,6 +177083,11 @@ function createMagicContextHook(deps) {
176652
177083
  return;
176653
177084
  };
176654
177085
  const ctxReduceEnabled = deps.config.ctx_reduce_enabled !== false;
177086
+ const dreamerRunnable = isDreamerRunnable(deps.config);
177087
+ const dreamerConfig = dreamerRunnable ? deps.config.dreamer : undefined;
177088
+ const historianRunnable = isHistorianRunnable(deps.config);
177089
+ const sidekickRunnable = isSidekickRunnable(deps.config);
177090
+ const sidekickConfig = sidekickRunnable ? deps.config.sidekick : undefined;
176655
177091
  const nudgerWithRecentReduce = ctxReduceEnabled ? createNudger({
176656
177092
  protected_tags: deps.config.protected_tags,
176657
177093
  nudge_interval_tokens: deps.config.nudge_interval_tokens ?? DEFAULT_NUDGE_INTERVAL_TOKENS,
@@ -176701,7 +177137,8 @@ function createMagicContextHook(deps) {
176701
177137
  return model ? `${model.providerID}/${model.modelID}` : undefined;
176702
177138
  },
176703
177139
  projectPath,
176704
- experimentalUserMemories: deps.config.dreamer?.user_memories?.enabled,
177140
+ historianRunnable,
177141
+ experimentalUserMemories: dreamerConfig?.user_memories?.enabled,
176705
177142
  experimentalTemporalAwareness: deps.config.experimental?.temporal_awareness === true,
176706
177143
  historianTwoPass: deps.config.historian?.two_pass === true,
176707
177144
  compressorMinCompartmentRatio: deps.config.compressor?.enabled === false ? undefined : deps.config.compressor?.min_compartment_ratio,
@@ -176740,7 +177177,7 @@ function createMagicContextHook(deps) {
176740
177177
  });
176741
177178
  const runDreamQueueInBackground = () => {
176742
177179
  const dreaming = deps.config.dreamer;
176743
- if (!dreaming?.enabled || !dreaming.schedule?.trim()) {
177180
+ if (!dreaming || dreaming.disable === true || !dreaming.schedule?.trim()) {
176744
177181
  return;
176745
177182
  }
176746
177183
  const now = Date.now();
@@ -176760,16 +177197,16 @@ function createMagicContextHook(deps) {
176760
177197
  tasks: dreaming.tasks,
176761
177198
  taskTimeoutMinutes: dreaming.task_timeout_minutes,
176762
177199
  maxRuntimeMinutes: dreaming.max_runtime_minutes,
176763
- experimentalUserMemories: deps.config.dreamer?.user_memories?.enabled ? {
177200
+ experimentalUserMemories: dreaming.user_memories?.enabled ? {
176764
177201
  enabled: true,
176765
- promotionThreshold: deps.config.dreamer.user_memories.promotion_threshold
177202
+ promotionThreshold: dreaming.user_memories.promotion_threshold
176766
177203
  } : undefined,
176767
- experimentalPinKeyFiles: deps.config.dreamer?.pin_key_files?.enabled ? {
177204
+ experimentalPinKeyFiles: dreaming.pin_key_files?.enabled ? {
176768
177205
  enabled: true,
176769
- token_budget: deps.config.dreamer.pin_key_files.token_budget,
176770
- min_reads: deps.config.dreamer.pin_key_files.min_reads
177206
+ token_budget: dreaming.pin_key_files.token_budget,
177207
+ min_reads: dreaming.pin_key_files.min_reads
176771
177208
  } : undefined,
176772
- fallbackModels: resolveFallbackChain(DREAMER_AGENT, deps.config.dreamer?.fallback_models),
177209
+ fallbackModels: resolveFallbackChain(DREAMER_AGENT, dreaming.fallback_models),
176773
177210
  projectIdentity: projectPath
176774
177211
  }).catch((error51) => {
176775
177212
  log("[dreamer] scheduled queue processing failed:", error51);
@@ -176798,7 +177235,7 @@ function createMagicContextHook(deps) {
176798
177235
  systemPromptRefreshSessions.add(sessionId);
176799
177236
  pendingMaterializationSessions.add(sessionId);
176800
177237
  },
176801
- executeRecomp: async (sessionId, options) => executeContextRecomp({
177238
+ executeRecomp: historianRunnable ? async (sessionId, options) => executeContextRecomp({
176802
177239
  client: deps.client,
176803
177240
  db,
176804
177241
  sessionId,
@@ -176822,34 +177259,34 @@ function createMagicContextHook(deps) {
176822
177259
  onDeferredMarkerPending: (sid) => {
176823
177260
  deferredHistoryRefreshSessions.add(sid);
176824
177261
  }
176825
- }, options),
177262
+ }, options) : undefined,
176826
177263
  sendNotification: async (sessionId, text, params) => {
176827
177264
  await sendIgnoredMessage(deps.client, sessionId, text, {
176828
177265
  ...getLiveNotificationParams(sessionId, liveModelBySession, variantBySession, agentBySession),
176829
177266
  ...params
176830
177267
  });
176831
177268
  },
176832
- sidekick: deps.config.sidekick?.enabled ? {
176833
- config: deps.config.sidekick,
177269
+ sidekick: sidekickConfig ? {
177270
+ config: sidekickConfig,
176834
177271
  projectPath,
176835
177272
  sessionDirectory: deps.directory,
176836
177273
  client: deps.client
176837
177274
  } : undefined,
176838
- dreamer: deps.config.dreamer ? {
176839
- config: deps.config.dreamer,
177275
+ dreamer: dreamerConfig ? {
177276
+ config: dreamerConfig,
176840
177277
  projectPath,
176841
177278
  client: deps.client,
176842
177279
  directory: deps.directory,
176843
- experimentalUserMemories: deps.config.dreamer?.user_memories?.enabled ? {
177280
+ experimentalUserMemories: dreamerConfig.user_memories?.enabled ? {
176844
177281
  enabled: true,
176845
- promotionThreshold: deps.config.dreamer.user_memories.promotion_threshold
177282
+ promotionThreshold: dreamerConfig.user_memories.promotion_threshold
176846
177283
  } : undefined,
176847
- experimentalPinKeyFiles: deps.config.dreamer?.pin_key_files?.enabled ? {
177284
+ experimentalPinKeyFiles: dreamerConfig.pin_key_files?.enabled ? {
176848
177285
  enabled: true,
176849
- token_budget: deps.config.dreamer.pin_key_files.token_budget,
176850
- min_reads: deps.config.dreamer.pin_key_files.min_reads
177286
+ token_budget: dreamerConfig.pin_key_files.token_budget,
177287
+ min_reads: dreamerConfig.pin_key_files.min_reads
176851
177288
  } : undefined,
176852
- fallbackModels: resolveFallbackChain(DREAMER_AGENT, deps.config.dreamer.fallback_models)
177289
+ fallbackModels: resolveFallbackChain(DREAMER_AGENT, dreamerConfig.fallback_models)
176853
177290
  } : undefined
176854
177291
  });
176855
177292
  const systemPromptHash = createSystemPromptHashHandler({
@@ -176857,7 +177294,7 @@ function createMagicContextHook(deps) {
176857
177294
  protectedTags: deps.config.protected_tags,
176858
177295
  ctxReduceEnabled,
176859
177296
  dropToolStructure: deps.config.drop_tool_structure ?? true,
176860
- dreamerEnabled: deps.config.dreamer?.enabled === true,
177297
+ dreamerEnabled: dreamerRunnable,
176861
177298
  injectDocs: deps.config.dreamer?.inject_docs !== false,
176862
177299
  directory: deps.directory,
176863
177300
  historyRefreshSessions,
@@ -177195,6 +177632,7 @@ function calibrateBuckets(input) {
177195
177632
  }
177196
177633
 
177197
177634
  // src/plugin/rpc-handlers.ts
177635
+ init_announcement();
177198
177636
  init_logger();
177199
177637
  init_rpc_notifications();
177200
177638
  function getDb() {
@@ -177241,7 +177679,7 @@ function resolveConfigValue(cfg, key, modelKey, defaultValue) {
177241
177679
  }
177242
177680
  return defaultValue;
177243
177681
  }
177244
- function buildSidebarSnapshot(db, sessionId, directory, liveSessionState, injectionBudgetTokens) {
177682
+ function buildSidebarSnapshot(db, sessionId, directory, liveSessionState, injectionBudgetTokens, config2) {
177245
177683
  const empty = {
177246
177684
  sessionId,
177247
177685
  usagePercentage: 0,
@@ -177265,7 +177703,8 @@ function buildSidebarSnapshot(db, sessionId, directory, liveSessionState, inject
177265
177703
  memoryTokens: 0,
177266
177704
  conversationTokens: 0,
177267
177705
  toolCallTokens: 0,
177268
- toolDefinitionTokens: 0
177706
+ toolDefinitionTokens: 0,
177707
+ executeThreshold: 65
177269
177708
  };
177270
177709
  try {
177271
177710
  const projectIdentity = resolveProjectIdentity(directory);
@@ -177384,6 +177823,18 @@ ${c.content}
177384
177823
  }
177385
177824
  }
177386
177825
  const contextLimit = activeProviderID && activeModelID ? resolveContextLimit(activeProviderID, activeModelID, { db, sessionID: sessionId }) : 0;
177826
+ let executeThreshold = 65;
177827
+ if (config2) {
177828
+ const modelKey = activeProviderID && activeModelID ? `${activeProviderID}/${activeModelID}` : undefined;
177829
+ const pctCfg = config2.execute_threshold_percentage;
177830
+ const tokensCfg = config2.execute_threshold_tokens;
177831
+ const thresholdDetail = resolveExecuteThresholdDetail(pctCfg ?? 65, modelKey, 65, {
177832
+ tokensConfig: tokensCfg,
177833
+ contextLimit: contextLimit || undefined,
177834
+ sessionId
177835
+ });
177836
+ executeThreshold = thresholdDetail.percentage;
177837
+ }
177387
177838
  const calibration = resolveModelCalibration(activeProviderID, activeModelID);
177388
177839
  const calibrated = calibrateBuckets({
177389
177840
  inputTokens,
@@ -177419,7 +177870,8 @@ ${c.content}
177419
177870
  memoryTokens: calibrated.memoryTokens,
177420
177871
  conversationTokens: calibrated.conversationTokens,
177421
177872
  toolCallTokens: calibrated.toolCallTokens,
177422
- toolDefinitionTokens: calibrated.toolDefinitionTokens
177873
+ toolDefinitionTokens: calibrated.toolDefinitionTokens,
177874
+ executeThreshold
177423
177875
  };
177424
177876
  return applyStickySnapshotCache(sessionId, fresh);
177425
177877
  } catch (err) {
@@ -177428,7 +177880,7 @@ ${c.content}
177428
177880
  }
177429
177881
  }
177430
177882
  function buildStatusDetail(db, sessionId, directory, modelKey, config2, liveSessionState, injectionBudgetTokens) {
177431
- const base = buildSidebarSnapshot(db, sessionId, directory, liveSessionState, injectionBudgetTokens);
177883
+ const base = buildSidebarSnapshot(db, sessionId, directory, liveSessionState, injectionBudgetTokens, config2);
177432
177884
  const detail = {
177433
177885
  ...base,
177434
177886
  tagCounter: 0,
@@ -177541,7 +177993,7 @@ function registerRpcHandlers(rpcServer, args) {
177541
177993
  const db = getDb();
177542
177994
  if (!db || !sessionId)
177543
177995
  return { error: "unavailable" };
177544
- return buildSidebarSnapshot(db, sessionId, dir, liveSessionState, injectionBudgetTokens);
177996
+ return buildSidebarSnapshot(db, sessionId, dir, liveSessionState, injectionBudgetTokens, rawConfig);
177545
177997
  });
177546
177998
  rpcServer.handle("status-detail", async (params) => {
177547
177999
  const sessionId = String(params.sessionId ?? "");
@@ -177603,6 +178055,23 @@ function registerRpcHandlers(rpcServer, args) {
177603
178055
  const notifications = drainNotifications(Number.isFinite(lastReceivedId) ? lastReceivedId : 0);
177604
178056
  return { messages: notifications };
177605
178057
  });
178058
+ rpcServer.handle("get-announcement", async () => {
178059
+ if (!shouldShowAnnouncement()) {
178060
+ return { show: false };
178061
+ }
178062
+ return {
178063
+ show: true,
178064
+ version: ANNOUNCEMENT_VERSION,
178065
+ features: [...ANNOUNCEMENT_FEATURES],
178066
+ footer: ANNOUNCEMENT_FOOTER
178067
+ };
178068
+ });
178069
+ rpcServer.handle("mark-announced", async () => {
178070
+ if (ANNOUNCEMENT_VERSION) {
178071
+ markAnnouncementSeen(ANNOUNCEMENT_VERSION);
178072
+ }
178073
+ return { ok: true };
178074
+ });
177606
178075
  }
177607
178076
 
177608
178077
  // src/plugin/tool-registry.ts
@@ -178546,7 +179015,7 @@ function createToolRegistry(args) {
178546
179015
  ...createCtxExpandTools(),
178547
179016
  ...createCtxNoteTools({
178548
179017
  db,
178549
- dreamerEnabled: pluginConfig.dreamer?.enabled === true,
179018
+ dreamerEnabled: isDreamerRunnable(pluginConfig),
178550
179019
  resolveProjectPath: resolveProjectPath2
178551
179020
  }),
178552
179021
  ...createCtxSearchTools({
@@ -178577,28 +179046,28 @@ init_models_dev_cache();
178577
179046
  // src/shared/rpc-server.ts
178578
179047
  init_logger();
178579
179048
  import {
178580
- mkdirSync as mkdirSync8,
179049
+ mkdirSync as mkdirSync9,
178581
179050
  readdirSync,
178582
- readFileSync as readFileSync14,
179051
+ readFileSync as readFileSync15,
178583
179052
  renameSync as renameSync2,
178584
179053
  unlinkSync as unlinkSync3,
178585
- writeFileSync as writeFileSync7
179054
+ writeFileSync as writeFileSync8
178586
179055
  } from "node:fs";
178587
179056
  import { createServer } from "node:http";
178588
179057
  import { dirname as dirname8 } from "node:path";
178589
179058
 
178590
179059
  // src/shared/rpc-utils.ts
178591
179060
  import { createHash as createHash10 } from "node:crypto";
178592
- import { join as join26 } from "node:path";
179061
+ import { join as join27 } from "node:path";
178593
179062
  function projectHash(directory) {
178594
179063
  const normalized = directory.replace(/\/+$/, "");
178595
179064
  return createHash10("sha256").update(normalized).digest("hex").slice(0, 16);
178596
179065
  }
178597
179066
  function rpcPortDir(storageDir, directory) {
178598
- return join26(storageDir, "rpc", projectHash(directory));
179067
+ return join27(storageDir, "rpc", projectHash(directory));
178599
179068
  }
178600
179069
  function rpcPortFilePath(storageDir, directory, pid = process.pid) {
178601
- return join26(rpcPortDir(storageDir, directory), `port-${pid}.json`);
179070
+ return join27(rpcPortDir(storageDir, directory), `port-${pid}.json`);
178602
179071
  }
178603
179072
  function isPidAlive(pid) {
178604
179073
  if (!Number.isInteger(pid) || pid <= 0)
@@ -178673,9 +179142,9 @@ class MagicContextRpcServer {
178673
179142
  try {
178674
179143
  this.warnIfOtherLiveInstance();
178675
179144
  const dir = dirname8(this.portFilePath);
178676
- mkdirSync8(dir, { recursive: true });
179145
+ mkdirSync9(dir, { recursive: true });
178677
179146
  const tmpPath = `${this.portFilePath}.tmp`;
178678
- writeFileSync7(tmpPath, JSON.stringify({
179147
+ writeFileSync8(tmpPath, JSON.stringify({
178679
179148
  port: this.port,
178680
179149
  pid: process.pid,
178681
179150
  started_at: this.startedAt
@@ -178695,7 +179164,7 @@ class MagicContextRpcServer {
178695
179164
  for (const entry of readdirSync(this.portDir)) {
178696
179165
  if (!entry.startsWith("port-") || !entry.endsWith(".json"))
178697
179166
  continue;
178698
- const record2 = parseRpcPortFile(readFileSync14(`${this.portDir}/${entry}`, "utf-8"));
179167
+ const record2 = parseRpcPortFile(readFileSync15(`${this.portDir}/${entry}`, "utf-8"));
178699
179168
  if (!record2 || record2.pid === process.pid || !isPidAlive(record2.pid))
178700
179169
  continue;
178701
179170
  log(`[rpc] another Magic Context RPC server is active for this project (pid ${record2.pid}, port ${record2.port}); starting separate instance on a new port`);
@@ -178820,18 +179289,19 @@ var plugin = async (ctx) => {
178820
179289
  });
178821
179290
  const storageDir = getMagicContextStorageDir();
178822
179291
  if (pluginConfig.enabled) {
179292
+ const dreamerRunnable = isDreamerRunnable(pluginConfig);
178823
179293
  const timerRegistration = {
178824
179294
  directory: ctx.directory,
178825
179295
  projectIdentity: resolveProjectIdentity(ctx.directory),
178826
179296
  client: ctx.client,
178827
- dreamerConfig: pluginConfig.dreamer,
179297
+ dreamerConfig: dreamerRunnable ? pluginConfig.dreamer : undefined,
178828
179298
  embeddingConfig: pluginConfig.embedding,
178829
179299
  memoryEnabled: pluginConfig.memory?.enabled === true,
178830
- experimentalUserMemories: pluginConfig.dreamer?.user_memories?.enabled ? {
179300
+ experimentalUserMemories: dreamerRunnable && pluginConfig.dreamer?.user_memories?.enabled ? {
178831
179301
  enabled: true,
178832
179302
  promotionThreshold: pluginConfig.dreamer.user_memories.promotion_threshold
178833
179303
  } : undefined,
178834
- experimentalPinKeyFiles: pluginConfig.dreamer?.pin_key_files?.enabled ? {
179304
+ experimentalPinKeyFiles: dreamerRunnable && pluginConfig.dreamer?.pin_key_files?.enabled ? {
178835
179305
  enabled: true,
178836
179306
  token_budget: pluginConfig.dreamer.pin_key_files.token_budget,
178837
179307
  min_reads: pluginConfig.dreamer.pin_key_files.min_reads
@@ -178875,6 +179345,22 @@ var plugin = async (ctx) => {
178875
179345
  }
178876
179346
  } catch {}
178877
179347
  }
179348
+ if (pluginConfig.enabled && !conflictResult?.hasConflict) {
179349
+ try {
179350
+ const {
179351
+ shouldShowAnnouncement: shouldShowAnnouncement2,
179352
+ ANNOUNCEMENT_VERSION: ANNOUNCEMENT_VERSION2,
179353
+ ANNOUNCEMENT_FEATURES: ANNOUNCEMENT_FEATURES2,
179354
+ ANNOUNCEMENT_FOOTER: ANNOUNCEMENT_FOOTER2,
179355
+ markAnnouncementSeen: markAnnouncementSeen2
179356
+ } = await Promise.resolve().then(() => (init_announcement(), exports_announcement));
179357
+ if (shouldShowAnnouncement2()) {
179358
+ setTimeout(() => {
179359
+ Promise.resolve().then(() => (init_conflict_warning_hook(), exports_conflict_warning_hook)).then(({ sendStartupAnnouncement: sendStartupAnnouncement2 }) => sendStartupAnnouncement2(ctx.client, ctx.directory, ANNOUNCEMENT_VERSION2, ANNOUNCEMENT_FEATURES2, ANNOUNCEMENT_FOOTER2, markAnnouncementSeen2)).catch(() => {});
179360
+ }, 8000);
179361
+ }
179362
+ } catch {}
179363
+ }
178878
179364
  let lastChatContext = null;
178879
179365
  return {
178880
179366
  tool: tools5,
@@ -178921,13 +179407,21 @@ var plugin = async (ctx) => {
178921
179407
  await hooks.magicContext?.["experimental.text.complete"]?.(input, output);
178922
179408
  },
178923
179409
  config: async (config2) => {
178924
- const buildHiddenAgentConfig = (agentId, prompt, overrides) => ({
178925
- prompt,
178926
- ...getAgentFallbackModels(agentId) ? { fallback_models: getAgentFallbackModels(agentId) } : {},
178927
- ...overrides ?? {},
178928
- mode: "subagent",
178929
- hidden: true
178930
- });
179410
+ const buildHiddenAgentConfig = (agentId, prompt, allowedTools, overrides) => {
179411
+ const { permission: overridePermission, ...restOverrides } = overrides ?? {};
179412
+ const basePermission = buildAllowOnlyPermission(allowedTools);
179413
+ return {
179414
+ prompt,
179415
+ ...getAgentFallbackModels(agentId) ? { fallback_models: getAgentFallbackModels(agentId) } : {},
179416
+ ...restOverrides,
179417
+ permission: {
179418
+ ...basePermission,
179419
+ ...overridePermission ?? {}
179420
+ },
179421
+ mode: "subagent",
179422
+ hidden: true
179423
+ };
179424
+ };
178931
179425
  const commandConfig = {
178932
179426
  ...config2.command ?? {},
178933
179427
  ...getMagicContextBuiltinCommands(),
@@ -178936,7 +179430,6 @@ var plugin = async (ctx) => {
178936
179430
  config2.command = commandConfig;
178937
179431
  const dreamerAgentOverrides = pluginConfig.dreamer ? (() => {
178938
179432
  const {
178939
- enabled: _enabled,
178940
179433
  schedule: _schedule,
178941
179434
  max_runtime_minutes: _max,
178942
179435
  tasks: _tasks,
@@ -178947,7 +179440,6 @@ var plugin = async (ctx) => {
178947
179440
  })() : undefined;
178948
179441
  const sidekickAgentOverrides = pluginConfig.sidekick ? (() => {
178949
179442
  const {
178950
- enabled: _enabled,
178951
179443
  timeout_ms: _timeoutMs,
178952
179444
  system_prompt: _systemPrompt,
178953
179445
  ...agentOverrides
@@ -178960,10 +179452,10 @@ var plugin = async (ctx) => {
178960
179452
  })() : undefined;
178961
179453
  config2.agent = {
178962
179454
  ...config2.agent ?? {},
178963
- [DREAMER_AGENT]: buildHiddenAgentConfig(DREAMER_AGENT, DREAMER_SYSTEM_PROMPT, dreamerAgentOverrides),
178964
- [HISTORIAN_AGENT]: buildHiddenAgentConfig(HISTORIAN_AGENT, pluginConfig.dreamer?.user_memories?.enabled ? COMPARTMENT_AGENT_SYSTEM_PROMPT + USER_OBSERVATIONS_APPENDIX : COMPARTMENT_AGENT_SYSTEM_PROMPT, historianAgentOverrides),
178965
- [HISTORIAN_EDITOR_AGENT]: buildHiddenAgentConfig(HISTORIAN_EDITOR_AGENT, HISTORIAN_EDITOR_SYSTEM_PROMPT, historianAgentOverrides),
178966
- [SIDEKICK_AGENT]: buildHiddenAgentConfig(SIDEKICK_AGENT, SIDEKICK_SYSTEM_PROMPT, sidekickAgentOverrides)
179455
+ [DREAMER_AGENT]: buildHiddenAgentConfig(DREAMER_AGENT, DREAMER_SYSTEM_PROMPT, DREAMER_ALLOWED_TOOLS, dreamerAgentOverrides),
179456
+ [HISTORIAN_AGENT]: buildHiddenAgentConfig(HISTORIAN_AGENT, isDreamerRunnable(pluginConfig) && pluginConfig.dreamer?.user_memories?.enabled ? COMPARTMENT_AGENT_SYSTEM_PROMPT + USER_OBSERVATIONS_APPENDIX : COMPARTMENT_AGENT_SYSTEM_PROMPT, HISTORIAN_ALLOWED_TOOLS, historianAgentOverrides),
179457
+ [HISTORIAN_EDITOR_AGENT]: buildHiddenAgentConfig(HISTORIAN_EDITOR_AGENT, HISTORIAN_EDITOR_SYSTEM_PROMPT, HISTORIAN_ALLOWED_TOOLS, historianAgentOverrides),
179458
+ [SIDEKICK_AGENT]: buildHiddenAgentConfig(SIDEKICK_AGENT, SIDEKICK_SYSTEM_PROMPT, SIDEKICK_ALLOWED_TOOLS, sidekickAgentOverrides)
178967
179459
  };
178968
179460
  }
178969
179461
  };