@cortexkit/magic-context 0.21.4 → 0.21.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 +48 -9
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -27378,6 +27378,21 @@ import { dirname as dirname7, isAbsolute, resolve as resolve2 } from "node:path"
27378
27378
  function substituteConfigVariables(input) {
27379
27379
  const warnings = [];
27380
27380
  let text2 = input.text;
27381
+ if (input.isProjectConfig) {
27382
+ const hasEnvTokens = ENV_PATTERN.test(text2);
27383
+ const hasFileTokens = FILE_PATTERN.test(text2);
27384
+ ENV_PATTERN.lastIndex = 0;
27385
+ FILE_PATTERN.lastIndex = 0;
27386
+ if (hasEnvTokens || hasFileTokens) {
27387
+ const tokenTypes = [
27388
+ hasEnvTokens ? "{env:}" : undefined,
27389
+ hasFileTokens ? "{file:}" : undefined
27390
+ ].filter(Boolean).join(" and ");
27391
+ warnings.push(`Project-level config no longer supports ${tokenTypes} tokens for security reasons; leaving tokens literal. Move secret expansion to user-level config.`);
27392
+ }
27393
+ return { text: text2, warnings };
27394
+ }
27395
+ text2 = stripJsonComments(text2);
27381
27396
  text2 = text2.replace(ENV_PATTERN, (_, rawName) => {
27382
27397
  const varName = rawName.trim();
27383
27398
  const value = varName ? process.env[varName] : undefined;
@@ -27385,7 +27400,7 @@ function substituteConfigVariables(input) {
27385
27400
  warnings.push(`Environment variable ${varName} is not set (referenced via {env:${varName}}); using empty string`);
27386
27401
  return "";
27387
27402
  }
27388
- return value;
27403
+ return JSON.stringify(value).slice(1, -1);
27389
27404
  });
27390
27405
  const fileMatches = Array.from(text2.matchAll(FILE_PATTERN));
27391
27406
  if (fileMatches.length === 0) {
@@ -27432,6 +27447,7 @@ function substituteConfigVariables(input) {
27432
27447
  }
27433
27448
  var ENV_PATTERN, FILE_PATTERN;
27434
27449
  var init_variable = __esm(() => {
27450
+ init_jsonc_parser();
27435
27451
  ENV_PATTERN = /\{env:([^}]+)\}/g;
27436
27452
  FILE_PATTERN = /\{file:([^}]+)\}/g;
27437
27453
  });
@@ -27447,13 +27463,17 @@ function getUserConfigBasePath() {
27447
27463
  function getProjectConfigBasePath(directory) {
27448
27464
  return join11(directory, ".opencode", CONFIG_FILE_BASENAME);
27449
27465
  }
27450
- function loadConfigFile(configPath) {
27466
+ function loadConfigFile(configPath, isProjectConfig = false) {
27451
27467
  try {
27452
27468
  if (!existsSync13(configPath)) {
27453
27469
  return null;
27454
27470
  }
27455
27471
  const rawText = readFileSync8(configPath, "utf-8");
27456
- const substituted = substituteConfigVariables({ text: rawText, configPath });
27472
+ const substituted = substituteConfigVariables({
27473
+ text: rawText,
27474
+ configPath,
27475
+ isProjectConfig
27476
+ });
27457
27477
  return {
27458
27478
  config: parseJsonc3(substituted.text),
27459
27479
  warnings: substituted.warnings.map((w3) => `${configPath}: ${w3}`)
@@ -27617,7 +27637,7 @@ function loadPluginConfig(directory) {
27617
27637
  const dotOpenCodeDetected = detectConfigFile(getProjectConfigBasePath(directory));
27618
27638
  const projectDetected = rootDetected.format !== "none" ? rootDetected : dotOpenCodeDetected;
27619
27639
  const userLoaded = userDetected.format === "none" ? null : loadConfigFile(userDetected.path);
27620
- const projectLoaded = projectDetected.format === "none" ? null : loadConfigFile(projectDetected.path);
27640
+ const projectLoaded = projectDetected.format === "none" ? null : loadConfigFile(projectDetected.path, true);
27621
27641
  const allWarnings = [];
27622
27642
  let mergedRaw = {};
27623
27643
  if (userLoaded) {
@@ -162015,8 +162035,10 @@ function deleteOrphanProjectKeyFiles(db, now = Date.now()) {
162015
162035
  if (existsSync18(row.projectPath))
162016
162036
  continue;
162017
162037
  try {
162018
- db.prepare("DELETE FROM project_key_files WHERE project_path = ?").run(row.projectPath);
162019
- db.prepare("DELETE FROM project_key_files_version WHERE project_path = ?").run(row.projectPath);
162038
+ db.transaction(() => {
162039
+ db.prepare("DELETE FROM project_key_files WHERE project_path = ?").run(row.projectPath);
162040
+ db.prepare("DELETE FROM project_key_files_version WHERE project_path = ?").run(row.projectPath);
162041
+ })();
162020
162042
  deletedProjects++;
162021
162043
  } catch (error51) {
162022
162044
  log2(`[key-files] orphan GC failed for ${row.projectPath}:`, error51);
@@ -162044,7 +162066,7 @@ function getCurrentVersion(db) {
162044
162066
  const row = db.prepare("SELECT MAX(version) as version FROM schema_migrations").get();
162045
162067
  return row?.version ?? 0;
162046
162068
  }
162047
- function isSiblingMigrationConflict(error51, version2) {
162069
+ function isSiblingMigrationConflict(db, error51, version2) {
162048
162070
  if (!(error51 instanceof Error))
162049
162071
  return false;
162050
162072
  const code = error51.code;
@@ -162056,7 +162078,8 @@ function isSiblingMigrationConflict(error51, version2) {
162056
162078
  return false;
162057
162079
  if (!msg.toLowerCase().includes("version"))
162058
162080
  return false;
162059
- return true;
162081
+ const confirmed = db.prepare("SELECT 1 FROM schema_migrations WHERE version = ?").get(version2);
162082
+ return confirmed != null;
162060
162083
  }
162061
162084
  function runMigrations(db) {
162062
162085
  ensureMigrationsTable(db);
@@ -162077,7 +162100,7 @@ function runMigrations(db) {
162077
162100
  log2(`[migrations] applied v${migration.version}: ${migration.description}`);
162078
162101
  migrationIndex += 1;
162079
162102
  } catch (error51) {
162080
- if (isSiblingMigrationConflict(error51, migration.version)) {
162103
+ if (isSiblingMigrationConflict(db, error51, migration.version)) {
162081
162104
  log2(`[migrations] v${migration.version} already applied by sibling instance — resuming with re-read version`);
162082
162105
  const reReadVersion = getCurrentVersion(db);
162083
162106
  if (reReadVersion <= currentVersion) {
@@ -162483,6 +162506,16 @@ var init_migrations = __esm(async () => {
162483
162506
  WHERE auto_search_hint_decisions IS NULL
162484
162507
  `);
162485
162508
  }
162509
+ },
162510
+ {
162511
+ version: 18,
162512
+ description: "Add pending_pi_compaction_marker_state column for Pi deferred marker drain",
162513
+ up: (db) => {
162514
+ const cols = db.prepare("PRAGMA table_info(session_meta)").all();
162515
+ if (!cols.some((c2) => c2.name === "pending_pi_compaction_marker_state")) {
162516
+ db.exec("ALTER TABLE session_meta ADD COLUMN pending_pi_compaction_marker_state TEXT");
162517
+ }
162518
+ }
162486
162519
  }
162487
162520
  ];
162488
162521
  });
@@ -163046,6 +163079,11 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
163046
163079
  -- Excluded from healNullTextColumns. Readers filter IS NOT NULL AND
163047
163080
  -- != empty-string defensively. Plan v6 section 3.
163048
163081
  pending_compaction_marker_state TEXT,
163082
+ -- pending_pi_compaction_marker_state: intentionally NULLABLE without a
163083
+ -- default. Absence of a deferred Pi-native marker is SQL NULL; presence
163084
+ -- is a valid JSON blob written via setPendingPiCompactionMarkerState.
163085
+ -- Excluded from healNullTextColumns.
163086
+ pending_pi_compaction_marker_state TEXT,
163049
163087
  -- deferred_execute_state: intentionally NULLABLE without a default.
163050
163088
  -- Absence is SQL NULL; presence is a JSON blob written via
163051
163089
  -- setDeferredExecutePendingIfAbsent. Excluded from healNullTextColumns.
@@ -163142,6 +163180,7 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
163142
163180
  ensureColumn(db, "session_meta", "detected_context_limit", "INTEGER DEFAULT 0");
163143
163181
  ensureColumn(db, "session_meta", "needs_emergency_recovery", "INTEGER DEFAULT 0");
163144
163182
  ensureColumn(db, "session_meta", "pending_compaction_marker_state", "TEXT");
163183
+ ensureColumn(db, "session_meta", "pending_pi_compaction_marker_state", "TEXT");
163145
163184
  ensureColumn(db, "session_meta", "deferred_execute_state", "TEXT");
163146
163185
  ensureColumn(db, "tags", "harness", "TEXT NOT NULL DEFAULT 'opencode'");
163147
163186
  ensureColumn(db, "pending_ops", "harness", "TEXT NOT NULL DEFAULT 'opencode'");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cortexkit/magic-context",
3
- "version": "0.21.4",
3
+ "version": "0.21.5",
4
4
  "description": "Unified CLI for Magic Context — setup, doctor, and migration across OpenCode and Pi",
5
5
  "keywords": [
6
6
  "opencode",