@amd-gaia/agent-ui 0.25.4-rc.13 → 0.25.4-rc.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/assets/AdvancedSettings-hLQJ-BvE.js +1 -0
- package/dist/assets/ConnectorsPane-DfybpMJr.js +1 -0
- package/dist/assets/{DocumentLibrary-ppKeCLCX.js → DocumentLibrary-B_SGGC-T.js} +2 -2
- package/dist/assets/{FileBrowser-CpxsuXLP.js → FileBrowser-CyQfWRCH.js} +4 -4
- package/dist/assets/MemoryDashboard-CB3sydNs.js +1 -0
- package/dist/assets/MobileAccessModal-CzCQcTd_.js +2 -0
- package/dist/assets/ScheduleManager-DBm4eFZV.js +1 -0
- package/dist/assets/api-UNqTRAb1.js +4 -0
- package/dist/assets/index-GK8rUlTc.js +80 -0
- package/dist/assets/useT-c44fzppq.js +3 -0
- package/dist/assets/{zap-_zbDbyXB.js → zap-BikC79-g.js} +1 -1
- package/dist/index.html +3 -3
- package/dist/sw.js +1 -1
- package/main.cjs +101 -11
- package/package.json +1 -1
- package/preload.cjs +8 -0
- package/services/backend-supervisor.cjs +150 -0
- package/services/port-manager.cjs +3 -0
- package/dist/assets/AdvancedSettings-Cq4p_oT3.js +0 -1
- package/dist/assets/ConnectorsPane-UDC3SVIx.js +0 -1
- package/dist/assets/MemoryDashboard-oMZpYqJp.js +0 -1
- package/dist/assets/MobileAccessModal-Dl6ADfRB.js +0 -2
- package/dist/assets/ScheduleManager-BCvf0FxU.js +0 -1
- package/dist/assets/api-CMkT9jku.js +0 -4
- package/dist/assets/index-DsqWzb7b.js +0 -80
- package/dist/assets/useT-TIhGZVZ6.js +0 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{q as e}from"./useT-c44fzppq.js";var t={name:`message-square`,size:24,node:[[`path`,{d:`M22 17a2 2 0 0 1-2 2H6.828a2 2 0 0 0-1.414.586l-2.202 2.202A.71.71 0 0 1 2 21.286V5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2z`,key:`18887p`}]]};t.node;var n=e(t),r={name:`zap`,size:24,node:[[`path`,{d:`M15.914 4a1.5 1.5 0 00-2.474-1.561l-9 9A1.5 1.5 0 005.5 14h4.002a.5.5 0 01.471.666L8.086 20a1.5 1.5 0 002.475 1.56l9-9A1.5 1.5 0 0018.5 10h-3.997a.5.5 0 01-.472-.667z`,key:`1v7up4`}]]};r.node;var i=e(r);export{n,i as t};
|
package/dist/index.html
CHANGED
|
@@ -12,10 +12,10 @@
|
|
|
12
12
|
<meta name="apple-mobile-web-app-capable" content="yes" />
|
|
13
13
|
<meta name="apple-mobile-web-app-title" content="GAIA" />
|
|
14
14
|
<title>GAIA Agent UI</title>
|
|
15
|
-
<script type="module" crossorigin src="./assets/index-
|
|
15
|
+
<script type="module" crossorigin src="./assets/index-GK8rUlTc.js"></script>
|
|
16
16
|
<link rel="modulepreload" crossorigin href="./assets/rolldown-runtime-XKyaHtl9.js">
|
|
17
|
-
<link rel="modulepreload" crossorigin href="./assets/useT-
|
|
18
|
-
<link rel="modulepreload" crossorigin href="./assets/api-
|
|
17
|
+
<link rel="modulepreload" crossorigin href="./assets/useT-c44fzppq.js">
|
|
18
|
+
<link rel="modulepreload" crossorigin href="./assets/api-UNqTRAb1.js">
|
|
19
19
|
<link rel="stylesheet" crossorigin href="./assets/index-B7tI0eKR.css">
|
|
20
20
|
</head>
|
|
21
21
|
<body>
|
package/dist/sw.js
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
// never sees a stale UI or stale data.
|
|
10
10
|
|
|
11
11
|
const CACHE_PREFIX = 'gaia-assets-';
|
|
12
|
-
const CACHE_NAME = CACHE_PREFIX + '0.25.
|
|
12
|
+
const CACHE_NAME = CACHE_PREFIX + '0.25.4rc15-aa5852539b09a5b3';
|
|
13
13
|
const ASSETS_PATH = new URL('assets/', self.registration.scope).pathname;
|
|
14
14
|
|
|
15
15
|
self.addEventListener('install', () => {
|
package/main.cjs
CHANGED
|
@@ -102,6 +102,7 @@ const KeepAwake = require("./services/keep-awake.cjs");
|
|
|
102
102
|
const PortManager = require("./services/port-manager.cjs");
|
|
103
103
|
const { isGaiaBackendProcess } = require("./services/backend-orphan.cjs");
|
|
104
104
|
const { showBackendCrashDialog } = require("./services/backend-crash-dialog.cjs");
|
|
105
|
+
const { createBackendSupervisor } = require("./services/backend-supervisor.cjs");
|
|
105
106
|
const { buildIndexQuery, INSTALL_SCREEN_QUERY } = require("./services/index-query.cjs");
|
|
106
107
|
const backendInstaller = require("./services/backend-installer.cjs");
|
|
107
108
|
const { createEngineInstall } = require("./services/engine-install.cjs");
|
|
@@ -214,6 +215,8 @@ const APP_NAME = "GAIA";
|
|
|
214
215
|
// from prior aborted sessions (issue #782 / T5).
|
|
215
216
|
const DEFAULT_BACKEND_PORT = 4200;
|
|
216
217
|
const STARTUP_TIMEOUT = 30000;
|
|
218
|
+
// A restart must answer within this, or it counts as a failed try.
|
|
219
|
+
const RESTART_TIMEOUT = 90000;
|
|
217
220
|
|
|
218
221
|
// Parse CLI args (T11: --minimized flag for auto-start)
|
|
219
222
|
const startMinimized = process.argv.includes("--minimized");
|
|
@@ -244,6 +247,8 @@ let backendProcess = null;
|
|
|
244
247
|
let backendStarting = null;
|
|
245
248
|
// Set as cleanup() begins; startup stops at its next step once it is.
|
|
246
249
|
let shutdownStarted = false;
|
|
250
|
+
// Set once an update install starts quitting the app.
|
|
251
|
+
let updateQuitStarted = false;
|
|
247
252
|
let backendPort = DEFAULT_BACKEND_PORT;
|
|
248
253
|
let healthCheckUrl = `http://localhost:${backendPort}/api/health`;
|
|
249
254
|
let backendStderrTail = [];
|
|
@@ -281,6 +286,11 @@ const portManager = new PortManager({
|
|
|
281
286
|
*/
|
|
282
287
|
let isQuitting = false;
|
|
283
288
|
|
|
289
|
+
/** Any quit is under way, an update install's included: start no backend. */
|
|
290
|
+
function quitStarted() {
|
|
291
|
+
return shutdownStarted || isQuitting || updateQuitStarted;
|
|
292
|
+
}
|
|
293
|
+
|
|
284
294
|
// ── Backend Process ────────────────────────────────────────────────────────
|
|
285
295
|
|
|
286
296
|
/**
|
|
@@ -389,6 +399,8 @@ async function startBackend() {
|
|
|
389
399
|
env: {
|
|
390
400
|
...process.env,
|
|
391
401
|
GAIA_APP_PID: String(process.pid),
|
|
402
|
+
// Piped stdout is block-buffered: a dying backend's last lines would never arrive.
|
|
403
|
+
PYTHONUNBUFFERED: "1",
|
|
392
404
|
...(app.isPackaged && {
|
|
393
405
|
GAIA_BUNDLED_LEMONADE_DIR: path.join(process.resourcesPath, "vendor", "lemonade"),
|
|
394
406
|
}),
|
|
@@ -434,17 +446,16 @@ async function startBackend() {
|
|
|
434
446
|
}
|
|
435
447
|
|
|
436
448
|
child.on("exit", (code, signal) => {
|
|
437
|
-
|
|
438
|
-
|
|
449
|
+
// Any exit we didn't ask for leaves the window without a backend, even code 0.
|
|
450
|
+
const crashed = !isIntentionalKill && !isQuitting;
|
|
451
|
+
if (crashed) {
|
|
452
|
+
console.error(`Backend exited with code ${code} (signal=${signal}, pid=${child.pid})`);
|
|
439
453
|
}
|
|
440
|
-
|
|
441
|
-
backendProcess = null;
|
|
454
|
+
if (backendProcess === child) backendProcess = null;
|
|
442
455
|
if (trayManager && !isQuitting) trayManager.setBackendAlive(false);
|
|
443
456
|
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
void handleBackendCrash(code, signal);
|
|
447
|
-
}
|
|
457
|
+
// Once restarts run out, the supervisor's onStopped shows the crash dialog.
|
|
458
|
+
if (crashed) backendSupervisor.crashed({ code, signal });
|
|
448
459
|
|
|
449
460
|
// Remove pidfile on exit to avoid leaving stale PID behind.
|
|
450
461
|
try {
|
|
@@ -461,12 +472,82 @@ async function startBackend() {
|
|
|
461
472
|
}
|
|
462
473
|
});
|
|
463
474
|
|
|
475
|
+
// "close" waits for stdio to drain, so the tail holds the backend's last words.
|
|
476
|
+
child.once("close", (code, signal) => {
|
|
477
|
+
if (isIntentionalKill || isQuitting) return;
|
|
478
|
+
const tail = backendStderrTail.length ? backendStderrTail.join("\n") : "(nothing on stderr)";
|
|
479
|
+
console.error(`[main] Backend pid ${child.pid} closed (code=${code}, signal=${signal}). Last stderr lines:\n${tail}`);
|
|
480
|
+
});
|
|
481
|
+
|
|
464
482
|
return child;
|
|
465
483
|
}
|
|
466
484
|
|
|
485
|
+
/**
|
|
486
|
+
* Start a new backend for the supervisor and resolve once it answers.
|
|
487
|
+
* Rejects when it exits first or never answers, so the supervisor retries.
|
|
488
|
+
*/
|
|
489
|
+
async function restartBackend() {
|
|
490
|
+
backendStarting = startBackend();
|
|
491
|
+
const child = await backendStarting;
|
|
492
|
+
if (!child) {
|
|
493
|
+
throw new Error("GAIA's backend program is missing, so it can't restart. Reinstall GAIA.");
|
|
494
|
+
}
|
|
495
|
+
if (quitStarted()) {
|
|
496
|
+
isIntentionalKill = true;
|
|
497
|
+
await portManager.killBackend(child);
|
|
498
|
+
throw new Error("GAIA is quitting, so the restarted backend was stopped.");
|
|
499
|
+
}
|
|
500
|
+
backendProcess = child;
|
|
501
|
+
const alive = () => child.exitCode === null && child.signalCode === null;
|
|
502
|
+
const ready = await waitForBackend(RESTART_TIMEOUT, alive);
|
|
503
|
+
if (!ready) {
|
|
504
|
+
if (!alive()) {
|
|
505
|
+
throw new Error(`The backend exited (code ${child.exitCode}, signal ${child.signalCode}) before it answered.`);
|
|
506
|
+
}
|
|
507
|
+
isIntentionalKill = true;
|
|
508
|
+
await portManager.killBackend(child);
|
|
509
|
+
throw new Error(`The backend did not answer within ${RESTART_TIMEOUT / 1000} s.`);
|
|
510
|
+
}
|
|
511
|
+
console.log(`[main] Backend restarted on port ${backendPort} (pid=${child.pid})`);
|
|
512
|
+
if (trayManager) {
|
|
513
|
+
trayManager.setBackendPort(backendPort);
|
|
514
|
+
trayManager.setBackendAlive(true);
|
|
515
|
+
}
|
|
516
|
+
return { port: backendPort };
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
/** What the renderer needs: the supervisor's state plus the API base to use. */
|
|
520
|
+
function backendStateForRenderer(state) {
|
|
521
|
+
return { ...state, apiBase: state.port ? buildIndexQuery(state.port).api : null };
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
const backendSupervisor = createBackendSupervisor({
|
|
525
|
+
start: restartBackend,
|
|
526
|
+
onStopped: (state) => {
|
|
527
|
+
const { code = null, signal = null } = state.lastExit || {};
|
|
528
|
+
void handleBackendCrash(code, signal);
|
|
529
|
+
},
|
|
530
|
+
onState: (state) => {
|
|
531
|
+
console.log(
|
|
532
|
+
`[main] Backend ${state.status}` +
|
|
533
|
+
(state.status === "restarting" ? ` (try ${state.attempt} of ${state.maxRestarts})` : "") +
|
|
534
|
+
(state.lastError ? `: ${state.lastError}` : "")
|
|
535
|
+
);
|
|
536
|
+
if (mainWindow && !mainWindow.isDestroyed()) {
|
|
537
|
+
mainWindow.webContents.send("backend:state", backendStateForRenderer(state));
|
|
538
|
+
}
|
|
539
|
+
},
|
|
540
|
+
});
|
|
541
|
+
|
|
542
|
+
ipcMain.handle("backend:get-state", () => backendStateForRenderer(backendSupervisor.getState()));
|
|
543
|
+
ipcMain.handle("backend:restart", () => {
|
|
544
|
+
backendSupervisor.restartNow();
|
|
545
|
+
return backendStateForRenderer(backendSupervisor.getState());
|
|
546
|
+
});
|
|
547
|
+
|
|
467
548
|
/**
|
|
468
549
|
* Tell the user the backend stopped and offer Restart / Save diagnostics /
|
|
469
|
-
* Quit. Invoked
|
|
550
|
+
* Quit. Invoked by the supervisor's onStopped once automatic restarts run out.
|
|
470
551
|
*/
|
|
471
552
|
async function handleBackendCrash(code, signal) {
|
|
472
553
|
autoUpdater.reportStartFailure();
|
|
@@ -488,11 +569,11 @@ async function handleBackendCrash(code, signal) {
|
|
|
488
569
|
}
|
|
489
570
|
}
|
|
490
571
|
|
|
491
|
-
async function waitForBackend(timeoutMs) {
|
|
572
|
+
async function waitForBackend(timeoutMs, isAlive = () => true) {
|
|
492
573
|
const start = Date.now();
|
|
493
574
|
const http = require("http");
|
|
494
575
|
|
|
495
|
-
while (Date.now() - start < timeoutMs) {
|
|
576
|
+
while (Date.now() - start < timeoutMs && isAlive()) {
|
|
496
577
|
try {
|
|
497
578
|
await new Promise((resolve, reject) => {
|
|
498
579
|
const req = http.get(healthCheckUrl, (res) => {
|
|
@@ -1213,6 +1294,7 @@ app.whenReady().then(async () => {
|
|
|
1213
1294
|
if (shutdownStarted) return;
|
|
1214
1295
|
backendStarting = startBackend();
|
|
1215
1296
|
backendProcess = await backendStarting;
|
|
1297
|
+
if (backendProcess) backendSupervisor.running(backendPort);
|
|
1216
1298
|
if (shutdownStarted) {
|
|
1217
1299
|
console.log("[main] Quit during startup — not opening the window");
|
|
1218
1300
|
return;
|
|
@@ -1344,6 +1426,7 @@ const quitGuard = installQuitGuard({
|
|
|
1344
1426
|
// Mark any subsequent backend exit as intentional so we don't pop the
|
|
1345
1427
|
// crash dialog during normal shutdown.
|
|
1346
1428
|
isIntentionalKill = true;
|
|
1429
|
+
backendSupervisor.stop();
|
|
1347
1430
|
},
|
|
1348
1431
|
onError: (err) => {
|
|
1349
1432
|
console.error("[main] Quit check failed:", err);
|
|
@@ -1355,12 +1438,19 @@ const quitGuard = installQuitGuard({
|
|
|
1355
1438
|
},
|
|
1356
1439
|
});
|
|
1357
1440
|
|
|
1441
|
+
// The installer is already running: a restart now would hold its files open.
|
|
1442
|
+
electronAutoUpdater.on("before-quit-for-update", () => {
|
|
1443
|
+
updateQuitStarted = true;
|
|
1444
|
+
backendSupervisor.stop();
|
|
1445
|
+
});
|
|
1446
|
+
|
|
1358
1447
|
quitOnTermSignal({ proc: process, app, guard: quitGuard });
|
|
1359
1448
|
|
|
1360
1449
|
installQuitCleanup({ app, cleanup });
|
|
1361
1450
|
|
|
1362
1451
|
async function cleanup() {
|
|
1363
1452
|
shutdownStarted = true;
|
|
1453
|
+
backendSupervisor.stop();
|
|
1364
1454
|
const installStopped = engineInstall ? engineInstall.stop() : null;
|
|
1365
1455
|
|
|
1366
1456
|
// Phase F: tear down auto-updater timers and IPC handlers.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@amd-gaia/agent-ui",
|
|
3
|
-
"version": "0.25.4-rc.
|
|
3
|
+
"version": "0.25.4-rc.15",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"productName": "GAIA Agent UI",
|
|
6
6
|
"description": "Chat with the GAIA agent - local and private by default on AMD Ryzen AI, cloud models when you choose them",
|
package/preload.cjs
CHANGED
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
* system:* — System metrics for the observability dashboard (#2007)
|
|
17
17
|
* power:* — Keep the PC awake while a chat turn runs (#5226)
|
|
18
18
|
* dialog:* — The OS folder picker
|
|
19
|
+
* backend:* — Backend restarts after a crash (services/backend-supervisor.cjs)
|
|
19
20
|
*/
|
|
20
21
|
|
|
21
22
|
const { contextBridge, ipcRenderer } = require("electron");
|
|
@@ -90,6 +91,13 @@ contextBridge.exposeInMainWorld("gaiaAPI", {
|
|
|
90
91
|
dialog: {
|
|
91
92
|
pickFolder: (defaultPath) => ipcRenderer.invoke("dialog:pick-folder", defaultPath),
|
|
92
93
|
},
|
|
94
|
+
|
|
95
|
+
// ── GAIA's backend process: restarts after a crash, and its new port ──
|
|
96
|
+
backend: {
|
|
97
|
+
getState: () => ipcRenderer.invoke("backend:get-state"),
|
|
98
|
+
restart: () => ipcRenderer.invoke("backend:restart"),
|
|
99
|
+
onState: (cb) => onEvent("backend:state", cb),
|
|
100
|
+
},
|
|
93
101
|
});
|
|
94
102
|
|
|
95
103
|
// ── Window frame ─────────────────────────────────────────────────────────
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
// Copyright(C) 2026 Advanced Micro Devices, Inc. All rights reserved.
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Restarts GAIA's backend when it exits on its own: after a growing wait,
|
|
6
|
+
* at most `maxRestarts` times in `windowMs`, then it stops and waits for the
|
|
7
|
+
* user's Restart GAIA (restartNow). No Electron imports, so it unit-tests.
|
|
8
|
+
*
|
|
9
|
+
* State, as sent to the renderer:
|
|
10
|
+
* status "running" | "restarting" | "stopped"
|
|
11
|
+
* port the backend's port once running
|
|
12
|
+
* since when this outage began (ms epoch), for the banner's timer
|
|
13
|
+
* attempt which try this outage is on
|
|
14
|
+
* nextAttemptAt when the next try starts, or null while one is starting
|
|
15
|
+
* lastExit { code, signal } of the last exit
|
|
16
|
+
* lastError why the last start failed, if it did
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
"use strict";
|
|
20
|
+
|
|
21
|
+
const DEFAULTS = Object.freeze({
|
|
22
|
+
maxRestarts: 3,
|
|
23
|
+
windowMs: 10 * 60_000,
|
|
24
|
+
backoffMs: [1000, 5000, 15000],
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* @param {object} deps
|
|
29
|
+
* @param {() => Promise<{port: number}>} deps.start spawns the backend and resolves once it answers
|
|
30
|
+
* @param {(state: object) => void} deps.onState called with every new state
|
|
31
|
+
* @param {(state: object) => void} [deps.onStopped] called once each time restarts run out
|
|
32
|
+
*/
|
|
33
|
+
function createBackendSupervisor({
|
|
34
|
+
start,
|
|
35
|
+
onState,
|
|
36
|
+
onStopped = () => {},
|
|
37
|
+
maxRestarts = DEFAULTS.maxRestarts,
|
|
38
|
+
windowMs = DEFAULTS.windowMs,
|
|
39
|
+
backoffMs = DEFAULTS.backoffMs,
|
|
40
|
+
now = Date.now,
|
|
41
|
+
setTimer = setTimeout,
|
|
42
|
+
clearTimer = clearTimeout,
|
|
43
|
+
}) {
|
|
44
|
+
if (!Number.isInteger(maxRestarts) || maxRestarts < 1) {
|
|
45
|
+
throw new Error(`backend supervisor: maxRestarts must be a positive integer, got ${maxRestarts}`);
|
|
46
|
+
}
|
|
47
|
+
if (!Array.isArray(backoffMs) || backoffMs.length === 0) {
|
|
48
|
+
throw new Error("backend supervisor: backoffMs must list at least one delay");
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Automatic restarts in the window; a user's Restart GAIA isn't counted.
|
|
52
|
+
let history = [];
|
|
53
|
+
let timer = null;
|
|
54
|
+
let starting = false;
|
|
55
|
+
let stopped = false;
|
|
56
|
+
let state = { status: "running", port: null, since: null, attempt: 0, nextAttemptAt: null, lastExit: null, lastError: null };
|
|
57
|
+
|
|
58
|
+
function emit(next) {
|
|
59
|
+
state = { ...state, ...next, maxRestarts };
|
|
60
|
+
onState({ ...state });
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function attemptStart() {
|
|
64
|
+
timer = null;
|
|
65
|
+
starting = true;
|
|
66
|
+
emit({ nextAttemptAt: null });
|
|
67
|
+
let started;
|
|
68
|
+
try {
|
|
69
|
+
started = Promise.resolve(start());
|
|
70
|
+
} catch (err) {
|
|
71
|
+
started = Promise.reject(err);
|
|
72
|
+
}
|
|
73
|
+
started.then(
|
|
74
|
+
({ port }) => {
|
|
75
|
+
starting = false;
|
|
76
|
+
if (stopped) return;
|
|
77
|
+
emit({ status: "running", port, since: null, attempt: 0, lastError: null });
|
|
78
|
+
},
|
|
79
|
+
(err) => {
|
|
80
|
+
starting = false;
|
|
81
|
+
if (stopped) return;
|
|
82
|
+
schedule({ lastError: err && err.message ? err.message : String(err) });
|
|
83
|
+
}
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function schedule(extra) {
|
|
88
|
+
const t = now();
|
|
89
|
+
history = history.filter((at) => t - at < windowMs);
|
|
90
|
+
const outage = state.status === "running" ? { since: t, attempt: 0 } : {};
|
|
91
|
+
if (history.length >= maxRestarts) {
|
|
92
|
+
const wasStopped = state.status === "stopped";
|
|
93
|
+
emit({ status: "stopped", nextAttemptAt: null, ...outage, ...extra });
|
|
94
|
+
if (!wasStopped) onStopped({ ...state });
|
|
95
|
+
return "stopped";
|
|
96
|
+
}
|
|
97
|
+
const delay = backoffMs[Math.min(history.length, backoffMs.length - 1)];
|
|
98
|
+
history.push(t + delay);
|
|
99
|
+
const attempt = (outage.attempt ?? state.attempt) + 1;
|
|
100
|
+
emit({ ...outage, status: "restarting", attempt, nextAttemptAt: t + delay, ...extra });
|
|
101
|
+
timer = setTimer(attemptStart, delay);
|
|
102
|
+
return "restarting";
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
return {
|
|
106
|
+
/** The backend is up on `port` (the first start, outside the supervisor). */
|
|
107
|
+
running(port) {
|
|
108
|
+
emit({ status: "running", port, since: null, attempt: 0, nextAttemptAt: null, lastError: null });
|
|
109
|
+
},
|
|
110
|
+
|
|
111
|
+
/** The backend exited on its own. Returns what happens next. */
|
|
112
|
+
crashed({ code = null, signal = null } = {}) {
|
|
113
|
+
if (stopped) return "stopped";
|
|
114
|
+
// An exit during a start is that start's failure, reported by start() itself;
|
|
115
|
+
// keep its exit so the crash dialog names the latest one.
|
|
116
|
+
if (starting) {
|
|
117
|
+
state = { ...state, lastExit: { code, signal } };
|
|
118
|
+
return state.status;
|
|
119
|
+
}
|
|
120
|
+
if (timer) return state.status;
|
|
121
|
+
return schedule({ lastExit: { code, signal } });
|
|
122
|
+
},
|
|
123
|
+
|
|
124
|
+
/** The user's Restart GAIA: start now, with a fresh budget. */
|
|
125
|
+
restartNow() {
|
|
126
|
+
if (stopped || starting) return;
|
|
127
|
+
if (timer) {
|
|
128
|
+
clearTimer(timer);
|
|
129
|
+
timer = null;
|
|
130
|
+
}
|
|
131
|
+
history = [];
|
|
132
|
+
if (state.status === "running") return;
|
|
133
|
+
emit({ status: "restarting", attempt: 1 });
|
|
134
|
+
attemptStart();
|
|
135
|
+
},
|
|
136
|
+
|
|
137
|
+
/** GAIA is quitting: no more restarts. */
|
|
138
|
+
stop() {
|
|
139
|
+
stopped = true;
|
|
140
|
+
if (timer) clearTimer(timer);
|
|
141
|
+
timer = null;
|
|
142
|
+
},
|
|
143
|
+
|
|
144
|
+
getState() {
|
|
145
|
+
return { ...state, maxRestarts };
|
|
146
|
+
},
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
module.exports = { createBackendSupervisor, DEFAULTS };
|
|
@@ -111,6 +111,9 @@ async function writeDiagnosticsBundle(destPath, logger) {
|
|
|
111
111
|
"gaia.log",
|
|
112
112
|
"electron-main.log",
|
|
113
113
|
"electron-install-state.json",
|
|
114
|
+
// Fatal-crash stacks from the backend (src/gaia/ui/fault_log.py), and its rotated copy.
|
|
115
|
+
"logs/backend-faults.log",
|
|
116
|
+
"logs/backend-faults.log.1",
|
|
114
117
|
];
|
|
115
118
|
|
|
116
119
|
const present = candidates.filter((rel) =>
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{r as e}from"./rolldown-runtime-XKyaHtl9.js";import{F as t,a as n,c as r,d as i,l as a,q as o,s}from"./useT-TIhGZVZ6.js";import{At as c,Bt as l,I as u,R as d,V as f,Y as p,jt as m,q as h,ut as g}from"./api-CMkT9jku.js";import{Ft as _,Lt as v,Vt as y,Z as b,a as x,c as S,d as C,et as w,f as T,l as E,o as D,r as O,s as k,vt as A}from"./index-DsqWzb7b.js";var j=e(o(),1);function M(){let e=n(),t=i(e=>e.runSetupAgain),o=i(e=>e.closeSettings),[l,d]=(0,j.useState)(null),[f,p]=(0,j.useState)(null),[m,h]=(0,j.useState)(``),[g,_]=(0,j.useState)(``),[y,b]=(0,j.useState)(!1),[x,S]=(0,j.useState)(null),[w,T]=(0,j.useState)(!1);(0,j.useEffect)(()=>{u().then(e=>{d(e),h(e.saved_base_url??e.base_url??``)}).catch(e=>p(e instanceof Error?e.message:String(e)))},[]);let E=(0,j.useCallback)(async e=>{b(!0),S(null);try{let n=await c(e);d(n),_(``),T(!1),n.mode===`gaia`&&!n.gaia_installed&&(o(),t(!0))}catch(e){T(C(e)),S(e instanceof Error?e.message:String(e))}finally{b(!1)}},[o,t]),D=()=>void E({mode:`external`,base_url:m.trim(),api_key:g.trim()||void 0});if(f)return a(`section`,{className:`settings-section`,children:[r(`h4`,{children:e(`settings.advanced.modelServer`)}),a(`div`,{className:`model-warning`,role:`alert`,children:[r(v,{size:14}),a(`div`,{className:`model-warning-content`,children:[r(`strong`,{children:e(`settings.server.readFailed`)}),r(`p`,{children:f})]})]})]});if(!l)return null;let O=l.mode===`external`,k=l.source===`env`;return a(`section`,{className:`settings-section`,"aria-label":e(`settings.advanced.modelServer`),children:[r(`h4`,{children:e(`settings.advanced.modelServer`)}),r(`p`,{className:`model-override-desc`,role:`status`,children:k?e(`settings.server.usesEnv`,{url:l.base_url??``}):O?e(`settings.server.usesYours`,{url:l.base_url??``}):e(`settings.server.usesOwn`)}),!k&&l.env_url_ignored&&r(`p`,{className:`model-status-hint`,children:e(`settings.server.envIgnored`,{url:l.env_url_ignored})}),k?r(`p`,{className:`model-status-hint`,children:e(`settings.server.envUseOwn`)}):a(s.Fragment,{children:[a(`p`,{className:`model-status-hint`,children:[e(`settings.server.useYours`),` `,r(`bdi`,{children:l.what_gaia_does})]}),a(`form`,{className:`model-input-row`,onSubmit:e=>{e.preventDefault(),D()},children:[r(`input`,{type:`text`,className:`model-input`,placeholder:`http://localhost:13305`,value:m,onChange:e=>{h(e.target.value),S(null)},disabled:y,spellCheck:!1,autoCapitalize:`off`,autoCorrect:`off`,"aria-label":e(`settings.server.address`)}),r(`input`,{type:`password`,className:`model-input`,autoComplete:`off`,placeholder:l.api_key_stored?e.bare(`settings.server.keySaved`):e.bare(`settings.server.keyOptional`),value:g,onChange:e=>_(e.target.value),disabled:y,"aria-label":e(`settings.server.key`)}),r(`div`,{className:`model-btn-group`,children:r(`button`,{type:`submit`,className:`btn-model-save`,disabled:y||!m.trim(),children:y?a(s.Fragment,{children:[r(A,{size:13,className:`btn-spinner`}),` `,e(`settings.server.checking`)]}):e(`settings.server.use`)})})]})]}),O&&r(`div`,{className:`setting-actions`,children:r(`button`,{type:`button`,className:`btn-secondary`,disabled:y,onClick:()=>void E({mode:`gaia`}),children:e(`settings.server.useOwn`)})}),x&&a(`div`,{className:`model-warning`,role:`alert`,children:[r(v,{size:14}),a(`div`,{className:`model-warning-content`,children:[r(`strong`,{children:e(w?`settings.server.needsKey`:`settings.server.notSwitched`)}),r(`p`,{children:x})]})]})]})}var N={vulkan:`Vulkan`,rocm:`ROCm`,metal:`Metal`,cpu:`CPU`,npu:`NPU`,remote:`Remote (cloud)`},P={gaia:`settings.server.ownerGaia`,user:`settings.server.ownerUser`,remote:`settings.server.ownerRemote`};function F(e){return e?N[e]??e:`unknown`}function I(e){if(!e)return`unknown`;let t=F(e.backend);return e.backend_source===`lemonade_default`?`${t} (Lemonade's default)`:t}function L(e){return e?`${Math.round(e/1024)}K tokens`:`unknown`}var R={asr:`settings.server.kind.speechRecognition`,embedding:`settings.server.kind.embedding`,image:`settings.server.kind.image`,llm:`settings.server.kind.language`,rerank:`settings.server.kind.reranker`,reranking:`settings.server.kind.reranker`,stt:`settings.server.kind.speechRecognition`,transcription:`settings.server.kind.speechRecognition`,tts:`settings.server.kind.speech`,vision:`settings.server.kind.vision`,"3d":`settings.server.kind.threeD`};function z(e,t){if(!e.model_type)return t(`settings.server.loadedModel`);let n=e.model_type.toLowerCase(),r=R[n];return r?t(r):t(`settings.server.kindOther`,{kind:`${n.charAt(0).toUpperCase()}${n.slice(1)}`})}function B(e,t){let n=[e.name?w(e.name):t.bare(`settings.server.unknownModel`),I(e)];return e.backend!==`remote`&&e.ctx_size&&n.push(L(e.ctx_size)),n.join(` · `)}function V({label:e,value:t,title:n}){return a(`div`,{className:`status-row`,children:[r(`span`,{className:`status-label`,children:e}),r(`span`,{className:`status-value model-server-value`,dir:`auto`,title:n??t,children:t})]})}function ee(){let e=n(),t=i(e=>e.openSettings),[o,c]=(0,j.useState)(null),[l,u]=(0,j.useState)(null),[d,p]=(0,j.useState)(null),[h,_]=(0,j.useState)(null),[v,y]=(0,j.useState)(!1);(0,j.useEffect)(()=>{f().then(c).catch(e=>u(e instanceof Error?e.message:String(e)))},[]);let b=(0,j.useCallback)(async t=>{p(t),_(null);try{let n=await m(t);c(n),_({ok:!0,text:e(`settings.server.savedBackend`)})}catch(e){_({ok:!1,text:e instanceof Error?e.message:String(e)})}finally{p(null)}},[e]),S=o?.chat_model??null,C=(0,j.useCallback)(async()=>{if(S?.name){y(!0);try{if(!await g(S.name,S.ctx_size??void 0))return;_({ok:!0,text:e(`settings.server.reloading`,{name:S.name})})}catch(e){_({ok:!1,text:e instanceof Error?e.message:String(e)})}finally{y(!1)}}},[S,e]),T=r(`button`,{type:`button`,className:`btn-secondary`,onClick:()=>t(`model`),children:e(`settings.server.changeModel`)});if(l)return a(`section`,{className:`settings-section`,"aria-label":e(`settings.advanced.modelServer`),children:[r(`h4`,{children:e(`settings.advanced.modelServer`)}),r(x,{message:l})]});if(!o)return a(`section`,{className:`settings-section`,"aria-label":e(`settings.advanced.modelServer`),children:[r(`h4`,{children:e(`settings.advanced.modelServer`)}),r(`p`,{className:`loading-text`,children:e(`settings.server.checkingServer`)})]});if(!o.reachable)return a(`section`,{className:`settings-section`,"aria-label":e(`settings.advanced.modelServer`),children:[r(`h4`,{children:e(`settings.advanced.modelServer`)}),r(x,{message:o.error??e(`settings.errors.serverDownTitle`)}),T]});let E=o.available_backends??[],D=o.preferred_backend??null,O=E.map(e=>e.name);D&&!O.includes(D)&&O.push(D);let k=D??o.default_backend??null,M=E.filter(e=>e.state===`installable`).map(e=>F(e.name)),N=!!S?.name&&S.recipe===`llamacpp`;return a(`section`,{className:`settings-section`,"aria-label":e(`settings.advanced.modelServer`),children:[r(`h4`,{children:e(`settings.advanced.modelServer`)}),a(`div`,{className:`status-grid`,children:[r(V,{label:e(`settings.server.server`),value:`${P[o.owner]?e(P[o.owner]):o.owner}${o.version?` v${o.version}`:``}`}),r(V,{label:e(`settings.server.addressShort`),value:o.base_url}),r(V,{label:e(`settings.server.chatModel`),value:S?.name?w(S.name):e(`settings.advanced.noneLoaded`),title:S?.name??void 0}),S&&r(V,{label:e(`settings.server.runsOn`),value:I(S)}),S&&S.backend!==`remote`&&r(V,{label:e(`settings.advanced.context`),value:L(S.ctx_size)}),r(V,{label:e(`settings.advanced.embedding`),value:o.embedding_model?.name?`${o.embedding_model.name} · ${I(o.embedding_model)}`:e(`settings.advanced.noneLoaded`)}),(o.loaded_models??[]).map((t,n)=>r(V,{label:z(t,e),value:B(t,e),title:t.name??void 0},`${t.name??`unknown`}-${n}`))]}),o.embedding_note&&r(`p`,{className:`settings-hint`,children:r(`bdi`,{children:o.embedding_note})}),o.system_info_error&&r(`p`,{className:`settings-hint`,children:r(`bdi`,{children:o.system_info_error})}),a(`div`,{className:`settings-field model-server-backend`,children:[r(`span`,{className:`settings-label`,children:e(`settings.server.backend`)}),E.length===0&&!D?r(`span`,{className:`settings-hint`,children:e(`settings.server.noBackends`)}):a(s.Fragment,{children:[r(`div`,{className:`segmented`,role:`radiogroup`,"aria-label":e(`settings.server.backendShort`),children:O.map(e=>a(`button`,{type:`button`,role:`radio`,"aria-checked":k===e,className:k===e?`is-active`:``,disabled:d!==null,onClick:()=>{e!==k&&b(e)},children:[d===e?r(A,{size:12,className:`spin`}):null,F(e)]},e))}),a(`span`,{className:`settings-hint`,children:[e(`settings.server.backendHint`),M.length>0&&` ${e(`settings.server.installable`,{names:M.join(`, `)})}`]})]}),h?.ok&&r(`p`,{className:`settings-ok`,role:`status`,children:h.text}),h&&!h.ok&&r(x,{message:h.text})]}),a(`div`,{className:`settings-row`,children:[T,N&&a(`button`,{type:`button`,className:`btn-secondary`,onClick:()=>void C(),disabled:v,children:[v?r(A,{size:13,className:`spin`}):null,e(`settings.server.reload`)]})]})]})}function H(){let e=n(),[i,o]=(0,j.useState)(null),[c,u]=(0,j.useState)(!0),[f,m]=(0,j.useState)([]),[g,C]=(0,j.useState)(``),[w,N]=(0,j.useState)(``),[P,F]=(0,j.useState)(!1),[I,L]=(0,j.useState)(!1),[R,z]=(0,j.useState)(null),[B,V]=(0,j.useState)(!1),H=(0,j.useRef)(null),[W,G]=(0,j.useState)(!1),[K,ne]=(0,j.useState)(!1),[q,re]=(0,j.useState)(!1),[ie,ae]=(0,j.useState)(null);(0,j.useEffect)(()=>{t.system.info(`Checking system status...`);let e=t.system.time();p().then(n=>{o(n),t.system.timed(`System status received`,e,{lemonade:n.lemonade_running?`running`:`stopped`,model:n.model_loaded||`none`,embedding:n.embedding_model_loaded?`yes`:`no`,disk:`${n.disk_space_gb}GB free`,memory:n.memory_available_gb==null?`unknown`:`${n.memory_available_gb}GB available`}),n.lemonade_running||t.system.warn(`Lemonade Server is NOT running.`)}).catch(e=>{t.system.error(`Failed to get system status`,e),o(null)}).finally(()=>u(!1)),d().then(e=>m(e.servers)).catch(()=>{}),h().then(e=>{let t=e.custom_model??``;C(t),N(t),G(e.dynamic_tools),ne(e.dynamic_tools_locked)}).catch(e=>{t.system.error(`Failed to load settings`,e)}).finally(()=>F(!0))},[]),(0,j.useEffect)(()=>()=>{H.current&&clearTimeout(H.current)},[]);let oe=(0,j.useCallback)(async()=>{let e=g.trim(),n=e.length>0?e:``;L(!0),z(null),V(!1);try{t.system.info(`Saving custom_model override`,{custom_model:n});let e=(await l({custom_model:n})).custom_model??``;C(e),N(e),V(!0),H.current&&clearTimeout(H.current),H.current=setTimeout(()=>V(!1),2200)}catch(e){let n=e instanceof Error?e.message:String(e);t.system.error(`Failed to save custom_model`,e),z(n)}finally{L(!1)}},[g]),se=(0,j.useCallback)(async()=>{if(K||q)return;let e=W,n=!e;G(n),re(!0),ae(null);try{t.system.info(`Saving dynamic_tools setting`,{dynamic_tools:n});let e=await l({dynamic_tools:n});G(e.dynamic_tools),ne(e.dynamic_tools_locked)}catch(n){let r=n instanceof Error?n.message:String(n);t.system.error(`Failed to save dynamic_tools`,n),G(e),ae(r)}finally{re(!1)}},[W,K,q]),ce=g.trim()!==w.trim(),J=i?i.default_model_name:b,{isLoadingModel:le,isDownloadingModel:Y,downloadError:X,loadModel:ue,downloadModel:de}=O(J??void 0),Z=!!i?.default_model_is_cloud,Q=!Z&&!!(i?.lemonade_running&&i.model_loaded&&i.expected_model_loaded===!1),fe=!Z&&!!(i?.lemonade_running&&i.model_loaded&&i.context_size_sufficient===!1),$=!Z&&!(!i?.lemonade_running||i.model_loaded||i.model_downloaded!==!1),pe=(Q||fe)&&J!==null,me=f.some(e=>!e.connected);return a(`div`,{className:`settings-pane`,children:[r(`h2`,{className:`settings-pane-title`,children:e(`settings.section.advanced`)}),r(`section`,{className:`settings-card`,"aria-label":e(`settings.advanced.status`),children:c?r(`p`,{className:`loading-text`,children:e(`settings.advanced.checking`)}):i?a(s.Fragment,{children:[a(`div`,{className:`status-grid`,children:[r(U,{label:e(`settings.advanced.modelServer`),value:i.lemonade_running?i.lemonade_version?e(`settings.advanced.runningAt`,{version:i.lemonade_version}):e(`settings.advanced.running`):S(i)?e(`settings.advanced.notInstalled`):i.lemonade_error?e(`settings.advanced.unavailable`):e(`settings.advanced.notRunning`),ok:i.lemonade_running,hint:i.lemonade_running?void 0:S(i)?e(`settings.advanced.notInstalledHint`):i.lemonade_error?e(`settings.advanced.queryFailed`,{reason:i.lemonade_error}):i.start_instruction&&!k(i.start_instruction)?i.start_instruction:e(`settings.advanced.notRunningHint`)}),S(i)&&r(D,{className:`btn-primary`}),r(U,{label:e(`settings.section.model`),value:i.model_loaded||e(`settings.advanced.noneLoaded`),ok:!!i.model_loaded&&(Z||i.expected_model_loaded!==!1),hint:i.model_loaded?!Z&&i.expected_model_loaded===!1?e(`settings.advanced.expected`,{name:J??``}):void 0:e(`settings.advanced.loadsFirst`)}),r(U,{label:e(`settings.advanced.disk`),value:a(`bdi`,{dir:`ltr`,children:[i.disk_space_gb,` GB`]}),ok:i.disk_space_gb>5,hint:!i.model_loaded&&i.disk_space_gb<30?e(`settings.advanced.diskLow`,{need:`6 GB`,size:`${i.disk_space_gb} GB`}):void 0})]}),$&&a(`div`,{className:`model-action-row model-action-row--download`,children:[a(`div`,{className:`model-action-info`,children:[r(`span`,{className:`model-action-label`,children:e(`settings.advanced.notDownloaded`)}),r(`span`,{className:`model-action-desc`,children:e(`settings.advanced.notDownloadedHint`,{name:J??``,need:`6 GB`})})]}),r(`button`,{className:`btn-model-action btn-model-action--download`,onClick:()=>de(!1),disabled:Y,children:Y?a(s.Fragment,{children:[r(A,{size:13,className:`btn-spinner`}),` `,e(`settings.advanced.downloading`)]}):e(`settings.model.download`)})]}),$&&X&&r(x,{message:X}),pe&&a(`div`,{className:`model-action-row model-action-row--load`,children:[a(`div`,{className:`model-action-info`,children:[r(`span`,{className:`model-action-label`,children:e(Q?`settings.advanced.wrongModel`:`settings.advanced.smallContext`)}),r(`span`,{className:`model-action-desc`,children:e(`settings.advanced.loadHint`,{name:J??``,size:`${32 .toFixed(0)}K`})})]}),r(`button`,{className:`btn-model-action btn-model-action--load`,onClick:()=>ue(),disabled:le,children:le?a(s.Fragment,{children:[r(A,{size:13,className:`btn-spinner`}),` `,e(`settings.advanced.loading`)]}):e(`settings.advanced.load`)})]}),a(`details`,{className:`settings-more`,children:[a(`summary`,{children:[r(y,{size:13,className:`settings-disclosure-chevron`,"aria-hidden":`true`}),` `,e(`settings.advanced.details`)]}),a(`div`,{className:`status-grid`,children:[i.model_size_gb!=null&&r(U,{label:e(`settings.advanced.modelSize`),value:a(`bdi`,{dir:`ltr`,children:[i.model_size_gb,` GB`]}),ok:!0}),i.model_device&&!Z&&r(U,{label:e(`settings.advanced.device`),value:i.model_device.toUpperCase(),ok:i.model_device!==`cpu`}),i.model_context_size!=null&&r(U,{label:e(`settings.advanced.context`),value:e(`settings.ctx.tokens`,{size:`${(i.model_context_size/1024).toFixed(0)}K`}),ok:i.context_size_sufficient}),i.model_labels&&i.model_labels.length>0&&r(U,{label:e(`settings.advanced.capabilities`),value:i.model_labels.join(`, `),ok:!0}),r(U,{label:e(`settings.advanced.embedding`),value:i.embedding_model_loaded?e(`settings.advanced.available`):e(`settings.advanced.notLoaded`),ok:i.embedding_model_loaded}),i.gpu_name&&r(U,{label:`GPU`,value:r(`bdi`,{children:`${i.gpu_name}${i.gpu_vram_gb?` (${T(i.gpu_vram_gb)})`:``}`}),ok:!0}),r(U,{label:e(`settings.advanced.memory`),value:i.memory_available_gb==null?e(`settings.advanced.unknown`):a(`bdi`,{dir:`ltr`,children:[i.memory_available_gb,` GB`]}),ok:i.memory_available_gb!=null&&i.memory_available_gb>2}),i.processor_name&&r(U,{label:e(`settings.advanced.processor`),value:r(`bdi`,{children:i.processor_name}),ok:!0})]}),i.lemonade_running&&J!==null&&!Z&&a(`div`,{className:`force-redownload-row`,children:[r(`span`,{className:`force-redownload-label`,children:e(`settings.advanced.corrupted`)}),r(`button`,{className:`btn-force-redownload`,onClick:()=>de(!0),disabled:Y,children:Y?a(s.Fragment,{children:[r(A,{size:12,className:`btn-spinner`}),` `,e(`settings.advanced.downloading`)]}):e(`settings.advanced.redownload`)})]}),!$&&X&&r(x,{message:X})]})]}):r(`div`,{className:`status-error`,children:r(`p`,{children:e(`settings.advanced.unreachable`)})})}),a(E,{title:e(`settings.advanced.serverTitle`),hint:e(`settings.advanced.serverHint`),children:[r(ee,{}),r(M,{})]}),a(E,{title:e(`settings.advanced.customTitle`),hint:w||e(`settings.advanced.customHint`),children:[r(`p`,{className:`model-override-desc`,children:e(`settings.advanced.customDesc`)}),a(`div`,{className:`model-input-row`,children:[r(`input`,{type:`text`,className:`model-input${w?` has-override`:``}`,placeholder:e.bare(`settings.advanced.customPlaceholder`),value:g,onChange:e=>{C(e.target.value),z(null),V(!1)},onKeyDown:e=>{e.key===`Enter`&&!I&&ce&&P&&(e.preventDefault(),oe())},disabled:!P||I,spellCheck:!1,autoCapitalize:`off`,autoCorrect:`off`,"aria-label":e(`settings.advanced.customAria`)}),r(`div`,{className:`model-btn-group`,children:r(`button`,{className:`btn-model-save${B?` saved`:``}`,onClick:()=>{oe()},disabled:!P||I||!ce&&!B,"aria-label":e(`settings.advanced.customSave`),children:I?a(s.Fragment,{children:[r(A,{size:13,className:`btn-spinner`}),` `,e(`settings.models.applying`)]}):B?a(s.Fragment,{children:[r(_,{size:13}),` `,e(`settings.advanced.saved`)]}):e(`settings.advanced.save`)})})]}),r(`p`,{className:`model-status-hint`,children:e(`settings.advanced.customIds`)}),R&&r(te,{message:R})]}),a(E,{title:e(`settings.advanced.dynamicTitle`),children:[r(`p`,{className:`model-override-desc`,children:e(`settings.advanced.dynamicDesc`)}),a(`label`,{className:`setting-row`,children:[r(`span`,{children:e(`settings.advanced.dynamicEnable`)}),a(`span`,{className:`toggle-switch`,children:[r(`input`,{type:`checkbox`,checked:W,onChange:()=>void se(),disabled:!P||q||K,"aria-label":e(W?`settings.advanced.dynamicOff`:`settings.advanced.dynamicOn`)}),r(`span`,{className:`toggle-track`})]})]}),K&&r(`p`,{className:`model-status-hint`,children:e(`settings.advanced.dynamicLocked`)}),ie&&r(te,{message:ie})]}),f.length>0&&r(E,{title:e(`settings.advanced.mcp`),count:f.length,defaultOpen:me,children:r(`div`,{className:`status-grid`,children:f.map(t=>a(`div`,{className:`status-row`,children:[r(`bdi`,{className:`status-label`,children:t.name}),r(`div`,{className:`status-value-wrap`,children:t.connected?a(`span`,{className:`status-value ok mcp-status-connected`,children:[r(_,{size:12}),e.plural(`settings.advanced.tools`,t.tool_count)]}):a(`span`,{className:`status-value warn mcp-status-failed`,title:t.error??void 0,children:[r(v,{size:12}),e(`settings.custom.failed`)]})})]},t.name))})}),a(`div`,{className:`about-info`,children:[a(`p`,{children:[a(`bdi`,{dir:`ltr`,children:[`GAIA v`,`0.25.4rc13`]}),` `,r(`span`,{className:`beta-badge`,children:`BETA`})]}),r(`p`,{className:`about-sub`,children:e(`settings.advanced.about`)})]})]})}function te({message:e}){let t=n();return a(`div`,{className:`model-warning`,role:`alert`,children:[r(v,{size:14}),a(`div`,{className:`model-warning-content`,children:[r(`strong`,{children:t(`settings.advanced.saveFailed`)}),r(`p`,{children:e})]})]})}function U({label:e,value:t,ok:n,hint:i}){return a(`div`,{className:`status-row${i?` status-row--has-hint`:``}`,children:[r(`span`,{className:`status-label`,children:e}),a(`div`,{className:`status-value-wrap`,children:[r(`span`,{className:`status-value ${n?`ok`:`warn`}`,children:t}),i&&r(`span`,{className:`status-hint`,children:i})]})]})}export{H as AdvancedSettings};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{r as e}from"./rolldown-runtime-XKyaHtl9.js";import{F as t,a as n,c as r,d as i,l as a,o,q as s,s as c}from"./useT-TIhGZVZ6.js";import{_n as l,bn as u,cn as d,dn as f,fn as p,gn as m,hn as h,ln as g,mn as _,on as v,pn as y,sn as b,un as x,vn as S,yn as C}from"./api-CMkT9jku.js";import{Dt as w,Ft as T,Lt as E,Ot as D,Rt as O,Vt as k,l as A,nt as j,vt as M}from"./index-DsqWzb7b.js";var N=e(s(),1),P=t.api;function F(e){switch(e){case`connector.configured`:return`configured`;case`connector.disconnected`:return`disconnected`;case`connection.revoked`:return`disconnected`;case`connector.oauth.completed`:return`oauth_completed`;case`connection.connected`:return`oauth_completed`;case`connector.oauth.error`:return`oauth_error`;case`connector.tested`:return`tested`;case`connector.enabled`:return`enabled`;case`connector.disabled`:return`disabled`;case`connector.grant.changed`:return`grant_changed`;case`connector.activation.changed`:return`activation_changed`;default:return null}}function I(e){let t=(0,N.useRef)(e);(0,N.useEffect)(()=>{t.current=e},[e]),(0,N.useEffect)(()=>{let e=`${o()}/connectors/events`,n=null,r=1e3,i=null,a=!1,s=()=>{a||(n=new EventSource(e),n.onopen=()=>{r=1e3},n.onmessage=e=>{try{let n=JSON.parse(e.data),r=F(n.type);if(r===null){P.debug(`connectors-sse: ignoring event`,n.type);return}let i=n.payload??{},a=i.connector_id??i.provider??null;t.current({connectorId:a,reason:r,payload:i})}catch(e){P.warn(`connectors-sse: malformed event`,e)}},n.onerror=()=>{n?.close(),n=null,!a&&(i=setTimeout(s,r),r=Math.min(r*2,3e4))})};return s(),()=>{a=!0,i&&clearTimeout(i),n?.close()}},[])}function L(e){return e.type===`mcp_server`&&e.configured}function R({connector:e,onChanged:t}){let i=n(),[o,s]=(0,N.useState)(!1),[c,l]=(0,N.useState)(!1),[u,d]=(0,N.useState)(null),[m,h]=(0,N.useState)(null),g=(0,N.useRef)(null),_=(0,N.useRef)(null);(0,N.useEffect)(()=>{if(!o)return;let e=e=>{let t=e.target;g.current&&!g.current.contains(t)&&_.current&&!_.current.contains(t)&&s(!1)};return document.addEventListener(`mousedown`,e),()=>document.removeEventListener(`mousedown`,e)},[o]);let v=(0,N.useCallback)(()=>s(!1),[]);if(j(o,v),(0,N.useEffect)(()=>{if(!o)return;let e=()=>{if(!g.current)return;let e=g.current.getBoundingClientRect();h({top:e.bottom+4,right:window.innerWidth-e.right})};return window.addEventListener(`resize`,e),window.addEventListener(`scroll`,e,!0),()=>{window.removeEventListener(`resize`,e),window.removeEventListener(`scroll`,e,!0)}},[o]),!L(e))return null;let b=e=>{e.stopPropagation(),e.preventDefault()},x=e=>{if(b(e),!o&&g.current){let e=g.current.getBoundingClientRect();h({top:e.bottom+4,right:window.innerWidth-e.right})}s(e=>!e)},S=async e=>{l(!0),d(null);try{await e(),s(!1),t()}catch(e){d(e instanceof Error?e.message:String(e))}finally{l(!1)}};return a(`div`,{className:`connector-tile-menu`,onClick:b,onKeyDown:b,children:[r(`button`,{ref:g,type:`button`,className:`connector-tile-menu-trigger`,"aria-haspopup":`menu`,"aria-expanded":o,"aria-label":i(`settings.connectors.actions`),onClick:x,disabled:c,children:r(D,{size:14})}),o&&m&&a(`div`,{ref:_,role:`menu`,className:`connector-tile-menu-popup`,style:{position:`fixed`,top:m.top,right:m.right},children:[e.enabled?r(`button`,{role:`menuitem`,type:`button`,className:`connector-tile-menu-item`,onClick:()=>void S(()=>f(e.id)),disabled:c,children:i(`settings.connectors.disable`)}):r(`button`,{role:`menuitem`,type:`button`,className:`connector-tile-menu-item`,onClick:()=>void S(()=>y(e.id)),disabled:c,children:i(`settings.connectors.enable`)}),r(`div`,{className:`connector-tile-menu-divider`}),r(`button`,{role:`menuitem`,type:`button`,className:`connector-tile-menu-item connector-tile-menu-item--danger`,onClick:()=>void S(()=>p(e.id)),disabled:c,children:i(`settings.connectors.disconnect`)}),u&&r(`div`,{className:`connector-tile-menu-error`,children:u})]})]})}var z={"https://www.googleapis.com/auth/gmail.readonly":`settings.connectors.scope.gmailRead`,"https://www.googleapis.com/auth/gmail.modify":`settings.connectors.scope.gmailModify`,"https://www.googleapis.com/auth/gmail.send":`settings.connectors.scope.gmailSend`,"https://www.googleapis.com/auth/gmail.compose":`settings.connectors.scope.gmailCompose`,"https://www.googleapis.com/auth/calendar.readonly":`settings.connectors.scope.calendarRead`,"https://www.googleapis.com/auth/calendar.events":`settings.connectors.scope.calendarEvents`,"https://www.googleapis.com/auth/drive.readonly":`settings.connectors.scope.driveRead`,"https://www.googleapis.com/auth/drive.file":`settings.connectors.scope.driveFile`,"https://www.googleapis.com/auth/spreadsheets.readonly":`settings.connectors.scope.sheetsRead`,"https://www.googleapis.com/auth/spreadsheets":`settings.connectors.scope.sheets`,openid:`settings.connectors.scope.openid`,"https://www.googleapis.com/auth/userinfo.email":`settings.connectors.scope.email`,email:`settings.connectors.scope.email`,profile:`settings.connectors.scope.profile`,"https://graph.microsoft.com/Mail.ReadWrite":`settings.connectors.scope.outlookMail`,"https://graph.microsoft.com/Mail.Send":`settings.connectors.scope.outlookSend`,"https://graph.microsoft.com/Calendars.ReadWrite":`settings.connectors.scope.outlookCalendar`,"https://graph.microsoft.com/Calendars.Read":`settings.connectors.scope.outlookCalendarRead`,"https://graph.microsoft.com/User.Read":`settings.connectors.scope.microsoftProfile`};function B(e,t){let n=z[e];return n?t(n):e.split(/[/.:]/).pop()??e}var V=6,H=[`use`];function U(e,t){return!(`revoke_supported`in e)||e.revoke_supported&&e.revoked_remotely?null:e.revoke_supported&&!e.revoked_remotely?t(`settings.connectors.notRevoked`,{reason:String(e.revoke_error??t.bare(`settings.advanced.unknown`))}):e.revoke_error?t(`settings.connectors.localOnly`,{reason:String(e.revoke_error)}):t(`settings.connectors.noRevokeApi`)}function W(){let e=n(),[t,i]=(0,N.useState)([]),[o,s]=(0,N.useState)([]),[l,u]=(0,N.useState)(!0),[d,f]=(0,N.useState)(null),[p,h]=(0,N.useState)(null),[g,v]=(0,N.useState)(null),[y,b]=(0,N.useState)(``),x=(0,N.useCallback)(async()=>{try{let[{connectors:e},{agent_mcps:t}]=await Promise.all([C(),m()]);i(e),s(t),f(null)}catch(e){f(e instanceof Error?e.message:String(e))}finally{u(!1)}},[]);(0,N.useEffect)(()=>{x()},[x]);let S=e=>v(t=>t===e?null:e),w=(0,N.useCallback)(async e=>{try{let t=await _(e);i(n=>n.map(n=>n.id===e?t:n))}catch{x()}},[x]);I((0,N.useCallback)(t=>{t.reason===`disconnected`&&h(U(t.payload,e)),t.connectorId?w(t.connectorId):x()},[w,x,e]));let T=y.trim().toLowerCase(),D=t.filter(e=>!T||e.display_name.toLowerCase().includes(T)||e.description.toLowerCase().includes(T)),O=D.filter(e=>e.configured),k=D.filter(e=>!e.configured&&e.type===`oauth_pkce`),j=D.filter(e=>!e.configured&&e.type!==`oauth_pkce`),P=!t.some(e=>e.configured),F=e=>r(`div`,{className:`connectors-list`,children:e.map(e=>r(G,{connector:e,expanded:g===e.id,onToggle:()=>S(e.id),onChanged:()=>void w(e.id)},e.id))});return a(`section`,{className:`connectors-section`,"aria-label":e(`settings.section.connectors`),children:[r(`p`,{className:`settings-pane-lede`,children:e(`settings.connectors.lede`)}),d&&a(`div`,{className:`error-banner`,children:[r(E,{size:14}),r(`span`,{children:d})]}),p&&a(`div`,{className:`error-banner`,role:`status`,onClick:()=>h(null),children:[r(E,{size:14}),r(`span`,{children:p})]}),l?r(`div`,{className:`connectors-loading`,children:r(M,{size:16,className:`spin`})}):a(c.Fragment,{children:[t.length>V&&r(`input`,{className:`settings-input`,type:`search`,value:y,onChange:e=>b(e.target.value),placeholder:e(`settings.connectors.search`),"aria-label":e(`settings.connectors.search`)}),t.length===0&&!d&&r(`p`,{className:`settings-hint`,children:e(`settings.connectors.none`)}),T&&D.length===0&&r(`p`,{className:`settings-hint`,children:e(`settings.connectors.noMatch`)}),O.length>0&&r(A,{title:e(`settings.connectors.connected`),count:O.length,defaultOpen:!0,forceOpen:!!T,children:F(O)}),k.length>0&&r(A,{title:e(`settings.connectors.accounts`),hint:e(`settings.connectors.accountsHint`),count:k.length,defaultOpen:P,forceOpen:!!T,children:F(k)}),j.length>0&&r(A,{title:e(`settings.connectors.servers`),hint:e(`settings.connectors.serversHint`),count:j.length,forceOpen:!!T,children:F(j)}),o.length>0&&!T&&r(A,{title:e(`settings.connectors.agentServers`),count:o.length,children:r(X,{servers:o,expanded:g,onToggle:S})})]})]})}function G({connector:e,expanded:t,onToggle:i,onChanged:o}){let s=n();return a(`div`,{className:`connector-tile${t?` connector-tile--open`:``}`,children:[a(`div`,{className:`connector-tile-row`,children:[a(`button`,{type:`button`,className:`connector-tile-header`,onClick:i,"aria-expanded":t,children:[r(`bdi`,{className:`connector-tile-name`,children:e.display_name}),e.configured&&r(`span`,{className:`connector-tile-type`,children:e.type===`oauth_pkce`?`OAuth`:`MCP`}),e.configured?e.type===`mcp_server`&&e.enabled===!1?r(`span`,{className:`connector-status disabled`,children:s(`settings.connectors.disabled`)}):a(`span`,{className:`connector-status ok`,children:[r(T,{size:12}),e.account_id?r(`bdi`,{dir:`ltr`,children:e.account_id}):s(`settings.connectors.configured`)]}):e.configurable===!1?r(`span`,{className:`connector-status idle`,children:s(`settings.connectors.setupRequired`)}):null,r(`span`,{className:`connector-tile-chevron`,children:r(t?O:k,{size:14})})]}),r(R,{connector:e,onChanged:o})]}),t&&a(`div`,{className:`connector-detail`,children:[e.type===`oauth_pkce`?r(K,{connector:e,onChanged:o}):r(J,{connector:e,onChanged:o}),e.configured&&r(Q,{connectorId:e.id,connectorType:e.type})]})]})}function K({connector:e,onChanged:t}){let o=n(),[s,l]=(0,N.useState)(!1),[u,f]=(0,N.useState)(null),[m,h]=(0,N.useState)({}),[_,v]=(0,N.useState)(null),{agents:y}=i(),x=y.filter(t=>t.namespaced_agent_id&&t.required_connections?.some(t=>t.connector_id===e.id)),S=x.map(e=>e.namespaced_agent_id).join(`,`),[C,T]=(0,N.useState)(()=>new Set);(0,N.useEffect)(()=>{T(new Set(x.map(e=>e.namespaced_agent_id)))},[S]);let D=e=>T(t=>{let n=new Set(t);return n.has(e)?n.delete(e):n.add(e),n}),O=()=>[...C];(0,N.useEffect)(()=>{let e=()=>{t()};return window.addEventListener(`focus`,e),()=>window.removeEventListener(`focus`,e)},[t]);let k=e=>{let t=window;t.gaia?.openExternal?t.gaia.openExternal(e):window.open(e,`_blank`,`noopener`)},A=async()=>{l(!0),f(null);try{let t=await b(e.id,e.available_scopes?.length?e.available_scopes:e.default_scopes,O());k(t.authorization_url)}catch(e){f(e instanceof Error?e.message:String(e))}finally{l(!1)}},j=async()=>{l(!0),f(null),v(null);try{let t=await d(e.id,e.available_scopes?.length?e.available_scopes:e.default_scopes,O());v(t)}catch(e){f(e instanceof Error?e.message:String(e))}finally{l(!1)}};(0,N.useEffect)(()=>{e.configured&&v(null)},[e.configured]),I((0,N.useCallback)(t=>{t.connectorId===e.id&&(t.reason===`oauth_error`?(f(String(t.payload.error??o(`settings.connectors.deviceFailed`))),v(null)):t.reason===`oauth_completed`&&v(null))},[e.id,o]));let P=async()=>{l(!0),f(null);try{await p(e.id),t()}catch(e){f(e instanceof Error?e.message:String(e))}finally{l(!1)}},F=async()=>{let n=(e.oauth_setup_fields??[]).filter(e=>e.required!==!1&&!m[e.key]?.trim()).map(e=>e.label);if(n.length)f(o(`settings.connectors.required`,{fields:n.join(`, `)}));else{l(!0),f(null);try{let n=e.available_scopes?.length?e.available_scopes:e.default_scopes,r=await g(e.id,{...m,scopes:n,grant_agents:O()}),i=typeof r.authorization_url==`string`?r.authorization_url:null;i&&k(i),t()}catch(e){f(e instanceof Error?e.message:String(e))}finally{l(!1)}}},L=e.oauth_setup_fields??[],R=e.configurable===!1&&!e.configured&&L.length>0;return a(`div`,{className:`configure-body`,children:[e.description&&r(`p`,{className:`connector-desc`,children:r(`bdi`,{children:e.description})}),R&&a(`div`,{className:`oauth-setup-form`,children:[r(`p`,{className:`connector-desc`,children:o(`settings.connectors.firstSetup`)}),L.map(e=>a(`label`,{className:`oauth-setup-field`,children:[r(`span`,{className:`oauth-setup-label`,children:e.label}),r(`input`,{type:e.kind===`secret`?`password`:`text`,className:`oauth-setup-input`,placeholder:e.placeholder,value:m[e.key]??``,onChange:t=>h(n=>({...n,[e.key]:t.target.value})),autoComplete:`off`,spellCheck:!1}),e.help_md&&r(`span`,{className:`oauth-setup-help`,children:r(`bdi`,{children:e.help_md})})]},e.key))]}),!e.configured&&x.length>0&&a(`div`,{className:`oauth-grant-onconnect`,children:[r(`p`,{className:`oauth-grant-onconnect-label`,children:o(`settings.connectors.grantOnConnect`)}),x.map(e=>a(`label`,{className:`oauth-grant-onconnect-item`,children:[r(`input`,{type:`checkbox`,checked:C.has(e.namespaced_agent_id),onChange:()=>D(e.namespaced_agent_id)}),r(`span`,{children:e.name})]},e.namespaced_agent_id)),r(`p`,{className:`oauth-grant-onconnect-help`,children:o(`settings.connectors.grantLater`)})]}),!R&&r(q,{connector:e,onChanged:t}),u&&a(`div`,{className:`configure-error`,children:[r(E,{size:12}),` `,u]}),a(`div`,{className:`configure-actions`,children:[e.configured?r(`button`,{className:`btn-secondary`,disabled:s,onClick:()=>void P(),children:s?r(M,{size:12,className:`spin`}):o(`settings.connectors.disconnect`)}):R?r(`button`,{className:`btn-primary`,disabled:s,onClick:()=>void F(),children:s?r(M,{size:12,className:`spin`}):a(c.Fragment,{children:[r(w,{size:12}),` `,o(`settings.connectors.saveConnect`)]})}):e.configurable===!1?r(`span`,{className:`connector-setup-required`,title:e.config_error??void 0,children:o(`settings.connectors.setupRequired`)}):a(c.Fragment,{children:[r(`button`,{className:`btn-primary`,disabled:s||_!==null,onClick:()=>void A(),children:s?r(M,{size:12,className:`spin`}):a(c.Fragment,{children:[r(w,{size:12}),` `,o(`settings.key.connect`)]})}),e.supports_device_code&&r(`button`,{className:`btn-secondary`,disabled:s||_!==null,onClick:()=>void j(),title:o(`settings.connectors.codeTitle`),children:o(`settings.connectors.code`)})]}),(e.docs_url||e.product_url)&&a(`a`,{href:e.docs_url||e.product_url||`#`,target:`_blank`,rel:`noopener noreferrer`,className:`connector-product-link`,children:[o(`settings.connectors.learnMore`),` `,r(w,{size:11})]})]}),_&&!e.configured&&a(`div`,{className:`device-code-block`,children:[a(`p`,{className:`device-code-instructions`,children:[o(`settings.connectors.goTo`),` `,r(`a`,{href:_.verification_uri,target:`_blank`,rel:`noopener noreferrer`,onClick:e=>{e.preventDefault(),k(_.verification_uri)},children:_.verification_uri})]}),a(`div`,{className:`device-code-value`,children:[r(`code`,{children:_.user_code}),r(`button`,{type:`button`,className:`btn-secondary`,onClick:()=>void navigator.clipboard?.writeText(_.user_code),title:o(`settings.connectors.copyCode`),children:o(`gpu.copy`)})]}),a(`p`,{className:`device-code-waiting`,children:[r(M,{size:12,className:`spin`}),` `,o(`settings.connectors.waiting`)]}),r(`button`,{type:`button`,className:`btn-secondary`,onClick:()=>v(null),children:o(`settings.key.cancel`)})]})]})}function q({connector:e,onChanged:t}){let i=n(),[o,s]=(0,N.useState)(!1),[l,u]=(0,N.useState)({}),[d,f]=(0,N.useState)(!1),[p,m]=(0,N.useState)(!1),[h,_]=(0,N.useState)(null),v=e.oauth_setup_fields??[];if(v.length===0)return null;let y=e.oauth_client,b=y?.source===`keyring`?i(`settings.connectors.savedClient`,{id:y.client_id??``}):y?.source===`env`?i(`settings.connectors.envClient`,{id:y.client_id??``}):i(`settings.connectors.noClient`),x=async()=>{if(!l.client_id?.trim())_(i(`settings.connectors.clientRequired`));else{f(!0),_(null),m(!1);try{await g(e.id,{...Object.fromEntries(Object.entries(l).map(([e,t])=>[e,t.trim()])),save_only:!0}),m(!0),u({}),t(),setTimeout(()=>m(!1),2200)}catch(e){_(e instanceof Error?e.message:String(e))}finally{f(!1)}}};return a(`div`,{className:`oauth-client-editor`,children:[a(`button`,{type:`button`,className:`oauth-client-editor__toggle`,onClick:()=>s(e=>!e),"aria-expanded":o,children:[r(o?O:k,{size:12}),r(`span`,{children:i(`settings.connectors.client`)}),r(`span`,{className:`oauth-client-editor__status`,children:b})]}),o&&a(`div`,{className:`oauth-setup-form`,children:[r(`p`,{className:`connector-desc`,children:i(`settings.connectors.clientHelp`)}),v.map(e=>a(`label`,{className:`oauth-setup-field`,children:[r(`span`,{className:`oauth-setup-label`,children:e.label}),r(`input`,{type:e.kind===`secret`?`password`:`text`,className:`oauth-setup-input`,placeholder:e.kind===`secret`&&y?.source===`keyring`&&y.has_secret?`••••••••`:e.placeholder,value:l[e.key]??``,onChange:t=>u(n=>({...n,[e.key]:t.target.value})),autoComplete:`off`,spellCheck:!1}),e.help_md&&r(`span`,{className:`oauth-setup-help`,children:r(`bdi`,{children:e.help_md})})]},e.key)),h&&a(`div`,{className:`configure-error`,children:[r(E,{size:12}),` `,h]}),r(`div`,{className:`configure-actions`,children:r(`button`,{className:`btn-model-save${p?` saved`:``}`,disabled:d||!l.client_id?.trim(),onClick:()=>void x(),children:d?r(M,{size:12,className:`spin`}):p?a(c.Fragment,{children:[r(T,{size:12}),` `,i(`settings.advanced.saved`)]}):i(`settings.connectors.saveClient`)})})]})]})}function J({connector:e,onChanged:t}){let i=n(),[o,s]=(0,N.useState)(()=>Object.fromEntries(e.mcp_env_keys.map(e=>[e,``]))),[l,u]=(0,N.useState)(!1),[d,m]=(0,N.useState)(!1),[h,_]=(0,N.useState)(null);(0,N.useEffect)(()=>{s(Object.fromEntries(e.mcp_env_keys.map(e=>[e,``])))},[e.mcp_env_keys.join(`,`)]);let v=e.mcp_env_keys.length===0,b=Object.values(o).every(e=>e.trim()===``),x=async()=>{let n=Object.fromEntries(Object.entries(o).filter(([,e])=>e.trim()!==``));if(v||Object.keys(n).length!==0){u(!0),_(null),m(!1);try{await g(e.id,n),m(!0),t(),setTimeout(()=>m(!1),2200)}catch(e){_(e instanceof Error?e.message:String(e))}finally{u(!1)}}},S=async()=>{u(!0),_(null);try{await p(e.id),s(Object.fromEntries(e.mcp_env_keys.map(e=>[e,``]))),t()}catch(e){_(e instanceof Error?e.message:String(e))}finally{u(!1)}},C=async()=>{u(!0),_(null);try{e.enabled?await f(e.id):await y(e.id),t()}catch(e){_(e instanceof Error?e.message:String(e))}finally{u(!1)}};return a(`div`,{className:`configure-body`,children:[e.description&&r(`p`,{className:`connector-desc`,children:r(`bdi`,{children:e.description})}),h&&a(`div`,{className:`configure-error`,children:[r(E,{size:12}),` `,h]}),e.configured&&a(`div`,{className:`connector-toggle-row`,children:[r(`span`,{className:`connector-toggle-label`,children:i(`settings.connectors.active`)}),a(`span`,{className:`toggle-switch`,children:[r(`input`,{type:`checkbox`,checked:e.enabled!==!1,onChange:()=>void C(),disabled:l,"aria-label":e.enabled?i(`settings.connectors.disableServer`):i(`settings.connectors.enableServer`)}),r(`span`,{className:`toggle-track`})]})]}),e.configured&&e.enabled===!1&&r(`p`,{className:`connector-toggle-help`,children:i(`settings.connectors.disabledHelp`)}),e.mcp_env_keys.map(t=>a(`div`,{className:`mcp-key-row`,children:[r(`label`,{className:`mcp-key-label`,children:t}),r(`input`,{type:`password`,className:`mcp-key-input`,placeholder:e.configured?`••••••••`:i.bare(`settings.connectors.enterValue`),value:o[t]??``,onChange:e=>s(n=>({...n,[t]:e.target.value})),spellCheck:!1,autoComplete:`off`})]},t)),a(`div`,{className:`configure-actions`,children:[!(v&&e.configured)&&r(`button`,{className:`btn-model-save${d?` saved`:``}`,disabled:l||!v&&b,onClick:()=>void x(),children:l?r(M,{size:12,className:`spin`}):d?a(c.Fragment,{children:[r(T,{size:12}),` `,i(`settings.advanced.saved`)]}):i(v?`settings.key.connect`:`settings.advanced.save`)}),e.configured&&r(`button`,{className:`btn-secondary`,disabled:l,onClick:()=>void S(),children:i(`settings.connectors.disconnect`)}),e.product_url&&a(`a`,{href:e.product_url,target:`_blank`,rel:`noopener noreferrer`,className:`connector-product-link`,children:[i(`settings.connectors.docs`),` `,r(w,{size:11})]})]})]})}function Y({agent:e,connectorId:t,grantedScopes:i,onChanged:o}){let s=n(),c=e.required_connections?.find(e=>e.connector_id===t),l=e.namespaced_agent_id;if(!c||!l)return null;let[d,f]=(0,N.useState)(()=>new Set(i)),[p,m]=(0,N.useState)(null),[g,_]=(0,N.useState)(null);(0,N.useEffect)(()=>{f(new Set(i))},[i.join(`,`)]);let v=async e=>{if(p!==null)return;let n=new Set(d);n.has(e)?n.delete(e):n.add(e),f(n),m(e),_(null);try{n.size===0?await u(t,l):await h(t,l,[...n]),o()}catch(e){f(new Set(i)),_(e instanceof Error?e.message:String(e))}finally{m(null)}};return a(`div`,{className:`grant-agent-card`,children:[r(`bdi`,{className:`grant-agent-card-name`,children:e.name}),r(`div`,{className:`grant-scope-list`,children:c.scopes.map(e=>a(`label`,{className:`grant-scope-item`,children:[r(`span`,{className:`grant-scope-label`,children:B(e,s)}),a(`span`,{className:`toggle-switch`,children:[r(`input`,{type:`checkbox`,checked:d.has(e),onChange:()=>void v(e),disabled:p!==null}),r(`span`,{className:`toggle-track`})]})]},e))}),g&&a(`div`,{className:`grant-scope-warning grant-scope-warning--error`,children:[r(E,{size:11}),` `,g]})]})}function X({servers:e,expanded:t,onToggle:n}){return r(`div`,{className:`agent-mcps-section`,children:r(`div`,{className:`connectors-list`,children:e.map(e=>{let i=`${e.agent_id}::${e.server_name}`;return r(Z,{server:e,expanded:t===i,onToggle:()=>n(i)},i)})})})}function Z({server:e,expanded:t,onToggle:i}){let o=n(),s=[e.command,...e.args].join(` `);return a(`div`,{className:`agent-mcp-tile${t?` agent-mcp-tile--open`:``}`,children:[a(`button`,{type:`button`,className:`agent-mcp-tile-header`,onClick:i,"aria-expanded":t,children:[r(`span`,{className:`agent-mcp-server-name`,children:e.server_name}),r(`span`,{className:`agent-mcp-agent-label`,children:o(`settings.connectors.via`,{name:e.agent_name})}),e.disabled?r(`span`,{className:`agent-mcp-status disabled`,children:o(`settings.connectors.disabled`)}):a(`span`,{className:`agent-mcp-status enabled`,children:[r(T,{size:11}),` `,o(`settings.connectors.active`)]}),r(`span`,{className:`agent-mcp-readonly-badge`,children:o(`settings.connectors.readOnly`)}),r(`span`,{className:`agent-mcp-chevron`,children:r(t?O:k,{size:14})})]}),t&&a(`div`,{className:`agent-mcp-detail`,children:[s&&r(`bdi`,{dir:`ltr`,className:`agent-mcp-command-row`,children:s}),r(`bdi`,{dir:`ltr`,className:`agent-mcp-config-path`,children:e.config_path}),r(`div`,{className:`agent-mcp-config-hint`,children:o(`settings.connectors.editConfig`)})]})]})}function Q({connectorId:e,connectorType:t}){let o=n(),{agents:s}=i(),[u,d]=(0,N.useState)({}),[f,p]=(0,N.useState)({}),[m,h]=(0,N.useState)(!0),g=(0,N.useCallback)(async()=>{try{let[{grants:t},{activations:n}]=await Promise.all([S(e),l(e)]);d(t),p(n)}catch{d({}),p({})}finally{h(!1)}},[e]);if((0,N.useEffect)(()=>{g()},[g]),I((0,N.useCallback)(t=>{t.connectorId===e&&(t.reason===`grant_changed`||t.reason===`activation_changed`||t.reason===`disconnected`)&&g()},[e,g])),m)return null;let _=s.filter(t=>t.namespaced_agent_id&&t.required_connections?.some(t=>t.connector_id===e)),v=t===`mcp_server`?s.filter(t=>t.namespaced_agent_id&&(t.consumes_mcp_servers||t.required_connections?.some(t=>t.connector_id===e))):[];return a(`div`,{className:`connection-grants`,children:[r(`div`,{className:`grants-header`,children:o(`settings.connectors.grants`)}),_.length===0?r(`div`,{className:`grants-empty`,children:o(`settings.connectors.noGrants`)}):_.map(t=>r(Y,{agent:t,connectorId:e,grantedScopes:u[t.namespaced_agent_id]??[],onChanged:()=>void g()},t.namespaced_agent_id)),v.length>0&&a(c.Fragment,{children:[r(`div`,{className:`grants-header grants-header--activations`,children:o(`settings.connectors.activeFor`)}),r(`div`,{className:`grants-help`,children:o(`settings.connectors.activationHelp`)}),v.map(t=>r($,{agent:t,connectorId:e,active:!!f[t.namespaced_agent_id],grantedScopes:u[t.namespaced_agent_id]??[],onChanged:()=>void g()},`activation-${t.namespaced_agent_id}`))]})]})}function $({agent:e,connectorId:t,active:i,grantedScopes:o,onChanged:s}){let c=n(),l=e.required_connections?.find(e=>e.connector_id===t),u=e.namespaced_agent_id;if(!u)return null;let[d,f]=(0,N.useState)(i),[p,m]=(0,N.useState)(!1),[h,g]=(0,N.useState)(null);(0,N.useEffect)(()=>{f(i)},[i]);let _=async()=>{if(p)return;let e=!d;f(e),m(!0),g(null);try{if(e){let e=o.length===0?l?[...l.scopes]:[...H]:void 0;await v(t,u,e)}else await x(t,u);s()}catch(e){f(i),g(e instanceof Error?e.message:String(e))}finally{m(!1)}};return a(`div`,{className:`grant-agent-card`,children:[r(`bdi`,{className:`grant-agent-card-name`,children:e.name}),r(`div`,{className:`grant-scope-list`,children:a(`label`,{className:`grant-scope-item`,children:[r(`span`,{className:`grant-scope-label`,children:c(d?`settings.connectors.toolsVisible`:`settings.connectors.toolsHidden`)}),a(`span`,{className:`toggle-switch`,children:[r(`input`,{type:`checkbox`,checked:d,onChange:()=>void _(),disabled:p}),r(`span`,{className:`toggle-track`})]})]})}),h&&a(`div`,{className:`grant-scope-warning grant-scope-warning--error`,children:[r(E,{size:11}),` `,h]})]})}function ee(){let e=n();return a(`div`,{className:`settings-pane`,children:[r(`h2`,{className:`settings-pane-title`,children:e(`settings.section.connectors`)}),r(W,{})]})}export{ee as ConnectorsPane};
|