@0xmaxma/claude-gateway 2.0.4 → 2.0.6
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 +123 -9
- package/dist/agent/runner.d.ts.map +1 -1
- package/dist/agent/runner.js +215 -182
- package/dist/agent/runner.js.map +1 -1
- package/dist/agent/session-compaction-scheduler.d.ts +22 -0
- package/dist/agent/session-compaction-scheduler.d.ts.map +1 -0
- package/dist/agent/session-compaction-scheduler.js +40 -0
- package/dist/agent/session-compaction-scheduler.js.map +1 -0
- 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 +323 -16
- package/dist/api/gateway-router.js.map +1 -1
- package/dist/api/memory-activity.d.ts +18 -0
- package/dist/api/memory-activity.d.ts.map +1 -0
- package/dist/api/memory-activity.js +97 -0
- package/dist/api/memory-activity.js.map +1 -0
- 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/compact-measurements.d.ts +21 -0
- package/dist/orchestration/compact-measurements.d.ts.map +1 -0
- package/dist/orchestration/compact-measurements.js +62 -0
- package/dist/orchestration/compact-measurements.js.map +1 -0
- package/dist/orchestration/config.d.ts +4 -0
- package/dist/orchestration/config.d.ts.map +1 -1
- package/dist/orchestration/config.js +1 -1
- package/dist/orchestration/config.js.map +1 -1
- package/dist/orchestration/context-delivery.d.ts +32 -0
- package/dist/orchestration/context-delivery.d.ts.map +1 -0
- package/dist/orchestration/context-delivery.js +101 -0
- package/dist/orchestration/context-delivery.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/conversation-intake.d.ts +10 -6
- package/dist/orchestration/conversation-intake.d.ts.map +1 -1
- package/dist/orchestration/conversation-intake.js +22 -8
- package/dist/orchestration/conversation-intake.js.map +1 -1
- package/dist/orchestration/dashboard-charts.d.ts +32 -0
- package/dist/orchestration/dashboard-charts.d.ts.map +1 -0
- package/dist/orchestration/dashboard-charts.js +77 -0
- package/dist/orchestration/dashboard-charts.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 +173 -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 +13 -0
- package/dist/orchestration/mutation-recovery.d.ts.map +1 -0
- package/dist/orchestration/mutation-recovery.js +49 -0
- package/dist/orchestration/mutation-recovery.js.map +1 -0
- package/dist/orchestration/native-compact.d.ts +8 -0
- package/dist/orchestration/native-compact.d.ts.map +1 -0
- package/dist/orchestration/native-compact.js +33 -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 +16 -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 +79 -0
- package/dist/orchestration/runtime.d.ts.map +1 -1
- package/dist/orchestration/runtime.js +415 -68
- package/dist/orchestration/runtime.js.map +1 -1
- package/dist/orchestration/session-compaction.d.ts +59 -0
- package/dist/orchestration/session-compaction.d.ts.map +1 -0
- package/dist/orchestration/session-compaction.js +212 -0
- package/dist/orchestration/session-compaction.js.map +1 -0
- 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 +132 -0
- package/dist/orchestration/token-ledger.d.ts.map +1 -0
- package/dist/orchestration/token-ledger.js +233 -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/types.d.ts +3 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/ui/cli-viewer-ui.js +1 -1
- package/dist/ui/dashboard-charts.d.ts +3 -0
- package/dist/ui/dashboard-charts.d.ts.map +1 -0
- package/dist/ui/dashboard-charts.js +130 -0
- package/dist/ui/dashboard-charts.js.map +1 -0
- 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 +184 -0
- package/dist/ui/dashboard-client.js.map +1 -0
- package/dist/ui/dashboard-controls.d.ts +4 -0
- package/dist/ui/dashboard-controls.d.ts.map +1 -0
- package/dist/ui/dashboard-controls.js +27 -0
- package/dist/ui/dashboard-controls.js.map +1 -0
- package/dist/ui/dashboard-presentation.d.ts +12 -0
- package/dist/ui/dashboard-presentation.d.ts.map +1 -0
- package/dist/ui/dashboard-presentation.js +62 -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 +36 -0
- package/dist/ui/dashboard-range.js.map +1 -0
- package/dist/ui/dashboard-theme.d.ts +6 -0
- package/dist/ui/dashboard-theme.d.ts.map +1 -0
- package/dist/ui/dashboard-theme.js +562 -0
- package/dist/ui/dashboard-theme.js.map +1 -0
- package/dist/ui/memory-activity.d.ts +4 -0
- package/dist/ui/memory-activity.d.ts.map +1 -0
- package/dist/ui/memory-activity.js +115 -0
- package/dist/ui/memory-activity.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 +90 -0
- package/dist/ui/token-report.d.ts.map +1 -0
- package/dist/ui/token-report.js +203 -0
- package/dist/ui/token-report.js.map +1 -0
- package/dist/ui/web-ui.d.ts +1 -1
- package/dist/ui/web-ui.d.ts.map +1 -1
- package/dist/ui/web-ui.js +129 -409
- 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 +45 -31
- package/mcp/tools/telegram/session-browser.ts +10 -0
- 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,19 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.generateDashboardHtml = generateDashboardHtml;
|
|
4
4
|
exports.generateLoginHtml = generateLoginHtml;
|
|
5
|
+
const dashboard_charts_1 = require("./dashboard-charts");
|
|
6
|
+
const dashboard_controls_1 = require("./dashboard-controls");
|
|
7
|
+
const memory_activity_1 = require("./memory-activity");
|
|
8
|
+
const dashboard_range_1 = require("./dashboard-range");
|
|
9
|
+
const dashboard_theme_1 = require("./dashboard-theme");
|
|
10
|
+
const dashboard_client_1 = require("./dashboard-client");
|
|
5
11
|
/**
|
|
6
12
|
* Generates a self-contained HTML dashboard page for the gateway status UI.
|
|
7
13
|
* No external dependencies except xterm.js CDN for PTY viewer.
|
|
8
14
|
*/
|
|
9
|
-
function generateDashboardHtml() {
|
|
15
|
+
function generateDashboardHtml(timezone = 'UTC') {
|
|
10
16
|
return `<!DOCTYPE html>
|
|
11
|
-
<html lang="en">
|
|
17
|
+
<html lang="en" data-theme="light">
|
|
12
18
|
<head>
|
|
13
19
|
<meta charset="UTF-8">
|
|
14
20
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
@@ -297,141 +303,80 @@ function generateDashboardHtml() {
|
|
|
297
303
|
position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
|
|
298
304
|
color: #718096; font-size: 0.9rem; text-align: center; padding: 20px; pointer-events: none;
|
|
299
305
|
}
|
|
300
|
-
/* --- Nightly dreaming report --- */
|
|
301
|
-
.dreams-list { display: flex; flex-direction: column; gap: 12px; padding: 4px 2px 20px; }
|
|
302
|
-
.dreams-empty { color: #718096; font-size: 0.9rem; text-align: center; padding: 40px 20px; }
|
|
303
|
-
.dream-run {
|
|
304
|
-
background: #131a2b; border: 1px solid #222c40; border-radius: 8px; padding: 12px 14px;
|
|
305
|
-
}
|
|
306
|
-
.dream-run-head { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 6px; }
|
|
307
|
-
.dream-run-head .agent { color: #63b3ed; font-weight: 600; }
|
|
308
|
-
.dream-run-head .when { color: #718096; font-size: 0.78rem; font-family: monospace; }
|
|
309
|
-
.dream-badge { border-radius: 4px; padding: 1px 7px; font-size: 0.7rem; font-weight: 600; }
|
|
310
|
-
.dream-badge.auto { background: #22543d; color: #9ae6b4; border: 1px solid #2f855a; }
|
|
311
|
-
.dream-badge.propose { background: #2a4365; color: #90cdf4; border: 1px solid #2b6cb0; }
|
|
312
|
-
.dream-badge.outcome { background: #2d3748; color: #cbd5e0; border: 1px solid #4a5568; }
|
|
313
|
-
.dream-summary { color: #cbd5e0; font-size: 0.86rem; margin: 4px 0 8px; }
|
|
314
|
-
.dream-meta { color: #718096; font-size: 0.75rem; margin-top: 8px; }
|
|
315
|
-
.dream-props { display: flex; flex-direction: column; gap: 6px; }
|
|
316
|
-
.dream-prop {
|
|
317
|
-
background: #0e1420; border: 1px solid #1e2740; border-radius: 6px; padding: 7px 9px; font-size: 0.82rem;
|
|
318
|
-
}
|
|
319
|
-
.dream-prop .op { font-weight: 600; text-transform: uppercase; font-size: 0.7rem; margin-right: 6px; }
|
|
320
|
-
.dream-prop .op.add { color: #68d391; } .dream-prop .op.replace { color: #f6ad55; } .dream-prop .op.remove { color: #fc8181; }
|
|
321
|
-
.dream-prop .file { color: #90cdf4; font-family: monospace; font-size: 0.76rem; }
|
|
322
|
-
.dream-prop .score { color: #718096; font-size: 0.72rem; float: right; }
|
|
323
|
-
.dream-prop .reason { color: #a0aec0; margin-top: 3px; }
|
|
324
|
-
.dream-prop .content { color: #cbd5e0; margin-top: 5px; white-space: pre-wrap; word-break: break-word;
|
|
325
|
-
background: #070a12; border-radius: 4px; padding: 6px 8px; font-size: 0.78rem; max-height: 140px; overflow: auto; }
|
|
326
|
-
.dream-prop .anchor { color: #f6ad55; font-family: monospace; font-size: 0.72rem; margin-top: 3px; }
|
|
327
|
-
.dream-prop.accepted { border-color: #2f855a; }
|
|
328
|
-
.dream-prop-actions { display: flex; align-items: center; gap: 8px; margin-top: 6px; }
|
|
329
|
-
.dream-accept-btn { background: #22543d; color: #9ae6b4; border: 1px solid #2f855a; border-radius: 4px;
|
|
330
|
-
padding: 2px 10px; font-size: 0.74rem; font-weight: 600; cursor: pointer; }
|
|
331
|
-
.dream-accept-btn:hover { background: #276749; }
|
|
332
|
-
.dream-accept-btn:disabled { opacity: 0.55; cursor: default; }
|
|
333
|
-
.prop-status { font-size: 0.72rem; font-weight: 600; }
|
|
334
|
-
.prop-status.applied { color: #9ae6b4; }
|
|
335
|
-
.prop-status.applied-auto { color: #68d391; }
|
|
336
|
-
.prop-status.pending { color: #90cdf4; }
|
|
337
|
-
.prop-status.failed { color: #fc8181; }
|
|
338
|
-
.dream-accept-all { background: #22543d; color: #9ae6b4; border: 1px solid #2f855a; border-radius: 4px;
|
|
339
|
-
padding: 1px 9px; font-size: 0.7rem; font-weight: 600; cursor: pointer; }
|
|
340
|
-
.dream-accept-all:hover { background: #276749; }
|
|
341
|
-
.dream-accept-all:disabled { opacity: 0.55; cursor: default; }
|
|
342
306
|
/* Note detail — full-width card below the graph. Shows the whole file. */
|
|
343
307
|
.kb-note {
|
|
344
|
-
margin-top: 12px; background:
|
|
345
|
-
padding: 16px 18px; font-size: 0.85rem; color:
|
|
308
|
+
margin-top: 12px; background: var(--panel); border: 1px solid var(--line); border-radius: 8px;
|
|
309
|
+
padding: 16px 18px; font-size: 0.85rem; color: var(--text);
|
|
346
310
|
}
|
|
347
311
|
.kb-note-head { display: flex; align-items: flex-start; gap: 10px; }
|
|
348
|
-
.kb-note-head h3 { margin: 0; font-size: 1.02rem; color:
|
|
312
|
+
.kb-note-head h3 { margin: 0; font-size: 1.02rem; color: var(--text); flex: 1; word-break: break-word; }
|
|
349
313
|
.kb-note-close {
|
|
350
|
-
cursor: pointer; color:
|
|
314
|
+
cursor: pointer; color: var(--muted); background: var(--panel); border: 1px solid var(--line);
|
|
351
315
|
border-radius: 4px; padding: 1px 8px; font-size: 0.9rem; line-height: 1.4;
|
|
352
316
|
}
|
|
353
|
-
.kb-note-close:hover { color:
|
|
317
|
+
.kb-note-close:hover { color: var(--text); background: var(--line); }
|
|
354
318
|
/* Metadata chips row. */
|
|
355
319
|
.kb-note-meta { display: flex; flex-wrap: wrap; gap: 6px; margin: 10px 0 4px; }
|
|
356
320
|
.kb-note-chip {
|
|
357
|
-
display: inline-flex; align-items: center; gap: 5px; background:
|
|
358
|
-
border: 1px solid
|
|
321
|
+
display: inline-flex; align-items: center; gap: 5px; background: var(--raised);
|
|
322
|
+
border: 1px solid var(--line); border-radius: 999px; padding: 2px 10px; font-size: 0.72rem; color: var(--muted);
|
|
359
323
|
}
|
|
360
|
-
.kb-note-chip b { color:
|
|
324
|
+
.kb-note-chip b { color: var(--text); font-weight: 600; }
|
|
361
325
|
.kb-note-chip i { width: 8px; height: 8px; border-radius: 50%; display: inline-block; }
|
|
362
326
|
/* File path line under the chips — full width, monospace, wraps on long paths. */
|
|
363
327
|
.kb-note-path {
|
|
364
328
|
margin: 6px 0 2px; font-size: 0.72rem; font-family: ui-monospace, monospace;
|
|
365
|
-
color:
|
|
329
|
+
color: var(--muted); word-break: break-all;
|
|
366
330
|
}
|
|
367
|
-
.kb-note-path b { color:
|
|
331
|
+
.kb-note-path b { color: var(--muted); font-weight: 600; }
|
|
368
332
|
/* Rendered Markdown body. */
|
|
369
333
|
.kb-md {
|
|
370
|
-
margin-top: 12px; padding-top: 12px; border-top: 1px solid
|
|
371
|
-
line-height: 1.62; color:
|
|
334
|
+
margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--line);
|
|
335
|
+
line-height: 1.62; color: var(--text); word-break: break-word;
|
|
372
336
|
}
|
|
373
337
|
.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:
|
|
338
|
+
.kb-md h1, .kb-md h2, .kb-md h3, .kb-md h4 { color: var(--text); line-height: 1.3; margin: 18px 0 8px; }
|
|
339
|
+
.kb-md h1 { font-size: 1.25rem; border-bottom: 1px solid var(--line); padding-bottom: 5px; }
|
|
340
|
+
.kb-md h2 { font-size: 1.1rem; border-bottom: 1px solid var(--line); padding-bottom: 4px; }
|
|
341
|
+
.kb-md h3 { font-size: 1rem; } .kb-md h4 { font-size: 0.9rem; color: var(--muted); }
|
|
378
342
|
.kb-md p { margin: 8px 0; }
|
|
379
343
|
.kb-md ul, .kb-md ol { margin: 8px 0; padding-left: 22px; }
|
|
380
344
|
.kb-md li { margin: 3px 0; }
|
|
381
|
-
.kb-md a { color:
|
|
345
|
+
.kb-md a { color: var(--accent); text-decoration: none; } .kb-md a:hover { text-decoration: underline; }
|
|
382
346
|
.kb-md code {
|
|
383
|
-
background:
|
|
384
|
-
padding: 1px 5px; font-size: 0.82em; font-family: ui-monospace, monospace; color:
|
|
347
|
+
background: var(--raised); border: 1px solid var(--line); border-radius: 4px;
|
|
348
|
+
padding: 1px 5px; font-size: 0.82em; font-family: ui-monospace, monospace; color: var(--text);
|
|
385
349
|
}
|
|
386
350
|
.kb-md pre {
|
|
387
|
-
background:
|
|
351
|
+
background: var(--raised); border: 1px solid var(--line); border-radius: 6px; padding: 10px 12px;
|
|
388
352
|
overflow-x: auto; margin: 10px 0;
|
|
389
353
|
}
|
|
390
354
|
.kb-md pre code { background: none; border: none; padding: 0; font-size: 0.8rem; line-height: 1.5; }
|
|
391
355
|
.kb-md blockquote {
|
|
392
|
-
margin: 10px 0; padding: 2px 14px; border-left: 3px solid
|
|
356
|
+
margin: 10px 0; padding: 2px 14px; border-left: 3px solid var(--line); color: var(--muted);
|
|
393
357
|
}
|
|
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:
|
|
358
|
+
.kb-md hr { border: none; border-top: 1px solid var(--line); margin: 14px 0; }
|
|
359
|
+
.kb-md strong { color: var(--text); } .kb-md table { border-collapse: collapse; margin: 0; width: 100%; font-size: 0.82rem; }
|
|
360
|
+
.kb-md th, .kb-md td { border: 1px solid var(--line); padding: 5px 10px; text-align: left; }
|
|
361
|
+
.kb-md th { background: var(--raised); color: var(--text); font-weight: 600; }
|
|
362
|
+
.kb-md tbody tr:nth-child(even) { background: var(--raised); }
|
|
399
363
|
/* Wide tables scroll horizontally instead of breaking the panel. */
|
|
400
364
|
.kb-table-wrap { overflow-x: auto; margin: 10px 0; border-radius: 6px; }
|
|
401
|
-
.kb-md del { color:
|
|
365
|
+
.kb-md del { color: var(--muted); }
|
|
402
366
|
/* Task-list items: bullet replaced by a real (disabled) checkbox. */
|
|
403
367
|
.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:
|
|
368
|
+
.kb-md li.kb-task input { margin-right: 7px; vertical-align: middle; accent-color: var(--accent); }
|
|
369
|
+
.kb-note-loading { color: var(--muted); font-size: 0.82rem; margin-top: 12px; }
|
|
370
|
+
${dashboard_theme_1.dashboardTheme}
|
|
406
371
|
</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>
|
|
372
|
+
${dashboard_theme_1.dashboardFontLink}<script>try{document.documentElement.dataset.sidebarCollapsed=localStorage.getItem("gateway-sidebar-collapsed")==="true"?"true":"false";}catch{}</script></head>
|
|
373
|
+
<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" aria-hidden="true">✳</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>${(0, dashboard_controls_1.themeButtonHtml)('dash-theme')}<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>
|
|
374
|
+
<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>${(0, dashboard_charts_1.dashboardChartsHtml)(timezone)}<section class="dash-panel" id="overview-attention-panel" hidden><h2>Needs your attention</h2><p class="live-note">Inspect the task here, then reply to your agent in the original chat.</p><div class="dash-mini-list" id="overview-attention"></div></section><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>
|
|
375
|
+
<div class="dash-filter turn-filters"><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", timezone)}<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>
|
|
376
|
+
<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>
|
|
377
|
+
<div id="view-system" class="view" style="display:none">
|
|
378
|
+
<h2>Processes</h2>
|
|
379
|
+
<div class="proc-tree" id="proc-tree">Loading...</div>
|
|
435
380
|
|
|
436
381
|
<!-- PTY viewer — full width so the native 200-col terminal has room.
|
|
437
382
|
Placed above the Sessions table so the live mirror is the first thing
|
|
@@ -450,32 +395,7 @@ function generateDashboardHtml() {
|
|
|
450
395
|
<div id="pty-terminal" tabindex="0"></div>
|
|
451
396
|
</div>
|
|
452
397
|
|
|
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
|
-
|
|
398
|
+
</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
399
|
<!-- Knowledge base — a 3D force-directed graph over the shared vault / an agent's memory.
|
|
480
400
|
Zero external deps: the spherical layout + canvas render + rotation are hand-rolled. -->
|
|
481
401
|
<div id="view-kb" class="view" style="display:none;">
|
|
@@ -519,28 +439,21 @@ function generateDashboardHtml() {
|
|
|
519
439
|
|
|
520
440
|
<!-- Nightly dreaming — the memory-consolidation audit trail (.dreaming/) per agent. -->
|
|
521
441
|
<div id="view-dreams" class="view" style="display:none;">
|
|
522
|
-
|
|
523
|
-
<button id="dreams-refresh" title="Reload the dreaming audit trail">↻ Refresh</button>
|
|
524
|
-
<label id="dreams-agent-wrap">Agent
|
|
525
|
-
<select id="dreams-agent"><option value="">All agents</option></select>
|
|
526
|
-
</label>
|
|
527
|
-
<span id="dreams-stats"></span>
|
|
528
|
-
</div>
|
|
529
|
-
<div id="dreams-list" class="dreams-list"></div>
|
|
530
|
-
<div id="dreams-empty" class="dreams-empty" style="display:none;"></div>
|
|
442
|
+
${memory_activity_1.memoryActivityHtml}
|
|
531
443
|
</div><!-- /view-dreams -->
|
|
532
444
|
|
|
533
|
-
<div id="error-msg" class="error" style="display:none;"></div>
|
|
445
|
+
<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
446
|
|
|
535
447
|
<script src="https://cdn.jsdelivr.net/npm/@xterm/xterm@6.0.0/lib/xterm.min.js"
|
|
536
448
|
integrity="sha384-pELe6ZHtFxFcuYBq3gMkqvmnNIqUWnAYjBG5gThqQQCjWp8PJ/65MLK4lMIfEK1e" crossorigin="anonymous"></script>
|
|
537
449
|
<script>
|
|
450
|
+
const dashboardTimezone = ${JSON.stringify(timezone).replace(/</g, '\\u003c')};
|
|
538
451
|
// Auth is carried by the HttpOnly 'dash_session' cookie the browser sends
|
|
539
452
|
// automatically on every same-origin request — no token is embedded in the
|
|
540
453
|
// page (nothing for view-source/XSS to steal). If any read returns 401 the
|
|
541
454
|
// session has expired or is missing, so bounce to /dashboard (login page).
|
|
542
455
|
function onUnauthorized() {
|
|
543
|
-
window.location.
|
|
456
|
+
window.location.reload();
|
|
544
457
|
}
|
|
545
458
|
|
|
546
459
|
// Must match the server PTY size (src/shell/screen.ts ScreenModel defaults).
|
|
@@ -561,7 +474,7 @@ function generateDashboardHtml() {
|
|
|
561
474
|
if (!ts) return '<span class="ts">—</span>';
|
|
562
475
|
try {
|
|
563
476
|
const d = new Date(ts);
|
|
564
|
-
return '<span class="ts">' + d.toLocaleString('en-US', {
|
|
477
|
+
return '<span class="ts">' + d.toLocaleString('en-US', {timeZone:dashboardTimezone,
|
|
565
478
|
year: 'numeric', month: 'numeric', day: 'numeric',
|
|
566
479
|
hour: 'numeric', minute: '2-digit', second: '2-digit', hour12: true
|
|
567
480
|
}) + '</span>';
|
|
@@ -861,7 +774,7 @@ function generateDashboardHtml() {
|
|
|
861
774
|
|
|
862
775
|
const expandedSessionRows = new Set();
|
|
863
776
|
// Event delegation for Live buttons (avoids inline onclick + HTML injection)
|
|
864
|
-
document.getElementById('
|
|
777
|
+
document.getElementById('session-results').addEventListener('click', function(e) {
|
|
865
778
|
const toggle = e.target.closest('.btn-workers');
|
|
866
779
|
if (toggle) {
|
|
867
780
|
const key=toggle.getAttribute('data-expand-key'), open=!expandedSessionRows.has(key);
|
|
@@ -871,8 +784,8 @@ function generateDashboardHtml() {
|
|
|
871
784
|
const detail=document.getElementById(toggle.getAttribute('aria-controls'));if(detail)detail.hidden=!open;
|
|
872
785
|
return;
|
|
873
786
|
}
|
|
874
|
-
const btn = e.target.closest('.btn-stream');
|
|
875
|
-
if (btn) void openPtyViewer(btn.getAttribute('data-agent-id'), btn.getAttribute('data-session-id'));
|
|
787
|
+
const btn = e.target.closest('button.btn-stream[data-agent-id][data-session-id]');
|
|
788
|
+
if (btn) { document.getElementById('tab-system').click(); void openPtyViewer(btn.getAttribute('data-agent-id'), btn.getAttribute('data-session-id')); }
|
|
876
789
|
});
|
|
877
790
|
|
|
878
791
|
function escHtml(s) {
|
|
@@ -916,26 +829,29 @@ function generateDashboardHtml() {
|
|
|
916
829
|
|
|
917
830
|
// Format a context-window token count compactly: 1234 -> "1.2k", 45000 -> "45k".
|
|
918
831
|
// Full value is kept in the tooltip. 0/unknown renders as a dash.
|
|
832
|
+
function toolInventory(loaded, used, contextTools) {
|
|
833
|
+
function list(label, names) {
|
|
834
|
+
return '<div title="'+(Array.isArray(names)?escHtml(names.join(', ')||'None'):'Not recorded')+'">'+label+': '+(Array.isArray(names)?compactNumber(names.length):'—')+'</div>';
|
|
835
|
+
}
|
|
836
|
+
return list('Loaded', contextTools)+list('Used', used);
|
|
837
|
+
}
|
|
838
|
+
|
|
839
|
+
function fmtRecordedTokens(n) {
|
|
840
|
+
return n == null ? '—' : n === 0 ? '0' : fmtTokens(n);
|
|
841
|
+
}
|
|
842
|
+
|
|
919
843
|
function fmtTokens(n) {
|
|
920
844
|
const v = Number(n) || 0;
|
|
921
845
|
if (v <= 0) return '<span class="ts">—</span>';
|
|
922
|
-
const label =
|
|
846
|
+
const label = compactNumber(v);
|
|
923
847
|
return '<span title="' + v.toLocaleString() + ' tokens">' + label + '</span>';
|
|
924
848
|
}
|
|
925
849
|
|
|
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
|
-
|
|
850
|
+
function applyDashboardSnapshot(data) {
|
|
935
851
|
document.getElementById('uptime').textContent = fmtUptime(data.uptime || 0);
|
|
936
852
|
document.getElementById('started-at').textContent = data.startedAt
|
|
937
|
-
? new Date(data.startedAt).toLocaleString() : '\\u2014';
|
|
938
|
-
document.getElementById('last-updated').textContent = new Date().toLocaleTimeString();
|
|
853
|
+
? new Date(data.startedAt).toLocaleString('en-GB',{timeZone:dashboardTimezone}) : '\\u2014';
|
|
854
|
+
document.getElementById('last-updated').textContent = new Date().toLocaleTimeString('en-GB',{timeZone:dashboardTimezone});
|
|
939
855
|
if (data.version) document.getElementById('gateway-version').textContent = 'v' + data.version;
|
|
940
856
|
document.getElementById('error-msg').style.display = 'none';
|
|
941
857
|
|
|
@@ -949,70 +865,33 @@ function generateDashboardHtml() {
|
|
|
949
865
|
const badges = agents.map(function(a) {
|
|
950
866
|
const ok = a.hasChannel ? a.isRunning : true;
|
|
951
867
|
const dot = ok ? '<span class="dot-green">●</span>' : '<span class="dot-red">●</span>';
|
|
952
|
-
return
|
|
868
|
+
return agentBadge(a.id);
|
|
953
869
|
});
|
|
954
870
|
document.getElementById('agents-bar').innerHTML = badges.join('') || '<span class="ts">No agents</span>';
|
|
955
871
|
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
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
|
-
});
|
|
872
|
+
renderDashboard(data);
|
|
873
|
+
|
|
874
|
+
document.getElementById('refresh-indicator').textContent = 'Live · updated';
|
|
875
|
+
}
|
|
1006
876
|
|
|
1007
|
-
|
|
1008
|
-
|
|
877
|
+
// ── Status Refresh ────────────────────────────────────────────────────────
|
|
878
|
+
async function refresh() {
|
|
879
|
+
if (dashboardBusy || document.hidden) return;
|
|
880
|
+
dashboardBusy = true;
|
|
881
|
+
const requestedOffset = dashboardOffset, requestedScope = dashboardScope;
|
|
882
|
+
document.getElementById('refresh-indicator').textContent = 'Updating…';
|
|
883
|
+
try {
|
|
884
|
+
const res = await fetch(apiUrl('/status')+'?offset='+requestedOffset+'&scope='+requestedScope);
|
|
885
|
+
if (res.status === 401) { onUnauthorized(); return; }
|
|
886
|
+
if (!res.ok) throw new Error('HTTP ' + res.status);
|
|
887
|
+
const data = await res.json();
|
|
1009
888
|
|
|
1010
|
-
|
|
889
|
+
if (requestedOffset === dashboardOffset && requestedScope === dashboardScope) applyDashboardSnapshot(data);
|
|
1011
890
|
} catch(e) {
|
|
1012
891
|
document.getElementById('error-msg').textContent = 'Error fetching status: ' + e.message;
|
|
1013
892
|
document.getElementById('error-msg').style.display = 'block';
|
|
1014
|
-
document.getElementById('refresh-indicator').textContent = '
|
|
1015
|
-
}
|
|
893
|
+
document.getElementById('refresh-indicator').textContent = 'Reconnecting…';
|
|
894
|
+
} finally {dashboardBusy=false;}
|
|
1016
895
|
}
|
|
1017
896
|
|
|
1018
897
|
// ── Process Tree ─────────────────────────────────────────────────────────
|
|
@@ -1166,14 +1045,16 @@ function generateDashboardHtml() {
|
|
|
1166
1045
|
try {
|
|
1167
1046
|
await fetch(apiUrl('/dashboard/logout'), { method: 'POST' });
|
|
1168
1047
|
} catch (e) { /* best-effort; navigate regardless */ }
|
|
1169
|
-
window.location.
|
|
1048
|
+
window.location.reload();
|
|
1170
1049
|
});
|
|
1171
1050
|
|
|
1051
|
+
${dashboard_controls_1.dashboardControlsClient}
|
|
1052
|
+
${dashboard_client_1.dashboardClient}
|
|
1172
1053
|
refresh();
|
|
1173
|
-
|
|
1174
|
-
setInterval(refresh,
|
|
1175
|
-
|
|
1176
|
-
|
|
1054
|
+
connectDashboardStream();
|
|
1055
|
+
setInterval(function(){if(!dashboardStream || dashboardStream.readyState!==1)refresh();},15000);
|
|
1056
|
+
setInterval(function(){if(!document.hidden && document.getElementById('view-system').style.display!=='none')refreshProcesses();},10000);
|
|
1057
|
+
document.addEventListener('visibilitychange',function(){if(document.hidden){dashboardStream?.close();dashboardStream=null;}else{refresh();connectDashboardStream();}});
|
|
1177
1058
|
</script>
|
|
1178
1059
|
|
|
1179
1060
|
<!-- Knowledge base graph: tab switching + hand-rolled force-directed renderer.
|
|
@@ -1400,7 +1281,11 @@ function generateDashboardHtml() {
|
|
|
1400
1281
|
// Labels: hubs always; hovered / selected / search-hit reveal on demand.
|
|
1401
1282
|
var showLabel = (o.deg >= LABEL_MIN_DEG) || isHov || isSel || (searching && o.hit);
|
|
1402
1283
|
if (showLabel && !dim){
|
|
1403
|
-
|
|
1284
|
+
// White, not var(--text): .kb-stage paints a fixed deep-space backdrop in BOTH
|
|
1285
|
+
// themes, but --text flips to near-black under the light theme (the page default),
|
|
1286
|
+
// which left labels unreadable on the dark canvas. Matches the white the hover /
|
|
1287
|
+
// selection rings above already use.
|
|
1288
|
+
ctx.fillStyle = '#fff';
|
|
1404
1289
|
ctx.font = (isHov || isSel ? '12px ' : '11px ') + 'ui-sans-serif, system-ui, sans-serif';
|
|
1405
1290
|
ctx.fillText(nd.title, p.sx + p.r + 4, p.sy + 3);
|
|
1406
1291
|
}
|
|
@@ -1530,7 +1415,7 @@ function generateDashboardHtml() {
|
|
|
1530
1415
|
o.hit = hay.indexOf(q) >= 0;
|
|
1531
1416
|
if (o.hit) hits.push(o);
|
|
1532
1417
|
});
|
|
1533
|
-
if (elSearchCount) elSearchCount.textContent = hits.length + ' / ' + G.nodes.length;
|
|
1418
|
+
if (elSearchCount) elSearchCount.textContent = compactNumber(hits.length) + ' / ' + compactNumber(G.nodes.length);
|
|
1534
1419
|
invalidate();
|
|
1535
1420
|
return hits;
|
|
1536
1421
|
}
|
|
@@ -1812,7 +1697,7 @@ function generateDashboardHtml() {
|
|
|
1812
1697
|
sourceSel.textContent = '';
|
|
1813
1698
|
(data.sources || [{ id: 'shared', label: 'Shared Knowledge Base', count: 0 }]).forEach(function(s){
|
|
1814
1699
|
var o = document.createElement('option');
|
|
1815
|
-
o.value = s.id; o.textContent = s.label + (typeof s.count === 'number' ? ' (' + s.count + ')' : '');
|
|
1700
|
+
o.value = s.id; o.textContent = s.label + (typeof s.count === 'number' ? ' (' + compactNumber(s.count) + ')' : '');
|
|
1816
1701
|
sourceSel.appendChild(o);
|
|
1817
1702
|
});
|
|
1818
1703
|
// Restore prior selection if it still exists, else fall back to Shared KB.
|
|
@@ -1855,7 +1740,7 @@ function generateDashboardHtml() {
|
|
|
1855
1740
|
}
|
|
1856
1741
|
buildModel(data);
|
|
1857
1742
|
renderLegend();
|
|
1858
|
-
elStats.textContent = data.nodes.length + ' notes, ' + data.edges.length + ' links';
|
|
1743
|
+
elStats.textContent = compactNumber(data.nodes.length) + ' notes, ' + compactNumber(data.edges.length) + ' links';
|
|
1859
1744
|
}).catch(function(err){
|
|
1860
1745
|
elStats.textContent = ''; elEmpty.textContent = 'Failed to load graph: ' + err.message; elEmpty.style.display = '';
|
|
1861
1746
|
});
|
|
@@ -1876,184 +1761,7 @@ function generateDashboardHtml() {
|
|
|
1876
1761
|
})();
|
|
1877
1762
|
</script>
|
|
1878
1763
|
|
|
1879
|
-
<script id="kb-dreams">
|
|
1880
|
-
// Nightly dreaming report renderer. Fetches /knowledge/dreams (parsed audit
|
|
1881
|
-
// trail across all agents), renders a newest-first timeline with per-run
|
|
1882
|
-
// proposals, and an agent filter. All text goes through textContent (no HTML
|
|
1883
|
-
// injection). Uses the global apiUrl/onUnauthorized helpers.
|
|
1884
|
-
(function(){
|
|
1885
|
-
var listEl = document.getElementById('dreams-list');
|
|
1886
|
-
var emptyEl = document.getElementById('dreams-empty');
|
|
1887
|
-
var statsEl = document.getElementById('dreams-stats');
|
|
1888
|
-
var agentSel = document.getElementById('dreams-agent');
|
|
1889
|
-
var refreshBtn = document.getElementById('dreams-refresh');
|
|
1890
|
-
var allRuns = [];
|
|
1891
|
-
var loaded = false;
|
|
1892
|
-
// Notice to show once, after the next render (a reload overwrites statsEl,
|
|
1893
|
-
// so an accept result set directly on statsEl would be lost immediately).
|
|
1894
|
-
var pendingNotice = '';
|
|
1895
|
-
|
|
1896
|
-
function el(tag, cls, text){
|
|
1897
|
-
var e = document.createElement(tag);
|
|
1898
|
-
if (cls) e.className = cls;
|
|
1899
|
-
if (text != null) e.textContent = text;
|
|
1900
|
-
return e;
|
|
1901
|
-
}
|
|
1902
|
-
|
|
1903
|
-
// Apply one or more proposals of a run to the agent's memory via the K4
|
|
1904
|
-
// applier. indexes === null ⇒ accept every pending proposal in the run.
|
|
1905
|
-
function acceptDreams(agent, ts, indexes, btn){
|
|
1906
|
-
var origText = btn ? btn.textContent : '';
|
|
1907
|
-
if (btn){ btn.disabled = true; btn.textContent = 'Applying…'; }
|
|
1908
|
-
var payload = { agentId: agent, ts: ts };
|
|
1909
|
-
if (indexes) payload.indexes = indexes;
|
|
1910
|
-
fetch(apiUrl('/knowledge/dreams/apply'), {
|
|
1911
|
-
method: 'POST',
|
|
1912
|
-
headers: { 'Content-Type': 'application/json' },
|
|
1913
|
-
body: JSON.stringify(payload)
|
|
1914
|
-
}).then(function(res){
|
|
1915
|
-
if (res.status === 401){ onUnauthorized(); return null; }
|
|
1916
|
-
return res.json().then(function(data){ return { ok: res.ok, data: data || {} }; });
|
|
1917
|
-
}).then(function(r){
|
|
1918
|
-
if (!r) return;
|
|
1919
|
-
if (!r.ok){
|
|
1920
|
-
if (btn){ btn.disabled = false; btn.textContent = origText || 'Accept'; }
|
|
1921
|
-
statsEl.textContent = 'Apply failed: ' + (r.data.error || 'error');
|
|
1922
|
-
return;
|
|
1923
|
-
}
|
|
1924
|
-
// Reload so applied proposals show ✓ and any anchor-stale skips stay
|
|
1925
|
-
// pending; the memory files themselves were already updated on disk.
|
|
1926
|
-
// The message is stashed in pendingNotice because loadDreams → render
|
|
1927
|
-
// rewrites statsEl.
|
|
1928
|
-
pendingNotice = 'Applied ' + (r.data.applied || 0)
|
|
1929
|
-
+ (r.data.skipped ? ', skipped ' + r.data.skipped + ' (anchor changed / net-negative)' : '')
|
|
1930
|
-
+ (r.data.alreadyAccepted ? ', ' + r.data.alreadyAccepted + ' already applied' : '');
|
|
1931
|
-
loadDreams(true);
|
|
1932
|
-
}).catch(function(e){
|
|
1933
|
-
if (btn){ btn.disabled = false; btn.textContent = origText || 'Accept'; }
|
|
1934
|
-
statsEl.textContent = 'Apply error: ' + e.message;
|
|
1935
|
-
});
|
|
1936
|
-
}
|
|
1937
|
-
|
|
1938
|
-
function renderRun(run){
|
|
1939
|
-
var box = el('div', 'dream-run');
|
|
1940
|
-
var head = el('div', 'dream-run-head');
|
|
1941
|
-
if (run.agent) head.appendChild(el('span', 'agent', run.agent));
|
|
1942
|
-
var modeCls = run.mode === 'auto' ? 'auto' : 'propose';
|
|
1943
|
-
head.appendChild(el('span', 'dream-badge ' + modeCls, run.mode));
|
|
1944
|
-
head.appendChild(el('span', 'dream-badge outcome', run.outcome));
|
|
1945
|
-
head.appendChild(el('span', 'when', run.iso));
|
|
1946
|
-
|
|
1947
|
-
// Pending = a propose-run proposal not yet manually accepted. Accept-all
|
|
1948
|
-
// shows only when there is something to apply.
|
|
1949
|
-
var pending = (run.proposals || []).filter(function(p){ return run.mode !== 'auto' && !p.accepted; });
|
|
1950
|
-
if (pending.length){
|
|
1951
|
-
var allBtn = el('button', 'dream-accept-all', 'Accept all (' + pending.length + ')');
|
|
1952
|
-
allBtn.title = 'Apply every pending proposal in this run to memory';
|
|
1953
|
-
allBtn.addEventListener('click', function(){
|
|
1954
|
-
acceptDreams(run.agent, run.ts, pending.map(function(p){ return p.index; }), allBtn);
|
|
1955
|
-
});
|
|
1956
|
-
head.appendChild(allBtn);
|
|
1957
|
-
}
|
|
1958
|
-
box.appendChild(head);
|
|
1959
|
-
|
|
1960
|
-
if (run.summary) box.appendChild(el('div', 'dream-summary', run.summary));
|
|
1961
|
-
|
|
1962
|
-
if (run.proposals && run.proposals.length){
|
|
1963
|
-
var props = el('div', 'dream-props');
|
|
1964
|
-
run.proposals.forEach(function(p){
|
|
1965
|
-
var pe = el('div', 'dream-prop' + (p.accepted ? ' accepted' : ''));
|
|
1966
|
-
var top = el('div');
|
|
1967
|
-
top.appendChild(el('span', 'op ' + (p.op || ''), p.op || '?'));
|
|
1968
|
-
top.appendChild(el('span', 'file', p.file || ''));
|
|
1969
|
-
top.appendChild(el('span', 'score', 'score ' + (p.score != null ? p.score : '?') + ' · recall ' + (p.recallCount != null ? p.recallCount : '?')));
|
|
1970
|
-
pe.appendChild(top);
|
|
1971
|
-
if (p.reason) pe.appendChild(el('div', 'reason', p.reason));
|
|
1972
|
-
if (p.target) pe.appendChild(el('div', 'anchor', 'anchor: ' + p.target));
|
|
1973
|
-
if (p.content) pe.appendChild(el('div', 'content', p.content));
|
|
1974
|
-
|
|
1975
|
-
// Per-proposal status + accept action.
|
|
1976
|
-
var actions = el('div', 'dream-prop-actions');
|
|
1977
|
-
if (p.accepted){
|
|
1978
|
-
actions.appendChild(el('span', 'prop-status applied', '✓ applied'));
|
|
1979
|
-
} else if (run.mode === 'auto'){
|
|
1980
|
-
actions.appendChild(el('span', 'prop-status applied-auto', '✓ applied (auto)'));
|
|
1981
|
-
} else {
|
|
1982
|
-
actions.appendChild(el('span', 'prop-status pending', 'pending'));
|
|
1983
|
-
var accBtn = el('button', 'dream-accept-btn', 'Accept');
|
|
1984
|
-
accBtn.title = 'Apply this proposal to ' + (p.file || 'memory');
|
|
1985
|
-
accBtn.addEventListener('click', function(){
|
|
1986
|
-
acceptDreams(run.agent, run.ts, [p.index], accBtn);
|
|
1987
|
-
});
|
|
1988
|
-
actions.appendChild(accBtn);
|
|
1989
|
-
}
|
|
1990
|
-
pe.appendChild(actions);
|
|
1991
|
-
props.appendChild(pe);
|
|
1992
|
-
});
|
|
1993
|
-
box.appendChild(props);
|
|
1994
|
-
}
|
|
1995
|
-
|
|
1996
|
-
var applied = (run.applied != null) ? (', applied ' + run.applied) : '';
|
|
1997
|
-
box.appendChild(el('div', 'dream-meta', 'tokens ' + (run.tokens||0) + ' · sessions ' + (run.sessions||0) + applied));
|
|
1998
|
-
return box;
|
|
1999
|
-
}
|
|
2000
|
-
|
|
2001
|
-
function render(){
|
|
2002
|
-
var filter = agentSel ? agentSel.value : '';
|
|
2003
|
-
var runs = filter ? allRuns.filter(function(r){ return r.agent === filter; }) : allRuns;
|
|
2004
|
-
listEl.textContent = '';
|
|
2005
|
-
if (!runs.length){
|
|
2006
|
-
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).';
|
|
2007
|
-
emptyEl.style.display = '';
|
|
2008
|
-
statsEl.textContent = '';
|
|
2009
|
-
return;
|
|
2010
|
-
}
|
|
2011
|
-
emptyEl.style.display = 'none';
|
|
2012
|
-
var pendingTotal = 0;
|
|
2013
|
-
runs.forEach(function(r){
|
|
2014
|
-
if (r.mode === 'auto') return;
|
|
2015
|
-
(r.proposals || []).forEach(function(p){ if (!p.accepted) pendingTotal++; });
|
|
2016
|
-
});
|
|
2017
|
-
statsEl.textContent = runs.length + ' run' + (runs.length === 1 ? '' : 's')
|
|
2018
|
-
+ (pendingTotal ? ' · ' + pendingTotal + ' pending' : '');
|
|
2019
|
-
if (pendingNotice){
|
|
2020
|
-
statsEl.textContent += ' — ' + pendingNotice;
|
|
2021
|
-
pendingNotice = '';
|
|
2022
|
-
}
|
|
2023
|
-
runs.forEach(function(r){ listEl.appendChild(renderRun(r)); });
|
|
2024
|
-
}
|
|
2025
|
-
|
|
2026
|
-
function loadDreams(force){
|
|
2027
|
-
if (loaded && !force) return;
|
|
2028
|
-
loaded = true;
|
|
2029
|
-
statsEl.textContent = 'Loading…';
|
|
2030
|
-
fetch(apiUrl('/knowledge/dreams'), { headers: { 'Accept': 'application/json' } }).then(function(res){
|
|
2031
|
-
if (res.status === 401) { onUnauthorized(); return null; }
|
|
2032
|
-
if (!res.ok) throw new Error('HTTP ' + res.status);
|
|
2033
|
-
return res.json();
|
|
2034
|
-
}).then(function(data){
|
|
2035
|
-
if (!data) return;
|
|
2036
|
-
allRuns = data.runs || [];
|
|
2037
|
-
// Populate the agent filter, preserving the current pick.
|
|
2038
|
-
if (agentSel){
|
|
2039
|
-
var prev = agentSel.value;
|
|
2040
|
-
agentSel.textContent = '';
|
|
2041
|
-
agentSel.appendChild(el('option', null, 'All agents')); agentSel.lastChild.value = '';
|
|
2042
|
-
(data.agents || []).forEach(function(a){ var o = el('option', null, a); o.value = a; agentSel.appendChild(o); });
|
|
2043
|
-
agentSel.value = prev; if (agentSel.value !== prev) agentSel.value = '';
|
|
2044
|
-
}
|
|
2045
|
-
render();
|
|
2046
|
-
}).catch(function(err){
|
|
2047
|
-
statsEl.textContent = ''; emptyEl.textContent = 'Failed to load dreams: ' + err.message; emptyEl.style.display = '';
|
|
2048
|
-
});
|
|
2049
|
-
}
|
|
2050
|
-
|
|
2051
|
-
if (agentSel) agentSel.addEventListener('change', render);
|
|
2052
|
-
if (refreshBtn) refreshBtn.addEventListener('click', function(){ loadDreams(true); });
|
|
2053
|
-
// Exposed so the tab switcher (in the kb-graph script) can lazy-load on first open.
|
|
2054
|
-
window.__loadDreams = loadDreams;
|
|
2055
|
-
})();
|
|
2056
|
-
</script>
|
|
1764
|
+
<script id="kb-dreams">${memory_activity_1.memoryActivityClient}</script>
|
|
2057
1765
|
</body>
|
|
2058
1766
|
</html>`;
|
|
2059
1767
|
}
|
|
@@ -2072,15 +1780,15 @@ function generateLoginHtml(disabledReason = '') {
|
|
|
2072
1780
|
? ` <h1>Claude Gateway</h1>
|
|
2073
1781
|
<div class="sub">${safeReason}</div>`
|
|
2074
1782
|
: ` <h1>Claude Gateway</h1>
|
|
2075
|
-
<div class="sub">
|
|
1783
|
+
<div class="sub">Sign in with your admin API key to inspect agents, workers and usage.</div>
|
|
2076
1784
|
<form id="login-form" autocomplete="off">
|
|
2077
|
-
<label for="key">API key</label>
|
|
2078
|
-
<input id="key" type="password" placeholder="
|
|
1785
|
+
<label for="key">Admin API key</label>
|
|
1786
|
+
<input id="key" type="password" placeholder="Enter your admin API key" required autocomplete="current-password" autofocus>
|
|
2079
1787
|
<button type="submit">Sign in</button>
|
|
2080
|
-
<div id="err"></div>
|
|
1788
|
+
<div id="err" role="alert" aria-live="polite"></div>
|
|
2081
1789
|
</form>`;
|
|
2082
1790
|
return `<!DOCTYPE html>
|
|
2083
|
-
<html lang="en">
|
|
1791
|
+
<html lang="en" data-theme="light">
|
|
2084
1792
|
<head>
|
|
2085
1793
|
<meta charset="UTF-8">
|
|
2086
1794
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
@@ -2110,12 +1818,12 @@ function generateLoginHtml(disabledReason = '') {
|
|
|
2110
1818
|
}
|
|
2111
1819
|
button:hover { background: #2b6cb0; }
|
|
2112
1820
|
#err { color: #fc8181; font-size: 0.8rem; margin-top: 12px; min-height: 1em; }
|
|
1821
|
+
${dashboard_theme_1.dashboardTheme}
|
|
1822
|
+
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
1823
|
</style>
|
|
2114
|
-
</head>
|
|
1824
|
+
${dashboard_theme_1.dashboardFontLink}</head>
|
|
2115
1825
|
<body>
|
|
2116
|
-
<div class="card">
|
|
2117
|
-
${bodyInner}
|
|
2118
|
-
</div>
|
|
1826
|
+
<main class="login-layout"><section class="login-intro"><div class="brand row" style="padding:0"><div class="brandmark" aria-hidden="true">✳</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
1827
|
<script>
|
|
2120
1828
|
function basePath() {
|
|
2121
1829
|
var p = window.location.pathname;
|
|
@@ -2129,17 +1837,29 @@ ${bodyInner}
|
|
|
2129
1837
|
var err = document.getElementById('err');
|
|
2130
1838
|
err.textContent = '';
|
|
2131
1839
|
var key = document.getElementById('key').value;
|
|
1840
|
+
var button = loginForm.querySelector('button'); button.disabled = true;
|
|
2132
1841
|
try {
|
|
2133
1842
|
var res = await fetch(basePath() + '/dashboard/login', {
|
|
2134
1843
|
method: 'POST',
|
|
2135
1844
|
headers: { 'Content-Type': 'application/json' },
|
|
2136
1845
|
body: JSON.stringify({ key: key }),
|
|
2137
1846
|
});
|
|
2138
|
-
if (res.ok) {
|
|
1847
|
+
if (res.ok) {
|
|
1848
|
+
var root = basePath() + '/dashboard';
|
|
1849
|
+
var target = new URL(window.location.href);
|
|
1850
|
+
var requested = target.searchParams.get('returnTo');
|
|
1851
|
+
if (requested) {
|
|
1852
|
+
var candidate = new URL(requested, window.location.origin + root + '/');
|
|
1853
|
+
if (candidate.origin === window.location.origin && candidate.pathname === root + '/token-report') target = candidate;
|
|
1854
|
+
else target = new URL(root, window.location.origin);
|
|
1855
|
+
}
|
|
1856
|
+
target.searchParams.delete('returnTo');
|
|
1857
|
+
window.location.replace(target.pathname + target.search + target.hash); return;
|
|
1858
|
+
}
|
|
2139
1859
|
err.textContent = res.status === 401 ? 'Invalid API key.' : ('Login failed (HTTP ' + res.status + ').');
|
|
2140
1860
|
} catch (e2) {
|
|
2141
|
-
err.textContent = '
|
|
2142
|
-
}
|
|
1861
|
+
err.textContent = 'Unable to connect. Please try again.';
|
|
1862
|
+
} finally { button.disabled = false; }
|
|
2143
1863
|
});
|
|
2144
1864
|
</script>
|
|
2145
1865
|
</body>
|