latticesql 4.3.0 → 4.3.1

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/index.js CHANGED
@@ -64001,12 +64001,16 @@ var tokensCss = `
64001
64001
  surface (a bare input on a modal, the Database wizard, User Config, etc.):
64002
64002
  dark text on a white field with a light border. Placeholders use the
64003
64003
  muted token. Affects every input/select/textarea across the GUI. */
64004
- input, select, textarea {
64004
+ /* Text-like fields only \u2014 radios/checkboxes keep their native rendering
64005
+ (the box/border treatment mangles them). The accent color tints the native
64006
+ controls so checked radios/checkboxes are on-brand blue. */
64007
+ input:not([type='radio']):not([type='checkbox']):not([type='range']), select, textarea {
64005
64008
  color: var(--text);
64006
64009
  background: var(--surface);
64007
64010
  border: 1px solid var(--border);
64008
64011
  border-radius: 6px;
64009
64012
  }
64013
+ input[type='radio'], input[type='checkbox'] { accent-color: var(--accent); }
64010
64014
  input::placeholder, textarea::placeholder {
64011
64015
  color: var(--text-muted);
64012
64016
  opacity: 1;
@@ -64991,7 +64995,7 @@ var teamsCss = ` /* \u2500\u2500 Teams (Project Config + User Config) \u2500\
64991
64995
  color: var(--text); font-weight: 500;
64992
64996
  text-transform: uppercase; letter-spacing: 0.04em;
64993
64997
  }
64994
- .modal .field input, .modal .field textarea {
64998
+ .modal .field input:not([type='radio']):not([type='checkbox']), .modal .field textarea {
64995
64999
  width: 100%; padding: 6px 8px;
64996
65000
  background: var(--surface); color: var(--text);
64997
65001
  border: 1px solid var(--border-strong);
@@ -65001,6 +65005,20 @@ var teamsCss = ` /* \u2500\u2500 Teams (Project Config + User Config) \u2500\
65001
65005
  color: var(--text-muted);
65002
65006
  }
65003
65007
  .modal .field textarea { min-height: 60px; font-family: ui-monospace, monospace; font-size: 12px; }
65008
+ /* New-workspace "Kind" selector \u2014 clean cards, blue-highlighted selection. */
65009
+ .wiz-kind-opts { display: flex; gap: 10px; margin-top: 6px; flex-wrap: wrap; }
65010
+ .wiz-kind-card {
65011
+ flex: 1 1 0; min-width: 132px; display: flex; align-items: center; gap: 9px;
65012
+ padding: 10px 12px; border: 1px solid var(--border); border-radius: 8px;
65013
+ background: var(--surface); cursor: pointer;
65014
+ transition: border-color 0.12s ease, background 0.12s ease;
65015
+ }
65016
+ .wiz-kind-card:hover { border-color: var(--border-strong); }
65017
+ .wiz-kind-card:has(input:checked) { border-color: var(--accent); background: var(--accent-soft); }
65018
+ .wiz-kind-card input { margin: 0; flex: 0 0 auto; }
65019
+ .wiz-kind-name { font-size: 13px; color: var(--text); text-transform: none; letter-spacing: 0; }
65020
+ .wiz-kind-sub { color: var(--text-muted); font-size: 11px; margin-left: 2px; }
65021
+ .wiz-kind-card:has(input:checked) .wiz-kind-name { color: var(--accent-deep); font-weight: 500; }
65004
65022
  .modal .copy-token {
65005
65023
  padding: 8px 10px; background: var(--surface-2); border: 1px solid var(--border);
65006
65024
  border-radius: 4px; font-family: ui-monospace, monospace; font-size: 12px;
@@ -66246,6 +66264,9 @@ var bootJs = ` // \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u250
66246
66264
  initRailDragDrop();
66247
66265
  renderComposer();
66248
66266
  initThreadControls();
66267
+ // Warm up on-device voice in the background shortly after boot so dictation
66268
+ // is ready on first use \u2014 no visible model-loading step, ever.
66269
+ if (typeof voicePreload === 'function') setTimeout(voicePreload, 1500);
66249
66270
  checkNativeSetup();
66250
66271
  // App is fully populated \u2014 reveal it (Feature C).
66251
66272
  hideAppLoading();
@@ -70009,9 +70030,14 @@ var dashboardJs = ` // \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
70009
70030
  }
70010
70031
  var d = displayFor(table);
70011
70032
  // The tab shows the open RECORD's name (e.g. an entity row), not the
70012
- // object/table name.
70033
+ // object/table name. Guard: only retitle a RECORD ('item:') tab \u2014 never the
70034
+ // shared Brain Graph ('graph') tab, even if a record render briefly runs
70035
+ // while the hash still resolves to the graph (which would rename \u{1F9E0}).
70013
70036
  if (typeof setTabTitle === 'function') {
70014
- setTabTitle(tabKeyForHash(location.hash), fsDisplayName(row) || d.label);
70037
+ var fsItemKey = tabKeyForHash(location.hash);
70038
+ if (fsItemKey && fsItemKey.indexOf('item:') === 0) {
70039
+ setTabTitle(fsItemKey, fsDisplayName(row) || d.label);
70040
+ }
70015
70041
  }
70016
70042
  // Files + artifacts get the two-view document layout (formatted display +
70017
70043
  // a View Source toggle) with a Version History + Delete dropdown \u2014 not the
@@ -70081,7 +70107,10 @@ var dashboardJs = ` // \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
70081
70107
  // The tab shows the FILE's name (e.g. "Properties Dashboard"), not the
70082
70108
  // object name ("Files").
70083
70109
  if (typeof setTabTitle === 'function') {
70084
- setTabTitle(tabKeyForHash(location.hash), fsDisplayName(row) || d.label);
70110
+ var fsDocKey = tabKeyForHash(location.hash);
70111
+ if (fsDocKey && fsDocKey.indexOf('item:') === 0) {
70112
+ setTabTitle(fsDocKey, fsDisplayName(row) || d.label);
70113
+ }
70085
70114
  }
70086
70115
  var mode = fileViewMode[id] || 'display';
70087
70116
  // Actions live in a dropdown menu next to the title; View source / Version
@@ -72288,15 +72317,18 @@ var dataModelJs = ` // \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
72288
72317
  return '' +
72289
72318
  nameField +
72290
72319
  '<div class="field"><label>Kind</label>' +
72291
- '<div style="display:flex;gap:16px;margin-top:4px;flex-wrap:wrap">' +
72292
- '<label style="display:flex;align-items:center;gap:6px;font-weight:400;text-transform:none;letter-spacing:0">' +
72293
- '<input type="radio" name="wiz-kind" value="local"' + (kind === 'local' ? ' checked' : '') + ' /> New local (SQLite)' +
72320
+ '<div class="wiz-kind-opts">' +
72321
+ '<label class="wiz-kind-card">' +
72322
+ '<input type="radio" name="wiz-kind" value="local"' + (kind === 'local' ? ' checked' : '') + ' />' +
72323
+ '<span class="wiz-kind-name">New local <span class="wiz-kind-sub">SQLite</span></span>' +
72294
72324
  '</label>' +
72295
- '<label style="display:flex;align-items:center;gap:6px;font-weight:400;text-transform:none;letter-spacing:0">' +
72296
- '<input type="radio" name="wiz-kind" value="cloud"' + (kind === 'cloud' ? ' checked' : '') + ' /> New cloud (Postgres)' +
72325
+ '<label class="wiz-kind-card">' +
72326
+ '<input type="radio" name="wiz-kind" value="cloud"' + (kind === 'cloud' ? ' checked' : '') + ' />' +
72327
+ '<span class="wiz-kind-name">New cloud <span class="wiz-kind-sub">Postgres</span></span>' +
72297
72328
  '</label>' +
72298
- '<label style="display:flex;align-items:center;gap:6px;font-weight:400;text-transform:none;letter-spacing:0">' +
72299
- '<input type="radio" name="wiz-kind" value="join"' + (kind === 'join' ? ' checked' : '') + ' /> Join a team (invite)' +
72329
+ '<label class="wiz-kind-card">' +
72330
+ '<input type="radio" name="wiz-kind" value="join"' + (kind === 'join' ? ' checked' : '') + ' />' +
72331
+ '<span class="wiz-kind-name">Join a team <span class="wiz-kind-sub">invite</span></span>' +
72300
72332
  '</label>' +
72301
72333
  '</div>' +
72302
72334
  '<p style="font-size:11px;color:var(--text-muted);margin:6px 0 0">' +
@@ -74441,6 +74473,14 @@ var voiceLocalJs = ` // \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u250
74441
74473
  return _voiceWorker;
74442
74474
  }
74443
74475
 
74476
+ // Warm up the voice worker + model in the BACKGROUND on launch, so dictation is
74477
+ // ready by the time the user records and any first-run weight fetch happens
74478
+ // silently up front (never mid-recording, never with a visible "downloading"
74479
+ // state). Idempotent + best-effort \u2014 a failure just leaves the mic to lazy-init.
74480
+ function voicePreload() {
74481
+ try { getVoiceWorker(); } catch (_) { /* best-effort */ }
74482
+ }
74483
+
74444
74484
  function voicePreferredDevice() {
74445
74485
  // WebGPU when the browser exposes it, else WASM. The worker downgrades to
74446
74486
  // wasm itself if the runtime can't honor webgpu, so this is just a hint.
@@ -74462,14 +74502,14 @@ var voiceLocalJs = ` // \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u250
74462
74502
  _voiceWorkerReady = false;
74463
74503
  }
74464
74504
 
74465
- // Forward model-download progress to the composer placeholder so the first
74466
- // use shows "Downloading voice model\u2026 N%" (it needs the network ONCE; after
74467
- // that it's cached and offline).
74468
- function onVoiceProgress(file, progress) {
74469
- var inp = document.getElementById('chat-input');
74470
- if (!inp) return;
74471
- var pct = (typeof progress === 'number' && progress > 0) ? (' ' + Math.round(progress) + '%') : '';
74472
- inp.setAttribute('placeholder', 'Downloading voice model\u2026' + pct);
74505
+ // Model loading is SILENT \u2014 the user never sees a "downloading voice model"
74506
+ // state. The worker + model are warmed up in the background on launch (see
74507
+ // voicePreload), and the ORT runtime ships bundled, so by the time anyone
74508
+ // records, dictation is ready. We intentionally surface no loading progress in
74509
+ // the composer; if a first-run weight fetch is still in flight, the existing
74510
+ // "Transcribing\u2026" placeholder covers it.
74511
+ function onVoiceProgress(_file, _progress) {
74512
+ /* intentionally silent \u2014 no visible voice-model loading UI */
74473
74513
  }
74474
74514
 
74475
74515
  // Decode a recorded audio blob to mono 16 kHz PCM (Float32Array), entirely in
@@ -75473,12 +75513,33 @@ var sourcesJs = `
75473
75513
  '<span class="src-name">' + escapeHtml(name) + '</span></div></li>';
75474
75514
  }).join('') + '</ul>'
75475
75515
  : '';
75516
+ // Preserve expanded folders across this re-render so an in-progress
75517
+ // ingest (which re-renders the sidebar) never snaps an open folder shut.
75518
+ // Capture each expanded folder's path + its lazily-loaded children markup,
75519
+ // then re-attach + re-open them after the rebuild (no re-fetch, no flicker).
75520
+ var openFolders = {};
75521
+ host.querySelectorAll('.src-folder[data-loaded="1"]').forEach(function (li) {
75522
+ var ul0 = li.querySelector(':scope > .src-children');
75523
+ if (ul0 && !ul0.hidden) openFolders[li.getAttribute('data-path')] = ul0.innerHTML;
75524
+ });
75476
75525
  if (!rootsHtml && !looseHtml) {
75477
75526
  host.innerHTML = '<div class="src-empty">No files yet.</div>';
75478
75527
  return;
75479
75528
  }
75480
75529
  host.innerHTML = rootsHtml + looseHtml;
75481
75530
  wireSourceTree(host);
75531
+ host.querySelectorAll('.src-folder').forEach(function (li) {
75532
+ var saved = openFolders[li.getAttribute('data-path')];
75533
+ if (saved == null) return;
75534
+ var ul1 = li.querySelector(':scope > .src-children');
75535
+ var caret = li.querySelector(':scope > .src-row > .src-caret');
75536
+ if (!ul1) return;
75537
+ ul1.innerHTML = saved;
75538
+ ul1.hidden = false;
75539
+ li.setAttribute('data-loaded', '1');
75540
+ if (caret) caret.textContent = '\u25BE';
75541
+ wireSourceTree(ul1);
75542
+ });
75482
75543
  })
75483
75544
  .catch(function () { host.innerHTML = ''; });
75484
75545
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "latticesql",
3
- "version": "4.3.0",
3
+ "version": "4.3.1",
4
4
  "description": "Persistent structured memory for AI agent systems — pluggable SQLite or Postgres backend, LLM context bridge",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -48,6 +48,7 @@
48
48
  "test:deno": "deno test --no-check -A tests/deno/",
49
49
  "desktop:dev": "npm run build && node scripts/sync-desktop-version.mjs && deno desktop --no-check --allow-all desktop/main.ts",
50
50
  "desktop:build:mac": "npm run build && node scripts/sync-desktop-version.mjs && deno desktop --no-check --allow-env --allow-read --allow-write --allow-net --allow-run --allow-sys --allow-ffi --include dist/gui-assets --output dist-desktop/Lattice.dmg desktop/main.ts",
51
+ "desktop:build:mac:pkg": "npm run build && node scripts/sync-desktop-version.mjs && deno desktop --no-check --allow-env --allow-read --allow-write --allow-net --allow-run --allow-sys --allow-ffi --include dist/gui-assets --output dist-desktop/Lattice.app desktop/main.ts && sh scripts/build-mac-pkg.sh",
51
52
  "desktop:build:win": "npm run build && node scripts/sync-desktop-version.mjs && deno desktop --no-check --allow-env --allow-read --allow-write --allow-net --allow-run --allow-sys --allow-ffi --include dist/gui-assets --output dist-desktop/Lattice.msi desktop/main.ts",
52
53
  "prepublishOnly": "npm run check:generic && npm run build && npm run typecheck && npm test"
53
54
  },