abtars 0.1.0-alpha.1
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/LICENSE +190 -0
- package/README.md +84 -0
- package/bundle/_registry.generated-M4WY2MMI.js +35 -0
- package/bundle/_registry.generated-M4WY2MMI.js.map +7 -0
- package/bundle/abtars-browser.js +162 -0
- package/bundle/abtars-browser.js.map +7 -0
- package/bundle/abtars-cli.js +1438 -0
- package/bundle/abtars-cli.js.map +7 -0
- package/bundle/abtars-restart.js +12 -0
- package/bundle/abtars-restart.js.map +7 -0
- package/bundle/abtars-rss.js +165 -0
- package/bundle/abtars-rss.js.map +7 -0
- package/bundle/abtars-task.js +258 -0
- package/bundle/abtars-task.js.map +7 -0
- package/bundle/abtars.js +4072 -0
- package/bundle/abtars.js.map +7 -0
- package/bundle/agent-api-rate-limit-OQNFMXTZ.js +38 -0
- package/bundle/agent-api-rate-limit-OQNFMXTZ.js.map +7 -0
- package/bundle/agent-registry-LT4JNQH6.js +18 -0
- package/bundle/agent-registry-LT4JNQH6.js.map +7 -0
- package/bundle/agents/default.md +29 -0
- package/bundle/anthropic-adapter-2APTH3LA.js +40 -0
- package/bundle/anthropic-adapter-2APTH3LA.js.map +7 -0
- package/bundle/bridge-lock-transport-4AC2G5G6.js +39 -0
- package/bundle/bridge-lock-transport-4AC2G5G6.js.map +7 -0
- package/bundle/browse-delivery-JXBY36GK.js +17 -0
- package/bundle/browse-delivery-JXBY36GK.js.map +7 -0
- package/bundle/browser-ELNDVPLC.js +18 -0
- package/bundle/browser-ELNDVPLC.js.map +7 -0
- package/bundle/capability-CIL3G4FI.js +17 -0
- package/bundle/capability-CIL3G4FI.js.map +7 -0
- package/bundle/chunk-265TPOPC.js +289 -0
- package/bundle/chunk-265TPOPC.js.map +7 -0
- package/bundle/chunk-2UENBO6M.js +223 -0
- package/bundle/chunk-2UENBO6M.js.map +7 -0
- package/bundle/chunk-2UPU3OW6.js +67 -0
- package/bundle/chunk-2UPU3OW6.js.map +7 -0
- package/bundle/chunk-2XU2X4OI.js +125 -0
- package/bundle/chunk-2XU2X4OI.js.map +7 -0
- package/bundle/chunk-3B7BBE4F.js +758 -0
- package/bundle/chunk-3B7BBE4F.js.map +7 -0
- package/bundle/chunk-3E545J66.js +69 -0
- package/bundle/chunk-3E545J66.js.map +7 -0
- package/bundle/chunk-5R2ANXQ7.js +510 -0
- package/bundle/chunk-5R2ANXQ7.js.map +7 -0
- package/bundle/chunk-6CPN4IGS.js +507 -0
- package/bundle/chunk-6CPN4IGS.js.map +7 -0
- package/bundle/chunk-6NR3OHEW.js +88 -0
- package/bundle/chunk-6NR3OHEW.js.map +7 -0
- package/bundle/chunk-6SETMHNN.js +206 -0
- package/bundle/chunk-6SETMHNN.js.map +7 -0
- package/bundle/chunk-6UCRKRWR.js +644 -0
- package/bundle/chunk-6UCRKRWR.js.map +7 -0
- package/bundle/chunk-AR6GO6YC.js +83 -0
- package/bundle/chunk-AR6GO6YC.js.map +7 -0
- package/bundle/chunk-AZJIODTQ.js +54 -0
- package/bundle/chunk-AZJIODTQ.js.map +7 -0
- package/bundle/chunk-BHMZ4RCC.js +3706 -0
- package/bundle/chunk-BHMZ4RCC.js.map +7 -0
- package/bundle/chunk-BQ2L4GMG.js +9175 -0
- package/bundle/chunk-BQ2L4GMG.js.map +7 -0
- package/bundle/chunk-BSSBCSCL.js +159 -0
- package/bundle/chunk-BSSBCSCL.js.map +7 -0
- package/bundle/chunk-BUUVFUPO.js +157 -0
- package/bundle/chunk-BUUVFUPO.js.map +7 -0
- package/bundle/chunk-CEVRHKJY.js +131 -0
- package/bundle/chunk-CEVRHKJY.js.map +7 -0
- package/bundle/chunk-CWOHNFUV.js +39 -0
- package/bundle/chunk-CWOHNFUV.js.map +7 -0
- package/bundle/chunk-D2DCBO6M.js +228 -0
- package/bundle/chunk-D2DCBO6M.js.map +7 -0
- package/bundle/chunk-FMWKEPM7.js +31 -0
- package/bundle/chunk-FMWKEPM7.js.map +7 -0
- package/bundle/chunk-GRNENTPA.js +145 -0
- package/bundle/chunk-GRNENTPA.js.map +7 -0
- package/bundle/chunk-GST5T3WZ.js +93 -0
- package/bundle/chunk-GST5T3WZ.js.map +7 -0
- package/bundle/chunk-GUQVJC3U.js +299 -0
- package/bundle/chunk-GUQVJC3U.js.map +7 -0
- package/bundle/chunk-HX7Y7EYP.js +3659 -0
- package/bundle/chunk-HX7Y7EYP.js.map +7 -0
- package/bundle/chunk-JCJS4ZIB.js +296 -0
- package/bundle/chunk-JCJS4ZIB.js.map +7 -0
- package/bundle/chunk-JW6RU47G.js +184 -0
- package/bundle/chunk-JW6RU47G.js.map +7 -0
- package/bundle/chunk-LSPKJQCI.js +24 -0
- package/bundle/chunk-LSPKJQCI.js.map +7 -0
- package/bundle/chunk-M6VBAPNT.js +16 -0
- package/bundle/chunk-M6VBAPNT.js.map +7 -0
- package/bundle/chunk-MPX525QO.js +129 -0
- package/bundle/chunk-MPX525QO.js.map +7 -0
- package/bundle/chunk-MW6WDLU7.js +130 -0
- package/bundle/chunk-MW6WDLU7.js.map +7 -0
- package/bundle/chunk-NT3OBORC.js +215 -0
- package/bundle/chunk-NT3OBORC.js.map +7 -0
- package/bundle/chunk-NWDBD4PA.js +50 -0
- package/bundle/chunk-NWDBD4PA.js.map +7 -0
- package/bundle/chunk-OP7BTAWY.js +29 -0
- package/bundle/chunk-OP7BTAWY.js.map +7 -0
- package/bundle/chunk-PLCY3GFH.js +77 -0
- package/bundle/chunk-PLCY3GFH.js.map +7 -0
- package/bundle/chunk-PNEDC45Y.js +97 -0
- package/bundle/chunk-PNEDC45Y.js.map +7 -0
- package/bundle/chunk-QBGBT5QS.js +81 -0
- package/bundle/chunk-QBGBT5QS.js.map +7 -0
- package/bundle/chunk-RVE2N7FA.js +70 -0
- package/bundle/chunk-RVE2N7FA.js.map +7 -0
- package/bundle/chunk-TZHIDLDS.js +71910 -0
- package/bundle/chunk-TZHIDLDS.js.map +7 -0
- package/bundle/chunk-UCQ2WC3B.js +126 -0
- package/bundle/chunk-UCQ2WC3B.js.map +7 -0
- package/bundle/chunk-UHRP745J.js +214 -0
- package/bundle/chunk-UHRP745J.js.map +7 -0
- package/bundle/chunk-V76TVMCM.js +58 -0
- package/bundle/chunk-V76TVMCM.js.map +7 -0
- package/bundle/chunk-VVEDVGCR.js +981 -0
- package/bundle/chunk-VVEDVGCR.js.map +7 -0
- package/bundle/chunk-W6FAL35D.js +102 -0
- package/bundle/chunk-W6FAL35D.js.map +7 -0
- package/bundle/chunk-X6TERNVJ.js +15902 -0
- package/bundle/chunk-X6TERNVJ.js.map +7 -0
- package/bundle/chunk-X76UX47U.js +47 -0
- package/bundle/chunk-X76UX47U.js.map +7 -0
- package/bundle/chunk-XREWVCUO.js +518 -0
- package/bundle/chunk-XREWVCUO.js.map +7 -0
- package/bundle/chunk-Y6XAEX2Q.js +408 -0
- package/bundle/chunk-Y6XAEX2Q.js.map +7 -0
- package/bundle/chunk-YOCTDKKL.js +28 -0
- package/bundle/chunk-YOCTDKKL.js.map +7 -0
- package/bundle/chunk-ZXPXCDA6.js +160 -0
- package/bundle/chunk-ZXPXCDA6.js.map +7 -0
- package/bundle/commands-BHVUOU3V.js +31 -0
- package/bundle/commands-BHVUOU3V.js.map +7 -0
- package/bundle/completion-buffer-P253ONKF.js +13 -0
- package/bundle/completion-buffer-P253ONKF.js.map +7 -0
- package/bundle/config-RGSDAPZN.js +19 -0
- package/bundle/config-RGSDAPZN.js.map +7 -0
- package/bundle/config-show-ERTATR6E.js +40 -0
- package/bundle/config-show-ERTATR6E.js.map +7 -0
- package/bundle/context-HCEGZNDC.js +72 -0
- package/bundle/context-HCEGZNDC.js.map +7 -0
- package/bundle/delegation-tools-GYTS2D6A.js +27 -0
- package/bundle/delegation-tools-GYTS2D6A.js.map +7 -0
- package/bundle/deploy-lib-import-32ZFKHWP.js +49 -0
- package/bundle/deploy-lib-import-32ZFKHWP.js.map +7 -0
- package/bundle/digital-signature-OFCGSHWO.js +13 -0
- package/bundle/digital-signature-OFCGSHWO.js.map +7 -0
- package/bundle/direct-api-transport-YR7SXXNN.js +860 -0
- package/bundle/direct-api-transport-YR7SXXNN.js.map +7 -0
- package/bundle/discord-adapter-YYWVMPPU.js +584 -0
- package/bundle/discord-adapter-YYWVMPPU.js.map +7 -0
- package/bundle/dist-MTMKARCP.js +1969 -0
- package/bundle/dist-MTMKARCP.js.map +7 -0
- package/bundle/dns-wakeup-27M7D2MR.js +107 -0
- package/bundle/dns-wakeup-27M7D2MR.js.map +7 -0
- package/bundle/doctor-QNUSDY73.js +248 -0
- package/bundle/doctor-QNUSDY73.js.map +7 -0
- package/bundle/ensure-invariants-NMXNS476.js +49 -0
- package/bundle/ensure-invariants-NMXNS476.js.map +7 -0
- package/bundle/env-schema-2KBHBDGN.js +19 -0
- package/bundle/env-schema-2KBHBDGN.js.map +7 -0
- package/bundle/esm-DDP6NCZG.js +100663 -0
- package/bundle/esm-DDP6NCZG.js.map +7 -0
- package/bundle/fallback-policy-L4QV2PEJ.js +46 -0
- package/bundle/fallback-policy-L4QV2PEJ.js.map +7 -0
- package/bundle/health-check-SPA7NT6N.js +56 -0
- package/bundle/health-check-SPA7NT6N.js.map +7 -0
- package/bundle/hook-system-6Q5YTR53.js +17 -0
- package/bundle/hook-system-6Q5YTR53.js.map +7 -0
- package/bundle/hotskills-K7BM4YLB.js +12 -0
- package/bundle/hotskills-K7BM4YLB.js.map +7 -0
- package/bundle/install-6HRZVKUM.js +15 -0
- package/bundle/install-6HRZVKUM.js.map +7 -0
- package/bundle/install-log-IAPHYKD4.js +28 -0
- package/bundle/install-log-IAPHYKD4.js.map +7 -0
- package/bundle/install-manifest-SPQRUNXL.js +102 -0
- package/bundle/install-manifest-SPQRUNXL.js.map +7 -0
- package/bundle/install-validate-PVLZXYLQ.js +53 -0
- package/bundle/install-validate-PVLZXYLQ.js.map +7 -0
- package/bundle/irc-adapter-OI5UZSQF.js +293 -0
- package/bundle/irc-adapter-OI5UZSQF.js.map +7 -0
- package/bundle/irc-config-55YO6EGB.js +88 -0
- package/bundle/irc-config-55YO6EGB.js.map +7 -0
- package/bundle/logs-ZNYXX5PA.js +19 -0
- package/bundle/logs-ZNYXX5PA.js.map +7 -0
- package/bundle/media-utils-XNNDTYFI.js +4662 -0
- package/bundle/media-utils-XNNDTYFI.js.map +7 -0
- package/bundle/message-pipeline-LLH5SYMO.js +33 -0
- package/bundle/message-pipeline-LLH5SYMO.js.map +7 -0
- package/bundle/meta.json +41304 -0
- package/bundle/model-health-registry-35LQNVQR.js +11 -0
- package/bundle/model-health-registry-35LQNVQR.js.map +7 -0
- package/bundle/notification-Y5S5MMLV.js +13 -0
- package/bundle/notification-Y5S5MMLV.js.map +7 -0
- package/bundle/openrouter-credits-EDY7ETAU.js +32 -0
- package/bundle/openrouter-credits-EDY7ETAU.js.map +7 -0
- package/bundle/passwd-RRFV4CC5.js +133 -0
- package/bundle/passwd-RRFV4CC5.js.map +7 -0
- package/bundle/paths-G33RZWZ7.js +17 -0
- package/bundle/paths-G33RZWZ7.js.map +7 -0
- package/bundle/peer-client-52XYMNI7.js +156 -0
- package/bundle/peer-client-52XYMNI7.js.map +7 -0
- package/bundle/peer-config-VK6EDLN5.js +16 -0
- package/bundle/peer-config-VK6EDLN5.js.map +7 -0
- package/bundle/peer-sessions-EAXTNQ36.js +49 -0
- package/bundle/peer-sessions-EAXTNQ36.js.map +7 -0
- package/bundle/pending-callback-RIMQZ7FJ.js +40 -0
- package/bundle/pending-callback-RIMQZ7FJ.js.map +7 -0
- package/bundle/phase-transport-KYERDL2O.js +22 -0
- package/bundle/phase-transport-KYERDL2O.js.map +7 -0
- package/bundle/public/css/dashboard.css +542 -0
- package/bundle/public/index.html +180 -0
- package/bundle/public/js/app.js +437 -0
- package/bundle/public/memory-universe.js +384 -0
- package/bundle/responses-adapter-AAQTY3K4.js +30 -0
- package/bundle/responses-adapter-AAQTY3K4.js.map +7 -0
- package/bundle/restore-ZE3SEPSS.js +46 -0
- package/bundle/restore-ZE3SEPSS.js.map +7 -0
- package/bundle/self-healer-utils-DMUUXC47.js +43 -0
- package/bundle/self-healer-utils-DMUUXC47.js.map +7 -0
- package/bundle/skill-stats-LLEXEXLR.js +22 -0
- package/bundle/skill-stats-LLEXEXLR.js.map +7 -0
- package/bundle/sleep-OYIUOVQD.js +19 -0
- package/bundle/sleep-OYIUOVQD.js.map +7 -0
- package/bundle/soul-loader-54WCVNLJ.js +16 -0
- package/bundle/soul-loader-54WCVNLJ.js.map +7 -0
- package/bundle/src-JL4PVO23.js +8 -0
- package/bundle/src-JL4PVO23.js.map +7 -0
- package/bundle/sse-parser-anthropic-P7CE2MH2.js +72 -0
- package/bundle/sse-parser-anthropic-P7CE2MH2.js.map +7 -0
- package/bundle/sse-parser-responses-EQQA5FWN.js +63 -0
- package/bundle/sse-parser-responses-EQQA5FWN.js.map +7 -0
- package/bundle/ssrf-guard-FZCBYIVW.js +64 -0
- package/bundle/ssrf-guard-FZCBYIVW.js.map +7 -0
- package/bundle/start-FH3GRMJ4.js +35 -0
- package/bundle/start-FH3GRMJ4.js.map +7 -0
- package/bundle/stream-single-WSG4D53C.js +33 -0
- package/bundle/stream-single-WSG4D53C.js.map +7 -0
- package/bundle/stt-2UH3RITX.js +14 -0
- package/bundle/stt-2UH3RITX.js.map +7 -0
- package/bundle/subagent-runtime-LE2ZXH3G.js +12 -0
- package/bundle/subagent-runtime-LE2ZXH3G.js.map +7 -0
- package/bundle/system-message-T5R3EYYN.js +30 -0
- package/bundle/system-message-T5R3EYYN.js.map +7 -0
- package/bundle/system-status-KQ6KHFJ6.js +189 -0
- package/bundle/system-status-KQ6KHFJ6.js.map +7 -0
- package/bundle/task-store-K7CQDEPI.js +22 -0
- package/bundle/task-store-K7CQDEPI.js.map +7 -0
- package/bundle/telegram-adapter-2V3XUMT5.js +1060 -0
- package/bundle/telegram-adapter-2V3XUMT5.js.map +7 -0
- package/bundle/tool-registry-MU3OX4UI.js +38 -0
- package/bundle/tool-registry-MU3OX4UI.js.map +7 -0
- package/bundle/tool-sandbox-VYOK4ZOA.js +20 -0
- package/bundle/tool-sandbox-VYOK4ZOA.js.map +7 -0
- package/bundle/transport-config-YLXU33RO.js +57 -0
- package/bundle/transport-config-YLXU33RO.js.map +7 -0
- package/bundle/update-QCW5LXRN.js +13 -0
- package/bundle/update-QCW5LXRN.js.map +7 -0
- package/bundle/update-check-27KZSAP6.js +12 -0
- package/bundle/update-check-27KZSAP6.js.map +7 -0
- package/bundle/usage-tracker-OVVEVMOY.js +17 -0
- package/bundle/usage-tracker-OVVEVMOY.js.map +7 -0
- package/bundle/user-registry-D4SD73UV.js +16 -0
- package/bundle/user-registry-D4SD73UV.js.map +7 -0
- package/core/professor.json +14 -0
- package/core/prompts/browsing_prompt.md +39 -0
- package/core/prompts/compaction.md +32 -0
- package/core/skills/memory/classification/SKILL.md +37 -0
- package/core/skills/memory/memory-anomalies/SKILL.md +39 -0
- package/core/skills/memory/memory-search/SKILL.md +48 -0
- package/core/skills/memory/topic-save/SKILL.md +44 -0
- package/core/skills/ops/cron/SKILL.md +51 -0
- package/core/skills/ops/gdrive-backup/SKILL.md +15 -0
- package/core/skills/ops/session-start/SKILL.md +11 -0
- package/core/skills/ops/skill-authoring/SKILL.md +54 -0
- package/core/skills/ops/system-health/SKILL.md +104 -0
- package/core/skills/ops/troubleshooting/SKILL.md +48 -0
- package/core/skills/ops/trust-gating/SKILL.md +30 -0
- package/core/skills/tools/a2a-communication/SKILL.md +68 -0
- package/core/skills/tools/browse-delegate/SKILL.md +27 -0
- package/core/skills/tools/browser/SKILL.md +36 -0
- package/core/skills/tools/clawhub/SKILL.md +44 -0
- package/core/skills/tools/delegation/SKILL.md +48 -0
- package/core/skills/tools/fxtwitter/SKILL.md +52 -0
- package/core/skills/tools/gmail/SKILL.md +44 -0
- package/core/skills/tools/irc-chat/SKILL.md +84 -0
- package/core/skills/tools/linear/SKILL.md +90 -0
- package/core/skills/tools/mcporter/SKILL.md +46 -0
- package/core/skills/tools/model-scout/SKILL.md +132 -0
- package/core/skills/tools/model-scout/scout-add-model.py +67 -0
- package/core/skills/tools/model-scout/scout-ollama.py +116 -0
- package/core/skills/tools/model-scout/scout-openrouter.py +85 -0
- package/core/skills/tools/nlm/SKILL.md +40 -0
- package/core/skills/tools/todo/SKILL.md +30 -0
- package/core/skills/tools/twitterX/SKILL.md +52 -0
- package/core/skills/tools/twitterX/scripts/abtars-tweet.js +532 -0
- package/core/skills/tools/twitterX/scripts/package.json +1 -0
- package/core/skills/tools/web-fetch/SKILL.md +29 -0
- package/package.json +59 -0
- package/scripts/abtars-daemon.service +23 -0
- package/scripts/abtars-fetch.sh +42 -0
- package/scripts/abtars-watchdog.service +13 -0
- package/scripts/abtars.sh +14 -0
- package/scripts/abtars@.service +21 -0
- package/scripts/browser-patchright.sh +79 -0
- package/scripts/com.abtars.daemon.plist +24 -0
- package/scripts/com.abtars.watchdog.plist +27 -0
- package/scripts/daily-backup.sh +62 -0
- package/scripts/doctor.sh +553 -0
- package/scripts/hooks/audit-logger.sh +22 -0
- package/scripts/upgrade-deps.sh +64 -0
- package/scripts/watchdog.sh +309 -0
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>abTARS Dashboard</title>
|
|
7
|
+
<link rel="stylesheet" href="/css/dashboard.css">
|
|
8
|
+
</head>
|
|
9
|
+
<body data-has-agent-api="false" data-agent-api-port="">
|
|
10
|
+
<header>
|
|
11
|
+
<img src="/assets/logo.png" alt="" onerror="this.style.display='none'">
|
|
12
|
+
<h1>abTARS Dashboard</h1>
|
|
13
|
+
</header>
|
|
14
|
+
<div id="connection-banner" class="connection-banner" style="display:none;">
|
|
15
|
+
Connection lost. Reconnecting<span id="reconnect-dots">...</span>
|
|
16
|
+
</div>
|
|
17
|
+
<main class="grid">
|
|
18
|
+
|
|
19
|
+
<!-- Bridge Health -->
|
|
20
|
+
<div class="card card-split" id="card-health">
|
|
21
|
+
<div class="split-top">
|
|
22
|
+
<h2>Bridge Health</h2>
|
|
23
|
+
<div class="stat-row"><span class="stat-label">Version</span><span class="stat-value" id="health-version">—</span></div>
|
|
24
|
+
<div class="stat-row"><span class="stat-label">Uptime</span><span class="stat-value" id="health-uptime">—</span></div>
|
|
25
|
+
<div class="stat-row"><span class="stat-label">Model</span><span class="stat-value" id="health-model">—</span></div>
|
|
26
|
+
<div class="stat-row"><span class="stat-label">Enabled Platforms</span><span class="stat-value" id="health-platforms">—</span></div>
|
|
27
|
+
<div class="stat-row"><span class="stat-label">Heartbeat</span><span class="stat-value" id="hb-status">—</span></div>
|
|
28
|
+
<div id="hb-tasks" style="margin-top:6px;"></div>
|
|
29
|
+
<div class="stat-row"><span class="stat-label">Last Update</span><span class="stat-value" id="health-timestamp">—</span></div>
|
|
30
|
+
</div>
|
|
31
|
+
<hr class="split-divider">
|
|
32
|
+
<div class="split-bottom">
|
|
33
|
+
<h2>Transport</h2>
|
|
34
|
+
<div class="stat-row"><span class="stat-label">Type</span><span class="stat-value" id="transport-type">—</span></div>
|
|
35
|
+
<div class="stat-row"><span class="stat-label">Connection</span><span class="stat-value" id="transport-state"><span class="indicator red"></span> disconnected</span></div>
|
|
36
|
+
<div style="margin-top:10px;">
|
|
37
|
+
<span class="stat-label">Context Window</span>
|
|
38
|
+
<div class="progress-bar-bg"><div class="progress-bar-fill" id="transport-ctx-bar" style="width:0%"></div></div>
|
|
39
|
+
<div style="text-align:right;font-size:0.75rem;color:#9e9e9e;margin-top:2px;"><span id="transport-ctx-pct">—</span></div>
|
|
40
|
+
</div>
|
|
41
|
+
</div>
|
|
42
|
+
</div>
|
|
43
|
+
|
|
44
|
+
<!-- Subsystem Health Grid -->
|
|
45
|
+
<div class="card" id="card-subsystems">
|
|
46
|
+
<h2>🏥 Subsystems</h2>
|
|
47
|
+
<div id="subsystem-grid" style="font-size:0.82rem;line-height:1.8;font-family:monospace;"></div>
|
|
48
|
+
<hr style="border-color:#0f3460;margin:12px 0;">
|
|
49
|
+
<div style="display:flex;gap:8px;flex-wrap:wrap;">
|
|
50
|
+
<button class="btn-search-toggle" data-action="toggle-overlay" data-target="log-overlay">📋 Log</button>
|
|
51
|
+
</div>
|
|
52
|
+
<hr style="border-color:#0f3460;margin:12px 0;">
|
|
53
|
+
<h2>Memory</h2>
|
|
54
|
+
<div id="memory-stats">
|
|
55
|
+
<div class="stat-row"><span class="stat-label">Status</span><span class="stat-value" id="mem-status">—</span></div>
|
|
56
|
+
<div class="stat-row"><span class="stat-label">Messages</span><span class="stat-value" id="mem-messages">—</span></div>
|
|
57
|
+
<div class="stat-row"><span class="stat-label">Extracted</span><span class="stat-value" id="mem-extracted">—</span></div>
|
|
58
|
+
<div class="stat-row"><span class="stat-label">Consolidations (D/W/Q)</span><span class="stat-value" id="mem-consolidations">—</span></div>
|
|
59
|
+
<div class="stat-row"><span class="stat-label">Documents</span><span class="stat-value" id="mem-documents">—</span></div>
|
|
60
|
+
<div class="stat-row"><span class="stat-label">DB Size</span><span class="stat-value" id="mem-dbsize">—</span></div>
|
|
61
|
+
</div>
|
|
62
|
+
<hr style="border-color:#0f3460;margin:12px 0;">
|
|
63
|
+
<div style="display:flex;gap:8px;flex-wrap:wrap;">
|
|
64
|
+
<button class="btn-search-toggle" data-action="load-universe">🌌 Universe</button>
|
|
65
|
+
<button class="btn-search-toggle" data-action="toggle-overlay" data-target="search-overlay">🔍 Search</button>
|
|
66
|
+
</div>
|
|
67
|
+
</div>
|
|
68
|
+
|
|
69
|
+
<!-- Platforms -->
|
|
70
|
+
<div class="card" id="card-platforms">
|
|
71
|
+
<h2>Platforms</h2>
|
|
72
|
+
<div class="platform-group">
|
|
73
|
+
<h3>Access Interfaces</h3>
|
|
74
|
+
<div class="platform-item" id="plat-telegram">
|
|
75
|
+
<span class="name">Telegram</span>
|
|
76
|
+
<span>
|
|
77
|
+
<span class="badge disabled" id="plat-telegram-badge">—</span>
|
|
78
|
+
<button class="btn-start" data-action="toggle-platform" data-name="telegram" data-op="start" id="plat-telegram-start">Start</button>
|
|
79
|
+
<button class="btn-stop" data-action="toggle-platform" data-name="telegram" data-op="stop" id="plat-telegram-stop">Stop</button>
|
|
80
|
+
</span>
|
|
81
|
+
</div>
|
|
82
|
+
<div class="platform-item" id="plat-discord">
|
|
83
|
+
<span class="name">Discord</span>
|
|
84
|
+
<span>
|
|
85
|
+
<span class="badge disabled" id="plat-discord-badge">—</span>
|
|
86
|
+
<button class="btn-start" data-action="toggle-platform" data-name="discord" data-op="start" id="plat-discord-start">Start</button>
|
|
87
|
+
<button class="btn-stop" data-action="toggle-platform" data-name="discord" data-op="stop" id="plat-discord-stop">Stop</button>
|
|
88
|
+
</span>
|
|
89
|
+
</div>
|
|
90
|
+
<div class="platform-item" id="plat-agent-api" style="display:none;">
|
|
91
|
+
<span class="name">Agent A2A</span>
|
|
92
|
+
<span>
|
|
93
|
+
<span class="badge disabled clickable" id="plat-agent-api-badge" data-action="toggle-a2a-panel">—</span>
|
|
94
|
+
<button class="btn-start" data-action="toggle-platform" data-name="agent-api" data-op="start" id="plat-agent-api-start">Start</button>
|
|
95
|
+
<button class="btn-stop" data-action="toggle-platform" data-name="agent-api" data-op="stop" id="plat-agent-api-stop">Stop</button>
|
|
96
|
+
</span>
|
|
97
|
+
</div>
|
|
98
|
+
</div>
|
|
99
|
+
<div class="platform-group">
|
|
100
|
+
<h3>External Tooling</h3>
|
|
101
|
+
<div class="platform-item"><span class="name">Gmail (gws)</span><span><span class="badge disabled" id="auth-gws">—</span></span></div>
|
|
102
|
+
<div class="platform-item" id="plat-nlm"><span class="name">LM Notebook</span><span><span class="badge disabled" id="auth-nlm">—</span></span></div>
|
|
103
|
+
</div>
|
|
104
|
+
</div>
|
|
105
|
+
|
|
106
|
+
<!-- Scheduled Tasks (4th column) -->
|
|
107
|
+
<div class="card" id="card-cron">
|
|
108
|
+
<h2>Scheduled Tasks</h2>
|
|
109
|
+
<div id="cron-entries"><div style="color:#666;font-size:0.82rem;">Loading...</div></div>
|
|
110
|
+
</div>
|
|
111
|
+
|
|
112
|
+
</main>
|
|
113
|
+
|
|
114
|
+
<!-- Log Overlay -->
|
|
115
|
+
<div id="log-overlay" class="overlay-panel" style="display:none;">
|
|
116
|
+
<div class="overlay-header">
|
|
117
|
+
<h2>📋 Log</h2>
|
|
118
|
+
<button class="btn-close-overlay" data-action="toggle-overlay" data-target="log-overlay">✕</button>
|
|
119
|
+
</div>
|
|
120
|
+
<div class="overlay-body" style="flex-direction:column;">
|
|
121
|
+
<div style="display:flex;gap:6px;margin-bottom:8px;">
|
|
122
|
+
<button class="log-level-btn lvl-info active" data-action="toggle-log-level" data-level="info">info</button>
|
|
123
|
+
<button class="log-level-btn lvl-warn active" data-action="toggle-log-level" data-level="warn">warn</button>
|
|
124
|
+
<button class="log-level-btn lvl-error active" data-action="toggle-log-level" data-level="error">error</button>
|
|
125
|
+
<button class="log-level-btn lvl-debug" data-action="toggle-log-level" data-level="debug">debug</button>
|
|
126
|
+
</div>
|
|
127
|
+
<div id="log-entries" style="flex:1;overflow-y:auto;font-size:0.88rem;font-family:monospace;line-height:1.6;"></div>
|
|
128
|
+
</div>
|
|
129
|
+
</div>
|
|
130
|
+
|
|
131
|
+
<!-- Search Overlay -->
|
|
132
|
+
<div id="search-overlay" class="overlay-panel" style="display:none;">
|
|
133
|
+
<div class="overlay-header">
|
|
134
|
+
<h2>🔍 Memory Search</h2>
|
|
135
|
+
<button class="btn-close-overlay" data-action="toggle-overlay" data-target="search-overlay">✕</button>
|
|
136
|
+
</div>
|
|
137
|
+
<div class="overlay-body">
|
|
138
|
+
<div class="search-panel-row">
|
|
139
|
+
<div class="search-box" style="margin:0;">
|
|
140
|
+
<input type="text" id="mem-userid-input" placeholder="all users" style="width:100px;text-align:center;flex:none;">
|
|
141
|
+
<button data-action="list-chat-ids">LIST</button>
|
|
142
|
+
</div>
|
|
143
|
+
<div class="layer-toggles" id="layer-toggles" style="margin:0;">
|
|
144
|
+
<button class="layer-btn active" data-layer="S1" data-action="toggle-layer">S1:en-fts</button>
|
|
145
|
+
<button class="layer-btn active" data-layer="S2" data-action="toggle-layer">S2:orig-fts</button>
|
|
146
|
+
<button class="layer-btn active" data-layer="S3" data-action="toggle-layer">S3:like</button>
|
|
147
|
+
<button class="layer-btn active" data-layer="S4" data-action="toggle-layer">S4:msg-fts</button>
|
|
148
|
+
<button class="layer-btn active" data-layer="S5" data-action="toggle-layer">S5:msg-like</button>
|
|
149
|
+
<button class="layer-btn active" data-layer="S6" data-action="toggle-layer">S6:consol</button>
|
|
150
|
+
<button class="layer-btn active" data-layer="S7" data-action="toggle-layer">S7:fallback</button>
|
|
151
|
+
<button class="layer-btn active" data-layer="Se" data-action="toggle-layer">Se:embed</button>
|
|
152
|
+
<button class="layer-btn" data-layer="NLM" data-action="toggle-layer">NLM</button>
|
|
153
|
+
</div>
|
|
154
|
+
</div>
|
|
155
|
+
<div class="search-panel-row" style="margin-top:8px;">
|
|
156
|
+
<button class="layer-btn active" id="mode-toggle" data-action="toggle-search-mode" style="min-width:42px;">OR</button>
|
|
157
|
+
<input type="text" id="mem-keyword-input" class="keyword-input" placeholder="Type keyword + Enter to add filter...">
|
|
158
|
+
<input type="text" id="mem-entity-input" placeholder="Entity filter" style="width:120px;flex:none;">
|
|
159
|
+
<button class="btn-search" data-action="search-memory">Search</button>
|
|
160
|
+
</div>
|
|
161
|
+
<div id="keyword-filters" class="keyword-filters"></div>
|
|
162
|
+
<div class="search-results" id="mem-search-results"></div>
|
|
163
|
+
</div>
|
|
164
|
+
</div>
|
|
165
|
+
|
|
166
|
+
<!-- A2A Panel -->
|
|
167
|
+
<div id="a2a-panel" class="a2a-panel" style="display:none;">
|
|
168
|
+
<div class="a2a-header">
|
|
169
|
+
<h3>🔗 A2A Traffic — abTARS ↔ Agents</h3>
|
|
170
|
+
<span class="a2a-count" id="a2a-count"></span>
|
|
171
|
+
</div>
|
|
172
|
+
<div class="a2a-entries" id="a2a-entries">
|
|
173
|
+
<div class="a2a-empty">No traffic yet. Waiting for agent requests...</div>
|
|
174
|
+
</div>
|
|
175
|
+
</div>
|
|
176
|
+
|
|
177
|
+
<script src="/memory-universe.js"></script>
|
|
178
|
+
<script type="module" src="/js/app.js"></script>
|
|
179
|
+
</body>
|
|
180
|
+
</html>
|
|
@@ -0,0 +1,437 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* app.js — Dashboard entry point (ES module).
|
|
3
|
+
* Sets up auth, WebSocket, event delegation, and card updates.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
// ── Auth ─────────────────────────────────────────────────────────────────────
|
|
7
|
+
let token = sessionStorage.getItem("dashboard_token");
|
|
8
|
+
if (!token) {
|
|
9
|
+
token = new URLSearchParams(location.search).get("token") || prompt("Enter dashboard auth token:");
|
|
10
|
+
if (token) sessionStorage.setItem("dashboard_token", token);
|
|
11
|
+
}
|
|
12
|
+
if (!token) {
|
|
13
|
+
document.body.innerHTML = '<div style="text-align:center;padding:60px;color:#f44336;">Authentication token required. Reload to try again.</div>';
|
|
14
|
+
throw new Error("no token");
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// ── Capability flags ─────────────────────────────────────────────────────────
|
|
18
|
+
const body = document.body;
|
|
19
|
+
if (body.dataset.hasAgentApi === "true") {
|
|
20
|
+
const el = document.getElementById("plat-agent-api");
|
|
21
|
+
if (el) el.style.display = "";
|
|
22
|
+
const badge = document.getElementById("plat-agent-api-badge");
|
|
23
|
+
if (badge) badge.dataset.port = body.dataset.agentApiPort || "";
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// ── Helpers ──────────────────────────────────────────────────────────────────
|
|
27
|
+
function formatBytes(bytes) {
|
|
28
|
+
if (bytes === 0) return "0 B";
|
|
29
|
+
const k = 1024, sizes = ["B", "KB", "MB", "GB"];
|
|
30
|
+
const i = Math.min(Math.floor(Math.log(bytes) / Math.log(k)), sizes.length - 1);
|
|
31
|
+
return (bytes / Math.pow(k, i)).toFixed(1) + " " + sizes[i];
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function formatUptime(ms) {
|
|
35
|
+
const s = Math.floor(ms / 1000), h = Math.floor(s / 3600), m = Math.floor((s % 3600) / 60), sec = s % 60;
|
|
36
|
+
const parts = [];
|
|
37
|
+
if (h > 0) parts.push(h + "h");
|
|
38
|
+
if (m > 0) parts.push(m + "m");
|
|
39
|
+
if (sec > 0 || parts.length === 0) parts.push(sec + "s");
|
|
40
|
+
return parts.join(" ");
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function setText(id, val) {
|
|
44
|
+
const el = document.getElementById(id);
|
|
45
|
+
if (el) el.textContent = val != null ? String(val) : "—";
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function escHtml(str) {
|
|
49
|
+
const d = document.createElement("div");
|
|
50
|
+
d.textContent = str;
|
|
51
|
+
return d.innerHTML;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function authHeaders() {
|
|
55
|
+
return { "Authorization": "Bearer " + token };
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// ── WebSocket ────────────────────────────────────────────────────────────────
|
|
59
|
+
let ws = null, reconnectAttempt = 0, reconnectTimer = null;
|
|
60
|
+
const banner = document.getElementById("connection-banner");
|
|
61
|
+
|
|
62
|
+
function getReconnectDelay(attempt) {
|
|
63
|
+
return Math.min(1000 * Math.pow(2, attempt - 1), 30000);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function connect() {
|
|
67
|
+
const proto = location.protocol === "https:" ? "wss:" : "ws:";
|
|
68
|
+
ws = new WebSocket(proto + "//" + location.host + "/ws?token=" + encodeURIComponent(token));
|
|
69
|
+
ws.onopen = () => { reconnectAttempt = 0; banner.style.display = "none"; if (reconnectTimer) { clearTimeout(reconnectTimer); reconnectTimer = null; } };
|
|
70
|
+
ws.onmessage = (evt) => { try { updateDashboard(JSON.parse(evt.data)); } catch {} };
|
|
71
|
+
ws.onclose = () => scheduleReconnect();
|
|
72
|
+
ws.onerror = () => { if (ws) ws.close(); };
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function scheduleReconnect() {
|
|
76
|
+
banner.style.display = "block";
|
|
77
|
+
reconnectAttempt++;
|
|
78
|
+
reconnectTimer = setTimeout(connect, getReconnectDelay(reconnectAttempt));
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// ── Dashboard Update ─────────────────────────────────────────────────────────
|
|
82
|
+
function updateDashboard(snap) {
|
|
83
|
+
// Bridge Health
|
|
84
|
+
setText("health-uptime", formatUptime(snap.uptimeMs));
|
|
85
|
+
setText("health-timestamp", new Date(snap.timestamp).toLocaleTimeString());
|
|
86
|
+
setText("health-version", snap.version && snap.commit ? `v${snap.version} (${snap.commit})` : "—");
|
|
87
|
+
setText("health-model", snap.model ? `${snap.model.name} (${snap.model.provider})` : "—");
|
|
88
|
+
|
|
89
|
+
// Platforms
|
|
90
|
+
if (snap.services) {
|
|
91
|
+
updateServiceRow("telegram", snap.services.telegram);
|
|
92
|
+
updateServiceRow("discord", snap.services.discord);
|
|
93
|
+
updateServiceRow("agent-api", snap.services["agent-api"]);
|
|
94
|
+
const enabled = [];
|
|
95
|
+
if (snap.services.telegram?.running) enabled.push("Telegram");
|
|
96
|
+
if (snap.services.discord?.running) enabled.push("Discord");
|
|
97
|
+
setText("health-platforms", enabled.length > 0 ? enabled.join(", ") : "None");
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Transport
|
|
101
|
+
if (snap.transport) {
|
|
102
|
+
setText("transport-type", snap.transport.type || "—");
|
|
103
|
+
const stateEl = document.getElementById("transport-state");
|
|
104
|
+
if (stateEl) stateEl.innerHTML = snap.transport.ready
|
|
105
|
+
? '<span class="indicator green"></span> connected'
|
|
106
|
+
: '<span class="indicator red"></span> disconnected';
|
|
107
|
+
const pct = snap.transport.contextPercent;
|
|
108
|
+
const bar = document.getElementById("transport-ctx-bar");
|
|
109
|
+
if (bar) {
|
|
110
|
+
bar.style.width = pct >= 0 ? Math.min(pct, 100) + "%" : "0%";
|
|
111
|
+
bar.style.background = pct > 85 ? "#f44336" : pct > 60 ? "#ff9800" : "#4caf50";
|
|
112
|
+
}
|
|
113
|
+
setText("transport-ctx-pct", pct >= 0 ? pct + "%" : "N/A");
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// Memory
|
|
117
|
+
if (snap.memory) {
|
|
118
|
+
const memStatus = document.getElementById("mem-status");
|
|
119
|
+
if (memStatus) {
|
|
120
|
+
memStatus.innerHTML = !snap.memory.enabled
|
|
121
|
+
? '<span class="indicator yellow"></span> disabled'
|
|
122
|
+
: snap.memory.error ? '<span class="indicator red"></span> error'
|
|
123
|
+
: '<span class="indicator green"></span> enabled';
|
|
124
|
+
}
|
|
125
|
+
if (snap.memory.stats) {
|
|
126
|
+
const s = snap.memory.stats;
|
|
127
|
+
setText("mem-messages", s.totalMessages);
|
|
128
|
+
setText("mem-extracted", s.extractedMemories);
|
|
129
|
+
setText("mem-consolidations", s.consolidationFiles.daily + " / " + s.consolidationFiles.weekly + " / " + s.consolidationFiles.quarterly);
|
|
130
|
+
setText("mem-documents", s.ingestedDocuments);
|
|
131
|
+
setText("mem-dbsize", formatBytes(s.dbSizeBytes));
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// Auth indicators
|
|
136
|
+
const authGws = document.getElementById("auth-gws");
|
|
137
|
+
if (authGws) authGws.innerHTML = '<span class="auth-dot ' + (snap.gwsAuth ? "ok" : "no") + '"></span>' + (snap.gwsAuth ? "Authenticated" : "Not configured");
|
|
138
|
+
const authNlm = document.getElementById("auth-nlm");
|
|
139
|
+
if (authNlm) authNlm.innerHTML = '<span class="auth-dot ' + (snap.notebooklm?.enabled ? "ok" : "no") + '"></span>' + (snap.notebooklm?.enabled ? "Active" : "Disabled");
|
|
140
|
+
const authX = document.getElementById("auth-x");
|
|
141
|
+
if (authX) authX.innerHTML = '<span class="auth-dot ' + (snap.xAuth ? "ok" : "no") + '"></span>' + (snap.xAuth ? "Authenticated" : "No cookies");
|
|
142
|
+
|
|
143
|
+
// Heartbeat
|
|
144
|
+
if (snap.heartbeat) {
|
|
145
|
+
const hbEl = document.getElementById("hb-status");
|
|
146
|
+
if (hbEl) {
|
|
147
|
+
hbEl.innerHTML = snap.heartbeat.running
|
|
148
|
+
? '<span class="indicator green"></span> ' + (snap.heartbeat.intervalMs ? (snap.heartbeat.intervalMs / 1000) + "s" : "")
|
|
149
|
+
: '<span class="indicator red"></span> FAILED';
|
|
150
|
+
}
|
|
151
|
+
const hbTasks = document.getElementById("hb-tasks");
|
|
152
|
+
if (hbTasks && snap.heartbeat.taskNames) {
|
|
153
|
+
hbTasks.innerHTML = snap.heartbeat.taskNames.length === 0
|
|
154
|
+
? '<div style="color:#666;font-size:0.82rem;">No tasks registered</div>'
|
|
155
|
+
: snap.heartbeat.taskNames.map(name =>
|
|
156
|
+
'<div class="stat-row"><span class="stat-label">' + escHtml(name) + '</span><span class="stat-value"><span class="indicator ' + (snap.heartbeat.running ? "green" : "yellow") + '"></span></span></div>'
|
|
157
|
+
).join("");
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// Cron
|
|
162
|
+
if (snap.cron) updateCronPanel(snap.cron);
|
|
163
|
+
|
|
164
|
+
// A2A
|
|
165
|
+
updateA2ATraffic(snap.agentApi);
|
|
166
|
+
|
|
167
|
+
// Subsystem health grid
|
|
168
|
+
if (snap.subsystems) updateSubsystemGrid(snap.subsystems);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
function updateServiceRow(name, state) {
|
|
172
|
+
const badge = document.getElementById("plat-" + name + "-badge");
|
|
173
|
+
const btnStart = document.getElementById("plat-" + name + "-start");
|
|
174
|
+
const btnStop = document.getElementById("plat-" + name + "-stop");
|
|
175
|
+
if (!badge) return;
|
|
176
|
+
if (!state || !state.configured) {
|
|
177
|
+
badge.textContent = "not configured"; badge.className = "badge disabled";
|
|
178
|
+
if (btnStart) btnStart.disabled = true;
|
|
179
|
+
if (btnStop) btnStop.disabled = true;
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
if (state.running) {
|
|
183
|
+
badge.textContent = name === "agent-api" ? "⚠️ " + (badge.dataset.port || "?") : "running";
|
|
184
|
+
badge.className = name === "agent-api" ? "badge running clickable" : "badge running";
|
|
185
|
+
if (btnStart) btnStart.disabled = true;
|
|
186
|
+
if (btnStop) btnStop.disabled = false;
|
|
187
|
+
} else {
|
|
188
|
+
badge.textContent = "stopped"; badge.className = "badge stopped";
|
|
189
|
+
if (btnStart) btnStart.disabled = false;
|
|
190
|
+
if (btnStop) btnStop.disabled = true;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// ── Cron Panel ───────────────────────────────────────────────────────────────
|
|
195
|
+
function updateCronPanel(entries) {
|
|
196
|
+
const container = document.getElementById("cron-entries");
|
|
197
|
+
if (!container) return;
|
|
198
|
+
if (!entries || entries.length === 0) {
|
|
199
|
+
container.innerHTML = '<div style="color:#666;font-size:0.82rem;">No scheduled tasks</div>';
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
container.innerHTML = entries.map(e => {
|
|
203
|
+
const statusBadge = e.paused ? '<span class="badge paused">paused</span>' : '<span class="badge running">active</span>';
|
|
204
|
+
const priorityBadge = e.priority === "high" ? ' <span class="badge high">HIGH</span>' : e.priority === "low" ? ' <span class="badge low">LOW</span>' : "";
|
|
205
|
+
const nextFire = e.paused ? "—" : new Date(e.fireAt).toLocaleString();
|
|
206
|
+
const lastRan = e.lastRanAt ? new Date(e.lastRanAt).toLocaleString() : "never";
|
|
207
|
+
const pauseBtn = e.paused
|
|
208
|
+
? `<button class="btn-start" data-action="cron-action" data-id="${e.id}" data-op="resume">Resume</button>`
|
|
209
|
+
: `<button class="btn-stop" data-action="cron-action" data-id="${e.id}" data-op="pause">Pause</button>`;
|
|
210
|
+
return `<div class="cron-entry"><div class="cron-info"><div class="cron-label">${statusBadge}${priorityBadge} ${escHtml(e.label)}</div><div class="cron-meta">${escHtml(e.schedule)} · ${e.executor} · next: ${nextFire} · last: ${lastRan}</div></div><div class="cron-actions">${pauseBtn}<button class="btn-start" style="background:#0f3460;color:#a0c4ff;" data-action="cron-action" data-id="${e.id}" data-op="trigger">▶ Run</button></div></div>`;
|
|
211
|
+
}).join("");
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
// ── A2A Traffic ──────────────────────────────────────────────────────────────
|
|
215
|
+
let lastTrafficCount = 0;
|
|
216
|
+
|
|
217
|
+
function updateA2ATraffic(agentApi) {
|
|
218
|
+
if (!agentApi?.traffic) return;
|
|
219
|
+
const entries = agentApi.traffic;
|
|
220
|
+
if (entries.length === lastTrafficCount) return;
|
|
221
|
+
lastTrafficCount = entries.length;
|
|
222
|
+
setText("a2a-count", entries.length + " entries");
|
|
223
|
+
const container = document.getElementById("a2a-entries");
|
|
224
|
+
if (!container) return;
|
|
225
|
+
if (entries.length === 0) {
|
|
226
|
+
container.innerHTML = '<div class="a2a-empty">No traffic yet. Waiting for agent requests...</div>';
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
229
|
+
container.innerHTML = entries.slice().reverse().map(e => {
|
|
230
|
+
const time = new Date(e.ts).toLocaleTimeString();
|
|
231
|
+
const epClass = e.endpoint === "prompt" ? "prompt" : e.endpoint === "reset" ? "reset" : "status";
|
|
232
|
+
let body = "";
|
|
233
|
+
if (e.endpoint === "prompt") {
|
|
234
|
+
body = '<div class="a2a-prompt">→ ' + escHtml(e.prompt) + "</div>";
|
|
235
|
+
if (e.response) body += '<div class="a2a-response">← ' + escHtml(e.response) + "</div>";
|
|
236
|
+
} else {
|
|
237
|
+
body = '<div class="a2a-response">' + escHtml(e.response || e.endpoint) + "</div>";
|
|
238
|
+
}
|
|
239
|
+
body += '<div class="a2a-meta">' + (e.ip || "—") + " · " + e.durationMs + "ms · " + e.status + "</div>";
|
|
240
|
+
return `<div class="a2a-entry"><span class="a2a-time">${time}</span><span class="a2a-endpoint ${epClass}">${e.endpoint}</span><div class="a2a-body">${body}</div></div>`;
|
|
241
|
+
}).join("");
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// ── Log Panel ────────────────────────────────────────────────────────────────
|
|
245
|
+
const logLevels = { info: true, warn: true, error: true, debug: false };
|
|
246
|
+
let logPollTimer = null;
|
|
247
|
+
|
|
248
|
+
function fetchLogs() {
|
|
249
|
+
const active = Object.keys(logLevels).filter(k => logLevels[k]);
|
|
250
|
+
const container = document.getElementById("log-entries");
|
|
251
|
+
if (active.length === 0) { if (container) container.innerHTML = '<div style="color:#666;padding:12px;">No levels selected</div>'; return; }
|
|
252
|
+
fetch("/api/logs?level=" + active.join(",") + "&limit=500", { headers: authHeaders() })
|
|
253
|
+
.then(r => r.json())
|
|
254
|
+
.then(data => {
|
|
255
|
+
if (!container || !data.lines) return;
|
|
256
|
+
const wasAtBottom = container.scrollHeight - container.scrollTop - container.clientHeight < 30;
|
|
257
|
+
container.innerHTML = data.lines.map(line => {
|
|
258
|
+
let lvl = "info";
|
|
259
|
+
if (line.includes(" WARN ")) lvl = "warn";
|
|
260
|
+
else if (line.includes(" ERROR")) lvl = "error";
|
|
261
|
+
else if (line.includes(" DEBUG")) lvl = "debug";
|
|
262
|
+
return '<div class="log-line ' + lvl + '">' + escHtml(line.slice(0, 19).replace("T", " ") + line.slice(24)) + "</div>";
|
|
263
|
+
}).join("");
|
|
264
|
+
if (wasAtBottom) container.scrollTop = container.scrollHeight;
|
|
265
|
+
}).catch(() => {});
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
// ── Memory Search ────────────────────────────────────────────────────────────
|
|
269
|
+
let keywordFilters = [];
|
|
270
|
+
let searchMode = "or";
|
|
271
|
+
|
|
272
|
+
function getSelectedStages() {
|
|
273
|
+
return [...document.querySelectorAll("#layer-toggles .layer-btn.active")].map(b => b.dataset.layer);
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
function renderFilters() {
|
|
277
|
+
const container = document.getElementById("keyword-filters");
|
|
278
|
+
if (!container) return;
|
|
279
|
+
container.innerHTML = keywordFilters.map((kw, i) =>
|
|
280
|
+
`<span class="keyword-chip" data-action="remove-filter" data-index="${i}">${escHtml(kw)} ✕</span>`
|
|
281
|
+
).join("");
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
function searchMemory() {
|
|
285
|
+
const container = document.getElementById("mem-search-results");
|
|
286
|
+
if (keywordFilters.length === 0) { if (container) container.innerHTML = ""; return; }
|
|
287
|
+
const stages = getSelectedStages();
|
|
288
|
+
if (stages.length === 0) { if (container) container.innerHTML = '<div style="color:#666;padding:6px 0;">No stages selected</div>'; return; }
|
|
289
|
+
const userId = document.getElementById("mem-userid-input")?.value.trim() || "";
|
|
290
|
+
const entity = document.getElementById("mem-entity-input")?.value || "";
|
|
291
|
+
const keywords = keywordFilters.join(",");
|
|
292
|
+
let url = "/api/memory/search?keywords=" + encodeURIComponent(keywords) + "&original=" + encodeURIComponent(keywords) + "&stages=" + encodeURIComponent(stages.join(",")) + "&mode=" + searchMode;
|
|
293
|
+
if (entity) url += "&entity=" + encodeURIComponent(entity);
|
|
294
|
+
if (userId) url += "&userId=" + encodeURIComponent(userId);
|
|
295
|
+
fetch(url, { headers: authHeaders() }).then(r => r.json()).then(data => {
|
|
296
|
+
if (!container) return;
|
|
297
|
+
if (data.error) { container.innerHTML = '<div style="color:#f44336;padding:6px 0;">' + escHtml(data.error) + "</div>"; return; }
|
|
298
|
+
if (!data.results?.length) { container.innerHTML = '<div style="color:#666;padding:6px 0;">No results found</div>'; return; }
|
|
299
|
+
let stageInfo = "";
|
|
300
|
+
if (data.layers) {
|
|
301
|
+
stageInfo = '<div style="color:#888;font-size:11px;margin-bottom:6px;">' + Object.keys(data.layers).map(k => k + ":" + (data.layers[k].hits || 0) + " (" + (data.layers[k].ms || 0) + "ms)").join(" | ") + "</div>";
|
|
302
|
+
}
|
|
303
|
+
container.innerHTML = stageInfo + data.results.map(r => {
|
|
304
|
+
let meta = '<span class="score">' + (r.score != null ? r.score.toFixed(2) : "—") + '</span> <span class="source">' + escHtml(r.source) + '</span> <span class="source">' + escHtml(r.date) + "</span>";
|
|
305
|
+
if (r.memoryType) meta += ' <span class="source">' + r.memoryType + "</span>";
|
|
306
|
+
let content = escHtml(r.content.substring(0, 300));
|
|
307
|
+
if (r.contentOriginal && r.contentOriginal !== r.content) content += '<div style="color:#888;font-size:11px;margin-top:2px;">' + escHtml(r.contentOriginal.substring(0, 200)) + "</div>";
|
|
308
|
+
return '<div class="search-result-item"><div class="result-meta">' + meta + '</div><div class="result-content">' + content + "</div></div>";
|
|
309
|
+
}).join("");
|
|
310
|
+
}).catch(err => { if (container) container.innerHTML = '<div style="color:#f44336;">Search failed: ' + escHtml(err.message) + "</div>"; });
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
function listChatIds() {
|
|
314
|
+
fetch("/api/memory/chats", { headers: authHeaders() }).then(r => r.json()).then(data => {
|
|
315
|
+
const container = document.getElementById("mem-search-results");
|
|
316
|
+
if (!container) return;
|
|
317
|
+
if (data.error) { container.innerHTML = '<div style="color:#f44336;">' + escHtml(data.error) + "</div>"; return; }
|
|
318
|
+
if (!data.userIds?.length) { container.innerHTML = '<div style="color:#666;">No chats found</div>'; return; }
|
|
319
|
+
container.innerHTML = '<div style="padding:6px 0;color:#e0e0e0;"><strong>Stored Chat IDs:</strong><br>' +
|
|
320
|
+
data.userIds.map(id => `<span style="cursor:pointer;color:#64b5f6;margin-right:12px;" data-action="select-chat-id" data-id="${id}">${id}</span>`).join("") + "</div>";
|
|
321
|
+
}).catch(() => {});
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
// ── Subsystem Health Grid ─────────────────────────────────────────────────────
|
|
325
|
+
function updateSubsystemGrid(subsystems) {
|
|
326
|
+
const container = document.getElementById("subsystem-grid");
|
|
327
|
+
if (!container || !subsystems.length) return;
|
|
328
|
+
container.innerHTML = subsystems.map(s => {
|
|
329
|
+
const icon = s.status === "ok" ? "✓" : s.status === "skipped" ? "○" : s.status === "retrying" ? "↻" : "✗";
|
|
330
|
+
const color = s.status === "ok" ? "#4caf50" : s.status === "skipped" ? "#9e9e9e" : s.status === "retrying" ? "#ff9800" : "#f44336";
|
|
331
|
+
const detail = s.detail ? ` <span style="color:#888;">— ${escHtml(s.detail)}</span>` : "";
|
|
332
|
+
return `<div><span style="color:${color};font-weight:bold;">${icon}</span> ${escHtml(s.name)}${detail}</div>`;
|
|
333
|
+
}).join("");
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
// ── Event Delegation ─────────────────────────────────────────────────────────
|
|
337
|
+
document.body.addEventListener("click", (e) => {
|
|
338
|
+
const target = e.target.closest("[data-action]");
|
|
339
|
+
if (!target) return;
|
|
340
|
+
const action = target.dataset.action;
|
|
341
|
+
|
|
342
|
+
switch (action) {
|
|
343
|
+
case "toggle-platform": {
|
|
344
|
+
const name = target.dataset.name, op = target.dataset.op;
|
|
345
|
+
fetch("/api/services/" + name + "/" + op, { method: "POST", headers: authHeaders() })
|
|
346
|
+
.then(r => r.json()).then(d => { if (d.error) alert("Error: " + d.error); })
|
|
347
|
+
.catch(err => alert("Request failed: " + err.message));
|
|
348
|
+
break;
|
|
349
|
+
}
|
|
350
|
+
case "toggle-overlay": {
|
|
351
|
+
const el = document.getElementById(target.dataset.target);
|
|
352
|
+
if (el) {
|
|
353
|
+
const show = el.style.display === "none";
|
|
354
|
+
el.style.display = show ? "flex" : "none";
|
|
355
|
+
// Start/stop log polling when log overlay toggles
|
|
356
|
+
if (target.dataset.target === "log-overlay") {
|
|
357
|
+
if (show) { fetchLogs(); logPollTimer = setInterval(fetchLogs, 5000); }
|
|
358
|
+
else { clearInterval(logPollTimer); logPollTimer = null; }
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
break;
|
|
362
|
+
}
|
|
363
|
+
case "toggle-a2a-panel": {
|
|
364
|
+
const panel = document.getElementById("a2a-panel");
|
|
365
|
+
if (panel) panel.style.display = panel.style.display === "none" ? "flex" : "none";
|
|
366
|
+
break;
|
|
367
|
+
}
|
|
368
|
+
case "load-universe": {
|
|
369
|
+
if (window.initMemoryUniverse) window.initMemoryUniverse(token);
|
|
370
|
+
break;
|
|
371
|
+
}
|
|
372
|
+
case "toggle-log-level": {
|
|
373
|
+
const level = target.dataset.level;
|
|
374
|
+
logLevels[level] = !logLevels[level];
|
|
375
|
+
target.classList.toggle("active", logLevels[level]);
|
|
376
|
+
fetchLogs();
|
|
377
|
+
break;
|
|
378
|
+
}
|
|
379
|
+
case "toggle-layer": {
|
|
380
|
+
target.classList.toggle("active");
|
|
381
|
+
searchMemory();
|
|
382
|
+
break;
|
|
383
|
+
}
|
|
384
|
+
case "toggle-search-mode": {
|
|
385
|
+
searchMode = searchMode === "or" ? "and" : "or";
|
|
386
|
+
target.textContent = searchMode.toUpperCase();
|
|
387
|
+
target.classList.toggle("active", searchMode === "or");
|
|
388
|
+
searchMemory();
|
|
389
|
+
break;
|
|
390
|
+
}
|
|
391
|
+
case "search-memory": {
|
|
392
|
+
searchMemory();
|
|
393
|
+
break;
|
|
394
|
+
}
|
|
395
|
+
case "list-chat-ids": {
|
|
396
|
+
listChatIds();
|
|
397
|
+
break;
|
|
398
|
+
}
|
|
399
|
+
case "remove-filter": {
|
|
400
|
+
keywordFilters.splice(Number(target.dataset.index), 1);
|
|
401
|
+
renderFilters();
|
|
402
|
+
searchMemory();
|
|
403
|
+
break;
|
|
404
|
+
}
|
|
405
|
+
case "cron-action": {
|
|
406
|
+
fetch("/api/cron/" + target.dataset.id + "/" + target.dataset.op, { method: "POST", headers: authHeaders() })
|
|
407
|
+
.then(r => r.json()).then(d => { if (d.error) alert("Error: " + d.error); })
|
|
408
|
+
.catch(err => alert("Request failed: " + err.message));
|
|
409
|
+
break;
|
|
410
|
+
}
|
|
411
|
+
case "select-chat-id": {
|
|
412
|
+
const input = document.getElementById("mem-userid-input");
|
|
413
|
+
if (input) input.value = target.dataset.id;
|
|
414
|
+
break;
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
});
|
|
418
|
+
|
|
419
|
+
// Keyword input Enter handler
|
|
420
|
+
const kwInput = document.getElementById("mem-keyword-input");
|
|
421
|
+
if (kwInput) {
|
|
422
|
+
kwInput.addEventListener("keydown", (e) => {
|
|
423
|
+
if (e.key === "Enter") {
|
|
424
|
+
const val = kwInput.value.trim();
|
|
425
|
+
if (val && !keywordFilters.includes(val)) {
|
|
426
|
+
keywordFilters.push(val);
|
|
427
|
+
renderFilters();
|
|
428
|
+
searchMemory();
|
|
429
|
+
}
|
|
430
|
+
kwInput.value = "";
|
|
431
|
+
}
|
|
432
|
+
});
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
// ── Init ─────────────────────────────────────────────────────────────────────
|
|
436
|
+
connect();
|
|
437
|
+
// Logs fetched on overlay open, not on page load
|