@agentdeck/bridge 0.2.2 → 0.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/fonts/IBMPlexSans-Bold.ttf +0 -0
- package/assets/fonts/IBMPlexSans-Regular.ttf +0 -0
- package/assets/fonts/JetBrainsMono-Bold.ttf +0 -0
- package/assets/fonts/JetBrainsMono-Regular.ttf +0 -0
- package/assets/fonts/LICENSES.md +22 -0
- package/dist/adapters/claude-code.d.ts +6 -0
- package/dist/adapters/claude-code.d.ts.map +1 -1
- package/dist/adapters/claude-code.js +8 -0
- package/dist/adapters/claude-code.js.map +1 -1
- package/dist/adapters/openclaw.d.ts +24 -0
- package/dist/adapters/openclaw.d.ts.map +1 -1
- package/dist/adapters/openclaw.js +291 -35
- package/dist/adapters/openclaw.js.map +1 -1
- package/dist/adapters/opencode-adapter.d.ts +59 -0
- package/dist/adapters/opencode-adapter.d.ts.map +1 -1
- package/dist/adapters/opencode-adapter.js +297 -35
- package/dist/adapters/opencode-adapter.js.map +1 -1
- package/dist/adb-reverse.d.ts +1 -1
- package/dist/adb-reverse.js +1 -1
- package/dist/antigravity-local.d.ts +1 -0
- package/dist/antigravity-local.d.ts.map +1 -1
- package/dist/antigravity-local.js +33 -0
- package/dist/antigravity-local.js.map +1 -1
- package/dist/apme/adapters/claude-hook.d.ts.map +1 -1
- package/dist/apme/adapters/claude-hook.js +5 -0
- package/dist/apme/adapters/claude-hook.js.map +1 -1
- package/dist/apme/adapters/codex-hook.d.ts +17 -0
- package/dist/apme/adapters/codex-hook.d.ts.map +1 -0
- package/dist/apme/adapters/codex-hook.js +95 -0
- package/dist/apme/adapters/codex-hook.js.map +1 -0
- package/dist/apme/adapters/codex-turn-manager.d.ts +86 -0
- package/dist/apme/adapters/codex-turn-manager.d.ts.map +1 -0
- package/dist/apme/adapters/codex-turn-manager.js +496 -0
- package/dist/apme/adapters/codex-turn-manager.js.map +1 -0
- package/dist/apme/adapters/openclaw-hook.d.ts +99 -0
- package/dist/apme/adapters/openclaw-hook.d.ts.map +1 -0
- package/dist/apme/adapters/openclaw-hook.js +234 -0
- package/dist/apme/adapters/openclaw-hook.js.map +1 -0
- package/dist/apme/adapters/opencode-hook.d.ts +56 -0
- package/dist/apme/adapters/opencode-hook.d.ts.map +1 -0
- package/dist/apme/adapters/opencode-hook.js +182 -0
- package/dist/apme/adapters/opencode-hook.js.map +1 -0
- package/dist/apme/adapters/timeline.d.ts.map +1 -1
- package/dist/apme/adapters/timeline.js +6 -1
- package/dist/apme/adapters/timeline.js.map +1 -1
- package/dist/apme/antigravity-transcript.d.ts +18 -0
- package/dist/apme/antigravity-transcript.d.ts.map +1 -0
- package/dist/apme/antigravity-transcript.js +94 -0
- package/dist/apme/antigravity-transcript.js.map +1 -0
- package/dist/apme/classify-turn.d.ts +13 -0
- package/dist/apme/classify-turn.d.ts.map +1 -0
- package/dist/apme/classify-turn.js +49 -0
- package/dist/apme/classify-turn.js.map +1 -0
- package/dist/apme/claude-transcript-reader.d.ts +10 -0
- package/dist/apme/claude-transcript-reader.d.ts.map +1 -1
- package/dist/apme/claude-transcript-reader.js +35 -0
- package/dist/apme/claude-transcript-reader.js.map +1 -1
- package/dist/apme/collector.d.ts +129 -6
- package/dist/apme/collector.d.ts.map +1 -1
- package/dist/apme/collector.js +470 -23
- package/dist/apme/collector.js.map +1 -1
- package/dist/apme/dashboard-html.d.ts.map +1 -1
- package/dist/apme/dashboard-html.js +87 -11
- package/dist/apme/dashboard-html.js.map +1 -1
- package/dist/apme/http.d.ts.map +1 -1
- package/dist/apme/http.js +43 -6
- package/dist/apme/http.js.map +1 -1
- package/dist/apme/index.d.ts +26 -5
- package/dist/apme/index.d.ts.map +1 -1
- package/dist/apme/index.js +135 -9
- package/dist/apme/index.js.map +1 -1
- package/dist/apme/pareto.d.ts +39 -0
- package/dist/apme/pareto.d.ts.map +1 -0
- package/dist/apme/pareto.js +59 -0
- package/dist/apme/pareto.js.map +1 -0
- package/dist/apme/recommend.d.ts +3 -0
- package/dist/apme/recommend.d.ts.map +1 -1
- package/dist/apme/recommend.js +43 -1
- package/dist/apme/recommend.js.map +1 -1
- package/dist/apme/runner.d.ts +92 -4
- package/dist/apme/runner.d.ts.map +1 -1
- package/dist/apme/runner.js +586 -70
- package/dist/apme/runner.js.map +1 -1
- package/dist/apme/sample-to-timeline.d.ts +26 -0
- package/dist/apme/sample-to-timeline.d.ts.map +1 -0
- package/dist/apme/sample-to-timeline.js +95 -0
- package/dist/apme/sample-to-timeline.js.map +1 -0
- package/dist/apme/scorers/index.d.ts +47 -0
- package/dist/apme/scorers/index.d.ts.map +1 -0
- package/dist/apme/scorers/index.js +96 -0
- package/dist/apme/scorers/index.js.map +1 -0
- package/dist/apme/settings.d.ts +14 -10
- package/dist/apme/settings.d.ts.map +1 -1
- package/dist/apme/settings.js +34 -8
- package/dist/apme/settings.js.map +1 -1
- package/dist/apme/store.d.ts +33 -1
- package/dist/apme/store.d.ts.map +1 -1
- package/dist/apme/store.js +334 -25
- package/dist/apme/store.js.map +1 -1
- package/dist/awaiting-overlay.d.ts +99 -0
- package/dist/awaiting-overlay.d.ts.map +1 -0
- package/dist/awaiting-overlay.js +148 -0
- package/dist/awaiting-overlay.js.map +1 -0
- package/dist/ble-sync-spawn.d.ts +63 -0
- package/dist/ble-sync-spawn.d.ts.map +1 -0
- package/dist/ble-sync-spawn.js +196 -0
- package/dist/ble-sync-spawn.js.map +1 -0
- package/dist/bridge-core.d.ts +24 -1
- package/dist/bridge-core.d.ts.map +1 -1
- package/dist/bridge-core.js +157 -24
- package/dist/bridge-core.js.map +1 -1
- package/dist/broadcast.d.ts +3 -0
- package/dist/broadcast.d.ts.map +1 -0
- package/dist/broadcast.js +122 -0
- package/dist/broadcast.js.map +1 -0
- package/dist/check-deps.d.ts.map +1 -1
- package/dist/check-deps.js +25 -9
- package/dist/check-deps.js.map +1 -1
- package/dist/cli.d.ts +15 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +1021 -93
- package/dist/cli.js.map +1 -1
- package/dist/codex-auth.d.ts +21 -0
- package/dist/codex-auth.d.ts.map +1 -1
- package/dist/codex-auth.js +52 -1
- package/dist/codex-auth.js.map +1 -1
- package/dist/codex-output-parser.d.ts +8 -0
- package/dist/codex-output-parser.d.ts.map +1 -1
- package/dist/codex-output-parser.js +110 -25
- package/dist/codex-output-parser.js.map +1 -1
- package/dist/codex-rate-limits.d.ts +16 -0
- package/dist/codex-rate-limits.d.ts.map +1 -0
- package/dist/codex-rate-limits.js +197 -0
- package/dist/codex-rate-limits.js.map +1 -0
- package/dist/codex-rollout-response.d.ts +31 -0
- package/dist/codex-rollout-response.d.ts.map +1 -0
- package/dist/codex-rollout-response.js +135 -0
- package/dist/codex-rollout-response.js.map +1 -0
- package/dist/daemon-server.d.ts +85 -0
- package/dist/daemon-server.d.ts.map +1 -1
- package/dist/daemon-server.js +1627 -159
- package/dist/daemon-server.js.map +1 -1
- package/dist/daemon.js +15 -6
- package/dist/daemon.js.map +1 -1
- package/dist/display-dim.d.ts +9 -0
- package/dist/display-dim.d.ts.map +1 -0
- package/dist/display-dim.js +53 -0
- package/dist/display-dim.js.map +1 -0
- package/dist/display-monitor.d.ts +15 -2
- package/dist/display-monitor.d.ts.map +1 -1
- package/dist/display-monitor.js +104 -26
- package/dist/display-monitor.js.map +1 -1
- package/dist/esp32-serial.d.ts +160 -1
- package/dist/esp32-serial.d.ts.map +1 -1
- package/dist/esp32-serial.js +950 -153
- package/dist/esp32-serial.js.map +1 -1
- package/dist/fallback-task-timeline.d.ts +42 -0
- package/dist/fallback-task-timeline.d.ts.map +1 -0
- package/dist/fallback-task-timeline.js +112 -0
- package/dist/fallback-task-timeline.js.map +1 -0
- package/dist/foundation-models-helper.d.ts +11 -0
- package/dist/foundation-models-helper.d.ts.map +1 -0
- package/dist/foundation-models-helper.js +241 -0
- package/dist/foundation-models-helper.js.map +1 -0
- package/dist/hook-migration.js +1 -1
- package/dist/hook-migration.js.map +1 -1
- package/dist/hook-server.d.ts +2 -3
- package/dist/hook-server.d.ts.map +1 -1
- package/dist/hook-server.js +22 -10
- package/dist/hook-server.js.map +1 -1
- package/dist/idotmatrix/idotmatrix-daemon-sync.d.ts +33 -0
- package/dist/idotmatrix/idotmatrix-daemon-sync.d.ts.map +1 -0
- package/dist/idotmatrix/idotmatrix-daemon-sync.js +164 -0
- package/dist/idotmatrix/idotmatrix-daemon-sync.js.map +1 -0
- package/dist/idotmatrix/idotmatrix-discover.d.ts +18 -0
- package/dist/idotmatrix/idotmatrix-discover.d.ts.map +1 -0
- package/dist/idotmatrix/idotmatrix-discover.js +85 -0
- package/dist/idotmatrix/idotmatrix-discover.js.map +1 -0
- package/dist/idotmatrix/idotmatrix-settings.d.ts +20 -0
- package/dist/idotmatrix/idotmatrix-settings.d.ts.map +1 -0
- package/dist/idotmatrix/idotmatrix-settings.js +57 -0
- package/dist/idotmatrix/idotmatrix-settings.js.map +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +215 -179
- package/dist/index.js.map +1 -1
- package/dist/log-stream.d.ts +15 -16
- package/dist/log-stream.d.ts.map +1 -1
- package/dist/log-stream.js +18 -96
- package/dist/log-stream.js.map +1 -1
- package/dist/logger.d.ts.map +1 -1
- package/dist/logger.js +12 -3
- package/dist/logger.js.map +1 -1
- package/dist/mdns.d.ts +17 -0
- package/dist/mdns.d.ts.map +1 -1
- package/dist/mdns.js +52 -18
- package/dist/mdns.js.map +1 -1
- package/dist/modules/adb-module.d.ts +1 -1
- package/dist/modules/adb-module.d.ts.map +1 -1
- package/dist/modules/adb-module.js +4 -3
- package/dist/modules/adb-module.js.map +1 -1
- package/dist/modules/broadcast-module.d.ts +17 -0
- package/dist/modules/broadcast-module.d.ts.map +1 -0
- package/dist/modules/broadcast-module.js +26 -0
- package/dist/modules/broadcast-module.js.map +1 -0
- package/dist/modules/idotmatrix-module.d.ts +9 -0
- package/dist/modules/idotmatrix-module.d.ts.map +1 -0
- package/dist/modules/idotmatrix-module.js +46 -0
- package/dist/modules/idotmatrix-module.js.map +1 -0
- package/dist/modules/index.d.ts +3 -1
- package/dist/modules/index.d.ts.map +1 -1
- package/dist/modules/index.js +9 -3
- package/dist/modules/index.js.map +1 -1
- package/dist/modules/pixoo-module.d.ts.map +1 -1
- package/dist/modules/pixoo-module.js +14 -4
- package/dist/modules/pixoo-module.js.map +1 -1
- package/dist/modules/serial-module.d.ts +4 -0
- package/dist/modules/serial-module.d.ts.map +1 -1
- package/dist/modules/serial-module.js +14 -12
- package/dist/modules/serial-module.js.map +1 -1
- package/dist/modules/timebox-module.d.ts +9 -0
- package/dist/modules/timebox-module.d.ts.map +1 -0
- package/dist/modules/timebox-module.js +46 -0
- package/dist/modules/timebox-module.js.map +1 -0
- package/dist/modules/types.d.ts +4 -2
- package/dist/modules/types.d.ts.map +1 -1
- package/dist/openclaw-session.d.ts +18 -0
- package/dist/openclaw-session.d.ts.map +1 -0
- package/dist/openclaw-session.js +34 -0
- package/dist/openclaw-session.js.map +1 -0
- package/dist/output-parser.d.ts +30 -0
- package/dist/output-parser.d.ts.map +1 -1
- package/dist/output-parser.js +125 -9
- package/dist/output-parser.js.map +1 -1
- package/dist/passive-observer.d.ts +26 -0
- package/dist/passive-observer.d.ts.map +1 -1
- package/dist/passive-observer.js +258 -49
- package/dist/passive-observer.js.map +1 -1
- package/dist/permission-resolver.d.ts +47 -0
- package/dist/permission-resolver.d.ts.map +1 -0
- package/dist/permission-resolver.js +103 -0
- package/dist/permission-resolver.js.map +1 -0
- package/dist/pixoo/micro-glyphs.d.ts +49 -0
- package/dist/pixoo/micro-glyphs.d.ts.map +1 -0
- package/dist/pixoo/micro-glyphs.js +276 -0
- package/dist/pixoo/micro-glyphs.js.map +1 -0
- package/dist/pixoo/pixoo-bridge.d.ts +2 -2
- package/dist/pixoo/pixoo-bridge.d.ts.map +1 -1
- package/dist/pixoo/pixoo-bridge.js +93 -25
- package/dist/pixoo/pixoo-bridge.js.map +1 -1
- package/dist/pixoo/pixoo-camera.d.ts +19 -3
- package/dist/pixoo/pixoo-camera.d.ts.map +1 -1
- package/dist/pixoo/pixoo-camera.js +62 -27
- package/dist/pixoo/pixoo-camera.js.map +1 -1
- package/dist/pixoo/pixoo-client.d.ts +13 -3
- package/dist/pixoo/pixoo-client.d.ts.map +1 -1
- package/dist/pixoo/pixoo-client.js +51 -22
- package/dist/pixoo/pixoo-client.js.map +1 -1
- package/dist/pixoo/pixoo-discover.d.ts +37 -0
- package/dist/pixoo/pixoo-discover.d.ts.map +1 -0
- package/dist/pixoo/pixoo-discover.js +105 -0
- package/dist/pixoo/pixoo-discover.js.map +1 -0
- package/dist/pixoo/pixoo-renderer.d.ts +8 -3
- package/dist/pixoo/pixoo-renderer.d.ts.map +1 -1
- package/dist/pixoo/pixoo-renderer.js +189 -60
- package/dist/pixoo/pixoo-renderer.js.map +1 -1
- package/dist/pixoo/pixoo-settings.d.ts +6 -0
- package/dist/pixoo/pixoo-settings.d.ts.map +1 -1
- package/dist/pixoo/pixoo-settings.js +9 -0
- package/dist/pixoo/pixoo-settings.js.map +1 -1
- package/dist/pixoo/pixoo-sprites.d.ts +60 -11
- package/dist/pixoo/pixoo-sprites.d.ts.map +1 -1
- package/dist/pixoo/pixoo-sprites.js +512 -209
- package/dist/pixoo/pixoo-sprites.js.map +1 -1
- package/dist/pty-manager.d.ts.map +1 -1
- package/dist/pty-manager.js +8 -2
- package/dist/pty-manager.js.map +1 -1
- package/dist/session-activity.d.ts +14 -0
- package/dist/session-activity.d.ts.map +1 -0
- package/dist/session-activity.js +160 -0
- package/dist/session-activity.js.map +1 -0
- package/dist/session-aggregator.d.ts +17 -0
- package/dist/session-aggregator.d.ts.map +1 -1
- package/dist/session-aggregator.js +48 -9
- package/dist/session-aggregator.js.map +1 -1
- package/dist/session-registry.d.ts +71 -3
- package/dist/session-registry.d.ts.map +1 -1
- package/dist/session-registry.js +137 -8
- package/dist/session-registry.js.map +1 -1
- package/dist/session-timeline-relay.d.ts.map +1 -1
- package/dist/session-timeline-relay.js +13 -4
- package/dist/session-timeline-relay.js.map +1 -1
- package/dist/session-transcript-timeline.d.ts +49 -0
- package/dist/session-transcript-timeline.d.ts.map +1 -0
- package/dist/session-transcript-timeline.js +276 -0
- package/dist/session-transcript-timeline.js.map +1 -0
- package/dist/state-machine.d.ts +6 -1
- package/dist/state-machine.d.ts.map +1 -1
- package/dist/state-machine.js +86 -28
- package/dist/state-machine.js.map +1 -1
- package/dist/timebox/timebox-daemon-sync.d.ts +19 -0
- package/dist/timebox/timebox-daemon-sync.d.ts.map +1 -0
- package/dist/timebox/timebox-daemon-sync.js +135 -0
- package/dist/timebox/timebox-daemon-sync.js.map +1 -0
- package/dist/timebox/timebox-discover.d.ts +19 -0
- package/dist/timebox/timebox-discover.d.ts.map +1 -0
- package/dist/timebox/timebox-discover.js +87 -0
- package/dist/timebox/timebox-discover.js.map +1 -0
- package/dist/timebox/timebox-settings.d.ts +32 -0
- package/dist/timebox/timebox-settings.d.ts.map +1 -0
- package/dist/timebox/timebox-settings.js +80 -0
- package/dist/timebox/timebox-settings.js.map +1 -0
- package/dist/timeline-store.d.ts +63 -3
- package/dist/timeline-store.d.ts.map +1 -1
- package/dist/timeline-store.js +292 -14
- package/dist/timeline-store.js.map +1 -1
- package/dist/timeline-summarizer.d.ts.map +1 -1
- package/dist/timeline-summarizer.js +29 -5
- package/dist/timeline-summarizer.js.map +1 -1
- package/dist/tui/ansi.d.ts +0 -4
- package/dist/tui/ansi.d.ts.map +1 -1
- package/dist/tui/ansi.js +14 -7
- package/dist/tui/ansi.js.map +1 -1
- package/dist/tui/dashboard.d.ts +1 -0
- package/dist/tui/dashboard.d.ts.map +1 -1
- package/dist/tui/dashboard.js +24 -7
- package/dist/tui/dashboard.js.map +1 -1
- package/dist/tui/renderer.d.ts +36 -0
- package/dist/tui/renderer.d.ts.map +1 -1
- package/dist/tui/renderer.js +303 -119
- package/dist/tui/renderer.js.map +1 -1
- package/dist/tui/terrarium.d.ts.map +1 -1
- package/dist/tui/terrarium.js +37 -49
- package/dist/tui/terrarium.js.map +1 -1
- package/dist/types.d.ts +2 -2
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +2 -2
- package/dist/types.js.map +1 -1
- package/dist/usage-api.d.ts.map +1 -1
- package/dist/usage-api.js +7 -1
- package/dist/usage-api.js.map +1 -1
- package/dist/usage-event.d.ts +10 -3
- package/dist/usage-event.d.ts.map +1 -1
- package/dist/usage-event.js +74 -12
- package/dist/usage-event.js.map +1 -1
- package/dist/utility-proxy.d.ts.map +1 -1
- package/dist/utility-proxy.js +8 -0
- package/dist/utility-proxy.js.map +1 -1
- package/dist/utils/project-name.d.ts +3 -0
- package/dist/utils/project-name.d.ts.map +1 -1
- package/dist/utils/project-name.js +44 -2
- package/dist/utils/project-name.js.map +1 -1
- package/dist/windows-service.d.ts +26 -0
- package/dist/windows-service.d.ts.map +1 -0
- package/dist/windows-service.js +145 -0
- package/dist/windows-service.js.map +1 -0
- package/dist/ws-server.d.ts +22 -1
- package/dist/ws-server.d.ts.map +1 -1
- package/dist/ws-server.js +89 -4
- package/dist/ws-server.js.map +1 -1
- package/fm-helper/AgentDeckFMHelper.swift +112 -0
- package/package.json +9 -3
- package/scripts/build-fm-helper.mjs +26 -0
- package/LICENSE +0 -21
- package/dist/apme/tuner.d.ts +0 -64
- package/dist/apme/tuner.d.ts.map +0 -1
- package/dist/apme/tuner.js +0 -297
- package/dist/apme/tuner.js.map +0 -1
- package/dist/d200h/hid-protocol.d.ts +0 -62
- package/dist/d200h/hid-protocol.d.ts.map +0 -1
- package/dist/d200h/hid-protocol.js +0 -124
- package/dist/d200h/hid-protocol.js.map +0 -1
- package/dist/d200h/image-renderer.d.ts +0 -36
- package/dist/d200h/image-renderer.d.ts.map +0 -1
- package/dist/d200h/image-renderer.js +0 -487
- package/dist/d200h/image-renderer.js.map +0 -1
- package/dist/modules/d200h-module.d.ts +0 -43
- package/dist/modules/d200h-module.d.ts.map +0 -1
- package/dist/modules/d200h-module.js +0 -360
- package/dist/modules/d200h-module.js.map +0 -1
- package/dist/modules/d200h-renderer.d.ts +0 -7
- package/dist/modules/d200h-renderer.d.ts.map +0 -1
- package/dist/modules/d200h-renderer.js +0 -321
- package/dist/modules/d200h-renderer.js.map +0 -1
package/dist/tui/renderer.js
CHANGED
|
@@ -92,6 +92,11 @@ function typeIcon(type) {
|
|
|
92
92
|
case 'scheduled': return 's';
|
|
93
93
|
case 'user_action': return 'u';
|
|
94
94
|
case 'eval_result': return '#';
|
|
95
|
+
// Task hierarchy -- mirrors timelineIconKey() (shared/src/timeline-icons.ts):
|
|
96
|
+
// task_start/task_end -> task, task_milestone -> success.
|
|
97
|
+
case 'task_start':
|
|
98
|
+
case 'task_end': return '=';
|
|
99
|
+
case 'task_milestone': return '+';
|
|
95
100
|
default: return '*';
|
|
96
101
|
}
|
|
97
102
|
}
|
|
@@ -108,6 +113,10 @@ function typeIcon(type) {
|
|
|
108
113
|
case 'model_response': return '\u25C8';
|
|
109
114
|
case 'memory_recall': return '\u25CC';
|
|
110
115
|
case 'scheduled': return '\u25D1';
|
|
116
|
+
// Task hierarchy -- mirrors timelineIconKey() (shared/src/timeline-icons.ts).
|
|
117
|
+
case 'task_start':
|
|
118
|
+
case 'task_end': return '\u25A3'; // white square w/ centre
|
|
119
|
+
case 'task_milestone': return '\u2713'; // check mark
|
|
111
120
|
case 'eval_result': return '\u2605'; // ★
|
|
112
121
|
default: return '\u25C6';
|
|
113
122
|
}
|
|
@@ -140,20 +149,24 @@ function creatureEmoji(agentType) {
|
|
|
140
149
|
return 'D';
|
|
141
150
|
if (agentType === 'openclaw')
|
|
142
151
|
return 'C';
|
|
143
|
-
if (agentType === 'codex-cli')
|
|
152
|
+
if (agentType === 'codex-cli' || agentType === 'codex-app')
|
|
144
153
|
return 'X';
|
|
145
154
|
if (agentType === 'opencode')
|
|
146
155
|
return 'O';
|
|
156
|
+
if (agentType === 'antigravity')
|
|
157
|
+
return 'A';
|
|
147
158
|
return '*';
|
|
148
159
|
}
|
|
149
160
|
if (agentType === 'daemon')
|
|
150
161
|
return '\u2699\uFE0F'; // ⚙️
|
|
151
162
|
if (agentType === 'openclaw')
|
|
152
163
|
return '\uD83E\uDD9E'; // 🦞
|
|
153
|
-
if (agentType === 'codex-cli')
|
|
164
|
+
if (agentType === 'codex-cli' || agentType === 'codex-app')
|
|
154
165
|
return '\u2601'; // ☁ (cloud — matches creature)
|
|
155
166
|
if (agentType === 'opencode')
|
|
156
167
|
return '\u25A3'; // ▣ (nested square — matches creature)
|
|
168
|
+
if (agentType === 'antigravity')
|
|
169
|
+
return '\u25B2'; // ▲ (Antigravity peak)
|
|
157
170
|
return '\u273B'; // ✻ (teardrop-spoked asterisk — Claude sparkle)
|
|
158
171
|
}
|
|
159
172
|
function creatureBrandColor(agentType) {
|
|
@@ -162,8 +175,10 @@ function creatureBrandColor(agentType) {
|
|
|
162
175
|
switch (agentType) {
|
|
163
176
|
case 'claude-code': return fg(192, 112, 88); // terracotta
|
|
164
177
|
case 'openclaw': return fg(255, 77, 77); // red
|
|
165
|
-
case 'codex-cli':
|
|
178
|
+
case 'codex-cli':
|
|
179
|
+
case 'codex-app': return fg(177, 167, 255); // indigo
|
|
166
180
|
case 'opencode': return fg(241, 236, 236); // warm gray (#F1ECEC)
|
|
181
|
+
case 'antigravity': return fg(210, 214, 220); // Google gray
|
|
167
182
|
default: return '';
|
|
168
183
|
}
|
|
169
184
|
}
|
|
@@ -197,8 +212,129 @@ function sessionHotkeyLabel(index) {
|
|
|
197
212
|
return '·';
|
|
198
213
|
return String(index + 1);
|
|
199
214
|
}
|
|
200
|
-
|
|
201
|
-
|
|
215
|
+
/**
|
|
216
|
+
* Build the unified left-HUD entry list shared with macOS / iOS / Android.
|
|
217
|
+
*
|
|
218
|
+
* Collapses primary + siblings + virtual OpenClaw into one array, sorts via
|
|
219
|
+
* the shared sortSessions (agentType → projectName → startedAt → id), and
|
|
220
|
+
* applies #N suffix via assignDisplayNames so the display order and #N
|
|
221
|
+
* numbering match every other surface.
|
|
222
|
+
*
|
|
223
|
+
* Primary handling mirrors apple/AgentDeck/UI/Monitor/SessionListPanel.swift:
|
|
224
|
+
* - if a sibling matches our connected port, that sibling becomes the
|
|
225
|
+
* primary anchor (its startedAt anchors the sort position)
|
|
226
|
+
* - otherwise primary is appended only when no sibling shares its
|
|
227
|
+
* agentType (duplicatePrimaryWithoutId guard)
|
|
228
|
+
* - daemon / openclaw primaries are never appended (they're virtual)
|
|
229
|
+
*/
|
|
230
|
+
export function buildHudEntries(state) {
|
|
231
|
+
const items = [];
|
|
232
|
+
const portToItem = new Map();
|
|
233
|
+
for (const s of state.sessions) {
|
|
234
|
+
const ri = s;
|
|
235
|
+
const item = {
|
|
236
|
+
id: s.id,
|
|
237
|
+
projectName: s.projectName ?? 'unknown',
|
|
238
|
+
agentType: s.agentType ?? undefined,
|
|
239
|
+
state: s.state ?? 'idle',
|
|
240
|
+
modelName: s.modelName ?? undefined,
|
|
241
|
+
startedAt: s.startedAt ?? undefined,
|
|
242
|
+
port: s.port ?? undefined,
|
|
243
|
+
controlMode: ri.controlMode,
|
|
244
|
+
currentTask: ri.currentTask,
|
|
245
|
+
contextPercent: ri.contextPercent,
|
|
246
|
+
totalTokens: ri.totalTokens,
|
|
247
|
+
isPrimary: false,
|
|
248
|
+
isVirtualOpenClaw: false,
|
|
249
|
+
};
|
|
250
|
+
items.push(item);
|
|
251
|
+
if (item.port !== undefined)
|
|
252
|
+
portToItem.set(item.port, item);
|
|
253
|
+
}
|
|
254
|
+
if (state.agentType && state.agentType !== 'daemon' && state.agentType !== 'openclaw' && state.state) {
|
|
255
|
+
const anchor = state.currentPort != null ? portToItem.get(state.currentPort) : undefined;
|
|
256
|
+
if (anchor) {
|
|
257
|
+
// Patch anchor with primary's live fields. macOS / Android compose
|
|
258
|
+
// SessionEntry from primary state and only borrow the anchor sibling's
|
|
259
|
+
// startedAt; if we left the sibling's snapshot in place the row would
|
|
260
|
+
// render stale modelName / state / currentTask whenever the sibling
|
|
261
|
+
// payload lagged the primary state_update. startedAt, port, id, and
|
|
262
|
+
// controlMode stay with the anchor so sort position and hotkey
|
|
263
|
+
// identity match every other surface.
|
|
264
|
+
anchor.isPrimary = true;
|
|
265
|
+
anchor.projectName = state.projectName ?? anchor.projectName;
|
|
266
|
+
anchor.agentType = state.agentType;
|
|
267
|
+
anchor.state = state.state;
|
|
268
|
+
anchor.modelName = state.modelName ?? undefined;
|
|
269
|
+
anchor.currentTask = state.currentTool ?? undefined;
|
|
270
|
+
}
|
|
271
|
+
else {
|
|
272
|
+
const duplicateAgentType = state.sessions.some(s => s.agentType === state.agentType);
|
|
273
|
+
if (!duplicateAgentType) {
|
|
274
|
+
items.push({
|
|
275
|
+
id: '__self__',
|
|
276
|
+
projectName: state.projectName ?? 'unknown',
|
|
277
|
+
agentType: state.agentType,
|
|
278
|
+
state: state.state,
|
|
279
|
+
modelName: state.modelName ?? undefined,
|
|
280
|
+
startedAt: undefined,
|
|
281
|
+
port: state.currentPort ?? undefined,
|
|
282
|
+
controlMode: undefined,
|
|
283
|
+
currentTask: state.currentTool ?? undefined,
|
|
284
|
+
contextPercent: undefined,
|
|
285
|
+
totalTokens: undefined,
|
|
286
|
+
isPrimary: true,
|
|
287
|
+
isVirtualOpenClaw: false,
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
const hasOpenClaw = items.some(it => it.agentType === 'openclaw' || it.agentType === 'gateway');
|
|
293
|
+
if (state.gatewayAvailable && !hasOpenClaw) {
|
|
294
|
+
items.push({
|
|
295
|
+
id: '__virtual_openclaw__',
|
|
296
|
+
projectName: 'OpenClaw',
|
|
297
|
+
agentType: 'openclaw',
|
|
298
|
+
state: state.crayfishRouting ? 'processing' : 'idle',
|
|
299
|
+
modelName: undefined,
|
|
300
|
+
startedAt: undefined,
|
|
301
|
+
port: undefined,
|
|
302
|
+
controlMode: undefined,
|
|
303
|
+
currentTask: undefined,
|
|
304
|
+
contextPercent: undefined,
|
|
305
|
+
totalTokens: undefined,
|
|
306
|
+
isPrimary: false,
|
|
307
|
+
isVirtualOpenClaw: true,
|
|
308
|
+
});
|
|
309
|
+
}
|
|
310
|
+
const sorted = sortSessions(items);
|
|
311
|
+
const named = assignDisplayNames(sorted.map(it => ({
|
|
312
|
+
id: it.id,
|
|
313
|
+
projectName: it.projectName,
|
|
314
|
+
agentType: it.agentType,
|
|
315
|
+
state: it.state,
|
|
316
|
+
})));
|
|
317
|
+
return sorted.map((it, i) => ({
|
|
318
|
+
id: it.id,
|
|
319
|
+
displayName: named[i].displayName,
|
|
320
|
+
projectName: it.projectName,
|
|
321
|
+
agentType: it.agentType,
|
|
322
|
+
state: it.state,
|
|
323
|
+
modelName: it.modelName,
|
|
324
|
+
startedAt: it.startedAt,
|
|
325
|
+
port: it.port,
|
|
326
|
+
controlMode: it.controlMode,
|
|
327
|
+
currentTask: it.currentTask,
|
|
328
|
+
contextPercent: it.contextPercent,
|
|
329
|
+
totalTokens: it.totalTokens,
|
|
330
|
+
isPrimary: it.isPrimary,
|
|
331
|
+
isVirtualOpenClaw: it.isVirtualOpenClaw,
|
|
332
|
+
}));
|
|
333
|
+
}
|
|
334
|
+
function hudHotkeyIndex(entry, nextIndex) {
|
|
335
|
+
if (entry.isPrimary || entry.isVirtualOpenClaw)
|
|
336
|
+
return null;
|
|
337
|
+
if (!entry.port || entry.controlMode === 'observed')
|
|
202
338
|
return null;
|
|
203
339
|
return nextIndex;
|
|
204
340
|
}
|
|
@@ -214,6 +350,85 @@ function observedDetailParts(session) {
|
|
|
214
350
|
parts.push(session.currentTask);
|
|
215
351
|
return parts;
|
|
216
352
|
}
|
|
353
|
+
function asRecord(value) {
|
|
354
|
+
return value && typeof value === 'object' && !Array.isArray(value)
|
|
355
|
+
? value
|
|
356
|
+
: undefined;
|
|
357
|
+
}
|
|
358
|
+
function asArray(value) {
|
|
359
|
+
return Array.isArray(value) ? value : [];
|
|
360
|
+
}
|
|
361
|
+
function asNumber(value) {
|
|
362
|
+
return typeof value === 'number' && Number.isFinite(value) ? value : undefined;
|
|
363
|
+
}
|
|
364
|
+
function moduleStatusIcon(ok, warning = false) {
|
|
365
|
+
if (!terminalCaps.unicode)
|
|
366
|
+
return ok ? 'o' : warning ? '!' : 'x';
|
|
367
|
+
return ok ? '\u25CF' : warning ? '\u25C6' : '\u25CB';
|
|
368
|
+
}
|
|
369
|
+
function renderModuleHealthLines(moduleHealth, width) {
|
|
370
|
+
const lines = [];
|
|
371
|
+
if (!moduleHealth)
|
|
372
|
+
return lines;
|
|
373
|
+
const push = (label, detail, ok, warning = false) => {
|
|
374
|
+
const color = ok ? colors.idle : warning ? colors.awaiting : colors.dim;
|
|
375
|
+
lines.push(` ${color}${moduleStatusIcon(ok, warning)}${RESET} ${truncText(`${label} ${detail}`.trim(), width - 4)}`);
|
|
376
|
+
};
|
|
377
|
+
const serial = asRecord(moduleHealth.serial);
|
|
378
|
+
if (serial) {
|
|
379
|
+
const connections = asArray(serial.connections).map(asRecord).filter(Boolean);
|
|
380
|
+
const connected = connections.filter((c) => c.connected === true || c.transportOpen === true);
|
|
381
|
+
const boards = connected
|
|
382
|
+
.map((c) => asRecord(c.deviceInfo)?.board)
|
|
383
|
+
.filter((b) => typeof b === 'string' && b.length > 0);
|
|
384
|
+
const count = asNumber(serial.connectionCount) ?? connected.length;
|
|
385
|
+
const shown = boards.slice(0, 3).join(', ');
|
|
386
|
+
const more = boards.length > 3 ? ` +${boards.length - 3}` : '';
|
|
387
|
+
const detail = count > 0 ? `${count}${shown ? `: ${shown}${more}` : ''}` : 'none';
|
|
388
|
+
push('Serial', detail, count > 0, Boolean(serial.lastError));
|
|
389
|
+
}
|
|
390
|
+
const pixoo = asRecord(moduleHealth.pixoo);
|
|
391
|
+
if (pixoo) {
|
|
392
|
+
const devices = asArray(pixoo.devices).map(asRecord).filter(Boolean);
|
|
393
|
+
const configured = asNumber(pixoo.configuredDeviceCount) ?? devices.length;
|
|
394
|
+
const online = devices.filter((d) => d.online === true && d.backedOff !== true).length;
|
|
395
|
+
const dimmed = pixoo.displayDimmed === true ? ' dim' : '';
|
|
396
|
+
push('Pixoo', `${online}/${configured}${dimmed}`, configured > 0 && online > 0, configured > 0);
|
|
397
|
+
}
|
|
398
|
+
// BLE matrix panels — Divoom Timebox Mini + iDotMatrix. The Swift daemon
|
|
399
|
+
// reports a live `connected`/`statusReason`; the Node daemon only knows a
|
|
400
|
+
// panel is configured (the Python BLE sync subprocess owns the link), so a
|
|
401
|
+
// configured-but-state-unknown panel reads as amber "cfg" rather than a red
|
|
402
|
+
// offline, which would be a false negative for a working Node-driven panel.
|
|
403
|
+
for (const [key, label] of [['timebox', 'Timebox'], ['idotmatrix', 'iDotMatrix']]) {
|
|
404
|
+
const m = asRecord(moduleHealth[key]);
|
|
405
|
+
if (!m)
|
|
406
|
+
continue;
|
|
407
|
+
const configured = asNumber(m.configuredDeviceCount) ?? asArray(m.devices).length;
|
|
408
|
+
if (configured <= 0)
|
|
409
|
+
continue;
|
|
410
|
+
const connected = m.connected === true;
|
|
411
|
+
const dimmed = m.displayDimmed === true ? ' dim' : '';
|
|
412
|
+
const reason = typeof m.statusReason === 'string' ? m.statusReason : '';
|
|
413
|
+
const detail = connected ? `ready${dimmed}` : (reason || `${configured} cfg`);
|
|
414
|
+
push(label, detail, connected, !connected);
|
|
415
|
+
}
|
|
416
|
+
const d200h = asRecord(moduleHealth.d200h);
|
|
417
|
+
if (d200h) {
|
|
418
|
+
const connected = d200h.connected === true || d200h.managerOpened === true;
|
|
419
|
+
const owner = d200h.externalOwner === true ? ' plugin' : '';
|
|
420
|
+
const detail = connected ? `ready${owner}` : 'offline';
|
|
421
|
+
push('D200H', detail, connected, Boolean(d200h.lastOpenError || d200h.lastWriteError));
|
|
422
|
+
}
|
|
423
|
+
const adb = asRecord(moduleHealth.adb);
|
|
424
|
+
if (adb) {
|
|
425
|
+
const devices = asArray(adb.devices);
|
|
426
|
+
const reverse = asNumber(adb.reverseReadyCount) ?? devices.length;
|
|
427
|
+
const available = adb.available === true;
|
|
428
|
+
push('ADB', available ? `${reverse} reverse` : 'missing', available && reverse > 0, available);
|
|
429
|
+
}
|
|
430
|
+
return lines;
|
|
431
|
+
}
|
|
217
432
|
// ===== Panel Renderers =====
|
|
218
433
|
function renderAgentLines(state, maxWidth, useLogo) {
|
|
219
434
|
const lines = [];
|
|
@@ -241,68 +456,33 @@ function renderAgentLines(state, maxWidth, useLogo) {
|
|
|
241
456
|
lines.push(` ${hotkey} ${emoji} ${col}${name}${RESET}`);
|
|
242
457
|
lines.push(`${colors.dim} ${truncText(secondary, maxWidth - 4)}${RESET}`);
|
|
243
458
|
};
|
|
244
|
-
//
|
|
245
|
-
//
|
|
246
|
-
//
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
currentTask:
|
|
257
|
-
contextPercent:
|
|
258
|
-
totalTokens:
|
|
259
|
-
})
|
|
260
|
-
let focusableIndex = 0;
|
|
261
|
-
for (const d of displayed) {
|
|
262
|
-
const hotkeyIndex = sessionHotkeyIndex(d.session, focusableIndex);
|
|
263
|
-
if (hotkeyIndex !== null)
|
|
264
|
-
focusableIndex += 1;
|
|
265
|
-
renderSession(d.displayName, d.session.modelName, d.session.state || 'idle', d.session.agentType, hotkeyIndex, d.session);
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
|
-
else if (state.state) {
|
|
269
|
-
// Self (primary session)
|
|
270
|
-
renderSession(state.projectName || 'unknown', state.modelName ?? undefined, state.state, state.agentType ?? undefined, null);
|
|
271
|
-
// Siblings — include self as virtual entry for correct #N numbering
|
|
272
|
-
const sorted = sortSessions(state.sessions);
|
|
273
|
-
const selfEntry = {
|
|
274
|
-
id: '__self__', projectName: state.projectName || 'unknown',
|
|
275
|
-
agentType: state.agentType ?? undefined, state: state.state,
|
|
276
|
-
};
|
|
277
|
-
const allForNumbering = [selfEntry, ...sorted.map(s => ({
|
|
278
|
-
id: s.id, projectName: s.projectName || 'unknown', agentType: s.agentType, state: s.state,
|
|
279
|
-
modelName: s.modelName,
|
|
280
|
-
port: s.port, controlMode: s.controlMode,
|
|
281
|
-
currentTask: s.currentTask,
|
|
282
|
-
contextPercent: s.contextPercent,
|
|
283
|
-
totalTokens: s.totalTokens,
|
|
284
|
-
}))];
|
|
285
|
-
const displayed = assignDisplayNames(allForNumbering);
|
|
286
|
-
// Skip the self entry (index 0), render siblings with hotkey indices
|
|
287
|
-
let focusableIndex = 0;
|
|
288
|
-
for (let i = 1; i < displayed.length; i++) {
|
|
289
|
-
const d = displayed[i];
|
|
290
|
-
const sessionInfo = d.session;
|
|
291
|
-
const hotkeyIndex = sessionHotkeyIndex(sessionInfo, focusableIndex);
|
|
292
|
-
if (hotkeyIndex !== null)
|
|
293
|
-
focusableIndex += 1;
|
|
294
|
-
renderSession(d.displayName, d.session.modelName, d.session.state || 'idle', d.session.agentType, hotkeyIndex, sessionInfo);
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
// Virtual OpenClaw entry when gateway detected but not in sessions list
|
|
298
|
-
const hasOcSession = state.sessions.some(s => s.agentType === 'openclaw' || s.agentType === 'gateway');
|
|
299
|
-
if (state.gatewayAvailable && !hasOcSession) {
|
|
300
|
-
renderSession('OpenClaw', undefined, state.crayfishRouting ? 'processing' : 'idle', 'openclaw', null);
|
|
459
|
+
// Unified entry list (primary + siblings + virtual OpenClaw). Order and #N
|
|
460
|
+
// suffix matches macOS / iOS / Android via the shared sortSessions +
|
|
461
|
+
// assignDisplayNames pipeline inside buildHudEntries.
|
|
462
|
+
const entries = buildHudEntries(state);
|
|
463
|
+
let focusableIndex = 0;
|
|
464
|
+
for (const e of entries) {
|
|
465
|
+
const hotkeyIndex = hudHotkeyIndex(e, focusableIndex);
|
|
466
|
+
if (hotkeyIndex !== null)
|
|
467
|
+
focusableIndex += 1;
|
|
468
|
+
renderSession(e.displayName, e.modelName, e.state, e.agentType, hotkeyIndex, {
|
|
469
|
+
port: e.port,
|
|
470
|
+
controlMode: e.controlMode,
|
|
471
|
+
currentTask: e.currentTask,
|
|
472
|
+
contextPercent: e.contextPercent,
|
|
473
|
+
totalTokens: e.totalTokens,
|
|
474
|
+
});
|
|
301
475
|
}
|
|
302
476
|
// Gateway error warning
|
|
303
477
|
if (state.gatewayHasError) {
|
|
304
478
|
lines.push(`${colors.error} \u26A0 Gateway Error${RESET}`);
|
|
305
479
|
}
|
|
480
|
+
const moduleLines = renderModuleHealthLines(state.moduleHealth, maxWidth);
|
|
481
|
+
if (moduleLines.length > 0) {
|
|
482
|
+
lines.push('');
|
|
483
|
+
lines.push(`${colors.header} DOWNSTREAM${RESET}`);
|
|
484
|
+
lines.push(...moduleLines);
|
|
485
|
+
}
|
|
306
486
|
// Voice assistant indicator
|
|
307
487
|
if (state.voiceAssistantState && state.voiceAssistantState !== 'disabled' && state.voiceAssistantState !== 'idle') {
|
|
308
488
|
lines.push('');
|
|
@@ -391,9 +571,9 @@ function renderStatusLines(state, width) {
|
|
|
391
571
|
}
|
|
392
572
|
function renderOauthCatalogLines(modelCatalog, oauthConnected, width) {
|
|
393
573
|
const lines = [];
|
|
394
|
-
const models = modelCatalog.filter((m) => m.available).map((m) => m.name);
|
|
574
|
+
const models = (modelCatalog ?? []).filter((m) => m.available).map((m) => m.name);
|
|
395
575
|
if (models.length > 0) {
|
|
396
|
-
return wrapCommaList(' OAuth: ', models, width);
|
|
576
|
+
return wrapCommaList(' OAuth: ', models, width, 4);
|
|
397
577
|
}
|
|
398
578
|
if (oauthConnected === true) {
|
|
399
579
|
lines.push(`${colors.dim}${truncText(' OAuth: connected', width)}${RESET}`);
|
|
@@ -403,22 +583,38 @@ function renderOauthCatalogLines(modelCatalog, oauthConnected, width) {
|
|
|
403
583
|
}
|
|
404
584
|
return lines;
|
|
405
585
|
}
|
|
406
|
-
function wrapCommaList(prefix, items, width) {
|
|
586
|
+
function wrapCommaList(prefix, items, width, maxLines = Number.POSITIVE_INFINITY) {
|
|
407
587
|
const lines = [];
|
|
408
588
|
const indent = ' '.repeat(prefix.length);
|
|
409
589
|
let current = prefix;
|
|
590
|
+
let consumed = 0;
|
|
410
591
|
for (let i = 0; i < items.length; i++) {
|
|
411
592
|
const chunk = i === 0 ? items[i] : `, ${items[i]}`;
|
|
412
593
|
if (visLen(current) + visLen(chunk) <= width) {
|
|
413
594
|
current += chunk;
|
|
595
|
+
consumed = i + 1;
|
|
414
596
|
continue;
|
|
415
597
|
}
|
|
416
598
|
if (visLen(current) > visLen(prefix)) {
|
|
417
599
|
lines.push(`${colors.dim}${padRight(current, width)}${RESET}`.trimEnd());
|
|
600
|
+
if (lines.length >= maxLines) {
|
|
601
|
+
const hidden = items.length - consumed;
|
|
602
|
+
if (hidden > 0)
|
|
603
|
+
lines.push(`${colors.dim}${truncText(` ${hidden} more models`, width)}${RESET}`);
|
|
604
|
+
return lines;
|
|
605
|
+
}
|
|
418
606
|
current = indent + items[i];
|
|
607
|
+
consumed = i + 1;
|
|
419
608
|
continue;
|
|
420
609
|
}
|
|
421
610
|
lines.push(`${colors.dim}${truncText(current + chunk, width)}${RESET}`);
|
|
611
|
+
consumed = i + 1;
|
|
612
|
+
if (lines.length >= maxLines) {
|
|
613
|
+
const hidden = items.length - consumed;
|
|
614
|
+
if (hidden > 0)
|
|
615
|
+
lines.push(`${colors.dim}${truncText(` ${hidden} more models`, width)}${RESET}`);
|
|
616
|
+
return lines;
|
|
617
|
+
}
|
|
422
618
|
current = indent;
|
|
423
619
|
}
|
|
424
620
|
if (visLen(current.trim()) > 0) {
|
|
@@ -451,12 +647,33 @@ function renderTimelineLines(state, width, maxLines, scrollOffset) {
|
|
|
451
647
|
const e = entries[i];
|
|
452
648
|
const time = new Date(e.ts);
|
|
453
649
|
const timeStr = `${String(time.getHours()).padStart(2, '0')}:${String(time.getMinutes()).padStart(2, '0')}`;
|
|
454
|
-
|
|
650
|
+
// task_end rows append a score+outcome suffix once the LLM judge resolves
|
|
651
|
+
// (5–30 s after the boundary itself). Until then the `taskOutcome` field
|
|
652
|
+
// is undefined and we render only the boundary label.
|
|
653
|
+
const evalSuffix = (e.type === 'task_end' && e.taskOutcome)
|
|
654
|
+
? formatTaskEvalSuffix(e.taskScore, e.taskOutcome)
|
|
655
|
+
: '';
|
|
656
|
+
const raw = truncText(`${e.raw}${evalSuffix}`, width - 10);
|
|
455
657
|
const pending = e.status === 'pending' ? `${colors.dim} [PENDING]${RESET}` : '';
|
|
456
658
|
lines.push(` ${colors.dim}${timeStr}${RESET} ${typeColor(e.type)}${typeIcon(e.type)}${RESET} ${raw}${pending}`);
|
|
457
659
|
}
|
|
458
660
|
return lines;
|
|
459
661
|
}
|
|
662
|
+
export function formatTaskEvalSuffix(score, outcome) {
|
|
663
|
+
// `abandoned` flows from the manual `agentdeck task cancel` path and
|
|
664
|
+
// must render as its own glyph — not fall through to '' (which would
|
|
665
|
+
// make the task look pending) and not borrow the fail glyph (which
|
|
666
|
+
// would read as agent failure rather than user-initiated stop).
|
|
667
|
+
const glyph = outcome === 'success' ? '✓'
|
|
668
|
+
: outcome === 'fail' ? '✗'
|
|
669
|
+
: outcome === 'partial' ? '△'
|
|
670
|
+
: outcome === 'abandoned' ? '⊘'
|
|
671
|
+
: '';
|
|
672
|
+
if (!glyph)
|
|
673
|
+
return '';
|
|
674
|
+
const scoreText = typeof score === 'number' ? score.toFixed(2) : '?';
|
|
675
|
+
return ` · ${scoreText} ${glyph}`;
|
|
676
|
+
}
|
|
460
677
|
function timelineHeader(state, width, maxLines, scrollOffset) {
|
|
461
678
|
const total = state.timeline.length;
|
|
462
679
|
if (total === 0)
|
|
@@ -649,64 +866,31 @@ function renderStandardLayout(state, cols, rows, terrariumLines, frame, scrollOf
|
|
|
649
866
|
}
|
|
650
867
|
function renderAgentCompactLines(state, width) {
|
|
651
868
|
const lines = [];
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
if (hotkeyIndex !== null)
|
|
668
|
-
focusableIndex += 1;
|
|
669
|
-
lines.push(` ${colors.dim}[${sessionHotkeyLabel(hotkeyIndex)}]${RESET} ${emoji} ${project} ${status}${marker}${model}`);
|
|
670
|
-
}
|
|
671
|
-
}
|
|
672
|
-
else if (state.state) {
|
|
673
|
-
// Self first
|
|
674
|
-
const col = stateColor(state.state);
|
|
675
|
-
const proj = truncText(state.projectName || '?', Math.max(8, width - 16));
|
|
676
|
-
const status = `${col}${stateIcon(state.state)} ${compactStateLabel(state.state)}${RESET}`;
|
|
677
|
-
const model = state.modelName ? `${colors.dim} · ${truncText(state.modelName, Math.max(8, width - 24))}${RESET}` : '';
|
|
678
|
-
const emoji = `${creatureBrandColor(state.agentType ?? undefined)}${creatureEmoji(state.agentType ?? undefined)}${RESET}`;
|
|
679
|
-
lines.push(` ${emoji} ${proj} ${status}${model}`);
|
|
680
|
-
// Siblings
|
|
681
|
-
let focusableIndex = 0;
|
|
682
|
-
for (const s of sortSessions(state.sessions)) {
|
|
683
|
-
const renderInfo = s;
|
|
684
|
-
const st = s.state || 'idle';
|
|
685
|
-
const sCol = stateColor(st);
|
|
686
|
-
const sEmoji = `${creatureBrandColor(s.agentType)}${creatureEmoji(s.agentType)}${RESET}`;
|
|
687
|
-
const sStatus = `${sCol}${stateIcon(st)} ${compactStateLabel(st)}${RESET}`;
|
|
688
|
-
const detail = renderInfo.currentTask || s.modelName;
|
|
689
|
-
const sModel = detail ? `${colors.dim} · ${truncText(detail, Math.max(8, width - 24))}${RESET}` : '';
|
|
690
|
-
const marker = renderInfo.controlMode === 'observed' ? `${colors.dim} · obs${RESET}` : '';
|
|
691
|
-
const sProject = truncText(s.projectName || '?', Math.max(8, width - 20));
|
|
692
|
-
const hotkeyIndex = sessionHotkeyIndex(renderInfo, focusableIndex);
|
|
693
|
-
if (hotkeyIndex !== null)
|
|
694
|
-
focusableIndex += 1;
|
|
695
|
-
lines.push(` ${colors.dim}[${sessionHotkeyLabel(hotkeyIndex)}]${RESET} ${sEmoji} ${sProject} ${sStatus}${marker}${sModel}`);
|
|
696
|
-
}
|
|
697
|
-
}
|
|
698
|
-
// Virtual OpenClaw entry
|
|
699
|
-
const hasOcCompact = state.sessions.some(s => s.agentType === 'openclaw' || s.agentType === 'gateway');
|
|
700
|
-
if (state.gatewayAvailable && !hasOcCompact) {
|
|
701
|
-
const ocState = state.crayfishRouting ? 'processing' : 'idle';
|
|
702
|
-
const ocCol = stateColor(ocState);
|
|
703
|
-
const ocEmoji = `${creatureBrandColor('openclaw')}${creatureEmoji('openclaw')}${RESET}`;
|
|
704
|
-
lines.push(` ${ocEmoji} OpenClaw ${ocCol}${stateIcon(ocState)}${ocState.toUpperCase()}${RESET}`);
|
|
869
|
+
// Unified entry list — same ordering and #N suffix as macOS / iOS / Android.
|
|
870
|
+
const entries = buildHudEntries(state);
|
|
871
|
+
let focusableIndex = 0;
|
|
872
|
+
for (const e of entries) {
|
|
873
|
+
const hotkeyIndex = hudHotkeyIndex(e, focusableIndex);
|
|
874
|
+
if (hotkeyIndex !== null)
|
|
875
|
+
focusableIndex += 1;
|
|
876
|
+
const col = stateColor(e.state);
|
|
877
|
+
const emoji = `${creatureBrandColor(e.agentType)}${creatureEmoji(e.agentType)}${RESET}`;
|
|
878
|
+
const status = `${col}${stateIcon(e.state)} ${compactStateLabel(e.state)}${RESET}`;
|
|
879
|
+
const detail = e.currentTask || e.modelName;
|
|
880
|
+
const model = detail ? `${colors.dim} · ${truncText(detail, Math.max(8, width - 24))}${RESET}` : '';
|
|
881
|
+
const marker = e.controlMode === 'observed' ? `${colors.dim} · obs${RESET}` : '';
|
|
882
|
+
const project = truncText(e.displayName, Math.max(8, width - 20));
|
|
883
|
+
lines.push(` ${colors.dim}[${sessionHotkeyLabel(hotkeyIndex)}]${RESET} ${emoji} ${project} ${status}${marker}${model}`);
|
|
705
884
|
}
|
|
706
885
|
// Gateway error warning
|
|
707
886
|
if (state.gatewayHasError) {
|
|
708
887
|
lines.push(`${colors.error} \u26A0 Gateway Error${RESET}`);
|
|
709
888
|
}
|
|
889
|
+
const moduleLines = renderModuleHealthLines(state.moduleHealth, width);
|
|
890
|
+
if (moduleLines.length > 0) {
|
|
891
|
+
lines.push(`${colors.header} DOWNSTREAM${RESET}`);
|
|
892
|
+
lines.push(...moduleLines);
|
|
893
|
+
}
|
|
710
894
|
// Voice assistant indicator (compact)
|
|
711
895
|
if (state.voiceAssistantState && state.voiceAssistantState !== 'disabled' && state.voiceAssistantState !== 'idle') {
|
|
712
896
|
if (state.voiceAssistantState === 'listening') {
|