@agentdeck/bridge 0.2.2 → 1.0.0
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/fm-helper/agentdeck-fm-helper +0 -0
- 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 +133 -6
- package/dist/apme/collector.d.ts.map +1 -1
- package/dist/apme/collector.js +471 -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 +117 -11
- package/dist/apme/dashboard-html.js.map +1 -1
- package/dist/apme/http.d.ts.map +1 -1
- package/dist/apme/http.js +52 -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 +146 -9
- package/dist/apme/index.js.map +1 -1
- package/dist/apme/judge-detect.d.ts +26 -0
- package/dist/apme/judge-detect.d.ts.map +1 -0
- package/dist/apme/judge-detect.js +69 -0
- package/dist/apme/judge-detect.js.map +1 -0
- 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 +99 -4
- package/dist/apme/runner.d.ts.map +1 -1
- package/dist/apme/runner.js +743 -72
- 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 +17 -11
- package/dist/apme/settings.d.ts.map +1 -1
- package/dist/apme/settings.js +30 -9
- 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 +112 -0
- package/dist/awaiting-overlay.d.ts.map +1 -0
- package/dist/awaiting-overlay.js +179 -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 +34 -1
- package/dist/bridge-core.d.ts.map +1 -1
- package/dist/bridge-core.js +207 -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/claude-permission-rules.d.ts +55 -0
- package/dist/claude-permission-rules.d.ts.map +1 -0
- package/dist/claude-permission-rules.js +197 -0
- package/dist/claude-permission-rules.js.map +1 -0
- package/dist/cli.d.ts +15 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +1030 -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/d200h/image-renderer.d.ts +4 -16
- package/dist/d200h/image-renderer.d.ts.map +1 -1
- package/dist/d200h/image-renderer.js +46 -212
- package/dist/d200h/image-renderer.js.map +1 -1
- package/dist/daemon-server.d.ts +85 -0
- package/dist/daemon-server.d.ts.map +1 -1
- package/dist/daemon-server.js +1975 -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 +190 -1
- package/dist/esp32-serial.d.ts.map +1 -1
- package/dist/esp32-serial.js +1090 -156
- 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 +119 -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 +23 -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 +217 -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 +3 -1
- package/dist/logger.d.ts.map +1 -1
- package/dist/logger.js +18 -5
- 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/model-catalog.d.ts +1 -1
- package/dist/model-catalog.d.ts.map +1 -1
- package/dist/model-catalog.js +2 -4
- package/dist/model-catalog.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/d200h-module.d.ts +22 -0
- package/dist/modules/d200h-module.d.ts.map +1 -1
- package/dist/modules/d200h-module.js +200 -65
- package/dist/modules/d200h-module.js.map +1 -1
- 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/trmnl-module.d.ts +38 -0
- package/dist/modules/trmnl-module.d.ts.map +1 -0
- package/dist/modules/trmnl-module.js +111 -0
- package/dist/modules/trmnl-module.js.map +1 -0
- package/dist/modules/types.d.ts +4 -2
- package/dist/modules/types.d.ts.map +1 -1
- package/dist/observed-steering.d.ts +93 -0
- package/dist/observed-steering.d.ts.map +1 -0
- package/dist/observed-steering.js +247 -0
- package/dist/observed-steering.js.map +1 -0
- 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/opencode-steering.d.ts +36 -0
- package/dist/opencode-steering.d.ts.map +1 -0
- package/dist/opencode-steering.js +84 -0
- package/dist/opencode-steering.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 +172 -18
- package/dist/output-parser.js.map +1 -1
- package/dist/passive-observer.d.ts +32 -0
- package/dist/passive-observer.d.ts.map +1 -1
- package/dist/passive-observer.js +288 -49
- package/dist/passive-observer.js.map +1 -1
- package/dist/permission-resolver.d.ts +55 -0
- package/dist/permission-resolver.d.ts.map +1 -0
- package/dist/permission-resolver.js +112 -0
- package/dist/permission-resolver.js.map +1 -0
- package/dist/pixoo/micro-glyphs.d.ts +18 -0
- package/dist/pixoo/micro-glyphs.d.ts.map +1 -0
- package/dist/pixoo/micro-glyphs.js +143 -0
- package/dist/pixoo/micro-glyphs.js.map +1 -0
- package/dist/pixoo/official-dot-glyphs.generated.d.ts +8 -0
- package/dist/pixoo/official-dot-glyphs.generated.d.ts.map +1 -0
- package/dist/pixoo/official-dot-glyphs.generated.js +247 -0
- package/dist/pixoo/official-dot-glyphs.generated.js.map +1 -0
- package/dist/pixoo/pixoo-bridge.d.ts +16 -8
- package/dist/pixoo/pixoo-bridge.d.ts.map +1 -1
- package/dist/pixoo/pixoo-bridge.js +127 -35
- 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 +27 -3
- package/dist/pixoo/pixoo-renderer.d.ts.map +1 -1
- package/dist/pixoo/pixoo-renderer.js +533 -135
- 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 +84 -11
- package/dist/pixoo/pixoo-sprites.d.ts.map +1 -1
- package/dist/pixoo/pixoo-sprites.js +620 -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/review-runner.d.ts +113 -0
- package/dist/review-runner.d.ts.map +1 -0
- package/dist/review-runner.js +428 -0
- package/dist/review-runner.js.map +1 -0
- 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 +25 -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-focus-relay.d.ts.map +1 -1
- package/dist/session-focus-relay.js +7 -1
- package/dist/session-focus-relay.js.map +1 -1
- package/dist/session-registry.d.ts +74 -3
- package/dist/session-registry.d.ts.map +1 -1
- package/dist/session-registry.js +140 -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 +112 -3
- package/dist/timeline-store.d.ts.map +1 -1
- package/dist/timeline-store.js +460 -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/trmnl/byos-server.d.ts +39 -0
- package/dist/trmnl/byos-server.d.ts.map +1 -0
- package/dist/trmnl/byos-server.js +301 -0
- package/dist/trmnl/byos-server.js.map +1 -0
- package/dist/trmnl/frame-cache.d.ts +37 -0
- package/dist/trmnl/frame-cache.d.ts.map +1 -0
- package/dist/trmnl/frame-cache.js +157 -0
- package/dist/trmnl/frame-cache.js.map +1 -0
- package/dist/trmnl/image-renderer.d.ts +27 -0
- package/dist/trmnl/image-renderer.d.ts.map +1 -0
- package/dist/trmnl/image-renderer.js +235 -0
- package/dist/trmnl/image-renderer.js.map +1 -0
- package/dist/trmnl/trmnl-settings.d.ts +96 -0
- package/dist/trmnl/trmnl-settings.d.ts.map +1 -0
- package/dist/trmnl/trmnl-settings.js +177 -0
- package/dist/trmnl/trmnl-settings.js.map +1 -0
- package/dist/trmnl/trmnl-telemetry.d.ts +47 -0
- package/dist/trmnl/trmnl-telemetry.d.ts.map +1 -0
- package/dist/trmnl/trmnl-telemetry.js +56 -0
- package/dist/trmnl/trmnl-telemetry.js.map +1 -0
- 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 +38 -11
- 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 +355 -121
- package/dist/tui/renderer.js.map +1 -1
- package/dist/tui/terrarium.d.ts.map +1 -1
- package/dist/tui/terrarium.js +44 -51
- 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 +98 -13
- 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/version-check.d.ts.map +1 -1
- package/dist/version-check.js +1 -17
- package/dist/version-check.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 +17 -3
- package/dist/ws-server.d.ts.map +1 -1
- package/dist/ws-server.js +78 -8
- package/dist/ws-server.js.map +1 -1
- package/fm-helper/AgentDeckFMHelper.swift +112 -0
- package/package.json +10 -4
- 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/index.js
CHANGED
|
@@ -5,13 +5,18 @@
|
|
|
5
5
|
* Uses BridgeCore for shared infrastructure.
|
|
6
6
|
*/
|
|
7
7
|
import { BridgeCore } from './bridge-core.js';
|
|
8
|
-
import {
|
|
8
|
+
import { buildDisplayStateEvent } from './display-dim.js';
|
|
9
|
+
import { SERIAL_FORWARDED_EVENTS } from '@agentdeck/shared/protocol';
|
|
10
|
+
import { prepareForSerial } from './esp32-serial.js';
|
|
11
|
+
import { initApme, isTimelineProjectionEnabled } from './apme/index.js';
|
|
12
|
+
import { FallbackTaskTimeline } from './fallback-task-timeline.js';
|
|
9
13
|
import { readLastTurn as readClaudeTranscriptLastTurn } from './apme/claude-transcript-reader.js';
|
|
10
14
|
import { claudeHookToSpans } from './apme/adapters/claude-hook.js';
|
|
15
|
+
import { codexHookToSpans } from './apme/adapters/codex-hook.js';
|
|
16
|
+
import { CodexTurnManager } from './apme/adapters/codex-turn-manager.js';
|
|
11
17
|
import { claudePtyParserEventToSpans, claudePtyResponseToSpan } from './apme/adapters/claude-pty.js';
|
|
12
18
|
import { timelineEntryToSpans } from './apme/adapters/timeline.js';
|
|
13
|
-
import {
|
|
14
|
-
import { randomUUID } from 'crypto';
|
|
19
|
+
import { classifyAndEnqueueTurn } from './apme/classify-turn.js';
|
|
15
20
|
import { VoiceManager } from './voice.js';
|
|
16
21
|
import { checkDependencies } from './check-deps.js';
|
|
17
22
|
import { enableDebugLog, log, debug, setPtyMode } from './logger.js';
|
|
@@ -22,8 +27,8 @@ import { createAdapter, ClaudeCodeAdapter, CodexCliAdapter, OpenCodeAdapter } fr
|
|
|
22
27
|
import { MonitorAdapter } from './adapters/monitor.js';
|
|
23
28
|
import { UtilityProxy } from './utility-proxy.js';
|
|
24
29
|
import { BridgeLogStream } from './log-stream.js';
|
|
25
|
-
import {
|
|
26
|
-
import {
|
|
30
|
+
import { cleanRawText, prepareMarkdownDetail, extractTopicHintWithKind, promptSnippetFallback, } from '@agentdeck/shared';
|
|
31
|
+
import { injectOpenClawSession } from './openclaw-session.js';
|
|
27
32
|
import { VoiceAssistantManager } from './voice-assistant.js';
|
|
28
33
|
import { TerminalStatus } from './terminal-status.js';
|
|
29
34
|
import { readFileSync } from 'fs';
|
|
@@ -142,6 +147,15 @@ export async function startSession(opts) {
|
|
|
142
147
|
log(`Starting AgentDeck bridge on port ${port} (agent: ${agentType})...`);
|
|
143
148
|
// ===== Create adapter =====
|
|
144
149
|
const adapter = createAdapter(agentType, opts.gatewayUrl);
|
|
150
|
+
// Seed the resolved (git-aware) name into the Claude output parser so its
|
|
151
|
+
// legacy PROJECT_DIR scrape doesn't override it: the scrape captures the
|
|
152
|
+
// bare basename of ANY path-like terminal line (first match sticks) and
|
|
153
|
+
// flows through the state-machine snapshot, which used to win over the
|
|
154
|
+
// resolver — a monorepo-subdir session would flip from the repo name to
|
|
155
|
+
// the subdir (or to an unrelated printed path).
|
|
156
|
+
if (adapter instanceof ClaudeCodeAdapter) {
|
|
157
|
+
adapter.seedProjectName(projectName);
|
|
158
|
+
}
|
|
145
159
|
// ===== Start adapter (creates HTTP server, spawns process) =====
|
|
146
160
|
try {
|
|
147
161
|
await adapter.start({ port, command: opts.command, gatewayUrl: opts.gatewayUrl });
|
|
@@ -162,36 +176,47 @@ export async function startSession(opts) {
|
|
|
162
176
|
projectName,
|
|
163
177
|
httpServer: adapter.getHttpServer(),
|
|
164
178
|
});
|
|
179
|
+
const esp32WifiEvents = new Set([
|
|
180
|
+
...SERIAL_FORWARDED_EVENTS,
|
|
181
|
+
'esp32_ota_begin',
|
|
182
|
+
'esp32_ota_chunk',
|
|
183
|
+
'esp32_ota_end',
|
|
184
|
+
'esp32_ota_abort',
|
|
185
|
+
]);
|
|
186
|
+
core.wsServer.setEventTransformer((event, client) => {
|
|
187
|
+
if (!core.wsServer.isEsp32Client(client))
|
|
188
|
+
return event;
|
|
189
|
+
if (!esp32WifiEvents.has(event.type))
|
|
190
|
+
return null;
|
|
191
|
+
return prepareForSerial(event);
|
|
192
|
+
});
|
|
165
193
|
// ===== APME (Agent Performance Monitoring & Evaluation) =====
|
|
166
194
|
// Optional: degrades to no-op if better-sqlite3 isn't installed.
|
|
167
|
-
|
|
195
|
+
// emitTimeline forwards task_start/task_end so the dashboard sees the task
|
|
196
|
+
// hierarchy header rows that group turns by APME boundary signal.
|
|
197
|
+
const projectTimeline = isTimelineProjectionEnabled();
|
|
198
|
+
const apme = await initApme(undefined, {
|
|
199
|
+
emitTimeline: (entry) => core.bridgeTimeline.addEntry(entry),
|
|
200
|
+
projectSampleTimeline: projectTimeline,
|
|
201
|
+
emitProjectedTimeline: (entry) => core.bridgeTimeline.addEntry(entry, { bypassSuppression: true }),
|
|
202
|
+
});
|
|
168
203
|
if (apme) {
|
|
169
204
|
core.setApme(apme, process.cwd());
|
|
205
|
+
if (projectTimeline) {
|
|
206
|
+
core.bridgeTimeline.setSuppressLocalChatTool(true);
|
|
207
|
+
log('APME timeline projection ENABLED (AGENTDECK_TIMELINE_PROJECTION=1) — chat/tool rows derive from SessionSample');
|
|
208
|
+
}
|
|
170
209
|
log('APME enabled — runs will be logged to ~/.agentdeck/apme.sqlite');
|
|
171
|
-
//
|
|
172
|
-
//
|
|
173
|
-
|
|
174
|
-
if (turnId) {
|
|
175
|
-
// Turn-level eval completed
|
|
176
|
-
const run = apme.store.getRun(runId);
|
|
177
|
-
if (!run)
|
|
178
|
-
return;
|
|
179
|
-
const turnEvals = apme.store.listEvalsForTurn(turnId);
|
|
180
|
-
const overall = turnEvals.find(e => e.metric === 'overall');
|
|
181
|
-
if (!overall)
|
|
182
|
-
return;
|
|
183
|
-
const pct = Math.round(overall.score * 100);
|
|
184
|
-
const axes = turnEvals.filter(e => e.metric !== 'overall');
|
|
185
|
-
const axisStr = axes.map(e => `${e.metric}=${Math.round(e.score * 100)}%`).join(' ');
|
|
186
|
-
core.bridgeTimeline.addEntry({
|
|
187
|
-
ts: Date.now(), type: 'eval_result',
|
|
188
|
-
raw: `★ turn ${pct}% [${run.taskCategory ?? '?'}]`,
|
|
189
|
-
detail: axisStr || `Turn eval · ${run.taskPrompt?.slice(0, 80) ?? ''}`,
|
|
190
|
-
agentType: run.agentType,
|
|
191
|
-
});
|
|
192
|
-
}
|
|
193
|
-
});
|
|
210
|
+
// Eval results are no longer projected onto the timeline (the timeline is an
|
|
211
|
+
// activity log only). Scores are stored in apme.sqlite and surfaced via the
|
|
212
|
+
// scorecard / `apme_eval` WS event, keeping the timeline noise-free.
|
|
194
213
|
}
|
|
214
|
+
// APME down (better-sqlite3 failed to load): keep the timeline's task
|
|
215
|
+
// hierarchy alive by minting fallback task_start/task_end rows from the
|
|
216
|
+
// hook boundary signals. No storage, no eval — structure only.
|
|
217
|
+
const fallbackTasks = apme
|
|
218
|
+
? null
|
|
219
|
+
: new FallbackTaskTimeline((entry) => core.bridgeTimeline.addEntry(entry), { agentType });
|
|
195
220
|
// ===== Session-specific components =====
|
|
196
221
|
const voiceManager = new VoiceManager();
|
|
197
222
|
const utilityProxy = new UtilityProxy();
|
|
@@ -260,26 +285,29 @@ export async function startSession(opts) {
|
|
|
260
285
|
hookServer.setMeta({ agentType, projectName });
|
|
261
286
|
hookServer.setVoiceManager(voiceManager);
|
|
262
287
|
hookServer.onApiUsage(() => ({ usage: core.cachedApiUsage, fetchedAt: core.lastApiFetchTime }));
|
|
263
|
-
hookServer.pairingToken = core.authToken;
|
|
264
288
|
}
|
|
265
289
|
else if (adapter instanceof CodexCliAdapter) {
|
|
266
290
|
hookServer = adapter.getCodexHookServer();
|
|
267
291
|
hookServer.setMeta({ agentType, projectName });
|
|
268
292
|
hookServer.setVoiceManager(voiceManager);
|
|
269
|
-
hookServer.pairingToken = core.authToken;
|
|
270
293
|
}
|
|
271
294
|
else if (adapter instanceof OpenCodeAdapter) {
|
|
272
295
|
hookServer = adapter.getHookServer();
|
|
273
296
|
hookServer.setMeta({ agentType, projectName });
|
|
274
297
|
hookServer.setVoiceManager(voiceManager);
|
|
275
|
-
|
|
298
|
+
// OpenCode has no CLI-level hooks; SSE is the only event channel. Bind
|
|
299
|
+
// the adapter to the APME session so SSE-derived spans (tool_call /
|
|
300
|
+
// tool_result / task_boundary / turn_*) can reach the collector. Without
|
|
301
|
+
// this OpenCode sessions land in APME's runs table but never get
|
|
302
|
+
// per-task evaluation — every session collapses to a single session_end
|
|
303
|
+
// task boundary, defeating per-task scoring.
|
|
304
|
+
adapter.setApmeSession(core.sessionId, process.cwd());
|
|
276
305
|
}
|
|
277
306
|
else if (adapter instanceof MonitorAdapter) {
|
|
278
307
|
hookServer = adapter.getHookServer();
|
|
279
308
|
hookServer.setMeta({ agentType, projectName });
|
|
280
309
|
hookServer.setVoiceManager(voiceManager);
|
|
281
310
|
hookServer.onApiUsage(() => ({ usage: core.cachedApiUsage, fetchedAt: core.lastApiFetchTime }));
|
|
282
|
-
hookServer.pairingToken = core.authToken;
|
|
283
311
|
}
|
|
284
312
|
const broadcastSse = (event) => hookServer?.broadcastSse(event);
|
|
285
313
|
core.setSseBroadcast(broadcastSse);
|
|
@@ -305,6 +333,7 @@ export async function startSession(opts) {
|
|
|
305
333
|
adb: 'auto',
|
|
306
334
|
serial: false, // daemon-only — session bridges never talk to ESP32
|
|
307
335
|
pixoo: false, // daemon-only — session bridges never talk to Pixoo
|
|
336
|
+
timebox: false, // daemon-only — session bridges never talk to Timebox
|
|
308
337
|
};
|
|
309
338
|
const deviceModules = createDefaultModules(agentType);
|
|
310
339
|
// Set up ESP32 state provider before module init
|
|
@@ -318,7 +347,7 @@ export async function startSession(opts) {
|
|
|
318
347
|
if (lastStateEvent)
|
|
319
348
|
events.push(lastStateEvent);
|
|
320
349
|
events.push(core.buildUsage());
|
|
321
|
-
events.push(
|
|
350
|
+
events.push(buildDisplayStateEvent(core.displayMonitor.isDisplayOn()));
|
|
322
351
|
core.broadcastSessionsList().catch(() => { });
|
|
323
352
|
return events;
|
|
324
353
|
});
|
|
@@ -337,8 +366,12 @@ export async function startSession(opts) {
|
|
|
337
366
|
if (wifiConfig?.autoProvision) {
|
|
338
367
|
const lanIp = getLanIp();
|
|
339
368
|
onESP32Message((portPath, msg) => {
|
|
340
|
-
|
|
341
|
-
|
|
369
|
+
const shouldRefreshIps10Endpoint = msg.type === 'device_info' &&
|
|
370
|
+
msg.board === 'ips_10' &&
|
|
371
|
+
msg.wifiConnected &&
|
|
372
|
+
!msg.wifiRadioParked;
|
|
373
|
+
if (msg.type === 'device_info' && (!msg.wifiConnected || shouldRefreshIps10Endpoint)) {
|
|
374
|
+
const sent = sendWifiProvisionToAll({
|
|
342
375
|
type: 'wifi_provision',
|
|
343
376
|
ssid: wifiConfig.ssid,
|
|
344
377
|
password: wifiConfig.password,
|
|
@@ -346,7 +379,8 @@ export async function startSession(opts) {
|
|
|
346
379
|
bridgePort: port,
|
|
347
380
|
authToken: core.authToken,
|
|
348
381
|
});
|
|
349
|
-
|
|
382
|
+
if (sent > 0)
|
|
383
|
+
log(`WiFi provision sent to ${sent} ESP32 device(s) after ${portPath}`);
|
|
350
384
|
}
|
|
351
385
|
else if (msg.type === 'wifi_provision_ack') {
|
|
352
386
|
log(msg.success ? `ESP32 WiFi connected: ${msg.ip} \u2713` : `ESP32 WiFi failed: ${msg.error || 'unknown'}`);
|
|
@@ -365,7 +399,11 @@ export async function startSession(opts) {
|
|
|
365
399
|
],
|
|
366
400
|
}));
|
|
367
401
|
// Pixoo live preview frame getter for GET /pixoo/frame
|
|
368
|
-
hookServer?.setPixooFrameGetter(() =>
|
|
402
|
+
hookServer?.setPixooFrameGetter((size, layout) =>
|
|
403
|
+
// The frame cache holds the standard terrarium, so render micro fresh.
|
|
404
|
+
layout === 'micro'
|
|
405
|
+
? renderPreviewFrame(size, 'micro')
|
|
406
|
+
: (getLastFrame(size) ?? renderPreviewFrame(size)));
|
|
369
407
|
// ===== Diagnostics =====
|
|
370
408
|
adapter.onDiag((tail) => createDiagDump(core.stateMachine, core.wsServer, journal, ptyRingBuffer, tail));
|
|
371
409
|
adapter.onRawData((data) => {
|
|
@@ -400,14 +438,17 @@ export async function startSession(opts) {
|
|
|
400
438
|
switch (evt.source) {
|
|
401
439
|
case 'hook':
|
|
402
440
|
journal.write('hook', 'hook', { event: evt.event, data: evt.data });
|
|
403
|
-
// APME ingestion via the shared TelemetrySpan envelope.
|
|
404
|
-
//
|
|
405
|
-
//
|
|
406
|
-
//
|
|
407
|
-
//
|
|
441
|
+
// APME ingestion via the shared TelemetrySpan envelope. Codex
|
|
442
|
+
// CLI sessions go through codexHookToSpans (codex_* event prefix);
|
|
443
|
+
// Claude Code goes through claudeHookToSpans. Both adapters detect
|
|
444
|
+
// `/clear` and emit a `task_boundary` span so there's no separate
|
|
445
|
+
// splitRun branch here.
|
|
408
446
|
if (apme) {
|
|
409
447
|
const ctx = makeApmeAdapterCtx(apme, core.sessionId, agentType);
|
|
410
|
-
|
|
448
|
+
const spans = agentType === 'codex-cli'
|
|
449
|
+
? codexHookToSpans(ctx, evt.event, evt.data ?? {})
|
|
450
|
+
: claudeHookToSpans(ctx, evt.event, evt.data ?? {});
|
|
451
|
+
for (const span of spans) {
|
|
411
452
|
apme.collector.ingestSpan(core.sessionId, span);
|
|
412
453
|
}
|
|
413
454
|
}
|
|
@@ -433,6 +474,9 @@ export async function startSession(opts) {
|
|
|
433
474
|
}
|
|
434
475
|
if (evt.event === 'Stop')
|
|
435
476
|
pendingPtyResponse = null; // Stop has cleaner response
|
|
477
|
+
// APME-off fallback: task rows from boundary hooks alone.
|
|
478
|
+
if (fallbackTasks)
|
|
479
|
+
fallbackTasks.ingestHook(core.sessionId, evt.event, evt.data ?? {});
|
|
436
480
|
if (evt.event === 'shutdown') {
|
|
437
481
|
shutdown();
|
|
438
482
|
return;
|
|
@@ -613,10 +657,15 @@ export async function startSession(opts) {
|
|
|
613
657
|
if (core.wsServer.getClientCount() > 0 && Date.now() - core.lastApiFetchTime > 10_000) {
|
|
614
658
|
core.fetchAndUpdateUsage().catch(() => { });
|
|
615
659
|
}
|
|
616
|
-
// Voice assistant: if processing a wake-word prompt, speak the response
|
|
660
|
+
// Voice assistant: if processing a wake-word prompt, speak the response.
|
|
661
|
+
// Prefer chat_response (the turn's primary completion row now that a
|
|
662
|
+
// paired chat_end is no longer emitted for turns that have response
|
|
663
|
+
// text); fall back to chat_end for response-less turns. Read detail
|
|
664
|
+
// (full markdown) first, then the raw snippet.
|
|
617
665
|
if (voiceAssistant?.getState() === 'processing') {
|
|
618
|
-
const lastEntry = core.bridgeTimeline.getLastEntry('
|
|
619
|
-
|
|
666
|
+
const lastEntry = core.bridgeTimeline.getLastEntry('chat_response')
|
|
667
|
+
?? core.bridgeTimeline.getLastEntry('chat_end');
|
|
668
|
+
const responseText = lastEntry?.detail ?? lastEntry?.raw;
|
|
620
669
|
if (responseText) {
|
|
621
670
|
voiceAssistant.handleResponse(responseText).catch((err) => {
|
|
622
671
|
debug('agentdeck', `Voice assistant TTS error: ${err}`);
|
|
@@ -653,6 +702,7 @@ export async function startSession(opts) {
|
|
|
653
702
|
}
|
|
654
703
|
core.broadcast({
|
|
655
704
|
type: 'prompt_options',
|
|
705
|
+
sessionId: core.sessionId,
|
|
656
706
|
promptType,
|
|
657
707
|
question: snapshot.question ?? undefined,
|
|
658
708
|
options: snapshot.options,
|
|
@@ -752,11 +802,17 @@ export async function startSession(opts) {
|
|
|
752
802
|
});
|
|
753
803
|
// Deck slot map relay
|
|
754
804
|
core.wsServer.onRawMessage((msg, sender) => {
|
|
805
|
+
if (msg.type === 'device_info') {
|
|
806
|
+
core.wsServer.markEsp32Client(sender);
|
|
807
|
+
return false;
|
|
808
|
+
}
|
|
755
809
|
if (msg.type === 'deck_slot_map') {
|
|
756
810
|
cachedSlotMap = msg;
|
|
757
811
|
core.wsServer.broadcastExcept(cachedSlotMap, sender);
|
|
758
812
|
broadcastSse(cachedSlotMap);
|
|
759
813
|
core.broadcast(computeButtonState());
|
|
814
|
+
// Re-broadcast sessions_list so slot buttons populate after plugin startup race
|
|
815
|
+
core.broadcastSessionsList().catch(() => { });
|
|
760
816
|
return true;
|
|
761
817
|
}
|
|
762
818
|
return false;
|
|
@@ -809,6 +865,7 @@ export async function startSession(opts) {
|
|
|
809
865
|
}
|
|
810
866
|
extraEvents.push({
|
|
811
867
|
type: 'prompt_options',
|
|
868
|
+
sessionId: core.sessionId,
|
|
812
869
|
promptType: initPromptType,
|
|
813
870
|
question: snapshot.question ?? undefined,
|
|
814
871
|
options: snapshot.options,
|
|
@@ -843,20 +900,12 @@ export async function startSession(opts) {
|
|
|
843
900
|
core.startGatewayProbe(800);
|
|
844
901
|
core.startGatewayHealthCheck();
|
|
845
902
|
core.startSessionsListPolling();
|
|
846
|
-
// Inject virtual OpenClaw session
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
return [...sessions, {
|
|
853
|
-
id: 'openclaw-gateway',
|
|
854
|
-
port: 18789,
|
|
855
|
-
projectName: 'OpenClaw',
|
|
856
|
-
agentType: 'openclaw',
|
|
857
|
-
alive: true,
|
|
858
|
-
}];
|
|
859
|
-
});
|
|
903
|
+
// Inject virtual OpenClaw session only after Gateway authentication succeeds
|
|
904
|
+
// (gatewayConnected). Reachability alone (cachedGatewayAvailable) is a
|
|
905
|
+
// topology signal, not proof commands can route — gating on it kept a phantom
|
|
906
|
+
// OpenClaw session alive whenever anything held port 18789 open. Shared
|
|
907
|
+
// injector with daemon-server.ts; mirror of Swift buildSessionsListEvent.
|
|
908
|
+
core.setSessionsEnricher((sessions) => injectOpenClawSession(sessions, { gatewayConnected: core.cachedGatewayConnected }));
|
|
860
909
|
// ===== Encoder state computation =====
|
|
861
910
|
function computeEncoderState() {
|
|
862
911
|
const snapshot = core.stateMachine.getSnapshot();
|
|
@@ -1133,110 +1182,60 @@ export async function startSession(opts) {
|
|
|
1133
1182
|
core.shutdown();
|
|
1134
1183
|
}
|
|
1135
1184
|
}
|
|
1136
|
-
// Mid-session classify + turn-level eval enqueue.
|
|
1137
|
-
// Shared between Claude spinner_stop, OpenClaw/OpenCode chat_response, and Codex spinner_stop
|
|
1138
|
-
// so all agents get the same turns.task_category stamping and non-code turn_judge evals.
|
|
1139
|
-
async function classifyAndEnqueueTurn(apme, sid) {
|
|
1140
|
-
const turnId = apme.collector.getActiveTurnId(sid);
|
|
1141
|
-
const runId = apme.collector.getRunId(sid);
|
|
1142
|
-
if (!turnId || !runId)
|
|
1143
|
-
return;
|
|
1144
|
-
const run = apme.store.getRun(runId);
|
|
1145
|
-
if (!run)
|
|
1146
|
-
return;
|
|
1147
|
-
let category = run.taskCategory ?? null;
|
|
1148
|
-
if (!category) {
|
|
1149
|
-
try {
|
|
1150
|
-
const { classifyRun } = await import('./apme/classifier.js');
|
|
1151
|
-
const { category: c, signals } = classifyRun(apme.store, run.id);
|
|
1152
|
-
if (c && c !== 'unknown') {
|
|
1153
|
-
category = c;
|
|
1154
|
-
apme.store.updateRun(run.id, {
|
|
1155
|
-
taskCategory: c,
|
|
1156
|
-
taskSignals: JSON.stringify(signals),
|
|
1157
|
-
taskCategorySource: 'rule',
|
|
1158
|
-
});
|
|
1159
|
-
}
|
|
1160
|
-
}
|
|
1161
|
-
catch (err) {
|
|
1162
|
-
debug('APME', `mid-session classify failed: ${String(err)}`);
|
|
1163
|
-
}
|
|
1164
|
-
}
|
|
1165
|
-
if (category) {
|
|
1166
|
-
try {
|
|
1167
|
-
apme.store.updateTurn(turnId, { taskCategory: category });
|
|
1168
|
-
}
|
|
1169
|
-
catch { /* ignore */ }
|
|
1170
|
-
}
|
|
1171
|
-
const NON_CODE = new Set(['conversation', 'planning', 'research', 'review']);
|
|
1172
|
-
if (category && NON_CODE.has(category)) {
|
|
1173
|
-
apme.runner.enqueueTurn({ runId: run.id, turnId, category });
|
|
1174
|
-
}
|
|
1175
|
-
}
|
|
1176
1185
|
// ===== Non-Claude agent APME wiring =====
|
|
1177
1186
|
// For OpenCode, Codex, OpenClaw: intercepts adapter timeline events to create
|
|
1178
1187
|
// APME turns with prompts and responses. Claude Code uses hooks instead.
|
|
1179
1188
|
function wireAgentApme(adapter, agentType, apme, core, ptyRingBuffer) {
|
|
1180
1189
|
const sid = core.sessionId;
|
|
1190
|
+
// Codex turn boundaries (hook-primary, PTY-fallback) live in their own
|
|
1191
|
+
// module. The class encapsulates the seven-state-variable PTY-only
|
|
1192
|
+
// machine plus the hook-fresh shortcut so non-codex sessions allocate
|
|
1193
|
+
// nothing here.
|
|
1194
|
+
const codexManager = agentType === 'codex-cli'
|
|
1195
|
+
? new CodexTurnManager(core, apme, ptyRingBuffer, sid, agentType)
|
|
1196
|
+
: null;
|
|
1181
1197
|
adapter.on('event', (evt) => {
|
|
1182
1198
|
// ── Timeline events (OpenCode / OpenClaw) ──
|
|
1183
1199
|
// Both adapters emit { source: 'timeline', entry: TimelineEntry }.
|
|
1184
1200
|
// The timeline adapter normalizes them to AgentDeck telemetry spans.
|
|
1185
1201
|
if (evt.source === 'timeline' && evt.entry) {
|
|
1186
1202
|
const entry = evt.entry;
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1203
|
+
// Upserts refine an already-ingested row (chat_start topic hint, async
|
|
1204
|
+
// LLM summary) — converting them to spans again would open a phantom
|
|
1205
|
+
// turn or overwrite the captured response with a summary label.
|
|
1206
|
+
if (evt.upsert)
|
|
1207
|
+
return;
|
|
1208
|
+
// Adapters bound to APME directly (OpenCode via setApmeSession) ingest
|
|
1209
|
+
// richer spans from their native event stream; converting their
|
|
1210
|
+
// timeline rows as well double-counted every turn and tool (the tool
|
|
1211
|
+
// sample dedupCore is counter-based, so storage-time dedup can't
|
|
1212
|
+
// collapse the second copy). Timeline conversion is the fallback for
|
|
1213
|
+
// sessions without a direct binding.
|
|
1214
|
+
const directApme = adapter
|
|
1215
|
+
.hasDirectApmeIngestion?.() === true;
|
|
1216
|
+
if (!directApme) {
|
|
1217
|
+
const ctx = makeApmeAdapterCtx(apme, sid, agentType);
|
|
1218
|
+
for (const span of timelineEntryToSpans(ctx, entry)) {
|
|
1219
|
+
apme.collector.ingestSpan(sid, span);
|
|
1220
|
+
}
|
|
1190
1221
|
}
|
|
1191
|
-
// Mid-session classification still runs once we've captured a response
|
|
1222
|
+
// Mid-session classification still runs once we've captured a response
|
|
1223
|
+
// (both ingestion paths write the turn response before this fires).
|
|
1192
1224
|
if (entry.type === 'chat_response') {
|
|
1193
1225
|
void classifyAndEnqueueTurn(apme, sid);
|
|
1194
1226
|
}
|
|
1195
1227
|
}
|
|
1196
|
-
// ── Codex: PTY
|
|
1197
|
-
if (
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
// PTY-derived prompt = synthetic turn_start span. We construct it
|
|
1203
|
-
// inline rather than reusing claudeHookToSpans because the source
|
|
1204
|
-
// is a parser event, not a hook payload.
|
|
1205
|
-
const span = {
|
|
1206
|
-
traceId: ctx.traceId,
|
|
1207
|
-
spanId: randomUUID(),
|
|
1208
|
-
parentSpanId: ctx.activeTurnId,
|
|
1209
|
-
name: spanNameForKind('turn_start'),
|
|
1210
|
-
kind: 'turn_start',
|
|
1211
|
-
ts: Date.now(),
|
|
1212
|
-
attributes: {
|
|
1213
|
-
'agentdeck.agent_type': ctx.agentType,
|
|
1214
|
-
'agentdeck.prompt_text': text,
|
|
1215
|
-
...(ctx.cwd ? { 'agentdeck.cwd': ctx.cwd } : {}),
|
|
1216
|
-
},
|
|
1217
|
-
};
|
|
1218
|
-
apme.collector.ingestSpan(sid, span);
|
|
1219
|
-
}
|
|
1220
|
-
}
|
|
1221
|
-
if (evt.event === 'spinner_stop') {
|
|
1222
|
-
setTimeout(() => {
|
|
1223
|
-
const tail = ptyRingBuffer.getTail(5000);
|
|
1224
|
-
const lines = tail.split('\n').map(l => l.trim()).filter(Boolean);
|
|
1225
|
-
// Filter out spinner/UI artifacts from tail (Codex PTY output)
|
|
1226
|
-
const clean = lines.filter(l => !/^[✢✳✶✻✽⏸⏵❯─>]/.test(l) &&
|
|
1227
|
-
!/planmode|plan\s*mode|shift\+tab|accept\s*edits/i.test(l) &&
|
|
1228
|
-
!/\?\s*for\s*shortcuts/.test(l));
|
|
1229
|
-
const response = clean.slice(-5).join('\n');
|
|
1230
|
-
if (response.length > 2) {
|
|
1231
|
-
const span = claudePtyResponseToSpan(ctx, response);
|
|
1232
|
-
if (span)
|
|
1233
|
-
apme.collector.ingestSpan(sid, span);
|
|
1234
|
-
void classifyAndEnqueueTurn(apme, sid);
|
|
1235
|
-
}
|
|
1236
|
-
}, 500);
|
|
1237
|
-
}
|
|
1228
|
+
// ── Codex: hook (primary) + PTY-parser fallback ──
|
|
1229
|
+
if (codexManager) {
|
|
1230
|
+
if (evt.source === 'hook')
|
|
1231
|
+
codexManager.onHookEvent(evt);
|
|
1232
|
+
else if (evt.source === 'parser')
|
|
1233
|
+
codexManager.onParserEvent(evt);
|
|
1238
1234
|
}
|
|
1239
1235
|
});
|
|
1236
|
+
if (codexManager) {
|
|
1237
|
+
core.onShutdown(() => codexManager.cleanup());
|
|
1238
|
+
}
|
|
1240
1239
|
}
|
|
1241
1240
|
/** Build the AdapterContext used by every APME ingestion adapter. The
|
|
1242
1241
|
* trace id mirrors the active run id so future OTLP exports tie spans
|
|
@@ -1251,6 +1250,9 @@ function makeApmeAdapterCtx(apme, sid, agentType) {
|
|
|
1251
1250
|
activeTurnId: apme.collector.getActiveTurnId(sid) ?? undefined,
|
|
1252
1251
|
};
|
|
1253
1252
|
}
|
|
1253
|
+
function isClaudeTaskNotificationPrompt(text) {
|
|
1254
|
+
return text.trim().toLowerCase().startsWith('<task-notification>');
|
|
1255
|
+
}
|
|
1254
1256
|
// ===== Claude Code timeline wiring =====
|
|
1255
1257
|
function wireClaudeCodeTimeline(adapter, core, journal, ptyRingBuffer) {
|
|
1256
1258
|
let ccChatStart = null;
|
|
@@ -1266,6 +1268,10 @@ function wireClaudeCodeTimeline(adapter, core, journal, ptyRingBuffer) {
|
|
|
1266
1268
|
ccPendingChatStartTimer = null;
|
|
1267
1269
|
}
|
|
1268
1270
|
ccPendingChatStart = false;
|
|
1271
|
+
if (isClaudeTaskNotificationPrompt(text)) {
|
|
1272
|
+
ccLastPromptText = null;
|
|
1273
|
+
return;
|
|
1274
|
+
}
|
|
1269
1275
|
ccLastPromptText = text || null;
|
|
1270
1276
|
const snippet = text.length > 500 ? text.slice(0, 497) + '...' : text;
|
|
1271
1277
|
const detail = text.length > 100 ? (text.length > 1000 ? text.slice(0, 1000) + '...' : text) : undefined;
|
|
@@ -1274,11 +1280,16 @@ function wireClaudeCodeTimeline(adapter, core, journal, ptyRingBuffer) {
|
|
|
1274
1280
|
const proj = core.stateMachine.getSnapshot().projectName;
|
|
1275
1281
|
return proj ? `Prompt \u00B7 ${proj}` : 'Prompt sent';
|
|
1276
1282
|
})();
|
|
1283
|
+
// taskId/runId are filled in by BridgeCore's timeline attributor
|
|
1284
|
+
// (wireTimeline → setAttributor) from the active APME task for this
|
|
1285
|
+
// session, so managed-session chat rows nest under their task header
|
|
1286
|
+
// without threading the id through here.
|
|
1277
1287
|
core.bridgeTimeline.addEntry({
|
|
1278
1288
|
ts: ccChatStart ?? Date.now(), type: 'chat_start',
|
|
1279
1289
|
raw: snippet || fallbackRaw,
|
|
1280
1290
|
...(detail ? { detail } : {}),
|
|
1281
1291
|
agentType: 'claude-code',
|
|
1292
|
+
startedAt: ccChatStart ?? Date.now(),
|
|
1282
1293
|
});
|
|
1283
1294
|
};
|
|
1284
1295
|
/** Extract response text from PTY ringbuffer after ⏺ marker (same pattern as APME) */
|
|
@@ -1306,59 +1317,86 @@ function wireClaudeCodeTimeline(adapter, core, journal, ptyRingBuffer) {
|
|
|
1306
1317
|
}
|
|
1307
1318
|
return clean.join('\n').trim();
|
|
1308
1319
|
};
|
|
1309
|
-
/**
|
|
1320
|
+
/**
|
|
1321
|
+
* Emit a single Claude turn-close row (shared by Stop hook and PTY fallback):
|
|
1322
|
+
* a `chat_response` when there is meaningful response text, otherwise a
|
|
1323
|
+
* `chat_end`. The two are mutually exclusive so a turn never produces both —
|
|
1324
|
+
* the paired dimmed `chat_end` used to fragment every turn into three rows on
|
|
1325
|
+
* the flat surfaces (plugin / TUI / timeline.json).
|
|
1326
|
+
*/
|
|
1310
1327
|
const emitCompletion = (responseText, duration, toolSummary) => {
|
|
1311
1328
|
const now = Date.now();
|
|
1329
|
+
const startedAt = ccChatStart ?? undefined;
|
|
1312
1330
|
// Change 5: emit chat_response if meaningful response text exists
|
|
1313
1331
|
if (responseText.length > 20) {
|
|
1314
1332
|
const respRaw = responseText.length > 200 ? responseText.slice(0, 197) + '...' : responseText;
|
|
1315
1333
|
core.bridgeTimeline.addEntry({
|
|
1316
1334
|
ts: now - 1, type: 'chat_response',
|
|
1317
1335
|
raw: cleanRawText(respRaw),
|
|
1318
|
-
|
|
1336
|
+
// Preserve markdown so the dashboard renderer can apply heading /
|
|
1337
|
+
// table / bold / code styles. cleanDetailText would have stripped
|
|
1338
|
+
// all of that before it ever reached the client.
|
|
1339
|
+
detail: prepareMarkdownDetail(responseText.slice(0, 3000)) || undefined,
|
|
1319
1340
|
agentType: 'claude-code',
|
|
1341
|
+
...(startedAt ? { startedAt } : {}),
|
|
1342
|
+
endedAt: now,
|
|
1320
1343
|
});
|
|
1321
1344
|
}
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1345
|
+
// Pick a summary label.
|
|
1346
|
+
// - 'topic' kind from response \u2192 real heuristic content
|
|
1347
|
+
// - 'topic' kind from prompt \u2192 still meaningful, mark as heuristic
|
|
1348
|
+
// - 'fallback' kind (politeness-only) or prompt snippet \u2192 mark as 'none'
|
|
1349
|
+
// (clients use this to decide whether the detail pane is worth showing)
|
|
1350
|
+
// - literal "Completed" only when prompt is also empty
|
|
1351
|
+
const respHint = responseText ? extractTopicHintWithKind(responseText) : { hint: null, kind: null };
|
|
1352
|
+
const promptHint = ccLastPromptText ? extractTopicHintWithKind(ccLastPromptText) : { hint: null, kind: null };
|
|
1353
|
+
let completedLabel;
|
|
1354
|
+
let summaryKind;
|
|
1355
|
+
if (respHint.kind === 'topic' && respHint.hint) {
|
|
1356
|
+
completedLabel = respHint.hint;
|
|
1357
|
+
summaryKind = 'heuristic';
|
|
1358
|
+
}
|
|
1359
|
+
else if (promptHint.kind === 'topic' && promptHint.hint) {
|
|
1360
|
+
completedLabel = promptHint.hint;
|
|
1361
|
+
summaryKind = 'heuristic';
|
|
1362
|
+
}
|
|
1363
|
+
else if (respHint.hint || promptHint.hint) {
|
|
1364
|
+
completedLabel = (respHint.hint || promptHint.hint);
|
|
1365
|
+
summaryKind = 'none';
|
|
1366
|
+
}
|
|
1367
|
+
else {
|
|
1368
|
+
const fallback = promptSnippetFallback(ccLastPromptText, 60);
|
|
1369
|
+
completedLabel = fallback ?? 'Completed';
|
|
1370
|
+
summaryKind = 'none';
|
|
1371
|
+
}
|
|
1325
1372
|
let summary = duration != null ? `${completedLabel} \u00B7 ${duration}s` : completedLabel;
|
|
1326
1373
|
if (toolSummary)
|
|
1327
1374
|
summary += ` \u00B7 ${toolSummary}`;
|
|
1328
1375
|
const chatEndDetail = responseText
|
|
1329
|
-
? (() => { const c =
|
|
1376
|
+
? (() => { const c = prepareMarkdownDetail(responseText); return c ? (c.length > 1000 ? c.slice(0, 1000) + '...' : c) : undefined; })()
|
|
1330
1377
|
: ccLastPromptText
|
|
1331
1378
|
? `Prompt: ${ccLastPromptText.length > 200 ? ccLastPromptText.slice(0, 200) + '...' : ccLastPromptText}`
|
|
1332
1379
|
: undefined;
|
|
1333
1380
|
const chatEndTs = now;
|
|
1334
1381
|
ccChatStart = null;
|
|
1335
1382
|
ccLastPromptText = null;
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
//
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
debug('timeline', `CC LLM summary: ${llmSummary}`);
|
|
1354
|
-
core.bridgeTimeline.upsertEntry({
|
|
1355
|
-
ts: chatEndTs, type: 'chat_end',
|
|
1356
|
-
raw: enrichedParts.join(' \u00B7 '),
|
|
1357
|
-
...(savedDetail ? { detail: savedDetail } : {}),
|
|
1358
|
-
agentType: 'claude-code',
|
|
1359
|
-
});
|
|
1360
|
-
}
|
|
1361
|
-
}).catch(() => { });
|
|
1383
|
+
// Only emit a chat_end turn-close row when there is NO chat_response to act
|
|
1384
|
+
// as the turn's completion row (a tool-only turn, or a Stop hook with no
|
|
1385
|
+
// last_assistant_message). When a chat_response exists it already marks the
|
|
1386
|
+
// turn complete; the extra dimmed "Completed · Ns · topic" row is redundant
|
|
1387
|
+
// metadata — the dashboard already drops it on render — and on the flat
|
|
1388
|
+
// surfaces (Stream Deck plugin / TUI / persisted timeline.json) it
|
|
1389
|
+
// fragmented every Claude turn into three rows. Keeping chat_start +
|
|
1390
|
+
// chat_response matches the cleaner OpenClaw turn shape.
|
|
1391
|
+
if (responseText.length <= 20) {
|
|
1392
|
+
core.bridgeTimeline.addEntry({
|
|
1393
|
+
ts: chatEndTs, type: 'chat_end', raw: summary,
|
|
1394
|
+
...(chatEndDetail ? { detail: chatEndDetail } : {}),
|
|
1395
|
+
agentType: 'claude-code',
|
|
1396
|
+
...(startedAt ? { startedAt } : {}),
|
|
1397
|
+
endedAt: chatEndTs,
|
|
1398
|
+
summaryKind,
|
|
1399
|
+
});
|
|
1362
1400
|
}
|
|
1363
1401
|
};
|
|
1364
1402
|
// Change 4: late upsert — user_prompt metadata arriving after 500ms timer
|