@amd-gaia/agent-ui 0.25.0-rc.8 → 0.25.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.
@@ -0,0 +1 @@
1
+ import{r as e}from"./rolldown-runtime-hePW80VL.js";import{o as t}from"./jsx-runtime-DVeaULmT.js";var n=e(t(),1);function r(e,t){(0,n.useEffect)(()=>{if(!e)return;let n=e=>{e.key!==`Escape`||e.defaultPrevented||(e.preventDefault(),t())};return document.addEventListener(`keydown`,n),()=>document.removeEventListener(`keydown`,n)},[e,t])}export{r as t};
package/dist/index.html CHANGED
@@ -8,10 +8,10 @@
8
8
  <meta name="theme-color" content="#17161C" />
9
9
  <link rel="icon" type="image/png" href="./favicon.png" />
10
10
  <title>GAIA Agent UI</title>
11
- <script type="module" crossorigin src="./assets/index-D00FJoXi.js"></script>
11
+ <script type="module" crossorigin src="./assets/index-DEPbenxC.js"></script>
12
12
  <link rel="modulepreload" crossorigin href="./assets/rolldown-runtime-hePW80VL.js">
13
13
  <link rel="modulepreload" crossorigin href="./assets/jsx-runtime-DVeaULmT.js">
14
- <link rel="stylesheet" crossorigin href="./assets/index-B8E7IBmc.css">
14
+ <link rel="stylesheet" crossorigin href="./assets/index-CFVpPQal.css">
15
15
  </head>
16
16
  <body>
17
17
  <div id="root"></div>
package/main.cjs CHANGED
@@ -337,7 +337,9 @@ async function startBackend() {
337
337
  {
338
338
  cwd: os.homedir(), // Electron's cwd is "/" on macOS when launched from Finder
339
339
  stdio: ["ignore", "pipe", "pipe"],
340
- env: { ...process.env },
340
+ // GAIA_APP_PID: GAIA's daemon unloads its models once this app exits
341
+ // and no other GAIA client is using them.
342
+ env: { ...process.env, GAIA_APP_PID: String(process.pid) },
341
343
  detached: false,
342
344
  windowsHide: true, // Prevent console window flash on Windows
343
345
  }
@@ -729,6 +731,21 @@ function setupJumpList() {
729
731
 
730
732
  // ── Backend Bootstrap (Phase A) ───────────────────────────────────────────
731
733
 
734
+ /** First install found a Lemonade already running: use it, or install GAIA's own? */
735
+ async function chooseLemonadeInDialog(found) {
736
+ const { response } = await dialog.showMessageBox({
737
+ type: "question",
738
+ title: "Lemonade Server found",
739
+ message: `A Lemonade Server (v${found.version}) is already running at ${found.url}. Use it instead of installing GAIA's own?`,
740
+ detail: "This avoids running two servers and keeping two copies of each model.",
741
+ buttons: ["Use my Lemonade", "Install GAIA's own"],
742
+ defaultId: 0,
743
+ cancelId: 1,
744
+ noLink: true,
745
+ });
746
+ return response === 0 ? "external" : "gaia";
747
+ }
748
+
732
749
  /**
733
750
  * Ensure the Python backend is installed before the main window loads.
734
751
  *
@@ -776,6 +793,7 @@ async function bootstrapBackend() {
776
793
  await backendInstaller.ensureBackend({
777
794
  onProgress: progress.onProgress,
778
795
  isPackaged: app.isPackaged,
796
+ chooseLemonade: chooseLemonadeInDialog,
779
797
  });
780
798
  progress.close();
781
799
  console.log("[main] Backend bootstrap complete");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@amd-gaia/agent-ui",
3
- "version": "0.25.0-rc.8",
3
+ "version": "0.25.0",
4
4
  "type": "module",
5
5
  "productName": "GAIA Agent UI",
6
6
  "description": "Chat with the GAIA agent - local and private by default on AMD Ryzen AI, cloud models when you choose them",
@@ -1375,6 +1375,112 @@ function toPep440(version) {
1375
1375
  return version.replace(/^(\d+\.\d+\.\d+)-rc\.(\d+)$/, "$1rc$2");
1376
1376
  }
1377
1377
 
1378
+ function shouldSkipGaiaInit(opts) {
1379
+ return Boolean(opts.skipGaiaInit) || isTruthyEnv(process.env.GAIA_SKIP_GAIA_INIT);
1380
+ }
1381
+
1382
+ /**
1383
+ * Run `gaia init` for the profile the app's own setup check asks about
1384
+ * (setup_runner.PROFILE), so the first launch finds setup done instead of
1385
+ * running it a second time.
1386
+ *
1387
+ * `chooseLemonade` is asked about a Lemonade Server already running here; see
1388
+ * lemonadeInitArgs.
1389
+ *
1390
+ * Returns "done", "failed" or "skipped". The state file records it: a backend
1391
+ * whose setup never finished is not installed, and the next launch runs it.
1392
+ */
1393
+ async function runGaiaInit(gaiaBin, report, version, skipGaiaInit, chooseLemonade) {
1394
+ if (skipGaiaInit) {
1395
+ log("Skipping gaia init (skipGaiaInit=true or GAIA_SKIP_GAIA_INIT set)");
1396
+ return "skipped";
1397
+ }
1398
+ setState(STATES.INSTALLING, { stage: STAGES.GAIA_INIT, version });
1399
+ report(
1400
+ STAGES.GAIA_INIT,
1401
+ 0,
1402
+ "Setting up Lemonade Server and downloading models (this can take several minutes)"
1403
+ );
1404
+ const lemonadeArgs = await lemonadeInitArgs(gaiaBin, chooseLemonade);
1405
+ const initResult = await runCommand(
1406
+ gaiaBin,
1407
+ ["init", "--profile", "gaia", "--yes", "--skip-webui-build", ...lemonadeArgs],
1408
+ { stageLabel: "gaia-init" }
1409
+ );
1410
+ if (initResult.code !== 0) {
1411
+ // Non-fatal: the app opens and its setup screen retries, and so does the
1412
+ // next launch, because the state file records that setup did not finish.
1413
+ log(
1414
+ `Warning: gaia init exited with code ${initResult.code}. Continuing; setup runs again next launch.`
1415
+ );
1416
+ report(STAGES.GAIA_INIT, 100, "Lemonade Server setup did not finish");
1417
+ return "failed";
1418
+ }
1419
+ report(STAGES.GAIA_INIT, 100, "Lemonade Server setup complete");
1420
+ return "done";
1421
+ }
1422
+
1423
+ /**
1424
+ * Run a `gaia ... --json` command and parse what it printed.
1425
+ * Returns undefined after logging a warning that names the failure.
1426
+ */
1427
+ async function readGaiaJson(run, gaiaBin, args) {
1428
+ const shown = `gaia ${args.join(" ")}`;
1429
+ const result = await run(gaiaBin, args, { stageLabel: "lemonade" });
1430
+ if (result.code !== 0) {
1431
+ log(`Warning: ${shown} exited with code ${result.code}: ${(result.stderr || result.stdout || "").trim().slice(-400)}`);
1432
+ return undefined;
1433
+ }
1434
+ const lines = (result.stdout || "").trim().split(/\r?\n/);
1435
+ try {
1436
+ return JSON.parse(lines[lines.length - 1]);
1437
+ } catch (err) {
1438
+ log(`Warning: ${shown} printed no JSON (${err.message}): ${(result.stdout || "").trim().slice(-400)}`);
1439
+ return undefined;
1440
+ }
1441
+ }
1442
+
1443
+ /**
1444
+ * Extra `gaia init` args for a Lemonade Server the user already runs.
1445
+ *
1446
+ * Asks `chooseLemonade(found)` only on a first setup (nothing saved, no
1447
+ * LEMONADE_BASE_URL) when a usable server answers. "external" adds
1448
+ * `--lemonade-url <url>`, "gaia" adds `--gaia-lemonade`, null adds nothing:
1449
+ * init then sets up GAIA's own and prints how to switch, as it always has.
1450
+ * A server that needs a key or is too old is left to the app's setup screen.
1451
+ */
1452
+ async function lemonadeInitArgs(gaiaBin, chooseLemonade, run = runCommand) {
1453
+ if (typeof chooseLemonade !== "function") return [];
1454
+ const unchanged = "gaia init will set up GAIA's own Lemonade Server; to use yours later run `gaia lemonade connect <url>`.";
1455
+ const status = await readGaiaJson(run, gaiaBin, ["lemonade", "status", "--json"]);
1456
+ if (status === undefined || status === null) {
1457
+ log(`Warning: could not read which Lemonade Server GAIA uses; ${unchanged}`);
1458
+ return [];
1459
+ }
1460
+ if (status.saved_mode != null || status.source === "env") return [];
1461
+ const found = await readGaiaJson(run, gaiaBin, ["lemonade", "detect", "--json"]);
1462
+ if (found === undefined) {
1463
+ log(`Warning: could not look for a Lemonade Server already running; ${unchanged}`);
1464
+ return [];
1465
+ }
1466
+ if (!found) return [];
1467
+ if (found.status !== "ok") {
1468
+ log(`Found a Lemonade Server at ${found.url} (${found.status}); the app's setup screen offers it.`);
1469
+ return [];
1470
+ }
1471
+ let answer;
1472
+ try {
1473
+ answer = await chooseLemonade(found);
1474
+ } catch (err) {
1475
+ log(`Warning: could not ask whether to use the Lemonade Server at ${found.url}: ${err.message}; ${unchanged}`);
1476
+ return [];
1477
+ }
1478
+ log(`Lemonade Server at ${found.url}: user chose ${answer || "not to answer"}`);
1479
+ if (answer === "external") return ["--lemonade-url", found.url];
1480
+ if (answer === "gaia") return ["--gaia-lemonade"];
1481
+ return [];
1482
+ }
1483
+
1378
1484
  /**
1379
1485
  * Install the GAIA Python backend from scratch.
1380
1486
  *
@@ -1382,6 +1488,8 @@ function toPep440(version) {
1382
1488
  * - onProgress(stage, percent, message)
1383
1489
  * - version: string — override the pinned version
1384
1490
  * - skipGaiaInit: boolean — skip `gaia init` (for testing)
1491
+ * - chooseLemonade(found): Promise<"external"|"gaia"|null> — asked when a
1492
+ * Lemonade Server already runs here; see lemonadeInitArgs
1385
1493
  *
1386
1494
  * Throws InstallError on failure. The state file is updated to reflect
1387
1495
  * the current stage so a subsequent launch can recover.
@@ -1399,8 +1507,7 @@ async function installBackend(opts = {}) {
1399
1507
  const pipPackage = localWheel
1400
1508
  ? `${localWheel}[ui]`
1401
1509
  : `amd-gaia[ui]==${toPep440(version)}`;
1402
- const skipGaiaInit =
1403
- Boolean(opts.skipGaiaInit) || isTruthyEnv(process.env.GAIA_SKIP_GAIA_INIT);
1510
+ const skipGaiaInit = shouldSkipGaiaInit(opts);
1404
1511
 
1405
1512
  log("================================================");
1406
1513
  log(" Installing GAIA backend");
@@ -1601,31 +1708,13 @@ async function installBackend(opts = {}) {
1601
1708
  report(STAGES.INSTALL_PACKAGE, 100, "GAIA package installed");
1602
1709
 
1603
1710
  // Stage 4: gaia init
1604
- if (!skipGaiaInit) {
1605
- setState(STATES.INSTALLING, { stage: STAGES.GAIA_INIT, version });
1606
- report(
1607
- STAGES.GAIA_INIT,
1608
- 0,
1609
- "Setting up Lemonade Server and downloading models (this can take several minutes)"
1610
- );
1611
-
1612
- const initResult = await runCommand(
1613
- GAIA_BIN,
1614
- ["init", "--profile", "minimal", "--yes"],
1615
- { stageLabel: "gaia-init" }
1616
- );
1617
-
1618
- if (initResult.code !== 0) {
1619
- // gaia init failure is non-fatal (user can retry later), but we still
1620
- // log it and treat the rest of the install as successful.
1621
- log(
1622
- `Warning: gaia init exited with code ${initResult.code}. Continuing anyway.`
1623
- );
1624
- }
1625
- report(STAGES.GAIA_INIT, 100, "Lemonade Server setup complete");
1626
- } else {
1627
- log("Skipping gaia init (skipGaiaInit=true or GAIA_SKIP_GAIA_INIT set)");
1628
- }
1711
+ const init = await runGaiaInit(
1712
+ GAIA_BIN,
1713
+ report,
1714
+ version,
1715
+ skipGaiaInit,
1716
+ opts.chooseLemonade
1717
+ );
1629
1718
 
1630
1719
  // Stage 5: verify
1631
1720
  setState(STATES.INSTALLING, { stage: STAGES.VERIFY, version });
@@ -1685,7 +1774,7 @@ async function installBackend(opts = {}) {
1685
1774
  log(`Shim creation check failed: ${err.message}`);
1686
1775
  }
1687
1776
 
1688
- setState(STATES.READY, { stage: null, version, installedVersion });
1777
+ setState(STATES.READY, { stage: null, version, installedVersion, init });
1689
1778
  log("Backend install complete");
1690
1779
  }
1691
1780
 
@@ -1722,6 +1811,7 @@ function getInstalledVersion(gaiaBin) {
1722
1811
  * - onProgress(stage, percent, message)
1723
1812
  * - version: override the pinned version
1724
1813
  * - skipGaiaInit: bool
1814
+ * - chooseLemonade: see installBackend
1725
1815
  * - allowPartialRestart: bool (default true) — restart from scratch if
1726
1816
  * the state file indicates a `partial` install.
1727
1817
  *
@@ -1741,11 +1831,11 @@ async function ensureBackend(opts = {}) {
1741
1831
  // The previous run never finished. Record this and proceed with a
1742
1832
  // fresh restart (per §10.4 recommendation A).
1743
1833
  log(
1744
- `Previous install was interrupted at stage=${prev.stage || "?"} — restarting from scratch`
1834
+ `Previous install was interrupted at stage=${prev.stage || "?"} — finishing it`
1745
1835
  );
1746
1836
  setState(STATES.PARTIAL, { stage: prev.stage, message: "Previous install interrupted" });
1747
1837
  } else if (prev.state === STATES.PARTIAL) {
1748
- log("Previous launch detected a partial install — restarting from scratch");
1838
+ log("Previous launch detected a partial install — finishing it");
1749
1839
  } else if (prev.state === STATES.FAILED) {
1750
1840
  log(`Previous install failed: ${prev.message || "(no detail)"} — retrying`);
1751
1841
  } else if (prev.state === STATES.READY) {
@@ -1803,15 +1893,46 @@ async function ensureBackend(opts = {}) {
1803
1893
  // reinstall from the local wheel so CI gets a fresh install each run.
1804
1894
  const expectedVersion = resolveBackendVersion(opts);
1805
1895
  const existingBin = findGaiaBin();
1896
+ // Installed means setup finished too, not just that the package is there.
1897
+ // No state file at all is an install from before it existed.
1898
+ const prev = preChecks.previousState;
1899
+ const setupFinished =
1900
+ !prev || (prev.state === STATES.READY && prev.init !== "failed");
1901
+ const packageFinished =
1902
+ setupFinished ||
1903
+ (prev &&
1904
+ (prev.state === STATES.READY ||
1905
+ prev.stage === STAGES.GAIA_INIT ||
1906
+ prev.stage === STAGES.VERIFY));
1806
1907
  if (existingBin) {
1807
1908
  const installedVersion = getInstalledVersion(existingBin);
1808
- if (expectedVersion !== null && installedVersion === toPep440(expectedVersion)) {
1909
+ const versionMatches =
1910
+ expectedVersion !== null && installedVersion === toPep440(expectedVersion);
1911
+ if (versionMatches && !setupFinished && packageFinished) {
1912
+ log(
1913
+ `GAIA ${installedVersion} is installed but its setup did not finish ` +
1914
+ `(state=${prev.state}, stage=${prev.stage || "-"}) — running gaia init`
1915
+ );
1916
+ const report = makeProgressReporter(opts.onProgress);
1917
+ const init = await runGaiaInit(
1918
+ existingBin,
1919
+ report,
1920
+ expectedVersion,
1921
+ shouldSkipGaiaInit(opts),
1922
+ opts.chooseLemonade
1923
+ );
1924
+ setState(STATES.READY, { version: expectedVersion, installedVersion, init });
1925
+ report(STAGES.VERIFY, 100, `GAIA ${installedVersion} ready`);
1926
+ return existingBin;
1927
+ }
1928
+ if (versionMatches && setupFinished) {
1809
1929
  log(
1810
1930
  `GAIA backend already installed at version ${installedVersion} — nothing to do`
1811
1931
  );
1812
1932
  setState(STATES.READY, {
1813
1933
  version: expectedVersion,
1814
1934
  installedVersion,
1935
+ init: prev ? prev.init : undefined,
1815
1936
  });
1816
1937
  // Tell the UI we are instantly ready.
1817
1938
  const report = makeProgressReporter(opts.onProgress);
@@ -1819,7 +1940,9 @@ async function ensureBackend(opts = {}) {
1819
1940
  return existingBin;
1820
1941
  }
1821
1942
  log(
1822
- `Version mismatch: expected=${expectedVersion} installed=${installedVersion || "unknown"} — upgrading`
1943
+ versionMatches
1944
+ ? `An earlier install stopped at stage=${prev.stage || "?"} — reinstalling`
1945
+ : `Version mismatch: expected=${expectedVersion} installed=${installedVersion || "unknown"} — upgrading`
1823
1946
  );
1824
1947
  } else {
1825
1948
  log("GAIA backend not found — installing from scratch");
@@ -1873,6 +1996,7 @@ module.exports = {
1873
1996
  getInstalledVersion,
1874
1997
  findGaiaBin,
1875
1998
  toPep440,
1999
+ lemonadeInitArgs,
1876
2000
 
1877
2001
  // Pre-checks
1878
2002
  runPreChecks,
@@ -251,7 +251,9 @@ class TrayManager {
251
251
  img.setTemplateImage(true);
252
252
  return img;
253
253
  }
254
- return this._loadIcon("tray-icon.png"); // Linux: full-colour PNG
254
+ // Linux: full-colour 32px PNG (+@2x); StatusNotifier hosts scale it
255
+ // down to their 16-24px slot, which stays sharp where upscaling blurs.
256
+ return this._loadIcon("tray-icon.png");
255
257
  }
256
258
 
257
259
  _loadIcon(filename) {
@@ -260,7 +262,13 @@ class TrayManager {
260
262
  if (!fs.existsSync(iconPath)) {
261
263
  throw new Error(`[tray] icon asset missing: ${iconPath}`);
262
264
  }
263
- return nativeImage.createFromPath(iconPath);
265
+ const img = nativeImage.createFromPath(iconPath);
266
+ // An undecodable file yields an empty image, which trays draw as a blank
267
+ // or placeholder square instead of erroring.
268
+ if (img.isEmpty()) {
269
+ throw new Error(`[tray] icon asset could not be decoded: ${iconPath}`);
270
+ }
271
+ return img;
264
272
  }
265
273
 
266
274
  // ── Private: Config persistence ──────────────────────────────────────
@@ -1 +0,0 @@
1
- import{r as e}from"./rolldown-runtime-hePW80VL.js";import{o as t,r as n,t as r}from"./jsx-runtime-DVeaULmT.js";import{$t as i,Bt as a,R as o,Tt as s,Zt as c,at as l,ct as u,n as ee,r as d,st as te}from"./index-D00FJoXi.js";var f=e(t(),1),p=r();function m(){return window.gaiaUpdater}function ne({onClose:e}){let[t,n]=(0,f.useState)({kind:`loading`}),r=(0,f.useRef)(null);(0,f.useEffect)(()=>{let e=m();if(!e){n({kind:`error`,message:`Couldn't reach GitHub to list releases — check your connection; you can still download installers from the Releases page.`});return}e.listReleases().then(e=>{n(Array.isArray(e)?{kind:`list`,releases:e}:{kind:`error`,message:e.error})}).catch(()=>{n({kind:`error`,message:`Couldn't reach GitHub to list releases — check your connection; you can still download installers from the Releases page.`})})},[]),(0,f.useEffect)(()=>{function t(t){t.key===`Escape`&&e()}return document.addEventListener(`keydown`,t),()=>document.removeEventListener(`keydown`,t)},[e]),(0,f.useEffect)(()=>{let e=r.current;e&&e.querySelector(`button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])`)?.focus()},[]),(0,f.useEffect)(()=>{let e=r.current;if(!e)return;function t(t){if(t.key!==`Tab`||!e)return;let n=e.querySelectorAll(`button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])`);if(n.length===0)return;let r=n[0],i=n[n.length-1];t.shiftKey?document.activeElement===r&&(t.preventDefault(),i?.focus()):document.activeElement===i&&(t.preventDefault(),r?.focus())}return e.addEventListener(`keydown`,t),()=>e.removeEventListener(`keydown`,t)},[]);function i(e,t){e.isCurrent||n({kind:`confirm`,release:e,releases:t})}async function a(t){n({kind:`installing`});let r=m();if(!r){n({kind:`error`,message:`Bridge unavailable — please restart the app.`});return}try{await r.installVersion(t.tag),e()}catch(e){let t=e instanceof Error?e.message:String(e);n({kind:`error`,message:`Failed to start rollback: ${t}`})}}function o(e){if(!e)return``;try{return new Date(e).toLocaleDateString(void 0,{year:`numeric`,month:`short`,day:`numeric`})}catch{return e}}return(0,p.jsx)(`div`,{className:`version-picker-overlay`,onClick:t=>{t.target===t.currentTarget&&e()},children:(0,p.jsxs)(`div`,{className:`version-picker-dialog`,role:`dialog`,"aria-modal":`true`,"aria-label":`Roll back to a previous version`,ref:r,children:[(0,p.jsxs)(`div`,{className:`version-picker-header`,children:[(0,p.jsx)(`h3`,{children:`Roll back to a previous version`}),(0,p.jsx)(`button`,{className:`version-picker-close`,onClick:e,"aria-label":`Close`,type:`button`,children:`×`})]}),(0,p.jsxs)(`div`,{className:`version-picker-body`,children:[t.kind===`loading`&&(0,p.jsxs)(`div`,{className:`version-picker-loading`,"aria-busy":`true`,children:[(0,p.jsx)(`span`,{className:`version-picker-spinner`}),`Loading releases…`]}),t.kind===`error`&&(0,p.jsxs)(`div`,{className:`version-picker-error`,children:[(0,p.jsx)(`p`,{children:t.message}),(0,p.jsx)(`p`,{children:(0,p.jsx)(`a`,{href:`https://github.com/amd/gaia/releases`,target:`_blank`,rel:`noreferrer`,children:`Browse releases on GitHub`})})]}),t.kind===`list`&&(0,p.jsx)(`ul`,{className:`version-picker-list`,role:`listbox`,"aria-label":`Available releases`,children:t.releases.map(e=>(0,p.jsx)(`li`,{children:(0,p.jsxs)(`button`,{type:`button`,className:`version-picker-row`,"data-version":e.version,"aria-label":`${e.version}${e.isCurrent?` — installed`:``}${e.isPinned?` — pinned`:``}`,"aria-disabled":e.isCurrent?`true`:`false`,onClick:()=>i(e,t.releases),disabled:e.isCurrent,children:[(0,p.jsx)(`span`,{className:`vp-version`,children:e.version}),(0,p.jsx)(`span`,{className:`vp-date`,children:o(e.date)}),e.isCurrent&&(0,p.jsx)(`span`,{className:`vp-badge vp-badge-current`,children:`Installed`}),e.isPinned&&!e.isCurrent&&(0,p.jsx)(`span`,{className:`vp-badge vp-badge-pinned`,children:`Pinned`}),!e.isCurrent&&(0,p.jsx)(`span`,{className:`vp-arrow`,"aria-hidden":`true`,children:`›`})]})},e.tag))}),t.kind===`list`&&(0,p.jsxs)(`p`,{className:`version-picker-more`,children:[`Showing the `,t.releases.length,` most recent.`,` `,(0,p.jsx)(`a`,{href:`https://github.com/amd/gaia/releases`,target:`_blank`,rel:`noreferrer`,children:`Browse all releases on GitHub`})]}),t.kind===`confirm`&&(0,p.jsxs)(`div`,{className:`version-picker-confirm`,children:[(0,p.jsxs)(`p`,{children:[`This will `,(0,p.jsxs)(`strong`,{children:[`downgrade to v`,t.release.version]}),` and restart the app.`]}),(0,p.jsxs)(`p`,{className:`vp-confirm-note`,children:[`Auto-update will be paused after rollback so the app stays on v`,t.release.version,`. You can resume updates from Settings → About.`]}),(0,p.jsxs)(`div`,{className:`vp-confirm-actions`,children:[(0,p.jsx)(`button`,{type:`button`,className:`vp-btn-cancel`,onClick:()=>n({kind:`list`,releases:t.releases}),children:`Back`}),(0,p.jsx)(`button`,{type:`button`,className:`vp-btn-confirm`,onClick:()=>a(t.release),children:`Confirm downgrade & restart`})]})]}),t.kind===`installing`&&(0,p.jsxs)(`div`,{className:`version-picker-loading`,"aria-busy":`true`,children:[(0,p.jsx)(`span`,{className:`version-picker-spinner`}),`Starting download…`]})]})]})})}function h(){let[e,t]=(0,f.useState)(null),[r,m]=(0,f.useState)(!0),[h,re]=(0,f.useState)([]),[ie,_]=(0,f.useState)(!1),v=ee(),[y,b]=(0,f.useState)(``),[x,S]=(0,f.useState)(``),[C,ae]=(0,f.useState)(!1),[w,T]=(0,f.useState)(!1),[E,D]=(0,f.useState)(null),[O,k]=(0,f.useState)(!1),A=(0,f.useRef)(null),[j,M]=(0,f.useState)(!1),[N,P]=(0,f.useState)(!1),[F,I]=(0,f.useState)(!1),[L,R]=(0,f.useState)(null);(0,f.useEffect)(()=>{n.system.info(`Checking system status...`);let e=n.system.time();u().then(r=>{t(r),n.system.timed(`System status received`,e,{lemonade:r.lemonade_running?`running`:`stopped`,model:r.model_loaded||`none`,embedding:r.embedding_model_loaded?`yes`:`no`,disk:`${r.disk_space_gb}GB free`,memory:r.memory_available_gb==null?`unknown`:`${r.memory_available_gb}GB available`}),r.lemonade_running||n.system.warn(`Lemonade Server is NOT running.`)}).catch(e=>{n.system.error(`Failed to get system status`,e),t(null)}).finally(()=>m(!1)),l().then(e=>re(e.servers)).catch(()=>{}),te().then(e=>{let t=e.custom_model??``;b(t),S(t),M(e.dynamic_tools),P(e.dynamic_tools_locked)}).catch(e=>{n.system.error(`Failed to load settings`,e)}).finally(()=>ae(!0))},[]),(0,f.useEffect)(()=>()=>{A.current&&clearTimeout(A.current)},[]);let z=(0,f.useCallback)(async()=>{let e=y.trim(),t=e.length>0?e:``;T(!0),D(null),k(!1);try{n.system.info(`Saving custom_model override`,{custom_model:t});let e=(await s({custom_model:t})).custom_model??``;b(e),S(e),k(!0),A.current&&clearTimeout(A.current),A.current=setTimeout(()=>k(!1),2200)}catch(e){let t=e instanceof Error?e.message:String(e);n.system.error(`Failed to save custom_model`,e),D(t)}finally{T(!1)}},[y]),oe=(0,f.useCallback)(async()=>{if(N||F)return;let e=j,t=!e;M(t),I(!0),R(null);try{n.system.info(`Saving dynamic_tools setting`,{dynamic_tools:t});let e=await s({dynamic_tools:t});M(e.dynamic_tools),P(e.dynamic_tools_locked)}catch(t){let r=t instanceof Error?t.message:String(t);n.system.error(`Failed to save dynamic_tools`,t),M(e),R(r)}finally{I(!1)}},[j,N,F]),B=y.trim()!==x.trim(),V=e?e.default_model_name:o,{isLoadingModel:H,isDownloadingModel:U,loadModel:W,downloadModel:G}=d(V??void 0),K=[{label:`4K`,value:4096},{label:`8K`,value:8192},{label:`16K`,value:16384},{label:`32K`,value:32768}],q=e?.model_context_size??null,[J,Y]=(0,f.useState)(``);(0,f.useEffect)(()=>{q!=null&&Y(String(q))},[q]);let X=(()=>{let e=parseInt(J,10);return Number.isFinite(e)&&e>0?e:null})(),se=X!=null&&X!==q,Z=e?.model_loaded??V,ce=(0,f.useCallback)(async()=>{X&&Z&&(n.system.info(`Reloading ${Z} with ctx_size=${X}`),await W(Z,X))},[X,Z,W]),Q=!!e?.default_model_is_cloud,$=!Q&&!!(e?.lemonade_running&&e.model_loaded&&e.expected_model_loaded===!1),le=!Q&&!!(e?.lemonade_running&&e.model_loaded&&e.context_size_sufficient===!1),ue=!Q&&!(!e?.lemonade_running||e.model_loaded||e.model_downloaded!==!1),de=($||le)&&V!==null;return(0,p.jsxs)(`div`,{className:`settings-pane`,children:[(0,p.jsx)(`h2`,{className:`settings-pane-title`,children:`Advanced`}),(0,p.jsxs)(`section`,{className:`settings-section`,children:[(0,p.jsx)(`h4`,{children:`Local model server`}),r?(0,p.jsx)(`p`,{className:`loading-text`,children:`Checking system...`}):e?(0,p.jsxs)(p.Fragment,{children:[(0,p.jsxs)(`div`,{className:`status-grid`,children:[(0,p.jsx)(g,{label:`Model server`,value:e.lemonade_running?`Running${e.lemonade_version?` v${e.lemonade_version}`:``}`:e.lemonade_error?`Status unavailable`:`Not Running`,ok:e.lemonade_running,hint:e.lemonade_running?void 0:e.lemonade_error?`Could not query it: ${e.lemonade_error}`:e.start_command?`Run: ${e.start_command}`:e.start_instruction??`Not running.`}),(0,p.jsx)(g,{label:`Model`,value:e.model_loaded||`None loaded`,ok:!!e.model_loaded&&(Q||e.expected_model_loaded!==!1),hint:e.model_loaded?!Q&&e.expected_model_loaded===!1?`Expected: ${V}`:void 0:`None loaded yet — it loads with the first message.`}),e.model_size_gb!=null&&(0,p.jsx)(g,{label:`Model Size`,value:`${e.model_size_gb} GB`,ok:!0}),e.model_device&&!Q&&(0,p.jsx)(g,{label:`Device`,value:e.model_device.toUpperCase(),ok:e.model_device!==`cpu`}),e.model_context_size!=null&&(0,p.jsx)(g,{label:`Context Window`,value:`${(e.model_context_size/1024).toFixed(0)}K tokens`,ok:e.context_size_sufficient}),e.model_labels&&e.model_labels.length>0&&(0,p.jsx)(g,{label:`Capabilities`,value:e.model_labels.join(`, `),ok:!0}),(0,p.jsx)(g,{label:`Embedding Model`,value:e.embedding_model_loaded?`Available`:`Not loaded`,ok:e.embedding_model_loaded}),e.gpu_name&&(0,p.jsx)(g,{label:`GPU`,value:`${e.gpu_name}${e.gpu_vram_gb?` (${e.gpu_vram_gb} GB)`:``}`,ok:!0}),(0,p.jsx)(g,{label:`Disk Space`,value:`${e.disk_space_gb} GB free`,ok:e.disk_space_gb>5,hint:!e.model_loaded&&e.disk_space_gb<30?`Local models need about 6 GB — only ${e.disk_space_gb} GB free`:void 0}),(0,p.jsx)(g,{label:`Memory`,value:e.memory_available_gb==null?`unknown`:`${e.memory_available_gb} GB available`,ok:e.memory_available_gb!=null&&e.memory_available_gb>2}),e.processor_name&&(0,p.jsx)(g,{label:`Processor`,value:e.processor_name,ok:!0})]}),ue&&(0,p.jsxs)(`div`,{className:`model-action-row model-action-row--download`,children:[(0,p.jsxs)(`div`,{className:`model-action-info`,children:[(0,p.jsx)(`span`,{className:`model-action-label`,children:`Model not downloaded.`}),(0,p.jsxs)(`span`,{className:`model-action-desc`,children:[(0,p.jsx)(`strong`,{children:V}),` is GAIA’s default local model (about 6 GB).`]})]}),(0,p.jsx)(`button`,{className:`btn-model-action btn-model-action--download`,onClick:()=>G(!1),disabled:U,children:U?(0,p.jsxs)(p.Fragment,{children:[(0,p.jsx)(a,{size:13,className:`btn-spinner`}),` Downloading…`]}):`Download`})]}),de&&(0,p.jsxs)(`div`,{className:`model-action-row model-action-row--load`,children:[(0,p.jsxs)(`div`,{className:`model-action-info`,children:[(0,p.jsx)(`span`,{className:`model-action-label`,children:$?`Wrong model loaded.`:`Context window too small.`}),(0,p.jsxs)(`span`,{className:`model-action-desc`,children:[`Load `,(0,p.jsx)(`strong`,{children:V}),` with `,32 .toFixed(0),`K token context.`]})]}),(0,p.jsx)(`button`,{className:`btn-model-action btn-model-action--load`,onClick:()=>W(),disabled:H,children:H?(0,p.jsxs)(p.Fragment,{children:[(0,p.jsx)(a,{size:13,className:`btn-spinner`}),` Loading…`]}):`Load Model`})]}),e.lemonade_running&&V!==null&&!Q&&(0,p.jsxs)(`div`,{className:`force-redownload-row`,children:[(0,p.jsx)(`span`,{className:`force-redownload-label`,children:`If the model file is corrupted:`}),(0,p.jsx)(`button`,{className:`btn-force-redownload`,onClick:()=>G(!0),disabled:U,children:U?(0,p.jsxs)(p.Fragment,{children:[(0,p.jsx)(a,{size:12,className:`btn-spinner`}),` Downloading…`]}):`Force Re-download`})]})]}):(0,p.jsx)(`div`,{className:`status-error`,children:(0,p.jsx)(`p`,{children:`Could not reach GAIA. Check that it is still running.`})})]}),(0,p.jsxs)(`section`,{className:`settings-section`,children:[(0,p.jsx)(`h4`,{children:`Custom model ID`}),(0,p.jsx)(`p`,{className:`model-override-desc`,children:`Run any model the local server knows by its ID. Leave empty to use the model chosen under Model.`}),(0,p.jsxs)(`div`,{className:`model-input-row`,children:[(0,p.jsx)(`input`,{type:`text`,className:`model-input${x?` has-override`:``}`,placeholder:`Use the model chosen under Model`,value:y,onChange:e=>{b(e.target.value),D(null),k(!1)},onKeyDown:e=>{e.key===`Enter`&&!w&&B&&C&&(e.preventDefault(),z())},disabled:!C||w,spellCheck:!1,autoCapitalize:`off`,autoCorrect:`off`,"aria-label":`Custom model override`}),(0,p.jsx)(`div`,{className:`model-btn-group`,children:(0,p.jsx)(`button`,{className:`btn-model-save${O?` saved`:``}`,onClick:()=>{z()},disabled:!C||w||!B&&!O,"aria-label":`Save custom model`,children:w?(0,p.jsxs)(p.Fragment,{children:[(0,p.jsx)(a,{size:13,className:`btn-spinner`}),` Saving…`]}):O?(0,p.jsxs)(p.Fragment,{children:[(0,p.jsx)(c,{size:13}),` Saved`]}):`Save`})})]}),(0,p.jsxs)(`p`,{className:`model-status-hint`,children:[`Accepts a Lemonade model ID (e.g. `,(0,p.jsx)(`code`,{children:`Qwen3-4B-Instruct-2507-GGUF`}),`)`,` `,`or a HuggingFace ID (e.g. `,(0,p.jsx)(`code`,{children:`unsloth/Qwen3-4B-GGUF`}),`).`]}),E&&(0,p.jsxs)(`div`,{className:`model-warning`,role:`alert`,children:[(0,p.jsx)(i,{size:14}),(0,p.jsxs)(`div`,{className:`model-warning-content`,children:[(0,p.jsx)(`strong`,{children:`Could not save`}),(0,p.jsx)(`p`,{children:E})]})]})]}),!Q&&(0,p.jsxs)(`section`,{className:`settings-section`,children:[(0,p.jsx)(`h4`,{children:`Context Size`}),(0,p.jsx)(`p`,{className:`model-override-desc`,children:`Reload the active model with a different context window. Larger contexts use more memory and slow inference; going past the model’s training length may degrade quality.`}),(0,p.jsx)(`div`,{className:`ctx-preset-row`,children:K.map(e=>{let t=X===e.value;return(0,p.jsx)(`button`,{className:`btn-ctx-preset${t?` active`:``}`,onClick:()=>Y(String(e.value)),disabled:H,type:`button`,children:e.label},e.value)})}),(0,p.jsxs)(`div`,{className:`model-input-row`,children:[(0,p.jsx)(`input`,{type:`number`,className:`model-input`,placeholder:q==null?`4096`:String(q),value:J,min:512,step:1024,onChange:e=>Y(e.target.value),disabled:H,"aria-label":`Context size in tokens`}),(0,p.jsx)(`div`,{className:`model-btn-group`,children:(0,p.jsx)(`button`,{className:`btn-model-save`,onClick:()=>{ce()},disabled:H||!se||!e?.lemonade_running,"aria-label":`Reload model with new context size`,children:H?(0,p.jsxs)(p.Fragment,{children:[(0,p.jsx)(a,{size:13,className:`btn-spinner`}),` Reloading…`]}):`Apply`})})]}),(0,p.jsxs)(`p`,{className:`model-status-hint`,children:[`Current: `,(0,p.jsx)(`code`,{children:q==null?`unknown`:`${q.toLocaleString()} tokens`}),e?.model_loaded&&(0,p.jsxs)(p.Fragment,{children:[` on `,(0,p.jsx)(`code`,{children:e.model_loaded})]}),`.`]})]}),(0,p.jsxs)(`section`,{className:`settings-section`,children:[(0,p.jsxs)(`h4`,{children:[`Dynamic Tools `,(0,p.jsx)(`span`,{className:`beta-badge`,children:`BETA`})]}),(0,p.jsx)(`p`,{className:`model-override-desc`,children:`Trim each turn’s tool list to a semantically-matched subset to speed up the first response. It does not apply to the GAIA agent yet.`}),(0,p.jsxs)(`label`,{className:`setting-row`,children:[(0,p.jsx)(`span`,{children:`Enable dynamic tool loading`}),(0,p.jsxs)(`span`,{className:`toggle-switch`,children:[(0,p.jsx)(`input`,{type:`checkbox`,checked:j,onChange:()=>void oe(),disabled:!C||F||N,"aria-label":j?`Disable dynamic tools`:`Enable dynamic tools`}),(0,p.jsx)(`span`,{className:`toggle-track`})]})]}),N&&(0,p.jsxs)(`p`,{className:`model-status-hint`,children:[`Controlled by `,(0,p.jsx)(`code`,{children:`GAIA_DYNAMIC_TOOLS`}),` — unset that environment variable to change this here.`]}),L&&(0,p.jsxs)(`div`,{className:`model-warning`,role:`alert`,children:[(0,p.jsx)(i,{size:14}),(0,p.jsxs)(`div`,{className:`model-warning-content`,children:[(0,p.jsx)(`strong`,{children:`Could not save`}),(0,p.jsx)(`p`,{children:L})]})]})]}),h.length>0&&(0,p.jsxs)(`section`,{className:`settings-section`,children:[(0,p.jsx)(`h4`,{children:`MCP Servers`}),(0,p.jsx)(`div`,{className:`status-grid`,children:h.map(e=>(0,p.jsxs)(`div`,{className:`status-row`,children:[(0,p.jsx)(`span`,{className:`status-label`,children:e.name}),(0,p.jsx)(`div`,{className:`status-value-wrap`,children:e.connected?(0,p.jsxs)(`span`,{className:`status-value ok mcp-status-connected`,children:[(0,p.jsx)(c,{size:12}),e.tool_count,` tool`,e.tool_count===1?``:`s`]}):(0,p.jsxs)(`span`,{className:`status-value warn mcp-status-failed`,title:e.error??void 0,children:[(0,p.jsx)(i,{size:12}),`Failed`]})})]},e.name))})]}),(0,p.jsxs)(`section`,{className:`settings-section`,children:[(0,p.jsx)(`h4`,{children:`About`}),(0,p.jsxs)(`div`,{className:`about-info`,children:[(0,p.jsxs)(`p`,{children:[`GAIA v`,`0.25.0rc8`,` `,(0,p.jsx)(`span`,{className:`beta-badge`,children:`BETA`})]}),(0,p.jsx)(`p`,{className:`about-sub`,children:`Privacy-first AI chat for AMD Ryzen AI PCs.`}),v.pinnedVersion&&(0,p.jsxs)(`p`,{className:`about-pinned-notice`,children:[`Auto-update paused (pinned to `,v.pinnedVersion,`).`,` `,(0,p.jsx)(`button`,{type:`button`,className:`about-resume-btn`,onClick:()=>{window.gaiaUpdater?.resumeUpdates().catch(e=>{n.system.error(`Resume updates failed`,e)})},children:`Resume updates`})]})]}),(0,p.jsx)(`div`,{className:`setting-actions`,children:(0,p.jsx)(`button`,{type:`button`,className:`btn-secondary`,onClick:()=>_(!0),children:`Roll back to a previous version`})})]}),ie&&(0,p.jsx)(ne,{onClose:()=>_(!1)})]})}function g({label:e,value:t,ok:n,hint:r}){return(0,p.jsxs)(`div`,{className:`status-row${r?` status-row--has-hint`:``}`,children:[(0,p.jsx)(`span`,{className:`status-label`,children:e}),(0,p.jsxs)(`div`,{className:`status-value-wrap`,children:[(0,p.jsx)(`span`,{className:`status-value ${n?`ok`:`warn`}`,children:t}),r&&(0,p.jsx)(`span`,{className:`status-hint`,children:(0,p.jsx)(`code`,{children:r})})]})]})}export{h as AdvancedSettings};
@@ -1 +0,0 @@
1
- import{r as e}from"./rolldown-runtime-hePW80VL.js";import{a as t,o as n,r,t as i}from"./jsx-runtime-DVeaULmT.js";import{$t as a,B as o,Dt as s,Et as ee,Ft as te,H as c,Ht as l,J as u,Lt as d,Nt as f,Ot as p,Q as ne,V as re,W as m,Wt as h,Xt as g,gt as _,it as v,jt as y,t as b,vt as x,xt as S}from"./index-D00FJoXi.js";var C={name:`circle-stop`,size:24,node:[[`circle`,{cx:`12`,cy:`12`,r:`10`,key:`1mglay`}],[`rect`,{x:`9`,y:`9`,width:`6`,height:`6`,rx:`1`,key:`1ssd4o`}]],aliases:[`stop-circle`]};C.node;var w=t(C),T={name:`link-2`,size:24,node:[[`path`,{d:`M9 17H7A5 5 0 0 1 7 7h2`,key:`8i5ue5`}],[`path`,{d:`M15 7h2a5 5 0 1 1 0 10h-2`,key:`1b9ql8`}],[`line`,{x1:`8`,x2:`16`,y1:`12`,y2:`12`,key:`1jonct`}]]};T.node;var ie=t(T),E={name:`loader`,size:24,node:[[`path`,{d:`M12 2v4`,key:`3427ic`}],[`path`,{d:`m16.2 7.8 2.9-2.9`,key:`r700ao`}],[`path`,{d:`M18 12h4`,key:`wj9ykh`}],[`path`,{d:`m16.2 16.2 2.9 2.9`,key:`1bxg5t`}],[`path`,{d:`M12 18v4`,key:`jadmvz`}],[`path`,{d:`m4.9 19.1 2.9-2.9`,key:`bwix9q`}],[`path`,{d:`M2 12h4`,key:`j09sii`}],[`path`,{d:`m4.9 4.9 2.9 2.9`,key:`giyufr`}]]};E.node;var ae=t(E),D={name:`refresh-ccw`,size:24,node:[[`path`,{d:`M21 12a9 9 0 0 0-9-9 9.75 9.75 0 0 0-6.74 2.74L3 8`,key:`14sxne`}],[`path`,{d:`M3 3v5h5`,key:`1xhq8a`}],[`path`,{d:`M3 12a9 9 0 0 0 9 9 9.75 9.75 0 0 0 6.74-2.74L21 16`,key:`1hlbsb`}],[`path`,{d:`M16 16h5v5`,key:`ccwih5`}]]};D.node;var oe=t(D),O=e(n(),1),k=i();function se(e){let t=Math.floor((Date.now()-e)/1e3);return t<60?`${t}s`:`${Math.floor(t/60)}m ${t%60}s`}function A(e){try{let t=new Date(e);if(isNaN(t.getTime()))return``;let n=new Date().getTime()-t.getTime(),r=Math.floor(n/1e3),i=Math.floor(r/60),a=Math.floor(i/60),o=Math.floor(a/24);return r<60?`just now`:i<60?`${i}m ago`:a<24?`${a}h ago`:o===1?`yesterday`:o<7?`${o}d ago`:t.toLocaleDateString(void 0,{month:`short`,day:`numeric`,hour:`numeric`,minute:`2-digit`})}catch{return``}}function j(e){try{let t=new Date(e);return isNaN(t.getTime())?``:t.toLocaleString(void 0,{year:`numeric`,month:`short`,day:`numeric`,hour:`numeric`,minute:`2-digit`,second:`2-digit`})}catch{return``}}function M(){let{documents:e,setDocuments:t,setShowDocLibrary:n,setShowFileBrowser:i,currentSessionId:C,sessions:T,updateSessionInList:E,draftDocumentIds:D,addDraftDocuments:M,removeDraftDocument:N}=p(),P=T.find(e=>e.id===C)??null,[F,I]=(0,O.useState)(!1),[L,R]=(0,O.useState)(!1),[z,B]=(0,O.useState)(``),[V,H]=(0,O.useState)(``),[U,W]=(0,O.useState)(null),[G,K]=(0,O.useState)(new Set),q=(0,O.useRef)(new Map),[,ce]=(0,O.useState)(0);(0,O.useEffect)(()=>{r.doc.info(`Loading document library...`);let e=r.doc.time();_().then(n=>{let i=n.documents||[];t(i),r.doc.timed(`Loaded ${i.length} document(s), ${n.total_chunks||0} chunks, ${n.total_size_bytes||0} bytes total`,e)}).catch(e=>{r.doc.error(`Failed to load documents`,e),t([])})},[t]);let J=e.some(e=>e.indexing_status===`indexing`||e.indexing_status===`pending`);(0,O.useEffect)(()=>{if(!J)return;let e=p.getState().documents;for(let t of e)(t.indexing_status===`indexing`||t.indexing_status===`pending`)&&!q.current.has(t.id)&&q.current.set(t.id,Date.now());let n=!1,r=setInterval(async()=>{if(ce(e=>e+1),!n){n=!0;try{let e=p.getState().documents.filter(e=>e.indexing_status===`indexing`||e.indexing_status===`pending`);for(let n of e)try{let e=await v(n.id);if(e.indexing_status!==`indexing`&&e.indexing_status!==`pending`){q.current.delete(n.id);let e=await _();t(e.documents||[]);break}}catch{}}finally{n=!1}}},2e3);return()=>clearInterval(r)},[J,t]),(0,O.useEffect)(()=>{let t=new Set(e.filter(e=>e.indexing_status===`indexing`||e.indexing_status===`pending`).map(e=>e.id));for(let e of q.current.keys())t.has(e)||q.current.delete(e)},[e]),(0,O.useEffect)(()=>{let e=setInterval(async()=>{try{let e=(await _()).documents||[],n=p.getState().documents;(e.length!==n.length||e.some((e,t)=>{let r=n.find(t=>t.id===e.id);return!r||r.indexing_status!==e.indexing_status||r.indexed_at!==e.indexed_at||r.chunk_count!==e.chunk_count}))&&(t(e),r.doc.debug(`Document list refreshed (server-side changes detected)`))}catch{}},15e3);return()=>clearInterval(e)},[t]);let le=e.reduce((e,t)=>e+t.file_size,0),Y=e.reduce((e,t)=>e+t.chunk_count,0),X=(0,O.useCallback)(async(e,n)=>{let i=e.includes(`.`)?`.`+e.split(`.`).pop()?.toLowerCase():``;if(i&&!c(i)){let t=re(i),n=t?t.message:`The file type "${i}" is not supported for indexing.`;r.doc.warn(`Unsupported file type: ${e} (${i})`),W({filename:e,error:n});return}r.doc.info(`Indexing document: ${e}`);let a=r.doc.time();R(!0),B(`Indexing ${e}...`),W(null);try{let i=await n();if(r.doc.timed(`Indexed "${e}": ${i?.chunk_count||`?`} chunks`,a),C&&i?.id)try{await m(C,i.id);let t=p.getState().sessions.find(e=>e.id===C)?.document_ids??[];t.includes(i.id)||E(C,{document_ids:[...t,i.id]}),r.doc.info(`Auto-attached "${e}" to session ${C}`)}catch(e){r.doc.warn(`Could not attach document to session: ${e}`)}else i?.id&&(M([i.id]),r.doc.info(`"${e}" will be attached to the next new chat`));let o=await _();t(o.documents||[]),B(``)}catch(t){r.doc.error(`Failed to index "${e}"`,t);let n=t instanceof Error?t.message:`Upload failed`;W({filename:e,error:n}),B(``)}finally{R(!1)}},[C,E,t,M]),Z=(0,O.useCallback)(async(e,t)=>{await X(t,()=>s(e))},[X]),Q=(0,O.useCallback)(async e=>{await X(e.name,()=>ee(e))},[X]),$=(0,O.useCallback)(async e=>{e.preventDefault(),I(!1);let t=Array.from(e.dataTransfer.files);r.doc.info(`Dropped ${t.length} file(s) into Document Library`);for(let e of t)await Q(e)},[Q]),ue=(0,O.useCallback)(async n=>{let i=e.find(e=>e.id===n);r.doc.info(`Deleting document: ${i?.filename||n}`);try{await ne(n),q.current.delete(n),N(n),t(e.filter(e=>e.id!==n)),r.doc.info(`Deleted document: ${i?.filename||n}`)}catch(e){r.doc.error(`Failed to delete document: ${i?.filename||n}`,e)}},[e,t,N]),de=(0,O.useCallback)(async(e,t)=>{r.doc.info(`Opening folder for: ${e}`);try{await x(e,!0)}catch(e){r.doc.error(`Failed to open folder for: ${t}`,e)}},[]),fe=(0,O.useCallback)(async n=>{let i=e.find(e=>e.id===n);r.doc.info(`Cancelling indexing for: ${i?.filename||n}`);try{await u(n),q.current.delete(n);let e=await _();t(e.documents||[]),r.doc.info(`Cancelled indexing for: ${i?.filename||n}`)}catch(e){r.doc.error(`Failed to cancel indexing: ${i?.filename||n}`,e)}},[e,t]),pe=(0,O.useCallback)(async n=>{if(G.has(n))return;let i=e.find(e=>e.id===n);r.doc.info(`Reindexing document: ${i?.filename||n}`),K(e=>new Set(e).add(n));try{await S(n),r.doc.info(`Reindex complete for: ${i?.filename||n}`)}catch(e){let t=e instanceof Error?e.message:String(e);r.doc.error(`Reindex failed for: ${i?.filename||n}`,e),W({filename:i?.filename||n,error:t})}finally{try{let e=await _();t(e.documents||[])}catch(e){r.doc.error(`Failed to refresh documents after reindex`,e)}K(e=>{let t=new Set(e);return t.delete(n),t})}},[e,t,G]),me=(0,O.useCallback)(async t=>{let n=e.find(e=>e.id===t);if(!C){M([t]),r.doc.info(`"${n?.filename||t}" will be attached to the next new chat`);return}r.doc.info(`Attaching document to session: ${n?.filename||t}`);try{await m(C,t);let e=p.getState().sessions.find(e=>e.id===C)?.document_ids??[];e.includes(t)||E(C,{document_ids:[...e,t]}),r.doc.info(`Attached "${n?.filename||t}" to session ${C}`)}catch(e){r.doc.error(`Failed to attach document to session: ${n?.filename||t}`,e)}},[C,e,E,M]),he=(0,O.useCallback)(async e=>{e.preventDefault(),V.trim()&&(r.doc.info(`Indexing from path input: ${V.trim()}`),await Z(V.trim(),V.trim().split(/[\\/]/).pop()||`file`),H(``))},[V,Z]),ge=e=>{let t=e.indexing_status||`complete`,n=q.current.get(e.id),r=e.indexed_at?A(e.indexed_at):``,i=e.indexed_at?j(e.indexed_at):``;switch(t){case`indexing`:case`pending`:return(0,k.jsxs)(`div`,{className:`doc-indexing-status`,children:[(0,k.jsxs)(`div`,{className:`doc-indexing-bar`,children:[(0,k.jsx)(`div`,{className:`doc-indexing-bar-track`,children:(0,k.jsx)(`div`,{className:`doc-indexing-bar-fill`})}),(0,k.jsxs)(`span`,{className:`doc-indexing-label`,children:[(0,k.jsx)(ae,{size:12,className:`doc-spin`}),`Indexing`,n?` (${se(n)})`:`...`]})]}),(0,k.jsxs)(`button`,{className:`btn-cancel`,onClick:t=>{t.stopPropagation(),fe(e.id)},title:`Cancel indexing`,"aria-label":`Cancel indexing ${e.filename}`,children:[(0,k.jsx)(w,{size:14}),`Cancel`]})]});case`failed`:return(0,k.jsxs)(`div`,{className:`doc-indexing-status`,children:[(0,k.jsxs)(`span`,{className:`doc-status-badge doc-status-failed`,title:e.last_error||void 0,"aria-label":e.last_error?`Failed: ${e.last_error}`:`Indexing failed`,children:[(0,k.jsx)(a,{size:12}),` Failed`]}),(0,k.jsxs)(`button`,{className:`btn-retry`,onClick:t=>{t.stopPropagation(),pe(e.id)},title:`Retry indexing`,"aria-label":`Retry indexing ${e.filename}`,disabled:G.has(e.id),children:[(0,k.jsx)(oe,{size:14}),G.has(e.id)?`Retrying…`:`Retry`]})]});case`cancelled`:return(0,k.jsxs)(`span`,{className:`doc-status-badge doc-status-cancelled`,children:[(0,k.jsx)(w,{size:12}),` Cancelled`]});case`missing`:return(0,k.jsxs)(`span`,{className:`doc-status-badge doc-status-missing`,children:[(0,k.jsx)(a,{size:12}),` File missing`]});default:return(0,k.jsxs)(`span`,{className:`doc-meta`,children:[b(e.file_size),` · `,e.chunk_count,` chunk`,e.chunk_count===1?``:`s`,r&&(0,k.jsxs)(`span`,{className:`doc-timestamp`,title:`Indexed: ${i}`,children:[(0,k.jsx)(g,{size:10}),r]})]})}};return(0,k.jsx)(`div`,{className:`modal-overlay`,onClick:()=>n(!1),role:`dialog`,"aria-modal":`true`,"aria-label":`Document Library`,children:(0,k.jsxs)(`div`,{className:`modal-panel doc-modal`,onClick:e=>e.stopPropagation(),children:[(0,k.jsxs)(`div`,{className:`modal-header`,children:[(0,k.jsx)(`h3`,{children:`Document Library`}),(0,k.jsx)(`button`,{className:`btn-icon`,onClick:()=>n(!1),"aria-label":`Close document library`,children:(0,k.jsx)(y,{size:18})})]}),(0,k.jsxs)(`div`,{className:`modal-body`,children:[(0,k.jsx)(`div`,{className:`drop-zone ${F?`drag-over`:``} ${L?`uploading`:``}`,onDragOver:e=>{e.preventDefault(),I(!0)},onDragLeave:()=>I(!1),onDrop:$,children:L?(0,k.jsxs)(k.Fragment,{children:[(0,k.jsx)(`div`,{className:`upload-spinner`}),(0,k.jsx)(`p`,{children:z})]}):(0,k.jsxs)(k.Fragment,{children:[(0,k.jsx)(f,{size:32,strokeWidth:1.5}),(0,k.jsx)(`p`,{children:`Drop files here to index`}),(0,k.jsx)(`span`,{className:`drop-hint`,children:`PDF, TXT, MD, code files, and 50+ formats`})]})}),(0,k.jsxs)(`form`,{className:`path-input-form`,onSubmit:he,children:[(0,k.jsx)(l,{size:16,className:`path-icon`}),(0,k.jsx)(`input`,{type:`text`,className:`path-input`,value:V,onChange:e=>H(e.target.value),placeholder:`Or enter file path: C:\\docs\\manual.pdf`,"aria-label":`File path to index`}),(0,k.jsx)(`button`,{type:`submit`,className:`btn-secondary`,disabled:!V.trim()||L,children:`Index`}),(0,k.jsxs)(`button`,{type:`button`,className:`btn-secondary`,onClick:()=>{n(!1),i(!0)},title:`Browse files on this computer`,children:[(0,k.jsx)(d,{size:14}),`Browse Files`]})]}),U&&(0,k.jsx)(o,{filename:U.filename,error:U.error,onDismiss:()=>W(null)}),e.length>0&&(0,k.jsxs)(`div`,{className:`doc-stats`,children:[(0,k.jsxs)(`span`,{children:[e.length,` document`,e.length===1?``:`s`]}),(0,k.jsx)(`span`,{children:`·`}),(0,k.jsxs)(`span`,{children:[Y,` chunk`,Y===1?``:`s`]}),(0,k.jsx)(`span`,{children:`·`}),(0,k.jsx)(`span`,{children:b(le)})]}),(0,k.jsxs)(`div`,{className:`doc-list`,children:[e.length===0&&!L&&(0,k.jsxs)(`div`,{className:`empty-docs`,children:[(0,k.jsx)(h,{size:32,strokeWidth:1}),(0,k.jsx)(`p`,{children:`No documents indexed yet`}),(0,k.jsx)(`span`,{children:`Drop files above or enter a file path`})]}),e.map(e=>(0,k.jsxs)(`div`,{className:`doc-row ${e.indexing_status===`indexing`?`doc-row-indexing`:``}`,children:[(0,k.jsxs)(`div`,{className:`doc-info`,children:[(0,k.jsx)(`span`,{className:`doc-name`,children:e.filename}),ge(e)]}),(0,k.jsxs)(`div`,{className:`doc-row-actions`,children:[e.filepath&&(0,k.jsx)(`button`,{className:`btn-icon-sm doc-open-folder`,onClick:()=>de(e.filepath,e.filename),title:`Open folder: ${e.filepath}`,"aria-label":`Open containing folder for ${e.filename}`,children:(0,k.jsx)(l,{size:14})}),e.indexing_status===`complete`&&!(C?P?.document_ids?.includes(e.id):D.includes(e.id))&&(0,k.jsx)(`button`,{className:`btn-icon-sm doc-attach`,onClick:()=>me(e.id),title:C?`Use in current session`:`Use in your next chat`,"aria-label":C?`Attach ${e.filename} to current session`:`Attach ${e.filename} to your next chat`,children:(0,k.jsx)(ie,{size:14})}),e.indexing_status!==`indexing`&&e.indexing_status!==`pending`&&(0,k.jsx)(`button`,{className:`btn-icon-sm doc-delete`,onClick:()=>ue(e.id),title:`Remove`,"aria-label":`Remove ${e.filename}`,children:(0,k.jsx)(te,{size:14})})]})]},e.id))]})]})]})})}export{M as DocumentLibrary};
@@ -1,4 +0,0 @@
1
- import{r as e}from"./rolldown-runtime-hePW80VL.js";import{a as t,o as n,r,t as i}from"./jsx-runtime-DVeaULmT.js";import{B as a,Ct as o,Dt as s,H as c,Ht as l,Kt as u,Lt as d,Nt as f,Ot as p,Ut as m,V as h,W as ee,Wt as g,bt as te,dt as _,en as ne,gt as v,in as re,jt as y,q as ie,rn as ae,t as oe}from"./index-D00FJoXi.js";var b={name:`code`,size:24,node:[[`path`,{d:`m16 18 6-6-6-6`,key:`eg8j8`}],[`path`,{d:`m8 6-6 6 6 6`,key:`ppft3o`}]]};b.node;var x=t(b),S={name:`eye`,size:24,node:[[`path`,{d:`M2.062 12.348a1 1 0 0 1 0-.696 10.75 10.75 0 0 1 19.876 0 1 1 0 0 1 0 .696 10.75 10.75 0 0 1-19.876 0`,key:`1nclc0`}],[`circle`,{cx:`12`,cy:`12`,r:`3`,key:`1v7zrd`}]]};S.node;var se=t(S),C={name:`folder`,size:24,node:[[`path`,{d:`M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z`,key:`1kt360`}]]};C.node;var w=t(C),T={name:`hard-drive`,size:24,node:[[`path`,{d:`M10 16h.01`,key:`1bzywj`}],[`path`,{d:`M2.212 11.577a2 2 0 0 0-.212.896V18a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-5.527a2 2 0 0 0-.212-.896L18.55 5.11A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11z`,key:`18tbho`}],[`path`,{d:`M21.946 12.013H2.054`,key:`zqlbp7`}],[`path`,{d:`M6 16h.01`,key:`1pmjb7`}]]};T.node;var ce=t(T),E={name:`house`,size:24,node:[[`path`,{d:`M15 21v-8a1 1 0 0 0-1-1h-4a1 1 0 0 0-1 1v8`,key:`5wwlr5`}],[`path`,{d:`M3 10a2 2 0 0 1 .709-1.528l7-6a2 2 0 0 1 2.582 0l7 6A2 2 0 0 1 21 10v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z`,key:`r6nss1`}]],aliases:[`home`]};E.node;var D=t(E),O={name:`monitor`,size:24,node:[[`rect`,{width:`20`,height:`14`,x:`2`,y:`3`,rx:`2`,key:`48i651`}],[`line`,{x1:`8`,x2:`16`,y1:`21`,y2:`21`,key:`1svkeh`}],[`line`,{x1:`12`,x2:`12`,y1:`17`,y2:`21`,key:`vw1qmm`}]]};O.node;var k=t(O),A={name:`table`,size:24,node:[[`path`,{d:`M12 3v18`,key:`108xh3`}],[`rect`,{width:`18`,height:`18`,x:`3`,y:`3`,rx:`2`,key:`afitv7`}],[`path`,{d:`M3 9h18`,key:`1pudct`}],[`path`,{d:`M3 15h18`,key:`5xshup`}]]};A.node;var j=t(A),M=e(n(),1),N=i();function le(e){if(e.type===`folder`)return(0,N.jsx)(w,{size:16});let t=(e.extension||``).toLowerCase();return[`.csv`,`.xlsx`,`.xls`,`.tsv`].includes(t)?(0,N.jsx)(j,{size:16}):[`.py`,`.js`,`.ts`,`.java`,`.c`,`.cpp`,`.go`,`.rs`].includes(t)?(0,N.jsx)(x,{size:16}):[`.pdf`,`.doc`,`.docx`,`.txt`,`.md`].includes(t)?(0,N.jsx)(g,{size:16}):(0,N.jsx)(m,{size:16})}function ue(e){if(!e)return``;let t=new Date(e),n=new Date,r=n.getTime()-t.getTime(),i=Math.floor(r/36e5);if(i<1)return`Just now`;if(i<24)return`${i}h ago`;let a=Math.floor(i/24);return a<7?`${a}d ago`:t.toLocaleDateString(void 0,{month:`short`,day:`numeric`,year:t.getFullYear()===n.getFullYear()?void 0:`numeric`})}function de(e){if(e.length===0)return``;let[t,...n]=e;return n.length>0?`${t} (+${n.length} more)`:t}function fe(e){switch(e){case`home`:return(0,N.jsx)(D,{size:14});case`desktop`:return(0,N.jsx)(k,{size:14});case`documents`:return(0,N.jsx)(g,{size:14});case`download`:return(0,N.jsx)(u,{size:14});default:return(0,N.jsx)(w,{size:14})}}var pe=[{label:`All Files`,value:``},{label:`Documents`,value:`pdf,doc,docx,txt,md`},{label:`Spreadsheets`,value:`csv,xlsx,xls,tsv`},{label:`Code`,value:`py,js,ts,java,c,cpp,go,rs,rb,sh`},{label:`Data`,value:`json,xml,yaml,yml,csv,tsv`}];async function P(e,t,n,i){let a=[],o=[];for(let t of e){let e=t.includes(`.`)?`.`+t.split(`.`).pop()?.toLowerCase():``;e&&!c(e)?o.push(t):a.push(t)}let l=[],u=[],d=0,f=``,m=new Set(t.filter(e=>e.type===`folder`).map(e=>e.path));for(let e of a)try{if(m.has(e)){let t=await _(e),n=[];t.documents.forEach(e=>{e.id&&n.push(e.id)}),n.length>0&&(n.forEach(e=>l.push(e)),u.push(e))}else{let t=await s(e);t?.id&&(l.push(t.id),u.push(e))}}catch(e){d++,f=e instanceof Error?e.message:`Unknown error`}if(n&&l.length>0){let e=[];for(let t of l)try{await ee(n,t),e.push(t)}catch(e){r.doc.warn(`Could not attach document to session: ${e}`)}let t=p.getState().sessions.find(e=>e.id===n)?.document_ids??[],a=e.filter(e=>!t.includes(e));a.length>0&&i(n,{document_ids:[...t,...a]})}else l.length>0&&p.getState().addDraftDocuments(l);if(l.length>0)try{let e=await v();p.getState().setDocuments(e.documents||[])}catch(e){r.doc.error(`Could not refresh the document list after indexing`,e)}return{docIds:l,supported:a,succeededFiles:u,unsupported:o,failed:d,lastError:f}}function F(){let{setShowFileBrowser:e,currentSessionId:t,updateSessionInList:n,setPendingPrompt:i}=p(),[s,u]=(0,M.useState)(``),[m,ee]=(0,M.useState)(null),[g,_]=(0,M.useState)([]),[v,b]=(0,M.useState)([]),[x,S]=(0,M.useState)(!1),[C,w]=(0,M.useState)(null),[T,E]=(0,M.useState)(``),[D,O]=(0,M.useState)(null),[k,A]=(0,M.useState)([]),[j,F]=(0,M.useState)(!1),[I,L]=(0,M.useState)(!1),[R,me]=(0,M.useState)(``),[z,B]=(0,M.useState)(new Set),[V,H]=(0,M.useState)(null),[he,U]=(0,M.useState)(!1),[W,G]=(0,M.useState)(new Set),[K,q]=(0,M.useState)(null),J=(0,M.useRef)(null),[Y,X]=(0,M.useState)(null),Z=(0,M.useCallback)(async e=>{S(!0),w(null),O(null),E(``),A([]);try{let t=await ie(e);u(t.current_path),ee(t.parent_path),_(t.entries),t.quick_links.length>0&&b(t.quick_links),r.ui.info(`Browsing: ${t.current_path} (${t.entries.length} items)`)}catch(e){let t=e instanceof Error?e.message:`Failed to load directory`;w(t),r.ui.error(`Browse failed`,e)}finally{S(!1)}},[]);(0,M.useEffect)(()=>{Z()},[Z]),(0,M.useEffect)(()=>()=>{J.current&&clearTimeout(J.current)},[]);let Q=(0,M.useCallback)(async()=>{if(!T.trim()){O(null),A([]);return}L(!0),w(null);try{let e=await o(T.trim(),R||void 0,30);O(e.results),A(e.searched_locations??[]),F(e.truncated===!0),r.ui.info(`Search "${T}": ${e.total} results`)}catch(e){let t=e instanceof Error?e.message:`Search failed`;w(t),r.ui.error(`Search failed`,e)}finally{L(!1)}},[T,R]),ge=e=>{e.key===`Enter`&&Q()},_e=(0,M.useCallback)(e=>{e.type===`folder`&&(Z(e.path),B(new Set),H(null))},[Z]),ve=(0,M.useCallback)(async e=>{U(!0);try{let t=await te(e);H(t)}catch(e){r.ui.error(`Preview failed`,e)}finally{U(!1)}},[]),ye=(0,M.useCallback)(e=>{B(t=>{let n=new Set(t);return n.has(e)?n.delete(e):n.add(e),n})},[]),be=(0,M.useCallback)(async()=>{if(z.size===0)return;let e=Array.from(z);if(X(null),!e.some(e=>{let t=e.includes(`.`)?`.`+e.split(`.`).pop()?.toLowerCase():``;return!t||c(t)})){let t=e[0],n=t.lastIndexOf(`.`),r=n>0?t.slice(n).toLowerCase():``,i=h(r);X({filename:e.length===1?t.split(/[\\/]/).pop()||t:`${e.length} files`,error:i?i.message:`File type "${r}" is not supported for indexing.`});return}G(new Set(e)),q(`Indexing ${e.length} file(s)...`);try{let r=await P(e,g,t,n);if(r.failed>0)q(`Done: ${r.docIds.length} indexed, ${r.failed} failed`),X({filename:`${r.failed} file(s)`,error:r.lastError||`Indexing failed for some files`});else{let e=r.unsupported.length>0?` (${r.unsupported.length} skipped — unsupported type)`:``;q(`Successfully indexed ${r.docIds.length} file(s)${e}`)}J.current&&clearTimeout(J.current),J.current=setTimeout(()=>q(null),5e3),B(new Set)}catch(t){r.doc.error(`Index selected failed`,t),X({filename:e.length===1?e[0].split(/[\\/]/).pop()||e[0]:`${e.length} files`,error:t instanceof Error?t.message:`An unexpected error occurred.`})}finally{G(new Set)}},[z,t,n,g]),xe=(0,M.useCallback)(async()=>{if(z.size===0)return;let a=Array.from(z);X(null),G(new Set(a)),q(`Indexing ${a.length} file(s) for analysis...`);try{let r=await P(a,g,t,n);if(r.supported.length===0){let e=a[0].lastIndexOf(`.`),t=e>0?a[0].slice(e).toLowerCase():``,n=h(t);X({filename:a.length===1?a[0].split(/[\\/]/).pop()||a[0]:`${a.length} files`,error:n?.message??`File type "${t}" is not supported for indexing.`});return}if(r.docIds.length===0){X({filename:r.supported.length===1?r.supported[0].split(/[\\/]/).pop()||r.supported[0]:`${r.supported.length} files`,error:`Failed to index selected file(s). Please try again.`});return}r.failed>0&&q(`Warning: ${r.failed} file(s) failed to index and will be excluded.`);let o=(r.succeededFiles.length>0?r.succeededFiles:r.supported).map(e=>e.split(/[\\/]/).pop()||e),s=o.length===1?`Please analyze this document for me: ${o[0]}`:`Please analyze these documents for me:\n${o.map(e=>`- ${e}`).join(`
2
- `)}`;i(s),e(!1),B(new Set)}catch(e){r.doc.error(`Ask Agent failed`,e),X({filename:a.length===1?a[0].split(/[\\/]/).pop()||a[0]:`${a.length} files`,error:e instanceof Error?e.message:`An unexpected error occurred.`})}finally{G(new Set),q(null)}},[z,t,n,g,i,e]),Se=s?s.replace(/\\/g,`/`).split(`/`).filter(Boolean):[],Ce=Se.map((e,t)=>({label:e,path:Se.slice(0,t+1).join(`/`)+(t===0&&e.includes(`:`)?`/`:``)})),we=de(k),$=D?D.map(e=>({name:e.name,path:e.path,type:`file`,size:e.size,extension:e.extension||``,modified:e.modified||``})):g;return(0,N.jsx)(`div`,{className:`modal-overlay`,onClick:()=>e(!1),role:`dialog`,"aria-modal":`true`,"aria-label":`File Browser`,children:(0,N.jsxs)(`div`,{className:`modal-panel file-browser-modal ${V?`has-preview`:``}`,onClick:e=>e.stopPropagation(),children:[(0,N.jsxs)(`div`,{className:`modal-header`,children:[(0,N.jsxs)(`h3`,{children:[(0,N.jsx)(l,{size:18}),` File Browser`]}),(0,N.jsx)(`button`,{className:`btn-icon`,onClick:()=>e(!1),"aria-label":`Close`,children:(0,N.jsx)(y,{size:18})})]}),(0,N.jsxs)(`div`,{className:`file-browser-body`,children:[(0,N.jsx)(`div`,{className:`fb-quick-links`,children:v.map(e=>(0,N.jsxs)(`button`,{className:`fb-quick-link`,onClick:()=>Z(e.path),title:e.path,children:[fe(e.icon),(0,N.jsx)(`span`,{children:e.name})]},e.path))}),(0,N.jsxs)(`div`,{className:`fb-search-bar`,children:[(0,N.jsxs)(`div`,{className:`fb-search-input-wrap`,children:[(0,N.jsx)(d,{size:14,className:`fb-search-icon`}),(0,N.jsx)(`input`,{type:`text`,className:`fb-search-input`,placeholder:`Search files on your PC...`,value:T,onChange:e=>E(e.target.value),onKeyDown:ge,"aria-label":`Search files`}),T&&(0,N.jsx)(`button`,{className:`fb-search-clear`,onClick:()=>{E(``),O(null),A([])},"aria-label":`Clear search`,children:(0,N.jsx)(y,{size:12})})]}),(0,N.jsx)(`select`,{className:`fb-type-filter`,value:R,onChange:e=>me(e.target.value),"aria-label":`File type filter`,children:pe.map(e=>(0,N.jsx)(`option`,{value:e.value,children:e.label},e.value))}),(0,N.jsx)(`button`,{className:`fb-search-btn`,onClick:Q,disabled:!T.trim()||I,children:I?`Searching...`:`Search`})]}),!D&&(0,N.jsxs)(`div`,{className:`fb-breadcrumb`,children:[(0,N.jsx)(`button`,{className:`fb-crumb`,onClick:()=>Z(`/`),children:(0,N.jsx)(ce,{size:12})}),Ce.map((e,t)=>(0,N.jsxs)(`span`,{className:`fb-crumb-item`,children:[(0,N.jsx)(ne,{size:12,className:`fb-crumb-sep`}),(0,N.jsx)(`button`,{className:`fb-crumb`,onClick:()=>Z(e.path),children:e.label})]},t)),m&&(0,N.jsx)(`button`,{className:`fb-up-btn`,onClick:()=>Z(m),title:`Go up`,children:(0,N.jsx)(re,{size:14})})]}),D&&(0,N.jsxs)(`div`,{className:`fb-search-header`,children:[(0,N.jsxs)(`div`,{className:`fb-search-summary`,children:[(0,N.jsxs)(`span`,{children:[`Found `,D.length,` result(s) for "`,T,`"`]}),we&&(0,N.jsxs)(`span`,{className:`fb-search-scope`,title:k.join(`
3
- `),children:[`Searching in: `,(0,N.jsx)(`code`,{children:we})]}),j&&(0,N.jsx)(`span`,{children:`Search stopped early, so some matches may be missing. Try a more specific name.`})]}),(0,N.jsx)(`button`,{className:`fb-back-btn`,onClick:()=>{O(null),E(``),A([])},children:`Back to browsing`})]}),C&&(0,N.jsx)(`div`,{className:`fb-error`,children:C}),(0,N.jsxs)(`div`,{className:`fb-content`,children:[(0,N.jsxs)(`div`,{className:`fb-file-list`,children:[x&&(0,N.jsx)(`div`,{className:`fb-loading`,children:`Loading...`}),!x&&$.length===0&&(0,N.jsx)(`div`,{className:`fb-empty`,children:D?`No files found`:`This folder is empty`}),!x&&$.map(e=>{let t=e.extension||(e.name.includes(`.`)?`.`+e.name.split(`.`).pop()?.toLowerCase():``),n=e.type===`file`&&t&&!c(t),r=n?h(t):null;return(0,N.jsxs)(`div`,{className:`fb-entry ${e.type} ${z.has(e.path)?`selected`:``} ${n?`unsupported`:``}`,onClick:()=>e.type===`folder`?_e(e):ye(e.path),onDoubleClick:()=>e.type===`folder`?_e(e):void 0,title:n?`${r?.label||`This`} file type cannot be indexed`:e.path,children:[(0,N.jsx)(`input`,{type:`checkbox`,className:`fb-entry-checkbox`,checked:z.has(e.path),onChange:()=>ye(e.path),onClick:e=>e.stopPropagation(),"aria-label":`Select ${e.name}`}),(0,N.jsx)(`span`,{className:`fb-entry-icon`,children:le(e)}),(0,N.jsx)(`span`,{className:`fb-entry-name`,title:e.path,children:e.name}),n&&(0,N.jsx)(`span`,{className:`fb-unsupported-badge`,children:`Not indexable`}),e.type===`file`&&(0,N.jsx)(`button`,{type:`button`,className:`fb-entry-preview-btn`,onClick:t=>{t.stopPropagation(),ve(e.path)},"aria-label":`Preview ${e.name}`,title:`Preview file`,children:(0,N.jsx)(se,{size:14})}),(0,N.jsx)(`span`,{className:`fb-entry-size`,children:e.type===`file`?oe(e.size):``}),(0,N.jsx)(`span`,{className:`fb-entry-date`,children:ue(e.modified)})]},e.path)})]}),V&&(0,N.jsxs)(`div`,{className:`fb-preview`,children:[(0,N.jsxs)(`div`,{className:`fb-preview-header`,children:[(0,N.jsx)(`span`,{className:`fb-preview-name`,children:V.name}),(0,N.jsx)(`button`,{className:`btn-icon-sm`,onClick:()=>H(null),"aria-label":`Close preview`,children:(0,N.jsx)(y,{size:14})})]}),(0,N.jsxs)(`div`,{className:`fb-preview-meta`,children:[(0,N.jsx)(`span`,{children:V.size_display}),V.total_lines&&(0,N.jsxs)(`span`,{children:[V.total_lines,` lines`]}),V.columns&&(0,N.jsxs)(`span`,{children:[V.columns.length,` columns`]}),V.row_count!==null&&(0,N.jsxs)(`span`,{children:[V.row_count,` rows`]})]}),V.columns&&(0,N.jsxs)(`div`,{className:`fb-preview-columns`,children:[(0,N.jsx)(`strong`,{children:`Columns:`}),` `,V.columns.join(`, `)]}),he?(0,N.jsx)(`div`,{className:`fb-preview-loading`,children:`Loading preview...`}):V.is_text&&V.preview_lines.length>0?(0,N.jsx)(`pre`,{className:`fb-preview-content`,children:V.preview_lines.slice(0,30).join(`
4
- `)}):(0,N.jsx)(`div`,{className:`fb-preview-binary`,children:`Binary file - no preview available`})]})]}),Y&&(0,N.jsx)(a,{filename:Y.filename,error:Y.error,onDismiss:()=>X(null)}),(0,N.jsxs)(`div`,{className:`fb-actions`,children:[(0,N.jsx)(`div`,{className:`fb-selection-info`,children:z.size>0?`${z.size} item(s) selected`:`Select files to index or analyze`}),K&&(0,N.jsx)(`span`,{className:`fb-index-status`,children:K}),(0,N.jsxs)(`div`,{className:`fb-action-btns`,children:[(0,N.jsxs)(`button`,{className:`fb-action-btn secondary`,onClick:be,disabled:z.size===0||W.size>0,title:`Index selected files for RAG search`,children:[(0,N.jsx)(f,{size:14}),`Index Selected`]}),(0,N.jsxs)(`button`,{className:`fb-action-btn primary`,onClick:xe,disabled:z.size===0||W.size>0,title:`Index and send selected files to the chat agent for analysis`,children:[(0,N.jsx)(ae,{size:14}),`Ask Agent`]})]})]})]})]})})}export{F as FileBrowser};
@@ -1 +0,0 @@
1
- .memory-dashboard-page{background:var(--bg-primary);flex-direction:column;height:100%;display:flex;overflow:hidden}.memory-dashboard-header{border-bottom:1px solid var(--border-light);flex-shrink:0;justify-content:space-between;align-items:center;padding:16px 24px;display:flex}.memory-dashboard-header-left{align-items:center;gap:12px;display:flex}.memory-dashboard-header h1{font-size:15px;font-weight:600;font-family:var(--font-sans);color:var(--text-primary)}.memory-dashboard-header-actions{align-items:center;gap:6px;display:flex}.memory-dashboard-body{scrollbar-width:thin;scrollbar-color:var(--border) transparent;flex:1;padding:24px;overflow-y:auto;container-type:inline-size}.memory-dashboard-body::-webkit-scrollbar{width:5px}.memory-dashboard-body::-webkit-scrollbar-track{background:0 0}.memory-dashboard-body::-webkit-scrollbar-thumb{background:var(--border);border-radius:var(--radius-full)}.mem-section{margin-bottom:28px}.mem-section:last-child{margin-bottom:0}.mem-section-title{font-size:11px;font-weight:600;font-family:var(--font-mono);text-transform:uppercase;letter-spacing:2px;color:var(--text-muted);align-items:center;gap:8px;margin-bottom:14px;display:flex}.mem-section-title-row{justify-content:space-between}.mem-section-title-left{align-items:center;gap:8px;display:flex}.mem-section-note{letter-spacing:.5px;text-transform:none;opacity:.8;margin-left:8px;font-weight:400}.mem-section-count{background:var(--bg-tertiary);border:1px solid var(--border);border-radius:var(--radius-full);min-width:20px;height:18px;color:var(--text-muted);letter-spacing:0;font-size:10px;font-weight:700;font-family:var(--font-mono);justify-content:center;align-items:center;padding:0 6px;display:inline-flex}.mem-section-add-btn{font-size:11px;font-weight:600;font-family:var(--font-mono);text-transform:uppercase;letter-spacing:.5px;border-radius:var(--radius-md);border:1px solid var(--border);background:var(--bg-secondary);color:var(--text-secondary);cursor:pointer;transition:all var(--duration) var(--ease);align-items:center;gap:5px;padding:4px 10px;display:inline-flex}.mem-section-add-btn:hover{border-color:var(--accent);color:var(--accent);background:var(--accent-dim)}.mem-range-tabs{border:1px solid var(--border);border-radius:var(--radius-md);display:flex;overflow:hidden}.mem-range-tab{font-size:10px;font-weight:700;font-family:var(--font-mono);letter-spacing:.5px;color:var(--text-muted);cursor:pointer;transition:all var(--duration) var(--ease);background:0 0;border:none;padding:3px 10px}.mem-range-tab+.mem-range-tab{border-left:1px solid var(--border)}.mem-range-tab:hover{color:var(--text-primary);background:var(--bg-hover)}.mem-range-tab.active{background:var(--accent-fill);color:var(--accent-fill-text)}.mem-disabled-banner{background:color-mix(in srgb, var(--accent) 8%, transparent);border:1px solid color-mix(in srgb, var(--accent) 25%, transparent);border-radius:var(--radius-md);color:var(--accent);font-size:12px;font-family:var(--font-sans);align-items:center;gap:10px;margin-bottom:20px;padding:10px 16px;display:flex}.mem-disabled-banner svg{flex-shrink:0}.mem-disabled-banner span{flex:1}.mem-disabled-banner-action{font-size:11px;font-weight:600;font-family:var(--font-mono);text-transform:uppercase;letter-spacing:.5px;border-radius:var(--radius-md);border:1px solid color-mix(in srgb, var(--accent) 40%, transparent);color:var(--accent);cursor:pointer;transition:all var(--duration) var(--ease);background:0 0;flex-shrink:0;padding:4px 12px}.mem-disabled-banner-action:hover{background:color-mix(in srgb, var(--accent) 15%, transparent);border-color:var(--accent)}.mem-stat-cards{grid-template-columns:repeat(4,minmax(0,1fr));gap:14px;margin-bottom:28px;display:grid}.mem-stat-card{background:var(--bg-secondary);border:1px solid var(--border-light);border-radius:var(--radius-lg);transition:border-color var(--duration) var(--ease), transform var(--duration) var(--ease);padding:18px 20px}.mem-stat-card:hover{border-color:var(--border);transform:translateY(-1px)}.mem-stat-value{font-size:28px;font-weight:700;font-family:var(--font-display);color:var(--text-primary);line-height:1.1}.mem-stat-label{color:var(--text-secondary);font-size:12px;font-weight:500;font-family:var(--font-sans);margin-top:4px}.mem-stat-sub{color:var(--text-muted);font-size:11px;font-family:var(--font-mono);margin-top:2px}.mem-stat-card[data-accent=purple] .mem-stat-value{color:var(--accent-purple)}.mem-stat-card[data-accent=blue] .mem-stat-value{color:var(--accent-blue)}.mem-stat-card[data-accent=green] .mem-stat-value{color:var(--accent-green)}.mem-stat-card[data-accent=red] .mem-stat-value{color:var(--accent)}.mem-stat-card[data-accent=gold] .mem-stat-value{color:var(--accent-yellow)}.mem-activity-chart{background:var(--bg-secondary);border:1px solid var(--border-light);border-radius:var(--radius-lg);align-items:flex-end;gap:2px;height:120px;padding:14px 10px 28px;display:flex;position:relative;overflow:hidden}.mem-activity-bar-group{cursor:default;flex-direction:column;flex:1;justify-content:flex-end;align-items:center;gap:1px;height:100%;display:flex;position:relative}.mem-activity-bar{width:100%;min-height:0;transition:opacity var(--duration-fast) var(--ease);border-radius:2px 2px 0 0}.mem-activity-bar.conversations{background:var(--accent-blue);opacity:.85}.mem-activity-bar.tool_calls{background:var(--accent-green);opacity:.85}.mem-activity-bar.knowledge{background:var(--accent-purple);opacity:.85}.mem-activity-bar.errors{background:var(--danger);opacity:.85}.mem-activity-bar-group:hover .mem-activity-bar{opacity:1}.mem-activity-date-label{color:var(--text-muted);font-size:9px;font-family:var(--font-mono);white-space:nowrap;position:absolute;bottom:-22px}.mem-activity-legend{font-size:11px;font-family:var(--font-mono);color:var(--text-secondary);gap:16px;margin-top:10px;display:flex}.mem-activity-legend-item{align-items:center;gap:5px;display:flex}.mem-activity-legend-dot{border-radius:2px;width:8px;height:8px}.mem-activity-legend-dot.conversations{background:var(--accent-blue)}.mem-activity-legend-dot.tool_calls{background:var(--accent-green)}.mem-activity-legend-dot.knowledge{background:var(--accent-purple)}.mem-activity-legend-dot.errors{background:var(--danger)}.mem-activity-tooltip{background:var(--bg-tertiary);border:1px solid var(--border);border-radius:var(--radius-sm);font-size:11px;font-family:var(--font-mono);color:var(--text-primary);white-space:nowrap;pointer-events:none;z-index:10;box-shadow:var(--shadow-md);padding:6px 10px;position:absolute;bottom:calc(100% + 8px);left:50%;transform:translate(-50%)}.mem-filters{flex-wrap:wrap;align-items:center;gap:8px;margin-bottom:12px;display:flex}.mem-filter-select{font-size:12px;font-family:var(--font-mono);border:1px solid var(--border);border-radius:var(--radius-md);background:var(--bg-input);color:var(--text-primary);cursor:pointer;transition:border-color var(--duration) var(--ease);appearance:none;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%239898b0' stroke-width='2'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");background-position:right 8px center;background-repeat:no-repeat;outline:none;padding:7px 28px 7px 12px}.mem-filter-select:focus{border-color:var(--accent)}.mem-category-pills{flex-wrap:wrap;align-items:center;gap:5px;display:flex}.mem-category-pill{font-size:11px;font-weight:600;font-family:var(--font-mono);text-transform:uppercase;letter-spacing:.5px;border-radius:var(--radius-full);border:1px solid var(--border);color:var(--text-muted);cursor:pointer;transition:all var(--duration) var(--ease);white-space:nowrap;background:0 0;padding:4px 11px;line-height:1.4}.mem-category-pill:hover{border-color:var(--text-secondary);color:var(--text-primary);background:var(--bg-hover)}.mem-category-pill:focus-visible{outline:2px solid var(--accent);outline-offset:1px}.mem-category-pill.fact.active{background:color-mix(in srgb, var(--accent-blue) 12%, transparent);border-color:var(--accent-blue);color:var(--accent-blue)}.mem-category-pill.preference.active{background:color-mix(in srgb, var(--accent-purple) 12%, transparent);border-color:var(--accent-purple);color:var(--accent-purple)}.mem-category-pill.error.active{background:var(--danger-dim);border-color:var(--danger);color:var(--danger)}.mem-category-pill.skill.active{background:var(--accent-green-dim);border-color:var(--accent-green);color:var(--accent-green)}.mem-category-pill.note.active{background:color-mix(in srgb, var(--accent-yellow) 12%, transparent);border-color:var(--accent-yellow);color:var(--accent-yellow)}.mem-category-pill.reminder.active{background:color-mix(in srgb, var(--accent) 10%, transparent);border-color:var(--accent);color:var(--accent)}.mem-category-pill.clear{border-style:dashed}.mem-category-pill.clear:hover{border-color:var(--danger);color:var(--danger);background:var(--danger-dim);border-style:solid}.mem-filter-search{box-sizing:border-box;width:100%;min-width:180px;font-size:12px;font-family:var(--font-mono);border:1px solid var(--border);border-radius:var(--radius-md);background:var(--bg-input);color:var(--text-primary);transition:border-color var(--duration) var(--ease);outline:none;flex:1;padding:7px 12px 7px 32px}.mem-filter-search:focus{border-color:var(--accent)}.mem-filter-search::placeholder{color:var(--text-muted)}.mem-filter-search-wrap{flex:1;min-width:180px;position:relative}.mem-filter-search-wrap .search-icon{color:var(--text-muted);pointer-events:none;position:absolute;top:50%;left:10px;transform:translateY(-50%)}.mem-knowledge-table{border-collapse:separate;border-spacing:0;width:100%;font-size:13px}.mem-knowledge-table th{text-align:left;font-size:10px;font-weight:600;font-family:var(--font-mono);text-transform:uppercase;letter-spacing:1.5px;color:var(--text-muted);border-bottom:1px solid var(--border);white-space:nowrap;cursor:pointer;-webkit-user-select:none;user-select:none;transition:color var(--duration) var(--ease);padding:8px 12px}.mem-knowledge-table th:hover{color:var(--text-primary)}.mem-knowledge-table th.sorted{color:var(--accent)}.mem-sort-arrow{margin-left:4px;font-size:10px}.mem-knowledge-table td{border-bottom:1px solid var(--border-light);vertical-align:top;font-family:var(--font-sans);padding:10px 12px}.mem-knowledge-table tbody tr{transition:background var(--duration-fast) var(--ease)}.mem-knowledge-table tbody tr:hover{background:var(--tint-subtle)}.mem-cat-badge{font-size:10px;font-weight:600;font-family:var(--font-mono);text-transform:uppercase;letter-spacing:.5px;border-radius:var(--radius-full);white-space:nowrap;padding:2px 8px;display:inline-block}.mem-cat-badge.fact{background:color-mix(in srgb, var(--accent-blue) 12%, transparent);color:var(--accent-blue)}.mem-cat-badge.preference{background:color-mix(in srgb, var(--accent-purple) 12%, transparent);color:var(--accent-purple)}.mem-cat-badge.error{background:var(--danger-dim);color:var(--danger)}.mem-cat-badge.skill{background:var(--accent-green-dim);color:var(--accent-green)}.mem-confidence{font-family:var(--font-mono);color:var(--text-secondary);align-items:center;gap:6px;font-size:12px;display:flex}.mem-confidence-bar{background:var(--border);border-radius:var(--radius-full);width:48px;height:4px;overflow:hidden}.mem-confidence-fill{border-radius:var(--radius-full);height:100%;transition:width .3s var(--ease)}.mem-confidence-fill.high{background:var(--accent-green)}.mem-confidence-fill.medium{background:var(--accent-yellow)}.mem-confidence-fill.low{background:var(--text-muted)}.mem-content-cell{text-overflow:ellipsis;white-space:nowrap;max-width:320px;overflow:hidden}.mem-sensitive-blur{filter:blur(4px);cursor:pointer;transition:filter var(--duration) var(--ease);-webkit-user-select:none;user-select:none}.mem-sensitive-blur:hover,.mem-sensitive-blur.revealed{filter:none}.mem-sensitive-badge{align-items:center;gap:3px;margin-right:4px;font-size:11px;display:inline-flex}.mem-entity-link{color:var(--accent-blue);cursor:pointer;font-size:11px;font-family:var(--font-mono);align-items:center;gap:3px;display:inline-flex}.mem-entity-link:hover{text-decoration:underline}.mem-due-badge{font-size:11px;font-family:var(--font-mono);white-space:nowrap}.mem-due-badge.overdue{color:var(--danger)}.mem-due-badge.upcoming{color:var(--accent-yellow)}.mem-due-badge.none{color:var(--text-muted)}.mem-date-cell{font-size:12px;font-family:var(--font-mono);color:var(--text-secondary);white-space:nowrap}.mem-row-actions{opacity:0;transition:opacity var(--duration-fast) var(--ease);gap:2px;display:flex}.mem-knowledge-table tbody tr:hover .mem-row-actions,.mem-knowledge-table tbody tr:focus-within .mem-row-actions{opacity:1}.mem-row-actions:has(.is-confirm){opacity:1}.mem-knowledge-table .mem-actions-cell{background:var(--bg-primary);position:sticky;right:0;box-shadow:-8px 0 8px -8px #00000059}.mem-knowledge-table tbody tr:hover .mem-actions-cell,.mem-knowledge-table .mem-expanded-row .mem-actions-cell{background:color-mix(in srgb, var(--text-primary) 3%, var(--bg-primary))}.mem-row-action-btn{border-radius:var(--radius-sm);width:26px;height:26px;color:var(--text-muted);transition:all var(--duration-fast) var(--ease);justify-content:center;align-items:center;display:flex}.mem-row-action-btn:hover{background:var(--bg-hover);color:var(--text-primary)}.mem-row-action-btn.delete:hover,.mem-row-action-btn.delete.is-confirm{color:var(--danger)}.mem-row-action-btn.is-confirm{width:auto;padding:0 6px}.mem-row-delete-label{font-size:11px;font-weight:600}.mem-pagination{font-size:12px;font-family:var(--font-mono);color:var(--text-muted);justify-content:space-between;align-items:center;margin-top:12px;display:flex}.mem-pagination-btns{gap:4px;display:flex}.mem-page-btn{border:1px solid var(--border);border-radius:var(--radius-sm);font-size:12px;font-family:var(--font-mono);color:var(--text-secondary);transition:all var(--duration) var(--ease);padding:4px 12px}.mem-page-btn:hover:not(:disabled){border-color:var(--accent);color:var(--accent)}.mem-page-btn:disabled{opacity:.3;cursor:not-allowed}.mem-add-btn{border:1px dashed var(--border);border-radius:var(--radius-md);font-size:12px;font-family:var(--font-mono);color:var(--text-secondary);transition:all var(--duration) var(--ease);align-items:center;gap:6px;margin-top:8px;padding:7px 16px;display:inline-flex}.mem-add-btn:hover{border-color:var(--accent);color:var(--accent);border-style:solid}.mem-tool-table{border-collapse:separate;border-spacing:0;width:100%;font-size:13px}.mem-tool-table th{text-align:left;font-size:10px;font-weight:600;font-family:var(--font-mono);text-transform:uppercase;letter-spacing:1.5px;color:var(--text-muted);border-bottom:1px solid var(--border);white-space:nowrap;padding:8px 12px}.mem-tool-table td{border-bottom:1px solid var(--border-light);font-family:var(--font-mono);padding:10px 12px;font-size:12px}.mem-tool-table tbody tr{transition:background var(--duration-fast) var(--ease);cursor:default}.mem-tool-table tbody tr:hover{background:var(--tint-subtle)}.mem-tool-name{color:var(--text-primary);font-weight:500}.mem-success-rate{font-weight:600}.mem-success-rate.high{color:var(--accent-green)}.mem-success-rate.medium{color:var(--accent-yellow)}.mem-success-rate.low{color:var(--danger)}.mem-tool-error{vertical-align:top;text-overflow:ellipsis;white-space:nowrap;max-width:260px;color:var(--text-muted);font-size:11px;display:inline-block;overflow:hidden}.mem-conv-search{margin-bottom:12px;position:relative}.mem-conv-search .search-icon{color:var(--text-muted);pointer-events:none;position:absolute;top:50%;left:10px;transform:translateY(-50%)}.mem-conv-search input{width:100%;font-size:12px;font-family:var(--font-mono);border:1px solid var(--border);border-radius:var(--radius-md);background:var(--bg-input);color:var(--text-primary);transition:border-color var(--duration) var(--ease);outline:none;padding:8px 12px 8px 32px}.mem-conv-search input:focus{border-color:var(--accent)}.mem-conv-search input{padding-right:32px}.mem-search-clear{border-radius:var(--radius-full);background:var(--bg-tertiary);width:20px;height:20px;color:var(--text-muted);cursor:pointer;transition:all var(--duration) var(--ease);border:none;justify-content:center;align-items:center;display:flex;position:absolute;top:50%;right:8px;transform:translateY(-50%)}.mem-search-clear:hover{background:var(--border);color:var(--text-primary)}.mem-delete-confirm{flex-wrap:wrap;align-items:center;gap:8px;display:flex}.mem-delete-confirm-label{color:var(--danger);font-size:12px;font-weight:600;font-family:var(--font-mono);white-space:nowrap}.mem-conv-list{flex-direction:column;gap:4px;display:flex}.mem-conv-item{border:1px solid var(--border-light);border-radius:var(--radius-md);transition:border-color var(--duration) var(--ease), background var(--duration) var(--ease);cursor:pointer;justify-content:space-between;align-items:center;padding:10px 14px;display:flex}.mem-conv-item:hover{border-color:var(--border);background:var(--tint-subtle)}.mem-conv-info{flex:1;min-width:0}.mem-conv-session-id{font-size:12px;font-family:var(--font-mono);color:var(--text-primary);text-overflow:ellipsis;white-space:nowrap;font-weight:500;overflow:hidden}.mem-conv-preview{color:var(--text-muted);text-overflow:ellipsis;white-space:nowrap;margin-top:2px;font-size:12px;overflow:hidden}.mem-conv-meta{font-size:11px;font-family:var(--font-mono);color:var(--text-muted);flex-shrink:0;gap:12px;margin-left:12px;display:flex}.mem-conv-detail-overlay{background:var(--bg-card);z-index:5;border-radius:var(--radius-xl);flex-direction:column;display:flex;position:absolute;inset:0}.mem-conv-detail-header{border-bottom:1px solid var(--border);flex-shrink:0;justify-content:space-between;align-items:center;padding:14px 20px;display:flex}.mem-conv-detail-header h2{font-size:12px;font-family:var(--font-mono);color:var(--text-secondary)}.mem-conv-detail-body{flex:1;padding:16px 20px;overflow-y:auto}.mem-conv-turn{border-bottom:1px solid var(--border-light);padding:8px 0}.mem-conv-turn:last-child{border-bottom:none}.mem-conv-turn-header{justify-content:space-between;align-items:center;margin-bottom:4px;display:flex}.mem-conv-turn-time{color:var(--text-muted);font-size:10px;font-family:var(--font-mono);flex-shrink:0}.mem-conv-turn-role{font-size:10px;font-weight:600;font-family:var(--font-mono);text-transform:uppercase;letter-spacing:1px;margin-bottom:4px}.mem-conv-turn-role.user{color:var(--accent-blue)}.mem-conv-turn-role.assistant{color:var(--accent-green)}.mem-conv-turn-content{color:var(--text-primary);white-space:pre-wrap;word-break:break-word;font-size:13px;line-height:1.6}.mem-temporal-list{flex-direction:column;gap:6px;display:flex}.mem-temporal-item{border:1px solid var(--border-light);border-radius:var(--radius-md);transition:border-color var(--duration) var(--ease);align-items:flex-start;gap:10px;padding:10px 14px;font-size:13px;display:flex}.mem-temporal-item:hover{border-color:var(--border)}.mem-temporal-item.overdue{border-left:3px solid var(--danger)}.mem-temporal-item.upcoming{border-left:3px solid var(--accent-yellow)}.mem-temporal-icon{flex-shrink:0;margin-top:1px;font-size:16px;line-height:1}.mem-temporal-content{flex:1;min-width:0}.mem-temporal-text{font-family:var(--font-sans);color:var(--text-primary)}.mem-temporal-date{font-size:11px;font-family:var(--font-mono);color:var(--text-muted);margin-top:2px}.mem-two-col{grid-template-columns:repeat(2,minmax(0,1fr));gap:24px;display:grid}.mem-two-col>*{min-width:0}@container (width<=860px){.mem-two-col{grid-template-columns:minmax(0,1fr)}}@container (width<=640px){.mem-stat-cards{grid-template-columns:repeat(2,minmax(0,1fr))}}.mem-empty{text-align:center;color:var(--text-muted);font-size:13px;font-family:var(--font-sans);padding:32px 20px}.mem-empty-icon{opacity:.4;margin-bottom:8px;font-size:32px}.mem-loading{color:var(--text-muted);font-size:13px;font-family:var(--font-mono);justify-content:center;align-items:center;gap:10px;padding:40px;display:flex}.mem-spinner{border:2px solid var(--border);border-top-color:var(--accent);border-radius:50%;width:18px;height:18px;animation:.8s linear infinite spin}.mem-inline-form{background:var(--bg-secondary);border:1px solid var(--border);border-radius:var(--radius-lg);flex-direction:column;gap:10px;margin-bottom:12px;padding:16px;display:flex}.mem-inline-form-row{align-items:center;gap:8px;display:flex}.mem-inline-form-row label{font-size:11px;font-weight:600;font-family:var(--font-mono);text-transform:uppercase;letter-spacing:1px;color:var(--text-muted);flex-shrink:0;width:80px}.mem-inline-form-row input,.mem-inline-form-row select,.mem-inline-form-row textarea{font-size:12px;font-family:var(--font-mono);border:1px solid var(--border);border-radius:var(--radius-md);background:var(--bg-input);color:var(--text-primary);transition:border-color var(--duration) var(--ease);outline:none;flex:1;padding:7px 12px}.mem-inline-form-row input:focus,.mem-inline-form-row select:focus,.mem-inline-form-row textarea:focus{border-color:var(--accent)}.mem-inline-form-row textarea{resize:vertical;min-height:60px}.mem-inline-form-actions{justify-content:flex-end;gap:8px;display:flex}.mem-expanded-row{background:var(--tint-subtle)!important}.mem-detail-row td{border-bottom:1px solid var(--border)!important;padding:0!important}.mem-detail-panel{background:var(--bg-secondary);border-top:1px solid var(--border-light);animation:detailExpand .2s var(--ease);padding:14px 20px 16px}@keyframes detailExpand{0%{opacity:0;max-height:0}to{opacity:1;max-height:500px}}.mem-detail-grid{grid-template-columns:repeat(4,1fr);gap:10px 20px;margin-bottom:10px;display:grid}.mem-detail-field{flex-direction:column;gap:2px;display:flex}.mem-detail-field.mem-detail-full{grid-column:1/-1}.mem-detail-label{font-size:10px;font-weight:600;font-family:var(--font-mono);text-transform:uppercase;letter-spacing:1px;color:var(--text-muted)}.mem-detail-value{font-size:12px;font-family:var(--font-mono);color:var(--text-primary);word-break:break-all}.mem-detail-chain{color:var(--accent-blue)}.mem-detail-content-full{border-top:1px solid var(--border-light);margin-top:8px;padding-top:8px}.mem-detail-content-text{font-size:13px;font-family:var(--font-sans);color:var(--text-primary);white-space:pre-wrap;word-break:break-word;max-height:200px;margin-top:4px;line-height:1.6;overflow-y:auto}.mem-embedding-coverage{align-items:center;gap:8px;padding:0 8px;display:flex}.mem-embedding-bar{background:var(--border);border-radius:var(--radius-full);width:60px;height:5px;overflow:hidden}.mem-embedding-fill{background:var(--accent-green);border-radius:var(--radius-full);height:100%;transition:width .4s var(--ease)}.mem-embedding-label{font-size:11px;font-family:var(--font-mono);color:var(--text-secondary);white-space:nowrap}.mem-maintenance-wrap{position:relative}.mem-maintenance-wrap .btn-icon{align-items:center;gap:0;display:flex}.mem-maintenance-menu{background:var(--bg-card);border:1px solid var(--border);border-radius:var(--radius-lg);min-width:220px;box-shadow:var(--shadow-lg);z-index:20;animation:modalPanelIn .15s var(--ease);padding:4px;position:absolute;top:calc(100% + 6px);right:0}.mem-maintenance-item{width:100%;font-size:12px;font-family:var(--font-mono);color:var(--text-primary);border-radius:var(--radius-md);transition:background var(--duration-fast) var(--ease);text-align:left;align-items:center;gap:10px;padding:9px 14px;display:flex}.mem-maintenance-item:hover:not(:disabled){background:var(--tint-subtle)}.mem-maintenance-item:disabled{opacity:.5;cursor:not-allowed}.mem-maintenance-divider{background:var(--border-light);height:1px;margin:4px 8px}.mem-spinner-sm{border:2px solid var(--border);border-top-color:var(--accent);border-radius:50%;width:14px;height:14px;animation:.8s linear infinite spin}.mem-embed-dot{vertical-align:middle;align-items:center;margin-right:5px;display:inline-flex}.mem-embed-dot.embedded{color:var(--accent-green)}.mem-embed-dot.missing{color:var(--danger);opacity:.6}.mem-superseded-row{opacity:.55}.mem-superseded-text{color:var(--text-muted);text-decoration:line-through}.mem-filter-toggle{font-size:11px;font-family:var(--font-mono);color:var(--text-secondary);cursor:pointer;white-space:nowrap;border:1px solid var(--border);border-radius:var(--radius-md);transition:border-color var(--duration) var(--ease);align-items:center;gap:5px;padding:7px 10px;display:flex}.mem-filter-toggle:hover{border-color:var(--border)}.mem-filter-toggle input{cursor:pointer;margin:0}.mem-consolidated-badge{color:var(--accent-green);opacity:.7;vertical-align:middle;align-items:center;margin-left:6px;display:inline-flex}.mem-cat-badge.note{background:color-mix(in srgb, var(--accent-yellow) 12%, transparent);color:var(--accent-yellow)}.mem-cat-badge.reminder{background:color-mix(in srgb, var(--danger) 12%, transparent);color:var(--danger)}.mem-toast-container{z-index:200;pointer-events:none;flex-direction:column;gap:8px;display:flex;position:fixed;bottom:24px;right:24px}.mem-toast{background:var(--bg-card);border:1px solid var(--border);border-radius:var(--radius-lg);box-shadow:var(--shadow-lg);font-size:12px;font-family:var(--font-mono);color:var(--text-primary);animation:toastIn .25s var(--ease);pointer-events:auto;align-items:center;gap:8px;padding:10px 18px;display:flex}.mem-toast-success{border-left:3px solid var(--accent-green)}.mem-toast-error{border-left:3px solid var(--danger)}.mem-toast-info{border-left:3px solid var(--accent-blue)}@keyframes toastIn{0%{opacity:0;transform:translateY(10px)scale(.96)}to{opacity:1;transform:none}}.mem-settings-row{justify-content:space-between;align-items:center;gap:16px;padding:10px 0;display:flex}.mem-settings-label{color:var(--text-primary);flex-direction:column;gap:3px;font-size:13px;display:flex}.mem-settings-hint{color:var(--text-muted);max-width:480px;font-size:11px}.mem-toggle{background:var(--border);cursor:pointer;width:40px;height:22px;transition:background var(--duration) var(--ease);border:none;border-radius:11px;flex-shrink:0;padding:0;position:relative}.mem-toggle:disabled{opacity:.5;cursor:not-allowed}.mem-toggle-on{background:var(--accent-green)}.mem-toggle-knob{background:var(--switch-knob);width:16px;height:16px;transition:transform var(--duration) var(--ease);border-radius:50%;position:absolute;top:3px;left:3px}.mem-toggle-on .mem-toggle-knob{transform:translate(18px)}.mem-setting-row{border-bottom:1px solid var(--border-light);justify-content:space-between;align-items:center;gap:16px;padding:10px 0;display:flex}.mem-setting-row:last-child{border-bottom:none}.mem-setting-info{flex-direction:column;flex:1;gap:3px;min-width:0;display:flex}.mem-setting-label{color:var(--text-primary);font-size:12px;font-weight:600}.mem-setting-desc{color:var(--text-muted);font-size:11px;line-height:1.4}.mem-setting-row-danger .mem-setting-label{color:var(--danger)}.mem-btn-danger{border:1px solid var(--danger);color:var(--danger);cursor:pointer;transition:background var(--duration) var(--ease), color var(--duration) var(--ease);white-space:nowrap;background:0 0;border-radius:6px;flex-shrink:0;padding:5px 12px;font-size:11px;font-weight:600}.mem-btn-danger:hover:not(:disabled){background:var(--danger);color:var(--text-inverse)}.mem-btn-danger:disabled{opacity:.5;cursor:not-allowed}.mem-db-footer{border-top:1px solid var(--border-light);font-size:11px;font-family:var(--font-mono);color:var(--text-muted);justify-content:space-between;align-items:center;margin-top:20px;padding-top:14px;display:flex}.mem-tab-bar{border-bottom:1px solid var(--border);background:var(--bg-card);flex-shrink:0;gap:0;padding:0 24px;display:flex}.mem-tab-btn{font-size:12px;font-weight:500;font-family:var(--font-mono);letter-spacing:.5px;color:var(--text-muted);cursor:pointer;transition:color var(--duration) var(--ease), border-color var(--duration) var(--ease);background:0 0;border:none;border-bottom:2px solid #0000;align-items:center;gap:6px;margin-bottom:-1px;padding:10px 18px;display:flex}.mem-tab-btn:hover{color:var(--text-secondary)}.mem-tab-active{color:var(--text-primary);border-bottom-color:var(--accent)}.mem-profile-grid{grid-template-columns:1fr 1fr;gap:20px;display:grid}.mem-profile-card{background:var(--bg-secondary);border:1px solid var(--border-light);border-radius:var(--radius-lg);flex-direction:column;gap:10px;padding:20px;display:flex}.mem-profile-card-title{font-size:13px;font-weight:600;font-family:var(--font-mono);color:var(--text-primary);align-items:center;gap:8px;display:flex}.mem-profile-desc{color:var(--text-secondary);margin:0;font-size:12px;line-height:1.5}.mem-profile-note{color:var(--text-muted);margin:0;font-size:11px;font-style:italic}.mem-profile-checkbox{font-size:12px;font-family:var(--font-mono);color:var(--text-secondary);cursor:pointer;align-items:center;gap:6px;display:flex}.mem-profile-checkbox input{cursor:pointer;margin:0}.mem-profile-run-btn{align-self:flex-start;align-items:center;gap:6px;padding:8px 18px;font-size:12px;display:flex}.mem-log{background:var(--bg-code);border:1px solid var(--border-code);border-radius:var(--radius-md);max-height:200px;font-family:var(--font-mono);scrollbar-width:thin;scrollbar-color:var(--border-code) transparent;padding:8px;font-size:12px;line-height:1.6;overflow-y:auto}.mem-log::-webkit-scrollbar{width:4px}.mem-log::-webkit-scrollbar-track{background:0 0}.mem-log::-webkit-scrollbar-thumb{background:var(--border-code);border-radius:2px}.mem-log-line{white-space:pre-wrap;word-break:break-word;color:var(--text-code)}.mem-log-line.finding{color:var(--code-warning)}.mem-log-line.error{color:var(--code-danger)}.mem-review-section{flex-direction:column;gap:8px;display:flex}.mem-review-header{font-size:11px;font-weight:600;font-family:var(--font-mono);text-transform:uppercase;letter-spacing:1.5px;color:var(--text-muted)}.mem-review-list{scrollbar-width:thin;scrollbar-color:var(--border) transparent;flex-direction:column;gap:4px;max-height:240px;display:flex;overflow-y:auto}.mem-review-list::-webkit-scrollbar{width:4px}.mem-review-list::-webkit-scrollbar-track{background:0 0}.mem-review-list::-webkit-scrollbar-thumb{background:var(--border);border-radius:2px}.mem-review-item{background:var(--bg-card);border:1px solid var(--border-light);border-radius:var(--radius-md);cursor:pointer;transition:border-color var(--duration) var(--ease);align-items:center;gap:8px;padding:6px 8px;display:flex}.mem-review-item:hover{border-color:var(--border)}.mem-review-item input{cursor:pointer;flex-shrink:0;margin:0}.mem-review-content{min-width:0;color:var(--text-primary);text-overflow:ellipsis;white-space:nowrap;flex:1;font-size:12px;overflow:hidden}.mem-conf-badge{font-size:10px;font-family:var(--font-mono);border-radius:var(--radius-sm);background:color-mix(in srgb, var(--text-muted) 12%, transparent);color:var(--text-muted);flex-shrink:0;padding:2px 6px}.mem-source-badge{font-size:10px;font-family:var(--font-mono);border-radius:var(--radius-sm);background:color-mix(in srgb, var(--text-muted) 12%, transparent);color:var(--text-secondary);flex-shrink:0;padding:2px 6px}.mem-domain-badge{font-size:10px;font-family:var(--font-mono);border-radius:var(--radius-sm);flex-shrink:0;padding:2px 8px;font-weight:600}.mem-domain-badge.blue{background:color-mix(in srgb, var(--accent-blue) 15%, transparent);color:var(--accent-blue)}.mem-domain-badge.purple{background:color-mix(in srgb, var(--accent-purple) 15%, transparent);color:var(--accent-purple)}.mem-domain-badge.green{background:color-mix(in srgb, var(--accent-green) 15%, transparent);color:var(--accent-green)}.mem-domain-badge.gray{background:color-mix(in srgb, var(--text-muted) 12%, transparent);color:var(--text-muted)}.mem-review-actions{align-items:center;gap:12px;margin-top:4px;display:flex}.mem-review-actions .btn-primary{align-items:center;gap:6px;padding:7px 16px;font-size:12px;display:flex}.mem-review-select-links{font-size:11px;font-family:var(--font-mono);color:var(--text-muted)}.mem-review-select-links a{color:var(--accent-blue);cursor:pointer;text-decoration:none}.mem-review-select-links a:hover{text-decoration:underline}.mem-profile-success{background:color-mix(in srgb, var(--accent-green) 10%, transparent);border:1px solid color-mix(in srgb, var(--accent-green) 25%, transparent);border-radius:var(--radius-md);font-size:12px;font-family:var(--font-mono);color:var(--accent-green);align-items:center;gap:6px;padding:8px 12px;display:flex}.mem-profile-empty{text-align:center;color:var(--text-muted);font-size:12px;font-family:var(--font-mono);padding:12px}@media (width<=768px){.memory-dashboard-header{padding-left:var(--sidebar-toggle-clearance)}}@media (width<=900px){.mem-stat-cards{grid-template-columns:repeat(2,1fr)}.mem-two-col{grid-template-columns:1fr}.mem-embedding-coverage{display:none}.mem-detail-grid{grid-template-columns:repeat(2,1fr)}.mem-profile-grid{grid-template-columns:1fr}}@media (width<=600px){.mem-stat-cards{grid-template-columns:1fr}.memory-dashboard-page{height:100%}.mem-knowledge-table{font-size:12px}.mem-filters{flex-direction:column}.mem-toast-container{bottom:12px;left:12px;right:12px}}.mem-goals-tab{flex-direction:column;gap:14px;padding:16px;display:flex}.mem-goals-stats-row{flex-wrap:wrap;gap:10px;display:flex}.mem-goals-stat-pill{background:var(--bg-hover);border:1px solid var(--border);border-radius:20px;align-items:center;gap:6px;padding:5px 12px;font-size:12px;font-weight:500;display:flex}.mem-goals-stat-n{font-size:16px;font-weight:700}.mem-goals-stat-label{opacity:.7;text-transform:capitalize}.mem-goal-status-queued{border-color:var(--accent-blue)!important}.mem-goal-status-in-progress{border-color:var(--accent-yellow)!important}.mem-goal-status-completed{border-color:var(--accent-green)!important}.mem-goal-status-failed{border-color:var(--danger)!important}.mem-goal-status-cancelled{opacity:.6;border-color:var(--border)!important}.mem-goals-approval-banner{background:color-mix(in srgb, var(--accent-yellow) 10%, transparent);border:1px solid color-mix(in srgb, var(--accent-yellow) 40%, transparent);border-radius:var(--radius-lg);flex-direction:column;gap:10px;padding:12px 14px;display:flex}.mem-goals-approval-title{opacity:.85;align-items:center;gap:6px;font-size:12px;font-weight:600;display:flex}.mem-goals-approval-item{background:var(--bg-card);border:1px solid var(--border);border-radius:var(--radius-md);justify-content:space-between;align-items:flex-start;gap:12px;padding:8px 10px;display:flex}.mem-goals-approval-text{flex-direction:column;gap:3px;font-size:13px;display:flex}.mem-goals-approval-text strong{font-weight:600}.mem-goals-approval-text span{opacity:.7;font-size:12px}.mem-goals-approval-actions{flex-shrink:0;gap:6px;display:flex}.btn-danger-sm{border-radius:var(--radius-md);background:color-mix(in srgb, var(--danger) 15%, transparent);border:1px solid color-mix(in srgb, var(--danger) 40%, transparent);color:var(--text-primary);cursor:pointer;padding:4px 10px;font-size:12px}.btn-danger-sm:hover{background:color-mix(in srgb, var(--danger) 25%, transparent)}.mem-goals-toolbar{gap:8px;display:flex}.mem-goals-add-form{background:var(--bg-hover);border:1px solid var(--border);border-radius:var(--radius-lg);flex-direction:column;gap:8px;padding:12px;display:flex}.mem-goals-form-row{align-items:center;gap:8px;display:flex}.mem-select{border-radius:var(--radius-md);background:var(--bg-card);border:1px solid var(--border);color:var(--text-primary);cursor:pointer;padding:6px 10px;font-size:13px}.mem-goals-list{flex-direction:column;gap:8px;display:flex}.mem-goal-card{border:1px solid var(--border);border-radius:var(--radius-lg);background:var(--bg-card);transition:border-color .15s;overflow:hidden}.mem-goal-header{cursor:pointer;-webkit-user-select:none;user-select:none;justify-content:space-between;align-items:center;gap:8px;padding:10px 14px;display:flex}.mem-goal-header:hover{background:var(--bg-hover)}.mem-goal-header-left{flex:1;align-items:center;gap:8px;min-width:0;display:flex}.mem-goal-header-right{flex-shrink:0;align-items:center;gap:8px;display:flex}.mem-goal-status-dot{background:var(--text-muted);border-radius:50%;flex-shrink:0;width:8px;height:8px}.mem-goal-status-dot.status-queued{background:var(--accent-blue)}.mem-goal-status-dot.status-in-progress{background:var(--accent-yellow)}.mem-goal-status-dot.status-completed{background:var(--accent-green)}.mem-goal-status-dot.status-failed{background:var(--danger)}.mem-goal-title{white-space:nowrap;text-overflow:ellipsis;font-size:13px;font-weight:600;overflow:hidden}.mem-goal-priority{border-radius:10px;flex-shrink:0;padding:1px 6px;font-size:11px;font-weight:500}.mem-priority-high{background:color-mix(in srgb, var(--danger) 15%, transparent)}.mem-priority-medium{background:color-mix(in srgb, var(--accent-yellow) 15%, transparent)}.mem-priority-low{background:color-mix(in srgb, var(--accent-blue) 15%, transparent)}.mem-goal-source-badge{background:color-mix(in srgb, var(--accent-purple) 15%, transparent);border-radius:10px;flex-shrink:0;align-items:center;gap:3px;padding:1px 6px;font-size:10px;display:flex}.mem-goal-task-count{opacity:.6;align-items:center;gap:4px;font-size:12px;display:flex}.mem-goal-action-btn{border-radius:var(--radius-md);background:var(--bg-hover);border:1px solid var(--border);color:var(--text-primary);cursor:pointer;align-items:center;gap:4px;padding:3px 8px;font-size:11px;display:flex}.mem-goal-action-btn:hover{background:var(--bg-active)}.mem-goal-delete-btn:hover{background:color-mix(in srgb, var(--danger) 15%, transparent);border-color:color-mix(in srgb, var(--danger) 40%, transparent)}.mem-chevron-open{transition:transform .15s;transform:rotate(180deg)}.mem-goal-body{border-top:1px solid var(--border);flex-direction:column;gap:8px;padding:0 14px 12px;display:flex}.mem-goal-desc{opacity:.7;margin:8px 0 0;font-size:12px}.mem-goal-progress{background:var(--bg-hover);border-radius:var(--radius-md);opacity:.8;padding:6px 8px;font-size:12px}.mem-goal-no-tasks{opacity:.5;font-size:12px;font-style:italic}.mem-task-list{flex-direction:column;gap:4px;margin-top:4px;display:flex}.mem-task-row{border-radius:var(--radius-md);align-items:flex-start;gap:8px;padding:5px 8px;font-size:12px;display:flex}.mem-task-row:hover{background:var(--bg-hover)}.mem-task-dot{background:var(--text-muted);border-radius:50%;flex-shrink:0;width:7px;height:7px;margin-top:3px}.mem-task-dot.status-in-progress{background:var(--accent-yellow)}.mem-task-dot.status-completed{background:var(--accent-green)}.mem-task-dot.status-failed{background:var(--danger)}.mem-task-dot.status-blocked{background:var(--accent-purple)}.mem-task-desc{flex:1}.mem-task-status-label{opacity:.5;text-transform:capitalize;flex-shrink:0;font-size:10px}.mem-task-result{opacity:.6;text-overflow:ellipsis;white-space:nowrap;flex-shrink:0;max-width:200px;font-size:11px;overflow:hidden}.mem-tab-badge{background:var(--accent-yellow);min-width:16px;height:16px;color:var(--text-inverse);border-radius:8px;justify-content:center;align-items:center;margin-left:2px;padding:0 4px;font-size:10px;font-weight:700;display:inline-flex}