latticesql 4.3.1 → 4.3.2

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.
@@ -29043,12 +29043,12 @@ var getNodeModulesParentDirs;
29043
29043
  var init_getNodeModulesParentDirs = __esm({
29044
29044
  "node_modules/@aws-sdk/core/dist-es/submodules/client/util-user-agent-node/getNodeModulesParentDirs.js"() {
29045
29045
  "use strict";
29046
- getNodeModulesParentDirs = (dirname17) => {
29046
+ getNodeModulesParentDirs = (dirname18) => {
29047
29047
  const cwd = process.cwd();
29048
- if (!dirname17) {
29048
+ if (!dirname18) {
29049
29049
  return [cwd];
29050
29050
  }
29051
- const normalizedPath = normalize(dirname17);
29051
+ const normalizedPath = normalize(dirname18);
29052
29052
  const parts = normalizedPath.split(sep6);
29053
29053
  const nodeModulesIndex = parts.indexOf("node_modules");
29054
29054
  const parentDir = nodeModulesIndex !== -1 ? parts.slice(0, nodeModulesIndex).join(sep6) : normalizedPath;
@@ -29126,8 +29126,8 @@ var init_getTypeScriptUserAgentPair = __esm({
29126
29126
  tscVersion = null;
29127
29127
  return void 0;
29128
29128
  }
29129
- const dirname17 = typeof __dirname !== "undefined" ? __dirname : void 0;
29130
- const nodeModulesParentDirs = getNodeModulesParentDirs(dirname17);
29129
+ const dirname18 = typeof __dirname !== "undefined" ? __dirname : void 0;
29130
+ const nodeModulesParentDirs = getNodeModulesParentDirs(dirname18);
29131
29131
  let versionFromApp;
29132
29132
  for (const nodeModulesParentDir of nodeModulesParentDirs) {
29133
29133
  try {
@@ -57916,9 +57916,9 @@ var init_dist_es22 = __esm({
57916
57916
  init_http();
57917
57917
  import { createServer } from "http";
57918
57918
  import { spawn as spawn2 } from "child_process";
57919
- import { existsSync as existsSync31 } from "fs";
57919
+ import { existsSync as existsSync32 } from "fs";
57920
57920
  import { WebSocketServer, WebSocket } from "ws";
57921
- import { dirname as dirname16, resolve as resolve15 } from "path";
57921
+ import { dirname as dirname17, resolve as resolve15 } from "path";
57922
57922
 
57923
57923
  // src/gui/active-db.ts
57924
57924
  init_adapter();
@@ -76618,8 +76618,16 @@ async function dispatchIngestRoute(req, res, ctx) {
76618
76618
 
76619
76619
  // src/gui/sources-routes.ts
76620
76620
  init_user_config();
76621
- import { statSync as statSync9, readdirSync as readdirSync8, readFileSync as readFileSync23, writeFileSync as writeFileSync9 } from "fs";
76622
- import { resolve as resolve11, join as join28, basename as basename12, sep as sep8 } from "path";
76621
+ import {
76622
+ statSync as statSync9,
76623
+ readdirSync as readdirSync8,
76624
+ readFileSync as readFileSync23,
76625
+ writeFileSync as writeFileSync9,
76626
+ existsSync as existsSync26,
76627
+ mkdirSync as mkdirSync11,
76628
+ rmSync
76629
+ } from "fs";
76630
+ import { resolve as resolve11, join as join28, basename as basename12, sep as sep8, dirname as dirname15 } from "path";
76623
76631
  import { execFile } from "child_process";
76624
76632
  import { randomUUID as randomUUID4 } from "crypto";
76625
76633
  init_http();
@@ -76627,20 +76635,49 @@ var MAX_LIST_ENTRIES = 2e3;
76627
76635
  var MAX_INGEST_FILES = 500;
76628
76636
  var MAX_INGEST_DEPTH = 8;
76629
76637
  var SKIP_DIRS = /* @__PURE__ */ new Set([".git", "node_modules", ".DS_Store", "__pycache__", ".venv", "venv"]);
76630
- function rootsFile() {
76631
- return join28(configDir(), "sources.json");
76638
+ function rootsFile(configPath) {
76639
+ return join28(dirname15(configPath), "sources.json");
76640
+ }
76641
+ function migrateGlobalRootsIfNeeded(configPath) {
76642
+ const wsFile = rootsFile(configPath);
76643
+ if (existsSync26(wsFile)) return;
76644
+ const globalFile = join28(configDir(), "sources.json");
76645
+ if (globalFile === wsFile || !existsSync26(globalFile)) return;
76646
+ let roots;
76647
+ try {
76648
+ const parsed = JSON.parse(readFileSync23(globalFile, "utf8"));
76649
+ if (!Array.isArray(parsed.roots) || parsed.roots.length === 0) return;
76650
+ roots = parsed.roots;
76651
+ } catch {
76652
+ return;
76653
+ }
76654
+ try {
76655
+ mkdirSync11(dirname15(wsFile), { recursive: true });
76656
+ writeFileSync9(wsFile, JSON.stringify({ roots }, null, 2), "utf8");
76657
+ } catch {
76658
+ return;
76659
+ }
76660
+ try {
76661
+ rmSync(globalFile, { force: true });
76662
+ } catch {
76663
+ try {
76664
+ writeFileSync9(globalFile, JSON.stringify({ roots: [] }, null, 2), "utf8");
76665
+ } catch {
76666
+ }
76667
+ }
76632
76668
  }
76633
- function readRoots() {
76669
+ function readRoots(configPath) {
76670
+ migrateGlobalRootsIfNeeded(configPath);
76634
76671
  try {
76635
- const raw = readFileSync23(rootsFile(), "utf8");
76672
+ const raw = readFileSync23(rootsFile(configPath), "utf8");
76636
76673
  const parsed = JSON.parse(raw);
76637
76674
  return Array.isArray(parsed.roots) ? parsed.roots : [];
76638
76675
  } catch {
76639
76676
  return [];
76640
76677
  }
76641
76678
  }
76642
- function writeRoots(roots) {
76643
- writeFileSync9(rootsFile(), JSON.stringify({ roots }, null, 2), "utf8");
76679
+ function writeRoots(configPath, roots) {
76680
+ writeFileSync9(rootsFile(configPath), JSON.stringify({ roots }, null, 2), "utf8");
76644
76681
  }
76645
76682
  function safeResolveInside2(target, roots) {
76646
76683
  const abs = resolve11(target);
@@ -76730,14 +76767,14 @@ async function ingestFolder(abs, ingestFile) {
76730
76767
  return { ingested, skipped };
76731
76768
  }
76732
76769
  async function dispatchSourcesRoute(req, res, deps) {
76733
- const { pathname, method, ingestFile } = deps;
76770
+ const { pathname, method, ingestFile, configPath } = deps;
76734
76771
  if (!pathname.startsWith("/api/sources/")) return false;
76735
76772
  if (!localFileOpenEnabled()) {
76736
76773
  sendJson(res, { enabled: false });
76737
76774
  return true;
76738
76775
  }
76739
76776
  if (pathname === "/api/sources/roots" && method === "GET") {
76740
- sendJson(res, { enabled: true, roots: readRoots() });
76777
+ sendJson(res, { enabled: true, roots: readRoots(configPath) });
76741
76778
  return true;
76742
76779
  }
76743
76780
  if (pathname === "/api/sources/roots" && method === "POST") {
@@ -76763,12 +76800,12 @@ async function dispatchSourcesRoute(req, res, deps) {
76763
76800
  sendJson(res, { error: `path not found: ${abs}` }, 400);
76764
76801
  return true;
76765
76802
  }
76766
- const roots = readRoots();
76803
+ const roots = readRoots(configPath);
76767
76804
  let root6 = roots.find((r6) => resolve11(r6.path) === abs);
76768
76805
  if (!root6) {
76769
76806
  root6 = { id: randomUUID4(), path: abs, kind, name: basename12(abs) || abs };
76770
76807
  roots.push(root6);
76771
- writeRoots(roots);
76808
+ writeRoots(configPath, roots);
76772
76809
  }
76773
76810
  let result;
76774
76811
  if (kind === "folder") result = await ingestFolder(abs, ingestFile);
@@ -76779,8 +76816,8 @@ async function dispatchSourcesRoute(req, res, deps) {
76779
76816
  const delMatch = /^\/api\/sources\/roots\/([^/]+)$/.exec(pathname);
76780
76817
  if (delMatch && method === "DELETE") {
76781
76818
  const id = decodeURIComponent(delMatch[1] ?? "");
76782
- const roots = readRoots().filter((r6) => r6.id !== id);
76783
- writeRoots(roots);
76819
+ const roots = readRoots(configPath).filter((r6) => r6.id !== id);
76820
+ writeRoots(configPath, roots);
76784
76821
  sendJson(res, { ok: true });
76785
76822
  return true;
76786
76823
  }
@@ -76798,7 +76835,7 @@ async function dispatchSourcesRoute(req, res, deps) {
76798
76835
  sendJson(res, { error: "path is required" }, 400);
76799
76836
  return true;
76800
76837
  }
76801
- const abs = safeResolveInside2(target, readRoots());
76838
+ const abs = safeResolveInside2(target, readRoots(configPath));
76802
76839
  if (!abs) {
76803
76840
  sendJson(res, { error: "path is outside any registered source root" }, 403);
76804
76841
  return true;
@@ -76813,7 +76850,7 @@ async function dispatchSourcesRoute(req, res, deps) {
76813
76850
  if (pathname === "/api/sources/ingest-folder" && method === "POST") {
76814
76851
  const body = await readJson(req).catch(() => ({}));
76815
76852
  const target = typeof body.path === "string" ? body.path : "";
76816
- const abs = safeResolveInside2(target, readRoots());
76853
+ const abs = safeResolveInside2(target, readRoots(configPath));
76817
76854
  if (!abs) {
76818
76855
  sendJson(res, { error: "path is outside any registered source root" }, 403);
76819
76856
  return true;
@@ -76827,7 +76864,7 @@ async function dispatchSourcesRoute(req, res, deps) {
76827
76864
  // src/gui/import-routes.ts
76828
76865
  init_adapter();
76829
76866
  init_http();
76830
- import { existsSync as existsSync26, readFileSync as readFileSync24, statSync as statSync10 } from "fs";
76867
+ import { existsSync as existsSync27, readFileSync as readFileSync24, statSync as statSync10 } from "fs";
76831
76868
  import { isAbsolute as isAbsolute4, join as join29 } from "path";
76832
76869
  init_native_entities();
76833
76870
  function badRequest(message) {
@@ -76861,7 +76898,7 @@ async function readImportSourceFromFile(db, fileId, latticeRoot) {
76861
76898
  );
76862
76899
  if (!row) throw badRequest("Unknown import file: " + fileId);
76863
76900
  const path3 = localPathOf2(row, latticeRoot);
76864
- if (!path3 || !existsSync26(path3)) {
76901
+ if (!path3 || !existsSync27(path3)) {
76865
76902
  throw badRequest("The import file\u2019s bytes are not available locally.");
76866
76903
  }
76867
76904
  const sizeBytes = statSync10(path3).size;
@@ -79002,7 +79039,7 @@ init_dispatch();
79002
79039
  init_column_descriptions();
79003
79040
  init_mutations();
79004
79041
  init_native_entities();
79005
- import { createReadStream as createReadStream3, existsSync as existsSync27, realpathSync as realpathSync2, statSync as statSync11 } from "fs";
79042
+ import { createReadStream as createReadStream3, existsSync as existsSync28, realpathSync as realpathSync2, statSync as statSync11 } from "fs";
79006
79043
  import { extname as extname3, join as join30, normalize as normalize2, sep as sep9 } from "path";
79007
79044
 
79008
79045
  // src/gui/count-many.ts
@@ -79210,7 +79247,7 @@ async function handleReadRoutes(req, res, ctx, deps) {
79210
79247
  const base = deps.guiAssetsDir.replace(/[/\\]+$/, "");
79211
79248
  const target = normalize2(join30(base, rel));
79212
79249
  const within = target === base || target.startsWith(base + sep9);
79213
- if (!within || !existsSync27(target) || !statSync11(target).isFile()) {
79250
+ if (!within || !existsSync28(target) || !statSync11(target).isFile()) {
79214
79251
  sendJson(res, { error: "asset not found" }, 404);
79215
79252
  return true;
79216
79253
  }
@@ -80418,16 +80455,16 @@ async function handleHistoryRoutes(req, res, ctx, deps) {
80418
80455
  // src/gui/workspaces-routes.ts
80419
80456
  init_http();
80420
80457
  import { resolve as resolve12 } from "path";
80421
- import { existsSync as existsSync28, rmSync } from "fs";
80458
+ import { existsSync as existsSync29, rmSync as rmSync2 } from "fs";
80422
80459
  init_workspace();
80423
80460
  init_lattice_root();
80424
80461
  init_user_config();
80425
80462
  function cleanupWorkspaceFiles(root6, ws) {
80426
80463
  if (!ws.configPath && ws.kind === "local") {
80427
- rmSync(workspaceDir(root6, ws.dir), { recursive: true, force: true });
80464
+ rmSync2(workspaceDir(root6, ws.dir), { recursive: true, force: true });
80428
80465
  } else if (ws.kind === "cloud") {
80429
- if (ws.configPath && existsSync28(ws.configPath)) {
80430
- rmSync(ws.configPath, { force: true });
80466
+ if (ws.configPath && existsSync29(ws.configPath)) {
80467
+ rmSync2(ws.configPath, { force: true });
80431
80468
  }
80432
80469
  const labelMatch = /^\$\{LATTICE_DB:([A-Za-z0-9._-]+)\}$/.exec(ws.db.trim());
80433
80470
  const label = labelMatch?.[1];
@@ -80630,15 +80667,15 @@ async function handleWorkspacesRoutes(req, res, ctx, deps) {
80630
80667
  // src/gui/databases-routes.ts
80631
80668
  init_http();
80632
80669
  import { basename as basename14, resolve as resolve14 } from "path";
80633
- import { existsSync as existsSync30 } from "fs";
80670
+ import { existsSync as existsSync31 } from "fs";
80634
80671
  init_parser();
80635
80672
 
80636
80673
  // src/gui/config-paths.ts
80637
80674
  init_parser();
80638
- import { basename as basename13, dirname as dirname15, join as join31, resolve as resolve13 } from "path";
80675
+ import { basename as basename13, dirname as dirname16, join as join31, resolve as resolve13 } from "path";
80639
80676
  import {
80640
- existsSync as existsSync29,
80641
- mkdirSync as mkdirSync11,
80677
+ existsSync as existsSync30,
80678
+ mkdirSync as mkdirSync12,
80642
80679
  readFileSync as readFileSync25,
80643
80680
  readdirSync as readdirSync9,
80644
80681
  unlinkSync as unlinkSync5,
@@ -80646,10 +80683,10 @@ import {
80646
80683
  } from "fs";
80647
80684
  import { parseDocument as parseDocument7 } from "yaml";
80648
80685
  function resolveOutputDirForConfig(configPath) {
80649
- const base = dirname15(resolve13(configPath));
80686
+ const base = dirname16(resolve13(configPath));
80650
80687
  for (const dir of ["context", ".", "generated"]) {
80651
80688
  const abs = resolve13(base, dir);
80652
- if (existsSync29(join31(abs, ".lattice", "manifest.json"))) return abs;
80689
+ if (existsSync30(join31(abs, ".lattice", "manifest.json"))) return abs;
80653
80690
  }
80654
80691
  return resolve13(base, "context");
80655
80692
  }
@@ -80658,7 +80695,7 @@ function friendlyConfigName(parsedName, configPath) {
80658
80695
  return basename13(configPath).replace(/\.(ya?ml)$/, "");
80659
80696
  }
80660
80697
  function listConfigs(activeConfigPath) {
80661
- const dir = dirname15(activeConfigPath);
80698
+ const dir = dirname16(activeConfigPath);
80662
80699
  const entries = [];
80663
80700
  for (const fname of readdirSync9(dir)) {
80664
80701
  if (!fname.endsWith(".yml") && !fname.endsWith(".yaml")) continue;
@@ -80687,17 +80724,17 @@ function listConfigs(activeConfigPath) {
80687
80724
  return entries.sort((a6, b6) => a6.label.localeCompare(b6.label));
80688
80725
  }
80689
80726
  function createBlankConfig(activeConfigPath, dbName) {
80690
- const dir = dirname15(activeConfigPath);
80727
+ const dir = dirname16(activeConfigPath);
80691
80728
  const slug = dbName.toLowerCase().replace(/[^a-z0-9_-]+/g, "-").replace(/^-+|-+$/g, "");
80692
80729
  if (!slug) throw new Error("Workspace name must contain at least one alphanumeric character");
80693
80730
  const configPath = join31(dir, `${slug}.config.yml`);
80694
- if (existsSync29(configPath)) throw new Error(`Config already exists: ${slug}.config.yml`);
80731
+ if (existsSync30(configPath)) throw new Error(`Config already exists: ${slug}.config.yml`);
80695
80732
  const yaml = `db: ./data/${slug}.db
80696
80733
 
80697
80734
  entities: {}
80698
80735
  `;
80699
80736
  writeFileSync10(configPath, yaml, "utf8");
80700
- mkdirSync11(join31(dir, "data"), { recursive: true });
80737
+ mkdirSync12(join31(dir, "data"), { recursive: true });
80701
80738
  return configPath;
80702
80739
  }
80703
80740
  function sqliteFileForConfig(configPath) {
@@ -80706,18 +80743,18 @@ function sqliteFileForConfig(configPath) {
80706
80743
  if (!raw) return null;
80707
80744
  if (isPostgresUrl(raw) || raw.startsWith("${LATTICE_DB:")) return null;
80708
80745
  if (raw === ":memory:" || raw.startsWith("file:")) return null;
80709
- return resolve13(dirname15(configPath), raw);
80746
+ return resolve13(dirname16(configPath), raw);
80710
80747
  }
80711
80748
  function deleteDatabaseFiles(targetConfigPath) {
80712
80749
  const sqliteFile = sqliteFileForConfig(targetConfigPath);
80713
80750
  unlinkSync5(targetConfigPath);
80714
80751
  let deletedDbFile = null;
80715
- if (sqliteFile && existsSync29(sqliteFile)) {
80752
+ if (sqliteFile && existsSync30(sqliteFile)) {
80716
80753
  unlinkSync5(sqliteFile);
80717
80754
  deletedDbFile = sqliteFile;
80718
80755
  for (const suffix of ["-wal", "-shm", "-journal"]) {
80719
80756
  const sidecar = sqliteFile + suffix;
80720
- if (existsSync29(sidecar)) unlinkSync5(sidecar);
80757
+ if (existsSync30(sidecar)) unlinkSync5(sidecar);
80721
80758
  }
80722
80759
  }
80723
80760
  return { deletedConfig: basename13(targetConfigPath), deletedDbFile };
@@ -80751,7 +80788,7 @@ async function handleDatabasesRoutes(req, res, ctx, deps) {
80751
80788
  return true;
80752
80789
  }
80753
80790
  const newPath = resolve14(body.path);
80754
- if (!existsSync30(newPath)) {
80791
+ if (!existsSync31(newPath)) {
80755
80792
  sendJson(res, { error: `Config not found: ${newPath}` }, 400);
80756
80793
  return true;
80757
80794
  }
@@ -80857,8 +80894,8 @@ async function handleDatabasesRoutes(req, res, ctx, deps) {
80857
80894
  // src/gui/server.ts
80858
80895
  init_user_config();
80859
80896
  function resolveDefaultGuiAssetsDir() {
80860
- const bundleSibling = process.argv[1] ? resolve15(dirname16(process.argv[1]), "gui-assets") : null;
80861
- if (bundleSibling && existsSync31(bundleSibling)) return bundleSibling;
80897
+ const bundleSibling = process.argv[1] ? resolve15(dirname17(process.argv[1]), "gui-assets") : null;
80898
+ if (bundleSibling && existsSync32(bundleSibling)) return bundleSibling;
80862
80899
  return resolve15(process.cwd(), "dist", "gui-assets");
80863
80900
  }
80864
80901
  function sendText(res, body, status = 200, contentType = "text/plain; charset=utf-8") {
@@ -80915,7 +80952,7 @@ async function startGuiServer(options) {
80915
80952
  const sessionId = crypto.randomUUID();
80916
80953
  let updateService = null;
80917
80954
  let activeRef = bootConfigPath && bootOutputDir ? await openConfig(bootConfigPath, bootOutputDir, autoRender, options.realtimeWatchdogMs) : null;
80918
- const latticeRoot = (bootConfigPath ? findLatticeRoot(dirname16(bootConfigPath)) : null) ?? (options.latticeRoot ? resolve15(options.latticeRoot) : null);
80955
+ const latticeRoot = (bootConfigPath ? findLatticeRoot(dirname17(bootConfigPath)) : null) ?? (options.latticeRoot ? resolve15(options.latticeRoot) : null);
80919
80956
  let currentWorkspaceId = null;
80920
80957
  if (latticeRoot && bootConfigPath) {
80921
80958
  const launched = listWorkspaces(latticeRoot).find(
@@ -81269,7 +81306,7 @@ async function startGuiServer(options) {
81269
81306
  createJunction: (otherTable) => createFileJunction(active, otherTable, sessionId),
81270
81307
  createEntity: (entity, columns) => createUserEntity(active, entity, columns, sessionId),
81271
81308
  aggressiveness: getAggressiveness(),
81272
- latticeRoot: dirname16(active.configPath),
81309
+ latticeRoot: dirname17(active.configPath),
81273
81310
  configPath: active.configPath,
81274
81311
  outputDir: active.outputDir,
81275
81312
  sessionId,
@@ -81294,7 +81331,7 @@ async function startGuiServer(options) {
81294
81331
  createJunction: (otherTable) => createFileJunction(active, otherTable, sessionId),
81295
81332
  createEntity: (entity, columns) => createUserEntity(active, entity, columns, sessionId),
81296
81333
  aggressiveness: getAggressiveness(),
81297
- latticeRoot: dirname16(active.configPath),
81334
+ latticeRoot: dirname17(active.configPath),
81298
81335
  configPath: active.configPath,
81299
81336
  outputDir: active.outputDir,
81300
81337
  sessionId,
@@ -81305,6 +81342,7 @@ async function startGuiServer(options) {
81305
81342
  return await dispatchSourcesRoute(req2, res2, {
81306
81343
  db: active.db,
81307
81344
  ingestFile: (p3) => ingestLocalFile(ingestCtx, mctx, p3, false),
81345
+ configPath: active.configPath,
81308
81346
  pathname,
81309
81347
  method
81310
81348
  });
@@ -81320,7 +81358,7 @@ async function startGuiServer(options) {
81320
81358
  return await dispatchImportRoute(req2, res2, {
81321
81359
  db: active.db,
81322
81360
  configPath: active.configPath,
81323
- latticeRoot: dirname16(active.configPath),
81361
+ latticeRoot: dirname17(active.configPath),
81324
81362
  validTables: active.validTables,
81325
81363
  softDeletable: active.softDeletable
81326
81364
  });
@@ -81349,7 +81387,7 @@ async function startGuiServer(options) {
81349
81387
  if (!pathname.startsWith("/api/files/")) return false;
81350
81388
  return await dispatchFilesRoute(req2, res2, {
81351
81389
  db: active.db,
81352
- latticeRoot: dirname16(active.configPath),
81390
+ latticeRoot: dirname17(active.configPath),
81353
81391
  configPath: active.configPath,
81354
81392
  pathname,
81355
81393
  method
@@ -81560,7 +81598,7 @@ ${e6.stack ?? ""}`
81560
81598
  }
81561
81599
 
81562
81600
  // src/desktop-entry.ts
81563
- var VERSION2 = true ? "4.3.1" : "unknown";
81601
+ var VERSION2 = true ? "4.3.2" : "unknown";
81564
81602
  export {
81565
81603
  VERSION2 as VERSION,
81566
81604
  ensureRootForGui,
package/dist/index.cjs CHANGED
@@ -23491,12 +23491,12 @@ var init_getNodeModulesParentDirs = __esm({
23491
23491
  "node_modules/@aws-sdk/core/dist-es/submodules/client/util-user-agent-node/getNodeModulesParentDirs.js"() {
23492
23492
  "use strict";
23493
23493
  import_node_path21 = require("path");
23494
- getNodeModulesParentDirs = (dirname18) => {
23494
+ getNodeModulesParentDirs = (dirname19) => {
23495
23495
  const cwd = process.cwd();
23496
- if (!dirname18) {
23496
+ if (!dirname19) {
23497
23497
  return [cwd];
23498
23498
  }
23499
- const normalizedPath = (0, import_node_path21.normalize)(dirname18);
23499
+ const normalizedPath = (0, import_node_path21.normalize)(dirname19);
23500
23500
  const parts = normalizedPath.split(import_node_path21.sep);
23501
23501
  const nodeModulesIndex = parts.indexOf("node_modules");
23502
23502
  const parentDir = nodeModulesIndex !== -1 ? parts.slice(0, nodeModulesIndex).join(import_node_path21.sep) : normalizedPath;
@@ -23574,8 +23574,8 @@ var init_getTypeScriptUserAgentPair = __esm({
23574
23574
  tscVersion = null;
23575
23575
  return void 0;
23576
23576
  }
23577
- const dirname18 = typeof __dirname !== "undefined" ? __dirname : void 0;
23578
- const nodeModulesParentDirs = getNodeModulesParentDirs(dirname18);
23577
+ const dirname19 = typeof __dirname !== "undefined" ? __dirname : void 0;
23578
+ const nodeModulesParentDirs = getNodeModulesParentDirs(dirname19);
23579
23579
  let versionFromApp;
23580
23580
  for (const nodeModulesParentDir of nodeModulesParentDirs) {
23581
23581
  try {
@@ -80292,20 +80292,49 @@ var MAX_LIST_ENTRIES = 2e3;
80292
80292
  var MAX_INGEST_FILES = 500;
80293
80293
  var MAX_INGEST_DEPTH = 8;
80294
80294
  var SKIP_DIRS = /* @__PURE__ */ new Set([".git", "node_modules", ".DS_Store", "__pycache__", ".venv", "venv"]);
80295
- function rootsFile() {
80296
- return (0, import_node_path44.join)(configDir(), "sources.json");
80295
+ function rootsFile(configPath) {
80296
+ return (0, import_node_path44.join)((0, import_node_path44.dirname)(configPath), "sources.json");
80297
+ }
80298
+ function migrateGlobalRootsIfNeeded(configPath) {
80299
+ const wsFile = rootsFile(configPath);
80300
+ if ((0, import_node_fs41.existsSync)(wsFile)) return;
80301
+ const globalFile = (0, import_node_path44.join)(configDir(), "sources.json");
80302
+ if (globalFile === wsFile || !(0, import_node_fs41.existsSync)(globalFile)) return;
80303
+ let roots;
80304
+ try {
80305
+ const parsed = JSON.parse((0, import_node_fs41.readFileSync)(globalFile, "utf8"));
80306
+ if (!Array.isArray(parsed.roots) || parsed.roots.length === 0) return;
80307
+ roots = parsed.roots;
80308
+ } catch {
80309
+ return;
80310
+ }
80311
+ try {
80312
+ (0, import_node_fs41.mkdirSync)((0, import_node_path44.dirname)(wsFile), { recursive: true });
80313
+ (0, import_node_fs41.writeFileSync)(wsFile, JSON.stringify({ roots }, null, 2), "utf8");
80314
+ } catch {
80315
+ return;
80316
+ }
80317
+ try {
80318
+ (0, import_node_fs41.rmSync)(globalFile, { force: true });
80319
+ } catch {
80320
+ try {
80321
+ (0, import_node_fs41.writeFileSync)(globalFile, JSON.stringify({ roots: [] }, null, 2), "utf8");
80322
+ } catch {
80323
+ }
80324
+ }
80297
80325
  }
80298
- function readRoots() {
80326
+ function readRoots(configPath) {
80327
+ migrateGlobalRootsIfNeeded(configPath);
80299
80328
  try {
80300
- const raw = (0, import_node_fs41.readFileSync)(rootsFile(), "utf8");
80329
+ const raw = (0, import_node_fs41.readFileSync)(rootsFile(configPath), "utf8");
80301
80330
  const parsed = JSON.parse(raw);
80302
80331
  return Array.isArray(parsed.roots) ? parsed.roots : [];
80303
80332
  } catch {
80304
80333
  return [];
80305
80334
  }
80306
80335
  }
80307
- function writeRoots(roots) {
80308
- (0, import_node_fs41.writeFileSync)(rootsFile(), JSON.stringify({ roots }, null, 2), "utf8");
80336
+ function writeRoots(configPath, roots) {
80337
+ (0, import_node_fs41.writeFileSync)(rootsFile(configPath), JSON.stringify({ roots }, null, 2), "utf8");
80309
80338
  }
80310
80339
  function safeResolveInside2(target, roots) {
80311
80340
  const abs = (0, import_node_path44.resolve)(target);
@@ -80395,14 +80424,14 @@ async function ingestFolder(abs, ingestFile) {
80395
80424
  return { ingested, skipped };
80396
80425
  }
80397
80426
  async function dispatchSourcesRoute(req, res, deps) {
80398
- const { pathname, method, ingestFile } = deps;
80427
+ const { pathname, method, ingestFile, configPath } = deps;
80399
80428
  if (!pathname.startsWith("/api/sources/")) return false;
80400
80429
  if (!localFileOpenEnabled()) {
80401
80430
  sendJson(res, { enabled: false });
80402
80431
  return true;
80403
80432
  }
80404
80433
  if (pathname === "/api/sources/roots" && method === "GET") {
80405
- sendJson(res, { enabled: true, roots: readRoots() });
80434
+ sendJson(res, { enabled: true, roots: readRoots(configPath) });
80406
80435
  return true;
80407
80436
  }
80408
80437
  if (pathname === "/api/sources/roots" && method === "POST") {
@@ -80428,12 +80457,12 @@ async function dispatchSourcesRoute(req, res, deps) {
80428
80457
  sendJson(res, { error: `path not found: ${abs}` }, 400);
80429
80458
  return true;
80430
80459
  }
80431
- const roots = readRoots();
80460
+ const roots = readRoots(configPath);
80432
80461
  let root6 = roots.find((r6) => (0, import_node_path44.resolve)(r6.path) === abs);
80433
80462
  if (!root6) {
80434
80463
  root6 = { id: (0, import_node_crypto24.randomUUID)(), path: abs, kind, name: (0, import_node_path44.basename)(abs) || abs };
80435
80464
  roots.push(root6);
80436
- writeRoots(roots);
80465
+ writeRoots(configPath, roots);
80437
80466
  }
80438
80467
  let result;
80439
80468
  if (kind === "folder") result = await ingestFolder(abs, ingestFile);
@@ -80444,8 +80473,8 @@ async function dispatchSourcesRoute(req, res, deps) {
80444
80473
  const delMatch = /^\/api\/sources\/roots\/([^/]+)$/.exec(pathname);
80445
80474
  if (delMatch && method === "DELETE") {
80446
80475
  const id = decodeURIComponent(delMatch[1] ?? "");
80447
- const roots = readRoots().filter((r6) => r6.id !== id);
80448
- writeRoots(roots);
80476
+ const roots = readRoots(configPath).filter((r6) => r6.id !== id);
80477
+ writeRoots(configPath, roots);
80449
80478
  sendJson(res, { ok: true });
80450
80479
  return true;
80451
80480
  }
@@ -80463,7 +80492,7 @@ async function dispatchSourcesRoute(req, res, deps) {
80463
80492
  sendJson(res, { error: "path is required" }, 400);
80464
80493
  return true;
80465
80494
  }
80466
- const abs = safeResolveInside2(target, readRoots());
80495
+ const abs = safeResolveInside2(target, readRoots(configPath));
80467
80496
  if (!abs) {
80468
80497
  sendJson(res, { error: "path is outside any registered source root" }, 403);
80469
80498
  return true;
@@ -80478,7 +80507,7 @@ async function dispatchSourcesRoute(req, res, deps) {
80478
80507
  if (pathname === "/api/sources/ingest-folder" && method === "POST") {
80479
80508
  const body = await readJson(req).catch(() => ({}));
80480
80509
  const target = typeof body.path === "string" ? body.path : "";
80481
- const abs = safeResolveInside2(target, readRoots());
80510
+ const abs = safeResolveInside2(target, readRoots(configPath));
80482
80511
  if (!abs) {
80483
80512
  sendJson(res, { error: "path is outside any registered source root" }, 403);
80484
80513
  return true;
@@ -83117,6 +83146,7 @@ async function startGuiServer(options) {
83117
83146
  return await dispatchSourcesRoute(req2, res2, {
83118
83147
  db: active.db,
83119
83148
  ingestFile: (p3) => ingestLocalFile(ingestCtx, mctx, p3, false),
83149
+ configPath: active.configPath,
83120
83150
  pathname,
83121
83151
  method
83122
83152
  });