latticesql 4.3.0 → 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.
package/dist/cli.js CHANGED
@@ -29084,12 +29084,12 @@ var getNodeModulesParentDirs;
29084
29084
  var init_getNodeModulesParentDirs = __esm({
29085
29085
  "node_modules/@aws-sdk/core/dist-es/submodules/client/util-user-agent-node/getNodeModulesParentDirs.js"() {
29086
29086
  "use strict";
29087
- getNodeModulesParentDirs = (dirname19) => {
29087
+ getNodeModulesParentDirs = (dirname20) => {
29088
29088
  const cwd = process.cwd();
29089
- if (!dirname19) {
29089
+ if (!dirname20) {
29090
29090
  return [cwd];
29091
29091
  }
29092
- const normalizedPath = normalize(dirname19);
29092
+ const normalizedPath = normalize(dirname20);
29093
29093
  const parts = normalizedPath.split(sep6);
29094
29094
  const nodeModulesIndex = parts.indexOf("node_modules");
29095
29095
  const parentDir = nodeModulesIndex !== -1 ? parts.slice(0, nodeModulesIndex).join(sep6) : normalizedPath;
@@ -29167,8 +29167,8 @@ var init_getTypeScriptUserAgentPair = __esm({
29167
29167
  tscVersion = null;
29168
29168
  return void 0;
29169
29169
  }
29170
- const dirname19 = typeof __dirname !== "undefined" ? __dirname : void 0;
29171
- const nodeModulesParentDirs = getNodeModulesParentDirs(dirname19);
29170
+ const dirname20 = typeof __dirname !== "undefined" ? __dirname : void 0;
29171
+ const nodeModulesParentDirs = getNodeModulesParentDirs(dirname20);
29172
29172
  let versionFromApp;
29173
29173
  for (const nodeModulesParentDir of nodeModulesParentDirs) {
29174
29174
  try {
@@ -57954,8 +57954,8 @@ var init_dist_es22 = __esm({
57954
57954
  });
57955
57955
 
57956
57956
  // src/cli.ts
57957
- import { resolve as resolve17, dirname as dirname18 } from "path";
57958
- import { readFileSync as readFileSync26, existsSync as existsSync33 } from "fs";
57957
+ import { resolve as resolve17, dirname as dirname19 } from "path";
57958
+ import { readFileSync as readFileSync26, existsSync as existsSync34 } from "fs";
57959
57959
  import { execSync } from "child_process";
57960
57960
  import { parse as parse3 } from "yaml";
57961
57961
 
@@ -58222,9 +58222,9 @@ function installLatest(ctx, version, opts = {}) {
58222
58222
  init_http();
58223
58223
  import { createServer } from "http";
58224
58224
  import { spawn as spawn2 } from "child_process";
58225
- import { existsSync as existsSync32 } from "fs";
58225
+ import { existsSync as existsSync33 } from "fs";
58226
58226
  import { WebSocketServer, WebSocket } from "ws";
58227
- import { dirname as dirname17, resolve as resolve16 } from "path";
58227
+ import { dirname as dirname18, resolve as resolve16 } from "path";
58228
58228
 
58229
58229
  // src/gui/active-db.ts
58230
58230
  init_adapter();
@@ -60429,12 +60429,16 @@ var tokensCss = `
60429
60429
  surface (a bare input on a modal, the Database wizard, User Config, etc.):
60430
60430
  dark text on a white field with a light border. Placeholders use the
60431
60431
  muted token. Affects every input/select/textarea across the GUI. */
60432
- input, select, textarea {
60432
+ /* Text-like fields only \u2014 radios/checkboxes keep their native rendering
60433
+ (the box/border treatment mangles them). The accent color tints the native
60434
+ controls so checked radios/checkboxes are on-brand blue. */
60435
+ input:not([type='radio']):not([type='checkbox']):not([type='range']), select, textarea {
60433
60436
  color: var(--text);
60434
60437
  background: var(--surface);
60435
60438
  border: 1px solid var(--border);
60436
60439
  border-radius: 6px;
60437
60440
  }
60441
+ input[type='radio'], input[type='checkbox'] { accent-color: var(--accent); }
60438
60442
  input::placeholder, textarea::placeholder {
60439
60443
  color: var(--text-muted);
60440
60444
  opacity: 1;
@@ -61419,7 +61423,7 @@ var teamsCss = ` /* \u2500\u2500 Teams (Project Config + User Config) \u2500\
61419
61423
  color: var(--text); font-weight: 500;
61420
61424
  text-transform: uppercase; letter-spacing: 0.04em;
61421
61425
  }
61422
- .modal .field input, .modal .field textarea {
61426
+ .modal .field input:not([type='radio']):not([type='checkbox']), .modal .field textarea {
61423
61427
  width: 100%; padding: 6px 8px;
61424
61428
  background: var(--surface); color: var(--text);
61425
61429
  border: 1px solid var(--border-strong);
@@ -61429,6 +61433,20 @@ var teamsCss = ` /* \u2500\u2500 Teams (Project Config + User Config) \u2500\
61429
61433
  color: var(--text-muted);
61430
61434
  }
61431
61435
  .modal .field textarea { min-height: 60px; font-family: ui-monospace, monospace; font-size: 12px; }
61436
+ /* New-workspace "Kind" selector \u2014 clean cards, blue-highlighted selection. */
61437
+ .wiz-kind-opts { display: flex; gap: 10px; margin-top: 6px; flex-wrap: wrap; }
61438
+ .wiz-kind-card {
61439
+ flex: 1 1 0; min-width: 132px; display: flex; align-items: center; gap: 9px;
61440
+ padding: 10px 12px; border: 1px solid var(--border); border-radius: 8px;
61441
+ background: var(--surface); cursor: pointer;
61442
+ transition: border-color 0.12s ease, background 0.12s ease;
61443
+ }
61444
+ .wiz-kind-card:hover { border-color: var(--border-strong); }
61445
+ .wiz-kind-card:has(input:checked) { border-color: var(--accent); background: var(--accent-soft); }
61446
+ .wiz-kind-card input { margin: 0; flex: 0 0 auto; }
61447
+ .wiz-kind-name { font-size: 13px; color: var(--text); text-transform: none; letter-spacing: 0; }
61448
+ .wiz-kind-sub { color: var(--text-muted); font-size: 11px; margin-left: 2px; }
61449
+ .wiz-kind-card:has(input:checked) .wiz-kind-name { color: var(--accent-deep); font-weight: 500; }
61432
61450
  .modal .copy-token {
61433
61451
  padding: 8px 10px; background: var(--surface-2); border: 1px solid var(--border);
61434
61452
  border-radius: 4px; font-family: ui-monospace, monospace; font-size: 12px;
@@ -62674,6 +62692,9 @@ var bootJs = ` // \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u250
62674
62692
  initRailDragDrop();
62675
62693
  renderComposer();
62676
62694
  initThreadControls();
62695
+ // Warm up on-device voice in the background shortly after boot so dictation
62696
+ // is ready on first use \u2014 no visible model-loading step, ever.
62697
+ if (typeof voicePreload === 'function') setTimeout(voicePreload, 1500);
62677
62698
  checkNativeSetup();
62678
62699
  // App is fully populated \u2014 reveal it (Feature C).
62679
62700
  hideAppLoading();
@@ -66437,9 +66458,14 @@ var dashboardJs = ` // \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
66437
66458
  }
66438
66459
  var d = displayFor(table);
66439
66460
  // The tab shows the open RECORD's name (e.g. an entity row), not the
66440
- // object/table name.
66461
+ // object/table name. Guard: only retitle a RECORD ('item:') tab \u2014 never the
66462
+ // shared Brain Graph ('graph') tab, even if a record render briefly runs
66463
+ // while the hash still resolves to the graph (which would rename \u{1F9E0}).
66441
66464
  if (typeof setTabTitle === 'function') {
66442
- setTabTitle(tabKeyForHash(location.hash), fsDisplayName(row) || d.label);
66465
+ var fsItemKey = tabKeyForHash(location.hash);
66466
+ if (fsItemKey && fsItemKey.indexOf('item:') === 0) {
66467
+ setTabTitle(fsItemKey, fsDisplayName(row) || d.label);
66468
+ }
66443
66469
  }
66444
66470
  // Files + artifacts get the two-view document layout (formatted display +
66445
66471
  // a View Source toggle) with a Version History + Delete dropdown \u2014 not the
@@ -66509,7 +66535,10 @@ var dashboardJs = ` // \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
66509
66535
  // The tab shows the FILE's name (e.g. "Properties Dashboard"), not the
66510
66536
  // object name ("Files").
66511
66537
  if (typeof setTabTitle === 'function') {
66512
- setTabTitle(tabKeyForHash(location.hash), fsDisplayName(row) || d.label);
66538
+ var fsDocKey = tabKeyForHash(location.hash);
66539
+ if (fsDocKey && fsDocKey.indexOf('item:') === 0) {
66540
+ setTabTitle(fsDocKey, fsDisplayName(row) || d.label);
66541
+ }
66513
66542
  }
66514
66543
  var mode = fileViewMode[id] || 'display';
66515
66544
  // Actions live in a dropdown menu next to the title; View source / Version
@@ -68716,15 +68745,18 @@ var dataModelJs = ` // \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
68716
68745
  return '' +
68717
68746
  nameField +
68718
68747
  '<div class="field"><label>Kind</label>' +
68719
- '<div style="display:flex;gap:16px;margin-top:4px;flex-wrap:wrap">' +
68720
- '<label style="display:flex;align-items:center;gap:6px;font-weight:400;text-transform:none;letter-spacing:0">' +
68721
- '<input type="radio" name="wiz-kind" value="local"' + (kind === 'local' ? ' checked' : '') + ' /> New local (SQLite)' +
68748
+ '<div class="wiz-kind-opts">' +
68749
+ '<label class="wiz-kind-card">' +
68750
+ '<input type="radio" name="wiz-kind" value="local"' + (kind === 'local' ? ' checked' : '') + ' />' +
68751
+ '<span class="wiz-kind-name">New local <span class="wiz-kind-sub">SQLite</span></span>' +
68722
68752
  '</label>' +
68723
- '<label style="display:flex;align-items:center;gap:6px;font-weight:400;text-transform:none;letter-spacing:0">' +
68724
- '<input type="radio" name="wiz-kind" value="cloud"' + (kind === 'cloud' ? ' checked' : '') + ' /> New cloud (Postgres)' +
68753
+ '<label class="wiz-kind-card">' +
68754
+ '<input type="radio" name="wiz-kind" value="cloud"' + (kind === 'cloud' ? ' checked' : '') + ' />' +
68755
+ '<span class="wiz-kind-name">New cloud <span class="wiz-kind-sub">Postgres</span></span>' +
68725
68756
  '</label>' +
68726
- '<label style="display:flex;align-items:center;gap:6px;font-weight:400;text-transform:none;letter-spacing:0">' +
68727
- '<input type="radio" name="wiz-kind" value="join"' + (kind === 'join' ? ' checked' : '') + ' /> Join a team (invite)' +
68757
+ '<label class="wiz-kind-card">' +
68758
+ '<input type="radio" name="wiz-kind" value="join"' + (kind === 'join' ? ' checked' : '') + ' />' +
68759
+ '<span class="wiz-kind-name">Join a team <span class="wiz-kind-sub">invite</span></span>' +
68728
68760
  '</label>' +
68729
68761
  '</div>' +
68730
68762
  '<p style="font-size:11px;color:var(--text-muted);margin:6px 0 0">' +
@@ -70869,6 +70901,14 @@ var voiceLocalJs = ` // \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u250
70869
70901
  return _voiceWorker;
70870
70902
  }
70871
70903
 
70904
+ // Warm up the voice worker + model in the BACKGROUND on launch, so dictation is
70905
+ // ready by the time the user records and any first-run weight fetch happens
70906
+ // silently up front (never mid-recording, never with a visible "downloading"
70907
+ // state). Idempotent + best-effort \u2014 a failure just leaves the mic to lazy-init.
70908
+ function voicePreload() {
70909
+ try { getVoiceWorker(); } catch (_) { /* best-effort */ }
70910
+ }
70911
+
70872
70912
  function voicePreferredDevice() {
70873
70913
  // WebGPU when the browser exposes it, else WASM. The worker downgrades to
70874
70914
  // wasm itself if the runtime can't honor webgpu, so this is just a hint.
@@ -70890,14 +70930,14 @@ var voiceLocalJs = ` // \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u250
70890
70930
  _voiceWorkerReady = false;
70891
70931
  }
70892
70932
 
70893
- // Forward model-download progress to the composer placeholder so the first
70894
- // use shows "Downloading voice model\u2026 N%" (it needs the network ONCE; after
70895
- // that it's cached and offline).
70896
- function onVoiceProgress(file, progress) {
70897
- var inp = document.getElementById('chat-input');
70898
- if (!inp) return;
70899
- var pct = (typeof progress === 'number' && progress > 0) ? (' ' + Math.round(progress) + '%') : '';
70900
- inp.setAttribute('placeholder', 'Downloading voice model\u2026' + pct);
70933
+ // Model loading is SILENT \u2014 the user never sees a "downloading voice model"
70934
+ // state. The worker + model are warmed up in the background on launch (see
70935
+ // voicePreload), and the ORT runtime ships bundled, so by the time anyone
70936
+ // records, dictation is ready. We intentionally surface no loading progress in
70937
+ // the composer; if a first-run weight fetch is still in flight, the existing
70938
+ // "Transcribing\u2026" placeholder covers it.
70939
+ function onVoiceProgress(_file, _progress) {
70940
+ /* intentionally silent \u2014 no visible voice-model loading UI */
70901
70941
  }
70902
70942
 
70903
70943
  // Decode a recorded audio blob to mono 16 kHz PCM (Float32Array), entirely in
@@ -71901,12 +71941,33 @@ var sourcesJs = `
71901
71941
  '<span class="src-name">' + escapeHtml(name) + '</span></div></li>';
71902
71942
  }).join('') + '</ul>'
71903
71943
  : '';
71944
+ // Preserve expanded folders across this re-render so an in-progress
71945
+ // ingest (which re-renders the sidebar) never snaps an open folder shut.
71946
+ // Capture each expanded folder's path + its lazily-loaded children markup,
71947
+ // then re-attach + re-open them after the rebuild (no re-fetch, no flicker).
71948
+ var openFolders = {};
71949
+ host.querySelectorAll('.src-folder[data-loaded="1"]').forEach(function (li) {
71950
+ var ul0 = li.querySelector(':scope > .src-children');
71951
+ if (ul0 && !ul0.hidden) openFolders[li.getAttribute('data-path')] = ul0.innerHTML;
71952
+ });
71904
71953
  if (!rootsHtml && !looseHtml) {
71905
71954
  host.innerHTML = '<div class="src-empty">No files yet.</div>';
71906
71955
  return;
71907
71956
  }
71908
71957
  host.innerHTML = rootsHtml + looseHtml;
71909
71958
  wireSourceTree(host);
71959
+ host.querySelectorAll('.src-folder').forEach(function (li) {
71960
+ var saved = openFolders[li.getAttribute('data-path')];
71961
+ if (saved == null) return;
71962
+ var ul1 = li.querySelector(':scope > .src-children');
71963
+ var caret = li.querySelector(':scope > .src-row > .src-caret');
71964
+ if (!ul1) return;
71965
+ ul1.innerHTML = saved;
71966
+ ul1.hidden = false;
71967
+ li.setAttribute('data-loaded', '1');
71968
+ if (caret) caret.textContent = '\u25BE';
71969
+ wireSourceTree(ul1);
71970
+ });
71910
71971
  })
71911
71972
  .catch(function () { host.innerHTML = ''; });
71912
71973
  }
@@ -76697,8 +76758,16 @@ async function dispatchIngestRoute(req, res, ctx) {
76697
76758
 
76698
76759
  // src/gui/sources-routes.ts
76699
76760
  init_user_config();
76700
- import { statSync as statSync9, readdirSync as readdirSync8, readFileSync as readFileSync23, writeFileSync as writeFileSync10 } from "fs";
76701
- import { resolve as resolve12, join as join29, basename as basename12, sep as sep8 } from "path";
76761
+ import {
76762
+ statSync as statSync9,
76763
+ readdirSync as readdirSync8,
76764
+ readFileSync as readFileSync23,
76765
+ writeFileSync as writeFileSync10,
76766
+ existsSync as existsSync27,
76767
+ mkdirSync as mkdirSync12,
76768
+ rmSync
76769
+ } from "fs";
76770
+ import { resolve as resolve12, join as join29, basename as basename12, sep as sep8, dirname as dirname16 } from "path";
76702
76771
  import { execFile } from "child_process";
76703
76772
  import { randomUUID as randomUUID4 } from "crypto";
76704
76773
  init_http();
@@ -76706,20 +76775,49 @@ var MAX_LIST_ENTRIES = 2e3;
76706
76775
  var MAX_INGEST_FILES = 500;
76707
76776
  var MAX_INGEST_DEPTH = 8;
76708
76777
  var SKIP_DIRS = /* @__PURE__ */ new Set([".git", "node_modules", ".DS_Store", "__pycache__", ".venv", "venv"]);
76709
- function rootsFile() {
76710
- return join29(configDir(), "sources.json");
76778
+ function rootsFile(configPath) {
76779
+ return join29(dirname16(configPath), "sources.json");
76780
+ }
76781
+ function migrateGlobalRootsIfNeeded(configPath) {
76782
+ const wsFile = rootsFile(configPath);
76783
+ if (existsSync27(wsFile)) return;
76784
+ const globalFile = join29(configDir(), "sources.json");
76785
+ if (globalFile === wsFile || !existsSync27(globalFile)) return;
76786
+ let roots;
76787
+ try {
76788
+ const parsed = JSON.parse(readFileSync23(globalFile, "utf8"));
76789
+ if (!Array.isArray(parsed.roots) || parsed.roots.length === 0) return;
76790
+ roots = parsed.roots;
76791
+ } catch {
76792
+ return;
76793
+ }
76794
+ try {
76795
+ mkdirSync12(dirname16(wsFile), { recursive: true });
76796
+ writeFileSync10(wsFile, JSON.stringify({ roots }, null, 2), "utf8");
76797
+ } catch {
76798
+ return;
76799
+ }
76800
+ try {
76801
+ rmSync(globalFile, { force: true });
76802
+ } catch {
76803
+ try {
76804
+ writeFileSync10(globalFile, JSON.stringify({ roots: [] }, null, 2), "utf8");
76805
+ } catch {
76806
+ }
76807
+ }
76711
76808
  }
76712
- function readRoots() {
76809
+ function readRoots(configPath) {
76810
+ migrateGlobalRootsIfNeeded(configPath);
76713
76811
  try {
76714
- const raw = readFileSync23(rootsFile(), "utf8");
76812
+ const raw = readFileSync23(rootsFile(configPath), "utf8");
76715
76813
  const parsed = JSON.parse(raw);
76716
76814
  return Array.isArray(parsed.roots) ? parsed.roots : [];
76717
76815
  } catch {
76718
76816
  return [];
76719
76817
  }
76720
76818
  }
76721
- function writeRoots(roots) {
76722
- writeFileSync10(rootsFile(), JSON.stringify({ roots }, null, 2), "utf8");
76819
+ function writeRoots(configPath, roots) {
76820
+ writeFileSync10(rootsFile(configPath), JSON.stringify({ roots }, null, 2), "utf8");
76723
76821
  }
76724
76822
  function safeResolveInside2(target, roots) {
76725
76823
  const abs = resolve12(target);
@@ -76809,14 +76907,14 @@ async function ingestFolder(abs, ingestFile) {
76809
76907
  return { ingested, skipped };
76810
76908
  }
76811
76909
  async function dispatchSourcesRoute(req, res, deps) {
76812
- const { pathname, method, ingestFile } = deps;
76910
+ const { pathname, method, ingestFile, configPath } = deps;
76813
76911
  if (!pathname.startsWith("/api/sources/")) return false;
76814
76912
  if (!localFileOpenEnabled()) {
76815
76913
  sendJson(res, { enabled: false });
76816
76914
  return true;
76817
76915
  }
76818
76916
  if (pathname === "/api/sources/roots" && method === "GET") {
76819
- sendJson(res, { enabled: true, roots: readRoots() });
76917
+ sendJson(res, { enabled: true, roots: readRoots(configPath) });
76820
76918
  return true;
76821
76919
  }
76822
76920
  if (pathname === "/api/sources/roots" && method === "POST") {
@@ -76842,12 +76940,12 @@ async function dispatchSourcesRoute(req, res, deps) {
76842
76940
  sendJson(res, { error: `path not found: ${abs}` }, 400);
76843
76941
  return true;
76844
76942
  }
76845
- const roots = readRoots();
76943
+ const roots = readRoots(configPath);
76846
76944
  let root6 = roots.find((r6) => resolve12(r6.path) === abs);
76847
76945
  if (!root6) {
76848
76946
  root6 = { id: randomUUID4(), path: abs, kind, name: basename12(abs) || abs };
76849
76947
  roots.push(root6);
76850
- writeRoots(roots);
76948
+ writeRoots(configPath, roots);
76851
76949
  }
76852
76950
  let result;
76853
76951
  if (kind === "folder") result = await ingestFolder(abs, ingestFile);
@@ -76858,8 +76956,8 @@ async function dispatchSourcesRoute(req, res, deps) {
76858
76956
  const delMatch = /^\/api\/sources\/roots\/([^/]+)$/.exec(pathname);
76859
76957
  if (delMatch && method === "DELETE") {
76860
76958
  const id = decodeURIComponent(delMatch[1] ?? "");
76861
- const roots = readRoots().filter((r6) => r6.id !== id);
76862
- writeRoots(roots);
76959
+ const roots = readRoots(configPath).filter((r6) => r6.id !== id);
76960
+ writeRoots(configPath, roots);
76863
76961
  sendJson(res, { ok: true });
76864
76962
  return true;
76865
76963
  }
@@ -76877,7 +76975,7 @@ async function dispatchSourcesRoute(req, res, deps) {
76877
76975
  sendJson(res, { error: "path is required" }, 400);
76878
76976
  return true;
76879
76977
  }
76880
- const abs = safeResolveInside2(target, readRoots());
76978
+ const abs = safeResolveInside2(target, readRoots(configPath));
76881
76979
  if (!abs) {
76882
76980
  sendJson(res, { error: "path is outside any registered source root" }, 403);
76883
76981
  return true;
@@ -76892,7 +76990,7 @@ async function dispatchSourcesRoute(req, res, deps) {
76892
76990
  if (pathname === "/api/sources/ingest-folder" && method === "POST") {
76893
76991
  const body = await readJson(req).catch(() => ({}));
76894
76992
  const target = typeof body.path === "string" ? body.path : "";
76895
- const abs = safeResolveInside2(target, readRoots());
76993
+ const abs = safeResolveInside2(target, readRoots(configPath));
76896
76994
  if (!abs) {
76897
76995
  sendJson(res, { error: "path is outside any registered source root" }, 403);
76898
76996
  return true;
@@ -76906,7 +77004,7 @@ async function dispatchSourcesRoute(req, res, deps) {
76906
77004
  // src/gui/import-routes.ts
76907
77005
  init_adapter();
76908
77006
  init_http();
76909
- import { existsSync as existsSync27, readFileSync as readFileSync24, statSync as statSync10 } from "fs";
77007
+ import { existsSync as existsSync28, readFileSync as readFileSync24, statSync as statSync10 } from "fs";
76910
77008
  import { isAbsolute as isAbsolute4, join as join30 } from "path";
76911
77009
  init_native_entities();
76912
77010
  function badRequest(message) {
@@ -76940,7 +77038,7 @@ async function readImportSourceFromFile(db, fileId, latticeRoot) {
76940
77038
  );
76941
77039
  if (!row) throw badRequest("Unknown import file: " + fileId);
76942
77040
  const path3 = localPathOf2(row, latticeRoot);
76943
- if (!path3 || !existsSync27(path3)) {
77041
+ if (!path3 || !existsSync28(path3)) {
76944
77042
  throw badRequest("The import file\u2019s bytes are not available locally.");
76945
77043
  }
76946
77044
  const sizeBytes = statSync10(path3).size;
@@ -79081,7 +79179,7 @@ init_dispatch();
79081
79179
  init_column_descriptions();
79082
79180
  init_mutations();
79083
79181
  init_native_entities();
79084
- import { createReadStream as createReadStream3, existsSync as existsSync28, realpathSync as realpathSync2, statSync as statSync11 } from "fs";
79182
+ import { createReadStream as createReadStream3, existsSync as existsSync29, realpathSync as realpathSync2, statSync as statSync11 } from "fs";
79085
79183
  import { extname as extname3, join as join31, normalize as normalize2, sep as sep9 } from "path";
79086
79184
 
79087
79185
  // src/gui/count-many.ts
@@ -79289,7 +79387,7 @@ async function handleReadRoutes(req, res, ctx, deps) {
79289
79387
  const base = deps.guiAssetsDir.replace(/[/\\]+$/, "");
79290
79388
  const target = normalize2(join31(base, rel));
79291
79389
  const within = target === base || target.startsWith(base + sep9);
79292
- if (!within || !existsSync28(target) || !statSync11(target).isFile()) {
79390
+ if (!within || !existsSync29(target) || !statSync11(target).isFile()) {
79293
79391
  sendJson(res, { error: "asset not found" }, 404);
79294
79392
  return true;
79295
79393
  }
@@ -80497,16 +80595,16 @@ async function handleHistoryRoutes(req, res, ctx, deps) {
80497
80595
  // src/gui/workspaces-routes.ts
80498
80596
  init_http();
80499
80597
  import { resolve as resolve13 } from "path";
80500
- import { existsSync as existsSync29, rmSync } from "fs";
80598
+ import { existsSync as existsSync30, rmSync as rmSync2 } from "fs";
80501
80599
  init_workspace();
80502
80600
  init_lattice_root();
80503
80601
  init_user_config();
80504
80602
  function cleanupWorkspaceFiles(root6, ws) {
80505
80603
  if (!ws.configPath && ws.kind === "local") {
80506
- rmSync(workspaceDir(root6, ws.dir), { recursive: true, force: true });
80604
+ rmSync2(workspaceDir(root6, ws.dir), { recursive: true, force: true });
80507
80605
  } else if (ws.kind === "cloud") {
80508
- if (ws.configPath && existsSync29(ws.configPath)) {
80509
- rmSync(ws.configPath, { force: true });
80606
+ if (ws.configPath && existsSync30(ws.configPath)) {
80607
+ rmSync2(ws.configPath, { force: true });
80510
80608
  }
80511
80609
  const labelMatch = /^\$\{LATTICE_DB:([A-Za-z0-9._-]+)\}$/.exec(ws.db.trim());
80512
80610
  const label = labelMatch?.[1];
@@ -80709,15 +80807,15 @@ async function handleWorkspacesRoutes(req, res, ctx, deps) {
80709
80807
  // src/gui/databases-routes.ts
80710
80808
  init_http();
80711
80809
  import { basename as basename14, resolve as resolve15 } from "path";
80712
- import { existsSync as existsSync31 } from "fs";
80810
+ import { existsSync as existsSync32 } from "fs";
80713
80811
  init_parser();
80714
80812
 
80715
80813
  // src/gui/config-paths.ts
80716
80814
  init_parser();
80717
- import { basename as basename13, dirname as dirname16, join as join32, resolve as resolve14 } from "path";
80815
+ import { basename as basename13, dirname as dirname17, join as join32, resolve as resolve14 } from "path";
80718
80816
  import {
80719
- existsSync as existsSync30,
80720
- mkdirSync as mkdirSync12,
80817
+ existsSync as existsSync31,
80818
+ mkdirSync as mkdirSync13,
80721
80819
  readFileSync as readFileSync25,
80722
80820
  readdirSync as readdirSync9,
80723
80821
  unlinkSync as unlinkSync5,
@@ -80725,10 +80823,10 @@ import {
80725
80823
  } from "fs";
80726
80824
  import { parseDocument as parseDocument7 } from "yaml";
80727
80825
  function resolveOutputDirForConfig(configPath) {
80728
- const base = dirname16(resolve14(configPath));
80826
+ const base = dirname17(resolve14(configPath));
80729
80827
  for (const dir of ["context", ".", "generated"]) {
80730
80828
  const abs = resolve14(base, dir);
80731
- if (existsSync30(join32(abs, ".lattice", "manifest.json"))) return abs;
80829
+ if (existsSync31(join32(abs, ".lattice", "manifest.json"))) return abs;
80732
80830
  }
80733
80831
  return resolve14(base, "context");
80734
80832
  }
@@ -80737,7 +80835,7 @@ function friendlyConfigName(parsedName, configPath) {
80737
80835
  return basename13(configPath).replace(/\.(ya?ml)$/, "");
80738
80836
  }
80739
80837
  function listConfigs(activeConfigPath) {
80740
- const dir = dirname16(activeConfigPath);
80838
+ const dir = dirname17(activeConfigPath);
80741
80839
  const entries = [];
80742
80840
  for (const fname of readdirSync9(dir)) {
80743
80841
  if (!fname.endsWith(".yml") && !fname.endsWith(".yaml")) continue;
@@ -80766,17 +80864,17 @@ function listConfigs(activeConfigPath) {
80766
80864
  return entries.sort((a6, b6) => a6.label.localeCompare(b6.label));
80767
80865
  }
80768
80866
  function createBlankConfig(activeConfigPath, dbName) {
80769
- const dir = dirname16(activeConfigPath);
80867
+ const dir = dirname17(activeConfigPath);
80770
80868
  const slug = dbName.toLowerCase().replace(/[^a-z0-9_-]+/g, "-").replace(/^-+|-+$/g, "");
80771
80869
  if (!slug) throw new Error("Workspace name must contain at least one alphanumeric character");
80772
80870
  const configPath = join32(dir, `${slug}.config.yml`);
80773
- if (existsSync30(configPath)) throw new Error(`Config already exists: ${slug}.config.yml`);
80871
+ if (existsSync31(configPath)) throw new Error(`Config already exists: ${slug}.config.yml`);
80774
80872
  const yaml = `db: ./data/${slug}.db
80775
80873
 
80776
80874
  entities: {}
80777
80875
  `;
80778
80876
  writeFileSync11(configPath, yaml, "utf8");
80779
- mkdirSync12(join32(dir, "data"), { recursive: true });
80877
+ mkdirSync13(join32(dir, "data"), { recursive: true });
80780
80878
  return configPath;
80781
80879
  }
80782
80880
  function sqliteFileForConfig(configPath) {
@@ -80785,18 +80883,18 @@ function sqliteFileForConfig(configPath) {
80785
80883
  if (!raw) return null;
80786
80884
  if (isPostgresUrl(raw) || raw.startsWith("${LATTICE_DB:")) return null;
80787
80885
  if (raw === ":memory:" || raw.startsWith("file:")) return null;
80788
- return resolve14(dirname16(configPath), raw);
80886
+ return resolve14(dirname17(configPath), raw);
80789
80887
  }
80790
80888
  function deleteDatabaseFiles(targetConfigPath) {
80791
80889
  const sqliteFile = sqliteFileForConfig(targetConfigPath);
80792
80890
  unlinkSync5(targetConfigPath);
80793
80891
  let deletedDbFile = null;
80794
- if (sqliteFile && existsSync30(sqliteFile)) {
80892
+ if (sqliteFile && existsSync31(sqliteFile)) {
80795
80893
  unlinkSync5(sqliteFile);
80796
80894
  deletedDbFile = sqliteFile;
80797
80895
  for (const suffix of ["-wal", "-shm", "-journal"]) {
80798
80896
  const sidecar = sqliteFile + suffix;
80799
- if (existsSync30(sidecar)) unlinkSync5(sidecar);
80897
+ if (existsSync31(sidecar)) unlinkSync5(sidecar);
80800
80898
  }
80801
80899
  }
80802
80900
  return { deletedConfig: basename13(targetConfigPath), deletedDbFile };
@@ -80830,7 +80928,7 @@ async function handleDatabasesRoutes(req, res, ctx, deps) {
80830
80928
  return true;
80831
80929
  }
80832
80930
  const newPath = resolve15(body.path);
80833
- if (!existsSync31(newPath)) {
80931
+ if (!existsSync32(newPath)) {
80834
80932
  sendJson(res, { error: `Config not found: ${newPath}` }, 400);
80835
80933
  return true;
80836
80934
  }
@@ -80936,8 +81034,8 @@ async function handleDatabasesRoutes(req, res, ctx, deps) {
80936
81034
  // src/gui/server.ts
80937
81035
  init_user_config();
80938
81036
  function resolveDefaultGuiAssetsDir() {
80939
- const bundleSibling = process.argv[1] ? resolve16(dirname17(process.argv[1]), "gui-assets") : null;
80940
- if (bundleSibling && existsSync32(bundleSibling)) return bundleSibling;
81037
+ const bundleSibling = process.argv[1] ? resolve16(dirname18(process.argv[1]), "gui-assets") : null;
81038
+ if (bundleSibling && existsSync33(bundleSibling)) return bundleSibling;
80941
81039
  return resolve16(process.cwd(), "dist", "gui-assets");
80942
81040
  }
80943
81041
  function sendText(res, body, status = 200, contentType = "text/plain; charset=utf-8") {
@@ -80994,7 +81092,7 @@ async function startGuiServer(options) {
80994
81092
  const sessionId = crypto.randomUUID();
80995
81093
  let updateService = null;
80996
81094
  let activeRef = bootConfigPath && bootOutputDir ? await openConfig(bootConfigPath, bootOutputDir, autoRender, options.realtimeWatchdogMs) : null;
80997
- const latticeRoot = (bootConfigPath ? findLatticeRoot(dirname17(bootConfigPath)) : null) ?? (options.latticeRoot ? resolve16(options.latticeRoot) : null);
81095
+ const latticeRoot = (bootConfigPath ? findLatticeRoot(dirname18(bootConfigPath)) : null) ?? (options.latticeRoot ? resolve16(options.latticeRoot) : null);
80998
81096
  let currentWorkspaceId = null;
80999
81097
  if (latticeRoot && bootConfigPath) {
81000
81098
  const launched = listWorkspaces(latticeRoot).find(
@@ -81348,7 +81446,7 @@ async function startGuiServer(options) {
81348
81446
  createJunction: (otherTable) => createFileJunction(active, otherTable, sessionId),
81349
81447
  createEntity: (entity, columns) => createUserEntity(active, entity, columns, sessionId),
81350
81448
  aggressiveness: getAggressiveness(),
81351
- latticeRoot: dirname17(active.configPath),
81449
+ latticeRoot: dirname18(active.configPath),
81352
81450
  configPath: active.configPath,
81353
81451
  outputDir: active.outputDir,
81354
81452
  sessionId,
@@ -81373,7 +81471,7 @@ async function startGuiServer(options) {
81373
81471
  createJunction: (otherTable) => createFileJunction(active, otherTable, sessionId),
81374
81472
  createEntity: (entity, columns) => createUserEntity(active, entity, columns, sessionId),
81375
81473
  aggressiveness: getAggressiveness(),
81376
- latticeRoot: dirname17(active.configPath),
81474
+ latticeRoot: dirname18(active.configPath),
81377
81475
  configPath: active.configPath,
81378
81476
  outputDir: active.outputDir,
81379
81477
  sessionId,
@@ -81384,6 +81482,7 @@ async function startGuiServer(options) {
81384
81482
  return await dispatchSourcesRoute(req2, res2, {
81385
81483
  db: active.db,
81386
81484
  ingestFile: (p3) => ingestLocalFile(ingestCtx, mctx, p3, false),
81485
+ configPath: active.configPath,
81387
81486
  pathname,
81388
81487
  method
81389
81488
  });
@@ -81399,7 +81498,7 @@ async function startGuiServer(options) {
81399
81498
  return await dispatchImportRoute(req2, res2, {
81400
81499
  db: active.db,
81401
81500
  configPath: active.configPath,
81402
- latticeRoot: dirname17(active.configPath),
81501
+ latticeRoot: dirname18(active.configPath),
81403
81502
  validTables: active.validTables,
81404
81503
  softDeletable: active.softDeletable
81405
81504
  });
@@ -81428,7 +81527,7 @@ async function startGuiServer(options) {
81428
81527
  if (!pathname.startsWith("/api/files/")) return false;
81429
81528
  return await dispatchFilesRoute(req2, res2, {
81430
81529
  db: active.db,
81431
- latticeRoot: dirname17(active.configPath),
81530
+ latticeRoot: dirname18(active.configPath),
81432
81531
  configPath: active.configPath,
81433
81532
  pathname,
81434
81533
  method
@@ -81921,7 +82020,7 @@ function printHelp() {
81921
82020
  );
81922
82021
  }
81923
82022
  function getVersion() {
81924
- if (true) return "4.3.0";
82023
+ if (true) return "4.3.2";
81925
82024
  try {
81926
82025
  const pkgPath = new URL("../package.json", import.meta.url).pathname;
81927
82026
  const pkg = JSON.parse(readFileSync26(pkgPath, "utf-8"));
@@ -81935,7 +82034,7 @@ function printVersion() {
81935
82034
  }
81936
82035
  function getGuiAssetsDir() {
81937
82036
  const fromBundle = new URL("./gui-assets", import.meta.url).pathname;
81938
- if (existsSync33(fromBundle)) return fromBundle;
82037
+ if (existsSync34(fromBundle)) return fromBundle;
81939
82038
  return new URL("../dist/gui-assets", import.meta.url).pathname;
81940
82039
  }
81941
82040
  async function runUpdate() {
@@ -81979,7 +82078,7 @@ function runGenerate(args) {
81979
82078
  console.error('Error: config must have an "entities" key');
81980
82079
  process.exit(1);
81981
82080
  }
81982
- const configDir2 = dirname18(configPath);
82081
+ const configDir2 = dirname19(configPath);
81983
82082
  const outDir = resolve17(args.out);
81984
82083
  try {
81985
82084
  const result = generateAll({ config, configDir: configDir2, outDir, scaffold: args.scaffold });