@openez-graph/cli 0.11.0 → 0.12.0

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.
package/dist/cli.cjs CHANGED
@@ -2912,7 +2912,7 @@ var require_command = __commonJS({
2912
2912
  var EventEmitter2 = require("events").EventEmitter;
2913
2913
  var childProcess = require("child_process");
2914
2914
  var path24 = require("path");
2915
- var fs22 = require("fs");
2915
+ var fs23 = require("fs");
2916
2916
  var process3 = require("process");
2917
2917
  var { Argument: Argument2, humanReadableArgName } = require_argument();
2918
2918
  var { CommanderError: CommanderError2 } = require_error();
@@ -3906,7 +3906,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
3906
3906
  * @param {string} subcommandName
3907
3907
  */
3908
3908
  _checkForMissingExecutable(executableFile, executableDir, subcommandName) {
3909
- if (fs22.existsSync(executableFile)) return;
3909
+ if (fs23.existsSync(executableFile)) return;
3910
3910
  const executableDirMessage = executableDir ? `searched for local subcommand relative to directory '${executableDir}'` : "no directory for search for local subcommand, use .executableDir() to supply a custom directory";
3911
3911
  const executableMissing = `'${executableFile}' does not exist
3912
3912
  - if '${subcommandName}' is not meant to be an executable command, remove description parameter from '.command()' and use '.description()' instead
@@ -3925,10 +3925,10 @@ Expecting one of '${allowedValues.join("', '")}'`);
3925
3925
  const sourceExt = [".js", ".ts", ".tsx", ".mjs", ".cjs"];
3926
3926
  function findFile(baseDir, baseName) {
3927
3927
  const localBin = path24.resolve(baseDir, baseName);
3928
- if (fs22.existsSync(localBin)) return localBin;
3928
+ if (fs23.existsSync(localBin)) return localBin;
3929
3929
  if (sourceExt.includes(path24.extname(baseName))) return void 0;
3930
3930
  const foundExt = sourceExt.find(
3931
- (ext) => fs22.existsSync(`${localBin}${ext}`)
3931
+ (ext) => fs23.existsSync(`${localBin}${ext}`)
3932
3932
  );
3933
3933
  if (foundExt) return `${localBin}${foundExt}`;
3934
3934
  return void 0;
@@ -3940,7 +3940,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
3940
3940
  if (this._scriptPath) {
3941
3941
  let resolvedScriptPath;
3942
3942
  try {
3943
- resolvedScriptPath = fs22.realpathSync(this._scriptPath);
3943
+ resolvedScriptPath = fs23.realpathSync(this._scriptPath);
3944
3944
  } catch {
3945
3945
  resolvedScriptPath = this._scriptPath;
3946
3946
  }
@@ -11528,6 +11528,8 @@ var init_schema = __esm({
11528
11528
  nodeCount: integer("node_count").notNull().default(0),
11529
11529
  edgeCount: integer("edge_count").notNull().default(0),
11530
11530
  lastError: text("last_error"),
11531
+ pinnedAt: text("pinned_at"),
11532
+ pinOrder: integer("pin_order"),
11531
11533
  createdAt: text("created_at").notNull().default(sql`(datetime('now'))`),
11532
11534
  updatedAt: text("updated_at").notNull().default(sql`(datetime('now'))`)
11533
11535
  },
@@ -11724,9 +11726,11 @@ function getRegistryDb() {
11724
11726
  const sqlite = createNativeDatabase(dbPath);
11725
11727
  sqlite.pragma("journal_mode = WAL");
11726
11728
  sqlite.pragma("foreign_keys = ON");
11727
- registryDb = drizzle(sqlite, { schema: schema_exports });
11729
+ const db = drizzle(sqlite, { schema: schema_exports });
11728
11730
  initializeRegistrySchema(sqlite);
11731
+ registryDb = db;
11729
11732
  } catch (err) {
11733
+ registryDb = null;
11730
11734
  const message = err instanceof Error ? err.message : String(err);
11731
11735
  throw new Error(`Failed to open registry DB at "${dbPath}": ${message}`);
11732
11736
  }
@@ -11751,6 +11755,7 @@ function initializeRegistrySchema(sqlite) {
11751
11755
  node_count INTEGER NOT NULL DEFAULT 0,
11752
11756
  edge_count INTEGER NOT NULL DEFAULT 0,
11753
11757
  last_error TEXT,
11758
+ pinned_at TEXT,
11754
11759
  created_at TEXT NOT NULL DEFAULT (datetime('now')),
11755
11760
  updated_at TEXT NOT NULL DEFAULT (datetime('now'))
11756
11761
  );
@@ -11764,6 +11769,38 @@ function initializeRegistrySchema(sqlite) {
11764
11769
  updated_at TEXT NOT NULL DEFAULT (datetime('now'))
11765
11770
  );
11766
11771
  `);
11772
+ migrateRegistryColumns(sqlite);
11773
+ }
11774
+ function migrateRegistryColumns(sqlite) {
11775
+ const getColumns = () => new Set(
11776
+ sqlite.prepare("PRAGMA table_info(workspaces)").all().map(
11777
+ (row) => row.name
11778
+ )
11779
+ );
11780
+ const addColumnIfMissing = (name, definition) => {
11781
+ if (getColumns().has(name)) return;
11782
+ try {
11783
+ sqlite.exec(`ALTER TABLE workspaces ADD COLUMN ${definition}`);
11784
+ } catch (err) {
11785
+ if (!getColumns().has(name)) {
11786
+ throw err;
11787
+ }
11788
+ }
11789
+ };
11790
+ addColumnIfMissing("pinned_at", "pinned_at TEXT");
11791
+ addColumnIfMissing("pin_order", "pin_order INTEGER");
11792
+ const unbackfilled = sqlite.prepare(
11793
+ "SELECT id FROM workspaces WHERE pinned_at IS NOT NULL AND pin_order IS NULL ORDER BY pinned_at DESC"
11794
+ ).all();
11795
+ if (unbackfilled.length > 0) {
11796
+ const maxRow = sqlite.prepare("SELECT MAX(pin_order) AS max_order FROM workspaces WHERE pin_order IS NOT NULL").get();
11797
+ let next = (maxRow?.max_order ?? 0) + 1;
11798
+ const stmt = sqlite.prepare("UPDATE workspaces SET pin_order = ? WHERE id = ?");
11799
+ for (const row of unbackfilled) {
11800
+ stmt.run(next, row.id);
11801
+ next += 1;
11802
+ }
11803
+ }
11767
11804
  }
11768
11805
  var import_node_fs2, import_node_os, import_node_path3, registryDb;
11769
11806
  var init_registry_db = __esm({
@@ -11796,8 +11833,20 @@ function getWorkspaceDb(rootPath) {
11796
11833
  const db = drizzle(sqlite, { schema: schema_exports });
11797
11834
  initializeWorkspaceSchema(sqlite);
11798
11835
  dbCache.set(rootPath, db);
11836
+ nativeCache.set(rootPath, sqlite);
11799
11837
  return db;
11800
11838
  }
11839
+ function closeWorkspaceDb(rootPath) {
11840
+ const native = nativeCache.get(rootPath);
11841
+ if (native) {
11842
+ try {
11843
+ native.close();
11844
+ } catch {
11845
+ }
11846
+ nativeCache.delete(rootPath);
11847
+ }
11848
+ dbCache.delete(rootPath);
11849
+ }
11801
11850
  function initializeWorkspaceSchema(sqlite) {
11802
11851
  const tables = getWorkspaceTableDefinitions();
11803
11852
  for (const ddl of tables) {
@@ -12045,7 +12094,7 @@ function getWorkspaceTableDefinitions() {
12045
12094
  )`
12046
12095
  ];
12047
12096
  }
12048
- var import_node_fs3, import_node_path4, WORKSPACE_DB_DIR_NAME, WORKSPACE_DB_FILE_NAME, dbCache;
12097
+ var import_node_fs3, import_node_path4, WORKSPACE_DB_DIR_NAME, WORKSPACE_DB_FILE_NAME, dbCache, nativeCache;
12049
12098
  var init_workspace_db = __esm({
12050
12099
  "../../packages/db/src/sqlite/workspace-db.ts"() {
12051
12100
  "use strict";
@@ -12057,6 +12106,7 @@ var init_workspace_db = __esm({
12057
12106
  WORKSPACE_DB_DIR_NAME = ".openez";
12058
12107
  WORKSPACE_DB_FILE_NAME = "index.sqlite";
12059
12108
  dbCache = /* @__PURE__ */ new Map();
12109
+ nativeCache = /* @__PURE__ */ new Map();
12060
12110
  }
12061
12111
  });
12062
12112
 
@@ -12181,7 +12231,7 @@ function createRegistryRepository() {
12181
12231
  return {
12182
12232
  async listWorkspaces() {
12183
12233
  const rows = db.select().from(workspaces).all();
12184
- return rows.map(mapWorkspaceRow);
12234
+ return rows.map(mapWorkspaceRow).sort(compareWorkspaces);
12185
12235
  },
12186
12236
  async getWorkspace(id) {
12187
12237
  const row = db.select().from(workspaces).where(eq(workspaces.id, id)).get();
@@ -12291,6 +12341,15 @@ function createRegistryRepository() {
12291
12341
  async deleteWorkspace(id) {
12292
12342
  db.delete(workspaces).where(eq(workspaces.id, id)).run();
12293
12343
  },
12344
+ async setPinned(id, pinned) {
12345
+ if (pinned) {
12346
+ const maxRow = native.prepare("SELECT MAX(pin_order) AS max_order FROM workspaces WHERE pin_order IS NOT NULL").get();
12347
+ const nextOrder = (maxRow?.max_order ?? 0) + 1;
12348
+ native.prepare("UPDATE workspaces SET pinned_at = ?, pin_order = ? WHERE id = ?").run((/* @__PURE__ */ new Date()).toISOString(), nextOrder, id);
12349
+ } else {
12350
+ native.prepare("UPDATE workspaces SET pinned_at = NULL, pin_order = NULL WHERE id = ?").run(id);
12351
+ }
12352
+ },
12294
12353
  async getSetting(key) {
12295
12354
  const row = native.prepare("SELECT value FROM settings WHERE key = ?").get(key);
12296
12355
  if (!row) return null;
@@ -12348,10 +12407,23 @@ function mapWorkspaceRow(row) {
12348
12407
  nodeCount: row.nodeCount,
12349
12408
  edgeCount: row.edgeCount,
12350
12409
  lastError: row.lastError ?? void 0,
12410
+ pinnedAt: row.pinnedAt ?? void 0,
12411
+ pinOrder: row.pinOrder ?? void 0,
12351
12412
  createdAt: row.createdAt,
12352
12413
  updatedAt: row.updatedAt
12353
12414
  };
12354
12415
  }
12416
+ function compareWorkspaces(a, b) {
12417
+ if (a.pinnedAt && !b.pinnedAt) return -1;
12418
+ if (!a.pinnedAt && b.pinnedAt) return 1;
12419
+ if (a.pinnedAt && b.pinnedAt) {
12420
+ const aOrder = a.pinOrder ?? -Infinity;
12421
+ const bOrder = b.pinOrder ?? -Infinity;
12422
+ if (aOrder !== bOrder) return bOrder - aOrder;
12423
+ if (a.pinnedAt !== b.pinnedAt) return b.pinnedAt.localeCompare(a.pinnedAt);
12424
+ }
12425
+ return b.createdAt.localeCompare(a.createdAt);
12426
+ }
12355
12427
  function getNativeWorkspaceDb(rootPath) {
12356
12428
  const db = getWorkspaceDb(rootPath);
12357
12429
  const native = db.$client;
@@ -12594,6 +12666,36 @@ function createWorkspaceRepository(rootPath) {
12594
12666
  }
12595
12667
  return ids;
12596
12668
  },
12669
+ async upsertGraphNodesBatch(inputs) {
12670
+ if (inputs.length === 0) return [];
12671
+ const now = (/* @__PURE__ */ new Date()).toISOString();
12672
+ const BATCH = 500;
12673
+ const results = [];
12674
+ for (let i = 0; i < inputs.length; i += BATCH) {
12675
+ const batch = inputs.slice(i, i + BATCH);
12676
+ const placeholders = batch.map(() => "(?, ?, ?, ?, ?, ?, ?)").join(",");
12677
+ const params = [];
12678
+ for (const item of batch) {
12679
+ const id = import_node_crypto2.default.randomUUID();
12680
+ params.push(
12681
+ id,
12682
+ item.type,
12683
+ item.label,
12684
+ item.refId ?? null,
12685
+ item.metadata ?? "{}",
12686
+ now,
12687
+ now
12688
+ );
12689
+ }
12690
+ const rows = native.prepare(
12691
+ `INSERT INTO graph_nodes (id, type, label, ref_id, metadata, created_at, updated_at) VALUES ${placeholders}
12692
+ ON CONFLICT(type, label) WHERE type != 'symbol' DO UPDATE SET ref_id = COALESCE(excluded.ref_id, graph_nodes.ref_id), metadata = excluded.metadata, updated_at = excluded.updated_at
12693
+ RETURNING id, label`
12694
+ ).all(...params);
12695
+ results.push(...rows.map((r) => ({ label: r.label, id: String(r.id) })));
12696
+ }
12697
+ return results;
12698
+ },
12597
12699
  async getGraphNode(id) {
12598
12700
  const row = native.prepare("SELECT * FROM graph_nodes WHERE id = ?").get(id);
12599
12701
  return row ? mapNodeRow(row) : null;
@@ -13193,6 +13295,93 @@ var init_local_workspace = __esm({
13193
13295
  }
13194
13296
  });
13195
13297
 
13298
+ // ../../packages/db/src/sqlite/remove-workspace.ts
13299
+ async function pathExists(target) {
13300
+ try {
13301
+ await import_promises5.default.stat(target);
13302
+ return true;
13303
+ } catch (err) {
13304
+ if (err instanceof Error && "code" in err && err.code === "ENOENT") {
13305
+ return false;
13306
+ }
13307
+ throw err;
13308
+ }
13309
+ }
13310
+ async function removeWorkspace(selector) {
13311
+ const repo = createRegistryRepository();
13312
+ const workspace = selector.id ? await repo.getWorkspace(selector.id) : selector.rootPath ? await repo.getWorkspaceByPath(selector.rootPath) : null;
13313
+ if (!workspace) return null;
13314
+ const warnings = [];
13315
+ if (workspace.indexingStatus === "running" || workspace.graphStatus === "running") {
13316
+ warnings.push(
13317
+ "Workspace appears to be indexing or building its graph; stop the process first to avoid stale writes."
13318
+ );
13319
+ }
13320
+ const dataDirPath = getLocalWorkspaceDir(workspace.rootPath);
13321
+ let dataDirRemoved = false;
13322
+ let rootPathExists = null;
13323
+ try {
13324
+ rootPathExists = await pathExists(workspace.rootPath);
13325
+ if (!rootPathExists) {
13326
+ warnings.push(`Workspace root path does not exist on disk: ${workspace.rootPath}`);
13327
+ } else {
13328
+ closeWorkspaceDb(workspace.rootPath);
13329
+ try {
13330
+ await import_promises5.default.rm(dataDirPath, { recursive: true, force: true });
13331
+ dataDirRemoved = !await pathExists(dataDirPath);
13332
+ } catch (err) {
13333
+ dataDirRemoved = false;
13334
+ warnings.push(
13335
+ `Failed to delete ${dataDirPath}: ${err instanceof Error ? err.message : String(err)}`
13336
+ );
13337
+ }
13338
+ }
13339
+ } catch (err) {
13340
+ warnings.push(
13341
+ `Could not check workspace root path ${workspace.rootPath}: ${err instanceof Error ? err.message : String(err)}`
13342
+ );
13343
+ }
13344
+ let unregistered = false;
13345
+ let rootPathAbsent = false;
13346
+ if (rootPathExists === false) {
13347
+ rootPathAbsent = true;
13348
+ } else if (rootPathExists === true) {
13349
+ try {
13350
+ rootPathAbsent = !await pathExists(workspace.rootPath);
13351
+ } catch (err) {
13352
+ warnings.push(
13353
+ `Could not re-check workspace root path ${workspace.rootPath}: ${err instanceof Error ? err.message : String(err)}`
13354
+ );
13355
+ }
13356
+ }
13357
+ if (dataDirRemoved || rootPathAbsent) {
13358
+ await repo.deleteWorkspace(workspace.id);
13359
+ unregistered = true;
13360
+ } else {
13361
+ warnings.push(
13362
+ "Workspace was not unregistered because the data directory could not be removed. Retry to attempt cleanup again."
13363
+ );
13364
+ }
13365
+ return {
13366
+ workspaceId: workspace.id,
13367
+ rootPath: workspace.rootPath,
13368
+ unregistered,
13369
+ dataDirRemoved,
13370
+ dataDirPath,
13371
+ warnings
13372
+ };
13373
+ }
13374
+ var import_promises5;
13375
+ var init_remove_workspace = __esm({
13376
+ "../../packages/db/src/sqlite/remove-workspace.ts"() {
13377
+ "use strict";
13378
+ import_promises5 = __toESM(require("fs/promises"), 1);
13379
+ init_local_workspace();
13380
+ init_repository();
13381
+ init_workspace_db();
13382
+ }
13383
+ });
13384
+
13196
13385
  // ../../packages/db/src/sqlite/index.ts
13197
13386
  var init_sqlite = __esm({
13198
13387
  "../../packages/db/src/sqlite/index.ts"() {
@@ -13202,6 +13391,7 @@ var init_sqlite = __esm({
13202
13391
  init_repository();
13203
13392
  init_secure_storage();
13204
13393
  init_local_workspace();
13394
+ init_remove_workspace();
13205
13395
  init_schema();
13206
13396
  }
13207
13397
  });
@@ -13286,7 +13476,7 @@ var require_package = __commonJS({
13286
13476
  var require_main = __commonJS({
13287
13477
  "../../node_modules/.pnpm/dotenv@16.6.1/node_modules/dotenv/lib/main.js"(exports2, module4) {
13288
13478
  "use strict";
13289
- var fs22 = require("fs");
13479
+ var fs23 = require("fs");
13290
13480
  var path24 = require("path");
13291
13481
  var os9 = require("os");
13292
13482
  var crypto4 = require("crypto");
@@ -13395,7 +13585,7 @@ var require_main = __commonJS({
13395
13585
  if (options && options.path && options.path.length > 0) {
13396
13586
  if (Array.isArray(options.path)) {
13397
13587
  for (const filepath of options.path) {
13398
- if (fs22.existsSync(filepath)) {
13588
+ if (fs23.existsSync(filepath)) {
13399
13589
  possibleVaultPath = filepath.endsWith(".vault") ? filepath : `${filepath}.vault`;
13400
13590
  }
13401
13591
  }
@@ -13405,7 +13595,7 @@ var require_main = __commonJS({
13405
13595
  } else {
13406
13596
  possibleVaultPath = path24.resolve(process.cwd(), ".env.vault");
13407
13597
  }
13408
- if (fs22.existsSync(possibleVaultPath)) {
13598
+ if (fs23.existsSync(possibleVaultPath)) {
13409
13599
  return possibleVaultPath;
13410
13600
  }
13411
13601
  return null;
@@ -13454,7 +13644,7 @@ var require_main = __commonJS({
13454
13644
  const parsedAll = {};
13455
13645
  for (const path25 of optionPaths) {
13456
13646
  try {
13457
- const parsed = DotenvModule.parse(fs22.readFileSync(path25, { encoding }));
13647
+ const parsed = DotenvModule.parse(fs23.readFileSync(path25, { encoding }));
13458
13648
  DotenvModule.populate(parsedAll, parsed, options);
13459
13649
  } catch (e) {
13460
13650
  if (debug) {
@@ -17796,7 +17986,7 @@ async function loadBrainConfig(startDir = process.cwd()) {
17796
17986
  retrieval: defaults3.retrieval
17797
17987
  };
17798
17988
  }
17799
- const source = await import_promises5.default.readFile(configFile, "utf8");
17989
+ const source = await import_promises6.default.readFile(configFile, "utf8");
17800
17990
  const sanitized = source.replace(/^import\s+type\s+.*$/gm, "").replace(/^import\s+.*$/gm, "").replace(/const\s+config\s*:\s*[^=]+=/m, "const config =").replace(/export default\s+/m, "const __default__ = ");
17801
17991
  const evaluator = new Function(
17802
17992
  `${sanitized}
@@ -17824,11 +18014,11 @@ async function getBrainSettings(startDir = process.cwd()) {
17824
18014
  retrieval: config2.retrieval ?? defaults2.retrieval
17825
18015
  };
17826
18016
  }
17827
- var import_promises5, import_node_path9, import_node_fs7, CONFIG_FILE_CANDIDATES;
18017
+ var import_promises6, import_node_path9, import_node_fs7, CONFIG_FILE_CANDIDATES;
17828
18018
  var init_load_brain_config = __esm({
17829
18019
  "../../packages/config/src/load-brain-config.ts"() {
17830
18020
  "use strict";
17831
- import_promises5 = __toESM(require("fs/promises"), 1);
18021
+ import_promises6 = __toESM(require("fs/promises"), 1);
17832
18022
  import_node_path9 = __toESM(require("path"), 1);
17833
18023
  import_node_fs7 = require("fs");
17834
18024
  init_types2();
@@ -30293,13 +30483,7 @@ function walkTree(root, config2, lines) {
30293
30483
  endLine: endRow,
30294
30484
  ...receiver ? { receiver } : {}
30295
30485
  });
30296
- extractCallsInNode(
30297
- node,
30298
- config2,
30299
- fullName,
30300
- calledIdentifiers,
30301
- callExpressions
30302
- );
30486
+ extractCallsInNode(node, config2, fullName, calledIdentifiers, callExpressions);
30303
30487
  const isContextNode = symbolRule.establishesContext || config2.contextNodeTypes.has(node.type);
30304
30488
  if (isContextNode) {
30305
30489
  const contextName = symbolRule.extractContextName ? symbolRule.extractContextName(node) ?? fullName : fullName;
@@ -30324,9 +30508,7 @@ function walkTree(root, config2, lines) {
30324
30508
  }
30325
30509
  function extractCallsInNode(symbolNode, config2, callerName, calledIdentifiers, callExpressions) {
30326
30510
  const nestedSymbolTypes = config2.symbolRules.map((r) => r.nodeType);
30327
- const nestedSymbols = symbolNode.descendantsOfType(nestedSymbolTypes).filter(
30328
- (n) => !(n.startIndex === symbolNode.startIndex && n.endIndex === symbolNode.endIndex)
30329
- );
30511
+ const nestedSymbols = symbolNode.descendantsOfType(nestedSymbolTypes).filter((n) => !(n.startIndex === symbolNode.startIndex && n.endIndex === symbolNode.endIndex));
30330
30512
  const callNodes = symbolNode.descendantsOfType(config2.callRule.nodeType);
30331
30513
  for (const callNode of callNodes) {
30332
30514
  const insideNested = nestedSymbols.some(
@@ -32613,11 +32795,11 @@ var require_source_map_support = __commonJS({
32613
32795
  "use strict";
32614
32796
  var SourceMapConsumer = require_source_map().SourceMapConsumer;
32615
32797
  var path24 = require("path");
32616
- var fs22;
32798
+ var fs23;
32617
32799
  try {
32618
- fs22 = require("fs");
32619
- if (!fs22.existsSync || !fs22.readFileSync) {
32620
- fs22 = null;
32800
+ fs23 = require("fs");
32801
+ if (!fs23.existsSync || !fs23.readFileSync) {
32802
+ fs23 = null;
32621
32803
  }
32622
32804
  } catch (err) {
32623
32805
  }
@@ -32688,7 +32870,7 @@ var require_source_map_support = __commonJS({
32688
32870
  }
32689
32871
  var contents = "";
32690
32872
  try {
32691
- if (!fs22) {
32873
+ if (!fs23) {
32692
32874
  var xhr = new XMLHttpRequest();
32693
32875
  xhr.open(
32694
32876
  "GET",
@@ -32700,8 +32882,8 @@ var require_source_map_support = __commonJS({
32700
32882
  if (xhr.readyState === 4 && xhr.status === 200) {
32701
32883
  contents = xhr.responseText;
32702
32884
  }
32703
- } else if (fs22.existsSync(path25)) {
32704
- contents = fs22.readFileSync(path25, "utf8");
32885
+ } else if (fs23.existsSync(path25)) {
32886
+ contents = fs23.readFileSync(path25, "utf8");
32705
32887
  }
32706
32888
  } catch (er) {
32707
32889
  }
@@ -32965,9 +33147,9 @@ var require_source_map_support = __commonJS({
32965
33147
  var line = +match2[2];
32966
33148
  var column = +match2[3];
32967
33149
  var contents = fileContentsCache[source];
32968
- if (!contents && fs22 && fs22.existsSync(source)) {
33150
+ if (!contents && fs23 && fs23.existsSync(source)) {
32969
33151
  try {
32970
- contents = fs22.readFileSync(source, "utf8");
33152
+ contents = fs23.readFileSync(source, "utf8");
32971
33153
  } catch (er) {
32972
33154
  contents = "";
32973
33155
  }
@@ -36739,10 +36921,10 @@ var require_typescript = __commonJS({
36739
36921
  function and2(f, g2) {
36740
36922
  return (arg) => f(arg) && g2(arg);
36741
36923
  }
36742
- function or2(...fs22) {
36924
+ function or2(...fs23) {
36743
36925
  return (...args) => {
36744
36926
  let lastResult;
36745
- for (const f of fs22) {
36927
+ for (const f of fs23) {
36746
36928
  lastResult = f(...args);
36747
36929
  if (lastResult) {
36748
36930
  return lastResult;
@@ -38317,7 +38499,7 @@ ${lanes.join("\n")}
38317
38499
  var tracing;
38318
38500
  var tracingEnabled;
38319
38501
  ((tracingEnabled2) => {
38320
- let fs22;
38502
+ let fs23;
38321
38503
  let traceCount = 0;
38322
38504
  let traceFd = 0;
38323
38505
  let mode;
@@ -38326,9 +38508,9 @@ ${lanes.join("\n")}
38326
38508
  const legend = [];
38327
38509
  function startTracing2(tracingMode, traceDir, configFilePath) {
38328
38510
  Debug.assert(!tracing, "Tracing already started");
38329
- if (fs22 === void 0) {
38511
+ if (fs23 === void 0) {
38330
38512
  try {
38331
- fs22 = require("fs");
38513
+ fs23 = require("fs");
38332
38514
  } catch (e) {
38333
38515
  throw new Error(`tracing requires having fs
38334
38516
  (original error: ${e.message || e})`);
@@ -38339,8 +38521,8 @@ ${lanes.join("\n")}
38339
38521
  if (legendPath === void 0) {
38340
38522
  legendPath = combinePaths(traceDir, "legend.json");
38341
38523
  }
38342
- if (!fs22.existsSync(traceDir)) {
38343
- fs22.mkdirSync(traceDir, { recursive: true });
38524
+ if (!fs23.existsSync(traceDir)) {
38525
+ fs23.mkdirSync(traceDir, { recursive: true });
38344
38526
  }
38345
38527
  const countPart = mode === "build" ? `.${process.pid}-${++traceCount}` : mode === "server" ? `.${process.pid}` : ``;
38346
38528
  const tracePath = combinePaths(traceDir, `trace${countPart}.json`);
@@ -38350,10 +38532,10 @@ ${lanes.join("\n")}
38350
38532
  tracePath,
38351
38533
  typesPath
38352
38534
  });
38353
- traceFd = fs22.openSync(tracePath, "w");
38535
+ traceFd = fs23.openSync(tracePath, "w");
38354
38536
  tracing = tracingEnabled2;
38355
38537
  const meta = { cat: "__metadata", ph: "M", ts: 1e3 * timestamp(), pid: 1, tid: 1 };
38356
- fs22.writeSync(
38538
+ fs23.writeSync(
38357
38539
  traceFd,
38358
38540
  "[\n" + [{ name: "process_name", args: { name: "tsc" }, ...meta }, { name: "thread_name", args: { name: "Main" }, ...meta }, { name: "TracingStartedInBrowser", ...meta, cat: "disabled-by-default-devtools.timeline" }].map((v) => JSON.stringify(v)).join(",\n")
38359
38541
  );
@@ -38362,10 +38544,10 @@ ${lanes.join("\n")}
38362
38544
  function stopTracing() {
38363
38545
  Debug.assert(tracing, "Tracing is not in progress");
38364
38546
  Debug.assert(!!typeCatalog.length === (mode !== "server"));
38365
- fs22.writeSync(traceFd, `
38547
+ fs23.writeSync(traceFd, `
38366
38548
  ]
38367
38549
  `);
38368
- fs22.closeSync(traceFd);
38550
+ fs23.closeSync(traceFd);
38369
38551
  tracing = void 0;
38370
38552
  if (typeCatalog.length) {
38371
38553
  dumpTypes(typeCatalog);
@@ -38437,11 +38619,11 @@ ${lanes.join("\n")}
38437
38619
  function writeEvent(eventType, phase, name, args, extras, time3 = 1e3 * timestamp()) {
38438
38620
  if (mode === "server" && phase === "checkTypes") return;
38439
38621
  mark("beginTracing");
38440
- fs22.writeSync(traceFd, `,
38622
+ fs23.writeSync(traceFd, `,
38441
38623
  {"pid":1,"tid":1,"ph":"${eventType}","cat":"${phase}","ts":${time3},"name":"${name}"`);
38442
- if (extras) fs22.writeSync(traceFd, `,${extras}`);
38443
- if (args) fs22.writeSync(traceFd, `,"args":${JSON.stringify(args)}`);
38444
- fs22.writeSync(traceFd, `}`);
38624
+ if (extras) fs23.writeSync(traceFd, `,${extras}`);
38625
+ if (args) fs23.writeSync(traceFd, `,"args":${JSON.stringify(args)}`);
38626
+ fs23.writeSync(traceFd, `}`);
38445
38627
  mark("endTracing");
38446
38628
  measure("Tracing", "beginTracing", "endTracing");
38447
38629
  }
@@ -38463,9 +38645,9 @@ ${lanes.join("\n")}
38463
38645
  var _a3, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s;
38464
38646
  mark("beginDumpTypes");
38465
38647
  const typesPath = legend[legend.length - 1].typesPath;
38466
- const typesFd = fs22.openSync(typesPath, "w");
38648
+ const typesFd = fs23.openSync(typesPath, "w");
38467
38649
  const recursionIdentityMap = /* @__PURE__ */ new Map();
38468
- fs22.writeSync(typesFd, "[");
38650
+ fs23.writeSync(typesFd, "[");
38469
38651
  const numTypes = types.length;
38470
38652
  for (let i = 0; i < numTypes; i++) {
38471
38653
  const type = types[i];
@@ -38561,13 +38743,13 @@ ${lanes.join("\n")}
38561
38743
  flags: Debug.formatTypeFlags(type.flags).split("|"),
38562
38744
  display
38563
38745
  };
38564
- fs22.writeSync(typesFd, JSON.stringify(descriptor));
38746
+ fs23.writeSync(typesFd, JSON.stringify(descriptor));
38565
38747
  if (i < numTypes - 1) {
38566
- fs22.writeSync(typesFd, ",\n");
38748
+ fs23.writeSync(typesFd, ",\n");
38567
38749
  }
38568
38750
  }
38569
- fs22.writeSync(typesFd, "]\n");
38570
- fs22.closeSync(typesFd);
38751
+ fs23.writeSync(typesFd, "]\n");
38752
+ fs23.closeSync(typesFd);
38571
38753
  mark("endDumpTypes");
38572
38754
  measure("Dump types", "beginDumpTypes", "endDumpTypes");
38573
38755
  }
@@ -38575,7 +38757,7 @@ ${lanes.join("\n")}
38575
38757
  if (!legendPath) {
38576
38758
  return;
38577
38759
  }
38578
- fs22.writeFileSync(legendPath, JSON.stringify(legend));
38760
+ fs23.writeFileSync(legendPath, JSON.stringify(legend));
38579
38761
  }
38580
38762
  tracingEnabled2.dumpLegend = dumpLegend;
38581
38763
  })(tracingEnabled || (tracingEnabled = {}));
@@ -248696,7 +248878,7 @@ var require_dist = __commonJS({
248696
248878
  enumerable: true
248697
248879
  }) : target, mod));
248698
248880
  var path24 = __toESM2(require("path"));
248699
- var fs22 = __toESM2(require("fs"));
248881
+ var fs23 = __toESM2(require("fs"));
248700
248882
  function cleanPath(path$1) {
248701
248883
  let normalized = (0, path24.normalize)(path$1);
248702
248884
  if (normalized.length > 1 && normalized[normalized.length - 1] === path24.sep) normalized = normalized.substring(0, normalized.length - 1);
@@ -248993,7 +249175,7 @@ var require_dist = __commonJS({
248993
249175
  symlinks: /* @__PURE__ */ new Map(),
248994
249176
  visited: [""].slice(0, 0),
248995
249177
  controller: new Aborter(),
248996
- fs: options.fs || fs22
249178
+ fs: options.fs || fs23
248997
249179
  };
248998
249180
  this.joinPath = build$7(this.root, options);
248999
249181
  this.pushDirectory = build$6(this.root, options);
@@ -249229,7 +249411,7 @@ var require_dist2 = __commonJS({
249229
249411
  value: mod,
249230
249412
  enumerable: true
249231
249413
  }) : target, mod));
249232
- var fs22 = require("fs");
249414
+ var fs23 = require("fs");
249233
249415
  var path24 = require("path");
249234
249416
  var url = require("url");
249235
249417
  var fdir = require_dist();
@@ -249477,12 +249659,12 @@ var require_dist2 = __commonJS({
249477
249659
  opts.cwd = (opts.cwd instanceof URL ? (0, url.fileURLToPath)(opts.cwd) : (0, path24.resolve)(opts.cwd)).replace(BACKSLASHES, "/");
249478
249660
  opts.ignore = ensureStringArray(opts.ignore);
249479
249661
  opts.fs && (opts.fs = {
249480
- readdir: opts.fs.readdir || fs22.readdir,
249481
- readdirSync: opts.fs.readdirSync || fs22.readdirSync,
249482
- realpath: opts.fs.realpath || fs22.realpath,
249483
- realpathSync: opts.fs.realpathSync || fs22.realpathSync,
249484
- stat: opts.fs.stat || fs22.stat,
249485
- statSync: opts.fs.statSync || fs22.statSync
249662
+ readdir: opts.fs.readdir || fs23.readdir,
249663
+ readdirSync: opts.fs.readdirSync || fs23.readdirSync,
249664
+ realpath: opts.fs.realpath || fs23.realpath,
249665
+ realpathSync: opts.fs.realpathSync || fs23.realpathSync,
249666
+ stat: opts.fs.stat || fs23.stat,
249667
+ statSync: opts.fs.statSync || fs23.statSync
249486
249668
  });
249487
249669
  if (opts.debug) log("globbing with options:", opts);
249488
249670
  return opts;
@@ -251413,30 +251595,30 @@ ${nodeLocation}` : message;
251413
251595
  yield path25;
251414
251596
  }
251415
251597
  }
251416
- var fs22 = runtime.fs;
251598
+ var fs23 = runtime.fs;
251417
251599
  var RealFileSystemHost = class {
251418
251600
  async delete(path25) {
251419
251601
  try {
251420
- await fs22.delete(path25);
251602
+ await fs23.delete(path25);
251421
251603
  } catch (err) {
251422
251604
  throw this.#getFileNotFoundErrorIfNecessary(err, path25);
251423
251605
  }
251424
251606
  }
251425
251607
  deleteSync(path25) {
251426
251608
  try {
251427
- fs22.deleteSync(path25);
251609
+ fs23.deleteSync(path25);
251428
251610
  } catch (err) {
251429
251611
  throw this.#getFileNotFoundErrorIfNecessary(err, path25);
251430
251612
  }
251431
251613
  }
251432
251614
  readDirSync(dirPath) {
251433
251615
  try {
251434
- const entries = fs22.readDirSync(dirPath);
251616
+ const entries = fs23.readDirSync(dirPath);
251435
251617
  for (const entry of entries) {
251436
251618
  entry.name = FileUtils.pathJoin(dirPath, entry.name);
251437
251619
  if (entry.isSymlink) {
251438
251620
  try {
251439
- const info = fs22.statSync(entry.name);
251621
+ const info = fs23.statSync(entry.name);
251440
251622
  if (info != null) {
251441
251623
  entry.isDirectory = info.isDirectory();
251442
251624
  entry.isFile = info.isFile();
@@ -251452,84 +251634,84 @@ ${nodeLocation}` : message;
251452
251634
  }
251453
251635
  async readFile(filePath, encoding = "utf-8") {
251454
251636
  try {
251455
- return await fs22.readFile(filePath, encoding);
251637
+ return await fs23.readFile(filePath, encoding);
251456
251638
  } catch (err) {
251457
251639
  throw this.#getFileNotFoundErrorIfNecessary(err, filePath);
251458
251640
  }
251459
251641
  }
251460
251642
  readFileSync(filePath, encoding = "utf-8") {
251461
251643
  try {
251462
- return fs22.readFileSync(filePath, encoding);
251644
+ return fs23.readFileSync(filePath, encoding);
251463
251645
  } catch (err) {
251464
251646
  throw this.#getFileNotFoundErrorIfNecessary(err, filePath);
251465
251647
  }
251466
251648
  }
251467
251649
  async writeFile(filePath, fileText) {
251468
- return fs22.writeFile(filePath, fileText);
251650
+ return fs23.writeFile(filePath, fileText);
251469
251651
  }
251470
251652
  writeFileSync(filePath, fileText) {
251471
- fs22.writeFileSync(filePath, fileText);
251653
+ fs23.writeFileSync(filePath, fileText);
251472
251654
  }
251473
251655
  mkdir(dirPath) {
251474
- return fs22.mkdir(dirPath);
251656
+ return fs23.mkdir(dirPath);
251475
251657
  }
251476
251658
  mkdirSync(dirPath) {
251477
- fs22.mkdirSync(dirPath);
251659
+ fs23.mkdirSync(dirPath);
251478
251660
  }
251479
251661
  move(srcPath, destPath) {
251480
- return fs22.move(srcPath, destPath);
251662
+ return fs23.move(srcPath, destPath);
251481
251663
  }
251482
251664
  moveSync(srcPath, destPath) {
251483
- fs22.moveSync(srcPath, destPath);
251665
+ fs23.moveSync(srcPath, destPath);
251484
251666
  }
251485
251667
  copy(srcPath, destPath) {
251486
- return fs22.copy(srcPath, destPath);
251668
+ return fs23.copy(srcPath, destPath);
251487
251669
  }
251488
251670
  copySync(srcPath, destPath) {
251489
- fs22.copySync(srcPath, destPath);
251671
+ fs23.copySync(srcPath, destPath);
251490
251672
  }
251491
251673
  async fileExists(filePath) {
251492
251674
  try {
251493
- return (await fs22.stat(filePath))?.isFile() ?? false;
251675
+ return (await fs23.stat(filePath))?.isFile() ?? false;
251494
251676
  } catch {
251495
251677
  return false;
251496
251678
  }
251497
251679
  }
251498
251680
  fileExistsSync(filePath) {
251499
251681
  try {
251500
- return fs22.statSync(filePath)?.isFile() ?? false;
251682
+ return fs23.statSync(filePath)?.isFile() ?? false;
251501
251683
  } catch {
251502
251684
  return false;
251503
251685
  }
251504
251686
  }
251505
251687
  async directoryExists(dirPath) {
251506
251688
  try {
251507
- return (await fs22.stat(dirPath))?.isDirectory() ?? false;
251689
+ return (await fs23.stat(dirPath))?.isDirectory() ?? false;
251508
251690
  } catch {
251509
251691
  return false;
251510
251692
  }
251511
251693
  }
251512
251694
  directoryExistsSync(dirPath) {
251513
251695
  try {
251514
- return fs22.statSync(dirPath)?.isDirectory() ?? false;
251696
+ return fs23.statSync(dirPath)?.isDirectory() ?? false;
251515
251697
  } catch {
251516
251698
  return false;
251517
251699
  }
251518
251700
  }
251519
251701
  realpathSync(path25) {
251520
- return fs22.realpathSync(path25);
251702
+ return fs23.realpathSync(path25);
251521
251703
  }
251522
251704
  getCurrentDirectory() {
251523
- return FileUtils.standardizeSlashes(fs22.getCurrentDirectory());
251705
+ return FileUtils.standardizeSlashes(fs23.getCurrentDirectory());
251524
251706
  }
251525
251707
  glob(patterns) {
251526
- return fs22.glob(backSlashesToForward(patterns));
251708
+ return fs23.glob(backSlashesToForward(patterns));
251527
251709
  }
251528
251710
  globSync(patterns) {
251529
- return fs22.globSync(backSlashesToForward(patterns));
251711
+ return fs23.globSync(backSlashesToForward(patterns));
251530
251712
  }
251531
251713
  isCaseSensitive() {
251532
- return fs22.isCaseSensitive();
251714
+ return fs23.isCaseSensitive();
251533
251715
  }
251534
251716
  #getDirectoryNotFoundErrorIfNecessary(err, path25) {
251535
251717
  return FileUtils.isNotExistsError(err) ? new exports2.errors.DirectoryNotFoundError(FileUtils.getStandardizedAbsolutePath(this, path25)) : err;
@@ -278636,8 +278818,8 @@ var require_utils4 = __commonJS({
278636
278818
  exports2.array = array2;
278637
278819
  var errno = require_errno();
278638
278820
  exports2.errno = errno;
278639
- var fs22 = require_fs();
278640
- exports2.fs = fs22;
278821
+ var fs23 = require_fs();
278822
+ exports2.fs = fs23;
278641
278823
  var path24 = require_path();
278642
278824
  exports2.path = path24;
278643
278825
  var pattern = require_pattern();
@@ -278821,12 +279003,12 @@ var require_fs2 = __commonJS({
278821
279003
  "use strict";
278822
279004
  Object.defineProperty(exports2, "__esModule", { value: true });
278823
279005
  exports2.createFileSystemAdapter = exports2.FILE_SYSTEM_ADAPTER = void 0;
278824
- var fs22 = require("fs");
279006
+ var fs23 = require("fs");
278825
279007
  exports2.FILE_SYSTEM_ADAPTER = {
278826
- lstat: fs22.lstat,
278827
- stat: fs22.stat,
278828
- lstatSync: fs22.lstatSync,
278829
- statSync: fs22.statSync
279008
+ lstat: fs23.lstat,
279009
+ stat: fs23.stat,
279010
+ lstatSync: fs23.lstatSync,
279011
+ statSync: fs23.statSync
278830
279012
  };
278831
279013
  function createFileSystemAdapter(fsMethods) {
278832
279014
  if (fsMethods === void 0) {
@@ -278843,12 +279025,12 @@ var require_settings = __commonJS({
278843
279025
  "../../node_modules/.pnpm/@nodelib+fs.stat@2.0.5/node_modules/@nodelib/fs.stat/out/settings.js"(exports2) {
278844
279026
  "use strict";
278845
279027
  Object.defineProperty(exports2, "__esModule", { value: true });
278846
- var fs22 = require_fs2();
279028
+ var fs23 = require_fs2();
278847
279029
  var Settings = class {
278848
279030
  constructor(_options = {}) {
278849
279031
  this._options = _options;
278850
279032
  this.followSymbolicLink = this._getValue(this._options.followSymbolicLink, true);
278851
- this.fs = fs22.createFileSystemAdapter(this._options.fs);
279033
+ this.fs = fs23.createFileSystemAdapter(this._options.fs);
278852
279034
  this.markSymbolicLink = this._getValue(this._options.markSymbolicLink, false);
278853
279035
  this.throwErrorOnBrokenSymbolicLink = this._getValue(this._options.throwErrorOnBrokenSymbolicLink, true);
278854
279036
  }
@@ -279005,8 +279187,8 @@ var require_utils5 = __commonJS({
279005
279187
  "use strict";
279006
279188
  Object.defineProperty(exports2, "__esModule", { value: true });
279007
279189
  exports2.fs = void 0;
279008
- var fs22 = require_fs3();
279009
- exports2.fs = fs22;
279190
+ var fs23 = require_fs3();
279191
+ exports2.fs = fs23;
279010
279192
  }
279011
279193
  });
279012
279194
 
@@ -279201,14 +279383,14 @@ var require_fs4 = __commonJS({
279201
279383
  "use strict";
279202
279384
  Object.defineProperty(exports2, "__esModule", { value: true });
279203
279385
  exports2.createFileSystemAdapter = exports2.FILE_SYSTEM_ADAPTER = void 0;
279204
- var fs22 = require("fs");
279386
+ var fs23 = require("fs");
279205
279387
  exports2.FILE_SYSTEM_ADAPTER = {
279206
- lstat: fs22.lstat,
279207
- stat: fs22.stat,
279208
- lstatSync: fs22.lstatSync,
279209
- statSync: fs22.statSync,
279210
- readdir: fs22.readdir,
279211
- readdirSync: fs22.readdirSync
279388
+ lstat: fs23.lstat,
279389
+ stat: fs23.stat,
279390
+ lstatSync: fs23.lstatSync,
279391
+ statSync: fs23.statSync,
279392
+ readdir: fs23.readdir,
279393
+ readdirSync: fs23.readdirSync
279212
279394
  };
279213
279395
  function createFileSystemAdapter(fsMethods) {
279214
279396
  if (fsMethods === void 0) {
@@ -279227,12 +279409,12 @@ var require_settings2 = __commonJS({
279227
279409
  Object.defineProperty(exports2, "__esModule", { value: true });
279228
279410
  var path24 = require("path");
279229
279411
  var fsStat = require_out();
279230
- var fs22 = require_fs4();
279412
+ var fs23 = require_fs4();
279231
279413
  var Settings = class {
279232
279414
  constructor(_options = {}) {
279233
279415
  this._options = _options;
279234
279416
  this.followSymbolicLinks = this._getValue(this._options.followSymbolicLinks, false);
279235
- this.fs = fs22.createFileSystemAdapter(this._options.fs);
279417
+ this.fs = fs23.createFileSystemAdapter(this._options.fs);
279236
279418
  this.pathSegmentSeparator = this._getValue(this._options.pathSegmentSeparator, path24.sep);
279237
279419
  this.stats = this._getValue(this._options.stats, false);
279238
279420
  this.throwErrorOnBrokenSymbolicLink = this._getValue(this._options.throwErrorOnBrokenSymbolicLink, true);
@@ -280613,16 +280795,16 @@ var require_settings4 = __commonJS({
280613
280795
  "use strict";
280614
280796
  Object.defineProperty(exports2, "__esModule", { value: true });
280615
280797
  exports2.DEFAULT_FILE_SYSTEM_ADAPTER = void 0;
280616
- var fs22 = require("fs");
280798
+ var fs23 = require("fs");
280617
280799
  var os9 = require("os");
280618
280800
  var CPU_COUNT = Math.max(os9.cpus().length, 1);
280619
280801
  exports2.DEFAULT_FILE_SYSTEM_ADAPTER = {
280620
- lstat: fs22.lstat,
280621
- lstatSync: fs22.lstatSync,
280622
- stat: fs22.stat,
280623
- statSync: fs22.statSync,
280624
- readdir: fs22.readdir,
280625
- readdirSync: fs22.readdirSync
280802
+ lstat: fs23.lstat,
280803
+ lstatSync: fs23.lstatSync,
280804
+ stat: fs23.stat,
280805
+ statSync: fs23.statSync,
280806
+ readdir: fs23.readdir,
280807
+ readdirSync: fs23.readdirSync
280626
280808
  };
280627
280809
  var Settings = class {
280628
280810
  constructor(_options = {}) {
@@ -280806,7 +280988,7 @@ async function scanWorkspaceFiles(input) {
280806
280988
  });
280807
280989
  const results = await Promise.all(
280808
280990
  entries.map(async (absolutePath) => {
280809
- const stat4 = await import_promises6.default.stat(absolutePath);
280991
+ const stat4 = await import_promises7.default.stat(absolutePath);
280810
280992
  return {
280811
280993
  absolutePath,
280812
280994
  relativePath: import_node_path13.default.relative(rootPath, absolutePath),
@@ -280817,12 +280999,12 @@ async function scanWorkspaceFiles(input) {
280817
280999
  );
280818
281000
  return results.sort((left, right) => left.relativePath.localeCompare(right.relativePath));
280819
281001
  }
280820
- var import_fast_glob, import_promises6, import_node_path13, import_node_fs10, DEFAULT_INCLUDE_PATTERNS, DEFAULT_EXCLUDE_PATTERNS;
281002
+ var import_fast_glob, import_promises7, import_node_path13, import_node_fs10, DEFAULT_INCLUDE_PATTERNS, DEFAULT_EXCLUDE_PATTERNS;
280821
281003
  var init_scanner = __esm({
280822
281004
  "../../packages/indexer/src/scanner.ts"() {
280823
281005
  "use strict";
280824
281006
  import_fast_glob = __toESM(require_out4(), 1);
280825
- import_promises6 = __toESM(require("fs/promises"), 1);
281007
+ import_promises7 = __toESM(require("fs/promises"), 1);
280826
281008
  import_node_path13 = __toESM(require("path"), 1);
280827
281009
  import_node_fs10 = require("fs");
280828
281010
  init_languages();
@@ -281073,7 +281255,14 @@ async function writeEmbeddingsToRepo(repo, chunkRows, provider) {
281073
281255
  const BATCH_SIZE = 50;
281074
281256
  let totalWritten = 0;
281075
281257
  let failedBatches = 0;
281258
+ const totalBatches = Math.ceil(toEmbed.length / BATCH_SIZE);
281076
281259
  for (let i = 0; i < toEmbed.length; i += BATCH_SIZE) {
281260
+ const batchNum = Math.floor(i / BATCH_SIZE) + 1;
281261
+ if (batchNum % 10 === 0 || batchNum === totalBatches) {
281262
+ process.stdout.write(
281263
+ `\r[embedding] batch ${batchNum}/${totalBatches} (${totalWritten} written)`
281264
+ );
281265
+ }
281077
281266
  const batch = toEmbed.slice(i, i + BATCH_SIZE);
281078
281267
  try {
281079
281268
  const vectors = await provider.embed(
@@ -281118,6 +281307,9 @@ async function writeEmbeddingsToRepo(repo, chunkRows, provider) {
281118
281307
  );
281119
281308
  }
281120
281309
  }
281310
+ if (totalBatches > 0) {
281311
+ process.stdout.write("\n");
281312
+ }
281121
281313
  return { written: totalWritten + reusedWritten, failedBatches };
281122
281314
  }
281123
281315
  async function parseInline(tasks, onProgress) {
@@ -281161,6 +281353,15 @@ async function indexWorkspace(input) {
281161
281353
  const excludeGlobs = workspace.excludeGlobs || configuredWorkspace?.exclude.join("\n") || "";
281162
281354
  const embeddingProvider = await getEmbeddingProvider();
281163
281355
  const runMode = input.mode ?? "incremental";
281356
+ if (embeddingProvider) {
281357
+ process.stdout.write(
281358
+ `[embedding] provider=${embeddingProvider.provider} model=${embeddingProvider.model}
281359
+ `
281360
+ );
281361
+ } else {
281362
+ process.stdout.write(`[embedding] disabled (no provider configured)
281363
+ `);
281364
+ }
281164
281365
  const reportProgress = async (message, progress) => {
281165
281366
  await input.onProgress?.({ message, progress });
281166
281367
  };
@@ -281226,7 +281427,7 @@ async function indexWorkspace(input) {
281226
281427
  const i = readIndex++;
281227
281428
  fileContents.set(
281228
281429
  filesToRead[i].relativePath,
281229
- await import_promises7.default.readFile(filesToRead[i].absolutePath, "utf8")
281430
+ await import_promises8.default.readFile(filesToRead[i].absolutePath, "utf8")
281230
281431
  );
281231
281432
  }
281232
281433
  }
@@ -281358,6 +281559,8 @@ async function indexWorkspace(input) {
281358
281559
  const chunkNodeIds = await repo.insertGraphNodesBatch(chunkNodeInputs);
281359
281560
  const edges = [];
281360
281561
  const reusedSymbolIds = /* @__PURE__ */ new Set();
281562
+ const newSymbolInputs = [];
281563
+ const pendingSymbolEdges = [];
281361
281564
  for (const [ci, chunkId] of chunkIds.entries()) {
281362
281565
  const chunkNodeId = chunkNodeIds[ci];
281363
281566
  edges.push({ fromNodeId: fileNodeId, toNodeId: chunkNodeId, type: "contains" });
@@ -281366,7 +281569,7 @@ async function indexWorkspace(input) {
281366
281569
  if (symbolName) {
281367
281570
  const fileSymbolKey = `${file.relativePath}\0${symbolName}`;
281368
281571
  let symbolNodeId = symbolNodeIdsByFileAndName.get(fileSymbolKey);
281369
- if (!symbolNodeId) {
281572
+ if (symbolNodeIdsByFileAndName.has(fileSymbolKey) === false) {
281370
281573
  const existingSymbolId = fileExistingSymbols.get(symbolName);
281371
281574
  if (existingSymbolId) {
281372
281575
  repo.updateSymbolNode(
@@ -281381,7 +281584,7 @@ async function indexWorkspace(input) {
281381
281584
  );
281382
281585
  symbolNodeId = existingSymbolId;
281383
281586
  } else {
281384
- symbolNodeId = await repo.upsertGraphNode({
281587
+ newSymbolInputs.push({
281385
281588
  type: "symbol",
281386
281589
  label: symbolName,
281387
281590
  refId: chunkId,
@@ -281390,14 +281593,41 @@ async function indexWorkspace(input) {
281390
281593
  filePath: file.relativePath,
281391
281594
  language: indexed.language,
281392
281595
  parser: indexed.parser
281393
- })
281596
+ }),
281597
+ _chunkIndex: ci
281394
281598
  });
281599
+ symbolNodeId = "";
281395
281600
  }
281396
281601
  symbolNodeIdsByFileAndName.set(fileSymbolKey, symbolNodeId);
281602
+ } else {
281603
+ symbolNodeId = symbolNodeIdsByFileAndName.get(fileSymbolKey) ?? "";
281397
281604
  }
281398
281605
  reusedSymbolIds.add(symbolNodeId);
281606
+ const definesEdgeIdx = edges.length;
281399
281607
  edges.push({ fromNodeId: fileNodeId, toNodeId: symbolNodeId, type: "defines" });
281608
+ const representedByEdgeIdx = edges.length;
281400
281609
  edges.push({ fromNodeId: symbolNodeId, toNodeId: chunkNodeId, type: "represented_by" });
281610
+ if (symbolNodeId === "") {
281611
+ pendingSymbolEdges.push({ label: symbolName, definesEdgeIdx, representedByEdgeIdx });
281612
+ }
281613
+ }
281614
+ }
281615
+ if (newSymbolInputs.length > 0) {
281616
+ const symbolIds = await repo.insertGraphNodesBatch(
281617
+ newSymbolInputs.map(({ _chunkIndex, ...rest }) => rest)
281618
+ );
281619
+ for (let si = 0; si < newSymbolInputs.length; si++) {
281620
+ const input2 = newSymbolInputs[si];
281621
+ const fileSymbolKey = `${file.relativePath}\0${input2.label}`;
281622
+ const newId = symbolIds[si];
281623
+ symbolNodeIdsByFileAndName.set(fileSymbolKey, newId);
281624
+ reusedSymbolIds.add(newId);
281625
+ }
281626
+ for (const pending of pendingSymbolEdges) {
281627
+ const newId = symbolNodeIdsByFileAndName.get(`${file.relativePath}\0${pending.label}`);
281628
+ if (!newId) continue;
281629
+ edges[pending.definesEdgeIdx].toNodeId = newId;
281630
+ edges[pending.representedByEdgeIdx].fromNodeId = newId;
281401
281631
  }
281402
281632
  }
281403
281633
  const staleSymbolIds = [];
@@ -281409,6 +281639,8 @@ async function indexWorkspace(input) {
281409
281639
  if (staleSymbolIds.length > 0) {
281410
281640
  repo.deleteGraphNodesByIds(staleSymbolIds);
281411
281641
  }
281642
+ const batchNodeInputs = [];
281643
+ const importEdgeInputs = [];
281412
281644
  for (const importPath of indexed.importPaths) {
281413
281645
  if (typeof importPath !== "string" || importPath.length === 0) continue;
281414
281646
  const resolvedImportPath = workspaceFileResolver?.resolveImport(
@@ -281417,25 +281649,43 @@ async function indexWorkspace(input) {
281417
281649
  indexed.language ?? void 0
281418
281650
  );
281419
281651
  if (!resolvedImportPath) continue;
281420
- const targetNodeId = await repo.upsertGraphNode({
281652
+ batchNodeInputs.push({
281421
281653
  type: "file",
281422
281654
  label: resolvedImportPath,
281423
281655
  metadata: JSON.stringify({ path: resolvedImportPath })
281424
281656
  });
281425
- edges.push({
281426
- fromNodeId: fileNodeId,
281427
- toNodeId: targetNodeId,
281428
- type: "imports",
281429
- metadata: JSON.stringify({ importPath })
281430
- });
281657
+ importEdgeInputs.push({ importPath, resolvedImportPath });
281431
281658
  }
281432
281659
  for (const link of indexed.wikilinks) {
281433
- const entityNodeId = await repo.upsertGraphNode({
281660
+ batchNodeInputs.push({
281434
281661
  type: "entity",
281435
281662
  label: link,
281436
281663
  metadata: "{}"
281437
281664
  });
281438
- edges.push({ fromNodeId: fileNodeId, toNodeId: entityNodeId, type: "mentions" });
281665
+ }
281666
+ if (batchNodeInputs.length > 0) {
281667
+ const upsertedNodes = await repo.upsertGraphNodesBatch(batchNodeInputs);
281668
+ const nodeByLabel = /* @__PURE__ */ new Map();
281669
+ for (const node of upsertedNodes) {
281670
+ nodeByLabel.set(node.label, node.id);
281671
+ }
281672
+ for (const { importPath, resolvedImportPath } of importEdgeInputs) {
281673
+ const targetNodeId = nodeByLabel.get(resolvedImportPath);
281674
+ if (targetNodeId) {
281675
+ edges.push({
281676
+ fromNodeId: fileNodeId,
281677
+ toNodeId: targetNodeId,
281678
+ type: "imports",
281679
+ metadata: JSON.stringify({ importPath })
281680
+ });
281681
+ }
281682
+ }
281683
+ for (const link of indexed.wikilinks) {
281684
+ const entityNodeId = nodeByLabel.get(link);
281685
+ if (entityNodeId) {
281686
+ edges.push({ fromNodeId: fileNodeId, toNodeId: entityNodeId, type: "mentions" });
281687
+ }
281688
+ }
281439
281689
  }
281440
281690
  const edgeSet = /* @__PURE__ */ new Set();
281441
281691
  const dedupedEdges = edges.filter((e) => {
@@ -281463,7 +281713,11 @@ async function indexWorkspace(input) {
281463
281713
  filesUpdated += 1;
281464
281714
  }
281465
281715
  });
281466
- if (allChunkRowsForEmbeddings.length > 0) {
281716
+ if (allChunkRowsForEmbeddings.length > 0 && embeddingProvider) {
281717
+ await reportProgress(
281718
+ `Embedding ${allChunkRowsForEmbeddings.length} chunks via ${embeddingProvider.provider}/${embeddingProvider.model}...`,
281719
+ 90
281720
+ );
281467
281721
  const embeddingResult = await writeEmbeddingsToRepo(
281468
281722
  repo,
281469
281723
  allChunkRowsForEmbeddings,
@@ -281473,10 +281727,12 @@ async function indexWorkspace(input) {
281473
281727
  embeddingFailures += embeddingResult.failedBatches;
281474
281728
  }
281475
281729
  if (bulkWriteMode) {
281730
+ await reportProgress("Rebuilding FTS index...", 93);
281476
281731
  repo.restoreFtsTriggers();
281477
281732
  repo.setOptimizedWriteMode(false);
281478
281733
  bulkWriteMode = false;
281479
281734
  }
281735
+ await reportProgress("Resolving call edges...", 95);
281480
281736
  const globalSymbolNodes = await repo.loadAllSymbolNodes();
281481
281737
  const insertedCallEdges = /* @__PURE__ */ new Set();
281482
281738
  const callEdges = [];
@@ -281566,11 +281822,11 @@ async function indexWorkspace(input) {
281566
281822
  embeddingFailures
281567
281823
  };
281568
281824
  }
281569
- var import_promises7, import_node_path14, RESOLVABLE_SOURCE_EXTENSIONS;
281825
+ var import_promises8, import_node_path14, RESOLVABLE_SOURCE_EXTENSIONS;
281570
281826
  var init_index_workspace = __esm({
281571
281827
  "../../packages/indexer/src/index-workspace.ts"() {
281572
281828
  "use strict";
281573
- import_promises7 = __toESM(require("fs/promises"), 1);
281829
+ import_promises8 = __toESM(require("fs/promises"), 1);
281574
281830
  import_node_path14 = __toESM(require("path"), 1);
281575
281831
  init_src2();
281576
281832
  init_src3();
@@ -295468,12 +295724,12 @@ var require_dist3 = __commonJS({
295468
295724
  throw new Error(`Unknown format "${name}"`);
295469
295725
  return f;
295470
295726
  };
295471
- function addFormats(ajv, list, fs22, exportName) {
295727
+ function addFormats(ajv, list, fs23, exportName) {
295472
295728
  var _a3;
295473
295729
  var _b;
295474
295730
  (_a3 = (_b = ajv.opts.code).formats) !== null && _a3 !== void 0 ? _a3 : _b.formats = (0, codegen_1._)`require("ajv-formats/dist/formats").${exportName}`;
295475
295731
  for (const f of list)
295476
- ajv.addFormat(f, fs22[f]);
295732
+ ajv.addFormat(f, fs23[f]);
295477
295733
  }
295478
295734
  module4.exports = exports2 = formatsPlugin;
295479
295735
  Object.defineProperty(exports2, "__esModule", { value: true });
@@ -296666,6 +296922,19 @@ function createMcpServer(options) {
296666
296922
  },
296667
296923
  required: []
296668
296924
  }
296925
+ },
296926
+ {
296927
+ name: "remove_workspace",
296928
+ description: "Remove a workspace from the registry and delete its .openez data directory. Destructive and irreversible: call only with confirm: true after explicit user approval.",
296929
+ inputSchema: {
296930
+ type: "object",
296931
+ properties: {
296932
+ workspaceId: { type: "string" },
296933
+ path: { type: "string" },
296934
+ confirm: { type: "boolean" }
296935
+ },
296936
+ required: ["confirm"]
296937
+ }
296669
296938
  }
296670
296939
  ]
296671
296940
  }));
@@ -296839,6 +297108,34 @@ ${result.answerContext}`
296839
297108
  const summary = await indexWorkspace({ workspaceId: workspace.id, mode: input.mode });
296840
297109
  return jsonResponse(summary);
296841
297110
  }
297111
+ case "remove_workspace": {
297112
+ const input = removeWorkspaceSchema.parse(request.params.arguments ?? {});
297113
+ if (input.confirm !== true) {
297114
+ return jsonResponse({
297115
+ error: "remove_workspace permanently deletes the registry entry and the workspace's .openez data directory. Requires confirm: true.",
297116
+ hint: "Ask the user for approval, then call remove_workspace again with confirm: true."
297117
+ });
297118
+ }
297119
+ if (input.workspaceId && input.path) {
297120
+ return jsonResponse({ error: "Pass either workspaceId or path, not both." });
297121
+ }
297122
+ if (!input.workspaceId && !input.path) {
297123
+ return jsonResponse({ error: "Pass an explicit workspaceId or path." });
297124
+ }
297125
+ const report = await removeWorkspace({
297126
+ id: input.workspaceId,
297127
+ rootPath: input.path ? import_node_path15.default.resolve(input.path) : void 0
297128
+ });
297129
+ if (!report) {
297130
+ return jsonResponse({
297131
+ error: "Workspace not found",
297132
+ workspaceId: input.workspaceId,
297133
+ path: input.path
297134
+ });
297135
+ }
297136
+ stopWatcherForWorkspace(report.workspaceId);
297137
+ return jsonResponse(report);
297138
+ }
296842
297139
  default:
296843
297140
  throw new Error(`Unknown tool: ${request.params.name}`);
296844
297141
  }
@@ -296877,15 +297174,18 @@ async function autoIndexAndSync(searchRoot) {
296877
297174
  if (!WATCH_ENABLED) {
296878
297175
  return;
296879
297176
  }
296880
- let debounceTimer = null;
297177
+ const debounceTimer = null;
296881
297178
  const watcher = esm_default.watch(resolvedRoot, {
296882
297179
  ignored: WATCH_IGNORE_PATTERNS,
296883
297180
  ignoreInitial: true,
296884
297181
  persistent: true
296885
297182
  });
297183
+ activeWatcher = { watcher, workspaceId: workspace.id, rootPath: resolvedRoot, debounceTimer };
296886
297184
  const triggerReindex = () => {
296887
- if (debounceTimer) clearTimeout(debounceTimer);
296888
- debounceTimer = setTimeout(async () => {
297185
+ const current = activeWatcher;
297186
+ if (!current) return;
297187
+ if (current.debounceTimer) clearTimeout(current.debounceTimer);
297188
+ current.debounceTimer = setTimeout(async () => {
296889
297189
  try {
296890
297190
  await indexWorkspace({ workspaceId: workspace.id, mode: "incremental" });
296891
297191
  } catch {
@@ -296900,9 +297200,17 @@ async function autoIndexAndSync(searchRoot) {
296900
297200
  `OpenEZ MCP auto-sync watcher disabled: ${error2 instanceof Error ? error2.message : String(error2)}`
296901
297201
  );
296902
297202
  void watcher.close();
297203
+ activeWatcher = null;
296903
297204
  });
296904
297205
  }
296905
- var import_node_fs11, import_node_path15, MIN_RESPONSE_TOKENS, codeQuerySchema, codeContextSchema, graphNeighborsSchema, memoryWriteSchema, memoryRecallSchema, indexWorkspaceSchema, MCP_CATCHUP_INTERVAL_MS, catchupState, WATCH_DEBOUNCE_MS, WATCH_ENABLED, WATCH_IGNORE_PATTERNS;
297206
+ function stopWatcherForWorkspace(workspaceId) {
297207
+ if (activeWatcher && activeWatcher.workspaceId === workspaceId) {
297208
+ if (activeWatcher.debounceTimer) clearTimeout(activeWatcher.debounceTimer);
297209
+ void activeWatcher.watcher.close();
297210
+ activeWatcher = null;
297211
+ }
297212
+ }
297213
+ var import_node_fs11, import_node_path15, MIN_RESPONSE_TOKENS, codeQuerySchema, codeContextSchema, graphNeighborsSchema, memoryWriteSchema, memoryRecallSchema, indexWorkspaceSchema, removeWorkspaceSchema, MCP_CATCHUP_INTERVAL_MS, catchupState, activeWatcher, WATCH_DEBOUNCE_MS, WATCH_ENABLED, WATCH_IGNORE_PATTERNS;
296906
297214
  var init_mcp_core = __esm({
296907
297215
  "../mcp/src/mcp-core.ts"() {
296908
297216
  "use strict";
@@ -296970,8 +297278,14 @@ var init_mcp_core = __esm({
296970
297278
  path: external_exports.string().optional(),
296971
297279
  mode: external_exports.enum(["incremental", "full"]).optional()
296972
297280
  });
297281
+ removeWorkspaceSchema = external_exports.object({
297282
+ workspaceId: external_exports.string().optional(),
297283
+ path: external_exports.string().optional(),
297284
+ confirm: external_exports.boolean().optional()
297285
+ });
296973
297286
  MCP_CATCHUP_INTERVAL_MS = Number(process.env.OPENEZ_MCP_CATCHUP_INTERVAL_MS ?? 5e3);
296974
297287
  catchupState = /* @__PURE__ */ new Map();
297288
+ activeWatcher = null;
296975
297289
  WATCH_DEBOUNCE_MS = 2e3;
296976
297290
  WATCH_ENABLED = ["1", "true", "yes"].includes(
296977
297291
  (process.env.OPENEZ_MCP_WATCH ?? "").toLowerCase()
@@ -296995,7 +297309,7 @@ __export(mcp_bridge_exports, {
296995
297309
  startMcpServer: () => startMcpServer
296996
297310
  });
296997
297311
  async function startMcpServer(defaultPath, version4) {
296998
- await createAndStartMcpServer({ defaultPath, version: version4, build: "cc56c89-dirty" });
297312
+ await createAndStartMcpServer({ defaultPath, version: version4, build: "56dde1b-dirty" });
296999
297313
  }
297000
297314
  var init_mcp_bridge = __esm({
297001
297315
  "src/mcp-bridge.ts"() {
@@ -300965,21 +301279,73 @@ function initializeRegistrySchema2(db) {
300965
301279
  node_count INTEGER NOT NULL DEFAULT 0,
300966
301280
  edge_count INTEGER NOT NULL DEFAULT 0,
300967
301281
  last_error TEXT,
301282
+ pinned_at TEXT,
301283
+ pin_order INTEGER,
300968
301284
  created_at TEXT NOT NULL DEFAULT (datetime('now')),
300969
301285
  updated_at TEXT NOT NULL DEFAULT (datetime('now'))
300970
301286
  );
300971
301287
  CREATE UNIQUE INDEX IF NOT EXISTS idx_workspaces_root_path ON workspaces(root_path);
300972
301288
  `);
301289
+ migrateRegistryColumns2(db);
301290
+ }
301291
+ function migrateRegistryColumns2(db) {
301292
+ const getColumns = () => new Set(
301293
+ db.prepare("PRAGMA table_info(workspaces)").all().map(
301294
+ (row) => row.name
301295
+ )
301296
+ );
301297
+ const addColumnIfMissing = (name, definition) => {
301298
+ if (getColumns().has(name)) return;
301299
+ try {
301300
+ db.exec(`ALTER TABLE workspaces ADD COLUMN ${definition}`);
301301
+ } catch (err) {
301302
+ if (!getColumns().has(name)) {
301303
+ throw err;
301304
+ }
301305
+ }
301306
+ };
301307
+ addColumnIfMissing("pinned_at", "pinned_at TEXT");
301308
+ addColumnIfMissing("pin_order", "pin_order INTEGER");
301309
+ const unbackfilled = db.prepare(
301310
+ "SELECT id FROM workspaces WHERE pinned_at IS NOT NULL AND pin_order IS NULL ORDER BY pinned_at DESC"
301311
+ ).all();
301312
+ if (unbackfilled.length > 0) {
301313
+ const maxRow = db.prepare("SELECT MAX(pin_order) AS max_order FROM workspaces WHERE pin_order IS NOT NULL").get();
301314
+ let next = (maxRow?.max_order ?? 0) + 1;
301315
+ const stmt = db.prepare("UPDATE workspaces SET pin_order = ? WHERE id = ?");
301316
+ for (const row of unbackfilled) {
301317
+ stmt.run(next, row.id);
301318
+ next += 1;
301319
+ }
301320
+ }
300973
301321
  }
300974
301322
  function getRegistryDb2() {
300975
301323
  if (!registryDb2) {
300976
301324
  const dbPath = resolveRegistryDbPath2();
300977
301325
  ensureDirForFile(dbPath);
300978
- registryDb2 = openSqlite(dbPath);
300979
- initializeRegistrySchema2(registryDb2);
301326
+ const db = openSqlite(dbPath);
301327
+ try {
301328
+ initializeRegistrySchema2(db);
301329
+ registryDb2 = db;
301330
+ } catch (err) {
301331
+ db.close();
301332
+ registryDb2 = null;
301333
+ throw err;
301334
+ }
300980
301335
  }
300981
301336
  return registryDb2;
300982
301337
  }
301338
+ function closeWorkspaceDb2(rootPath) {
301339
+ const normalized = normalizeRootPath2(rootPath);
301340
+ const db = workspaceDbs.get(normalized);
301341
+ if (db) {
301342
+ try {
301343
+ db.close();
301344
+ } catch {
301345
+ }
301346
+ workspaceDbs.delete(normalized);
301347
+ }
301348
+ }
300983
301349
  function resolveWorkspaceDbPath(rootPath) {
300984
301350
  return import_node_path17.default.join(rootPath, ".openez", "index.sqlite");
300985
301351
  }
@@ -301145,12 +301511,16 @@ function mapWorkspace(row) {
301145
301511
  nodeCount: Number(row.node_count ?? 0),
301146
301512
  edgeCount: Number(row.edge_count ?? 0),
301147
301513
  lastError: row.last_error ? String(row.last_error) : void 0,
301514
+ pinnedAt: row.pinned_at ? String(row.pinned_at) : void 0,
301515
+ pinOrder: row.pin_order != null ? Number(row.pin_order) : void 0,
301148
301516
  createdAt: String(row.created_at),
301149
301517
  updatedAt: String(row.updated_at)
301150
301518
  };
301151
301519
  }
301152
301520
  function listRegistryWorkspaces() {
301153
- const rows = getRegistryDb2().prepare("SELECT * FROM workspaces ORDER BY created_at DESC").all();
301521
+ const rows = getRegistryDb2().prepare(
301522
+ "SELECT * FROM workspaces ORDER BY (pinned_at IS NULL), pin_order DESC, pinned_at DESC, created_at DESC"
301523
+ ).all();
301154
301524
  return rows.map(mapWorkspace);
301155
301525
  }
301156
301526
  function getRegistryWorkspace(id) {
@@ -301195,8 +301565,19 @@ function ensureRegistryWorkspace(input) {
301195
301565
  );
301196
301566
  return getRegistryWorkspace(nextId);
301197
301567
  }
301198
- function deleteRegistryWorkspace(id) {
301199
- getRegistryDb2().prepare("DELETE FROM workspaces WHERE id = ?").run(id);
301568
+ function setRegistryWorkspacePinned(id, pinned) {
301569
+ const db = getRegistryDb2();
301570
+ if (pinned) {
301571
+ const maxRow = db.prepare("SELECT MAX(pin_order) AS max_order FROM workspaces WHERE pin_order IS NOT NULL").get();
301572
+ const nextOrder = (maxRow?.max_order ?? 0) + 1;
301573
+ db.prepare("UPDATE workspaces SET pinned_at = ?, pin_order = ? WHERE id = ?").run(
301574
+ (/* @__PURE__ */ new Date()).toISOString(),
301575
+ nextOrder,
301576
+ id
301577
+ );
301578
+ } else {
301579
+ db.prepare("UPDATE workspaces SET pinned_at = NULL, pin_order = NULL WHERE id = ?").run(id);
301580
+ }
301200
301581
  }
301201
301582
  function mapRunRow(row, kind) {
301202
301583
  return {
@@ -301488,6 +301869,7 @@ function mapWorkspace2(ws) {
301488
301869
  nodeCount: ws.nodeCount,
301489
301870
  edgeCount: ws.edgeCount,
301490
301871
  lastError: ws.lastError ?? null,
301872
+ pinnedAt: ws.pinnedAt ?? null,
301491
301873
  createdAt: new Date(ws.createdAt),
301492
301874
  updatedAt: new Date(ws.updatedAt)
301493
301875
  };
@@ -301775,14 +302157,34 @@ var init_server3 = __esm({
301775
302157
  return c.json({ success: false, error: "Failed to create workspace" });
301776
302158
  }
301777
302159
  });
301778
- app.delete("/api/workspaces/:id", (c) => {
302160
+ app.delete("/api/workspaces/:id", async (c) => {
301779
302161
  try {
301780
302162
  const id = c.req.param("id");
301781
- deleteRegistryWorkspace(id);
301782
- return c.json({ success: true });
302163
+ const ws = getRegistryWorkspace(id);
302164
+ if (ws) closeWorkspaceDb2(ws.rootPath);
302165
+ const report = await removeWorkspace({ id });
302166
+ if (!report) return c.json({ success: false, error: "Workspace not found" }, 404);
302167
+ return c.json({ success: true, report });
301783
302168
  } catch (err) {
301784
302169
  console.error("Failed to delete workspace:", err);
301785
- return c.json({ success: false, error: "Failed to delete workspace" });
302170
+ return c.json({ success: false, error: "Failed to delete workspace" }, 500);
302171
+ }
302172
+ });
302173
+ app.patch("/api/workspaces/:id/pin", async (c) => {
302174
+ try {
302175
+ const id = c.req.param("id");
302176
+ const body = await c.req.json().catch(() => null);
302177
+ if (typeof body?.pinned !== "boolean") {
302178
+ return c.json({ success: false, error: "pinned (boolean) is required" }, 400);
302179
+ }
302180
+ if (!getRegistryWorkspace(id)) {
302181
+ return c.json({ success: false, error: "Workspace not found" }, 404);
302182
+ }
302183
+ setRegistryWorkspacePinned(id, body.pinned);
302184
+ return c.json({ success: true });
302185
+ } catch (err) {
302186
+ console.error("Failed to pin workspace:", err);
302187
+ return c.json({ success: false, error: "Failed to pin workspace" });
301786
302188
  }
301787
302189
  });
301788
302190
  app.get("/api/workspaces/:id/index", (c) => {
@@ -303394,6 +303796,7 @@ var init_setup_devin = __esm({
303394
303796
  // src/cli.ts
303395
303797
  var import_node_fs21 = __toESM(require("fs"), 1);
303396
303798
  var import_node_path25 = __toESM(require("path"), 1);
303799
+ var import_node_readline = __toESM(require("readline"), 1);
303397
303800
  init_esm2();
303398
303801
 
303399
303802
  // ../../node_modules/.pnpm/commander@14.0.3/node_modules/commander/esm.mjs
@@ -303614,10 +304017,62 @@ program2.command("list").description("List all registered workspaces").action(as
303614
304017
  console.log("Registered workspaces:");
303615
304018
  for (const workspace of workspaces2) {
303616
304019
  const statusIcon = workspace.status === "indexed" ? "\u2713" : workspace.status === "error" ? "\u2717" : "\u25CB";
303617
- console.log(` ${statusIcon} ${workspace.name} (${workspace.id})`);
304020
+ const pinMarker = workspace.pinnedAt ? " \u{1F4CC}" : "";
304021
+ console.log(` ${statusIcon}${pinMarker} ${workspace.name} (${workspace.id})`);
303618
304022
  console.log(` ${workspace.rootPath}`);
303619
304023
  }
303620
304024
  });
304025
+ function confirmDestructive(prompt) {
304026
+ if (!process.stdin.isTTY) return Promise.reject(new Error("Confirmation required; rerun with --yes."));
304027
+ const rl = import_node_readline.default.createInterface({ input: process.stdin, output: process.stdout });
304028
+ return new Promise((resolve4) => {
304029
+ rl.question(`${prompt} [y/N] `, (answer) => {
304030
+ rl.close();
304031
+ const normalized = answer.trim().toLowerCase();
304032
+ resolve4(normalized === "y" || normalized === "yes");
304033
+ });
304034
+ });
304035
+ }
304036
+ program2.command("remove").alias("rm").description("Remove a workspace from the registry and delete its .openez data directory").argument("[path]", "path to the workspace directory", process.cwd()).option("--id <workspaceId>", "workspace id (takes precedence over path)").option("-y, --yes", "skip confirmation prompt").action(async (targetPath, options) => {
304037
+ const registry2 = createRegistryRepository();
304038
+ const resolvedPath = import_node_path25.default.resolve(targetPath);
304039
+ const workspace = options.id ? await registry2.getWorkspace(options.id) : await registry2.getWorkspaceByPath(resolvedPath);
304040
+ if (!workspace) {
304041
+ console.error(`Error: no registered workspace found for ${options.id ?? resolvedPath}`);
304042
+ process.exit(1);
304043
+ }
304044
+ const dataDir = getLocalWorkspaceDir(workspace.rootPath);
304045
+ console.log(`Workspace: ${workspace.name} (${workspace.id})`);
304046
+ console.log(` Path: ${workspace.rootPath}`);
304047
+ console.log(` Data dir: ${dataDir}`);
304048
+ console.log(` Indexed: ${workspace.documentCount} docs, ${workspace.chunkCount} chunks`);
304049
+ console.log(
304050
+ "This removes the registry entry and deletes the data directory. Source code is not touched."
304051
+ );
304052
+ if (!options.yes) {
304053
+ const confirmed = await confirmDestructive("Proceed?");
304054
+ if (!confirmed) {
304055
+ console.log("Aborted.");
304056
+ return;
304057
+ }
304058
+ }
304059
+ const report = await removeWorkspace({ id: workspace.id });
304060
+ if (!report) {
304061
+ console.error(`Error: workspace '${workspace.id}' no longer exists in the registry.`);
304062
+ process.exit(1);
304063
+ }
304064
+ if (report.unregistered) {
304065
+ console.log(`\u2713 Unregistered workspace ${report.workspaceId}`);
304066
+ } else {
304067
+ console.log(`\u2717 Workspace ${report.workspaceId} could not be unregistered (see warnings)`);
304068
+ }
304069
+ if (report.dataDirRemoved) {
304070
+ console.log(`\u2713 Deleted ${report.dataDirPath}`);
304071
+ }
304072
+ for (const warning of report.warnings) {
304073
+ console.log(`! ${warning}`);
304074
+ }
304075
+ });
303621
304076
  var EMBEDDING_CONFIG_KEYS = [
303622
304077
  "embedding.provider",
303623
304078
  "embedding.openai_api_key",