@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.
- package/assets/tray-icon.png +0 -0
- package/assets/tray-icon@2x.png +0 -0
- package/bin/gaia-ui.cjs +25 -1
- package/dist/assets/AdvancedSettings-5cX0pGZc.js +1 -0
- package/dist/assets/{ConnectorsPane-DXvmZT6E.js → ConnectorsPane-CuWxzcBY.js} +1 -1
- package/dist/assets/DocumentLibrary-BdAKDe8H.js +1 -0
- package/dist/assets/FileBrowser-B8s6hKC5.js +4 -0
- package/dist/assets/MemoryDashboard-DQxtAW90.css +1 -0
- package/dist/assets/MemoryDashboard-DtolA-HZ.js +1 -0
- package/dist/assets/MobileAccessModal-C3nWkpWA.js +2 -0
- package/dist/assets/ScheduleManager-HHdD6sko.js +2 -0
- package/dist/assets/index-CFVpPQal.css +1 -0
- package/dist/assets/index-DEPbenxC.js +60 -0
- package/dist/assets/useEscapeToClose-B8fw5mn-.js +1 -0
- package/dist/index.html +2 -2
- package/main.cjs +19 -1
- package/package.json +1 -1
- package/services/backend-installer.cjs +156 -32
- package/services/tray-manager.cjs +10 -2
- package/dist/assets/AdvancedSettings-DNQod9tb.js +0 -1
- package/dist/assets/DocumentLibrary-H6_dL1FQ.js +0 -1
- package/dist/assets/FileBrowser-JEScQZqn.js +0 -4
- package/dist/assets/MemoryDashboard-B-YH4b1Z.css +0 -1
- package/dist/assets/MemoryDashboard-CK5IZKJ8.js +0 -1
- package/dist/assets/MobileAccessModal-CV7e2cgI.js +0 -2
- package/dist/assets/ScheduleManager-A5eLWyGP.js +0 -2
- package/dist/assets/index-B8E7IBmc.css +0 -1
- package/dist/assets/index-D00FJoXi.js +0 -58
|
@@ -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-
|
|
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-
|
|
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
|
-
|
|
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
|
@@ -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
|
-
|
|
1605
|
-
|
|
1606
|
-
report
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
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 || "?"} —
|
|
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 —
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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}
|