@cortexkit/magic-context 0.31.2 → 0.31.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +621 -309
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -8476,7 +8476,7 @@ var init_data_path = () => {};
8476
8476
  // src/lib/paths.ts
8477
8477
  import { existsSync as existsSync4, readdirSync, statSync as statSync4 } from "node:fs";
8478
8478
  import { homedir as homedir4 } from "node:os";
8479
- import { join as join5 } from "node:path";
8479
+ import { dirname as dirname3, join as join5 } from "node:path";
8480
8480
  function getOpenCodeConfigDir() {
8481
8481
  const envDir = process.env.OPENCODE_CONFIG_DIR?.trim();
8482
8482
  if (envDir)
@@ -8540,11 +8540,24 @@ function detectConfigPaths() {
8540
8540
  tuiConfigFormat
8541
8541
  };
8542
8542
  }
8543
- function getPiAgentConfigDir() {
8543
+ function envFirstHomeDir() {
8544
+ const home = process.env.HOME?.trim();
8545
+ return home || homedir4();
8546
+ }
8547
+ function getPiAgentDir() {
8544
8548
  const envDir = process.env.PI_CODING_AGENT_DIR?.trim();
8545
8549
  if (envDir)
8546
8550
  return envDir;
8547
- return join5(homedir4(), ".pi", "agent");
8551
+ return join5(envFirstHomeDir(), ".pi", "agent");
8552
+ }
8553
+ function getPiAgentConfigDir() {
8554
+ return getPiAgentDir();
8555
+ }
8556
+ function getPiSessionsRoot() {
8557
+ return join5(getPiAgentDir(), "sessions");
8558
+ }
8559
+ function getPiCacheRoot() {
8560
+ return join5(dirname3(getPiAgentDir()), "cache");
8548
8561
  }
8549
8562
  function getPiUserConfigPath() {
8550
8563
  return resolveCortexKitUserConfigPath();
@@ -8622,7 +8635,7 @@ var init_opencode_plugin_cache = __esm(() => {
8622
8635
 
8623
8636
  // src/adapters/opencode.ts
8624
8637
  import { existsSync as existsSync5, readFileSync as readFileSync2 } from "node:fs";
8625
- import { dirname as dirname3 } from "node:path";
8638
+ import { dirname as dirname4 } from "node:path";
8626
8639
 
8627
8640
  class OpenCodeAdapter {
8628
8641
  kind = "opencode";
@@ -8843,7 +8856,7 @@ function matchesPluginEntry(entry, pkgName) {
8843
8856
  return head === pkgName;
8844
8857
  }
8845
8858
  function ensureDir(filePath) {
8846
- const dir = dirname3(filePath);
8859
+ const dir = dirname4(filePath);
8847
8860
  if (!existsSync5(dir)) {
8848
8861
  const { mkdirSync: mkdirSync3 } = __require("node:fs");
8849
8862
  mkdirSync3(dir, { recursive: true });
@@ -8948,7 +8961,7 @@ var init_pi_helpers = __esm(() => {
8948
8961
  // src/adapters/pi.ts
8949
8962
  import { execFileSync as execFileSync2 } from "node:child_process";
8950
8963
  import { existsSync as existsSync7, readFileSync as readFileSync3 } from "node:fs";
8951
- import { dirname as dirname4 } from "node:path";
8964
+ import { dirname as dirname5 } from "node:path";
8952
8965
 
8953
8966
  class PiAdapter {
8954
8967
  kind = "pi";
@@ -9105,7 +9118,7 @@ function matchesPiPackage(entry) {
9105
9118
  return false;
9106
9119
  }
9107
9120
  function ensureDir2(filePath) {
9108
- const dir = dirname4(filePath);
9121
+ const dir = dirname5(filePath);
9109
9122
  if (!existsSync7(dir)) {
9110
9123
  const { mkdirSync: mkdirSync3 } = __require("node:fs");
9111
9124
  mkdirSync3(dir, { recursive: true });
@@ -11974,7 +11987,7 @@ var init_opencode_helpers = () => {};
11974
11987
 
11975
11988
  // src/commands/setup-opencode.ts
11976
11989
  import { existsSync as existsSync10, mkdirSync as mkdirSync3, readFileSync as readFileSync6 } from "node:fs";
11977
- import { basename as basename2, dirname as dirname5 } from "node:path";
11990
+ import { basename as basename2, dirname as dirname6 } from "node:path";
11978
11991
  function ensureDir3(dir) {
11979
11992
  if (!existsSync10(dir)) {
11980
11993
  mkdirSync3(dir, { recursive: true });
@@ -11990,7 +12003,7 @@ function readJsonc(path2) {
11990
12003
  }
11991
12004
  }
11992
12005
  function addPluginToOpenCodeConfig(configPath, format) {
11993
- ensureDir3(dirname5(configPath));
12006
+ ensureDir3(dirname6(configPath));
11994
12007
  if (format === "none") {
11995
12008
  const config = {
11996
12009
  plugin: [OPENCODE_PLUGIN_ENTRY_WITH_VERSION],
@@ -12020,7 +12033,7 @@ function addPluginToOpenCodeConfig(configPath, format) {
12020
12033
  `);
12021
12034
  }
12022
12035
  function addPluginToTuiConfig(configPath, format) {
12023
- ensureDir3(dirname5(configPath));
12036
+ ensureDir3(dirname6(configPath));
12024
12037
  if (format === "none") {
12025
12038
  writeFileAtomic(configPath, `${import_comment_json4.stringify({ plugin: [OPENCODE_PLUGIN_ENTRY_WITH_VERSION] }, null, 2)}
12026
12039
  `);
@@ -12386,7 +12399,7 @@ var PI_MAGIC_CONTEXT_PACKAGE_NAME = "@cortexkit/pi-magic-context";
12386
12399
 
12387
12400
  // src/commands/setup-pi.ts
12388
12401
  import { existsSync as existsSync11, mkdirSync as mkdirSync4, readFileSync as readFileSync7 } from "node:fs";
12389
- import { dirname as dirname6 } from "node:path";
12402
+ import { dirname as dirname7 } from "node:path";
12390
12403
  function ensureDir4(path2) {
12391
12404
  if (!existsSync11(path2))
12392
12405
  mkdirSync4(path2, { recursive: true });
@@ -12429,7 +12442,7 @@ function comparePiVersion(a3, b2) {
12429
12442
  return 0;
12430
12443
  }
12431
12444
  function writePiSettingsPackage(settingsPath, packageSource = PI_PACKAGE_SOURCE) {
12432
- ensureDir4(dirname6(settingsPath));
12445
+ ensureDir4(dirname7(settingsPath));
12433
12446
  const settings2 = existsSync11(settingsPath) ? readJsonc2(settingsPath) ?? {} : {};
12434
12447
  const packages = Array.isArray(settings2.packages) ? settings2.packages : [];
12435
12448
  const hasPackage = hasPiMagicContextPackage(packages);
@@ -12441,7 +12454,7 @@ function writePiSettingsPackage(settingsPath, packageSource = PI_PACKAGE_SOURCE)
12441
12454
  return !hasPackage;
12442
12455
  }
12443
12456
  function writeMagicContextConfig2(configPath, options) {
12444
- ensureDir4(dirname6(configPath));
12457
+ ensureDir4(dirname7(configPath));
12445
12458
  const config = existsSync11(configPath) ? readJsonc2(configPath) ?? {} : {};
12446
12459
  if (!config.$schema) {
12447
12460
  config.$schema = "https://raw.githubusercontent.com/cortexkit/magic-context/master/assets/magic-context.schema.json";
@@ -12775,7 +12788,7 @@ __export(exports_migrate, {
12775
12788
  formatPiFilenameTimestamp: () => formatPiFilenameTimestamp
12776
12789
  });
12777
12790
  import { randomBytes } from "node:crypto";
12778
- import { existsSync as existsSync12, mkdirSync as mkdirSync5, unlinkSync as unlinkSync2, writeFileSync as writeFileSync4 } from "node:fs";
12791
+ import { unlinkSync as unlinkSync2 } from "node:fs";
12779
12792
  import { homedir as homedir7 } from "node:os";
12780
12793
  import { join as join11 } from "node:path";
12781
12794
  function defaultOpenCodeDbPath() {
@@ -12785,10 +12798,10 @@ function defaultCortexkitDbPath() {
12785
12798
  return join11(getMagicContextStorageDir(), "context.db");
12786
12799
  }
12787
12800
  function defaultPiSessionsRoot() {
12788
- return join11(homedir7(), ".pi", "agent", "sessions");
12801
+ return getPiSessionsRoot();
12789
12802
  }
12790
12803
  function defaultFs() {
12791
- return { existsSync: existsSync12, mkdirSync: mkdirSync5, writeFileSync: writeFileSync4, unlinkSync: unlinkSync2 };
12804
+ return { writeFileAtomic, unlinkSync: unlinkSync2 };
12792
12805
  }
12793
12806
  function stmt(db, sql) {
12794
12807
  return db.prepare(sql);
@@ -13259,9 +13272,7 @@ function migrateOpenCodeSessionToPi(opts) {
13259
13272
  `)}
13260
13273
  `;
13261
13274
  if (!opts.dryRun) {
13262
- if (!fs.existsSync(outputDir))
13263
- fs.mkdirSync(outputDir, { recursive: true });
13264
- fs.writeFileSync(outputPath, jsonl);
13275
+ fs.writeFileAtomic(outputPath, jsonl);
13265
13276
  try {
13266
13277
  commitMagicContextState?.();
13267
13278
  } catch (commitError) {
@@ -13386,6 +13397,8 @@ async function runMigrateCli(args) {
13386
13397
  var DEFAULT_PROVIDER = "openai-codex", DEFAULT_MODEL = "gpt-5.5", MIGRATION_COMPACTION_SUMMARY = "Magic Context compacted prior conversation. See <session-history> block for the structured summary.";
13387
13398
  var init_migrate = __esm(async () => {
13388
13399
  init_data_path();
13400
+ init_atomic_write();
13401
+ init_paths();
13389
13402
  await init_sqlite();
13390
13403
  });
13391
13404
 
@@ -13452,7 +13465,7 @@ var init_logger = __esm(() => {
13452
13465
  // ../plugin/src/features/magic-context/memory/project-identity.ts
13453
13466
  import { execFileSync as execFileSync4 } from "node:child_process";
13454
13467
  import { createHash } from "node:crypto";
13455
- import { existsSync as existsSync13, realpathSync, statSync as statSync5 } from "node:fs";
13468
+ import { existsSync as existsSync12, realpathSync, statSync as statSync5 } from "node:fs";
13456
13469
  import path3 from "node:path";
13457
13470
  function asError(error) {
13458
13471
  return error instanceof Error ? error : undefined;
@@ -13691,7 +13704,7 @@ function hasGitDir(canonical) {
13691
13704
  function hasGitDirInAncestorChain(startDirectory) {
13692
13705
  let current = startDirectory;
13693
13706
  while (true) {
13694
- if (existsSync13(path3.join(current, ".git"))) {
13707
+ if (existsSync12(path3.join(current, ".git"))) {
13695
13708
  return true;
13696
13709
  }
13697
13710
  const parent = path3.dirname(current);
@@ -13855,7 +13868,7 @@ __export(exports_migrate_session, {
13855
13868
  planMigrateSession: () => planMigrateSession,
13856
13869
  applyMigrateSession: () => applyMigrateSession
13857
13870
  });
13858
- import { copyFileSync, existsSync as existsSync14, realpathSync as realpathSync2 } from "node:fs";
13871
+ import { copyFileSync, existsSync as existsSync13, realpathSync as realpathSync2 } from "node:fs";
13859
13872
  import { homedir as homedir8 } from "node:os";
13860
13873
  import path4, { join as join12 } from "node:path";
13861
13874
  function existingSessionColumns(db) {
@@ -14018,7 +14031,7 @@ function realDeps(opencodeDb, contextDb) {
14018
14031
  opencodeDb,
14019
14032
  contextDb,
14020
14033
  resolveIdentity: resolveProjectIdentity,
14021
- hasGitDir: (dir) => existsSync14(join12(dir, ".git")),
14034
+ hasGitDir: (dir) => existsSync13(join12(dir, ".git")),
14022
14035
  realpath: (p2) => realpathSync2(p2)
14023
14036
  };
14024
14037
  }
@@ -14097,7 +14110,7 @@ async function runMigrateSessionCli(args) {
14097
14110
  return 1;
14098
14111
  }
14099
14112
  const expandedTo = toDir.startsWith("~") ? join12(homedir8(), toDir.slice(1).replace(/^[/\\]/, "")) : toDir;
14100
- if (!existsSync14(expandedTo)) {
14113
+ if (!existsSync13(expandedTo)) {
14101
14114
  console.error(`Target directory does not exist: ${expandedTo}`);
14102
14115
  return 1;
14103
14116
  }
@@ -146830,14 +146843,17 @@ var init_read_session_chunk = __esm(async () => {
146830
146843
  });
146831
146844
 
146832
146845
  // ../plugin/src/features/magic-context/message-index.ts
146833
- var lastIndexedStatements, insertMessageStatements, upsertIndexStatements, deleteFtsStatements, deleteIndexStatements, countIndexedMessageStatements;
146846
+ var lastIndexedStatements, insertMessageStatements, upsertIndexStatements, upsertCleanIndexStatements, upsertDirtyFloorStatements, deleteFtsStatements, deleteFtsFromOrdinalStatements, deleteIndexStatements, countIndexedMessageStatements;
146834
146847
  var init_message_index = __esm(async () => {
146835
146848
  init_compression_depth_storage();
146836
146849
  await init_read_session_chunk();
146837
146850
  lastIndexedStatements = new WeakMap;
146838
146851
  insertMessageStatements = new WeakMap;
146839
146852
  upsertIndexStatements = new WeakMap;
146853
+ upsertCleanIndexStatements = new WeakMap;
146854
+ upsertDirtyFloorStatements = new WeakMap;
146840
146855
  deleteFtsStatements = new WeakMap;
146856
+ deleteFtsFromOrdinalStatements = new WeakMap;
146841
146857
  deleteIndexStatements = new WeakMap;
146842
146858
  countIndexedMessageStatements = new WeakMap;
146843
146859
  });
@@ -146876,6 +146892,7 @@ function healNullTextColumns(db) {
146876
146892
  ["cache_ttl", ""],
146877
146893
  ["last_nudge_band", ""],
146878
146894
  ["last_nudge_level", ""],
146895
+ ["channel2_nudge_claim_token", ""],
146879
146896
  ["last_transform_error", ""],
146880
146897
  ["nudge_anchor_message_id", ""],
146881
146898
  ["nudge_anchor_text", ""],
@@ -147016,6 +147033,7 @@ function bumpEpochsForWorkspaceMemberSet(db, identities, now = Date.now()) {
147016
147033
  }
147017
147034
  var VALID_SHARE_CATEGORIES;
147018
147035
  var init_workspaces = __esm(() => {
147036
+ init_logger();
147019
147037
  init_constants();
147020
147038
  init_project_identity2();
147021
147039
  VALID_SHARE_CATEGORIES = new Set(V2_MEMORY_CATEGORIES);
@@ -148469,7 +148487,7 @@ var init_tool_definition_tokens = __esm(() => {
148469
148487
  });
148470
148488
 
148471
148489
  // ../plugin/src/features/magic-context/tool-owner-backfill.ts
148472
- import { existsSync as existsSync15 } from "node:fs";
148490
+ import { existsSync as existsSync14 } from "node:fs";
148473
148491
  import { join as join13 } from "node:path";
148474
148492
  function resolveOpencodeDbPath() {
148475
148493
  return join13(getDataDir(), "opencode", "opencode.db");
@@ -148507,7 +148525,7 @@ function runToolOwnerBackfill(db) {
148507
148525
  return result;
148508
148526
  }
148509
148527
  const opencodeDbPath = resolveOpencodeDbPath();
148510
- if (!existsSync15(opencodeDbPath)) {
148528
+ if (!existsSync14(opencodeDbPath)) {
148511
148529
  log3(`[backfill] OpenCode DB not found at ${opencodeDbPath} — marking all unbackfilled sessions as skipped. Lazy adoption (defense-in-depth) handles legacy rows at runtime.`);
148512
148530
  markAllUnbackfilledSessionsSkipped(db);
148513
148531
  result.sessionsSkippedNoOcDb = countSessionsByStatus(db, "skipped");
@@ -148731,10 +148749,10 @@ var init_tool_owner_backfill = __esm(() => {
148731
148749
  });
148732
148750
 
148733
148751
  // ../plugin/src/features/magic-context/storage-db.ts
148734
- import { chmodSync as chmodSync2, copyFileSync as copyFileSync2, cpSync, existsSync as existsSync16, mkdirSync as mkdirSync7, mkdtempSync } from "node:fs";
148735
- import { dirname as dirname8, join as join14 } from "node:path";
148752
+ import { chmodSync as chmodSync2, copyFileSync as copyFileSync2, cpSync, existsSync as existsSync15, mkdirSync as mkdirSync6, mkdtempSync } from "node:fs";
148753
+ import { dirname as dirname9, join as join14 } from "node:path";
148736
148754
  function ensureSecureStorageDir(dir) {
148737
- mkdirSync7(dir, { recursive: true, mode: 448 });
148755
+ mkdirSync6(dir, { recursive: true, mode: 448 });
148738
148756
  if (!PERMISSIONS_ENFORCEABLE)
148739
148757
  return;
148740
148758
  try {
@@ -148748,7 +148766,7 @@ function restrictDatabaseFilePermissions(dbPath) {
148748
148766
  return;
148749
148767
  for (const suffix of ["", "-wal", "-shm"]) {
148750
148768
  const file = `${dbPath}${suffix}`;
148751
- if (!existsSync16(file))
148769
+ if (!existsSync15(file))
148752
148770
  continue;
148753
148771
  try {
148754
148772
  chmodSync2(file, 384);
@@ -148759,7 +148777,7 @@ function restrictDatabaseFilePermissions(dbPath) {
148759
148777
  }
148760
148778
  function resolveDatabasePath(dbPathOverride) {
148761
148779
  if (dbPathOverride) {
148762
- return { dbDir: dirname8(dbPathOverride), dbPath: dbPathOverride };
148780
+ return { dbDir: dirname9(dbPathOverride), dbPath: dbPathOverride };
148763
148781
  }
148764
148782
  const testDataDir = process.env.MAGIC_CONTEXT_TEST_DATA_DIR;
148765
148783
  if (testDataDir && !process.env.XDG_DATA_HOME) {
@@ -148771,11 +148789,11 @@ function resolveDatabasePath(dbPathOverride) {
148771
148789
  return { dbDir, dbPath: join14(dbDir, "context.db") };
148772
148790
  }
148773
148791
  function migrateLegacyStorageIfNeeded(targetDbPath, targetDbDir) {
148774
- if (existsSync16(targetDbPath))
148792
+ if (existsSync15(targetDbPath))
148775
148793
  return;
148776
148794
  const legacyDir = getLegacyOpenCodeMagicContextStorageDir();
148777
148795
  const legacyDbPath = join14(legacyDir, "context.db");
148778
- if (!existsSync16(legacyDbPath))
148796
+ if (!existsSync15(legacyDbPath))
148779
148797
  return;
148780
148798
  log3(`[magic-context] migrating legacy plugin storage: ${legacyDir} -> ${targetDbDir} (legacy left in place as backup)`);
148781
148799
  ensureSecureStorageDir(targetDbDir);
@@ -148792,7 +148810,7 @@ function migrateLegacyStorageIfNeeded(targetDbPath, targetDbDir) {
148792
148810
  for (const suffix of ["", "-wal", "-shm"]) {
148793
148811
  const src = `${legacyDbPath}${suffix}`;
148794
148812
  const dst = join14(targetDbDir, `context.db${suffix}`);
148795
- if (existsSync16(src)) {
148813
+ if (existsSync15(src)) {
148796
148814
  try {
148797
148815
  copyFileSync2(src, dst);
148798
148816
  } catch (error) {
@@ -148802,7 +148820,7 @@ function migrateLegacyStorageIfNeeded(targetDbPath, targetDbDir) {
148802
148820
  }
148803
148821
  const legacyModelsDir = join14(legacyDir, "models");
148804
148822
  const targetModelsDir = join14(targetDbDir, "models");
148805
- if (existsSync16(legacyModelsDir) && !existsSync16(targetModelsDir)) {
148823
+ if (existsSync15(legacyModelsDir) && !existsSync15(targetModelsDir)) {
148806
148824
  try {
148807
148825
  cpSync(legacyModelsDir, targetModelsDir, { recursive: true });
148808
148826
  } catch (error) {
@@ -149293,6 +149311,7 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
149293
149311
  CREATE TABLE IF NOT EXISTS message_history_index (
149294
149312
  session_id TEXT PRIMARY KEY,
149295
149313
  last_indexed_ordinal INTEGER NOT NULL DEFAULT 0,
149314
+ dirty_floor_ordinal INTEGER NOT NULL DEFAULT 0,
149296
149315
  updated_at INTEGER NOT NULL,
149297
149316
  harness TEXT NOT NULL DEFAULT 'opencode'
149298
149317
  );
@@ -149322,6 +149341,7 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
149322
149341
  last_nudge_level TEXT DEFAULT '',
149323
149342
  channel2_nudge_state TEXT DEFAULT '',
149324
149343
  channel2_nudge_claimed_at INTEGER DEFAULT 0,
149344
+ channel2_nudge_claim_token TEXT DEFAULT '',
149325
149345
  last_emergency_input_sample INTEGER DEFAULT 0,
149326
149346
  last_transform_error TEXT DEFAULT '',
149327
149347
  nudge_anchor_message_id TEXT DEFAULT '',
@@ -149568,6 +149588,7 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
149568
149588
  ensureColumn(db, "session_meta", "last_nudge_level", "TEXT DEFAULT ''");
149569
149589
  ensureColumn(db, "session_meta", "channel2_nudge_state", "TEXT DEFAULT ''");
149570
149590
  ensureColumn(db, "session_meta", "channel2_nudge_claimed_at", "INTEGER DEFAULT 0");
149591
+ ensureColumn(db, "session_meta", "channel2_nudge_claim_token", "TEXT DEFAULT ''");
149571
149592
  ensureColumn(db, "session_meta", "last_emergency_input_sample", "INTEGER DEFAULT 0");
149572
149593
  ensureColumn(db, "session_meta", "last_transform_error", "TEXT DEFAULT ''");
149573
149594
  ensureColumn(db, "session_meta", "nudge_anchor_message_id", "TEXT DEFAULT ''");
@@ -149780,6 +149801,7 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
149780
149801
  ON transform_decisions(session_id, harness);
149781
149802
  `);
149782
149803
  ensureColumn(db, "tags", "harness", "TEXT NOT NULL DEFAULT 'opencode'");
149804
+ ensureColumn(db, "message_history_index", "dirty_floor_ordinal", "INTEGER NOT NULL DEFAULT 0");
149783
149805
  ensureColumn(db, "pending_ops", "harness", "TEXT NOT NULL DEFAULT 'opencode'");
149784
149806
  ensureColumn(db, "source_contents", "harness", "TEXT NOT NULL DEFAULT 'opencode'");
149785
149807
  ensureColumn(db, "compartments", "harness", "TEXT NOT NULL DEFAULT 'opencode'");
@@ -149794,7 +149816,7 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
149794
149816
  function healWedgedChannel2Claims(db) {
149795
149817
  try {
149796
149818
  const staleBefore = Date.now() - CHANNEL2_CLAIM_TTL_MS;
149797
- db.prepare("UPDATE session_meta SET channel2_nudge_state = 'pending', channel2_nudge_claimed_at = 0 WHERE channel2_nudge_state = 'claimed' AND (channel2_nudge_claimed_at IS NULL OR channel2_nudge_claimed_at = 0 OR channel2_nudge_claimed_at <= ?)").run(staleBefore);
149819
+ db.prepare("UPDATE session_meta SET channel2_nudge_state = 'pending', channel2_nudge_claimed_at = 0, channel2_nudge_claim_token = '' WHERE channel2_nudge_state = 'claimed' AND (channel2_nudge_claimed_at IS NULL OR channel2_nudge_claimed_at = 0 OR channel2_nudge_claimed_at <= ?)").run(staleBefore);
149798
149820
  } catch {}
149799
149821
  }
149800
149822
  function openDatabase(dbPathOrOptions) {
@@ -150605,127 +150627,6 @@ function migrateLegacyExperimental(rawConfig, warnings) {
150605
150627
  return patched;
150606
150628
  }
150607
150629
 
150608
- // ../plugin/src/config/project-security.ts
150609
- function isPlainObject(value) {
150610
- return typeof value === "object" && value !== null && !Array.isArray(value);
150611
- }
150612
- function stripUnsafeProjectConfigFields(projectRaw) {
150613
- const warnings = [];
150614
- if ("auto_update" in projectRaw) {
150615
- delete projectRaw.auto_update;
150616
- warnings.push("Ignoring auto_update from project config (security: this setting only honors user-level config).");
150617
- }
150618
- if ("language" in projectRaw) {
150619
- delete projectRaw.language;
150620
- warnings.push("Ignoring language from project config (security: output language is a user-level setting).");
150621
- }
150622
- if ("sqlite" in projectRaw) {
150623
- delete projectRaw.sqlite;
150624
- warnings.push("Ignoring sqlite.* from project config (security: SQLite cache/mmap PRAGMAs apply to the " + "process-global shared database handle; only user-level config may set them).");
150625
- }
150626
- const embedding = projectRaw.embedding;
150627
- if (isPlainObject(embedding)) {
150628
- const removed = [];
150629
- for (const field of EMBEDDING_DESTINATION_FIELDS) {
150630
- if (field in embedding) {
150631
- delete embedding[field];
150632
- removed.push(field);
150633
- }
150634
- }
150635
- if (removed.length > 0) {
150636
- warnings.push(`Ignoring embedding.${removed.join("/")} from project config ` + "(security: a repository cannot choose where private text is embedded).");
150637
- }
150638
- }
150639
- for (const agentKey of HIDDEN_AGENT_KEYS) {
150640
- const block2 = projectRaw[agentKey];
150641
- if (!isPlainObject(block2))
150642
- continue;
150643
- const removed = [];
150644
- for (const field of AGENT_ESCALATION_FIELDS) {
150645
- if (field in block2) {
150646
- delete block2[field];
150647
- removed.push(field);
150648
- }
150649
- }
150650
- if (removed.length > 0) {
150651
- warnings.push(`Ignoring ${agentKey}.${removed.join("/")} from project config ` + "(security: a repository cannot reprogram or re-permission hidden agents).");
150652
- }
150653
- }
150654
- return warnings;
150655
- }
150656
- function normalizeEndpoint(value) {
150657
- if (typeof value !== "string")
150658
- return;
150659
- const trimmed = value.trim().replace(/\/+$/, "");
150660
- return trimmed.length > 0 ? trimmed.toLowerCase() : undefined;
150661
- }
150662
- function dropInheritedEmbeddingKeyOnRedirect(projectRaw, mergedRaw, userRaw) {
150663
- const projectEmbedding = projectRaw.embedding;
150664
- if (!isPlainObject(projectEmbedding))
150665
- return [];
150666
- const redirectsEndpoint = "endpoint" in projectEmbedding;
150667
- if (!redirectsEndpoint)
150668
- return [];
150669
- const userEmbedding = userRaw?.embedding;
150670
- if (isPlainObject(userEmbedding)) {
150671
- const projectEndpoint = normalizeEndpoint(projectEmbedding.endpoint);
150672
- const userEndpoint = normalizeEndpoint(userEmbedding.endpoint);
150673
- if (projectEndpoint !== undefined && projectEndpoint === userEndpoint) {
150674
- return [];
150675
- }
150676
- }
150677
- const providesOwnKey = typeof projectEmbedding.api_key === "string" && projectEmbedding.api_key.length > 0;
150678
- if (providesOwnKey)
150679
- return [];
150680
- const mergedEmbedding = mergedRaw.embedding;
150681
- if (!isPlainObject(mergedEmbedding))
150682
- return [];
150683
- if (!("api_key" in mergedEmbedding))
150684
- return [];
150685
- delete mergedEmbedding.api_key;
150686
- return [
150687
- "Dropped inherited user embedding api_key because project config redirected " + "embedding.endpoint without supplying its own key (security: prevents key " + "exfiltration to a repository-chosen endpoint)."
150688
- ];
150689
- }
150690
- var HIDDEN_AGENT_KEYS, AGENT_ESCALATION_FIELDS, EMBEDDING_DESTINATION_FIELDS;
150691
- var init_project_security = __esm(() => {
150692
- HIDDEN_AGENT_KEYS = ["historian", "dreamer", "sidekick"];
150693
- AGENT_ESCALATION_FIELDS = ["prompt", "permission", "tools", "system_prompt"];
150694
- EMBEDDING_DESTINATION_FIELDS = ["endpoint", "provider"];
150695
- });
150696
-
150697
- // ../plugin/src/config/prune-config-leaf.ts
150698
- function isPlainObject2(value) {
150699
- return typeof value === "object" && value !== null && !Array.isArray(value);
150700
- }
150701
- function pruneNestedConfigLeaf(block2, relativePath) {
150702
- if (relativePath.length === 0)
150703
- return null;
150704
- const result = { ...block2 };
150705
- let cursor3 = result;
150706
- for (let i2 = 0;i2 < relativePath.length - 1; i2++) {
150707
- const seg = String(relativePath[i2]);
150708
- const child = cursor3[seg];
150709
- if (!isPlainObject2(child)) {
150710
- if (!(seg in cursor3))
150711
- return null;
150712
- delete cursor3[seg];
150713
- return {
150714
- block: result,
150715
- removed: relativePath.slice(0, i2 + 1).map(String).join(".")
150716
- };
150717
- }
150718
- const clonedChild = { ...child };
150719
- cursor3[seg] = clonedChild;
150720
- cursor3 = clonedChild;
150721
- }
150722
- const leaf = String(relativePath[relativePath.length - 1]);
150723
- if (!(leaf in cursor3))
150724
- return null;
150725
- delete cursor3[leaf];
150726
- return { block: result, removed: relativePath.map(String).join(".") };
150727
- }
150728
-
150729
150630
  // ../../node_modules/.bun/zod@4.4.3/node_modules/zod/v4/core/core.js
150730
150631
  function $constructor(name2, initializer, params) {
150731
150632
  function init(inst, def) {
@@ -150836,7 +150737,7 @@ __export(exports_util, {
150836
150737
  jsonStringifyReplacer: () => jsonStringifyReplacer,
150837
150738
  joinValues: () => joinValues,
150838
150739
  issue: () => issue,
150839
- isPlainObject: () => isPlainObject3,
150740
+ isPlainObject: () => isPlainObject,
150840
150741
  isObject: () => isObject,
150841
150742
  hexToUint8Array: () => hexToUint8Array,
150842
150743
  getSizableOrigin: () => getSizableOrigin,
@@ -151001,7 +150902,7 @@ function slugify(input) {
151001
150902
  function isObject(data) {
151002
150903
  return typeof data === "object" && data !== null && !Array.isArray(data);
151003
150904
  }
151004
- function isPlainObject3(o2) {
150905
+ function isPlainObject(o2) {
151005
150906
  if (isObject(o2) === false)
151006
150907
  return false;
151007
150908
  const ctor = o2.constructor;
@@ -151018,7 +150919,7 @@ function isPlainObject3(o2) {
151018
150919
  return true;
151019
150920
  }
151020
150921
  function shallowClone(o2) {
151021
- if (isPlainObject3(o2))
150922
+ if (isPlainObject(o2))
151022
150923
  return { ...o2 };
151023
150924
  if (Array.isArray(o2))
151024
150925
  return [...o2];
@@ -151158,7 +151059,7 @@ function omit(schema, mask) {
151158
151059
  return clone(schema, def);
151159
151060
  }
151160
151061
  function extend(schema, shape) {
151161
- if (!isPlainObject3(shape)) {
151062
+ if (!isPlainObject(shape)) {
151162
151063
  throw new Error("Invalid input to extend: expected a plain object");
151163
151064
  }
151164
151065
  const checks = schema._zod.def.checks;
@@ -151181,7 +151082,7 @@ function extend(schema, shape) {
151181
151082
  return clone(schema, def);
151182
151083
  }
151183
151084
  function safeExtend(schema, shape) {
151184
- if (!isPlainObject3(shape)) {
151085
+ if (!isPlainObject(shape)) {
151185
151086
  throw new Error("Invalid input to safeExtend: expected a plain object");
151186
151087
  }
151187
151088
  const def = mergeDefs(schema._zod.def, {
@@ -152664,7 +152565,7 @@ function mergeValues(a3, b2) {
152664
152565
  if (a3 instanceof Date && b2 instanceof Date && +a3 === +b2) {
152665
152566
  return { valid: true, data: a3 };
152666
152567
  }
152667
- if (isPlainObject3(a3) && isPlainObject3(b2)) {
152568
+ if (isPlainObject(a3) && isPlainObject(b2)) {
152668
152569
  const bKeys = Object.keys(b2);
152669
152570
  const sharedKeys = Object.keys(a3).filter((key) => bKeys.indexOf(key) !== -1);
152670
152571
  const newObj = { ...a3, ...b2 };
@@ -153921,7 +153822,7 @@ var init_schemas = __esm(() => {
153921
153822
  $ZodType.init(inst, def);
153922
153823
  inst._zod.parse = (payload, ctx) => {
153923
153824
  const input = payload.value;
153924
- if (!isPlainObject3(input)) {
153825
+ if (!isPlainObject(input)) {
153925
153826
  payload.issues.push({
153926
153827
  expected: "record",
153927
153828
  code: "invalid_type",
@@ -165587,6 +165488,10 @@ var init_magic_context = __esm(() => {
165587
165488
  }).describe("Embedding provider configuration"),
165588
165489
  temporal_awareness: exports_external.boolean().default(true).describe('Inject wall-clock gap markers (<!-- +Xm -->) between user messages where > 5 min elapsed since the previous message, and add start/end date attributes on compartments. Gives the agent a sense of session pacing and "how long ago" across multi-day sessions. Graduated from experimental.temporal_awareness; default: true (set false to opt out).'),
165589
165490
  keep_subagents: exports_external.boolean().default(false).describe("Debug: keep the child sessions Magic Context spawns for its own subagents (historian, dreamer, sidekick, memory-migration) instead of deleting them on success. Useful for short-term inspection/data collection — their full transcript (prompt, tool calls, token usage, output) stays in the host session store. Kept sessions accumulate until manually cleared; leave false for normal use. Requires a restart to take effect."),
165491
+ todowrite: exports_external.object({
165492
+ enabled: exports_external.boolean().default(true).describe("Pi only: register Magic Context's todowrite task-list tool. Disable if you use your own todo extension. OpenCode ships its own built-in todowrite; this setting has no effect there."),
165493
+ overlay: exports_external.boolean().default(true).describe("Pi only: show the persistent todo overlay above the editor while tasks are active.")
165494
+ }).default({ enabled: true, overlay: true }).describe("Pi-only todowrite tool and overlay controls. Pi registers tools and widgets at extension boot, so changing this after /cd requires /reload or restart."),
165590
165495
  smart_drops: exports_external.boolean().default(false).describe("Content-aware reclaim of provably-superseded tool output, layered on the existing execute-pass auto-drop. When on: superseded todowrite (keep newest 1), spent ctx_reduce (keep newest 5), and zero-value meta (bash_status, bash_kill, ctx_note read/dismiss) outputs are dropped; older edits to a file are compressed to a filePath-preserving marker while the newest edit per file stays full. Only acts on passes already busting the cache, so it never originates a cache bust. Honors the protected-tag reserve. Experimental: opt-in, default off until cache stability is proven; when off the wire is byte-identical to the positional-only reclaim. Requires a restart."),
165591
165496
  caveman_text_compression: exports_external.object({
165592
165497
  enabled: exports_external.boolean().default(false).describe("Apply deterministic caveman-style text compression to old conversation text. Active for primary sessions when enabled; never for subagents. Compresses user/assistant text in oldest-first tiers: ultra (oldest 20%), full, lite, untouched (newest 40%)."),
@@ -165624,10 +165529,332 @@ var init_magic_context = __esm(() => {
165624
165529
  });
165625
165530
  });
165626
165531
 
165532
+ // ../plugin/src/config/project-security.ts
165533
+ function isPlainObject2(value) {
165534
+ return typeof value === "object" && value !== null && !Array.isArray(value);
165535
+ }
165536
+ function isValidPercentageThreshold(value) {
165537
+ return typeof value === "number" && Number.isFinite(value) && value >= 20 && value <= 80;
165538
+ }
165539
+ function isValidTokenThreshold(value) {
165540
+ return typeof value === "number" && Number.isFinite(value) && value >= 5000 && value <= 2000000;
165541
+ }
165542
+ function normalizeTrustedPercentageThresholds(value) {
165543
+ if (typeof value === "number" && Number.isFinite(value)) {
165544
+ return { defaultValue: value, overrides: new Map };
165545
+ }
165546
+ if (isPlainObject2(value) && typeof value.default === "number" && Number.isFinite(value.default)) {
165547
+ const overrides = new Map;
165548
+ for (const [key, child] of Object.entries(value)) {
165549
+ if (key === "default")
165550
+ continue;
165551
+ if (typeof child === "number" && Number.isFinite(child)) {
165552
+ overrides.set(key, child);
165553
+ }
165554
+ }
165555
+ return { defaultValue: value.default, overrides };
165556
+ }
165557
+ return { defaultValue: DEFAULT_EXECUTE_THRESHOLD_PERCENTAGE, overrides: new Map };
165558
+ }
165559
+ function normalizeTrustedTokenThresholds(value) {
165560
+ if (!isPlainObject2(value)) {
165561
+ return { defaultValue: undefined, overrides: new Map };
165562
+ }
165563
+ const overrides = new Map;
165564
+ for (const [key, child] of Object.entries(value)) {
165565
+ if (key === "default")
165566
+ continue;
165567
+ if (typeof child === "number" && Number.isFinite(child)) {
165568
+ overrides.set(key, child);
165569
+ }
165570
+ }
165571
+ return {
165572
+ defaultValue: typeof value.default === "number" && Number.isFinite(value.default) ? value.default : undefined,
165573
+ overrides
165574
+ };
165575
+ }
165576
+ function clonePercentageThresholds(value) {
165577
+ return {
165578
+ defaultValue: value.defaultValue,
165579
+ overrides: new Map(value.overrides)
165580
+ };
165581
+ }
165582
+ function cloneTokenThresholds(value) {
165583
+ return {
165584
+ defaultValue: value.defaultValue,
165585
+ overrides: new Map(value.overrides)
165586
+ };
165587
+ }
165588
+ function percentageThresholdsEqual(left, right) {
165589
+ if (left.defaultValue !== right.defaultValue)
165590
+ return false;
165591
+ if (left.overrides.size !== right.overrides.size)
165592
+ return false;
165593
+ for (const [key, value] of left.overrides) {
165594
+ if (right.overrides.get(key) !== value)
165595
+ return false;
165596
+ }
165597
+ return true;
165598
+ }
165599
+ function setMergedPercentageThreshold(mergedRaw, value) {
165600
+ if (value.overrides.size === 0) {
165601
+ mergedRaw.execute_threshold_percentage = value.defaultValue;
165602
+ return;
165603
+ }
165604
+ const serialized = { default: value.defaultValue };
165605
+ for (const [key, threshold] of value.overrides) {
165606
+ serialized[key] = threshold;
165607
+ }
165608
+ mergedRaw.execute_threshold_percentage = serialized;
165609
+ }
165610
+ function setMergedTokenThreshold(mergedRaw, value) {
165611
+ if (value.defaultValue === undefined && value.overrides.size === 0) {
165612
+ delete mergedRaw.execute_threshold_tokens;
165613
+ return;
165614
+ }
165615
+ const serialized = {};
165616
+ if (value.defaultValue !== undefined) {
165617
+ serialized.default = value.defaultValue;
165618
+ }
165619
+ for (const [key, threshold] of value.overrides) {
165620
+ serialized[key] = threshold;
165621
+ }
165622
+ mergedRaw.execute_threshold_tokens = serialized;
165623
+ }
165624
+ function makeProjectThresholdWarning(field, reason) {
165625
+ return `Ignoring ${field} from project config (${reason})`;
165626
+ }
165627
+ function stripUnsafeProjectConfigFields(projectRaw) {
165628
+ const warnings = [];
165629
+ if ("auto_update" in projectRaw) {
165630
+ delete projectRaw.auto_update;
165631
+ warnings.push("Ignoring auto_update from project config (security: this setting only honors user-level config).");
165632
+ }
165633
+ if ("language" in projectRaw) {
165634
+ delete projectRaw.language;
165635
+ warnings.push("Ignoring language from project config (security: output language is a user-level setting).");
165636
+ }
165637
+ if ("sqlite" in projectRaw) {
165638
+ delete projectRaw.sqlite;
165639
+ warnings.push("Ignoring sqlite.* from project config (security: SQLite cache/mmap PRAGMAs apply to the " + "process-global shared database handle; only user-level config may set them).");
165640
+ }
165641
+ const embedding = projectRaw.embedding;
165642
+ if (isPlainObject2(embedding)) {
165643
+ const removed = [];
165644
+ for (const field of EMBEDDING_DESTINATION_FIELDS) {
165645
+ if (field in embedding) {
165646
+ delete embedding[field];
165647
+ removed.push(field);
165648
+ }
165649
+ }
165650
+ if (removed.length > 0) {
165651
+ warnings.push(`Ignoring embedding.${removed.join("/")} from project config ` + "(security: a repository cannot choose where private text is embedded).");
165652
+ }
165653
+ }
165654
+ const historian = projectRaw.historian;
165655
+ if (isPlainObject2(historian)) {
165656
+ const removed = [];
165657
+ for (const field of HISTORIAN_USER_ONLY_FIELDS) {
165658
+ if (field in historian) {
165659
+ delete historian[field];
165660
+ removed.push(field);
165661
+ }
165662
+ }
165663
+ if (removed.length > 0) {
165664
+ warnings.push(`Ignoring historian.${removed.join("/")} from project config ` + "(security: historian model selection is user-level only; a repository cannot force extra compaction cost).");
165665
+ }
165666
+ }
165667
+ for (const agentKey of HIDDEN_AGENT_KEYS) {
165668
+ const block2 = projectRaw[agentKey];
165669
+ if (!isPlainObject2(block2))
165670
+ continue;
165671
+ const removed = [];
165672
+ for (const field of AGENT_ESCALATION_FIELDS) {
165673
+ if (field in block2) {
165674
+ delete block2[field];
165675
+ removed.push(field);
165676
+ }
165677
+ }
165678
+ if (removed.length > 0) {
165679
+ warnings.push(`Ignoring ${agentKey}.${removed.join("/")} from project config ` + "(security: a repository cannot reprogram or re-permission hidden agents).");
165680
+ }
165681
+ }
165682
+ return warnings;
165683
+ }
165684
+ function constrainProjectThresholdOverrides(args) {
165685
+ const warnings = [];
165686
+ const basePercentage = normalizeTrustedPercentageThresholds(args.trustedBaseConfig.execute_threshold_percentage);
165687
+ const baseTokens = normalizeTrustedTokenThresholds(args.trustedBaseConfig.execute_threshold_tokens);
165688
+ if ("execute_threshold_percentage" in args.projectRaw) {
165689
+ const projectValue = args.projectRaw.execute_threshold_percentage;
165690
+ if (isValidPercentageThreshold(projectValue)) {
165691
+ const constrained = clonePercentageThresholds(basePercentage);
165692
+ constrained.defaultValue = Math.max(basePercentage.defaultValue, projectValue);
165693
+ for (const [modelKey, threshold] of basePercentage.overrides) {
165694
+ const raisedThreshold = Math.max(threshold, projectValue);
165695
+ if (raisedThreshold === constrained.defaultValue) {
165696
+ constrained.overrides.delete(modelKey);
165697
+ } else {
165698
+ constrained.overrides.set(modelKey, raisedThreshold);
165699
+ }
165700
+ }
165701
+ setMergedPercentageThreshold(args.mergedRaw, constrained);
165702
+ if (percentageThresholdsEqual(constrained, basePercentage)) {
165703
+ warnings.push(makeProjectThresholdWarning("execute_threshold_percentage", PERCENTAGE_THRESHOLD_REASON));
165704
+ }
165705
+ } else if (isPlainObject2(projectValue)) {
165706
+ const constrained = clonePercentageThresholds(basePercentage);
165707
+ let touchedValidEntry = false;
165708
+ if (isValidPercentageThreshold(projectValue.default)) {
165709
+ touchedValidEntry = true;
165710
+ if (projectValue.default > basePercentage.defaultValue) {
165711
+ constrained.defaultValue = projectValue.default;
165712
+ } else {
165713
+ warnings.push(makeProjectThresholdWarning("execute_threshold_percentage.default", PERCENTAGE_THRESHOLD_REASON));
165714
+ }
165715
+ }
165716
+ for (const [modelKey, rawValue] of Object.entries(projectValue)) {
165717
+ if (modelKey === "default")
165718
+ continue;
165719
+ if (!isValidPercentageThreshold(rawValue))
165720
+ continue;
165721
+ touchedValidEntry = true;
165722
+ const baseValue = basePercentage.overrides.get(modelKey) ?? basePercentage.defaultValue;
165723
+ if (rawValue > baseValue) {
165724
+ if (rawValue === constrained.defaultValue) {
165725
+ constrained.overrides.delete(modelKey);
165726
+ } else {
165727
+ constrained.overrides.set(modelKey, rawValue);
165728
+ }
165729
+ } else {
165730
+ warnings.push(makeProjectThresholdWarning(`execute_threshold_percentage.${modelKey}`, PERCENTAGE_THRESHOLD_REASON));
165731
+ }
165732
+ }
165733
+ if (touchedValidEntry) {
165734
+ setMergedPercentageThreshold(args.mergedRaw, constrained);
165735
+ }
165736
+ }
165737
+ }
165738
+ if ("execute_threshold_tokens" in args.projectRaw && isPlainObject2(args.projectRaw.execute_threshold_tokens)) {
165739
+ const projectValue = args.projectRaw.execute_threshold_tokens;
165740
+ const constrained = cloneTokenThresholds(baseTokens);
165741
+ let touchedValidEntry = false;
165742
+ if (isValidTokenThreshold(projectValue.default)) {
165743
+ touchedValidEntry = true;
165744
+ if (baseTokens.defaultValue === undefined) {
165745
+ warnings.push(makeProjectThresholdWarning("execute_threshold_tokens.default", TOKEN_THRESHOLD_INTRODUCTION_REASON));
165746
+ } else if (projectValue.default > baseTokens.defaultValue) {
165747
+ constrained.defaultValue = projectValue.default;
165748
+ } else {
165749
+ warnings.push(makeProjectThresholdWarning("execute_threshold_tokens.default", TOKEN_THRESHOLD_REASON));
165750
+ }
165751
+ }
165752
+ for (const [modelKey, rawValue] of Object.entries(projectValue)) {
165753
+ if (modelKey === "default")
165754
+ continue;
165755
+ if (!isValidTokenThreshold(rawValue))
165756
+ continue;
165757
+ touchedValidEntry = true;
165758
+ const baseValue = baseTokens.overrides.get(modelKey) ?? baseTokens.defaultValue;
165759
+ if (baseValue === undefined) {
165760
+ warnings.push(makeProjectThresholdWarning(`execute_threshold_tokens.${modelKey}`, TOKEN_THRESHOLD_INTRODUCTION_REASON));
165761
+ continue;
165762
+ }
165763
+ if (rawValue > baseValue) {
165764
+ if (rawValue === constrained.defaultValue) {
165765
+ constrained.overrides.delete(modelKey);
165766
+ } else {
165767
+ constrained.overrides.set(modelKey, rawValue);
165768
+ }
165769
+ } else {
165770
+ warnings.push(makeProjectThresholdWarning(`execute_threshold_tokens.${modelKey}`, TOKEN_THRESHOLD_REASON));
165771
+ }
165772
+ }
165773
+ if (touchedValidEntry) {
165774
+ setMergedTokenThreshold(args.mergedRaw, constrained);
165775
+ }
165776
+ }
165777
+ return warnings;
165778
+ }
165779
+ function normalizeEndpoint(value) {
165780
+ if (typeof value !== "string")
165781
+ return;
165782
+ const trimmed = value.trim().replace(/\/+$/, "");
165783
+ return trimmed.length > 0 ? trimmed.toLowerCase() : undefined;
165784
+ }
165785
+ function dropInheritedEmbeddingKeyOnRedirect(projectRaw, mergedRaw, userRaw) {
165786
+ const projectEmbedding = projectRaw.embedding;
165787
+ if (!isPlainObject2(projectEmbedding))
165788
+ return [];
165789
+ const redirectsEndpoint = "endpoint" in projectEmbedding;
165790
+ if (!redirectsEndpoint)
165791
+ return [];
165792
+ const userEmbedding = userRaw?.embedding;
165793
+ if (isPlainObject2(userEmbedding)) {
165794
+ const projectEndpoint = normalizeEndpoint(projectEmbedding.endpoint);
165795
+ const userEndpoint = normalizeEndpoint(userEmbedding.endpoint);
165796
+ if (projectEndpoint !== undefined && projectEndpoint === userEndpoint) {
165797
+ return [];
165798
+ }
165799
+ }
165800
+ const providesOwnKey = typeof projectEmbedding.api_key === "string" && projectEmbedding.api_key.length > 0;
165801
+ if (providesOwnKey)
165802
+ return [];
165803
+ const mergedEmbedding = mergedRaw.embedding;
165804
+ if (!isPlainObject2(mergedEmbedding))
165805
+ return [];
165806
+ if (!("api_key" in mergedEmbedding))
165807
+ return [];
165808
+ delete mergedEmbedding.api_key;
165809
+ return [
165810
+ "Dropped inherited user embedding api_key because project config redirected " + "embedding.endpoint without supplying its own key (security: prevents key " + "exfiltration to a repository-chosen endpoint)."
165811
+ ];
165812
+ }
165813
+ var HIDDEN_AGENT_KEYS, HISTORIAN_USER_ONLY_FIELDS, AGENT_ESCALATION_FIELDS, EMBEDDING_DESTINATION_FIELDS, PERCENTAGE_THRESHOLD_REASON = "security: a repository may only raise compaction thresholds above the user's effective value; it cannot force earlier historian work or cloned-repo cost escalation.", TOKEN_THRESHOLD_REASON = "security: a repository may only raise execute_threshold_tokens above the user's trusted token threshold; it cannot force earlier historian work or cloned-repo cost escalation.", TOKEN_THRESHOLD_INTRODUCTION_REASON = "security: a repository cannot introduce a new execute_threshold_tokens override when the user has no trusted token threshold for that key; that could force earlier historian work or cloned-repo cost escalation.";
165814
+ var init_project_security = __esm(() => {
165815
+ init_magic_context();
165816
+ HIDDEN_AGENT_KEYS = ["historian", "dreamer", "sidekick"];
165817
+ HISTORIAN_USER_ONLY_FIELDS = ["model", "fallback_models"];
165818
+ AGENT_ESCALATION_FIELDS = ["prompt", "permission", "tools", "system_prompt"];
165819
+ EMBEDDING_DESTINATION_FIELDS = ["endpoint", "provider"];
165820
+ });
165821
+
165822
+ // ../plugin/src/config/prune-config-leaf.ts
165823
+ function isPlainObject3(value) {
165824
+ return typeof value === "object" && value !== null && !Array.isArray(value);
165825
+ }
165826
+ function pruneNestedConfigLeaf(block2, relativePath) {
165827
+ if (relativePath.length === 0)
165828
+ return null;
165829
+ const result = { ...block2 };
165830
+ let cursor3 = result;
165831
+ for (let i2 = 0;i2 < relativePath.length - 1; i2++) {
165832
+ const seg = String(relativePath[i2]);
165833
+ const child = cursor3[seg];
165834
+ if (!isPlainObject3(child)) {
165835
+ if (!(seg in cursor3))
165836
+ return null;
165837
+ delete cursor3[seg];
165838
+ return {
165839
+ block: result,
165840
+ removed: relativePath.slice(0, i2 + 1).map(String).join(".")
165841
+ };
165842
+ }
165843
+ const clonedChild = { ...child };
165844
+ cursor3[seg] = clonedChild;
165845
+ cursor3 = clonedChild;
165846
+ }
165847
+ const leaf = String(relativePath[relativePath.length - 1]);
165848
+ if (!(leaf in cursor3))
165849
+ return null;
165850
+ delete cursor3[leaf];
165851
+ return { block: result, removed: relativePath.map(String).join(".") };
165852
+ }
165853
+
165627
165854
  // ../plugin/src/config/variable.ts
165628
- import { existsSync as existsSync17, readFileSync as readFileSync8 } from "node:fs";
165855
+ import { existsSync as existsSync16, readFileSync as readFileSync8 } from "node:fs";
165629
165856
  import { homedir as homedir9 } from "node:os";
165630
- import { dirname as dirname9, isAbsolute as isAbsolute2, resolve as resolve2 } from "node:path";
165857
+ import { dirname as dirname10, isAbsolute as isAbsolute2, resolve as resolve2 } from "node:path";
165631
165858
  function sensitiveFilePathReason(resolvedPath) {
165632
165859
  const home = homedir9();
165633
165860
  const sensitiveDirs = [
@@ -165674,7 +165901,7 @@ function substituteConfigVariables(input) {
165674
165901
  if (fileMatches.length === 0) {
165675
165902
  return { text: text3, warnings };
165676
165903
  }
165677
- const configDir = input.configPath ? dirname9(input.configPath) : process.cwd();
165904
+ const configDir = input.configPath ? dirname10(input.configPath) : process.cwd();
165678
165905
  let output = "";
165679
165906
  let cursor3 = 0;
165680
165907
  for (const match of fileMatches) {
@@ -165700,7 +165927,7 @@ function substituteConfigVariables(input) {
165700
165927
  if (sensitiveReason) {
165701
165928
  warnings.push(`${token} resolves to a sensitive path (${sensitiveReason}: ${filePath}); ` + "inlining its contents into config — make sure this is intentional.");
165702
165929
  }
165703
- if (!existsSync17(filePath)) {
165930
+ if (!existsSync16(filePath)) {
165704
165931
  warnings.push(`File not found for ${token} (resolved to ${filePath}); using empty string`);
165705
165932
  continue;
165706
165933
  }
@@ -165725,7 +165952,7 @@ var init_variable = __esm(() => {
165725
165952
  });
165726
165953
 
165727
165954
  // ../plugin/src/config/index.ts
165728
- import { existsSync as existsSync18, readFileSync as readFileSync9 } from "node:fs";
165955
+ import { existsSync as existsSync17, readFileSync as readFileSync9 } from "node:fs";
165729
165956
  function getUserConfigBasePath() {
165730
165957
  return cortexKitUserConfigBasePath();
165731
165958
  }
@@ -165733,10 +165960,10 @@ function getProjectConfigBasePath(directory) {
165733
165960
  return cortexKitProjectConfigBasePath(directory);
165734
165961
  }
165735
165962
  function resolveLegacyReadFallback(sources) {
165736
- return { source: sources.find((s) => existsSync18(s.path)) ?? null };
165963
+ return { source: sources.find((s) => existsSync17(s.path)) ?? null };
165737
165964
  }
165738
165965
  function loadConfigFileDetailed(configPath, source) {
165739
- if (!existsSync18(configPath)) {
165966
+ if (!existsSync17(configPath)) {
165740
165967
  return null;
165741
165968
  }
165742
165969
  let rawText;
@@ -165951,12 +166178,13 @@ function loadPluginConfigDetailed(directory) {
165951
166178
  const harnessLegacy = resolveLegacyConfigSourcesForHarness(directory, "opencode");
165952
166179
  const userLegacyFallback = userDetected.format === "none" ? resolveLegacyReadFallback(harnessLegacy.user) : { source: null };
165953
166180
  const projectLegacyFallback = projectDetected.format === "none" ? resolveLegacyReadFallback(harnessLegacy.project) : { source: null };
165954
- const legacyUserUnmigrated = userDetected.format === "none" && !userLegacyFallback.source && legacySources.user.some((source) => existsSync18(source.path));
165955
- const legacyProjectUnmigrated = projectDetected.format === "none" && !projectLegacyFallback.source && legacySources.project.some((source) => existsSync18(source.path));
166181
+ const legacyUserUnmigrated = userDetected.format === "none" && !userLegacyFallback.source && legacySources.user.some((source) => existsSync17(source.path));
166182
+ const legacyProjectUnmigrated = projectDetected.format === "none" && !projectLegacyFallback.source && legacySources.project.some((source) => existsSync17(source.path));
165956
166183
  const userLoaded = userDetected.format !== "none" ? loadConfigFileDetailed(userDetected.path, "user") : userLegacyFallback.source ? loadConfigFileDetailed(userLegacyFallback.source.path, "user") : null;
165957
166184
  const projectLoaded = projectDetected.format !== "none" ? loadConfigFileDetailed(projectDetected.path, "project") : projectLegacyFallback.source ? loadConfigFileDetailed(projectLegacyFallback.source.path, "project") : null;
165958
166185
  const allWarnings = [];
165959
166186
  let mergedRaw = {};
166187
+ const trustedBaseConfig = parsePluginConfig(userLoaded?.config ?? {});
165960
166188
  if (userLegacyFallback.source) {
165961
166189
  allWarnings.push(`[user config] reading legacy config from ${userLegacyFallback.source.path} until migration completes; run \`npx @cortexkit/magic-context doctor\` to consolidate into the shared CortexKit location.`);
165962
166190
  } else if (legacyUserUnmigrated) {
@@ -165981,6 +166209,13 @@ function loadPluginConfigDetailed(directory) {
165981
166209
  for (const warning of dropInheritedEmbeddingKeyOnRedirect(projectRaw, mergedRaw, userLoaded?.config)) {
165982
166210
  allWarnings.push(`[project config] ${warning}`);
165983
166211
  }
166212
+ for (const warning of constrainProjectThresholdOverrides({
166213
+ mergedRaw,
166214
+ projectRaw,
166215
+ trustedBaseConfig
166216
+ })) {
166217
+ allWarnings.push(`[project config] ${warning}`);
166218
+ }
165984
166219
  }
165985
166220
  const recoveredTopLevelKeys = [];
165986
166221
  const config2 = parsePluginConfig(mergedRaw, recoveredTopLevelKeys);
@@ -166137,14 +166372,14 @@ var DEFAULT_TIMEOUT_MS = 1e4, MAX_PREVIEW_CHARS = 240;
166137
166372
  // ../plugin/src/shared/tui-config.ts
166138
166373
  import {
166139
166374
  chmodSync as chmodSync3,
166140
- existsSync as existsSync19,
166141
- mkdirSync as mkdirSync8,
166375
+ existsSync as existsSync18,
166376
+ mkdirSync as mkdirSync7,
166142
166377
  readFileSync as readFileSync10,
166143
166378
  renameSync as renameSync3,
166144
166379
  statSync as statSync6,
166145
- writeFileSync as writeFileSync5
166380
+ writeFileSync as writeFileSync4
166146
166381
  } from "node:fs";
166147
- import { dirname as dirname10, join as join15 } from "node:path";
166382
+ import { dirname as dirname11, join as join15 } from "node:path";
166148
166383
  function pluginEntryId(entry) {
166149
166384
  if (typeof entry === "string")
166150
166385
  return entry;
@@ -166175,7 +166410,7 @@ function writeTuiConfigAtomic(configPath, config2) {
166175
166410
  const body = `${import_comment_json6.stringify(config2, null, 2)}
166176
166411
  `;
166177
166412
  const tmpPath = `${configPath}.tmp`;
166178
- writeFileSync5(tmpPath, body);
166413
+ writeFileSync4(tmpPath, body);
166179
166414
  try {
166180
166415
  if (statSync6(configPath, { throwIfNoEntry: false })?.isFile()) {
166181
166416
  chmodSync3(tmpPath, statSync6(configPath).mode & 511);
@@ -166187,9 +166422,9 @@ function resolveTuiConfigPath() {
166187
166422
  const configDir = getOpenCodeConfigPaths({ binary: "opencode" }).configDir;
166188
166423
  const jsoncPath = join15(configDir, "tui.jsonc");
166189
166424
  const jsonPath = join15(configDir, "tui.json");
166190
- if (existsSync19(jsoncPath))
166425
+ if (existsSync18(jsoncPath))
166191
166426
  return jsoncPath;
166192
- if (existsSync19(jsonPath))
166427
+ if (existsSync18(jsonPath))
166193
166428
  return jsonPath;
166194
166429
  return jsoncPath;
166195
166430
  }
@@ -166197,7 +166432,7 @@ function ensureTuiPluginEntry() {
166197
166432
  try {
166198
166433
  const configPath = resolveTuiConfigPath();
166199
166434
  let config2 = {};
166200
- if (existsSync19(configPath)) {
166435
+ if (existsSync18(configPath)) {
166201
166436
  const raw = readFileSync10(configPath, "utf-8");
166202
166437
  config2 = import_comment_json6.parse(raw) ?? {};
166203
166438
  }
@@ -166232,7 +166467,7 @@ function ensureTuiPluginEntry() {
166232
166467
  }
166233
166468
  }
166234
166469
  config2.plugin = plugins;
166235
- mkdirSync8(dirname10(configPath), { recursive: true });
166470
+ mkdirSync7(dirname11(configPath), { recursive: true });
166236
166471
  writeTuiConfigAtomic(configPath, config2);
166237
166472
  log3(`[magic-context] updated TUI plugin entry in ${configPath}`);
166238
166473
  return true;
@@ -166487,6 +166722,8 @@ function sanitizeDiagnosticText(value) {
166487
166722
  return redactSecretText(sanitizePathString(value));
166488
166723
  }
166489
166724
  function sanitizeConfigValue(value, keyPath = []) {
166725
+ if (value === null || typeof value === "number" || typeof value === "boolean")
166726
+ return value;
166490
166727
  const key = keyPath.at(-1) ?? "";
166491
166728
  if (key && isSecretKey(key)) {
166492
166729
  return `<REDACTED:${redactionTypeForKey(key)}>`;
@@ -166592,12 +166829,29 @@ var init_redaction = __esm(() => {
166592
166829
  });
166593
166830
 
166594
166831
  // src/lib/redaction.ts
166832
+ function sanitizeDiagnosticEndpoint(value) {
166833
+ const trimmed = value.trim();
166834
+ if (!trimmed)
166835
+ return sanitizeDiagnosticText(value);
166836
+ try {
166837
+ const url2 = new URL(trimmed);
166838
+ url2.username = "";
166839
+ url2.password = "";
166840
+ url2.search = "";
166841
+ url2.hash = "";
166842
+ return sanitizeDiagnosticText(url2.toString());
166843
+ } catch {
166844
+ const withoutQuery = trimmed.replace(/[?#].*$/, "");
166845
+ const withoutUserInfo = withoutQuery.replace(/^([a-z][a-z0-9+.-]*:\/\/)[^/@\s]+@/i, "$1");
166846
+ return sanitizeDiagnosticText(withoutUserInfo);
166847
+ }
166848
+ }
166595
166849
  var init_redaction2 = __esm(() => {
166596
166850
  init_redaction();
166597
166851
  });
166598
166852
 
166599
166853
  // src/lib/diagnostics-opencode.ts
166600
- import { existsSync as existsSync20, readdirSync as readdirSync2, readFileSync as readFileSync11, statSync as statSync7 } from "node:fs";
166854
+ import { existsSync as existsSync19, readdirSync as readdirSync2, readFileSync as readFileSync11, statSync as statSync7 } from "node:fs";
166601
166855
  import { createRequire as createRequire2 } from "node:module";
166602
166856
  import { homedir as homedir11 } from "node:os";
166603
166857
  import { join as join16 } from "node:path";
@@ -166618,7 +166872,7 @@ function getPluginCacheInfo() {
166618
166872
  let cached2;
166619
166873
  for (const installedPkgPath of getOpenCodePluginPackageJsonPaths()) {
166620
166874
  try {
166621
- if (existsSync20(installedPkgPath)) {
166875
+ if (existsSync19(installedPkgPath)) {
166622
166876
  const pkg = JSON.parse(readFileSync11(installedPkgPath, "utf-8"));
166623
166877
  cached2 = typeof pkg.version === "string" ? pkg.version : undefined;
166624
166878
  if (cached2)
@@ -166636,7 +166890,7 @@ function getStorageDir() {
166636
166890
  }
166637
166891
  function fileSize(path6) {
166638
166892
  try {
166639
- return existsSync20(path6) ? statSync7(path6).size : 0;
166893
+ return existsSync19(path6) ? statSync7(path6).size : 0;
166640
166894
  } catch {
166641
166895
  return 0;
166642
166896
  }
@@ -166648,7 +166902,7 @@ function sanitizeValue(value) {
166648
166902
  return sanitizeConfigValue(value);
166649
166903
  }
166650
166904
  function readConfig2(path6) {
166651
- if (!existsSync20(path6))
166905
+ if (!existsSync19(path6))
166652
166906
  return { value: null };
166653
166907
  try {
166654
166908
  const raw = readFileSync11(path6, "utf-8");
@@ -166709,7 +166963,7 @@ function parseHistorianDumpMeta(path6) {
166709
166963
  }
166710
166964
  }
166711
166965
  function listDumpsInDir(dir, limit) {
166712
- if (!existsSync20(dir))
166966
+ if (!existsSync19(dir))
166713
166967
  return { count: 0, recent: [] };
166714
166968
  try {
166715
166969
  const entries = readdirSync2(dir).filter((name2) => name2.endsWith(".xml")).map((name2) => {
@@ -166777,8 +167031,9 @@ function collectHistorianDumps(recentSessions) {
166777
167031
  };
166778
167032
  }
166779
167033
  async function collectRecentSessions() {
166780
- const opencodeDbPath = join16(homedir11(), ".local", "share", "opencode", "opencode.db");
166781
- if (!existsSync20(opencodeDbPath))
167034
+ const dataHome = process.env.XDG_DATA_HOME || join16(process.env.HOME || homedir11(), ".local", "share");
167035
+ const opencodeDbPath = join16(dataHome, "opencode", "opencode.db");
167036
+ if (!existsSync19(opencodeDbPath))
166782
167037
  return [];
166783
167038
  if (typeof globalThis.Bun === "undefined") {
166784
167039
  return [];
@@ -166813,7 +167068,7 @@ async function collectRecentSessions() {
166813
167068
  }
166814
167069
  async function collectHistorianFailures(storageDirPath) {
166815
167070
  const contextDbPath = join16(storageDirPath, "context.db");
166816
- if (!existsSync20(contextDbPath))
167071
+ if (!existsSync19(contextDbPath))
166817
167072
  return [];
166818
167073
  if (typeof globalThis.Bun === "undefined") {
166819
167074
  return [];
@@ -166847,7 +167102,7 @@ async function collectHistorianFailures(storageDirPath) {
166847
167102
  }
166848
167103
  async function collectHistorianRuns(storageDirPath) {
166849
167104
  const contextDbPath = join16(storageDirPath, "context.db");
166850
- if (!existsSync20(contextDbPath))
167105
+ if (!existsSync19(contextDbPath))
166851
167106
  return [];
166852
167107
  if (typeof globalThis.Bun === "undefined")
166853
167108
  return [];
@@ -166918,7 +167173,7 @@ async function collectDiagnostics() {
166918
167173
  const storageDirPath = getStorageDir();
166919
167174
  const contextDbPath = join16(storageDirPath, "context.db");
166920
167175
  const logPath = getMagicContextLogPath2("opencode");
166921
- const logFileSize = existsSync20(logPath) ? statSync7(logPath).size : 0;
167176
+ const logFileSize = existsSync19(logPath) ? statSync7(logPath).size : 0;
166922
167177
  const conflictResult = detectConflicts(process.cwd());
166923
167178
  const recentSessions = await collectRecentSessions();
166924
167179
  const openCodeDetection = detectOpenCode();
@@ -166937,14 +167192,14 @@ async function collectDiagnostics() {
166937
167192
  opencodeConfigHasPlugin: configHasPluginEntry(opencodeConfig.value),
166938
167193
  tuiConfigHasPlugin: configHasPluginEntry(tuiConfig.value),
166939
167194
  magicContextConfig: {
166940
- exists: existsSync20(configPaths.magicContextConfig),
167195
+ exists: existsSync19(configPaths.magicContextConfig),
166941
167196
  ...magicContextConfig.error ? { parseError: magicContextConfig.error } : {},
166942
167197
  flags: sanitizeValue(magicContextConfig.value ?? {}) ?? {}
166943
167198
  },
166944
167199
  pluginCache: getPluginCacheInfo(),
166945
167200
  storageDir: {
166946
167201
  path: storageDirPath,
166947
- exists: existsSync20(storageDirPath),
167202
+ exists: existsSync19(storageDirPath),
166948
167203
  contextDbSizeBytes: fileSize(contextDbPath)
166949
167204
  },
166950
167205
  conflicts: {
@@ -166953,7 +167208,7 @@ async function collectDiagnostics() {
166953
167208
  },
166954
167209
  logFile: {
166955
167210
  path: logPath,
166956
- exists: existsSync20(logPath),
167211
+ exists: existsSync19(logPath),
166957
167212
  sizeKb: Math.round(logFileSize / 1024)
166958
167213
  },
166959
167214
  recentSessions,
@@ -167007,7 +167262,7 @@ function renderDiagnosticsMarkdown(report) {
167007
167262
  };
167008
167263
  const recentSessions = report.recentSessions.map((session) => ({
167009
167264
  sessionId: session.sessionId,
167010
- title: session.title,
167265
+ title: sanitizeDiagnosticText(session.title),
167011
167266
  directory: sanitizeString(session.directory),
167012
167267
  lastActiveAt: session.lastActiveAt
167013
167268
  }));
@@ -167093,9 +167348,9 @@ var init_diagnostics_opencode = __esm(() => {
167093
167348
 
167094
167349
  // src/lib/embedding-runtime.ts
167095
167350
  import { spawnSync as spawnSync2 } from "node:child_process";
167096
- import { existsSync as existsSync21 } from "node:fs";
167351
+ import { existsSync as existsSync20 } from "node:fs";
167097
167352
  import { createRequire as createRequire3 } from "node:module";
167098
- import { dirname as dirname11, join as join17, sep } from "node:path";
167353
+ import { dirname as dirname12, join as join17, sep } from "node:path";
167099
167354
  function describeError(error51) {
167100
167355
  const message = error51 instanceof Error ? error51.message : String(error51 ?? "unknown error");
167101
167356
  const code = error51?.code;
@@ -167208,7 +167463,7 @@ function expectedBinaryRelPath(platform, arch) {
167208
167463
  }
167209
167464
  function checkLocalEmbeddingRuntimeAt(installRoot, platform = process.platform, arch = process.arch) {
167210
167465
  const packageDir = join17(installRoot, "node_modules", "onnxruntime-node");
167211
- if (!existsSync21(join17(packageDir, "package.json"))) {
167466
+ if (!existsSync20(join17(packageDir, "package.json"))) {
167212
167467
  return { state: "package-missing", packageDir };
167213
167468
  }
167214
167469
  const rel = expectedBinaryRelPath(platform, arch);
@@ -167216,13 +167471,13 @@ function checkLocalEmbeddingRuntimeAt(installRoot, platform = process.platform,
167216
167471
  return probeOnnxRuntimeNodeLoad(packageDir) ?? { state: "ok", binaryPath: packageDir };
167217
167472
  }
167218
167473
  const binaryPath = join17(packageDir, rel);
167219
- if (!existsSync21(binaryPath)) {
167474
+ if (!existsSync20(binaryPath)) {
167220
167475
  return { state: "binary-missing", packageDir, expectedBinary: binaryPath };
167221
167476
  }
167222
167477
  return probeOnnxRuntimeNodeLoad(packageDir) ?? { state: "ok", binaryPath };
167223
167478
  }
167224
167479
  function checkLocalEmbeddingRuntime(installRoots, platform = process.platform, arch = process.arch) {
167225
- const existing = installRoots.filter((root) => existsSync21(root));
167480
+ const existing = installRoots.filter((root) => existsSync20(root));
167226
167481
  if (existing.length === 0) {
167227
167482
  return {
167228
167483
  state: "unknown",
@@ -167242,10 +167497,10 @@ function checkLocalEmbeddingRuntime(installRoots, platform = process.platform, a
167242
167497
  function packageDirFromResolved(resolvedPath, packageName) {
167243
167498
  const marker = `node_modules${sep}${packageName.split("/").join(sep)}`;
167244
167499
  const idx = resolvedPath.indexOf(marker);
167245
- return idx >= 0 ? resolvedPath.slice(0, idx + marker.length) : dirname11(resolvedPath);
167500
+ return idx >= 0 ? resolvedPath.slice(0, idx + marker.length) : dirname12(resolvedPath);
167246
167501
  }
167247
167502
  function checkLocalEmbeddingRuntimeByResolution(pluginDir, platform = process.platform, arch = process.arch) {
167248
- if (!existsSync21(join17(pluginDir, "package.json"))) {
167503
+ if (!existsSync20(join17(pluginDir, "package.json"))) {
167249
167504
  return { state: "unknown", reason: "plugin package dir not found" };
167250
167505
  }
167251
167506
  let onnxDir = null;
@@ -167281,7 +167536,7 @@ function checkLocalEmbeddingRuntimeByResolution(pluginDir, platform = process.pl
167281
167536
  return probeOnnxRuntimeNodeLoad(onnxDir) ?? { state: "ok", binaryPath: onnxDir };
167282
167537
  }
167283
167538
  const binaryPath = join17(onnxDir, rel);
167284
- if (!existsSync21(binaryPath)) {
167539
+ if (!existsSync20(binaryPath)) {
167285
167540
  return { state: "binary-missing", packageDir: onnxDir, expectedBinary: binaryPath };
167286
167541
  }
167287
167542
  return probeOnnxRuntimeNodeLoad(onnxDir) ?? { state: "ok", binaryPath };
@@ -167327,33 +167582,30 @@ function extractRecentErrors(sanitized, limit = 20) {
167327
167582
  function capBodyToGithubLimit(body, maxBytes = MAX_GITHUB_BODY_BYTES) {
167328
167583
  if (Buffer.byteLength(body, "utf8") <= maxBytes)
167329
167584
  return body;
167585
+ let capped = body;
167330
167586
  const heading = "## Log (last";
167331
167587
  const headingIdx = body.indexOf(heading);
167332
167588
  if (headingIdx === -1) {
167333
- const marker = `
167334
-
167335
- [truncated for GitHub 64KB limit]
167336
- `;
167337
- const markerBytes2 = Buffer.byteLength(marker, "utf8");
167338
- return truncateToByteBudget(body, maxBytes - markerBytes2) + marker;
167589
+ const markerBytes2 = Buffer.byteLength(FALLBACK_TRUNCATION_MARKER, "utf8");
167590
+ capped = truncateToByteBudget(body, maxBytes - markerBytes2) + FALLBACK_TRUNCATION_MARKER;
167591
+ return enforceFinalBodyLimit(capped, maxBytes);
167339
167592
  }
167340
167593
  const fenceOpenIdx = body.indexOf("\n```", headingIdx);
167341
167594
  if (fenceOpenIdx === -1)
167342
- return body;
167595
+ return enforceFinalBodyLimit(body, maxBytes);
167343
167596
  const logStart = fenceOpenIdx + "\n```\n".length;
167344
167597
  const fenceCloseIdx = body.indexOf("\n```", logStart);
167345
167598
  if (fenceCloseIdx === -1)
167346
- return body;
167599
+ return enforceFinalBodyLimit(body, maxBytes);
167347
167600
  const head = body.slice(0, logStart);
167348
167601
  const log4 = body.slice(logStart, fenceCloseIdx);
167349
167602
  const tail = body.slice(fenceCloseIdx);
167350
167603
  const overheadBytes = Buffer.byteLength(head, "utf8") + Buffer.byteLength(tail, "utf8");
167351
- const truncationMarker = `[truncated for GitHub 64KB limit — older log lines dropped]
167352
- `;
167353
- const markerBytes = Buffer.byteLength(truncationMarker, "utf8");
167604
+ const markerBytes = Buffer.byteLength(LOG_TRUNCATION_MARKER, "utf8");
167354
167605
  const logBudget = maxBytes - overheadBytes - markerBytes;
167355
167606
  if (logBudget <= 0) {
167356
- return `${head}${truncationMarker}${tail}`;
167607
+ capped = `${head}${LOG_TRUNCATION_MARKER}${tail}`;
167608
+ return enforceFinalBodyLimit(capped, maxBytes);
167357
167609
  }
167358
167610
  const lines = log4.split(`
167359
167611
  `);
@@ -167369,7 +167621,17 @@ function capBodyToGithubLimit(body, maxBytes = MAX_GITHUB_BODY_BYTES) {
167369
167621
  if (Buffer.byteLength(kept, "utf8") > logBudget) {
167370
167622
  kept = truncateToByteBudget(kept, logBudget);
167371
167623
  }
167372
- return `${head}${truncationMarker}${kept}${tail}`;
167624
+ capped = `${head}${LOG_TRUNCATION_MARKER}${kept}${tail}`;
167625
+ return enforceFinalBodyLimit(capped, maxBytes);
167626
+ }
167627
+ function enforceFinalBodyLimit(body, maxBytes) {
167628
+ if (Buffer.byteLength(body, "utf8") <= maxBytes)
167629
+ return body;
167630
+ const markerBytes = Buffer.byteLength(FINAL_TRUNCATION_MARKER, "utf8");
167631
+ if (markerBytes >= maxBytes) {
167632
+ return truncateToByteBudget(FINAL_TRUNCATION_MARKER, maxBytes);
167633
+ }
167634
+ return truncateToByteBudget(body, maxBytes - markerBytes) + FINAL_TRUNCATION_MARKER;
167373
167635
  }
167374
167636
  function truncateToByteBudget(input, maxBytes) {
167375
167637
  if (maxBytes <= 0)
@@ -167383,7 +167645,14 @@ function truncateToByteBudget(input, maxBytes) {
167383
167645
  }
167384
167646
  return buf.subarray(0, end).toString("utf8");
167385
167647
  }
167386
- var MAX_GITHUB_BODY_BYTES = 60000, ERROR_LOG_PATTERNS;
167648
+ var MAX_GITHUB_BODY_BYTES = 60000, LOG_TRUNCATION_MARKER = `[truncated for GitHub 64KB limit — older log lines dropped]
167649
+ `, FINAL_TRUNCATION_MARKER = `
167650
+
167651
+ [truncated further to fit GitHub body limit]
167652
+ `, FALLBACK_TRUNCATION_MARKER = `
167653
+
167654
+ [truncated for GitHub 64KB limit]
167655
+ `, ERROR_LOG_PATTERNS;
167387
167656
  var init_issue_body = __esm(() => {
167388
167657
  ERROR_LOG_PATTERNS = [
167389
167658
  /\bfailed:/i,
@@ -167396,8 +167665,7 @@ var init_issue_body = __esm(() => {
167396
167665
  });
167397
167666
 
167398
167667
  // src/lib/logs-opencode.ts
167399
- import { readFileSync as readFileSync12, writeFileSync as writeFileSync6 } from "node:fs";
167400
- import { homedir as homedir12 } from "node:os";
167668
+ import { readFileSync as readFileSync12, writeFileSync as writeFileSync5 } from "node:fs";
167401
167669
  import { join as join18 } from "node:path";
167402
167670
  function sanitizeLogContent(content) {
167403
167671
  return sanitizeDiagnosticText(content);
@@ -167438,7 +167706,7 @@ function filterLogLinesBySession(lines, sessionId) {
167438
167706
  return matches.every((id) => id === sessionId);
167439
167707
  });
167440
167708
  }
167441
- async function bundleIssueReport(report, description, _title, sessionFilter = null) {
167709
+ async function bundleIssueReport(report, description, title, sessionFilter = null) {
167442
167710
  const LOG_TAIL_LINES = 400;
167443
167711
  const allLogLines = report.logFile.exists ? readFileSync12(report.logFile.path, "utf-8").split(/\r?\n/) : [];
167444
167712
  const logLines = filterLogLinesBySession(allLogLines, sessionFilter);
@@ -167451,10 +167719,13 @@ async function bundleIssueReport(report, description, _title, sessionFilter = nu
167451
167719
  `));
167452
167720
  const recentErrorLines = extractRecentErrors(errorScanWindow, 20);
167453
167721
  const configBody = JSON.stringify(sanitizeConfigValue(report.magicContextConfig.flags), null, 2);
167454
- const sanitizedConfigPath = report.configPaths.magicContextConfig.replace(homedir12(), "~");
167722
+ const sanitizedConfigPath = sanitizeDiagnosticText(report.configPaths.magicContextConfig);
167723
+ const sanitizedDescription = sanitizeDiagnosticText(description);
167724
+ const sanitizedTitle = sanitizeDiagnosticText(title).trim();
167455
167725
  const rawBodyMarkdown = [
167726
+ ...sanitizedTitle ? ["## Title", sanitizedTitle, ""] : [],
167456
167727
  "## Description",
167457
- description,
167728
+ sanitizedDescription,
167458
167729
  "",
167459
167730
  "## Environment",
167460
167731
  `- Plugin: v${report.pluginVersion}`,
@@ -167489,7 +167760,7 @@ async function bundleIssueReport(report, description, _title, sessionFilter = nu
167489
167760
  `);
167490
167761
  const bodyMarkdown = capBodyToGithubLimit(rawBodyMarkdown);
167491
167762
  const path6 = join18(process.cwd(), `magic-context-issue-${formatTimestamp(new Date)}.md`);
167492
- writeFileSync6(path6, `${bodyMarkdown}
167763
+ writeFileSync5(path6, `${bodyMarkdown}
167493
167764
  `);
167494
167765
  return { path: path6, bodyMarkdown };
167495
167766
  }
@@ -167752,11 +168023,11 @@ function migrateExperimentalPinKeyFilesForDoctor(mcConfig) {
167752
168023
  }
167753
168024
 
167754
168025
  // src/commands/doctor-opencode-cache.ts
167755
- import { existsSync as existsSync22, readFileSync as readFileSync13, rmSync as rmSync2 } from "node:fs";
168026
+ import { existsSync as existsSync21, readFileSync as readFileSync13, rmSync as rmSync2 } from "node:fs";
167756
168027
  function readCachedPluginVersion(pluginCacheDir) {
167757
168028
  try {
167758
168029
  const installedPkgPath = getOpenCodePluginPackageJsonPath(pluginCacheDir);
167759
- if (!existsSync22(installedPkgPath))
168030
+ if (!existsSync21(installedPkgPath))
167760
168031
  return;
167761
168032
  const pkg = JSON.parse(readFileSync13(installedPkgPath, "utf-8"));
167762
168033
  return typeof pkg.version === "string" ? pkg.version : undefined;
@@ -167767,7 +168038,7 @@ function readCachedPluginVersion(pluginCacheDir) {
167767
168038
  async function clearPluginCache(options = {}, deps = {}) {
167768
168039
  const remove = deps.remove ?? ((path6) => rmSync2(path6, { recursive: true, force: true }));
167769
168040
  const pluginCacheRoots = getOpenCodePluginCacheRoots();
167770
- const existingRoots = pluginCacheRoots.filter((root) => existsSync22(root));
168041
+ const existingRoots = pluginCacheRoots.filter((root) => existsSync21(root));
167771
168042
  if (existingRoots.length === 0) {
167772
168043
  return { action: "not_found", path: pluginCacheRoots[0] ?? "" };
167773
168044
  }
@@ -167815,6 +168086,8 @@ async function clearPluginCache(options = {}, deps = {}) {
167815
168086
  action: "error",
167816
168087
  path: firstFailure?.path ?? clearTargets[0]?.path ?? existingRoots[0] ?? "",
167817
168088
  paths: failed.map((entry) => entry.path),
168089
+ clearedPaths: cleared.map((entry) => entry.path),
168090
+ failedPaths: failed.map((entry) => entry.path),
167818
168091
  error: firstFailure?.error
167819
168092
  };
167820
168093
  }
@@ -167833,9 +168106,9 @@ var init_doctor_opencode_cache = __esm(() => {
167833
168106
 
167834
168107
  // src/commands/doctor-opencode.ts
167835
168108
  import { execSync as execSync2, spawnSync as spawnSync3 } from "node:child_process";
167836
- import { existsSync as existsSync23, readFileSync as readFileSync14, statSync as statSync8 } from "node:fs";
168109
+ import { existsSync as existsSync22, readFileSync as readFileSync14, statSync as statSync8 } from "node:fs";
167837
168110
  import { createRequire as createRequire4 } from "node:module";
167838
- import { homedir as homedir13 } from "node:os";
168111
+ import { homedir as homedir12 } from "node:os";
167839
168112
  import { join as join19 } from "node:path";
167840
168113
  function migrateLegacyAgentEnabledConfigForDoctor(mcConfig, logs) {
167841
168114
  let changed = false;
@@ -167905,6 +168178,38 @@ function getSelfVersion2() {
167905
168178
  }
167906
168179
  return "0.0.0";
167907
168180
  }
168181
+ function isPinnedOpenCodePluginSpecifier(specifier) {
168182
+ if (specifier === OPENCODE_PLUGIN_NAME || specifier === OPENCODE_PLUGIN_ENTRY_WITH_VERSION)
168183
+ return false;
168184
+ return specifier.startsWith(`${OPENCODE_PLUGIN_NAME}@`);
168185
+ }
168186
+ function getUserNpmrcPath() {
168187
+ const custom2 = process.env.NPM_CONFIG_USERCONFIG?.trim();
168188
+ if (custom2)
168189
+ return custom2;
168190
+ const home = process.env.HOME?.trim();
168191
+ return join19(home || homedir12(), ".npmrc");
168192
+ }
168193
+ function collectNpmReleaseAgeWarnings() {
168194
+ const ageWarnings = [];
168195
+ const npmrcPath = getUserNpmrcPath();
168196
+ if (!existsSync22(npmrcPath))
168197
+ return ageWarnings;
168198
+ try {
168199
+ const npmrc = readFileSync14(npmrcPath, "utf-8");
168200
+ for (const line of npmrc.split(`
168201
+ `)) {
168202
+ const trimmed = line.trim();
168203
+ if (trimmed.startsWith("#") || trimmed.startsWith(";"))
168204
+ continue;
168205
+ const [key] = trimmed.split("=").map((s) => s.trim());
168206
+ if (key === "min-release-age" || key === "before") {
168207
+ ageWarnings.push(`${sanitizePathString(npmrcPath)} has '${sanitizeDiagnosticText(trimmed)}'`);
168208
+ }
168209
+ }
168210
+ } catch {}
168211
+ return ageWarnings;
168212
+ }
167908
168213
  function compareVersions(a3, b2) {
167909
168214
  const pa = a3.split(/[.-]/).map((s) => Number.parseInt(s, 10));
167910
168215
  const pb = b2.split(/[.-]/).map((s) => Number.parseInt(s, 10));
@@ -168026,7 +168331,7 @@ function checkLocalEmbeddingRuntimeForDoctor() {
168026
168331
  return { issues: 0 };
168027
168332
  }
168028
168333
  async function checkEmbeddingConfig(magicContextConfigPath) {
168029
- if (!existsSync23(magicContextConfigPath)) {
168334
+ if (!existsSync22(magicContextConfigPath)) {
168030
168335
  return checkLocalEmbeddingRuntimeForDoctor();
168031
168336
  }
168032
168337
  let rawText;
@@ -168089,7 +168394,7 @@ async function checkEmbeddingConfig(magicContextConfigPath) {
168089
168394
  }
168090
168395
  }
168091
168396
  const probeSpinner = spinner2();
168092
- probeSpinner.start(`Testing embedding endpoint ${endpoint} (model: ${model})`);
168397
+ probeSpinner.start(`Testing embedding endpoint ${sanitizeDiagnosticEndpoint(endpoint)} (model: ${sanitizeDiagnosticText(model)})`);
168093
168398
  let outcome;
168094
168399
  try {
168095
168400
  outcome = await probeEmbeddingEndpoint({
@@ -168102,7 +168407,7 @@ async function checkEmbeddingConfig(magicContextConfigPath) {
168102
168407
  });
168103
168408
  } catch (error51) {
168104
168409
  probeSpinner.stop("Embedding probe failed unexpectedly");
168105
- log2.error(`Probe threw: ${error51 instanceof Error ? error51.message : String(error51)}`);
168410
+ log2.error(`Probe threw: ${sanitizeDiagnosticText(error51 instanceof Error ? error51.message : String(error51))}`);
168106
168411
  return { issues: localIssues + 1 };
168107
168412
  }
168108
168413
  probeSpinner.stop("Embedding endpoint probed");
@@ -168113,28 +168418,28 @@ async function checkEmbeddingConfig(magicContextConfigPath) {
168113
168418
  case "auth_failed":
168114
168419
  log2.error(`Embedding endpoint rejected credentials (${outcome.status}) — check api_key / env var`);
168115
168420
  if (outcome.preview)
168116
- log2.info(` ${outcome.preview}`);
168421
+ log2.info(` ${sanitizeDiagnosticText(outcome.preview)}`);
168117
168422
  return { issues: localIssues + 1 };
168118
168423
  case "endpoint_unsupported":
168119
168424
  log2.error(`Embedding endpoint does not support embeddings (${outcome.status})`);
168120
168425
  if (outcome.preview)
168121
- log2.info(` ${outcome.preview}`);
168426
+ log2.info(` ${sanitizeDiagnosticText(outcome.preview)}`);
168122
168427
  log2.info(" Common causes: endpoint points at a chat-completion route (should be the provider base, e.g. '.../v1'), or the provider doesn't offer an embeddings API");
168123
168428
  log2.info(" Known non-embedding providers: OpenRouter (chat proxy), Anthropic (no embeddings endpoint). Use OpenAI, Voyage, Together, or a local provider instead.");
168124
168429
  return { issues: localIssues + 1 };
168125
168430
  case "http_error":
168126
168431
  log2.error(`Embedding endpoint returned ${outcome.status}`);
168127
168432
  if (outcome.preview)
168128
- log2.info(` ${outcome.preview}`);
168433
+ log2.info(` ${sanitizeDiagnosticText(outcome.preview)}`);
168129
168434
  return { issues: localIssues + 1 };
168130
168435
  case "timeout":
168131
168436
  log2.warn(`Embedding endpoint did not respond within ${outcome.timeoutMs}ms — check endpoint URL and network`);
168132
168437
  return { issues: localIssues + 1 };
168133
168438
  case "network_error":
168134
- log2.error(`Could not reach embedding endpoint: ${outcome.message}`);
168439
+ log2.error(`Could not reach embedding endpoint: ${sanitizeDiagnosticText(outcome.message)}`);
168135
168440
  return { issues: localIssues + 1 };
168136
168441
  case "invalid_scheme":
168137
- log2.error(`Embedding endpoint must start with http:// or https://: ${outcome.endpoint}`);
168442
+ log2.error(`Embedding endpoint must start with http:// or https://: ${sanitizeDiagnosticEndpoint(outcome.endpoint)}`);
168138
168443
  return { issues: localIssues + 1 };
168139
168444
  }
168140
168445
  }
@@ -168202,7 +168507,7 @@ async function runDoctor(options = {}) {
168202
168507
  } else {
168203
168508
  pass(`OpenCode config: ${paths.opencodeConfig}`);
168204
168509
  }
168205
- if (existsSync23(paths.magicContextConfig)) {
168510
+ if (existsSync22(paths.magicContextConfig)) {
168206
168511
  pass(`Magic Context config: ${paths.magicContextConfig}`);
168207
168512
  try {
168208
168513
  const raw = readFileSync14(paths.magicContextConfig, "utf-8");
@@ -168230,7 +168535,7 @@ async function runDoctor(options = {}) {
168230
168535
  warn(`No magic-context.jsonc found — using defaults`);
168231
168536
  log2.info(" Run 'setup' to create one with model recommendations");
168232
168537
  }
168233
- if (existsSync23(paths.magicContextConfig)) {
168538
+ if (existsSync22(paths.magicContextConfig)) {
168234
168539
  try {
168235
168540
  const mcRaw = readFileSync14(paths.magicContextConfig, "utf-8");
168236
168541
  const mcConfig = import_comment_json8.parse(mcRaw);
@@ -168369,7 +168674,7 @@ async function runDoctor(options = {}) {
168369
168674
  if (isDevPathPluginEntry(oldEntry)) {
168370
168675
  pass(`Plugin registered in ${configName} (dev path: ${oldEntryStr})`);
168371
168676
  } else {
168372
- const isPinned = oldEntryStr !== OPENCODE_PLUGIN_NAME && oldEntryStr !== OPENCODE_PLUGIN_ENTRY_WITH_VERSION && /^@cortexkit\/opencode-magic-context@\d/.test(oldEntryStr);
168677
+ const isPinned = isPinnedOpenCodePluginSpecifier(oldEntryStr);
168373
168678
  if (isPinned && !options.force) {
168374
168679
  warn(`Plugin pinned to ${oldEntryStr} in ${configName} — use 'doctor --force' to upgrade`);
168375
168680
  } else {
@@ -168421,7 +168726,7 @@ async function runDoctor(options = {}) {
168421
168726
  pass("Added TUI sidebar plugin to tui.json");
168422
168727
  warn("Restart OpenCode to see the sidebar");
168423
168728
  fixed++;
168424
- } else if (existsSync23(paths.tuiConfig)) {
168729
+ } else if (existsSync22(paths.tuiConfig)) {
168425
168730
  try {
168426
168731
  const tuiRaw = readFileSync14(paths.tuiConfig, "utf-8");
168427
168732
  const tuiConfig = import_comment_json8.parse(tuiRaw);
@@ -168440,7 +168745,7 @@ async function runDoctor(options = {}) {
168440
168745
  if (isDevPathPluginEntry(tuiEntry)) {
168441
168746
  pass(`TUI sidebar plugin configured (dev path: ${tuiEntryStr})`);
168442
168747
  } else {
168443
- const tuiPinned = tuiEntryStr !== OPENCODE_PLUGIN_NAME && tuiEntryStr !== OPENCODE_PLUGIN_ENTRY_WITH_VERSION && /^@cortexkit\/opencode-magic-context@\d/.test(tuiEntryStr);
168748
+ const tuiPinned = isPinnedOpenCodePluginSpecifier(tuiEntryStr);
168444
168749
  if (tuiPinned && !options.force) {
168445
168750
  warn(`TUI plugin pinned to ${tuiEntryStr} — use 'doctor --force' to upgrade`);
168446
168751
  } else if (tuiPinned && options.force) {
@@ -168469,7 +168774,7 @@ async function runDoctor(options = {}) {
168469
168774
  } else {
168470
168775
  pass("TUI sidebar plugin configured (tui.json created)");
168471
168776
  }
168472
- if (existsSync23(paths.magicContextConfig)) {
168777
+ if (existsSync22(paths.magicContextConfig)) {
168473
168778
  try {
168474
168779
  const mcRaw = readFileSync14(paths.magicContextConfig, "utf-8");
168475
168780
  const mcConfig = import_comment_json8.parse(mcRaw);
@@ -168490,7 +168795,7 @@ async function runDoctor(options = {}) {
168490
168795
  else
168491
168796
  passCount++;
168492
168797
  const dbPath = join19(getMagicContextStorageDir(), "context.db");
168493
- if (!existsSync23(dbPath)) {
168798
+ if (!existsSync22(dbPath)) {
168494
168799
  log2.info(`Shared context DB not yet created at ${dbPath} (will be created on first run)`);
168495
168800
  } else {
168496
168801
  pass(`Shared context DB exists at ${dbPath}`);
@@ -168550,29 +168855,20 @@ async function runDoctor(options = {}) {
168550
168855
  warn(`Plugin cache version check unavailable; preserving cached plugin${cacheResult.cached ? ` (cached: ${cacheResult.cached})` : ""}. Use doctor --force to reinstall it.`);
168551
168856
  } else if (cacheResult.action === "error") {
168552
168857
  warn(`Could not clear plugin cache: ${cacheResult.error}`);
168553
- log2.info(` Manually delete: ${cacheResult.path}`);
168858
+ if (cacheResult.clearedPaths && cacheResult.clearedPaths.length > 0) {
168859
+ log2.info(` Cleared roots: ${cacheResult.clearedPaths.join(", ")}`);
168860
+ }
168861
+ if (cacheResult.failedPaths && cacheResult.failedPaths.length > 0) {
168862
+ log2.info(` Failed roots: ${cacheResult.failedPaths.join(", ")}`);
168863
+ } else {
168864
+ log2.info(` Manually delete: ${cacheResult.path}`);
168865
+ }
168554
168866
  issues++;
168555
168867
  } else {
168556
168868
  pass("Plugin cache clean (no cached version found)");
168557
168869
  }
168558
168870
  {
168559
- const ageWarnings = [];
168560
- const npmrcPath = join19(homedir13(), ".npmrc");
168561
- if (existsSync23(npmrcPath)) {
168562
- try {
168563
- const npmrc = readFileSync14(npmrcPath, "utf-8");
168564
- for (const line of npmrc.split(`
168565
- `)) {
168566
- const trimmed = line.trim();
168567
- if (trimmed.startsWith("#") || trimmed.startsWith(";"))
168568
- continue;
168569
- const [key] = trimmed.split("=").map((s) => s.trim());
168570
- if (key === "min-release-age" || key === "before") {
168571
- ageWarnings.push(`~/.npmrc has '${trimmed}'`);
168572
- }
168573
- }
168574
- } catch {}
168575
- }
168871
+ const ageWarnings = collectNpmReleaseAgeWarnings();
168576
168872
  if (ageWarnings.length > 0) {
168577
168873
  log2.warn("npm min-release-age restriction detected — this can prevent OpenCode from installing the latest plugin version");
168578
168874
  for (const w of ageWarnings) {
@@ -168584,7 +168880,7 @@ async function runDoctor(options = {}) {
168584
168880
  }
168585
168881
  }
168586
168882
  const logPath = getMagicContextLogPath2("opencode");
168587
- if (existsSync23(logPath)) {
168883
+ if (existsSync22(logPath)) {
168588
168884
  const logStat = statSync8(logPath);
168589
168885
  const sizeKb = (logStat.size / 1024).toFixed(0);
168590
168886
  log2.info(`Log file: ${logPath} (${sizeKb} KB)`);
@@ -168649,6 +168945,7 @@ var init_doctor_opencode = __esm(async () => {
168649
168945
  init_opencode_plugin_cache();
168650
168946
  init_paths();
168651
168947
  init_prompts();
168948
+ init_redaction2();
168652
168949
  init_v22_backfill_commands();
168653
168950
  init_doctor_opencode_cache();
168654
168951
  await __promiseAll([
@@ -168659,7 +168956,7 @@ var init_doctor_opencode = __esm(async () => {
168659
168956
  });
168660
168957
 
168661
168958
  // ../pi-plugin/src/config/index.ts
168662
- import { existsSync as existsSync24, readFileSync as readFileSync15 } from "node:fs";
168959
+ import { existsSync as existsSync23, readFileSync as readFileSync15 } from "node:fs";
168663
168960
  function getProjectConfigPaths(cwd) {
168664
168961
  const basePath = cortexKitProjectConfigBasePath(cwd);
168665
168962
  return [`${basePath}.jsonc`, `${basePath}.json`];
@@ -168669,10 +168966,10 @@ function getUserConfigPaths() {
168669
168966
  return [`${basePath}.jsonc`, `${basePath}.json`];
168670
168967
  }
168671
168968
  function resolveFirstExisting(paths) {
168672
- return paths.find((path6) => existsSync24(path6));
168969
+ return paths.find((path6) => existsSync23(path6));
168673
168970
  }
168674
168971
  function resolvePiLegacyFallback(sources) {
168675
- return sources.find((source) => existsSync24(source.path)) ?? null;
168972
+ return sources.find((source) => existsSync23(source.path)) ?? null;
168676
168973
  }
168677
168974
  function loadConfigFile(path6, scope) {
168678
168975
  try {
@@ -168809,7 +169106,7 @@ function loadPiConfig(opts = {}) {
168809
169106
  if (loaded)
168810
169107
  loadedFiles.push(loaded);
168811
169108
  }
168812
- const legacyProjectUnmigrated = !projectPath && !projectLegacyFallback && legacySources.project.some((source) => existsSync24(source.path));
169109
+ const legacyProjectUnmigrated = !projectPath && !projectLegacyFallback && legacySources.project.some((source) => existsSync23(source.path));
168813
169110
  const userPath = resolveFirstExisting(getUserConfigPaths());
168814
169111
  const userLegacyFallback = userPath ? null : resolvePiLegacyFallback(harnessLegacy.user);
168815
169112
  const userReadPath = userPath ?? userLegacyFallback?.path;
@@ -168818,7 +169115,7 @@ function loadPiConfig(opts = {}) {
168818
169115
  if (loaded)
168819
169116
  loadedFiles.push(loaded);
168820
169117
  }
168821
- const legacyUserUnmigrated = !userPath && !userLegacyFallback && legacySources.user.some((source) => existsSync24(source.path));
169118
+ const legacyUserUnmigrated = !userPath && !userLegacyFallback && legacySources.user.some((source) => existsSync23(source.path));
168822
169119
  if (userLegacyFallback) {
168823
169120
  warnings.push(`[user config] reading legacy config from ${userLegacyFallback.path} until migration completes; run \`npx @cortexkit/magic-context doctor\` to consolidate into the shared CortexKit location.`);
168824
169121
  } else if (legacyUserUnmigrated) {
@@ -168836,6 +169133,7 @@ function loadPiConfig(opts = {}) {
168836
169133
  return a3.scope === "user" ? -1 : 1;
168837
169134
  });
168838
169135
  const userRaw = mergeFiles.find((f2) => f2.scope === "user")?.config;
169136
+ const trustedBaseConfig = parsePiConfig(userRaw ?? {}).config;
168839
169137
  for (const loaded of mergeFiles) {
168840
169138
  const prefix = loaded.scope === "user" ? "[user config]" : "[project config]";
168841
169139
  warnings.push(...loaded.warnings.map((warning) => `${prefix} ${warning}`));
@@ -168848,6 +169146,13 @@ function loadPiConfig(opts = {}) {
168848
169146
  for (const warning of dropInheritedEmbeddingKeyOnRedirect(projectRaw, rawConfig, userRaw)) {
168849
169147
  warnings.push(`${prefix} ${warning}`);
168850
169148
  }
169149
+ for (const warning of constrainProjectThresholdOverrides({
169150
+ mergedRaw: rawConfig,
169151
+ projectRaw,
169152
+ trustedBaseConfig
169153
+ })) {
169154
+ warnings.push(`${prefix} ${warning}`);
169155
+ }
168851
169156
  } else {
168852
169157
  rawConfig = mergeRawConfigs(rawConfig, loaded.config);
168853
169158
  }
@@ -168872,9 +169177,9 @@ var init_config2 = __esm(() => {
168872
169177
 
168873
169178
  // src/lib/diagnostics-pi.ts
168874
169179
  import { createHash as createHash3 } from "node:crypto";
168875
- import { existsSync as existsSync25, readdirSync as readdirSync3, readFileSync as readFileSync16, statSync as statSync9 } from "node:fs";
169180
+ import { existsSync as existsSync24, readdirSync as readdirSync3, readFileSync as readFileSync16, statSync as statSync9 } from "node:fs";
168876
169181
  import { createRequire as createRequire5 } from "node:module";
168877
- import { homedir as homedir14, userInfo as userInfo2 } from "node:os";
169182
+ import { homedir as homedir13, userInfo as userInfo2 } from "node:os";
168878
169183
  import { join as join20 } from "node:path";
168879
169184
  function getSelfVersion3() {
168880
169185
  const req = createRequire5(import.meta.url);
@@ -168890,7 +169195,7 @@ function getSelfVersion3() {
168890
169195
  }
168891
169196
  function fileSize2(path6) {
168892
169197
  try {
168893
- return existsSync25(path6) ? statSync9(path6).size : 0;
169198
+ return existsSync24(path6) ? statSync9(path6).size : 0;
168894
169199
  } catch {
168895
169200
  return 0;
168896
169201
  }
@@ -168906,7 +169211,7 @@ function redactSecretString(value) {
168906
169211
  return redactSecretText(value).replace(/Bearer\s+[A-Za-z0-9._~+\-/=]+/g, "Bearer <REDACTED>").replace(/sk-[A-Za-z0-9_-]{12,}/g, "sk-<REDACTED>").replace(/api[_-]?key=([^\s&]+)/gi, "api_key=<REDACTED>").replace(/token=([^\s&]+)/gi, "token=<REDACTED>");
168907
169212
  }
168908
169213
  function sanitizeString2(value) {
168909
- const home = process.env.HOME || homedir14();
169214
+ const home = process.env.HOME || homedir13();
168910
169215
  const username = userInfo2().username;
168911
169216
  const userHash = `<USER:${currentUserHash()}>`;
168912
169217
  let sanitized = redactSecretString(value);
@@ -168925,6 +169230,8 @@ function shouldRedactKey(key) {
168925
169230
  return /api[_-]?key|token|secret|password|authorization|cookie/i.test(key);
168926
169231
  }
168927
169232
  function sanitizeValue2(value, key = "") {
169233
+ if (value === null || typeof value === "number" || typeof value === "boolean")
169234
+ return value;
168928
169235
  if (shouldRedactKey(key))
168929
169236
  return "<REDACTED>";
168930
169237
  if (typeof value === "string")
@@ -168940,7 +169247,7 @@ function sanitizeValue2(value, key = "") {
168940
169247
  return value;
168941
169248
  }
168942
169249
  function readJsonc3(path6) {
168943
- if (!existsSync25(path6))
169250
+ if (!existsSync24(path6))
168944
169251
  return { value: {} };
168945
169252
  try {
168946
169253
  return {
@@ -168960,7 +169267,7 @@ function readConfigDiagnostic(path6) {
168960
169267
  const parsed = readJsonc3(path6);
168961
169268
  return {
168962
169269
  path: path6,
168963
- exists: existsSync25(path6),
169270
+ exists: existsSync24(path6),
168964
169271
  ...parsed.parseError ? { parseError: parsed.parseError } : {},
168965
169272
  flags: sanitizeValue2(parsed.value)
168966
169273
  };
@@ -168977,8 +169284,8 @@ function reverseSlugToDirectory(slug) {
168977
169284
  return `/${inner.replace(/-/g, "/")}`;
168978
169285
  }
168979
169286
  function collectPiRecentSessions() {
168980
- const sessionsRoot = join20(homedir14(), ".pi", "agent", "sessions");
168981
- if (!existsSync25(sessionsRoot))
169287
+ const sessionsRoot = getPiSessionsRoot();
169288
+ if (!existsSync24(sessionsRoot))
168982
169289
  return [];
168983
169290
  try {
168984
169291
  const slugs = readdirSync3(sessionsRoot, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name);
@@ -169047,7 +169354,7 @@ function parseHistorianDumpMeta2(path6) {
169047
169354
  }
169048
169355
  }
169049
169356
  function listDumpsInDir2(dir, limit) {
169050
- if (!existsSync25(dir))
169357
+ if (!existsSync24(dir))
169051
169358
  return { count: 0, recent: [] };
169052
169359
  try {
169053
169360
  const entries = readdirSync3(dir).filter((name2) => name2.endsWith(".xml")).map((name2) => {
@@ -169125,7 +169432,7 @@ async function collectDiagnostics2(cwd = process.cwd()) {
169125
169432
  const storageDirPath = getMagicContextStorageDir();
169126
169433
  const dbPath = join20(storageDirPath, "context.db");
169127
169434
  const logPath = getMagicContextLogPath2("pi");
169128
- const logFileSize = existsSync25(logPath) ? statSync9(logPath).size : 0;
169435
+ const logFileSize = existsSync24(logPath) ? statSync9(logPath).size : 0;
169129
169436
  const otherPiExtensions = packages.filter((entry) => !isPiMagicContextPackageEntry(entry)).map(describePiPackageEntry);
169130
169437
  const recentSessions = collectPiRecentSessions();
169131
169438
  const historianDumps = collectPiHistorianDumps(recentSessions);
@@ -169140,7 +169447,7 @@ async function collectDiagnostics2(cwd = process.cwd()) {
169140
169447
  piVersion: pi ? getPiVersion(pi.path) : null,
169141
169448
  settings: {
169142
169449
  path: settingsPath,
169143
- exists: existsSync25(settingsPath),
169450
+ exists: existsSync24(settingsPath),
169144
169451
  ...settingsParsed.parseError ? { parseError: settingsParsed.parseError } : {},
169145
169452
  hasMagicContextPackage: hasPiMagicContextPackage(packages),
169146
169453
  packages: sanitizeValue2(packages)
@@ -169156,7 +169463,7 @@ async function collectDiagnostics2(cwd = process.cwd()) {
169156
169463
  loadWarnings: loaded.warnings.map(sanitizeString2),
169157
169464
  storageDir: {
169158
169465
  path: storageDirPath,
169159
- exists: existsSync25(storageDirPath),
169466
+ exists: existsSync24(storageDirPath),
169160
169467
  contextDbSizeBytes: fileSize2(dbPath)
169161
169468
  },
169162
169469
  conflicts: {
@@ -169165,7 +169472,7 @@ async function collectDiagnostics2(cwd = process.cwd()) {
169165
169472
  },
169166
169473
  logFile: {
169167
169474
  path: logPath,
169168
- exists: existsSync25(logPath),
169475
+ exists: existsSync24(logPath),
169169
169476
  sizeKb: Math.round(logFileSize / 1024)
169170
169477
  },
169171
169478
  recentSessions,
@@ -169259,7 +169566,7 @@ var init_diagnostics_pi = __esm(() => {
169259
169566
  });
169260
169567
 
169261
169568
  // src/lib/logs-pi.ts
169262
- import { readFileSync as readFileSync17, writeFileSync as writeFileSync7 } from "node:fs";
169569
+ import { readFileSync as readFileSync17, writeFileSync as writeFileSync6 } from "node:fs";
169263
169570
  import { join as join21 } from "node:path";
169264
169571
  function sanitizeLogContent2(content) {
169265
169572
  return sanitizeString2(content);
@@ -169326,7 +169633,7 @@ async function bundleIssueReport2(report, description, title, options = {}) {
169326
169633
  const bodyMarkdown = capBodyToGithubLimit(rawBodyMarkdown);
169327
169634
  const cwd = options.cwd ?? process.cwd();
169328
169635
  const path6 = join21(cwd, `magic-context-pi-issue-${formatTimestamp2(options.now ?? new Date)}.md`);
169329
- writeFileSync7(path6, `${bodyMarkdown}
169636
+ writeFileSync6(path6, `${bodyMarkdown}
169330
169637
  `);
169331
169638
  return { path: path6, bodyMarkdown };
169332
169639
  }
@@ -169337,10 +169644,10 @@ var init_logs_pi = __esm(() => {
169337
169644
 
169338
169645
  // src/commands/doctor-pi.ts
169339
169646
  import { execFileSync as execFileSync5, spawnSync as spawnSync4 } from "node:child_process";
169340
- import { existsSync as existsSync26, mkdirSync as mkdirSync9, readdirSync as readdirSync4, readFileSync as readFileSync18, rmSync as rmSync3, statSync as statSync10 } from "node:fs";
169647
+ import { existsSync as existsSync25, mkdirSync as mkdirSync8, readdirSync as readdirSync4, readFileSync as readFileSync18, rmSync as rmSync3, statSync as statSync10 } from "node:fs";
169341
169648
  import { createRequire as createRequire6 } from "node:module";
169342
- import { homedir as homedir15 } from "node:os";
169343
- import { dirname as dirname12, isAbsolute as isAbsolute3, join as join22 } from "node:path";
169649
+ import { homedir as homedir14 } from "node:os";
169650
+ import { dirname as dirname13, isAbsolute as isAbsolute3, join as join22 } from "node:path";
169344
169651
  function depsFrom(options) {
169345
169652
  return {
169346
169653
  ...DEFAULT_DEPS,
@@ -169454,13 +169761,13 @@ function piPluginDirCandidates(packages, cwd) {
169454
169761
  }
169455
169762
  dirs.push(join22(agentDir, "npm", "node_modules", PACKAGE_NAME));
169456
169763
  dirs.push(join22(cwd, ".pi", "npm", "node_modules", PACKAGE_NAME));
169457
- return dirs.filter((dir) => existsSync26(join22(dir, "package.json")));
169764
+ return dirs.filter((dir) => existsSync25(join22(dir, "package.json")));
169458
169765
  }
169459
169766
  function projectConfigPath(cwd) {
169460
169767
  return resolveCortexKitProjectConfigPath(cwd);
169461
169768
  }
169462
169769
  function readConfigForEmbedding(path6, isProjectConfig) {
169463
- if (!existsSync26(path6))
169770
+ if (!existsSync25(path6))
169464
169771
  return null;
169465
169772
  try {
169466
169773
  const rawText = readFileSync18(path6, "utf-8");
@@ -169494,7 +169801,7 @@ function classifyEmbeddingOutcome(outcome) {
169494
169801
  case "network_error":
169495
169802
  return {
169496
169803
  status: "fail",
169497
- message: `Embedding endpoint network error: ${outcome.message}`
169804
+ message: `Embedding endpoint network error: ${sanitizeDiagnosticText(outcome.message)}`
169498
169805
  };
169499
169806
  case "endpoint_unsupported":
169500
169807
  return {
@@ -169509,7 +169816,7 @@ function classifyEmbeddingOutcome(outcome) {
169509
169816
  case "invalid_scheme":
169510
169817
  return {
169511
169818
  status: "fail",
169512
- message: `Embedding endpoint must start with http:// or https://: ${outcome.endpoint}`
169819
+ message: `Embedding endpoint must start with http:// or https://: ${sanitizeDiagnosticEndpoint(outcome.endpoint)}`
169513
169820
  };
169514
169821
  }
169515
169822
  }
@@ -169522,11 +169829,12 @@ function countTable(db, table) {
169522
169829
  }
169523
169830
  }
169524
169831
  function cacheRoots() {
169525
- const home = homedir15();
169526
- const cacheHome = process.env.XDG_CACHE_HOME || join22(home, ".cache");
169832
+ const home = process.env.HOME?.trim();
169833
+ const cacheHome = process.env.XDG_CACHE_HOME || join22(home || homedir14(), ".cache");
169834
+ const piCacheRoot = getPiCacheRoot();
169527
169835
  return [
169528
- join22(home, ".pi", "cache", "extensions"),
169529
- join22(home, ".pi", "cache", "packages"),
169836
+ join22(piCacheRoot, "extensions"),
169837
+ join22(piCacheRoot, "packages"),
169530
169838
  join22(cacheHome, "pi", "extensions"),
169531
169839
  join22(cacheHome, "pi", "packages"),
169532
169840
  join22(getPiAgentConfigDir(), "cache", "extensions")
@@ -169535,7 +169843,7 @@ function cacheRoots() {
169535
169843
  function findPiMagicContextCacheDirs(self, force = false) {
169536
169844
  const found = new Map;
169537
169845
  const visit = (path6, depth) => {
169538
- if (depth < 0 || !existsSync26(path6))
169846
+ if (depth < 0 || !existsSync25(path6))
169539
169847
  return;
169540
169848
  let stat;
169541
169849
  try {
@@ -169546,7 +169854,7 @@ function findPiMagicContextCacheDirs(self, force = false) {
169546
169854
  if (!stat.isDirectory())
169547
169855
  return;
169548
169856
  const packageJson = join22(path6, "package.json");
169549
- if (existsSync26(packageJson)) {
169857
+ if (existsSync25(packageJson)) {
169550
169858
  try {
169551
169859
  const pkg = JSON.parse(readFileSync18(packageJson, "utf-8"));
169552
169860
  const name2 = typeof pkg.name === "string" ? pkg.name : "";
@@ -169581,7 +169889,7 @@ async function runHealthChecks(options) {
169581
169889
  writeUserConfig: false,
169582
169890
  clearCachePaths: []
169583
169891
  };
169584
- const self = selfVersion();
169892
+ const self = options.deps.selfVersion();
169585
169893
  const pi = options.deps.detectPiBinary();
169586
169894
  if (!pi) {
169587
169895
  add(results, "fail", "Pi binary not found on PATH or at ~/.pi/bin/pi");
@@ -169596,16 +169904,19 @@ async function runHealthChecks(options) {
169596
169904
  }
169597
169905
  }
169598
169906
  const latest = options.deps.getLatestNpmVersion();
169599
- if (latest && compareSemver(self, latest) === -1) {
169907
+ const latestCompare = latest ? compareSemver(self, latest) : null;
169908
+ if (latest && latestCompare === -1) {
169600
169909
  add(results, "warn", `Magic Context for Pi CLI v${self} is older than npm latest v${latest}`);
169601
- } else if (latest) {
169910
+ } else if (latest && latestCompare !== null) {
169602
169911
  add(results, "pass", `Magic Context for Pi CLI v${self} is current (npm latest v${latest})`);
169912
+ } else if (latest) {
169913
+ add(results, "info", `Magic Context for Pi CLI version unknown; npm latest is v${latest}`);
169603
169914
  } else {
169604
169915
  add(results, "info", `Magic Context for Pi CLI v${self}; npm latest check unavailable`);
169605
169916
  }
169606
169917
  const settingsPath = getPiUserExtensionsPath();
169607
169918
  let packages = [];
169608
- if (!existsSync26(settingsPath)) {
169919
+ if (!existsSync25(settingsPath)) {
169609
169920
  add(results, "warn", `Pi settings not found at ${settingsPath}`);
169610
169921
  repairPlan.addPackageEntry = true;
169611
169922
  } else {
@@ -169629,7 +169940,7 @@ async function runHealthChecks(options) {
169629
169940
  ["user", userConfigPath, true],
169630
169941
  ["project", projectPath, false]
169631
169942
  ]) {
169632
- if (!existsSync26(path6)) {
169943
+ if (!existsSync25(path6)) {
169633
169944
  if (required2) {
169634
169945
  add(results, "warn", `No ${label} magic-context.jsonc found at ${path6}`);
169635
169946
  if (userConfigMigrationRefused) {
@@ -169667,7 +169978,7 @@ async function runHealthChecks(options) {
169667
169978
  }
169668
169979
  const storageDir = getMagicContextStorageDir();
169669
169980
  const dbPath = join22(storageDir, "context.db");
169670
- const existedBeforeOpen = existsSync26(dbPath);
169981
+ const existedBeforeOpen = existsSync25(dbPath);
169671
169982
  if (existedBeforeOpen)
169672
169983
  add(results, "pass", `Shared context DB exists at ${dbPath}`);
169673
169984
  else
@@ -169731,7 +170042,7 @@ async function runHealthChecks(options) {
169731
170042
  const classified = classifyEmbeddingOutcome(outcome);
169732
170043
  add(results, classified.status, classified.message);
169733
170044
  } catch (error51) {
169734
- add(results, "fail", `Embedding probe threw: ${error51 instanceof Error ? error51.message : String(error51)}`);
170045
+ add(results, "fail", `Embedding probe threw: ${sanitizeDiagnosticText(error51 instanceof Error ? error51.message : String(error51))}`);
169735
170046
  }
169736
170047
  }
169737
170048
  } else if (loadedConfig.config.embedding.provider === "off") {
@@ -169775,7 +170086,7 @@ async function runHealthChecks(options) {
169775
170086
  add(results, "pass", "Pi extension cache clean (no stale cached package found)");
169776
170087
  }
169777
170088
  const logPath = getMagicContextLogPath2("pi");
169778
- if (existsSync26(logPath)) {
170089
+ if (existsSync25(logPath)) {
169779
170090
  const stat = statSync10(logPath);
169780
170091
  const sizeKb = (stat.size / 1024).toFixed(0);
169781
170092
  const lines = readFileSync18(logPath, "utf-8").split(/\r?\n/).map((line) => line.trim()).filter(Boolean);
@@ -169813,7 +170124,7 @@ async function runHealthChecks(options) {
169813
170124
  return { results, repairPlan, ...summarize(results) };
169814
170125
  }
169815
170126
  function writeDefaultMagicContextConfig(path6) {
169816
- mkdirSync9(dirname12(path6), { recursive: true });
170127
+ mkdirSync8(dirname13(path6), { recursive: true });
169817
170128
  const config2 = {
169818
170129
  $schema: "https://raw.githubusercontent.com/cortexkit/magic-context/master/assets/magic-context.schema.json",
169819
170130
  ...MagicContextConfigSchema.parse({})
@@ -169835,7 +170146,7 @@ function repair(plan, prompts) {
169835
170146
  }
169836
170147
  if (plan.writeUserConfig) {
169837
170148
  const configPath = getPiUserConfigPath();
169838
- if (!existsSync26(configPath)) {
170149
+ if (!existsSync25(configPath)) {
169839
170150
  try {
169840
170151
  writeDefaultMagicContextConfig(configPath);
169841
170152
  prompts.log.success(`Wrote default Magic Context config to ${configPath}`);
@@ -170038,6 +170349,7 @@ var init_doctor_pi = __esm(async () => {
170038
170349
  detectPiBinary,
170039
170350
  getPiVersion,
170040
170351
  getLatestNpmVersion: () => getLatestNpmVersion(PACKAGE_NAME),
170352
+ selfVersion,
170041
170353
  probeEmbeddingEndpoint,
170042
170354
  openDatabase,
170043
170355
  isDatabasePersisted,
@@ -170053,7 +170365,7 @@ var exports_doctor = {};
170053
170365
  __export(exports_doctor, {
170054
170366
  runDoctor: () => runDoctor3
170055
170367
  });
170056
- import { existsSync as existsSync27, rmSync as rmSync4 } from "node:fs";
170368
+ import { existsSync as existsSync26, rmSync as rmSync4 } from "node:fs";
170057
170369
  async function runDoctor3(options) {
170058
170370
  if (options.clear)
170059
170371
  return runClear();
@@ -170142,7 +170454,7 @@ async function runClear() {
170142
170454
  const s = spinner2();
170143
170455
  s.start(`Clearing ${item.path}`);
170144
170456
  try {
170145
- if (existsSync27(item.path)) {
170457
+ if (existsSync26(item.path)) {
170146
170458
  rmSync4(item.path, { recursive: true, force: true });
170147
170459
  }
170148
170460
  s.stop(`Cleared ${item.path}`);