@0xmaxma/claude-gateway 2.0.4 → 2.0.5
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/README.md +10 -1
- package/dist/agent/builtin-commands.d.ts +1 -1
- package/dist/agent/builtin-commands.d.ts.map +1 -1
- package/dist/agent/builtin-commands.js +3 -2
- package/dist/agent/builtin-commands.js.map +1 -1
- package/dist/agent/runner.d.ts +109 -9
- package/dist/agent/runner.d.ts.map +1 -1
- package/dist/agent/runner.js +148 -119
- package/dist/agent/runner.js.map +1 -1
- package/dist/agent/skill-learning/index.d.ts.map +1 -1
- package/dist/agent/skill-learning/index.js +27 -8
- package/dist/agent/skill-learning/index.js.map +1 -1
- package/dist/agent/skill-learning/reviewer.d.ts +3 -1
- package/dist/agent/skill-learning/reviewer.d.ts.map +1 -1
- package/dist/agent/skill-learning/reviewer.js +6 -2
- package/dist/agent/skill-learning/reviewer.js.map +1 -1
- package/dist/agent/turn-stream.d.ts +3 -1
- package/dist/agent/turn-stream.d.ts.map +1 -1
- package/dist/agent/turn-stream.js +8 -4
- package/dist/agent/turn-stream.js.map +1 -1
- package/dist/api/gateway-router.d.ts +2 -0
- package/dist/api/gateway-router.d.ts.map +1 -1
- package/dist/api/gateway-router.js +229 -12
- package/dist/api/gateway-router.js.map +1 -1
- package/dist/api/router.js +11 -11
- package/dist/api/router.js.map +1 -1
- package/dist/api/slack-webhook-router.js +1 -1
- package/dist/api/slack-webhook-router.js.map +1 -1
- package/dist/api/voice-router.d.ts +1 -0
- package/dist/api/voice-router.d.ts.map +1 -1
- package/dist/api/voice-router.js +129 -7
- package/dist/api/voice-router.js.map +1 -1
- package/dist/config/claude-settings.d.ts +14 -0
- package/dist/config/claude-settings.d.ts.map +1 -1
- package/dist/config/claude-settings.js +20 -0
- package/dist/config/claude-settings.js.map +1 -1
- package/dist/orchestration/agent-cli-session.d.ts +46 -0
- package/dist/orchestration/agent-cli-session.d.ts.map +1 -0
- package/dist/orchestration/agent-cli-session.js +121 -0
- package/dist/orchestration/agent-cli-session.js.map +1 -0
- package/dist/orchestration/agent-tool-schemas.d.ts +6 -0
- package/dist/orchestration/agent-tool-schemas.d.ts.map +1 -0
- package/dist/orchestration/agent-tool-schemas.js +23 -0
- package/dist/orchestration/agent-tool-schemas.js.map +1 -0
- package/dist/orchestration/bridge.d.ts +6 -3
- package/dist/orchestration/bridge.d.ts.map +1 -1
- package/dist/orchestration/bridge.js +31 -14
- package/dist/orchestration/bridge.js.map +1 -1
- package/dist/orchestration/browser-voice.d.ts +14 -0
- package/dist/orchestration/browser-voice.d.ts.map +1 -0
- package/dist/orchestration/browser-voice.js +30 -0
- package/dist/orchestration/browser-voice.js.map +1 -0
- package/dist/orchestration/context-footprint.d.ts +14 -0
- package/dist/orchestration/context-footprint.d.ts.map +1 -0
- package/dist/orchestration/context-footprint.js +57 -0
- package/dist/orchestration/context-footprint.js.map +1 -0
- package/dist/orchestration/dashboard-reader-worker.d.ts +2 -0
- package/dist/orchestration/dashboard-reader-worker.d.ts.map +1 -0
- package/dist/orchestration/dashboard-reader-worker.js +155 -0
- package/dist/orchestration/dashboard-reader-worker.js.map +1 -0
- package/dist/orchestration/dashboard-reader.d.ts +15 -0
- package/dist/orchestration/dashboard-reader.d.ts.map +1 -0
- package/dist/orchestration/dashboard-reader.js +87 -0
- package/dist/orchestration/dashboard-reader.js.map +1 -0
- package/dist/orchestration/decision-context.d.ts +15 -0
- package/dist/orchestration/decision-context.d.ts.map +1 -0
- package/dist/orchestration/decision-context.js +57 -0
- package/dist/orchestration/decision-context.js.map +1 -0
- package/dist/orchestration/display-stream.d.ts +21 -2
- package/dist/orchestration/display-stream.d.ts.map +1 -1
- package/dist/orchestration/display-stream.js +61 -8
- package/dist/orchestration/display-stream.js.map +1 -1
- package/dist/orchestration/inference-errors.d.ts.map +1 -1
- package/dist/orchestration/inference-errors.js +19 -21
- package/dist/orchestration/inference-errors.js.map +1 -1
- package/dist/orchestration/mutation-recovery.d.ts +12 -0
- package/dist/orchestration/mutation-recovery.d.ts.map +1 -0
- package/dist/orchestration/mutation-recovery.js +41 -0
- package/dist/orchestration/mutation-recovery.js.map +1 -0
- package/dist/orchestration/native-compact.d.ts +5 -0
- package/dist/orchestration/native-compact.d.ts.map +1 -0
- package/dist/orchestration/native-compact.js +29 -0
- package/dist/orchestration/native-compact.js.map +1 -0
- package/dist/orchestration/notification-mailbox.d.ts +3 -1
- package/dist/orchestration/notification-mailbox.d.ts.map +1 -1
- package/dist/orchestration/notification-mailbox.js +4 -2
- package/dist/orchestration/notification-mailbox.js.map +1 -1
- package/dist/orchestration/process-turn.d.ts +15 -2
- package/dist/orchestration/process-turn.d.ts.map +1 -1
- package/dist/orchestration/process-turn.js +78 -14
- package/dist/orchestration/process-turn.js.map +1 -1
- package/dist/orchestration/progress-review.d.ts +8 -18
- package/dist/orchestration/progress-review.d.ts.map +1 -1
- package/dist/orchestration/progress-review.js +12 -14
- package/dist/orchestration/progress-review.js.map +1 -1
- package/dist/orchestration/provider-message.d.ts +7 -0
- package/dist/orchestration/provider-message.d.ts.map +1 -0
- package/dist/orchestration/provider-message.js +63 -0
- package/dist/orchestration/provider-message.js.map +1 -0
- package/dist/orchestration/response-errors.d.ts +6 -0
- package/dist/orchestration/response-errors.d.ts.map +1 -0
- package/dist/orchestration/response-errors.js +88 -0
- package/dist/orchestration/response-errors.js.map +1 -0
- package/dist/orchestration/response-schema.d.ts +33 -0
- package/dist/orchestration/response-schema.d.ts.map +1 -0
- package/dist/orchestration/response-schema.js +61 -0
- package/dist/orchestration/response-schema.js.map +1 -0
- package/dist/orchestration/runtime.d.ts +67 -0
- package/dist/orchestration/runtime.d.ts.map +1 -1
- package/dist/orchestration/runtime.js +266 -62
- package/dist/orchestration/runtime.js.map +1 -1
- package/dist/orchestration/skills.d.ts.map +1 -1
- package/dist/orchestration/skills.js +3 -2
- package/dist/orchestration/skills.js.map +1 -1
- package/dist/orchestration/source-policy.d.ts +1 -1
- package/dist/orchestration/source-policy.d.ts.map +1 -1
- package/dist/orchestration/source-policy.js +1 -1
- package/dist/orchestration/speech.d.ts +15 -17
- package/dist/orchestration/speech.d.ts.map +1 -1
- package/dist/orchestration/speech.js +90 -30
- package/dist/orchestration/speech.js.map +1 -1
- package/dist/orchestration/store.d.ts +2 -0
- package/dist/orchestration/store.d.ts.map +1 -1
- package/dist/orchestration/store.js +16 -1
- package/dist/orchestration/store.js.map +1 -1
- package/dist/orchestration/tasks/driver.d.ts.map +1 -1
- package/dist/orchestration/tasks/driver.js +8 -3
- package/dist/orchestration/tasks/driver.js.map +1 -1
- package/dist/orchestration/tasks/pool.d.ts.map +1 -1
- package/dist/orchestration/tasks/pool.js +8 -4
- package/dist/orchestration/tasks/pool.js.map +1 -1
- package/dist/orchestration/tasks/service.d.ts +48 -1
- package/dist/orchestration/tasks/service.d.ts.map +1 -1
- package/dist/orchestration/tasks/service.js +41 -17
- package/dist/orchestration/tasks/service.js.map +1 -1
- package/dist/orchestration/token-ledger.d.ts +125 -0
- package/dist/orchestration/token-ledger.d.ts.map +1 -0
- package/dist/orchestration/token-ledger.js +232 -0
- package/dist/orchestration/token-ledger.js.map +1 -0
- package/dist/orchestration/token-usage.d.ts +46 -0
- package/dist/orchestration/token-usage.d.ts.map +1 -0
- package/dist/orchestration/token-usage.js +102 -0
- package/dist/orchestration/token-usage.js.map +1 -0
- package/dist/orchestration/tool-activity.d.ts.map +1 -1
- package/dist/orchestration/tool-activity.js +5 -3
- package/dist/orchestration/tool-activity.js.map +1 -1
- package/dist/orchestration/tool-name.d.ts +10 -0
- package/dist/orchestration/tool-name.d.ts.map +1 -0
- package/dist/orchestration/tool-name.js +14 -0
- package/dist/orchestration/tool-name.js.map +1 -0
- package/dist/orchestration/transcript-checkpoint.d.ts +14 -0
- package/dist/orchestration/transcript-checkpoint.d.ts.map +1 -0
- package/dist/orchestration/transcript-checkpoint.js +83 -0
- package/dist/orchestration/transcript-checkpoint.js.map +1 -0
- package/dist/orchestration/unanswered-inputs.d.ts +6 -0
- package/dist/orchestration/unanswered-inputs.d.ts.map +1 -0
- package/dist/orchestration/unanswered-inputs.js +18 -0
- package/dist/orchestration/unanswered-inputs.js.map +1 -0
- package/dist/session/process.d.ts +10 -0
- package/dist/session/process.d.ts.map +1 -1
- package/dist/session/process.js +91 -9
- package/dist/session/process.js.map +1 -1
- package/dist/session/request-tool-capture.d.ts +31 -0
- package/dist/session/request-tool-capture.d.ts.map +1 -0
- package/dist/session/request-tool-capture.js +194 -0
- package/dist/session/request-tool-capture.js.map +1 -0
- package/dist/session/runtime-profile.d.ts +7 -3
- package/dist/session/runtime-profile.d.ts.map +1 -1
- package/dist/session/runtime-profile.js +3 -1
- package/dist/session/runtime-profile.js.map +1 -1
- package/dist/session/store.d.ts +7 -0
- package/dist/session/store.d.ts.map +1 -1
- package/dist/session/store.js +27 -0
- package/dist/session/store.js.map +1 -1
- package/dist/shell/tailer.d.ts +7 -5
- package/dist/shell/tailer.d.ts.map +1 -1
- package/dist/shell/tailer.js +6 -17
- package/dist/shell/tailer.js.map +1 -1
- package/dist/ui/cli-viewer-ui.js +1 -1
- package/dist/ui/dashboard-client.d.ts +3 -0
- package/dist/ui/dashboard-client.d.ts.map +1 -0
- package/dist/ui/dashboard-client.js +188 -0
- package/dist/ui/dashboard-client.js.map +1 -0
- package/dist/ui/dashboard-presentation.d.ts +9 -0
- package/dist/ui/dashboard-presentation.d.ts.map +1 -0
- package/dist/ui/dashboard-presentation.js +56 -0
- package/dist/ui/dashboard-presentation.js.map +1 -0
- package/dist/ui/dashboard-range.d.ts +5 -0
- package/dist/ui/dashboard-range.d.ts.map +1 -0
- package/dist/ui/dashboard-range.js +20 -0
- package/dist/ui/dashboard-range.js.map +1 -0
- package/dist/ui/dashboard-theme.d.ts +4 -0
- package/dist/ui/dashboard-theme.d.ts.map +1 -0
- package/dist/ui/dashboard-theme.js +485 -0
- package/dist/ui/dashboard-theme.js.map +1 -0
- package/dist/ui/token-report-client.d.ts +3 -0
- package/dist/ui/token-report-client.d.ts.map +1 -0
- package/dist/ui/token-report-client.js +34 -0
- package/dist/ui/token-report-client.js.map +1 -0
- package/dist/ui/token-report.d.ts +89 -0
- package/dist/ui/token-report.d.ts.map +1 -0
- package/dist/ui/token-report.js +200 -0
- package/dist/ui/token-report.js.map +1 -0
- package/dist/ui/web-ui.d.ts.map +1 -1
- package/dist/ui/web-ui.js +124 -181
- package/dist/ui/web-ui.js.map +1 -1
- package/dist/voice/replay.d.ts +8 -0
- package/dist/voice/replay.d.ts.map +1 -0
- package/dist/voice/replay.js +48 -0
- package/dist/voice/replay.js.map +1 -0
- package/dist/voice/session.d.ts +9 -0
- package/dist/voice/session.d.ts.map +1 -1
- package/dist/voice/session.js +72 -14
- package/dist/voice/session.js.map +1 -1
- package/mcp/lazy-connector.test.ts +58 -0
- package/mcp/lazy-connector.ts +67 -0
- package/mcp/lazy-tools.test.ts +152 -0
- package/mcp/lazy-tools.ts +41 -0
- package/mcp/server.ts +53 -34
- package/mcp/tools/discord/commands.ts +2 -0
- package/mcp/tools/tasks/module.ts +1 -12
- package/mcp/tools/telegram/receiver-server.ts +14 -14
- package/package.json +2 -1
- package/resource/dashboard/OFL.txt +93 -0
- package/resource/dashboard/poppins-300.woff2 +0 -0
- package/resource/dashboard/poppins-400.woff2 +0 -0
- package/resource/dashboard/poppins-500.woff2 +0 -0
- package/resource/dashboard/poppins-600.woff2 +0 -0
package/dist/ui/web-ui.js
CHANGED
|
@@ -2,13 +2,16 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.generateDashboardHtml = generateDashboardHtml;
|
|
4
4
|
exports.generateLoginHtml = generateLoginHtml;
|
|
5
|
+
const dashboard_range_1 = require("./dashboard-range");
|
|
6
|
+
const dashboard_theme_1 = require("./dashboard-theme");
|
|
7
|
+
const dashboard_client_1 = require("./dashboard-client");
|
|
5
8
|
/**
|
|
6
9
|
* Generates a self-contained HTML dashboard page for the gateway status UI.
|
|
7
10
|
* No external dependencies except xterm.js CDN for PTY viewer.
|
|
8
11
|
*/
|
|
9
12
|
function generateDashboardHtml() {
|
|
10
13
|
return `<!DOCTYPE html>
|
|
11
|
-
<html lang="en">
|
|
14
|
+
<html lang="en" data-theme="light">
|
|
12
15
|
<head>
|
|
13
16
|
<meta charset="UTF-8">
|
|
14
17
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
@@ -341,97 +344,78 @@ function generateDashboardHtml() {
|
|
|
341
344
|
.dream-accept-all:disabled { opacity: 0.55; cursor: default; }
|
|
342
345
|
/* Note detail — full-width card below the graph. Shows the whole file. */
|
|
343
346
|
.kb-note {
|
|
344
|
-
margin-top: 12px; background:
|
|
345
|
-
padding: 16px 18px; font-size: 0.85rem; color:
|
|
347
|
+
margin-top: 12px; background: var(--panel); border: 1px solid var(--line); border-radius: 8px;
|
|
348
|
+
padding: 16px 18px; font-size: 0.85rem; color: var(--text);
|
|
346
349
|
}
|
|
347
350
|
.kb-note-head { display: flex; align-items: flex-start; gap: 10px; }
|
|
348
|
-
.kb-note-head h3 { margin: 0; font-size: 1.02rem; color:
|
|
351
|
+
.kb-note-head h3 { margin: 0; font-size: 1.02rem; color: var(--text); flex: 1; word-break: break-word; }
|
|
349
352
|
.kb-note-close {
|
|
350
|
-
cursor: pointer; color:
|
|
353
|
+
cursor: pointer; color: var(--muted); background: var(--panel); border: 1px solid var(--line);
|
|
351
354
|
border-radius: 4px; padding: 1px 8px; font-size: 0.9rem; line-height: 1.4;
|
|
352
355
|
}
|
|
353
|
-
.kb-note-close:hover { color:
|
|
356
|
+
.kb-note-close:hover { color: var(--text); background: var(--line); }
|
|
354
357
|
/* Metadata chips row. */
|
|
355
358
|
.kb-note-meta { display: flex; flex-wrap: wrap; gap: 6px; margin: 10px 0 4px; }
|
|
356
359
|
.kb-note-chip {
|
|
357
|
-
display: inline-flex; align-items: center; gap: 5px; background:
|
|
358
|
-
border: 1px solid
|
|
360
|
+
display: inline-flex; align-items: center; gap: 5px; background: var(--raised);
|
|
361
|
+
border: 1px solid var(--line); border-radius: 999px; padding: 2px 10px; font-size: 0.72rem; color: var(--muted);
|
|
359
362
|
}
|
|
360
|
-
.kb-note-chip b { color:
|
|
363
|
+
.kb-note-chip b { color: var(--text); font-weight: 600; }
|
|
361
364
|
.kb-note-chip i { width: 8px; height: 8px; border-radius: 50%; display: inline-block; }
|
|
362
365
|
/* File path line under the chips — full width, monospace, wraps on long paths. */
|
|
363
366
|
.kb-note-path {
|
|
364
367
|
margin: 6px 0 2px; font-size: 0.72rem; font-family: ui-monospace, monospace;
|
|
365
|
-
color:
|
|
368
|
+
color: var(--muted); word-break: break-all;
|
|
366
369
|
}
|
|
367
|
-
.kb-note-path b { color:
|
|
370
|
+
.kb-note-path b { color: var(--muted); font-weight: 600; }
|
|
368
371
|
/* Rendered Markdown body. */
|
|
369
372
|
.kb-md {
|
|
370
|
-
margin-top: 12px; padding-top: 12px; border-top: 1px solid
|
|
371
|
-
line-height: 1.62; color:
|
|
373
|
+
margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--line);
|
|
374
|
+
line-height: 1.62; color: var(--text); word-break: break-word;
|
|
372
375
|
}
|
|
373
376
|
.kb-md > :first-child { margin-top: 0; }
|
|
374
|
-
.kb-md h1, .kb-md h2, .kb-md h3, .kb-md h4 { color:
|
|
375
|
-
.kb-md h1 { font-size: 1.25rem; border-bottom: 1px solid
|
|
376
|
-
.kb-md h2 { font-size: 1.1rem; border-bottom: 1px solid
|
|
377
|
-
.kb-md h3 { font-size: 1rem; } .kb-md h4 { font-size: 0.9rem; color:
|
|
377
|
+
.kb-md h1, .kb-md h2, .kb-md h3, .kb-md h4 { color: var(--text); line-height: 1.3; margin: 18px 0 8px; }
|
|
378
|
+
.kb-md h1 { font-size: 1.25rem; border-bottom: 1px solid var(--line); padding-bottom: 5px; }
|
|
379
|
+
.kb-md h2 { font-size: 1.1rem; border-bottom: 1px solid var(--line); padding-bottom: 4px; }
|
|
380
|
+
.kb-md h3 { font-size: 1rem; } .kb-md h4 { font-size: 0.9rem; color: var(--muted); }
|
|
378
381
|
.kb-md p { margin: 8px 0; }
|
|
379
382
|
.kb-md ul, .kb-md ol { margin: 8px 0; padding-left: 22px; }
|
|
380
383
|
.kb-md li { margin: 3px 0; }
|
|
381
|
-
.kb-md a { color:
|
|
384
|
+
.kb-md a { color: var(--accent); text-decoration: none; } .kb-md a:hover { text-decoration: underline; }
|
|
382
385
|
.kb-md code {
|
|
383
|
-
background:
|
|
384
|
-
padding: 1px 5px; font-size: 0.82em; font-family: ui-monospace, monospace; color:
|
|
386
|
+
background: var(--raised); border: 1px solid var(--line); border-radius: 4px;
|
|
387
|
+
padding: 1px 5px; font-size: 0.82em; font-family: ui-monospace, monospace; color: var(--text);
|
|
385
388
|
}
|
|
386
389
|
.kb-md pre {
|
|
387
|
-
background:
|
|
390
|
+
background: var(--raised); border: 1px solid var(--line); border-radius: 6px; padding: 10px 12px;
|
|
388
391
|
overflow-x: auto; margin: 10px 0;
|
|
389
392
|
}
|
|
390
393
|
.kb-md pre code { background: none; border: none; padding: 0; font-size: 0.8rem; line-height: 1.5; }
|
|
391
394
|
.kb-md blockquote {
|
|
392
|
-
margin: 10px 0; padding: 2px 14px; border-left: 3px solid
|
|
395
|
+
margin: 10px 0; padding: 2px 14px; border-left: 3px solid var(--line); color: var(--muted);
|
|
393
396
|
}
|
|
394
|
-
.kb-md hr { border: none; border-top: 1px solid
|
|
395
|
-
.kb-md strong { color:
|
|
396
|
-
.kb-md th, .kb-md td { border: 1px solid
|
|
397
|
-
.kb-md th { background:
|
|
398
|
-
.kb-md tbody tr:nth-child(even) { background:
|
|
397
|
+
.kb-md hr { border: none; border-top: 1px solid var(--line); margin: 14px 0; }
|
|
398
|
+
.kb-md strong { color: var(--text); } .kb-md table { border-collapse: collapse; margin: 0; width: 100%; font-size: 0.82rem; }
|
|
399
|
+
.kb-md th, .kb-md td { border: 1px solid var(--line); padding: 5px 10px; text-align: left; }
|
|
400
|
+
.kb-md th { background: var(--raised); color: var(--text); font-weight: 600; }
|
|
401
|
+
.kb-md tbody tr:nth-child(even) { background: var(--raised); }
|
|
399
402
|
/* Wide tables scroll horizontally instead of breaking the panel. */
|
|
400
403
|
.kb-table-wrap { overflow-x: auto; margin: 10px 0; border-radius: 6px; }
|
|
401
|
-
.kb-md del { color:
|
|
404
|
+
.kb-md del { color: var(--muted); }
|
|
402
405
|
/* Task-list items: bullet replaced by a real (disabled) checkbox. */
|
|
403
406
|
.kb-md li.kb-task { list-style: none; margin-left: -18px; }
|
|
404
|
-
.kb-md li.kb-task input { margin-right: 7px; vertical-align: middle; accent-color:
|
|
405
|
-
.kb-note-loading { color:
|
|
407
|
+
.kb-md li.kb-task input { margin-right: 7px; vertical-align: middle; accent-color: var(--accent); }
|
|
408
|
+
.kb-note-loading { color: var(--muted); font-size: 0.82rem; margin-top: 12px; }
|
|
409
|
+
${dashboard_theme_1.dashboardTheme}
|
|
406
410
|
</style>
|
|
407
|
-
</head>
|
|
408
|
-
<body>
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
<!-- Tab switcher: Sessions (live PTY + table) | Knowledge base (shared-KB graph) -->
|
|
417
|
-
<div class="tabs">
|
|
418
|
-
<button class="tab active" id="tab-sessions" data-view="view-sessions">Sessions</button>
|
|
419
|
-
<button class="tab" id="tab-kb" data-view="view-kb">Knowledge base</button>
|
|
420
|
-
<button class="tab" id="tab-dreams" data-view="view-dreams">Nightly dreaming</button>
|
|
421
|
-
</div>
|
|
422
|
-
|
|
423
|
-
<div id="view-sessions" class="view">
|
|
424
|
-
<!-- Row: Processes 70% | Agent badges 30% (collapses on narrow screens) -->
|
|
425
|
-
<div class="top-grid">
|
|
426
|
-
<div>
|
|
427
|
-
<h2>Processes</h2>
|
|
428
|
-
<div class="proc-tree" id="proc-tree">Loading...</div>
|
|
429
|
-
</div>
|
|
430
|
-
<div>
|
|
431
|
-
<h2>Agents</h2>
|
|
432
|
-
<div class="agents-bar" id="agents-bar"></div>
|
|
433
|
-
</div>
|
|
434
|
-
</div>
|
|
411
|
+
${dashboard_theme_1.dashboardFontLink}<script>try{document.documentElement.dataset.sidebarCollapsed=localStorage.getItem("gateway-sidebar-collapsed")==="true"?"true":"false";}catch{}</script></head>
|
|
412
|
+
<body><div class="layout"><aside class="sidebar" id="dashboard-sidebar"><div class="brand row" id="sidebar-brand" role="button" tabindex="0" aria-label="Collapse sidebar" aria-expanded="true" aria-controls="dashboard-sidebar"><div class="brandmark">✳</div><div>Claude Gateway<small>OPERATIONS CONSOLE</small></div></div><div class="navlabel">WORKSPACE</div><nav class="tabs" aria-label="Main navigation"><button class="tab active" id="tab-overview" data-view="view-overview"><svg class="icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M3 3h7v7H3zM14 3h7v4h-7zM14 11h7v10h-7zM3 14h7v7H3z"/></svg>Overview</button><button class="tab " id="tab-sessions" data-view="view-sessions"><svg class="icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M21 11a8 8 0 0 1-8 8H6l-4 3 1-7a8 8 0 1 1 18-4Z"/></svg>Conversations</button><button class="tab " id="tab-tasks" data-view="view-tasks"><svg class="icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M9 5h12M9 12h12M9 19h12M3 5l1 1 2-3M3 12l1 1 2-3M3 19l1 1 2-3"/></svg>Tasks</button><button class="tab " id="tab-usage" data-view="view-usage"><svg class="icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M4 20V10m8 10V4m8 16v-7"/></svg>Usage & tokens</button><button class="tab " id="tab-kb" data-view="view-kb"><svg class="icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M4 3h7v18H4zM14 3h7v18h-7zM7 7h1m9 0h1"/></svg>Knowledge base</button><button class="tab " id="tab-dreams" data-view="view-dreams"><svg class="icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M20 15A9 9 0 0 1 9 4 9 9 0 1 0 20 15Z"/></svg>Nightly dreaming</button><button class="tab " id="tab-system" data-view="view-system"><svg class="icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M3 4h18v6H3zM3 14h18v6H3zM6 7h1M6 17h1"/></svg>System</button></nav><div class="sidebarfoot"><div class="instance">Claude Gateway<br><span id="gateway-version"></span></div></div></aside><div class="main"><header class="topbar"><div class="row"><button id="dash-menu" class="mobilemenu" aria-label="Collapse sidebar" aria-expanded="true" aria-controls="dashboard-sidebar" title="Collapse sidebar"><svg class="icon" viewBox="0 0 24 24" aria-hidden="true"><rect x="3" y="4" width="18" height="16" rx="2"/><path d="M9 4v16"/></svg></button><h1 id="dash-current-view">Overview</h1></div><div id="top-right"><span id="refresh-indicator">Connecting…</span><button class="theme-toggle" id="dash-theme" aria-label="Toggle light and dark theme">◐</button><button id="logout-btn">Logout</button></div></header><main class="shell-content"><div class="meta">Uptime: <span id="uptime">—</span> · Started: <span id="started-at">—</span> · Updated: <span id="last-updated">—</span></div>
|
|
413
|
+
<div id="view-overview" class="view"><div class="heading" style="margin-top:24px"><div class="eyebrow">ONE WORKSPACE. EVERY CONVERSATION.</div><h1>Good work, <span class="gradient-title">in motion.</span></h1><p>Your agents, ongoing work, and what needs your attention.</p></div><div class="dash-grid" id="overview-stats"></div><div class="columns"><section class="dash-panel"><h2>Token activity</h2><p class="live-note">Today · UTC · Workers (violet) / Agent (blue)</p><div id="overview-chart"></div><p class="live-note">Recorded token volume, including cache. Not billing cost.</p></section><section class="dash-panel"><h2>Needs your attention</h2><div class="dash-mini-list" id="overview-attention"></div></section></div><section class="dash-panel"><h2>Agents</h2><div class="agents-bar" id="agents-bar"></div></section><section class="dash-panel"><h2>Active & recent work</h2><div id="overview-tasks"></div></section></div>
|
|
414
|
+
<div class="dash-filter"><input id="dash-search" type="search" aria-label="Filter displayed sessions" placeholder="Filter this page by session, chat or model…">${(0, dashboard_range_1.rangeButtons)("dash-scope", "24h")}<select id="dash-agent-filter" aria-label="Filter agent"><option value="">All agents</option></select></div><div class="dash-pager"><span data-dash-page></span><div class="row"><button data-dash-prev disabled>← Previous</button><button data-dash-next disabled>Next →</button></div></div>
|
|
415
|
+
<div id="view-tasks" class="view" style="display:none"><h2>Tasks & workers</h2><p id="tasks-scope" class="live-note"></p><div id="task-results"></div></div><div id="view-usage" class="view" style="display:none"><h2>Usage & tokens</h2><p class="live-note">Session totals include every recorded attempt, including retries. Missing measurements are shown as —. Open a report for input, cache write, cache read, output and per-turn details.</p><div id="usage-results"></div></div>
|
|
416
|
+
<div id="view-system" class="view" style="display:none">
|
|
417
|
+
<h2>Processes</h2>
|
|
418
|
+
<div class="proc-tree" id="proc-tree">Loading...</div>
|
|
435
419
|
|
|
436
420
|
<!-- PTY viewer — full width so the native 200-col terminal has room.
|
|
437
421
|
Placed above the Sessions table so the live mirror is the first thing
|
|
@@ -450,32 +434,7 @@ function generateDashboardHtml() {
|
|
|
450
434
|
<div id="pty-terminal" tabindex="0"></div>
|
|
451
435
|
</div>
|
|
452
436
|
|
|
453
|
-
|
|
454
|
-
<h2>Sessions</h2>
|
|
455
|
-
<div class="table-wrap">
|
|
456
|
-
<table id="sessions-table">
|
|
457
|
-
<thead>
|
|
458
|
-
<tr>
|
|
459
|
-
<th>Agent</th>
|
|
460
|
-
<th>Session ID</th>
|
|
461
|
-
<th>Chat ID</th>
|
|
462
|
-
<th>Source</th>
|
|
463
|
-
<th>Mode</th>
|
|
464
|
-
<th>Model</th>
|
|
465
|
-
<th>Tokens</th>
|
|
466
|
-
<th>Status</th>
|
|
467
|
-
<th>Uptime</th>
|
|
468
|
-
<th>Spawned</th>
|
|
469
|
-
<th>Shell</th>
|
|
470
|
-
</tr>
|
|
471
|
-
</thead>
|
|
472
|
-
<tbody id="sessions-tbody">
|
|
473
|
-
<tr><td colspan="11" class="ts">Loading...</td></tr>
|
|
474
|
-
</tbody>
|
|
475
|
-
</table>
|
|
476
|
-
</div>
|
|
477
|
-
</div><!-- /view-sessions -->
|
|
478
|
-
|
|
437
|
+
</div><div id="view-sessions" class="view" style="display:none"><h2>Conversations</h2><p class="live-note">Inspect a session for its Agent turns and Worker attempts. Inspect the tools used in each session and worker attempt.</p><div id="session-results"></div></div>
|
|
479
438
|
<!-- Knowledge base — a 3D force-directed graph over the shared vault / an agent's memory.
|
|
480
439
|
Zero external deps: the spherical layout + canvas render + rotation are hand-rolled. -->
|
|
481
440
|
<div id="view-kb" class="view" style="display:none;">
|
|
@@ -530,7 +489,7 @@ function generateDashboardHtml() {
|
|
|
530
489
|
<div id="dreams-empty" class="dreams-empty" style="display:none;"></div>
|
|
531
490
|
</div><!-- /view-dreams -->
|
|
532
491
|
|
|
533
|
-
<div id="error-msg" class="error" style="display:none;"></div>
|
|
492
|
+
<div id="error-msg" class="error" style="display:none;" role="status"></div><footer class="footer">Claude Gateway · Admin dashboard</footer></main></div></div><div id="dash-drawer-back" class="dash-drawer-back"><section id="dash-drawer" class="dash-drawer" role="dialog" aria-modal="true" aria-label="Recorded session and task details" tabindex="-1"></section></div>
|
|
534
493
|
|
|
535
494
|
<script src="https://cdn.jsdelivr.net/npm/@xterm/xterm@6.0.0/lib/xterm.min.js"
|
|
536
495
|
integrity="sha384-pELe6ZHtFxFcuYBq3gMkqvmnNIqUWnAYjBG5gThqQQCjWp8PJ/65MLK4lMIfEK1e" crossorigin="anonymous"></script>
|
|
@@ -540,7 +499,7 @@ function generateDashboardHtml() {
|
|
|
540
499
|
// page (nothing for view-source/XSS to steal). If any read returns 401 the
|
|
541
500
|
// session has expired or is missing, so bounce to /dashboard (login page).
|
|
542
501
|
function onUnauthorized() {
|
|
543
|
-
window.location.
|
|
502
|
+
window.location.reload();
|
|
544
503
|
}
|
|
545
504
|
|
|
546
505
|
// Must match the server PTY size (src/shell/screen.ts ScreenModel defaults).
|
|
@@ -861,7 +820,7 @@ function generateDashboardHtml() {
|
|
|
861
820
|
|
|
862
821
|
const expandedSessionRows = new Set();
|
|
863
822
|
// Event delegation for Live buttons (avoids inline onclick + HTML injection)
|
|
864
|
-
document.getElementById('
|
|
823
|
+
document.getElementById('session-results').addEventListener('click', function(e) {
|
|
865
824
|
const toggle = e.target.closest('.btn-workers');
|
|
866
825
|
if (toggle) {
|
|
867
826
|
const key=toggle.getAttribute('data-expand-key'), open=!expandedSessionRows.has(key);
|
|
@@ -871,8 +830,8 @@ function generateDashboardHtml() {
|
|
|
871
830
|
const detail=document.getElementById(toggle.getAttribute('aria-controls'));if(detail)detail.hidden=!open;
|
|
872
831
|
return;
|
|
873
832
|
}
|
|
874
|
-
const btn = e.target.closest('.btn-stream');
|
|
875
|
-
if (btn) void openPtyViewer(btn.getAttribute('data-agent-id'), btn.getAttribute('data-session-id'));
|
|
833
|
+
const btn = e.target.closest('button.btn-stream[data-agent-id][data-session-id]');
|
|
834
|
+
if (btn) { document.getElementById('tab-system').click(); void openPtyViewer(btn.getAttribute('data-agent-id'), btn.getAttribute('data-session-id')); }
|
|
876
835
|
});
|
|
877
836
|
|
|
878
837
|
function escHtml(s) {
|
|
@@ -916,22 +875,25 @@ function generateDashboardHtml() {
|
|
|
916
875
|
|
|
917
876
|
// Format a context-window token count compactly: 1234 -> "1.2k", 45000 -> "45k".
|
|
918
877
|
// Full value is kept in the tooltip. 0/unknown renders as a dash.
|
|
878
|
+
function toolInventory(loaded, used, contextTools) {
|
|
879
|
+
function list(label, names) {
|
|
880
|
+
return '<div title="'+(Array.isArray(names)?escHtml(names.join(', ')||'None'):'Not recorded')+'">'+label+': '+(Array.isArray(names)?compactNumber(names.length):'—')+'</div>';
|
|
881
|
+
}
|
|
882
|
+
return list('Loaded', contextTools)+list('Used', used);
|
|
883
|
+
}
|
|
884
|
+
|
|
885
|
+
function fmtRecordedTokens(n) {
|
|
886
|
+
return n == null ? '—' : n === 0 ? '0' : fmtTokens(n);
|
|
887
|
+
}
|
|
888
|
+
|
|
919
889
|
function fmtTokens(n) {
|
|
920
890
|
const v = Number(n) || 0;
|
|
921
891
|
if (v <= 0) return '<span class="ts">—</span>';
|
|
922
|
-
const label =
|
|
892
|
+
const label = compactNumber(v);
|
|
923
893
|
return '<span title="' + v.toLocaleString() + ' tokens">' + label + '</span>';
|
|
924
894
|
}
|
|
925
895
|
|
|
926
|
-
|
|
927
|
-
async function refresh() {
|
|
928
|
-
document.getElementById('refresh-indicator').textContent = 'refreshing...';
|
|
929
|
-
try {
|
|
930
|
-
const res = await fetch(apiUrl('/status'));
|
|
931
|
-
if (res.status === 401) { onUnauthorized(); return; }
|
|
932
|
-
if (!res.ok) throw new Error('HTTP ' + res.status);
|
|
933
|
-
const data = await res.json();
|
|
934
|
-
|
|
896
|
+
function applyDashboardSnapshot(data) {
|
|
935
897
|
document.getElementById('uptime').textContent = fmtUptime(data.uptime || 0);
|
|
936
898
|
document.getElementById('started-at').textContent = data.startedAt
|
|
937
899
|
? new Date(data.startedAt).toLocaleString() : '\\u2014';
|
|
@@ -949,70 +911,33 @@ function generateDashboardHtml() {
|
|
|
949
911
|
const badges = agents.map(function(a) {
|
|
950
912
|
const ok = a.hasChannel ? a.isRunning : true;
|
|
951
913
|
const dot = ok ? '<span class="dot-green">●</span>' : '<span class="dot-red">●</span>';
|
|
952
|
-
return
|
|
914
|
+
return agentBadge(a.id);
|
|
953
915
|
});
|
|
954
916
|
document.getElementById('agents-bar').innerHTML = badges.join('') || '<span class="ts">No agents</span>';
|
|
955
917
|
|
|
956
|
-
|
|
957
|
-
// all agents; agents with no session do not produce a row.
|
|
958
|
-
const rows = [];
|
|
959
|
-
agents.forEach(function(a) {
|
|
960
|
-
(a.sessions || []).forEach(function(s) {
|
|
961
|
-
const statusBadge = s.orchestration ? '<span class="badge '+(['thinking','working'].includes(s.status) ? 'badge-green' : 'badge-gray')+'">'+escHtml(s.status)+'</span>' : s.isRunning
|
|
962
|
-
? '<span class="badge badge-green">running</span>'
|
|
963
|
-
: '<span class="badge badge-gray">stopped</span>';
|
|
964
|
-
const uptime = s.isRunning ? fmtUptime(s.uptimeSec || 0) : '<span class="ts">—</span>';
|
|
965
|
-
const sessId = s.sessionId
|
|
966
|
-
? '<span class="session-id">' + escHtml(s.sessionId) + '</span>'
|
|
967
|
-
: '<span class="ts">—</span>';
|
|
968
|
-
const chatCell = s.chatId
|
|
969
|
-
? '<span class="session-id">' + escHtml(String(s.chatId)) + '</span>'
|
|
970
|
-
: '<span class="ts">—</span>';
|
|
971
|
-
const liveBtn = (s.hasPtyStream && s.isRunning && s.mode === 'pty-shell')
|
|
972
|
-
? '<button class="btn-stream" data-agent-id="' + escHtml(a.id) + '" data-session-id="' + escHtml(s.sessionId || '') + '">💻 View</button>'
|
|
973
|
-
: '<span class="ts">—</span>';
|
|
974
|
-
const key=a.id+':'+s.sessionId, detailId='workers-'+encodeURIComponent(key), open=expandedSessionRows.has(key);
|
|
975
|
-
const childTasks=s.tasks||[], count=childTasks.length;
|
|
976
|
-
const label='Workers / tasks ('+count+')';
|
|
977
|
-
const expand=s.orchestration ? '<br><button class="btn-stream btn-workers" data-expand-key="'+escHtml(key)+'" data-label="'+escHtml(label)+'" aria-expanded="'+open+'" aria-controls="'+escHtml(detailId)+'">'+(open?'▾ ':'▸ ')+escHtml(label)+'</button>' : '';
|
|
978
|
-
rows.push(
|
|
979
|
-
'<tr class="session-row" data-agent="'+escHtml(a.id)+'" data-session="'+escHtml(s.sessionId)+'">' +
|
|
980
|
-
'<td><span style="color:#90cdf4;font-weight:600;">' + escHtml(a.id) + '</span></td>' +
|
|
981
|
-
'<td>' + sessId + expand + '</td>' +
|
|
982
|
-
'<td>' + chatCell + '</td>' +
|
|
983
|
-
'<td>' + sourceBadge(s.source) + '</td>' +
|
|
984
|
-
'<td><div class="session-modes">' + (s.orchestration ? '<span class="badge badge-purple">orchestration</span>' : '') + modeBadge(s.mode) + '</div></td>' +
|
|
985
|
-
'<td>' + fmtModel(s.model) + '</td>' +
|
|
986
|
-
'<td>' + fmtTokens(s.tokens) + '</td>' +
|
|
987
|
-
'<td>' + statusBadge + '</td>' +
|
|
988
|
-
'<td>' + uptime + '</td>' +
|
|
989
|
-
'<td>' + fmtTs(s.spawnedAt ? new Date(s.spawnedAt).toISOString() : null) + '</td>' +
|
|
990
|
-
'<td>' + liveBtn + '</td>' +
|
|
991
|
-
'</tr>'
|
|
992
|
-
);
|
|
993
|
-
if (s.orchestration) {
|
|
994
|
-
const pool=a.orchestration.workerPool, slots=pool ? pool.workers.filter(w => (s.workerIds||[]).includes(w.workerId)) : [];
|
|
995
|
-
let content='<div style="padding:12px 20px;border-left:3px solid #805ad5"><div class="ts">'+escHtml(a.orchestration.workspaceMode)+(a.container ? ' · '+escHtml(a.container) : '')+(pool ? ' · Agent pool '+pool.workers.length+'/'+pool.maxWorkers+' · idle TTL '+Math.round(pool.idleTtlMs/60000)+' min' : '')+'</div>';
|
|
996
|
-
slots.forEach(function(w){content+='<div class="worker-slot">'+escHtml(w.state)+' · Worker '+escHtml(w.workerId)+' · session '+escHtml(w.sessionId)+(w.expiresAt ? ' · expires '+escHtml(new Date(w.expiresAt).toLocaleTimeString()) : '')+'</div>';});
|
|
997
|
-
if (count) {
|
|
998
|
-
content+='<table class="worker-tasks"><thead><tr><th>Worker / Session</th><th>Task</th><th>Status</th><th>Tool</th><th>Process</th></tr></thead><tbody>';
|
|
999
|
-
childTasks.forEach(function(t){content+='<tr data-task="'+escHtml(t.taskId)+'"><td>'+escHtml(t.workerId||'Unassigned')+'<br><span class="ts">'+escHtml(t.workerSessionId||'')+(t.resumed?' · resumed':'')+'</span></td><td>'+escHtml(t.title)+'<br><span class="ts">'+escHtml(t.taskId)+(t.continueTaskId?' · follows '+escHtml(t.continueTaskId):'')+'</span></td><td>'+escHtml(t.state)+'</td><td>'+escHtml(t.lastTool ? t.lastTool.name+' · '+t.lastTool.type+(t.lastTool.is_error?' (error)':'') : '—')+'</td><td>'+escHtml(t.hostProcessId ? String(t.hostProcessId)+(t.container?' (docker exec)':'') : '—')+'</td></tr>';});
|
|
1000
|
-
content+='</tbody></table>';
|
|
1001
|
-
} else content+='<div class="ts">No worker tasks in this session</div>';
|
|
1002
|
-
rows.push('<tr class="session-workers" id="'+escHtml(detailId)+'"'+(open?'':' hidden')+'><td colspan="11">'+content+'</div></td></tr>');
|
|
1003
|
-
}
|
|
1004
|
-
});
|
|
1005
|
-
});
|
|
918
|
+
renderDashboard(data);
|
|
1006
919
|
|
|
1007
|
-
document.getElementById('
|
|
1008
|
-
|
|
920
|
+
document.getElementById('refresh-indicator').textContent = 'Live · updated';
|
|
921
|
+
}
|
|
1009
922
|
|
|
1010
|
-
|
|
923
|
+
// ── Status Refresh ────────────────────────────────────────────────────────
|
|
924
|
+
async function refresh() {
|
|
925
|
+
if (dashboardBusy || document.hidden) return;
|
|
926
|
+
dashboardBusy = true;
|
|
927
|
+
const requestedOffset = dashboardOffset, requestedScope = dashboardScope;
|
|
928
|
+
document.getElementById('refresh-indicator').textContent = 'Updating…';
|
|
929
|
+
try {
|
|
930
|
+
const res = await fetch(apiUrl('/status')+'?offset='+requestedOffset+'&scope='+requestedScope);
|
|
931
|
+
if (res.status === 401) { onUnauthorized(); return; }
|
|
932
|
+
if (!res.ok) throw new Error('HTTP ' + res.status);
|
|
933
|
+
const data = await res.json();
|
|
934
|
+
|
|
935
|
+
if (requestedOffset === dashboardOffset && requestedScope === dashboardScope) applyDashboardSnapshot(data);
|
|
1011
936
|
} catch(e) {
|
|
1012
937
|
document.getElementById('error-msg').textContent = 'Error fetching status: ' + e.message;
|
|
1013
938
|
document.getElementById('error-msg').style.display = 'block';
|
|
1014
|
-
document.getElementById('refresh-indicator').textContent = '
|
|
1015
|
-
}
|
|
939
|
+
document.getElementById('refresh-indicator').textContent = 'Reconnecting…';
|
|
940
|
+
} finally {dashboardBusy=false;}
|
|
1016
941
|
}
|
|
1017
942
|
|
|
1018
943
|
// ── Process Tree ─────────────────────────────────────────────────────────
|
|
@@ -1166,14 +1091,15 @@ function generateDashboardHtml() {
|
|
|
1166
1091
|
try {
|
|
1167
1092
|
await fetch(apiUrl('/dashboard/logout'), { method: 'POST' });
|
|
1168
1093
|
} catch (e) { /* best-effort; navigate regardless */ }
|
|
1169
|
-
window.location.
|
|
1094
|
+
window.location.reload();
|
|
1170
1095
|
});
|
|
1171
1096
|
|
|
1097
|
+
${dashboard_client_1.dashboardClient}
|
|
1172
1098
|
refresh();
|
|
1173
|
-
|
|
1174
|
-
setInterval(refresh,
|
|
1175
|
-
|
|
1176
|
-
|
|
1099
|
+
connectDashboardStream();
|
|
1100
|
+
setInterval(function(){if(!dashboardStream || dashboardStream.readyState!==1)refresh();},15000);
|
|
1101
|
+
setInterval(function(){if(!document.hidden && document.getElementById('view-system').style.display!=='none')refreshProcesses();},10000);
|
|
1102
|
+
document.addEventListener('visibilitychange',function(){if(document.hidden){dashboardStream?.close();dashboardStream=null;}else{refresh();connectDashboardStream();}});
|
|
1177
1103
|
</script>
|
|
1178
1104
|
|
|
1179
1105
|
<!-- Knowledge base graph: tab switching + hand-rolled force-directed renderer.
|
|
@@ -1400,7 +1326,11 @@ function generateDashboardHtml() {
|
|
|
1400
1326
|
// Labels: hubs always; hovered / selected / search-hit reveal on demand.
|
|
1401
1327
|
var showLabel = (o.deg >= LABEL_MIN_DEG) || isHov || isSel || (searching && o.hit);
|
|
1402
1328
|
if (showLabel && !dim){
|
|
1403
|
-
|
|
1329
|
+
// White, not var(--text): .kb-stage paints a fixed deep-space backdrop in BOTH
|
|
1330
|
+
// themes, but --text flips to near-black under the light theme (the page default),
|
|
1331
|
+
// which left labels unreadable on the dark canvas. Matches the white the hover /
|
|
1332
|
+
// selection rings above already use.
|
|
1333
|
+
ctx.fillStyle = '#fff';
|
|
1404
1334
|
ctx.font = (isHov || isSel ? '12px ' : '11px ') + 'ui-sans-serif, system-ui, sans-serif';
|
|
1405
1335
|
ctx.fillText(nd.title, p.sx + p.r + 4, p.sy + 3);
|
|
1406
1336
|
}
|
|
@@ -1530,7 +1460,7 @@ function generateDashboardHtml() {
|
|
|
1530
1460
|
o.hit = hay.indexOf(q) >= 0;
|
|
1531
1461
|
if (o.hit) hits.push(o);
|
|
1532
1462
|
});
|
|
1533
|
-
if (elSearchCount) elSearchCount.textContent = hits.length + ' / ' + G.nodes.length;
|
|
1463
|
+
if (elSearchCount) elSearchCount.textContent = compactNumber(hits.length) + ' / ' + compactNumber(G.nodes.length);
|
|
1534
1464
|
invalidate();
|
|
1535
1465
|
return hits;
|
|
1536
1466
|
}
|
|
@@ -1812,7 +1742,7 @@ function generateDashboardHtml() {
|
|
|
1812
1742
|
sourceSel.textContent = '';
|
|
1813
1743
|
(data.sources || [{ id: 'shared', label: 'Shared Knowledge Base', count: 0 }]).forEach(function(s){
|
|
1814
1744
|
var o = document.createElement('option');
|
|
1815
|
-
o.value = s.id; o.textContent = s.label + (typeof s.count === 'number' ? ' (' + s.count + ')' : '');
|
|
1745
|
+
o.value = s.id; o.textContent = s.label + (typeof s.count === 'number' ? ' (' + compactNumber(s.count) + ')' : '');
|
|
1816
1746
|
sourceSel.appendChild(o);
|
|
1817
1747
|
});
|
|
1818
1748
|
// Restore prior selection if it still exists, else fall back to Shared KB.
|
|
@@ -1855,7 +1785,7 @@ function generateDashboardHtml() {
|
|
|
1855
1785
|
}
|
|
1856
1786
|
buildModel(data);
|
|
1857
1787
|
renderLegend();
|
|
1858
|
-
elStats.textContent = data.nodes.length + ' notes, ' + data.edges.length + ' links';
|
|
1788
|
+
elStats.textContent = compactNumber(data.nodes.length) + ' notes, ' + compactNumber(data.edges.length) + ' links';
|
|
1859
1789
|
}).catch(function(err){
|
|
1860
1790
|
elStats.textContent = ''; elEmpty.textContent = 'Failed to load graph: ' + err.message; elEmpty.style.display = '';
|
|
1861
1791
|
});
|
|
@@ -1938,11 +1868,11 @@ function generateDashboardHtml() {
|
|
|
1938
1868
|
function renderRun(run){
|
|
1939
1869
|
var box = el('div', 'dream-run');
|
|
1940
1870
|
var head = el('div', 'dream-run-head');
|
|
1941
|
-
if (run.agent)
|
|
1871
|
+
if (run.agent) { var agentEl=el('span'); agentEl.innerHTML=agentBadge(run.agent); head.appendChild(agentEl); }
|
|
1942
1872
|
var modeCls = run.mode === 'auto' ? 'auto' : 'propose';
|
|
1943
1873
|
head.appendChild(el('span', 'dream-badge ' + modeCls, run.mode));
|
|
1944
1874
|
head.appendChild(el('span', 'dream-badge outcome', run.outcome));
|
|
1945
|
-
head.appendChild(el('span', 'when', run.iso));
|
|
1875
|
+
head.appendChild(el('span', 'when', new Date(run.iso).toLocaleString()));
|
|
1946
1876
|
|
|
1947
1877
|
// Pending = a propose-run proposal not yet manually accepted. Accept-all
|
|
1948
1878
|
// shows only when there is something to apply.
|
|
@@ -1994,13 +1924,14 @@ function generateDashboardHtml() {
|
|
|
1994
1924
|
}
|
|
1995
1925
|
|
|
1996
1926
|
var applied = (run.applied != null) ? (', applied ' + run.applied) : '';
|
|
1997
|
-
box.appendChild(el('div', 'dream-meta', 'tokens ' + (run.tokens||0) + ' · sessions ' + (run.sessions||0) + applied));
|
|
1927
|
+
box.appendChild(el('div', 'dream-meta', 'tokens ' + compactNumber(run.tokens||0) + ' · sessions ' + compactNumber(run.sessions||0) + applied));
|
|
1998
1928
|
return box;
|
|
1999
1929
|
}
|
|
2000
1930
|
|
|
2001
1931
|
function render(){
|
|
2002
1932
|
var filter = agentSel ? agentSel.value : '';
|
|
2003
1933
|
var runs = filter ? allRuns.filter(function(r){ return r.agent === filter; }) : allRuns;
|
|
1934
|
+
runs=runs.filter(function(r){return Date.parse(r.iso)>=dashboardSince(dashboardScope);}).sort(function(a,b){return Date.parse(b.iso)-Date.parse(a.iso);});
|
|
2004
1935
|
listEl.textContent = '';
|
|
2005
1936
|
if (!runs.length){
|
|
2006
1937
|
emptyEl.textContent = allRuns.length ? 'No dream runs for this agent.' : 'No dream runs yet. The nightly dreaming pass writes here after it first runs (auto or propose mode).';
|
|
@@ -2014,8 +1945,8 @@ function generateDashboardHtml() {
|
|
|
2014
1945
|
if (r.mode === 'auto') return;
|
|
2015
1946
|
(r.proposals || []).forEach(function(p){ if (!p.accepted) pendingTotal++; });
|
|
2016
1947
|
});
|
|
2017
|
-
statsEl.textContent = runs.length + ' run' + (runs.length === 1 ? '' : 's')
|
|
2018
|
-
+ (pendingTotal ? ' · ' + pendingTotal + ' pending' : '');
|
|
1948
|
+
statsEl.textContent = compactNumber(runs.length) + ' run' + (runs.length === 1 ? '' : 's')
|
|
1949
|
+
+ (pendingTotal ? ' · ' + compactNumber(pendingTotal) + ' pending' : '');
|
|
2019
1950
|
if (pendingNotice){
|
|
2020
1951
|
statsEl.textContent += ' — ' + pendingNotice;
|
|
2021
1952
|
pendingNotice = '';
|
|
@@ -2072,15 +2003,15 @@ function generateLoginHtml(disabledReason = '') {
|
|
|
2072
2003
|
? ` <h1>Claude Gateway</h1>
|
|
2073
2004
|
<div class="sub">${safeReason}</div>`
|
|
2074
2005
|
: ` <h1>Claude Gateway</h1>
|
|
2075
|
-
<div class="sub">
|
|
2006
|
+
<div class="sub">Sign in with your admin API key to inspect agents, workers and usage.</div>
|
|
2076
2007
|
<form id="login-form" autocomplete="off">
|
|
2077
|
-
<label for="key">API key</label>
|
|
2078
|
-
<input id="key" type="password" placeholder="
|
|
2008
|
+
<label for="key">Admin API key</label>
|
|
2009
|
+
<input id="key" type="password" placeholder="Enter your admin API key" required autocomplete="current-password" autofocus>
|
|
2079
2010
|
<button type="submit">Sign in</button>
|
|
2080
|
-
<div id="err"></div>
|
|
2011
|
+
<div id="err" role="alert" aria-live="polite"></div>
|
|
2081
2012
|
</form>`;
|
|
2082
2013
|
return `<!DOCTYPE html>
|
|
2083
|
-
<html lang="en">
|
|
2014
|
+
<html lang="en" data-theme="light">
|
|
2084
2015
|
<head>
|
|
2085
2016
|
<meta charset="UTF-8">
|
|
2086
2017
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
@@ -2110,12 +2041,12 @@ function generateLoginHtml(disabledReason = '') {
|
|
|
2110
2041
|
}
|
|
2111
2042
|
button:hover { background: #2b6cb0; }
|
|
2112
2043
|
#err { color: #fc8181; font-size: 0.8rem; margin-top: 12px; min-height: 1em; }
|
|
2044
|
+
${dashboard_theme_1.dashboardTheme}
|
|
2045
|
+
body{display:grid;place-items:center;min-height:100vh;padding:24px;background:var(--bg)}.login-layout{display:grid;grid-template-columns:1fr 1fr;width:min(980px,100%);background:var(--panel);border:1px solid var(--line);border-radius:28px;overflow:hidden;box-shadow:var(--shadow)}.login-intro{padding:48px;background:var(--lavender);display:flex;flex-direction:column;justify-content:space-between;gap:48px}.login-intro h2{font-size:36px;font-weight:400;line-height:1.25;color:var(--text);margin:0 0 20px}.login-intro p{font-size:13px;line-height:1.8;color:var(--muted)}.login-card{padding:52px 40px;align-self:center}.login-card h1{font-size:26px;margin-bottom:16px}.login-card .sub{color:var(--muted);font-size:13px;line-height:1.7;margin-bottom:28px}.login-card label{color:var(--text);font-size:12px;margin-bottom:10px}.login-card input{background:var(--panel);border-color:var(--line);padding:13px;font-size:13px}.login-card button{border-radius:160px;background:#6161ff;padding:13px;color:white;font-size:13px}.login-card button:disabled{opacity:.6}#err{color:var(--yellow);font-size:12px;line-height:1.6}.login-caption{font-size:11px;color:var(--muted);margin-top:22px;line-height:1.7}@media(max-width:760px){.login-layout{grid-template-columns:1fr;max-width:440px}.login-intro{padding:28px;gap:24px}.login-intro h2{font-size:28px}.login-card{padding:30px 26px}.login-intro .login-description{display:none}}
|
|
2113
2046
|
</style>
|
|
2114
|
-
</head>
|
|
2047
|
+
${dashboard_theme_1.dashboardFontLink}</head>
|
|
2115
2048
|
<body>
|
|
2116
|
-
<div class="card">
|
|
2117
|
-
${bodyInner}
|
|
2118
|
-
</div>
|
|
2049
|
+
<main class="login-layout"><section class="login-intro"><div class="brand row" style="padding:0"><div class="brandmark">✳</div>Claude Gateway</div><div><h2>Your agents.<br>Your workspace.</h2><p class="login-description">A clear view of conversations, worker activity and token usage. All in one place.</p></div><p>Orchestration · Voice · Multi-channel</p></section><section class="login-card">${bodyInner}<p class="login-caption">Admin access only. Your key is exchanged for a secure session cookie and is not saved in browser storage.</p></section></main>
|
|
2119
2050
|
<script>
|
|
2120
2051
|
function basePath() {
|
|
2121
2052
|
var p = window.location.pathname;
|
|
@@ -2129,17 +2060,29 @@ ${bodyInner}
|
|
|
2129
2060
|
var err = document.getElementById('err');
|
|
2130
2061
|
err.textContent = '';
|
|
2131
2062
|
var key = document.getElementById('key').value;
|
|
2063
|
+
var button = loginForm.querySelector('button'); button.disabled = true;
|
|
2132
2064
|
try {
|
|
2133
2065
|
var res = await fetch(basePath() + '/dashboard/login', {
|
|
2134
2066
|
method: 'POST',
|
|
2135
2067
|
headers: { 'Content-Type': 'application/json' },
|
|
2136
2068
|
body: JSON.stringify({ key: key }),
|
|
2137
2069
|
});
|
|
2138
|
-
if (res.ok) {
|
|
2070
|
+
if (res.ok) {
|
|
2071
|
+
var root = basePath() + '/dashboard';
|
|
2072
|
+
var target = new URL(window.location.href);
|
|
2073
|
+
var requested = target.searchParams.get('returnTo');
|
|
2074
|
+
if (requested) {
|
|
2075
|
+
var candidate = new URL(requested, window.location.origin + root + '/');
|
|
2076
|
+
if (candidate.origin === window.location.origin && candidate.pathname === root + '/token-report') target = candidate;
|
|
2077
|
+
else target = new URL(root, window.location.origin);
|
|
2078
|
+
}
|
|
2079
|
+
target.searchParams.delete('returnTo');
|
|
2080
|
+
window.location.replace(target.pathname + target.search + target.hash); return;
|
|
2081
|
+
}
|
|
2139
2082
|
err.textContent = res.status === 401 ? 'Invalid API key.' : ('Login failed (HTTP ' + res.status + ').');
|
|
2140
2083
|
} catch (e2) {
|
|
2141
|
-
err.textContent = '
|
|
2142
|
-
}
|
|
2084
|
+
err.textContent = 'Unable to connect. Please try again.';
|
|
2085
|
+
} finally { button.disabled = false; }
|
|
2143
2086
|
});
|
|
2144
2087
|
</script>
|
|
2145
2088
|
</body>
|
package/dist/ui/web-ui.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"web-ui.js","sourceRoot":"","sources":["../../src/ui/web-ui.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"web-ui.js","sourceRoot":"","sources":["../../src/ui/web-ui.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { TtsProvider } from './types';
|
|
2
|
+
/** Bounded, shared synthesis for explicit replay requests, independent of a microphone lease. */
|
|
3
|
+
export declare class VoiceReplays {
|
|
4
|
+
private readonly pending;
|
|
5
|
+
generate(key: string, provider: TtsProvider, voiceId: string, text: string): Promise<Buffer>;
|
|
6
|
+
close(): void;
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=replay.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"replay.d.ts","sourceRoot":"","sources":["../../src/voice/replay.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,WAAW,EAAc,MAAM,SAAS,CAAC;AAGzD,iGAAiG;AACjG,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA+E;IACvG,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAwB5F,KAAK,IAAI,IAAI;CACd"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.VoiceReplays = void 0;
|
|
4
|
+
const types_1 = require("./types");
|
|
5
|
+
const wav_1 = require("./wav");
|
|
6
|
+
/** Bounded, shared synthesis for explicit replay requests, independent of a microphone lease. */
|
|
7
|
+
class VoiceReplays {
|
|
8
|
+
constructor() {
|
|
9
|
+
this.pending = new Map();
|
|
10
|
+
}
|
|
11
|
+
generate(key, provider, voiceId, text) {
|
|
12
|
+
const existing = this.pending.get(key);
|
|
13
|
+
if (existing)
|
|
14
|
+
return existing.result;
|
|
15
|
+
if (this.pending.size >= 4)
|
|
16
|
+
return Promise.reject(new types_1.VoiceError('VOICE_REPLAY_BUSY'));
|
|
17
|
+
const controller = new AbortController();
|
|
18
|
+
const timer = setTimeout(() => controller.abort(), 60000);
|
|
19
|
+
const result = (async () => {
|
|
20
|
+
const chunks = [];
|
|
21
|
+
let size = 0, sequence = 0;
|
|
22
|
+
for await (const chunk of provider.synthesize({ text: (async function* () { yield text; })(), voiceId, outputFormat: types_1.PCM16, signal: controller.signal })) {
|
|
23
|
+
if (controller.signal.aborted)
|
|
24
|
+
throw new types_1.VoiceError('TTS_UNAVAILABLE');
|
|
25
|
+
if (chunk.chunkSeq !== sequence++ || chunk.format.encoding !== types_1.PCM16.encoding || chunk.format.sampleRate !== types_1.PCM16.sampleRate || chunk.format.channels !== 1 || chunk.bytes.length % 2)
|
|
26
|
+
throw new types_1.VoiceError('INVALID_AUDIO_CHUNK');
|
|
27
|
+
size += chunk.bytes.length;
|
|
28
|
+
if (size > 16 * 1024 * 1024 - 44) {
|
|
29
|
+
controller.abort();
|
|
30
|
+
throw new types_1.VoiceError('VOICE_REPLAY_TOO_LARGE');
|
|
31
|
+
}
|
|
32
|
+
chunks.push(Buffer.from(chunk.bytes));
|
|
33
|
+
}
|
|
34
|
+
if (!size || controller.signal.aborted)
|
|
35
|
+
throw new types_1.VoiceError('TTS_UNAVAILABLE');
|
|
36
|
+
return (0, wav_1.pcmToWav)(Buffer.concat(chunks));
|
|
37
|
+
})();
|
|
38
|
+
// A provider must not leave the HTTP request hanging if it ignores cancellation.
|
|
39
|
+
const aborted = new Promise((_, reject) => controller.signal.addEventListener('abort', () => reject(new types_1.VoiceError('TTS_UNAVAILABLE')), { once: true }));
|
|
40
|
+
const bounded = Promise.race([result, aborted]).finally(() => { clearTimeout(timer); this.pending.delete(key); });
|
|
41
|
+
this.pending.set(key, { result: bounded, controller });
|
|
42
|
+
return bounded;
|
|
43
|
+
}
|
|
44
|
+
close() { for (const job of this.pending.values())
|
|
45
|
+
job.controller.abort(); }
|
|
46
|
+
}
|
|
47
|
+
exports.VoiceReplays = VoiceReplays;
|
|
48
|
+
//# sourceMappingURL=replay.js.map
|