@agentdeck/bridge 0.1.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/dist/adapters/claude-code.d.ts +11 -27
- package/dist/adapters/claude-code.d.ts.map +1 -1
- package/dist/adapters/claude-code.js +29 -123
- package/dist/adapters/claude-code.js.map +1 -1
- package/dist/adapters/codex-cli.d.ts +21 -0
- package/dist/adapters/codex-cli.d.ts.map +1 -0
- package/dist/adapters/codex-cli.js +53 -0
- package/dist/adapters/codex-cli.js.map +1 -0
- package/dist/adapters/index.d.ts +4 -0
- package/dist/adapters/index.d.ts.map +1 -1
- package/dist/adapters/index.js +13 -0
- package/dist/adapters/index.js.map +1 -1
- package/dist/adapters/monitor.d.ts +34 -0
- package/dist/adapters/monitor.d.ts.map +1 -0
- package/dist/adapters/monitor.js +86 -0
- package/dist/adapters/monitor.js.map +1 -0
- package/dist/adapters/openclaw.d.ts +36 -2
- package/dist/adapters/openclaw.d.ts.map +1 -1
- package/dist/adapters/openclaw.js +329 -59
- package/dist/adapters/openclaw.js.map +1 -1
- package/dist/adapters/opencode-adapter.d.ts +48 -0
- package/dist/adapters/opencode-adapter.d.ts.map +1 -0
- package/dist/adapters/opencode-adapter.js +345 -0
- package/dist/adapters/opencode-adapter.js.map +1 -0
- package/dist/adapters/pty-adapter.d.ts +56 -0
- package/dist/adapters/pty-adapter.d.ts.map +1 -0
- package/dist/adapters/pty-adapter.js +143 -0
- package/dist/adapters/pty-adapter.js.map +1 -0
- package/dist/adb-reverse.d.ts +25 -0
- package/dist/adb-reverse.d.ts.map +1 -0
- package/dist/adb-reverse.js +129 -0
- package/dist/adb-reverse.js.map +1 -0
- package/dist/antigravity-local.d.ts +7 -0
- package/dist/antigravity-local.d.ts.map +1 -0
- package/dist/antigravity-local.js +153 -0
- package/dist/antigravity-local.js.map +1 -0
- package/dist/apme/adapters/claude-hook.d.ts +15 -0
- package/dist/apme/adapters/claude-hook.d.ts.map +1 -0
- package/dist/apme/adapters/claude-hook.js +85 -0
- package/dist/apme/adapters/claude-hook.js.map +1 -0
- package/dist/apme/adapters/claude-pty.d.ts +28 -0
- package/dist/apme/adapters/claude-pty.d.ts.map +1 -0
- package/dist/apme/adapters/claude-pty.js +88 -0
- package/dist/apme/adapters/claude-pty.js.map +1 -0
- package/dist/apme/adapters/timeline.d.ts +16 -0
- package/dist/apme/adapters/timeline.d.ts.map +1 -0
- package/dist/apme/adapters/timeline.js +66 -0
- package/dist/apme/adapters/timeline.js.map +1 -0
- package/dist/apme/classifier.d.ts +53 -0
- package/dist/apme/classifier.d.ts.map +1 -0
- package/dist/apme/classifier.js +266 -0
- package/dist/apme/classifier.js.map +1 -0
- package/dist/apme/claude-transcript-reader.d.ts +38 -0
- package/dist/apme/claude-transcript-reader.d.ts.map +1 -0
- package/dist/apme/claude-transcript-reader.js +127 -0
- package/dist/apme/claude-transcript-reader.js.map +1 -0
- package/dist/apme/collector.d.ts +108 -0
- package/dist/apme/collector.d.ts.map +1 -0
- package/dist/apme/collector.js +659 -0
- package/dist/apme/collector.js.map +1 -0
- package/dist/apme/dashboard-html.d.ts +9 -0
- package/dist/apme/dashboard-html.d.ts.map +1 -0
- package/dist/apme/dashboard-html.js +416 -0
- package/dist/apme/dashboard-html.js.map +1 -0
- package/dist/apme/http.d.ts +19 -0
- package/dist/apme/http.d.ts.map +1 -0
- package/dist/apme/http.js +210 -0
- package/dist/apme/http.js.map +1 -0
- package/dist/apme/hw-sampler.d.ts +30 -0
- package/dist/apme/hw-sampler.d.ts.map +1 -0
- package/dist/apme/hw-sampler.js +106 -0
- package/dist/apme/hw-sampler.js.map +1 -0
- package/dist/apme/index.d.ts +43 -0
- package/dist/apme/index.d.ts.map +1 -0
- package/dist/apme/index.js +75 -0
- package/dist/apme/index.js.map +1 -0
- package/dist/apme/outcome.d.ts +48 -0
- package/dist/apme/outcome.d.ts.map +1 -0
- package/dist/apme/outcome.js +232 -0
- package/dist/apme/outcome.js.map +1 -0
- package/dist/apme/recommend.d.ts +32 -0
- package/dist/apme/recommend.d.ts.map +1 -0
- package/dist/apme/recommend.js +41 -0
- package/dist/apme/recommend.js.map +1 -0
- package/dist/apme/runner.d.ts +94 -0
- package/dist/apme/runner.d.ts.map +1 -0
- package/dist/apme/runner.js +812 -0
- package/dist/apme/runner.js.map +1 -0
- package/dist/apme/settings.d.ts +65 -0
- package/dist/apme/settings.d.ts.map +1 -0
- package/dist/apme/settings.js +97 -0
- package/dist/apme/settings.js.map +1 -0
- package/dist/apme/store.d.ts +99 -0
- package/dist/apme/store.d.ts.map +1 -0
- package/dist/apme/store.js +911 -0
- package/dist/apme/store.js.map +1 -0
- package/dist/apme/tuner.d.ts +64 -0
- package/dist/apme/tuner.d.ts.map +1 -0
- package/dist/apme/tuner.js +297 -0
- package/dist/apme/tuner.js.map +1 -0
- package/dist/apme/types.d.ts +11 -0
- package/dist/apme/types.d.ts.map +1 -0
- package/dist/apme/types.js +10 -0
- package/dist/apme/types.js.map +1 -0
- package/dist/auth.d.ts +1 -1
- package/dist/auth.d.ts.map +1 -1
- package/dist/auth.js +15 -5
- package/dist/auth.js.map +1 -1
- package/dist/bridge-core.d.ts +162 -0
- package/dist/bridge-core.d.ts.map +1 -0
- package/dist/bridge-core.js +627 -0
- package/dist/bridge-core.js.map +1 -0
- package/dist/check-deps.d.ts +3 -1
- package/dist/check-deps.d.ts.map +1 -1
- package/dist/check-deps.js +34 -13
- package/dist/check-deps.js.map +1 -1
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +1235 -0
- package/dist/cli.js.map +1 -0
- package/dist/codex-auth.d.ts +10 -0
- package/dist/codex-auth.d.ts.map +1 -0
- package/dist/codex-auth.js +63 -0
- package/dist/codex-auth.js.map +1 -0
- package/dist/codex-output-parser.d.ts +21 -0
- package/dist/codex-output-parser.d.ts.map +1 -0
- package/dist/codex-output-parser.js +253 -0
- package/dist/codex-output-parser.js.map +1 -0
- package/dist/d200h/hid-protocol.d.ts +62 -0
- package/dist/d200h/hid-protocol.d.ts.map +1 -0
- package/dist/d200h/hid-protocol.js +124 -0
- package/dist/d200h/hid-protocol.js.map +1 -0
- package/dist/d200h/image-renderer.d.ts +36 -0
- package/dist/d200h/image-renderer.d.ts.map +1 -0
- package/dist/d200h/image-renderer.js +487 -0
- package/dist/d200h/image-renderer.js.map +1 -0
- package/dist/daemon-server.d.ts +19 -0
- package/dist/daemon-server.d.ts.map +1 -0
- package/dist/daemon-server.js +1168 -0
- package/dist/daemon-server.js.map +1 -0
- package/dist/daemon-ws-client.d.ts +82 -0
- package/dist/daemon-ws-client.d.ts.map +1 -0
- package/dist/daemon-ws-client.js +179 -0
- package/dist/daemon-ws-client.js.map +1 -0
- package/dist/daemon.d.ts +10 -0
- package/dist/daemon.d.ts.map +1 -0
- package/dist/daemon.js +56 -0
- package/dist/daemon.js.map +1 -0
- package/dist/display-monitor.d.ts +25 -0
- package/dist/display-monitor.d.ts.map +1 -0
- package/dist/display-monitor.js +143 -0
- package/dist/display-monitor.js.map +1 -0
- package/dist/esp32-serial.d.ts +112 -0
- package/dist/esp32-serial.d.ts.map +1 -0
- package/dist/esp32-serial.js +502 -0
- package/dist/esp32-serial.js.map +1 -0
- package/dist/gateway-probe.d.ts +12 -0
- package/dist/gateway-probe.d.ts.map +1 -0
- package/dist/gateway-probe.js +39 -0
- package/dist/gateway-probe.js.map +1 -0
- package/dist/hook-migration.d.ts +2 -0
- package/dist/hook-migration.d.ts.map +1 -0
- package/dist/hook-migration.js +104 -0
- package/dist/hook-migration.js.map +1 -0
- package/dist/hook-server.d.ts +29 -0
- package/dist/hook-server.d.ts.map +1 -1
- package/dist/hook-server.js +366 -8
- package/dist/hook-server.js.map +1 -1
- package/dist/index.d.ts +20 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1304 -562
- package/dist/index.js.map +1 -1
- package/dist/log-stream.d.ts +26 -0
- package/dist/log-stream.d.ts.map +1 -0
- package/dist/log-stream.js +111 -0
- package/dist/log-stream.js.map +1 -0
- package/dist/logger.d.ts +9 -2
- package/dist/logger.d.ts.map +1 -1
- package/dist/logger.js +36 -5
- package/dist/logger.js.map +1 -1
- package/dist/mdns.d.ts +15 -1
- package/dist/mdns.d.ts.map +1 -1
- package/dist/mdns.js +143 -28
- package/dist/mdns.js.map +1 -1
- package/dist/mlx-probe.d.ts +14 -0
- package/dist/mlx-probe.d.ts.map +1 -0
- package/dist/mlx-probe.js +44 -0
- package/dist/mlx-probe.js.map +1 -0
- package/dist/model-catalog.d.ts +5 -3
- package/dist/model-catalog.d.ts.map +1 -1
- package/dist/model-catalog.js +45 -29
- package/dist/model-catalog.js.map +1 -1
- package/dist/modules/adb-module.d.ts +14 -0
- package/dist/modules/adb-module.d.ts.map +1 -0
- package/dist/modules/adb-module.js +36 -0
- package/dist/modules/adb-module.js.map +1 -0
- package/dist/modules/d200h-module.d.ts +43 -0
- package/dist/modules/d200h-module.d.ts.map +1 -0
- package/dist/modules/d200h-module.js +360 -0
- package/dist/modules/d200h-module.js.map +1 -0
- package/dist/modules/d200h-renderer.d.ts +7 -0
- package/dist/modules/d200h-renderer.d.ts.map +1 -0
- package/dist/modules/d200h-renderer.js +321 -0
- package/dist/modules/d200h-renderer.js.map +1 -0
- package/dist/modules/index.d.ts +23 -0
- package/dist/modules/index.d.ts.map +1 -0
- package/dist/modules/index.js +65 -0
- package/dist/modules/index.js.map +1 -0
- package/dist/modules/mdns-module.d.ts +12 -0
- package/dist/modules/mdns-module.d.ts.map +1 -0
- package/dist/modules/mdns-module.js +21 -0
- package/dist/modules/mdns-module.js.map +1 -0
- package/dist/modules/pixoo-module.d.ts +8 -0
- package/dist/modules/pixoo-module.d.ts.map +1 -0
- package/dist/modules/pixoo-module.js +24 -0
- package/dist/modules/pixoo-module.js.map +1 -0
- package/dist/modules/serial-module.d.ts +18 -0
- package/dist/modules/serial-module.d.ts.map +1 -0
- package/dist/modules/serial-module.js +47 -0
- package/dist/modules/serial-module.js.map +1 -0
- package/dist/modules/types.d.ts +39 -0
- package/dist/modules/types.d.ts.map +1 -0
- package/dist/modules/types.js +2 -0
- package/dist/modules/types.js.map +1 -0
- package/dist/ollama-probe.d.ts +13 -0
- package/dist/ollama-probe.d.ts.map +1 -0
- package/dist/ollama-probe.js +46 -0
- package/dist/ollama-probe.js.map +1 -0
- package/dist/opencode-client.d.ts +126 -0
- package/dist/opencode-client.d.ts.map +1 -0
- package/dist/opencode-client.js +181 -0
- package/dist/opencode-client.js.map +1 -0
- package/dist/output-parser.d.ts +3 -0
- package/dist/output-parser.d.ts.map +1 -1
- package/dist/output-parser.js +29 -3
- package/dist/output-parser.js.map +1 -1
- package/dist/passive-observer.d.ts +38 -0
- package/dist/passive-observer.d.ts.map +1 -0
- package/dist/passive-observer.js +632 -0
- package/dist/passive-observer.js.map +1 -0
- package/dist/pixoo/pixoo-bridge.d.ts +50 -0
- package/dist/pixoo/pixoo-bridge.d.ts.map +1 -0
- package/dist/pixoo/pixoo-bridge.js +280 -0
- package/dist/pixoo/pixoo-bridge.js.map +1 -0
- package/dist/pixoo/pixoo-camera.d.ts +80 -0
- package/dist/pixoo/pixoo-camera.d.ts.map +1 -0
- package/dist/pixoo/pixoo-camera.js +271 -0
- package/dist/pixoo/pixoo-camera.js.map +1 -0
- package/dist/pixoo/pixoo-client.d.ts +67 -0
- package/dist/pixoo/pixoo-client.d.ts.map +1 -0
- package/dist/pixoo/pixoo-client.js +335 -0
- package/dist/pixoo/pixoo-client.js.map +1 -0
- package/dist/pixoo/pixoo-font.d.ts +24 -0
- package/dist/pixoo/pixoo-font.d.ts.map +1 -0
- package/dist/pixoo/pixoo-font.js +121 -0
- package/dist/pixoo/pixoo-font.js.map +1 -0
- package/dist/pixoo/pixoo-renderer.d.ts +32 -0
- package/dist/pixoo/pixoo-renderer.d.ts.map +1 -0
- package/dist/pixoo/pixoo-renderer.js +696 -0
- package/dist/pixoo/pixoo-renderer.js.map +1 -0
- package/dist/pixoo/pixoo-settings.d.ts +10 -0
- package/dist/pixoo/pixoo-settings.d.ts.map +1 -0
- package/dist/pixoo/pixoo-settings.js +47 -0
- package/dist/pixoo/pixoo-settings.js.map +1 -0
- package/dist/pixoo/pixoo-sprites.d.ts +187 -0
- package/dist/pixoo/pixoo-sprites.d.ts.map +1 -0
- package/dist/pixoo/pixoo-sprites.js +926 -0
- package/dist/pixoo/pixoo-sprites.js.map +1 -0
- package/dist/pty-manager.d.ts +1 -1
- package/dist/pty-manager.d.ts.map +1 -1
- package/dist/pty-manager.js +36 -15
- package/dist/pty-manager.js.map +1 -1
- package/dist/session-aggregator.d.ts +41 -0
- package/dist/session-aggregator.d.ts.map +1 -0
- package/dist/session-aggregator.js +76 -0
- package/dist/session-aggregator.js.map +1 -0
- package/dist/session-focus-relay.d.ts +35 -0
- package/dist/session-focus-relay.d.ts.map +1 -0
- package/dist/session-focus-relay.js +127 -0
- package/dist/session-focus-relay.js.map +1 -0
- package/dist/session-registry.d.ts +88 -1
- package/dist/session-registry.d.ts.map +1 -1
- package/dist/session-registry.js +222 -15
- package/dist/session-registry.js.map +1 -1
- package/dist/session-timeline-relay.d.ts +27 -0
- package/dist/session-timeline-relay.d.ts.map +1 -0
- package/dist/session-timeline-relay.js +124 -0
- package/dist/session-timeline-relay.js.map +1 -0
- package/dist/state-machine.d.ts +1 -0
- package/dist/state-machine.d.ts.map +1 -1
- package/dist/state-machine.js +14 -0
- package/dist/state-machine.js.map +1 -1
- package/dist/terminal-status.d.ts +28 -0
- package/dist/terminal-status.d.ts.map +1 -0
- package/dist/terminal-status.js +152 -0
- package/dist/terminal-status.js.map +1 -0
- package/dist/timeline-store.d.ts +22 -0
- package/dist/timeline-store.d.ts.map +1 -0
- package/dist/timeline-store.js +79 -0
- package/dist/timeline-store.js.map +1 -0
- package/dist/timeline-summarizer.d.ts +14 -0
- package/dist/timeline-summarizer.d.ts.map +1 -0
- package/dist/timeline-summarizer.js +154 -0
- package/dist/timeline-summarizer.js.map +1 -0
- package/dist/tts.d.ts +25 -0
- package/dist/tts.d.ts.map +1 -0
- package/dist/tts.js +99 -0
- package/dist/tts.js.map +1 -0
- package/dist/tui/ansi.d.ts +92 -0
- package/dist/tui/ansi.d.ts.map +1 -0
- package/dist/tui/ansi.js +181 -0
- package/dist/tui/ansi.js.map +1 -0
- package/dist/tui/dashboard.d.ts +35 -0
- package/dist/tui/dashboard.d.ts.map +1 -0
- package/dist/tui/dashboard.js +436 -0
- package/dist/tui/dashboard.js.map +1 -0
- package/dist/tui/gauge.d.ts +15 -0
- package/dist/tui/gauge.d.ts.map +1 -0
- package/dist/tui/gauge.js +82 -0
- package/dist/tui/gauge.js.map +1 -0
- package/dist/tui/renderer.d.ts +15 -0
- package/dist/tui/renderer.d.ts.map +1 -0
- package/dist/tui/renderer.js +758 -0
- package/dist/tui/renderer.js.map +1 -0
- package/dist/tui/screen.d.ts +27 -0
- package/dist/tui/screen.d.ts.map +1 -0
- package/dist/tui/screen.js +109 -0
- package/dist/tui/screen.js.map +1 -0
- package/dist/tui/terrarium.d.ts +96 -0
- package/dist/tui/terrarium.d.ts.map +1 -0
- package/dist/tui/terrarium.js +912 -0
- package/dist/tui/terrarium.js.map +1 -0
- package/dist/types.d.ts +4 -2
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +3 -2
- package/dist/types.js.map +1 -1
- package/dist/usage-api.d.ts +9 -2
- package/dist/usage-api.d.ts.map +1 -1
- package/dist/usage-api.js +224 -42
- package/dist/usage-api.js.map +1 -1
- package/dist/usage-event.d.ts +12 -0
- package/dist/usage-event.d.ts.map +1 -0
- package/dist/usage-event.js +78 -0
- package/dist/usage-event.js.map +1 -0
- package/dist/usage-tracker.d.ts +4 -0
- package/dist/usage-tracker.d.ts.map +1 -1
- package/dist/usage-tracker.js +17 -0
- package/dist/usage-tracker.js.map +1 -1
- package/dist/utility-proxy.d.ts +30 -0
- package/dist/utility-proxy.d.ts.map +1 -0
- package/dist/utility-proxy.js +217 -0
- package/dist/utility-proxy.js.map +1 -0
- package/dist/utils/project-name.d.ts +22 -0
- package/dist/utils/project-name.d.ts.map +1 -0
- package/dist/utils/project-name.js +72 -0
- package/dist/utils/project-name.js.map +1 -0
- package/dist/version-check.d.ts +26 -0
- package/dist/version-check.d.ts.map +1 -0
- package/dist/version-check.js +225 -0
- package/dist/version-check.js.map +1 -0
- package/dist/voice-assistant.d.ts +63 -0
- package/dist/voice-assistant.d.ts.map +1 -0
- package/dist/voice-assistant.js +406 -0
- package/dist/voice-assistant.js.map +1 -0
- package/dist/voice.d.ts +2 -0
- package/dist/voice.d.ts.map +1 -1
- package/dist/voice.js +26 -1
- package/dist/voice.js.map +1 -1
- package/dist/wake-word.d.ts +35 -0
- package/dist/wake-word.d.ts.map +1 -0
- package/dist/wake-word.js +225 -0
- package/dist/wake-word.js.map +1 -0
- package/dist/whisper-server-manager.d.ts +1 -1
- package/dist/whisper-server-manager.js +1 -1
- package/dist/wifi-config.d.ts +24 -0
- package/dist/wifi-config.d.ts.map +1 -0
- package/dist/wifi-config.js +84 -0
- package/dist/wifi-config.js.map +1 -0
- package/dist/ws-server.d.ts +12 -0
- package/dist/ws-server.d.ts.map +1 -1
- package/dist/ws-server.js +81 -3
- package/dist/ws-server.js.map +1 -1
- package/package.json +21 -13
|
@@ -12,6 +12,11 @@ import type { AgentAdapter, AgentCapabilities, AdapterStartOptions, PluginComman
|
|
|
12
12
|
* - Has no terminal (PTY), mode switching, or diff review
|
|
13
13
|
* - Handles select_option/navigate_option/send_prompt directly via RPC
|
|
14
14
|
*/
|
|
15
|
+
export interface OpenClawAdapterOptions {
|
|
16
|
+
gatewayUrl?: string;
|
|
17
|
+
/** Set false to disable automatic reconnect (daemon manages lifecycle externally) */
|
|
18
|
+
autoReconnect?: boolean;
|
|
19
|
+
}
|
|
15
20
|
export declare class OpenClawAdapter extends EventEmitter implements AgentAdapter {
|
|
16
21
|
readonly capabilities: AgentCapabilities;
|
|
17
22
|
private gatewayUrl;
|
|
@@ -23,19 +28,31 @@ export declare class OpenClawAdapter extends EventEmitter implements AgentAdapte
|
|
|
23
28
|
private projectName;
|
|
24
29
|
private alive;
|
|
25
30
|
private shutdownRequested;
|
|
31
|
+
private externalHttpServer;
|
|
26
32
|
private diagHandler;
|
|
27
33
|
private rawDataCallback;
|
|
34
|
+
private autoReconnect;
|
|
28
35
|
private currentSessionKey;
|
|
29
36
|
private currentRunId;
|
|
30
37
|
private pendingApprovalId;
|
|
38
|
+
private chatStarted;
|
|
39
|
+
private chatStartTime;
|
|
40
|
+
private chatToolCount;
|
|
41
|
+
private chatToolNames;
|
|
42
|
+
private lastPrompt;
|
|
43
|
+
private accumulatedResponse;
|
|
44
|
+
private topicExtracted;
|
|
45
|
+
private chatIsAutomated;
|
|
31
46
|
private deviceIdentity;
|
|
32
47
|
private deviceAuthToken;
|
|
33
48
|
/** Reconnect delay (doubles on each failure, max 30s) */
|
|
34
49
|
private reconnectDelay;
|
|
35
50
|
private static readonly MAX_RECONNECT_DELAY;
|
|
36
51
|
private static readonly RPC_TIMEOUT;
|
|
37
|
-
constructor(
|
|
38
|
-
start(options: AdapterStartOptions
|
|
52
|
+
constructor(options?: string | OpenClawAdapterOptions);
|
|
53
|
+
start(options: AdapterStartOptions & {
|
|
54
|
+
externalServer?: Server;
|
|
55
|
+
}): Promise<void>;
|
|
39
56
|
handleCommand(cmd: PluginCommand): boolean;
|
|
40
57
|
writeInput(data: string): void;
|
|
41
58
|
isAlive(): boolean;
|
|
@@ -53,6 +70,12 @@ export declare class OpenClawAdapter extends EventEmitter implements AgentAdapte
|
|
|
53
70
|
private buildDeviceAuth;
|
|
54
71
|
private connectGateway;
|
|
55
72
|
private scheduleReconnect;
|
|
73
|
+
/**
|
|
74
|
+
* Typed RPC dispatch. `GatewayMethodMap` correlates the method name with
|
|
75
|
+
* its param shape and result shape (declared in `shared/gateway-protocol.ts`),
|
|
76
|
+
* so misuse — wrong params for a method, or calling an unknown method — is
|
|
77
|
+
* a compile error here rather than a runtime surprise.
|
|
78
|
+
*/
|
|
56
79
|
private rpcCall;
|
|
57
80
|
private handleGatewayMessage;
|
|
58
81
|
private handleGatewayEvent;
|
|
@@ -65,6 +88,17 @@ export declare class OpenClawAdapter extends EventEmitter implements AgentAdapte
|
|
|
65
88
|
private fetchSessions;
|
|
66
89
|
/** Fetch model catalog via CLI and emit events. Retries once on failure. */
|
|
67
90
|
private emitModelCatalog;
|
|
91
|
+
/**
|
|
92
|
+
* Extract text from Gateway chat message structure.
|
|
93
|
+
* Format: payload.message = { role, content: [{ type: "text", text: "..." }], timestamp }
|
|
94
|
+
*/
|
|
95
|
+
private extractMessageText;
|
|
96
|
+
/** Build tool count summary like "Read(3), Bash(2)" */
|
|
97
|
+
private buildToolSummary;
|
|
98
|
+
/** Emit a timeline event through the adapter event system */
|
|
99
|
+
private emitTimelineEntry;
|
|
100
|
+
/** Emit a timeline upsert (update existing entry with same ts+type, or add new) */
|
|
101
|
+
private emitTimelineUpsert;
|
|
68
102
|
private emitAdapterEvent;
|
|
69
103
|
}
|
|
70
104
|
//# sourceMappingURL=openclaw.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"openclaw.d.ts","sourceRoot":"","sources":["../../src/adapters/openclaw.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,EAAgB,KAAK,MAAM,EAAE,MAAM,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"openclaw.d.ts","sourceRoot":"","sources":["../../src/adapters/openclaw.ts"],"names":[],"mappings":"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"}
|
|
@@ -6,23 +6,10 @@ import { homedir } from 'os';
|
|
|
6
6
|
import { createPublicKey, createPrivateKey, sign as cryptoSign, randomUUID } from 'crypto';
|
|
7
7
|
import WebSocket from 'ws';
|
|
8
8
|
import { debug } from '../logger.js';
|
|
9
|
+
import { summarizeResponse, extractTopicHint } from '../timeline-summarizer.js';
|
|
10
|
+
import { cleanDetailText, cleanRawText, cleanNopMarkers, ED25519_SPKI_PREFIX_LEN, GATEWAY_PROTOCOL_VERSION, } from '@agentdeck/shared';
|
|
9
11
|
import { OPENCLAW_CAPABILITIES, OPENCLAW_GATEWAY_PORT } from '../types.js';
|
|
10
12
|
import { fetchModelCatalog, getDefaultModelName, invalidateModelCache } from '../model-catalog.js';
|
|
11
|
-
/** Ed25519 SPKI DER prefix length (bytes before the raw 32-byte key) */
|
|
12
|
-
const ED25519_SPKI_PREFIX_LEN = 12;
|
|
13
|
-
/** Protocol version supported by this adapter */
|
|
14
|
-
const PROTOCOL_VERSION = 3;
|
|
15
|
-
/**
|
|
16
|
-
* OpenClaw adapter — connects to OpenClaw Gateway via WebSocket.
|
|
17
|
-
*
|
|
18
|
-
* Protocol: Custom framing (req/res/event), Ed25519 device auth handshake,
|
|
19
|
-
* v3 protocol. Unlike ClaudeCodeAdapter (PTY-based), this adapter:
|
|
20
|
-
* - Connects to an already-running Gateway process
|
|
21
|
-
* - Authenticates via Ed25519 device signature (~/.openclaw/identity/)
|
|
22
|
-
* - Uses req/res framing over WebSocket for all commands
|
|
23
|
-
* - Has no terminal (PTY), mode switching, or diff review
|
|
24
|
-
* - Handles select_option/navigate_option/send_prompt directly via RPC
|
|
25
|
-
*/
|
|
26
13
|
export class OpenClawAdapter extends EventEmitter {
|
|
27
14
|
capabilities = OPENCLAW_CAPABILITIES;
|
|
28
15
|
gatewayUrl;
|
|
@@ -34,12 +21,23 @@ export class OpenClawAdapter extends EventEmitter {
|
|
|
34
21
|
projectName = null;
|
|
35
22
|
alive = false;
|
|
36
23
|
shutdownRequested = false;
|
|
24
|
+
externalHttpServer = false;
|
|
37
25
|
diagHandler = null;
|
|
38
26
|
rawDataCallback = null;
|
|
27
|
+
autoReconnect;
|
|
39
28
|
// Session tracking
|
|
40
29
|
currentSessionKey = null;
|
|
41
30
|
currentRunId = null;
|
|
42
31
|
pendingApprovalId = null;
|
|
32
|
+
// Chat tracking for timeline events
|
|
33
|
+
chatStarted = false;
|
|
34
|
+
chatStartTime = 0;
|
|
35
|
+
chatToolCount = 0;
|
|
36
|
+
chatToolNames = [];
|
|
37
|
+
lastPrompt = null;
|
|
38
|
+
accumulatedResponse = '';
|
|
39
|
+
topicExtracted = false;
|
|
40
|
+
chatIsAutomated = false;
|
|
43
41
|
// Device identity (loaded once on start)
|
|
44
42
|
deviceIdentity = null;
|
|
45
43
|
deviceAuthToken = null;
|
|
@@ -47,9 +45,17 @@ export class OpenClawAdapter extends EventEmitter {
|
|
|
47
45
|
reconnectDelay = 1000;
|
|
48
46
|
static MAX_RECONNECT_DELAY = 30_000;
|
|
49
47
|
static RPC_TIMEOUT = 10_000;
|
|
50
|
-
constructor(
|
|
48
|
+
constructor(options) {
|
|
51
49
|
super();
|
|
52
|
-
|
|
50
|
+
if (typeof options === 'string') {
|
|
51
|
+
// Legacy: constructor(gatewayUrl?: string)
|
|
52
|
+
this.gatewayUrl = options || `ws://127.0.0.1:${OPENCLAW_GATEWAY_PORT}`;
|
|
53
|
+
this.autoReconnect = true;
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
this.gatewayUrl = options?.gatewayUrl || `ws://127.0.0.1:${OPENCLAW_GATEWAY_PORT}`;
|
|
57
|
+
this.autoReconnect = options?.autoReconnect ?? true;
|
|
58
|
+
}
|
|
53
59
|
// Create bare HTTP server for WsServer (plugin) attachment.
|
|
54
60
|
this.httpServer = createServer((req, res) => {
|
|
55
61
|
if (req.method === 'GET' && req.url === '/health') {
|
|
@@ -92,21 +98,29 @@ export class OpenClawAdapter extends EventEmitter {
|
|
|
92
98
|
}
|
|
93
99
|
// Load device identity for Ed25519 auth (non-fatal if missing)
|
|
94
100
|
this.loadDeviceIdentity();
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
this.httpServer
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
101
|
+
if (options.externalServer) {
|
|
102
|
+
// Use externally provided HTTP server (daemon mode)
|
|
103
|
+
this.httpServer = options.externalServer;
|
|
104
|
+
this.externalHttpServer = true;
|
|
105
|
+
debug('adapter:openclaw', 'Using external HTTP server');
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
108
|
+
// Start own HTTP server for plugin WebSocket attachment
|
|
109
|
+
await new Promise((resolve, reject) => {
|
|
110
|
+
this.httpServer.on('error', (err) => {
|
|
111
|
+
if (err.code === 'EADDRINUSE') {
|
|
112
|
+
reject(new Error(`Port ${options.port} is already in use.`));
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
reject(err);
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
this.httpServer.listen(options.port, '127.0.0.1', () => {
|
|
119
|
+
debug('adapter:openclaw', `HTTP server listening on 127.0.0.1:${options.port}`);
|
|
120
|
+
resolve();
|
|
121
|
+
});
|
|
108
122
|
});
|
|
109
|
-
}
|
|
123
|
+
}
|
|
110
124
|
// Connect to OpenClaw Gateway
|
|
111
125
|
this.connectGateway();
|
|
112
126
|
}
|
|
@@ -146,6 +160,23 @@ export class OpenClawAdapter extends EventEmitter {
|
|
|
146
160
|
return true;
|
|
147
161
|
case 'send_prompt': {
|
|
148
162
|
debug('adapter:openclaw', `send_prompt: "${cmd.text.slice(0, 60)}"`);
|
|
163
|
+
this.lastPrompt = cmd.text;
|
|
164
|
+
// Optimistic: immediate timeline + PROCESSING state (no waiting for delta)
|
|
165
|
+
if (!this.chatStarted) {
|
|
166
|
+
this.chatStarted = true;
|
|
167
|
+
this.chatIsAutomated = false;
|
|
168
|
+
this.chatStartTime = Date.now();
|
|
169
|
+
this.chatToolCount = 0;
|
|
170
|
+
this.chatToolNames = [];
|
|
171
|
+
const prompt = cmd.text;
|
|
172
|
+
const promptRaw = prompt.length > 500 ? prompt.slice(0, 497) + '...' : prompt;
|
|
173
|
+
const promptDetail = prompt.length > 100 ? (prompt.length > 1000 ? prompt.slice(0, 997) + '...' : prompt) : undefined;
|
|
174
|
+
this.emitTimelineEntry({
|
|
175
|
+
ts: Date.now(), type: 'chat_start', raw: promptRaw,
|
|
176
|
+
...(promptDetail ? { detail: promptDetail } : {}),
|
|
177
|
+
});
|
|
178
|
+
this.emitAdapterEvent({ source: 'parser', event: 'spinner_start' });
|
|
179
|
+
}
|
|
149
180
|
if (this.currentSessionKey) {
|
|
150
181
|
this.rpcCall('chat.send', {
|
|
151
182
|
sessionKey: this.currentSessionKey,
|
|
@@ -153,10 +184,24 @@ export class OpenClawAdapter extends EventEmitter {
|
|
|
153
184
|
idempotencyKey: randomUUID(),
|
|
154
185
|
}).catch((err) => {
|
|
155
186
|
debug('adapter:openclaw', `chat.send failed: ${err}`);
|
|
187
|
+
this.emitTimelineEntry({
|
|
188
|
+
ts: Date.now(), type: 'error', raw: `Send failed: ${err instanceof Error ? err.message : String(err)}`,
|
|
189
|
+
});
|
|
190
|
+
this.chatStarted = false;
|
|
191
|
+
this.lastPrompt = null;
|
|
192
|
+
this.accumulatedResponse = '';
|
|
193
|
+
this.currentRunId = null;
|
|
194
|
+
this.emitAdapterEvent({ source: 'parser', event: 'idle' });
|
|
156
195
|
});
|
|
157
196
|
}
|
|
158
197
|
else {
|
|
159
198
|
debug('adapter:openclaw', 'send_prompt: no active session');
|
|
199
|
+
this.emitTimelineEntry({
|
|
200
|
+
ts: Date.now(), type: 'error', raw: 'No active session',
|
|
201
|
+
});
|
|
202
|
+
this.chatStarted = false;
|
|
203
|
+
this.emitAdapterEvent({ source: 'parser', event: 'idle' });
|
|
204
|
+
return false;
|
|
160
205
|
}
|
|
161
206
|
return true;
|
|
162
207
|
}
|
|
@@ -243,9 +288,11 @@ export class OpenClawAdapter extends EventEmitter {
|
|
|
243
288
|
this.ws = null;
|
|
244
289
|
}
|
|
245
290
|
this.alive = false;
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
291
|
+
if (!this.externalHttpServer) {
|
|
292
|
+
await new Promise((resolve) => {
|
|
293
|
+
this.httpServer.close(() => resolve());
|
|
294
|
+
});
|
|
295
|
+
}
|
|
249
296
|
}
|
|
250
297
|
// ===== Private: Device Identity =====
|
|
251
298
|
loadDeviceIdentity() {
|
|
@@ -359,7 +406,7 @@ export class OpenClawAdapter extends EventEmitter {
|
|
|
359
406
|
});
|
|
360
407
|
}
|
|
361
408
|
scheduleReconnect() {
|
|
362
|
-
if (this.shutdownRequested || this.reconnectTimer)
|
|
409
|
+
if (this.shutdownRequested || this.reconnectTimer || !this.autoReconnect)
|
|
363
410
|
return;
|
|
364
411
|
debug('adapter:openclaw', `Reconnecting in ${this.reconnectDelay}ms...`);
|
|
365
412
|
this.reconnectTimer = setTimeout(() => {
|
|
@@ -369,6 +416,12 @@ export class OpenClawAdapter extends EventEmitter {
|
|
|
369
416
|
this.reconnectDelay = Math.min(this.reconnectDelay * 2, OpenClawAdapter.MAX_RECONNECT_DELAY);
|
|
370
417
|
}
|
|
371
418
|
// ===== Private: Request/Response =====
|
|
419
|
+
/**
|
|
420
|
+
* Typed RPC dispatch. `GatewayMethodMap` correlates the method name with
|
|
421
|
+
* its param shape and result shape (declared in `shared/gateway-protocol.ts`),
|
|
422
|
+
* so misuse — wrong params for a method, or calling an unknown method — is
|
|
423
|
+
* a compile error here rather than a runtime surprise.
|
|
424
|
+
*/
|
|
372
425
|
rpcCall(method, params) {
|
|
373
426
|
return new Promise((resolve, reject) => {
|
|
374
427
|
if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
|
|
@@ -377,7 +430,11 @@ export class OpenClawAdapter extends EventEmitter {
|
|
|
377
430
|
}
|
|
378
431
|
const id = `r${++this.reqId}`;
|
|
379
432
|
const message = { type: 'req', id, method, params };
|
|
380
|
-
this.pendingRpc.set(id, {
|
|
433
|
+
this.pendingRpc.set(id, {
|
|
434
|
+
resolve: resolve,
|
|
435
|
+
reject,
|
|
436
|
+
method,
|
|
437
|
+
});
|
|
381
438
|
setTimeout(() => {
|
|
382
439
|
if (this.pendingRpc.has(id)) {
|
|
383
440
|
this.pendingRpc.delete(id);
|
|
@@ -418,7 +475,7 @@ export class OpenClawAdapter extends EventEmitter {
|
|
|
418
475
|
if (this.alive) {
|
|
419
476
|
this.emitAdapterEvent({ source: 'activity' });
|
|
420
477
|
}
|
|
421
|
-
this.handleGatewayEvent(msg.event, msg.payload
|
|
478
|
+
this.handleGatewayEvent(msg.event, (msg.payload ?? {}));
|
|
422
479
|
}
|
|
423
480
|
}
|
|
424
481
|
handleGatewayEvent(event, payload) {
|
|
@@ -440,29 +497,177 @@ export class OpenClawAdapter extends EventEmitter {
|
|
|
440
497
|
const state = payload.state;
|
|
441
498
|
const runId = payload.runId;
|
|
442
499
|
const sessionKey = payload.sessionKey;
|
|
500
|
+
// Debug: log payload structure for diagnostic (delta/final only)
|
|
501
|
+
if (state === 'delta' || state === 'final') {
|
|
502
|
+
const keys = Object.keys(payload).join(',');
|
|
503
|
+
debug('adapter:openclaw', `Chat ${state} keys=[${keys}]`);
|
|
504
|
+
if (state === 'delta') {
|
|
505
|
+
// Log first delta fully for prompt discovery, then just keys
|
|
506
|
+
if (!this.chatStarted) {
|
|
507
|
+
debug('adapter:openclaw', `First delta payload: ${JSON.stringify(payload).slice(0, 800)}`);
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
else {
|
|
511
|
+
debug('adapter:openclaw', `Final payload: ${JSON.stringify(payload).slice(0, 800)}`);
|
|
512
|
+
}
|
|
513
|
+
}
|
|
443
514
|
// Track active run and session
|
|
444
515
|
if (runId)
|
|
445
516
|
this.currentRunId = runId;
|
|
446
517
|
if (sessionKey)
|
|
447
518
|
this.currentSessionKey = sessionKey;
|
|
448
519
|
switch (state) {
|
|
449
|
-
case 'delta':
|
|
520
|
+
case 'delta': {
|
|
521
|
+
// Extract text from Gateway message structure:
|
|
522
|
+
// payload.message = { role: "assistant", content: [{ type: "text", text: "..." }] }
|
|
523
|
+
const deltaText = this.extractMessageText(payload);
|
|
524
|
+
if (!this.chatStarted) {
|
|
525
|
+
// Non-optimistic path: gateway-initiated chat (cron, web, etc.)
|
|
526
|
+
this.chatStarted = true;
|
|
527
|
+
this.chatIsAutomated = !this.lastPrompt;
|
|
528
|
+
this.chatStartTime = Date.now();
|
|
529
|
+
this.chatToolCount = 0;
|
|
530
|
+
this.chatToolNames = [];
|
|
531
|
+
this.topicExtracted = false;
|
|
532
|
+
this.accumulatedResponse = deltaText || '';
|
|
533
|
+
const prompt = this.lastPrompt || '자동 작업';
|
|
534
|
+
const promptRaw = prompt.length > 500 ? prompt.slice(0, 497) + '...' : prompt;
|
|
535
|
+
const promptDetail = prompt.length > 100 ? (prompt.length > 1000 ? prompt.slice(0, 997) + '...' : prompt) : undefined;
|
|
536
|
+
this.emitTimelineEntry({
|
|
537
|
+
ts: Date.now(), type: 'chat_start', raw: promptRaw,
|
|
538
|
+
...(promptDetail ? { detail: promptDetail } : {}),
|
|
539
|
+
...(this.chatIsAutomated ? { automated: true } : {}),
|
|
540
|
+
});
|
|
541
|
+
}
|
|
542
|
+
else {
|
|
543
|
+
// Gateway always sends cumulative content — replace, never append
|
|
544
|
+
if (deltaText) {
|
|
545
|
+
this.accumulatedResponse = deltaText;
|
|
546
|
+
}
|
|
547
|
+
// Early topic extraction — upsert chat_start with topic hint
|
|
548
|
+
if (!this.topicExtracted && this.accumulatedResponse.length > 20) {
|
|
549
|
+
const topicHint = extractTopicHint(this.accumulatedResponse);
|
|
550
|
+
if (topicHint && (!this.lastPrompt || this.lastPrompt === '자동 작업')) {
|
|
551
|
+
this.topicExtracted = true;
|
|
552
|
+
this.emitTimelineUpsert({
|
|
553
|
+
ts: this.chatStartTime, type: 'chat_start',
|
|
554
|
+
raw: cleanRawText(topicHint),
|
|
555
|
+
});
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
}
|
|
450
559
|
this.emitAdapterEvent({
|
|
451
560
|
source: 'parser',
|
|
452
561
|
event: 'spinner_start',
|
|
453
562
|
data: { runId, sessionKey },
|
|
454
563
|
});
|
|
455
564
|
break;
|
|
456
|
-
|
|
457
|
-
case '
|
|
565
|
+
}
|
|
566
|
+
case 'final': {
|
|
567
|
+
// Extract modelId from payload if present (fallback when catalog probe fails)
|
|
568
|
+
const modelId = payload.model ?? payload.modelId;
|
|
569
|
+
if (typeof modelId === 'string' && modelId) {
|
|
570
|
+
this.emitAdapterEvent({
|
|
571
|
+
source: 'parser', event: 'model_info',
|
|
572
|
+
data: { model: modelId, plan: null },
|
|
573
|
+
});
|
|
574
|
+
}
|
|
575
|
+
const duration = this.chatStarted ? Math.round((Date.now() - this.chatStartTime) / 1000) : 0;
|
|
576
|
+
const toolSummary = this.buildToolSummary();
|
|
577
|
+
// Extract response content for detail + LLM summarization
|
|
578
|
+
const finalText = this.extractMessageText(payload);
|
|
579
|
+
const responseContent = (finalText || undefined)
|
|
580
|
+
|| (this.accumulatedResponse || undefined);
|
|
581
|
+
// Emit chat_response for APME turn response capture
|
|
582
|
+
if (responseContent) {
|
|
583
|
+
const respRaw = responseContent.length > 500 ? responseContent.slice(0, 497) + '...' : responseContent;
|
|
584
|
+
this.emitTimelineEntry({
|
|
585
|
+
ts: Date.now(), type: 'chat_response',
|
|
586
|
+
raw: cleanRawText(respRaw),
|
|
587
|
+
detail: cleanDetailText(responseContent.slice(0, 3000)),
|
|
588
|
+
});
|
|
589
|
+
}
|
|
590
|
+
const cleanedResponse = responseContent ? cleanNopMarkers(cleanDetailText(responseContent)) : undefined;
|
|
591
|
+
const responseDetail = cleanedResponse
|
|
592
|
+
? (cleanedResponse.length > 1000 ? cleanedResponse.slice(0, 997) + '...' : cleanedResponse)
|
|
593
|
+
: undefined;
|
|
594
|
+
// Emit chat_end with heuristic summary, then async LLM enrichment
|
|
595
|
+
const heuristicLabel = (responseContent && extractTopicHint(responseContent)) || 'Completed';
|
|
596
|
+
const parts = [heuristicLabel];
|
|
597
|
+
if (duration > 0)
|
|
598
|
+
parts.push(`${duration}s`);
|
|
599
|
+
if (toolSummary)
|
|
600
|
+
parts.push(toolSummary);
|
|
601
|
+
const chatEndTs = Date.now();
|
|
602
|
+
this.emitTimelineEntry({
|
|
603
|
+
ts: chatEndTs, type: 'chat_end', raw: parts.join(' \u00b7 '),
|
|
604
|
+
...(responseDetail ? { detail: responseDetail } : {}),
|
|
605
|
+
...(this.chatIsAutomated ? { automated: true } : {}),
|
|
606
|
+
});
|
|
607
|
+
// Async LLM summarization — fire-and-forget, upsert chat_end when ready
|
|
608
|
+
if (responseContent && responseContent.length > 30) {
|
|
609
|
+
const savedToolSummary = toolSummary;
|
|
610
|
+
const savedDuration = duration;
|
|
611
|
+
const savedAutomated = this.chatIsAutomated;
|
|
612
|
+
summarizeResponse(responseContent).then((summary) => {
|
|
613
|
+
if (summary) {
|
|
614
|
+
const enrichedParts = [summary];
|
|
615
|
+
if (savedDuration > 0)
|
|
616
|
+
enrichedParts.push(`${savedDuration}s`);
|
|
617
|
+
if (savedToolSummary)
|
|
618
|
+
enrichedParts.push(savedToolSummary);
|
|
619
|
+
debug('adapter:openclaw', `LLM summary: ${summary}`);
|
|
620
|
+
// Upsert chat_end with LLM summary replacing "Completed"
|
|
621
|
+
this.emitTimelineUpsert({
|
|
622
|
+
ts: chatEndTs, type: 'chat_end',
|
|
623
|
+
raw: enrichedParts.join(' \u00b7 '),
|
|
624
|
+
...(responseDetail ? { detail: responseDetail } : {}),
|
|
625
|
+
...(savedAutomated ? { automated: true } : {}),
|
|
626
|
+
});
|
|
627
|
+
}
|
|
628
|
+
}).catch(() => { });
|
|
629
|
+
}
|
|
630
|
+
this.chatStarted = false;
|
|
631
|
+
this.lastPrompt = null;
|
|
632
|
+
this.accumulatedResponse = '';
|
|
458
633
|
this.currentRunId = null;
|
|
459
634
|
this.emitAdapterEvent({ source: 'parser', event: 'idle' });
|
|
460
635
|
break;
|
|
461
|
-
|
|
636
|
+
}
|
|
637
|
+
case 'aborted': {
|
|
638
|
+
const abortDuration = this.chatStarted ? Math.round((Date.now() - this.chatStartTime) / 1000) : 0;
|
|
639
|
+
const abortToolSummary = this.buildToolSummary();
|
|
640
|
+
const abortParts = ['Aborted'];
|
|
641
|
+
if (abortDuration > 0)
|
|
642
|
+
abortParts.push(`after ${abortDuration}s`);
|
|
643
|
+
if (abortToolSummary)
|
|
644
|
+
abortParts.push(abortToolSummary);
|
|
645
|
+
const abortDetail = this.accumulatedResponse || undefined;
|
|
646
|
+
this.emitTimelineEntry({
|
|
647
|
+
ts: Date.now(), type: 'chat_end', raw: abortParts.join(' \u00b7 '),
|
|
648
|
+
...(abortDetail ? { detail: abortDetail } : {}),
|
|
649
|
+
...(this.chatIsAutomated ? { automated: true } : {}),
|
|
650
|
+
});
|
|
651
|
+
this.chatStarted = false;
|
|
652
|
+
this.lastPrompt = null;
|
|
653
|
+
this.accumulatedResponse = '';
|
|
654
|
+
this.currentRunId = null;
|
|
655
|
+
this.emitAdapterEvent({ source: 'parser', event: 'idle' });
|
|
656
|
+
break;
|
|
657
|
+
}
|
|
658
|
+
case 'error': {
|
|
659
|
+
const errMsg = payload.errorMessage || 'unknown';
|
|
660
|
+
this.emitTimelineEntry({
|
|
661
|
+
ts: Date.now(), type: 'error', raw: errMsg,
|
|
662
|
+
});
|
|
663
|
+
this.chatStarted = false;
|
|
664
|
+
this.lastPrompt = null;
|
|
665
|
+
this.accumulatedResponse = '';
|
|
462
666
|
this.currentRunId = null;
|
|
463
|
-
debug('adapter:openclaw', `Chat error: ${
|
|
667
|
+
debug('adapter:openclaw', `Chat error: ${errMsg}`);
|
|
464
668
|
this.emitAdapterEvent({ source: 'parser', event: 'idle' });
|
|
465
669
|
break;
|
|
670
|
+
}
|
|
466
671
|
}
|
|
467
672
|
break;
|
|
468
673
|
}
|
|
@@ -472,6 +677,20 @@ export class OpenClawAdapter extends EventEmitter {
|
|
|
472
677
|
const command = payload.command;
|
|
473
678
|
const ask = payload.ask;
|
|
474
679
|
this.pendingApprovalId = approvalId;
|
|
680
|
+
// Track tool for chat summary
|
|
681
|
+
const toolName = command?.split(' ')[0] || 'tool';
|
|
682
|
+
this.chatToolCount++;
|
|
683
|
+
if (!this.chatToolNames.includes(toolName)) {
|
|
684
|
+
this.chatToolNames.push(toolName);
|
|
685
|
+
}
|
|
686
|
+
const toolRaw = ask ? `${command}: ${ask}` : (command || 'Approve tool execution?');
|
|
687
|
+
const toolRequestRaw = toolRaw.length > 500 ? toolRaw.slice(0, 497) + '...' : toolRaw;
|
|
688
|
+
const toolRequestDetail = ask && ask.length > 100 ? (ask.length > 1000 ? ask.slice(0, 997) + '...' : ask) : undefined;
|
|
689
|
+
this.emitTimelineEntry({
|
|
690
|
+
ts: Date.now(), type: 'tool_request', raw: toolRequestRaw,
|
|
691
|
+
...(toolRequestDetail ? { detail: toolRequestDetail } : {}),
|
|
692
|
+
approvalId, status: 'pending',
|
|
693
|
+
});
|
|
475
694
|
this.emitAdapterEvent({
|
|
476
695
|
source: 'parser',
|
|
477
696
|
event: 'permission_prompt',
|
|
@@ -487,11 +706,32 @@ export class OpenClawAdapter extends EventEmitter {
|
|
|
487
706
|
});
|
|
488
707
|
break;
|
|
489
708
|
}
|
|
490
|
-
case 'exec.approval.resolved':
|
|
709
|
+
case 'exec.approval.resolved': {
|
|
491
710
|
// Approval resolved (by us or another client) → processing continues
|
|
711
|
+
const resolvedId = this.pendingApprovalId;
|
|
712
|
+
const decision = payload.decision || 'allow';
|
|
492
713
|
this.pendingApprovalId = null;
|
|
714
|
+
if (resolvedId) {
|
|
715
|
+
this.emitTimelineEntry({
|
|
716
|
+
ts: Date.now(), type: 'tool_resolved',
|
|
717
|
+
raw: decision === 'allow' ? 'Approved' : 'Denied',
|
|
718
|
+
approvalId: resolvedId,
|
|
719
|
+
status: decision === 'allow' ? 'approved' : 'denied',
|
|
720
|
+
});
|
|
721
|
+
}
|
|
493
722
|
this.emitAdapterEvent({ source: 'parser', event: 'spinner_start' });
|
|
494
723
|
break;
|
|
724
|
+
}
|
|
725
|
+
// ===== Gateway health =====
|
|
726
|
+
case 'health': {
|
|
727
|
+
const ok = payload.ok;
|
|
728
|
+
this.emitAdapterEvent({
|
|
729
|
+
source: 'metadata',
|
|
730
|
+
event: 'gateway_health',
|
|
731
|
+
data: { ok, payload },
|
|
732
|
+
});
|
|
733
|
+
break;
|
|
734
|
+
}
|
|
495
735
|
// ===== Presence / keepalive =====
|
|
496
736
|
case 'presence':
|
|
497
737
|
case 'tick':
|
|
@@ -520,8 +760,8 @@ export class OpenClawAdapter extends EventEmitter {
|
|
|
520
760
|
?? ['operator.admin', 'operator.approvals', 'operator.read'];
|
|
521
761
|
const authToken = this.deviceAuthToken?.token ?? '';
|
|
522
762
|
const params = {
|
|
523
|
-
minProtocol:
|
|
524
|
-
maxProtocol:
|
|
763
|
+
minProtocol: GATEWAY_PROTOCOL_VERSION,
|
|
764
|
+
maxProtocol: GATEWAY_PROTOCOL_VERSION,
|
|
525
765
|
client: {
|
|
526
766
|
id: 'gateway-client',
|
|
527
767
|
displayName: 'AgentDeck',
|
|
@@ -563,9 +803,9 @@ export class OpenClawAdapter extends EventEmitter {
|
|
|
563
803
|
}
|
|
564
804
|
}
|
|
565
805
|
// Fetch sessions (async, non-blocking)
|
|
566
|
-
this.fetchSessions();
|
|
806
|
+
this.fetchSessions().catch(err => debug('adapter:openclaw', `fetchSessions error: ${err}`));
|
|
567
807
|
// Fetch model catalog (async, non-blocking)
|
|
568
|
-
this.emitModelCatalog();
|
|
808
|
+
this.emitModelCatalog().catch(err => debug('adapter:openclaw', `emitModelCatalog error: ${err}`));
|
|
569
809
|
},
|
|
570
810
|
reject: (err) => {
|
|
571
811
|
debug('adapter:openclaw', `Handshake failed: ${err.message}`);
|
|
@@ -605,15 +845,14 @@ export class OpenClawAdapter extends EventEmitter {
|
|
|
605
845
|
// Pick the most recently updated session
|
|
606
846
|
const sorted = [...sessions].sort((a, b) => (b.updatedAt || 0) - (a.updatedAt || 0));
|
|
607
847
|
this.currentSessionKey = sorted[0].key;
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
}
|
|
848
|
+
// Use fixed name — Gateway session labels can be user identifiers
|
|
849
|
+
// (e.g. phone numbers) which are unsuitable as project names
|
|
850
|
+
this.projectName = 'OpenClaw';
|
|
851
|
+
this.emitAdapterEvent({
|
|
852
|
+
source: 'parser',
|
|
853
|
+
event: 'project_name',
|
|
854
|
+
data: { name: 'OpenClaw' },
|
|
855
|
+
});
|
|
617
856
|
debug('adapter:openclaw', `Active session: ${this.currentSessionKey}`);
|
|
618
857
|
}
|
|
619
858
|
catch (err) {
|
|
@@ -621,11 +860,11 @@ export class OpenClawAdapter extends EventEmitter {
|
|
|
621
860
|
}
|
|
622
861
|
}
|
|
623
862
|
/** Fetch model catalog via CLI and emit events. Retries once on failure. */
|
|
624
|
-
emitModelCatalog(retry = true) {
|
|
863
|
+
async emitModelCatalog(retry = true) {
|
|
625
864
|
// Invalidate cache on reconnect to get fresh data
|
|
626
865
|
invalidateModelCache();
|
|
627
866
|
try {
|
|
628
|
-
const catalog = fetchModelCatalog();
|
|
867
|
+
const catalog = await fetchModelCatalog();
|
|
629
868
|
if (!catalog) {
|
|
630
869
|
if (retry && this.alive) {
|
|
631
870
|
debug('adapter:openclaw', 'Model catalog empty — retrying in 10s');
|
|
@@ -634,7 +873,7 @@ export class OpenClawAdapter extends EventEmitter {
|
|
|
634
873
|
return;
|
|
635
874
|
}
|
|
636
875
|
// Emit model_info for default model name (StateMachine uses this)
|
|
637
|
-
const defaultModel = getDefaultModelName();
|
|
876
|
+
const defaultModel = await getDefaultModelName();
|
|
638
877
|
if (defaultModel) {
|
|
639
878
|
this.emitAdapterEvent({
|
|
640
879
|
source: 'parser',
|
|
@@ -657,6 +896,37 @@ export class OpenClawAdapter extends EventEmitter {
|
|
|
657
896
|
}
|
|
658
897
|
}
|
|
659
898
|
}
|
|
899
|
+
/**
|
|
900
|
+
* Extract text from Gateway chat message structure.
|
|
901
|
+
* Format: payload.message = { role, content: [{ type: "text", text: "..." }], timestamp }
|
|
902
|
+
*/
|
|
903
|
+
extractMessageText(payload) {
|
|
904
|
+
const msg = payload.message;
|
|
905
|
+
if (!msg)
|
|
906
|
+
return undefined;
|
|
907
|
+
const content = msg.content;
|
|
908
|
+
if (!content || !Array.isArray(content))
|
|
909
|
+
return undefined;
|
|
910
|
+
const texts = content
|
|
911
|
+
.filter(c => c.type === 'text' && c.text)
|
|
912
|
+
.map(c => c.text);
|
|
913
|
+
return texts.length > 0 ? texts.join('') : undefined;
|
|
914
|
+
}
|
|
915
|
+
/** Build tool count summary like "Read(3), Bash(2)" */
|
|
916
|
+
buildToolSummary() {
|
|
917
|
+
if (this.chatToolNames.length === 0)
|
|
918
|
+
return '';
|
|
919
|
+
// Count occurrences (simplified — uses total count distributed)
|
|
920
|
+
return this.chatToolNames.join(', ');
|
|
921
|
+
}
|
|
922
|
+
/** Emit a timeline event through the adapter event system */
|
|
923
|
+
emitTimelineEntry(entry) {
|
|
924
|
+
this.emitAdapterEvent({ source: 'timeline', entry });
|
|
925
|
+
}
|
|
926
|
+
/** Emit a timeline upsert (update existing entry with same ts+type, or add new) */
|
|
927
|
+
emitTimelineUpsert(entry) {
|
|
928
|
+
this.emitAdapterEvent({ source: 'timeline', entry, upsert: true });
|
|
929
|
+
}
|
|
660
930
|
emitAdapterEvent(evt) {
|
|
661
931
|
this.emit('event', evt);
|
|
662
932
|
}
|