@cortexkit/magic-context 0.31.3 → 0.31.5

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 +629 -314
  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",
@@ -165628,10 +165529,332 @@ var init_magic_context = __esm(() => {
165628
165529
  });
165629
165530
  });
165630
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
+
165631
165854
  // ../plugin/src/config/variable.ts
165632
- import { existsSync as existsSync17, readFileSync as readFileSync8 } from "node:fs";
165855
+ import { existsSync as existsSync16, readFileSync as readFileSync8 } from "node:fs";
165633
165856
  import { homedir as homedir9 } from "node:os";
165634
- 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";
165635
165858
  function sensitiveFilePathReason(resolvedPath) {
165636
165859
  const home = homedir9();
165637
165860
  const sensitiveDirs = [
@@ -165678,7 +165901,7 @@ function substituteConfigVariables(input) {
165678
165901
  if (fileMatches.length === 0) {
165679
165902
  return { text: text3, warnings };
165680
165903
  }
165681
- const configDir = input.configPath ? dirname9(input.configPath) : process.cwd();
165904
+ const configDir = input.configPath ? dirname10(input.configPath) : process.cwd();
165682
165905
  let output = "";
165683
165906
  let cursor3 = 0;
165684
165907
  for (const match of fileMatches) {
@@ -165704,7 +165927,7 @@ function substituteConfigVariables(input) {
165704
165927
  if (sensitiveReason) {
165705
165928
  warnings.push(`${token} resolves to a sensitive path (${sensitiveReason}: ${filePath}); ` + "inlining its contents into config — make sure this is intentional.");
165706
165929
  }
165707
- if (!existsSync17(filePath)) {
165930
+ if (!existsSync16(filePath)) {
165708
165931
  warnings.push(`File not found for ${token} (resolved to ${filePath}); using empty string`);
165709
165932
  continue;
165710
165933
  }
@@ -165729,7 +165952,7 @@ var init_variable = __esm(() => {
165729
165952
  });
165730
165953
 
165731
165954
  // ../plugin/src/config/index.ts
165732
- import { existsSync as existsSync18, readFileSync as readFileSync9 } from "node:fs";
165955
+ import { existsSync as existsSync17, readFileSync as readFileSync9 } from "node:fs";
165733
165956
  function getUserConfigBasePath() {
165734
165957
  return cortexKitUserConfigBasePath();
165735
165958
  }
@@ -165737,10 +165960,10 @@ function getProjectConfigBasePath(directory) {
165737
165960
  return cortexKitProjectConfigBasePath(directory);
165738
165961
  }
165739
165962
  function resolveLegacyReadFallback(sources) {
165740
- return { source: sources.find((s) => existsSync18(s.path)) ?? null };
165963
+ return { source: sources.find((s) => existsSync17(s.path)) ?? null };
165741
165964
  }
165742
165965
  function loadConfigFileDetailed(configPath, source) {
165743
- if (!existsSync18(configPath)) {
165966
+ if (!existsSync17(configPath)) {
165744
165967
  return null;
165745
165968
  }
165746
165969
  let rawText;
@@ -165955,12 +166178,13 @@ function loadPluginConfigDetailed(directory) {
165955
166178
  const harnessLegacy = resolveLegacyConfigSourcesForHarness(directory, "opencode");
165956
166179
  const userLegacyFallback = userDetected.format === "none" ? resolveLegacyReadFallback(harnessLegacy.user) : { source: null };
165957
166180
  const projectLegacyFallback = projectDetected.format === "none" ? resolveLegacyReadFallback(harnessLegacy.project) : { source: null };
165958
- const legacyUserUnmigrated = userDetected.format === "none" && !userLegacyFallback.source && legacySources.user.some((source) => existsSync18(source.path));
165959
- 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));
165960
166183
  const userLoaded = userDetected.format !== "none" ? loadConfigFileDetailed(userDetected.path, "user") : userLegacyFallback.source ? loadConfigFileDetailed(userLegacyFallback.source.path, "user") : null;
165961
166184
  const projectLoaded = projectDetected.format !== "none" ? loadConfigFileDetailed(projectDetected.path, "project") : projectLegacyFallback.source ? loadConfigFileDetailed(projectLegacyFallback.source.path, "project") : null;
165962
166185
  const allWarnings = [];
165963
166186
  let mergedRaw = {};
166187
+ const trustedBaseConfig = parsePluginConfig(userLoaded?.config ?? {});
165964
166188
  if (userLegacyFallback.source) {
165965
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.`);
165966
166190
  } else if (legacyUserUnmigrated) {
@@ -165985,6 +166209,13 @@ function loadPluginConfigDetailed(directory) {
165985
166209
  for (const warning of dropInheritedEmbeddingKeyOnRedirect(projectRaw, mergedRaw, userLoaded?.config)) {
165986
166210
  allWarnings.push(`[project config] ${warning}`);
165987
166211
  }
166212
+ for (const warning of constrainProjectThresholdOverrides({
166213
+ mergedRaw,
166214
+ projectRaw,
166215
+ trustedBaseConfig
166216
+ })) {
166217
+ allWarnings.push(`[project config] ${warning}`);
166218
+ }
165988
166219
  }
165989
166220
  const recoveredTopLevelKeys = [];
165990
166221
  const config2 = parsePluginConfig(mergedRaw, recoveredTopLevelKeys);
@@ -166141,14 +166372,14 @@ var DEFAULT_TIMEOUT_MS = 1e4, MAX_PREVIEW_CHARS = 240;
166141
166372
  // ../plugin/src/shared/tui-config.ts
166142
166373
  import {
166143
166374
  chmodSync as chmodSync3,
166144
- existsSync as existsSync19,
166145
- mkdirSync as mkdirSync8,
166375
+ existsSync as existsSync18,
166376
+ mkdirSync as mkdirSync7,
166146
166377
  readFileSync as readFileSync10,
166147
166378
  renameSync as renameSync3,
166148
166379
  statSync as statSync6,
166149
- writeFileSync as writeFileSync5
166380
+ writeFileSync as writeFileSync4
166150
166381
  } from "node:fs";
166151
- import { dirname as dirname10, join as join15 } from "node:path";
166382
+ import { dirname as dirname11, join as join15 } from "node:path";
166152
166383
  function pluginEntryId(entry) {
166153
166384
  if (typeof entry === "string")
166154
166385
  return entry;
@@ -166179,7 +166410,7 @@ function writeTuiConfigAtomic(configPath, config2) {
166179
166410
  const body = `${import_comment_json6.stringify(config2, null, 2)}
166180
166411
  `;
166181
166412
  const tmpPath = `${configPath}.tmp`;
166182
- writeFileSync5(tmpPath, body);
166413
+ writeFileSync4(tmpPath, body);
166183
166414
  try {
166184
166415
  if (statSync6(configPath, { throwIfNoEntry: false })?.isFile()) {
166185
166416
  chmodSync3(tmpPath, statSync6(configPath).mode & 511);
@@ -166191,9 +166422,9 @@ function resolveTuiConfigPath() {
166191
166422
  const configDir = getOpenCodeConfigPaths({ binary: "opencode" }).configDir;
166192
166423
  const jsoncPath = join15(configDir, "tui.jsonc");
166193
166424
  const jsonPath = join15(configDir, "tui.json");
166194
- if (existsSync19(jsoncPath))
166425
+ if (existsSync18(jsoncPath))
166195
166426
  return jsoncPath;
166196
- if (existsSync19(jsonPath))
166427
+ if (existsSync18(jsonPath))
166197
166428
  return jsonPath;
166198
166429
  return jsoncPath;
166199
166430
  }
@@ -166201,7 +166432,7 @@ function ensureTuiPluginEntry() {
166201
166432
  try {
166202
166433
  const configPath = resolveTuiConfigPath();
166203
166434
  let config2 = {};
166204
- if (existsSync19(configPath)) {
166435
+ if (existsSync18(configPath)) {
166205
166436
  const raw = readFileSync10(configPath, "utf-8");
166206
166437
  config2 = import_comment_json6.parse(raw) ?? {};
166207
166438
  }
@@ -166236,7 +166467,7 @@ function ensureTuiPluginEntry() {
166236
166467
  }
166237
166468
  }
166238
166469
  config2.plugin = plugins;
166239
- mkdirSync8(dirname10(configPath), { recursive: true });
166470
+ mkdirSync7(dirname11(configPath), { recursive: true });
166240
166471
  writeTuiConfigAtomic(configPath, config2);
166241
166472
  log3(`[magic-context] updated TUI plugin entry in ${configPath}`);
166242
166473
  return true;
@@ -166491,6 +166722,8 @@ function sanitizeDiagnosticText(value) {
166491
166722
  return redactSecretText(sanitizePathString(value));
166492
166723
  }
166493
166724
  function sanitizeConfigValue(value, keyPath = []) {
166725
+ if (value === null || typeof value === "number" || typeof value === "boolean")
166726
+ return value;
166494
166727
  const key = keyPath.at(-1) ?? "";
166495
166728
  if (key && isSecretKey(key)) {
166496
166729
  return `<REDACTED:${redactionTypeForKey(key)}>`;
@@ -166596,12 +166829,29 @@ var init_redaction = __esm(() => {
166596
166829
  });
166597
166830
 
166598
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
+ }
166599
166849
  var init_redaction2 = __esm(() => {
166600
166850
  init_redaction();
166601
166851
  });
166602
166852
 
166603
166853
  // src/lib/diagnostics-opencode.ts
166604
- 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";
166605
166855
  import { createRequire as createRequire2 } from "node:module";
166606
166856
  import { homedir as homedir11 } from "node:os";
166607
166857
  import { join as join16 } from "node:path";
@@ -166622,7 +166872,7 @@ function getPluginCacheInfo() {
166622
166872
  let cached2;
166623
166873
  for (const installedPkgPath of getOpenCodePluginPackageJsonPaths()) {
166624
166874
  try {
166625
- if (existsSync20(installedPkgPath)) {
166875
+ if (existsSync19(installedPkgPath)) {
166626
166876
  const pkg = JSON.parse(readFileSync11(installedPkgPath, "utf-8"));
166627
166877
  cached2 = typeof pkg.version === "string" ? pkg.version : undefined;
166628
166878
  if (cached2)
@@ -166640,7 +166890,7 @@ function getStorageDir() {
166640
166890
  }
166641
166891
  function fileSize(path6) {
166642
166892
  try {
166643
- return existsSync20(path6) ? statSync7(path6).size : 0;
166893
+ return existsSync19(path6) ? statSync7(path6).size : 0;
166644
166894
  } catch {
166645
166895
  return 0;
166646
166896
  }
@@ -166652,7 +166902,7 @@ function sanitizeValue(value) {
166652
166902
  return sanitizeConfigValue(value);
166653
166903
  }
166654
166904
  function readConfig2(path6) {
166655
- if (!existsSync20(path6))
166905
+ if (!existsSync19(path6))
166656
166906
  return { value: null };
166657
166907
  try {
166658
166908
  const raw = readFileSync11(path6, "utf-8");
@@ -166713,7 +166963,7 @@ function parseHistorianDumpMeta(path6) {
166713
166963
  }
166714
166964
  }
166715
166965
  function listDumpsInDir(dir, limit) {
166716
- if (!existsSync20(dir))
166966
+ if (!existsSync19(dir))
166717
166967
  return { count: 0, recent: [] };
166718
166968
  try {
166719
166969
  const entries = readdirSync2(dir).filter((name2) => name2.endsWith(".xml")).map((name2) => {
@@ -166783,7 +167033,7 @@ function collectHistorianDumps(recentSessions) {
166783
167033
  async function collectRecentSessions() {
166784
167034
  const dataHome = process.env.XDG_DATA_HOME || join16(process.env.HOME || homedir11(), ".local", "share");
166785
167035
  const opencodeDbPath = join16(dataHome, "opencode", "opencode.db");
166786
- if (!existsSync20(opencodeDbPath))
167036
+ if (!existsSync19(opencodeDbPath))
166787
167037
  return [];
166788
167038
  if (typeof globalThis.Bun === "undefined") {
166789
167039
  return [];
@@ -166818,7 +167068,7 @@ async function collectRecentSessions() {
166818
167068
  }
166819
167069
  async function collectHistorianFailures(storageDirPath) {
166820
167070
  const contextDbPath = join16(storageDirPath, "context.db");
166821
- if (!existsSync20(contextDbPath))
167071
+ if (!existsSync19(contextDbPath))
166822
167072
  return [];
166823
167073
  if (typeof globalThis.Bun === "undefined") {
166824
167074
  return [];
@@ -166852,7 +167102,7 @@ async function collectHistorianFailures(storageDirPath) {
166852
167102
  }
166853
167103
  async function collectHistorianRuns(storageDirPath) {
166854
167104
  const contextDbPath = join16(storageDirPath, "context.db");
166855
- if (!existsSync20(contextDbPath))
167105
+ if (!existsSync19(contextDbPath))
166856
167106
  return [];
166857
167107
  if (typeof globalThis.Bun === "undefined")
166858
167108
  return [];
@@ -166923,7 +167173,7 @@ async function collectDiagnostics() {
166923
167173
  const storageDirPath = getStorageDir();
166924
167174
  const contextDbPath = join16(storageDirPath, "context.db");
166925
167175
  const logPath = getMagicContextLogPath2("opencode");
166926
- const logFileSize = existsSync20(logPath) ? statSync7(logPath).size : 0;
167176
+ const logFileSize = existsSync19(logPath) ? statSync7(logPath).size : 0;
166927
167177
  const conflictResult = detectConflicts(process.cwd());
166928
167178
  const recentSessions = await collectRecentSessions();
166929
167179
  const openCodeDetection = detectOpenCode();
@@ -166942,14 +167192,14 @@ async function collectDiagnostics() {
166942
167192
  opencodeConfigHasPlugin: configHasPluginEntry(opencodeConfig.value),
166943
167193
  tuiConfigHasPlugin: configHasPluginEntry(tuiConfig.value),
166944
167194
  magicContextConfig: {
166945
- exists: existsSync20(configPaths.magicContextConfig),
167195
+ exists: existsSync19(configPaths.magicContextConfig),
166946
167196
  ...magicContextConfig.error ? { parseError: magicContextConfig.error } : {},
166947
167197
  flags: sanitizeValue(magicContextConfig.value ?? {}) ?? {}
166948
167198
  },
166949
167199
  pluginCache: getPluginCacheInfo(),
166950
167200
  storageDir: {
166951
167201
  path: storageDirPath,
166952
- exists: existsSync20(storageDirPath),
167202
+ exists: existsSync19(storageDirPath),
166953
167203
  contextDbSizeBytes: fileSize(contextDbPath)
166954
167204
  },
166955
167205
  conflicts: {
@@ -166958,7 +167208,7 @@ async function collectDiagnostics() {
166958
167208
  },
166959
167209
  logFile: {
166960
167210
  path: logPath,
166961
- exists: existsSync20(logPath),
167211
+ exists: existsSync19(logPath),
166962
167212
  sizeKb: Math.round(logFileSize / 1024)
166963
167213
  },
166964
167214
  recentSessions,
@@ -167012,7 +167262,7 @@ function renderDiagnosticsMarkdown(report) {
167012
167262
  };
167013
167263
  const recentSessions = report.recentSessions.map((session) => ({
167014
167264
  sessionId: session.sessionId,
167015
- title: session.title,
167265
+ title: sanitizeDiagnosticText(session.title),
167016
167266
  directory: sanitizeString(session.directory),
167017
167267
  lastActiveAt: session.lastActiveAt
167018
167268
  }));
@@ -167098,9 +167348,9 @@ var init_diagnostics_opencode = __esm(() => {
167098
167348
 
167099
167349
  // src/lib/embedding-runtime.ts
167100
167350
  import { spawnSync as spawnSync2 } from "node:child_process";
167101
- import { existsSync as existsSync21 } from "node:fs";
167351
+ import { existsSync as existsSync20 } from "node:fs";
167102
167352
  import { createRequire as createRequire3 } from "node:module";
167103
- import { dirname as dirname11, join as join17, sep } from "node:path";
167353
+ import { dirname as dirname12, join as join17, sep } from "node:path";
167104
167354
  function describeError(error51) {
167105
167355
  const message = error51 instanceof Error ? error51.message : String(error51 ?? "unknown error");
167106
167356
  const code = error51?.code;
@@ -167213,7 +167463,7 @@ function expectedBinaryRelPath(platform, arch) {
167213
167463
  }
167214
167464
  function checkLocalEmbeddingRuntimeAt(installRoot, platform = process.platform, arch = process.arch) {
167215
167465
  const packageDir = join17(installRoot, "node_modules", "onnxruntime-node");
167216
- if (!existsSync21(join17(packageDir, "package.json"))) {
167466
+ if (!existsSync20(join17(packageDir, "package.json"))) {
167217
167467
  return { state: "package-missing", packageDir };
167218
167468
  }
167219
167469
  const rel = expectedBinaryRelPath(platform, arch);
@@ -167221,13 +167471,13 @@ function checkLocalEmbeddingRuntimeAt(installRoot, platform = process.platform,
167221
167471
  return probeOnnxRuntimeNodeLoad(packageDir) ?? { state: "ok", binaryPath: packageDir };
167222
167472
  }
167223
167473
  const binaryPath = join17(packageDir, rel);
167224
- if (!existsSync21(binaryPath)) {
167474
+ if (!existsSync20(binaryPath)) {
167225
167475
  return { state: "binary-missing", packageDir, expectedBinary: binaryPath };
167226
167476
  }
167227
167477
  return probeOnnxRuntimeNodeLoad(packageDir) ?? { state: "ok", binaryPath };
167228
167478
  }
167229
167479
  function checkLocalEmbeddingRuntime(installRoots, platform = process.platform, arch = process.arch) {
167230
- const existing = installRoots.filter((root) => existsSync21(root));
167480
+ const existing = installRoots.filter((root) => existsSync20(root));
167231
167481
  if (existing.length === 0) {
167232
167482
  return {
167233
167483
  state: "unknown",
@@ -167247,10 +167497,10 @@ function checkLocalEmbeddingRuntime(installRoots, platform = process.platform, a
167247
167497
  function packageDirFromResolved(resolvedPath, packageName) {
167248
167498
  const marker = `node_modules${sep}${packageName.split("/").join(sep)}`;
167249
167499
  const idx = resolvedPath.indexOf(marker);
167250
- return idx >= 0 ? resolvedPath.slice(0, idx + marker.length) : dirname11(resolvedPath);
167500
+ return idx >= 0 ? resolvedPath.slice(0, idx + marker.length) : dirname12(resolvedPath);
167251
167501
  }
167252
167502
  function checkLocalEmbeddingRuntimeByResolution(pluginDir, platform = process.platform, arch = process.arch) {
167253
- if (!existsSync21(join17(pluginDir, "package.json"))) {
167503
+ if (!existsSync20(join17(pluginDir, "package.json"))) {
167254
167504
  return { state: "unknown", reason: "plugin package dir not found" };
167255
167505
  }
167256
167506
  let onnxDir = null;
@@ -167286,7 +167536,7 @@ function checkLocalEmbeddingRuntimeByResolution(pluginDir, platform = process.pl
167286
167536
  return probeOnnxRuntimeNodeLoad(onnxDir) ?? { state: "ok", binaryPath: onnxDir };
167287
167537
  }
167288
167538
  const binaryPath = join17(onnxDir, rel);
167289
- if (!existsSync21(binaryPath)) {
167539
+ if (!existsSync20(binaryPath)) {
167290
167540
  return { state: "binary-missing", packageDir: onnxDir, expectedBinary: binaryPath };
167291
167541
  }
167292
167542
  return probeOnnxRuntimeNodeLoad(onnxDir) ?? { state: "ok", binaryPath };
@@ -167332,33 +167582,30 @@ function extractRecentErrors(sanitized, limit = 20) {
167332
167582
  function capBodyToGithubLimit(body, maxBytes = MAX_GITHUB_BODY_BYTES) {
167333
167583
  if (Buffer.byteLength(body, "utf8") <= maxBytes)
167334
167584
  return body;
167585
+ let capped = body;
167335
167586
  const heading = "## Log (last";
167336
167587
  const headingIdx = body.indexOf(heading);
167337
167588
  if (headingIdx === -1) {
167338
- const marker = `
167339
-
167340
- [truncated for GitHub 64KB limit]
167341
- `;
167342
- const markerBytes2 = Buffer.byteLength(marker, "utf8");
167343
- 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);
167344
167592
  }
167345
167593
  const fenceOpenIdx = body.indexOf("\n```", headingIdx);
167346
167594
  if (fenceOpenIdx === -1)
167347
- return body;
167595
+ return enforceFinalBodyLimit(body, maxBytes);
167348
167596
  const logStart = fenceOpenIdx + "\n```\n".length;
167349
167597
  const fenceCloseIdx = body.indexOf("\n```", logStart);
167350
167598
  if (fenceCloseIdx === -1)
167351
- return body;
167599
+ return enforceFinalBodyLimit(body, maxBytes);
167352
167600
  const head = body.slice(0, logStart);
167353
167601
  const log4 = body.slice(logStart, fenceCloseIdx);
167354
167602
  const tail = body.slice(fenceCloseIdx);
167355
167603
  const overheadBytes = Buffer.byteLength(head, "utf8") + Buffer.byteLength(tail, "utf8");
167356
- const truncationMarker = `[truncated for GitHub 64KB limit — older log lines dropped]
167357
- `;
167358
- const markerBytes = Buffer.byteLength(truncationMarker, "utf8");
167604
+ const markerBytes = Buffer.byteLength(LOG_TRUNCATION_MARKER, "utf8");
167359
167605
  const logBudget = maxBytes - overheadBytes - markerBytes;
167360
167606
  if (logBudget <= 0) {
167361
- return `${head}${truncationMarker}${tail}`;
167607
+ capped = `${head}${LOG_TRUNCATION_MARKER}${tail}`;
167608
+ return enforceFinalBodyLimit(capped, maxBytes);
167362
167609
  }
167363
167610
  const lines = log4.split(`
167364
167611
  `);
@@ -167374,7 +167621,17 @@ function capBodyToGithubLimit(body, maxBytes = MAX_GITHUB_BODY_BYTES) {
167374
167621
  if (Buffer.byteLength(kept, "utf8") > logBudget) {
167375
167622
  kept = truncateToByteBudget(kept, logBudget);
167376
167623
  }
167377
- 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;
167378
167635
  }
167379
167636
  function truncateToByteBudget(input, maxBytes) {
167380
167637
  if (maxBytes <= 0)
@@ -167388,7 +167645,14 @@ function truncateToByteBudget(input, maxBytes) {
167388
167645
  }
167389
167646
  return buf.subarray(0, end).toString("utf8");
167390
167647
  }
167391
- 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;
167392
167656
  var init_issue_body = __esm(() => {
167393
167657
  ERROR_LOG_PATTERNS = [
167394
167658
  /\bfailed:/i,
@@ -167401,8 +167665,7 @@ var init_issue_body = __esm(() => {
167401
167665
  });
167402
167666
 
167403
167667
  // src/lib/logs-opencode.ts
167404
- import { readFileSync as readFileSync12, writeFileSync as writeFileSync6 } from "node:fs";
167405
- import { homedir as homedir12 } from "node:os";
167668
+ import { readFileSync as readFileSync12, writeFileSync as writeFileSync5 } from "node:fs";
167406
167669
  import { join as join18 } from "node:path";
167407
167670
  function sanitizeLogContent(content) {
167408
167671
  return sanitizeDiagnosticText(content);
@@ -167443,7 +167706,7 @@ function filterLogLinesBySession(lines, sessionId) {
167443
167706
  return matches.every((id) => id === sessionId);
167444
167707
  });
167445
167708
  }
167446
- async function bundleIssueReport(report, description, _title, sessionFilter = null) {
167709
+ async function bundleIssueReport(report, description, title, sessionFilter = null) {
167447
167710
  const LOG_TAIL_LINES = 400;
167448
167711
  const allLogLines = report.logFile.exists ? readFileSync12(report.logFile.path, "utf-8").split(/\r?\n/) : [];
167449
167712
  const logLines = filterLogLinesBySession(allLogLines, sessionFilter);
@@ -167456,10 +167719,13 @@ async function bundleIssueReport(report, description, _title, sessionFilter = nu
167456
167719
  `));
167457
167720
  const recentErrorLines = extractRecentErrors(errorScanWindow, 20);
167458
167721
  const configBody = JSON.stringify(sanitizeConfigValue(report.magicContextConfig.flags), null, 2);
167459
- 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();
167460
167725
  const rawBodyMarkdown = [
167726
+ ...sanitizedTitle ? ["## Title", sanitizedTitle, ""] : [],
167461
167727
  "## Description",
167462
- description,
167728
+ sanitizedDescription,
167463
167729
  "",
167464
167730
  "## Environment",
167465
167731
  `- Plugin: v${report.pluginVersion}`,
@@ -167494,7 +167760,7 @@ async function bundleIssueReport(report, description, _title, sessionFilter = nu
167494
167760
  `);
167495
167761
  const bodyMarkdown = capBodyToGithubLimit(rawBodyMarkdown);
167496
167762
  const path6 = join18(process.cwd(), `magic-context-issue-${formatTimestamp(new Date)}.md`);
167497
- writeFileSync6(path6, `${bodyMarkdown}
167763
+ writeFileSync5(path6, `${bodyMarkdown}
167498
167764
  `);
167499
167765
  return { path: path6, bodyMarkdown };
167500
167766
  }
@@ -167757,11 +168023,11 @@ function migrateExperimentalPinKeyFilesForDoctor(mcConfig) {
167757
168023
  }
167758
168024
 
167759
168025
  // src/commands/doctor-opencode-cache.ts
167760
- 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";
167761
168027
  function readCachedPluginVersion(pluginCacheDir) {
167762
168028
  try {
167763
168029
  const installedPkgPath = getOpenCodePluginPackageJsonPath(pluginCacheDir);
167764
- if (!existsSync22(installedPkgPath))
168030
+ if (!existsSync21(installedPkgPath))
167765
168031
  return;
167766
168032
  const pkg = JSON.parse(readFileSync13(installedPkgPath, "utf-8"));
167767
168033
  return typeof pkg.version === "string" ? pkg.version : undefined;
@@ -167772,7 +168038,7 @@ function readCachedPluginVersion(pluginCacheDir) {
167772
168038
  async function clearPluginCache(options = {}, deps = {}) {
167773
168039
  const remove = deps.remove ?? ((path6) => rmSync2(path6, { recursive: true, force: true }));
167774
168040
  const pluginCacheRoots = getOpenCodePluginCacheRoots();
167775
- const existingRoots = pluginCacheRoots.filter((root) => existsSync22(root));
168041
+ const existingRoots = pluginCacheRoots.filter((root) => existsSync21(root));
167776
168042
  if (existingRoots.length === 0) {
167777
168043
  return { action: "not_found", path: pluginCacheRoots[0] ?? "" };
167778
168044
  }
@@ -167820,6 +168086,8 @@ async function clearPluginCache(options = {}, deps = {}) {
167820
168086
  action: "error",
167821
168087
  path: firstFailure?.path ?? clearTargets[0]?.path ?? existingRoots[0] ?? "",
167822
168088
  paths: failed.map((entry) => entry.path),
168089
+ clearedPaths: cleared.map((entry) => entry.path),
168090
+ failedPaths: failed.map((entry) => entry.path),
167823
168091
  error: firstFailure?.error
167824
168092
  };
167825
168093
  }
@@ -167838,9 +168106,9 @@ var init_doctor_opencode_cache = __esm(() => {
167838
168106
 
167839
168107
  // src/commands/doctor-opencode.ts
167840
168108
  import { execSync as execSync2, spawnSync as spawnSync3 } from "node:child_process";
167841
- 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";
167842
168110
  import { createRequire as createRequire4 } from "node:module";
167843
- import { homedir as homedir13 } from "node:os";
168111
+ import { homedir as homedir12 } from "node:os";
167844
168112
  import { join as join19 } from "node:path";
167845
168113
  function migrateLegacyAgentEnabledConfigForDoctor(mcConfig, logs) {
167846
168114
  let changed = false;
@@ -167879,6 +168147,17 @@ function migrateLegacyAgentEnabledConfigForDoctor(mcConfig, logs) {
167879
168147
  migrateLegacyAgentEnabled("historian");
167880
168148
  return { changed, fixes };
167881
168149
  }
168150
+ function checkUserMemoriesDreamerCompatibility(mcConfig) {
168151
+ const dreamerObj = mcConfig?.dreamer;
168152
+ if (dreamerObj?.disable !== true)
168153
+ return null;
168154
+ const tasksObj = dreamerObj.tasks;
168155
+ const reviewTask = tasksObj?.["review-user-memories"];
168156
+ const schedule = reviewTask?.schedule;
168157
+ if (typeof schedule !== "string" || schedule.trim() === "")
168158
+ return null;
168159
+ return 'dreamer.tasks["review-user-memories"] is scheduled but dreamer.disable=true, so new promotions will not run. Remove dreamer.disable or set dreamer.tasks["review-user-memories"].schedule="" to disable the task.';
168160
+ }
167882
168161
  async function fetchNpmLatest(pkg, timeoutMs = 5000) {
167883
168162
  try {
167884
168163
  const controller = new AbortController;
@@ -167910,6 +168189,38 @@ function getSelfVersion2() {
167910
168189
  }
167911
168190
  return "0.0.0";
167912
168191
  }
168192
+ function isPinnedOpenCodePluginSpecifier(specifier) {
168193
+ if (specifier === OPENCODE_PLUGIN_NAME || specifier === OPENCODE_PLUGIN_ENTRY_WITH_VERSION)
168194
+ return false;
168195
+ return specifier.startsWith(`${OPENCODE_PLUGIN_NAME}@`);
168196
+ }
168197
+ function getUserNpmrcPath() {
168198
+ const custom2 = process.env.NPM_CONFIG_USERCONFIG?.trim();
168199
+ if (custom2)
168200
+ return custom2;
168201
+ const home = process.env.HOME?.trim();
168202
+ return join19(home || homedir12(), ".npmrc");
168203
+ }
168204
+ function collectNpmReleaseAgeWarnings() {
168205
+ const ageWarnings = [];
168206
+ const npmrcPath = getUserNpmrcPath();
168207
+ if (!existsSync22(npmrcPath))
168208
+ return ageWarnings;
168209
+ try {
168210
+ const npmrc = readFileSync14(npmrcPath, "utf-8");
168211
+ for (const line of npmrc.split(`
168212
+ `)) {
168213
+ const trimmed = line.trim();
168214
+ if (trimmed.startsWith("#") || trimmed.startsWith(";"))
168215
+ continue;
168216
+ const [key] = trimmed.split("=").map((s) => s.trim());
168217
+ if (key === "min-release-age" || key === "before") {
168218
+ ageWarnings.push(`${sanitizePathString(npmrcPath)} has '${sanitizeDiagnosticText(trimmed)}'`);
168219
+ }
168220
+ }
168221
+ } catch {}
168222
+ return ageWarnings;
168223
+ }
167913
168224
  function compareVersions(a3, b2) {
167914
168225
  const pa = a3.split(/[.-]/).map((s) => Number.parseInt(s, 10));
167915
168226
  const pb = b2.split(/[.-]/).map((s) => Number.parseInt(s, 10));
@@ -168031,7 +168342,7 @@ function checkLocalEmbeddingRuntimeForDoctor() {
168031
168342
  return { issues: 0 };
168032
168343
  }
168033
168344
  async function checkEmbeddingConfig(magicContextConfigPath) {
168034
- if (!existsSync23(magicContextConfigPath)) {
168345
+ if (!existsSync22(magicContextConfigPath)) {
168035
168346
  return checkLocalEmbeddingRuntimeForDoctor();
168036
168347
  }
168037
168348
  let rawText;
@@ -168094,7 +168405,7 @@ async function checkEmbeddingConfig(magicContextConfigPath) {
168094
168405
  }
168095
168406
  }
168096
168407
  const probeSpinner = spinner2();
168097
- probeSpinner.start(`Testing embedding endpoint ${endpoint} (model: ${model})`);
168408
+ probeSpinner.start(`Testing embedding endpoint ${sanitizeDiagnosticEndpoint(endpoint)} (model: ${sanitizeDiagnosticText(model)})`);
168098
168409
  let outcome;
168099
168410
  try {
168100
168411
  outcome = await probeEmbeddingEndpoint({
@@ -168107,7 +168418,7 @@ async function checkEmbeddingConfig(magicContextConfigPath) {
168107
168418
  });
168108
168419
  } catch (error51) {
168109
168420
  probeSpinner.stop("Embedding probe failed unexpectedly");
168110
- log2.error(`Probe threw: ${error51 instanceof Error ? error51.message : String(error51)}`);
168421
+ log2.error(`Probe threw: ${sanitizeDiagnosticText(error51 instanceof Error ? error51.message : String(error51))}`);
168111
168422
  return { issues: localIssues + 1 };
168112
168423
  }
168113
168424
  probeSpinner.stop("Embedding endpoint probed");
@@ -168118,28 +168429,28 @@ async function checkEmbeddingConfig(magicContextConfigPath) {
168118
168429
  case "auth_failed":
168119
168430
  log2.error(`Embedding endpoint rejected credentials (${outcome.status}) — check api_key / env var`);
168120
168431
  if (outcome.preview)
168121
- log2.info(` ${outcome.preview}`);
168432
+ log2.info(` ${sanitizeDiagnosticText(outcome.preview)}`);
168122
168433
  return { issues: localIssues + 1 };
168123
168434
  case "endpoint_unsupported":
168124
168435
  log2.error(`Embedding endpoint does not support embeddings (${outcome.status})`);
168125
168436
  if (outcome.preview)
168126
- log2.info(` ${outcome.preview}`);
168437
+ log2.info(` ${sanitizeDiagnosticText(outcome.preview)}`);
168127
168438
  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");
168128
168439
  log2.info(" Known non-embedding providers: OpenRouter (chat proxy), Anthropic (no embeddings endpoint). Use OpenAI, Voyage, Together, or a local provider instead.");
168129
168440
  return { issues: localIssues + 1 };
168130
168441
  case "http_error":
168131
168442
  log2.error(`Embedding endpoint returned ${outcome.status}`);
168132
168443
  if (outcome.preview)
168133
- log2.info(` ${outcome.preview}`);
168444
+ log2.info(` ${sanitizeDiagnosticText(outcome.preview)}`);
168134
168445
  return { issues: localIssues + 1 };
168135
168446
  case "timeout":
168136
168447
  log2.warn(`Embedding endpoint did not respond within ${outcome.timeoutMs}ms — check endpoint URL and network`);
168137
168448
  return { issues: localIssues + 1 };
168138
168449
  case "network_error":
168139
- log2.error(`Could not reach embedding endpoint: ${outcome.message}`);
168450
+ log2.error(`Could not reach embedding endpoint: ${sanitizeDiagnosticText(outcome.message)}`);
168140
168451
  return { issues: localIssues + 1 };
168141
168452
  case "invalid_scheme":
168142
- log2.error(`Embedding endpoint must start with http:// or https://: ${outcome.endpoint}`);
168453
+ log2.error(`Embedding endpoint must start with http:// or https://: ${sanitizeDiagnosticEndpoint(outcome.endpoint)}`);
168143
168454
  return { issues: localIssues + 1 };
168144
168455
  }
168145
168456
  }
@@ -168207,7 +168518,7 @@ async function runDoctor(options = {}) {
168207
168518
  } else {
168208
168519
  pass(`OpenCode config: ${paths.opencodeConfig}`);
168209
168520
  }
168210
- if (existsSync23(paths.magicContextConfig)) {
168521
+ if (existsSync22(paths.magicContextConfig)) {
168211
168522
  pass(`Magic Context config: ${paths.magicContextConfig}`);
168212
168523
  try {
168213
168524
  const raw = readFileSync14(paths.magicContextConfig, "utf-8");
@@ -168235,7 +168546,7 @@ async function runDoctor(options = {}) {
168235
168546
  warn(`No magic-context.jsonc found — using defaults`);
168236
168547
  log2.info(" Run 'setup' to create one with model recommendations");
168237
168548
  }
168238
- if (existsSync23(paths.magicContextConfig)) {
168549
+ if (existsSync22(paths.magicContextConfig)) {
168239
168550
  try {
168240
168551
  const mcRaw = readFileSync14(paths.magicContextConfig, "utf-8");
168241
168552
  const mcConfig = import_comment_json8.parse(mcRaw);
@@ -168374,7 +168685,7 @@ async function runDoctor(options = {}) {
168374
168685
  if (isDevPathPluginEntry(oldEntry)) {
168375
168686
  pass(`Plugin registered in ${configName} (dev path: ${oldEntryStr})`);
168376
168687
  } else {
168377
- const isPinned = oldEntryStr !== OPENCODE_PLUGIN_NAME && oldEntryStr !== OPENCODE_PLUGIN_ENTRY_WITH_VERSION && /^@cortexkit\/opencode-magic-context@\d/.test(oldEntryStr);
168688
+ const isPinned = isPinnedOpenCodePluginSpecifier(oldEntryStr);
168378
168689
  if (isPinned && !options.force) {
168379
168690
  warn(`Plugin pinned to ${oldEntryStr} in ${configName} — use 'doctor --force' to upgrade`);
168380
168691
  } else {
@@ -168426,7 +168737,7 @@ async function runDoctor(options = {}) {
168426
168737
  pass("Added TUI sidebar plugin to tui.json");
168427
168738
  warn("Restart OpenCode to see the sidebar");
168428
168739
  fixed++;
168429
- } else if (existsSync23(paths.tuiConfig)) {
168740
+ } else if (existsSync22(paths.tuiConfig)) {
168430
168741
  try {
168431
168742
  const tuiRaw = readFileSync14(paths.tuiConfig, "utf-8");
168432
168743
  const tuiConfig = import_comment_json8.parse(tuiRaw);
@@ -168445,7 +168756,7 @@ async function runDoctor(options = {}) {
168445
168756
  if (isDevPathPluginEntry(tuiEntry)) {
168446
168757
  pass(`TUI sidebar plugin configured (dev path: ${tuiEntryStr})`);
168447
168758
  } else {
168448
- const tuiPinned = tuiEntryStr !== OPENCODE_PLUGIN_NAME && tuiEntryStr !== OPENCODE_PLUGIN_ENTRY_WITH_VERSION && /^@cortexkit\/opencode-magic-context@\d/.test(tuiEntryStr);
168759
+ const tuiPinned = isPinnedOpenCodePluginSpecifier(tuiEntryStr);
168449
168760
  if (tuiPinned && !options.force) {
168450
168761
  warn(`TUI plugin pinned to ${tuiEntryStr} — use 'doctor --force' to upgrade`);
168451
168762
  } else if (tuiPinned && options.force) {
@@ -168474,16 +168785,13 @@ async function runDoctor(options = {}) {
168474
168785
  } else {
168475
168786
  pass("TUI sidebar plugin configured (tui.json created)");
168476
168787
  }
168477
- if (existsSync23(paths.magicContextConfig)) {
168788
+ if (existsSync22(paths.magicContextConfig)) {
168478
168789
  try {
168479
168790
  const mcRaw = readFileSync14(paths.magicContextConfig, "utf-8");
168480
168791
  const mcConfig = import_comment_json8.parse(mcRaw);
168481
- const dreamerObj = mcConfig?.dreamer;
168482
- const dreamerDisabled = dreamerObj?.disable === true;
168483
- const userMemObj = dreamerObj?.user_memories;
168484
- const userMemEnabled = userMemObj?.enabled !== false;
168485
- if (userMemEnabled && dreamerDisabled) {
168486
- log2.warn("dreamer.user_memories is enabled but dreamer.disable=true, so new promotions will not run. Remove dreamer.disable or set dreamer.user_memories.enabled=false.");
168792
+ const warning = checkUserMemoriesDreamerCompatibility(mcConfig);
168793
+ if (warning) {
168794
+ log2.warn(warning);
168487
168795
  issues++;
168488
168796
  }
168489
168797
  } catch {}
@@ -168495,7 +168803,7 @@ async function runDoctor(options = {}) {
168495
168803
  else
168496
168804
  passCount++;
168497
168805
  const dbPath = join19(getMagicContextStorageDir(), "context.db");
168498
- if (!existsSync23(dbPath)) {
168806
+ if (!existsSync22(dbPath)) {
168499
168807
  log2.info(`Shared context DB not yet created at ${dbPath} (will be created on first run)`);
168500
168808
  } else {
168501
168809
  pass(`Shared context DB exists at ${dbPath}`);
@@ -168555,29 +168863,20 @@ async function runDoctor(options = {}) {
168555
168863
  warn(`Plugin cache version check unavailable; preserving cached plugin${cacheResult.cached ? ` (cached: ${cacheResult.cached})` : ""}. Use doctor --force to reinstall it.`);
168556
168864
  } else if (cacheResult.action === "error") {
168557
168865
  warn(`Could not clear plugin cache: ${cacheResult.error}`);
168558
- log2.info(` Manually delete: ${cacheResult.path}`);
168866
+ if (cacheResult.clearedPaths && cacheResult.clearedPaths.length > 0) {
168867
+ log2.info(` Cleared roots: ${cacheResult.clearedPaths.join(", ")}`);
168868
+ }
168869
+ if (cacheResult.failedPaths && cacheResult.failedPaths.length > 0) {
168870
+ log2.info(` Failed roots: ${cacheResult.failedPaths.join(", ")}`);
168871
+ } else {
168872
+ log2.info(` Manually delete: ${cacheResult.path}`);
168873
+ }
168559
168874
  issues++;
168560
168875
  } else {
168561
168876
  pass("Plugin cache clean (no cached version found)");
168562
168877
  }
168563
168878
  {
168564
- const ageWarnings = [];
168565
- const npmrcPath = join19(homedir13(), ".npmrc");
168566
- if (existsSync23(npmrcPath)) {
168567
- try {
168568
- const npmrc = readFileSync14(npmrcPath, "utf-8");
168569
- for (const line of npmrc.split(`
168570
- `)) {
168571
- const trimmed = line.trim();
168572
- if (trimmed.startsWith("#") || trimmed.startsWith(";"))
168573
- continue;
168574
- const [key] = trimmed.split("=").map((s) => s.trim());
168575
- if (key === "min-release-age" || key === "before") {
168576
- ageWarnings.push(`~/.npmrc has '${trimmed}'`);
168577
- }
168578
- }
168579
- } catch {}
168580
- }
168879
+ const ageWarnings = collectNpmReleaseAgeWarnings();
168581
168880
  if (ageWarnings.length > 0) {
168582
168881
  log2.warn("npm min-release-age restriction detected — this can prevent OpenCode from installing the latest plugin version");
168583
168882
  for (const w of ageWarnings) {
@@ -168589,7 +168888,7 @@ async function runDoctor(options = {}) {
168589
168888
  }
168590
168889
  }
168591
168890
  const logPath = getMagicContextLogPath2("opencode");
168592
- if (existsSync23(logPath)) {
168891
+ if (existsSync22(logPath)) {
168593
168892
  const logStat = statSync8(logPath);
168594
168893
  const sizeKb = (logStat.size / 1024).toFixed(0);
168595
168894
  log2.info(`Log file: ${logPath} (${sizeKb} KB)`);
@@ -168654,6 +168953,7 @@ var init_doctor_opencode = __esm(async () => {
168654
168953
  init_opencode_plugin_cache();
168655
168954
  init_paths();
168656
168955
  init_prompts();
168956
+ init_redaction2();
168657
168957
  init_v22_backfill_commands();
168658
168958
  init_doctor_opencode_cache();
168659
168959
  await __promiseAll([
@@ -168664,7 +168964,7 @@ var init_doctor_opencode = __esm(async () => {
168664
168964
  });
168665
168965
 
168666
168966
  // ../pi-plugin/src/config/index.ts
168667
- import { existsSync as existsSync24, readFileSync as readFileSync15 } from "node:fs";
168967
+ import { existsSync as existsSync23, readFileSync as readFileSync15 } from "node:fs";
168668
168968
  function getProjectConfigPaths(cwd) {
168669
168969
  const basePath = cortexKitProjectConfigBasePath(cwd);
168670
168970
  return [`${basePath}.jsonc`, `${basePath}.json`];
@@ -168674,10 +168974,10 @@ function getUserConfigPaths() {
168674
168974
  return [`${basePath}.jsonc`, `${basePath}.json`];
168675
168975
  }
168676
168976
  function resolveFirstExisting(paths) {
168677
- return paths.find((path6) => existsSync24(path6));
168977
+ return paths.find((path6) => existsSync23(path6));
168678
168978
  }
168679
168979
  function resolvePiLegacyFallback(sources) {
168680
- return sources.find((source) => existsSync24(source.path)) ?? null;
168980
+ return sources.find((source) => existsSync23(source.path)) ?? null;
168681
168981
  }
168682
168982
  function loadConfigFile(path6, scope) {
168683
168983
  try {
@@ -168814,7 +169114,7 @@ function loadPiConfig(opts = {}) {
168814
169114
  if (loaded)
168815
169115
  loadedFiles.push(loaded);
168816
169116
  }
168817
- const legacyProjectUnmigrated = !projectPath && !projectLegacyFallback && legacySources.project.some((source) => existsSync24(source.path));
169117
+ const legacyProjectUnmigrated = !projectPath && !projectLegacyFallback && legacySources.project.some((source) => existsSync23(source.path));
168818
169118
  const userPath = resolveFirstExisting(getUserConfigPaths());
168819
169119
  const userLegacyFallback = userPath ? null : resolvePiLegacyFallback(harnessLegacy.user);
168820
169120
  const userReadPath = userPath ?? userLegacyFallback?.path;
@@ -168823,7 +169123,7 @@ function loadPiConfig(opts = {}) {
168823
169123
  if (loaded)
168824
169124
  loadedFiles.push(loaded);
168825
169125
  }
168826
- const legacyUserUnmigrated = !userPath && !userLegacyFallback && legacySources.user.some((source) => existsSync24(source.path));
169126
+ const legacyUserUnmigrated = !userPath && !userLegacyFallback && legacySources.user.some((source) => existsSync23(source.path));
168827
169127
  if (userLegacyFallback) {
168828
169128
  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.`);
168829
169129
  } else if (legacyUserUnmigrated) {
@@ -168841,6 +169141,7 @@ function loadPiConfig(opts = {}) {
168841
169141
  return a3.scope === "user" ? -1 : 1;
168842
169142
  });
168843
169143
  const userRaw = mergeFiles.find((f2) => f2.scope === "user")?.config;
169144
+ const trustedBaseConfig = parsePiConfig(userRaw ?? {}).config;
168844
169145
  for (const loaded of mergeFiles) {
168845
169146
  const prefix = loaded.scope === "user" ? "[user config]" : "[project config]";
168846
169147
  warnings.push(...loaded.warnings.map((warning) => `${prefix} ${warning}`));
@@ -168853,6 +169154,13 @@ function loadPiConfig(opts = {}) {
168853
169154
  for (const warning of dropInheritedEmbeddingKeyOnRedirect(projectRaw, rawConfig, userRaw)) {
168854
169155
  warnings.push(`${prefix} ${warning}`);
168855
169156
  }
169157
+ for (const warning of constrainProjectThresholdOverrides({
169158
+ mergedRaw: rawConfig,
169159
+ projectRaw,
169160
+ trustedBaseConfig
169161
+ })) {
169162
+ warnings.push(`${prefix} ${warning}`);
169163
+ }
168856
169164
  } else {
168857
169165
  rawConfig = mergeRawConfigs(rawConfig, loaded.config);
168858
169166
  }
@@ -168877,9 +169185,9 @@ var init_config2 = __esm(() => {
168877
169185
 
168878
169186
  // src/lib/diagnostics-pi.ts
168879
169187
  import { createHash as createHash3 } from "node:crypto";
168880
- import { existsSync as existsSync25, readdirSync as readdirSync3, readFileSync as readFileSync16, statSync as statSync9 } from "node:fs";
169188
+ import { existsSync as existsSync24, readdirSync as readdirSync3, readFileSync as readFileSync16, statSync as statSync9 } from "node:fs";
168881
169189
  import { createRequire as createRequire5 } from "node:module";
168882
- import { homedir as homedir14, userInfo as userInfo2 } from "node:os";
169190
+ import { homedir as homedir13, userInfo as userInfo2 } from "node:os";
168883
169191
  import { join as join20 } from "node:path";
168884
169192
  function getSelfVersion3() {
168885
169193
  const req = createRequire5(import.meta.url);
@@ -168895,7 +169203,7 @@ function getSelfVersion3() {
168895
169203
  }
168896
169204
  function fileSize2(path6) {
168897
169205
  try {
168898
- return existsSync25(path6) ? statSync9(path6).size : 0;
169206
+ return existsSync24(path6) ? statSync9(path6).size : 0;
168899
169207
  } catch {
168900
169208
  return 0;
168901
169209
  }
@@ -168911,7 +169219,7 @@ function redactSecretString(value) {
168911
169219
  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>");
168912
169220
  }
168913
169221
  function sanitizeString2(value) {
168914
- const home = process.env.HOME || homedir14();
169222
+ const home = process.env.HOME || homedir13();
168915
169223
  const username = userInfo2().username;
168916
169224
  const userHash = `<USER:${currentUserHash()}>`;
168917
169225
  let sanitized = redactSecretString(value);
@@ -168930,6 +169238,8 @@ function shouldRedactKey(key) {
168930
169238
  return /api[_-]?key|token|secret|password|authorization|cookie/i.test(key);
168931
169239
  }
168932
169240
  function sanitizeValue2(value, key = "") {
169241
+ if (value === null || typeof value === "number" || typeof value === "boolean")
169242
+ return value;
168933
169243
  if (shouldRedactKey(key))
168934
169244
  return "<REDACTED>";
168935
169245
  if (typeof value === "string")
@@ -168945,7 +169255,7 @@ function sanitizeValue2(value, key = "") {
168945
169255
  return value;
168946
169256
  }
168947
169257
  function readJsonc3(path6) {
168948
- if (!existsSync25(path6))
169258
+ if (!existsSync24(path6))
168949
169259
  return { value: {} };
168950
169260
  try {
168951
169261
  return {
@@ -168965,7 +169275,7 @@ function readConfigDiagnostic(path6) {
168965
169275
  const parsed = readJsonc3(path6);
168966
169276
  return {
168967
169277
  path: path6,
168968
- exists: existsSync25(path6),
169278
+ exists: existsSync24(path6),
168969
169279
  ...parsed.parseError ? { parseError: parsed.parseError } : {},
168970
169280
  flags: sanitizeValue2(parsed.value)
168971
169281
  };
@@ -168982,8 +169292,8 @@ function reverseSlugToDirectory(slug) {
168982
169292
  return `/${inner.replace(/-/g, "/")}`;
168983
169293
  }
168984
169294
  function collectPiRecentSessions() {
168985
- const sessionsRoot = join20(process.env.HOME || homedir14(), ".pi", "agent", "sessions");
168986
- if (!existsSync25(sessionsRoot))
169295
+ const sessionsRoot = getPiSessionsRoot();
169296
+ if (!existsSync24(sessionsRoot))
168987
169297
  return [];
168988
169298
  try {
168989
169299
  const slugs = readdirSync3(sessionsRoot, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name);
@@ -169052,7 +169362,7 @@ function parseHistorianDumpMeta2(path6) {
169052
169362
  }
169053
169363
  }
169054
169364
  function listDumpsInDir2(dir, limit) {
169055
- if (!existsSync25(dir))
169365
+ if (!existsSync24(dir))
169056
169366
  return { count: 0, recent: [] };
169057
169367
  try {
169058
169368
  const entries = readdirSync3(dir).filter((name2) => name2.endsWith(".xml")).map((name2) => {
@@ -169130,7 +169440,7 @@ async function collectDiagnostics2(cwd = process.cwd()) {
169130
169440
  const storageDirPath = getMagicContextStorageDir();
169131
169441
  const dbPath = join20(storageDirPath, "context.db");
169132
169442
  const logPath = getMagicContextLogPath2("pi");
169133
- const logFileSize = existsSync25(logPath) ? statSync9(logPath).size : 0;
169443
+ const logFileSize = existsSync24(logPath) ? statSync9(logPath).size : 0;
169134
169444
  const otherPiExtensions = packages.filter((entry) => !isPiMagicContextPackageEntry(entry)).map(describePiPackageEntry);
169135
169445
  const recentSessions = collectPiRecentSessions();
169136
169446
  const historianDumps = collectPiHistorianDumps(recentSessions);
@@ -169145,7 +169455,7 @@ async function collectDiagnostics2(cwd = process.cwd()) {
169145
169455
  piVersion: pi ? getPiVersion(pi.path) : null,
169146
169456
  settings: {
169147
169457
  path: settingsPath,
169148
- exists: existsSync25(settingsPath),
169458
+ exists: existsSync24(settingsPath),
169149
169459
  ...settingsParsed.parseError ? { parseError: settingsParsed.parseError } : {},
169150
169460
  hasMagicContextPackage: hasPiMagicContextPackage(packages),
169151
169461
  packages: sanitizeValue2(packages)
@@ -169161,7 +169471,7 @@ async function collectDiagnostics2(cwd = process.cwd()) {
169161
169471
  loadWarnings: loaded.warnings.map(sanitizeString2),
169162
169472
  storageDir: {
169163
169473
  path: storageDirPath,
169164
- exists: existsSync25(storageDirPath),
169474
+ exists: existsSync24(storageDirPath),
169165
169475
  contextDbSizeBytes: fileSize2(dbPath)
169166
169476
  },
169167
169477
  conflicts: {
@@ -169170,7 +169480,7 @@ async function collectDiagnostics2(cwd = process.cwd()) {
169170
169480
  },
169171
169481
  logFile: {
169172
169482
  path: logPath,
169173
- exists: existsSync25(logPath),
169483
+ exists: existsSync24(logPath),
169174
169484
  sizeKb: Math.round(logFileSize / 1024)
169175
169485
  },
169176
169486
  recentSessions,
@@ -169264,7 +169574,7 @@ var init_diagnostics_pi = __esm(() => {
169264
169574
  });
169265
169575
 
169266
169576
  // src/lib/logs-pi.ts
169267
- import { readFileSync as readFileSync17, writeFileSync as writeFileSync7 } from "node:fs";
169577
+ import { readFileSync as readFileSync17, writeFileSync as writeFileSync6 } from "node:fs";
169268
169578
  import { join as join21 } from "node:path";
169269
169579
  function sanitizeLogContent2(content) {
169270
169580
  return sanitizeString2(content);
@@ -169331,7 +169641,7 @@ async function bundleIssueReport2(report, description, title, options = {}) {
169331
169641
  const bodyMarkdown = capBodyToGithubLimit(rawBodyMarkdown);
169332
169642
  const cwd = options.cwd ?? process.cwd();
169333
169643
  const path6 = join21(cwd, `magic-context-pi-issue-${formatTimestamp2(options.now ?? new Date)}.md`);
169334
- writeFileSync7(path6, `${bodyMarkdown}
169644
+ writeFileSync6(path6, `${bodyMarkdown}
169335
169645
  `);
169336
169646
  return { path: path6, bodyMarkdown };
169337
169647
  }
@@ -169342,10 +169652,10 @@ var init_logs_pi = __esm(() => {
169342
169652
 
169343
169653
  // src/commands/doctor-pi.ts
169344
169654
  import { execFileSync as execFileSync5, spawnSync as spawnSync4 } from "node:child_process";
169345
- import { existsSync as existsSync26, mkdirSync as mkdirSync9, readdirSync as readdirSync4, readFileSync as readFileSync18, rmSync as rmSync3, statSync as statSync10 } from "node:fs";
169655
+ import { existsSync as existsSync25, mkdirSync as mkdirSync8, readdirSync as readdirSync4, readFileSync as readFileSync18, rmSync as rmSync3, statSync as statSync10 } from "node:fs";
169346
169656
  import { createRequire as createRequire6 } from "node:module";
169347
- import { homedir as homedir15 } from "node:os";
169348
- import { dirname as dirname12, isAbsolute as isAbsolute3, join as join22 } from "node:path";
169657
+ import { homedir as homedir14 } from "node:os";
169658
+ import { dirname as dirname13, isAbsolute as isAbsolute3, join as join22 } from "node:path";
169349
169659
  function depsFrom(options) {
169350
169660
  return {
169351
169661
  ...DEFAULT_DEPS,
@@ -169459,13 +169769,13 @@ function piPluginDirCandidates(packages, cwd) {
169459
169769
  }
169460
169770
  dirs.push(join22(agentDir, "npm", "node_modules", PACKAGE_NAME));
169461
169771
  dirs.push(join22(cwd, ".pi", "npm", "node_modules", PACKAGE_NAME));
169462
- return dirs.filter((dir) => existsSync26(join22(dir, "package.json")));
169772
+ return dirs.filter((dir) => existsSync25(join22(dir, "package.json")));
169463
169773
  }
169464
169774
  function projectConfigPath(cwd) {
169465
169775
  return resolveCortexKitProjectConfigPath(cwd);
169466
169776
  }
169467
169777
  function readConfigForEmbedding(path6, isProjectConfig) {
169468
- if (!existsSync26(path6))
169778
+ if (!existsSync25(path6))
169469
169779
  return null;
169470
169780
  try {
169471
169781
  const rawText = readFileSync18(path6, "utf-8");
@@ -169499,7 +169809,7 @@ function classifyEmbeddingOutcome(outcome) {
169499
169809
  case "network_error":
169500
169810
  return {
169501
169811
  status: "fail",
169502
- message: `Embedding endpoint network error: ${outcome.message}`
169812
+ message: `Embedding endpoint network error: ${sanitizeDiagnosticText(outcome.message)}`
169503
169813
  };
169504
169814
  case "endpoint_unsupported":
169505
169815
  return {
@@ -169514,7 +169824,7 @@ function classifyEmbeddingOutcome(outcome) {
169514
169824
  case "invalid_scheme":
169515
169825
  return {
169516
169826
  status: "fail",
169517
- message: `Embedding endpoint must start with http:// or https://: ${outcome.endpoint}`
169827
+ message: `Embedding endpoint must start with http:// or https://: ${sanitizeDiagnosticEndpoint(outcome.endpoint)}`
169518
169828
  };
169519
169829
  }
169520
169830
  }
@@ -169527,11 +169837,12 @@ function countTable(db, table) {
169527
169837
  }
169528
169838
  }
169529
169839
  function cacheRoots() {
169530
- const home = homedir15();
169531
- const cacheHome = process.env.XDG_CACHE_HOME || join22(home, ".cache");
169840
+ const home = process.env.HOME?.trim();
169841
+ const cacheHome = process.env.XDG_CACHE_HOME || join22(home || homedir14(), ".cache");
169842
+ const piCacheRoot = getPiCacheRoot();
169532
169843
  return [
169533
- join22(home, ".pi", "cache", "extensions"),
169534
- join22(home, ".pi", "cache", "packages"),
169844
+ join22(piCacheRoot, "extensions"),
169845
+ join22(piCacheRoot, "packages"),
169535
169846
  join22(cacheHome, "pi", "extensions"),
169536
169847
  join22(cacheHome, "pi", "packages"),
169537
169848
  join22(getPiAgentConfigDir(), "cache", "extensions")
@@ -169540,7 +169851,7 @@ function cacheRoots() {
169540
169851
  function findPiMagicContextCacheDirs(self, force = false) {
169541
169852
  const found = new Map;
169542
169853
  const visit = (path6, depth) => {
169543
- if (depth < 0 || !existsSync26(path6))
169854
+ if (depth < 0 || !existsSync25(path6))
169544
169855
  return;
169545
169856
  let stat;
169546
169857
  try {
@@ -169551,7 +169862,7 @@ function findPiMagicContextCacheDirs(self, force = false) {
169551
169862
  if (!stat.isDirectory())
169552
169863
  return;
169553
169864
  const packageJson = join22(path6, "package.json");
169554
- if (existsSync26(packageJson)) {
169865
+ if (existsSync25(packageJson)) {
169555
169866
  try {
169556
169867
  const pkg = JSON.parse(readFileSync18(packageJson, "utf-8"));
169557
169868
  const name2 = typeof pkg.name === "string" ? pkg.name : "";
@@ -169586,7 +169897,7 @@ async function runHealthChecks(options) {
169586
169897
  writeUserConfig: false,
169587
169898
  clearCachePaths: []
169588
169899
  };
169589
- const self = selfVersion();
169900
+ const self = options.deps.selfVersion();
169590
169901
  const pi = options.deps.detectPiBinary();
169591
169902
  if (!pi) {
169592
169903
  add(results, "fail", "Pi binary not found on PATH or at ~/.pi/bin/pi");
@@ -169601,16 +169912,19 @@ async function runHealthChecks(options) {
169601
169912
  }
169602
169913
  }
169603
169914
  const latest = options.deps.getLatestNpmVersion();
169604
- if (latest && compareSemver(self, latest) === -1) {
169915
+ const latestCompare = latest ? compareSemver(self, latest) : null;
169916
+ if (latest && latestCompare === -1) {
169605
169917
  add(results, "warn", `Magic Context for Pi CLI v${self} is older than npm latest v${latest}`);
169606
- } else if (latest) {
169918
+ } else if (latest && latestCompare !== null) {
169607
169919
  add(results, "pass", `Magic Context for Pi CLI v${self} is current (npm latest v${latest})`);
169920
+ } else if (latest) {
169921
+ add(results, "info", `Magic Context for Pi CLI version unknown; npm latest is v${latest}`);
169608
169922
  } else {
169609
169923
  add(results, "info", `Magic Context for Pi CLI v${self}; npm latest check unavailable`);
169610
169924
  }
169611
169925
  const settingsPath = getPiUserExtensionsPath();
169612
169926
  let packages = [];
169613
- if (!existsSync26(settingsPath)) {
169927
+ if (!existsSync25(settingsPath)) {
169614
169928
  add(results, "warn", `Pi settings not found at ${settingsPath}`);
169615
169929
  repairPlan.addPackageEntry = true;
169616
169930
  } else {
@@ -169634,7 +169948,7 @@ async function runHealthChecks(options) {
169634
169948
  ["user", userConfigPath, true],
169635
169949
  ["project", projectPath, false]
169636
169950
  ]) {
169637
- if (!existsSync26(path6)) {
169951
+ if (!existsSync25(path6)) {
169638
169952
  if (required2) {
169639
169953
  add(results, "warn", `No ${label} magic-context.jsonc found at ${path6}`);
169640
169954
  if (userConfigMigrationRefused) {
@@ -169672,7 +169986,7 @@ async function runHealthChecks(options) {
169672
169986
  }
169673
169987
  const storageDir = getMagicContextStorageDir();
169674
169988
  const dbPath = join22(storageDir, "context.db");
169675
- const existedBeforeOpen = existsSync26(dbPath);
169989
+ const existedBeforeOpen = existsSync25(dbPath);
169676
169990
  if (existedBeforeOpen)
169677
169991
  add(results, "pass", `Shared context DB exists at ${dbPath}`);
169678
169992
  else
@@ -169736,7 +170050,7 @@ async function runHealthChecks(options) {
169736
170050
  const classified = classifyEmbeddingOutcome(outcome);
169737
170051
  add(results, classified.status, classified.message);
169738
170052
  } catch (error51) {
169739
- add(results, "fail", `Embedding probe threw: ${error51 instanceof Error ? error51.message : String(error51)}`);
170053
+ add(results, "fail", `Embedding probe threw: ${sanitizeDiagnosticText(error51 instanceof Error ? error51.message : String(error51))}`);
169740
170054
  }
169741
170055
  }
169742
170056
  } else if (loadedConfig.config.embedding.provider === "off") {
@@ -169780,7 +170094,7 @@ async function runHealthChecks(options) {
169780
170094
  add(results, "pass", "Pi extension cache clean (no stale cached package found)");
169781
170095
  }
169782
170096
  const logPath = getMagicContextLogPath2("pi");
169783
- if (existsSync26(logPath)) {
170097
+ if (existsSync25(logPath)) {
169784
170098
  const stat = statSync10(logPath);
169785
170099
  const sizeKb = (stat.size / 1024).toFixed(0);
169786
170100
  const lines = readFileSync18(logPath, "utf-8").split(/\r?\n/).map((line) => line.trim()).filter(Boolean);
@@ -169818,7 +170132,7 @@ async function runHealthChecks(options) {
169818
170132
  return { results, repairPlan, ...summarize(results) };
169819
170133
  }
169820
170134
  function writeDefaultMagicContextConfig(path6) {
169821
- mkdirSync9(dirname12(path6), { recursive: true });
170135
+ mkdirSync8(dirname13(path6), { recursive: true });
169822
170136
  const config2 = {
169823
170137
  $schema: "https://raw.githubusercontent.com/cortexkit/magic-context/master/assets/magic-context.schema.json",
169824
170138
  ...MagicContextConfigSchema.parse({})
@@ -169840,7 +170154,7 @@ function repair(plan, prompts) {
169840
170154
  }
169841
170155
  if (plan.writeUserConfig) {
169842
170156
  const configPath = getPiUserConfigPath();
169843
- if (!existsSync26(configPath)) {
170157
+ if (!existsSync25(configPath)) {
169844
170158
  try {
169845
170159
  writeDefaultMagicContextConfig(configPath);
169846
170160
  prompts.log.success(`Wrote default Magic Context config to ${configPath}`);
@@ -170043,6 +170357,7 @@ var init_doctor_pi = __esm(async () => {
170043
170357
  detectPiBinary,
170044
170358
  getPiVersion,
170045
170359
  getLatestNpmVersion: () => getLatestNpmVersion(PACKAGE_NAME),
170360
+ selfVersion,
170046
170361
  probeEmbeddingEndpoint,
170047
170362
  openDatabase,
170048
170363
  isDatabasePersisted,
@@ -170058,7 +170373,7 @@ var exports_doctor = {};
170058
170373
  __export(exports_doctor, {
170059
170374
  runDoctor: () => runDoctor3
170060
170375
  });
170061
- import { existsSync as existsSync27, rmSync as rmSync4 } from "node:fs";
170376
+ import { existsSync as existsSync26, rmSync as rmSync4 } from "node:fs";
170062
170377
  async function runDoctor3(options) {
170063
170378
  if (options.clear)
170064
170379
  return runClear();
@@ -170147,7 +170462,7 @@ async function runClear() {
170147
170462
  const s = spinner2();
170148
170463
  s.start(`Clearing ${item.path}`);
170149
170464
  try {
170150
- if (existsSync27(item.path)) {
170465
+ if (existsSync26(item.path)) {
170151
170466
  rmSync4(item.path, { recursive: true, force: true });
170152
170467
  }
170153
170468
  s.stop(`Cleared ${item.path}`);