@mind2flow/daemon 0.1.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/dist/command-center-client.d.ts +32 -0
- package/dist/command-center-client.d.ts.map +1 -0
- package/dist/command-center-client.js +137 -0
- package/dist/command-center-client.js.map +1 -0
- package/dist/config.d.ts +51 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +89 -0
- package/dist/config.js.map +1 -0
- package/dist/daemon.d.ts +21 -0
- package/dist/daemon.d.ts.map +1 -0
- package/dist/daemon.js +1937 -0
- package/dist/daemon.js.map +1 -0
- package/dist/gateway-client.d.ts +175 -0
- package/dist/gateway-client.d.ts.map +1 -0
- package/dist/gateway-client.js +494 -0
- package/dist/gateway-client.js.map +1 -0
- package/dist/heartbeat.d.ts +35 -0
- package/dist/heartbeat.d.ts.map +1 -0
- package/dist/heartbeat.js +116 -0
- package/dist/heartbeat.js.map +1 -0
- package/dist/openclaw-manager.d.ts +41 -0
- package/dist/openclaw-manager.d.ts.map +1 -0
- package/dist/openclaw-manager.js +199 -0
- package/dist/openclaw-manager.js.map +1 -0
- package/dist/protocols/index.d.ts +21 -0
- package/dist/protocols/index.d.ts.map +1 -0
- package/dist/protocols/index.js +30 -0
- package/dist/protocols/index.js.map +1 -0
- package/dist/protocols/jsonrpc-protocol.d.ts +24 -0
- package/dist/protocols/jsonrpc-protocol.d.ts.map +1 -0
- package/dist/protocols/jsonrpc-protocol.js +83 -0
- package/dist/protocols/jsonrpc-protocol.js.map +1 -0
- package/dist/protocols/openclaw-protocol.d.ts +33 -0
- package/dist/protocols/openclaw-protocol.d.ts.map +1 -0
- package/dist/protocols/openclaw-protocol.js +131 -0
- package/dist/protocols/openclaw-protocol.js.map +1 -0
- package/dist/protocols/types.d.ts +86 -0
- package/dist/protocols/types.d.ts.map +1 -0
- package/dist/protocols/types.js +13 -0
- package/dist/protocols/types.js.map +1 -0
- package/package.json +40 -0
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Heartbeat sender — collects system information and sends periodic
|
|
3
|
+
* heartbeats to the Command Center.
|
|
4
|
+
*/
|
|
5
|
+
import { hostname, platform, release, arch, cpus, totalmem, freemem } from "node:os";
|
|
6
|
+
// ── CPU usage tracker ────────────────────────────────────────────
|
|
7
|
+
let lastCpuTimes = null;
|
|
8
|
+
function getCpuUsage() {
|
|
9
|
+
const cores = cpus();
|
|
10
|
+
let idle = 0;
|
|
11
|
+
let total = 0;
|
|
12
|
+
for (const core of cores) {
|
|
13
|
+
idle += core.times.idle;
|
|
14
|
+
total += core.times.user + core.times.nice + core.times.sys + core.times.irq + core.times.idle;
|
|
15
|
+
}
|
|
16
|
+
if (!lastCpuTimes) {
|
|
17
|
+
lastCpuTimes = { idle, total };
|
|
18
|
+
return 0; // First call — no delta available
|
|
19
|
+
}
|
|
20
|
+
const idleDelta = idle - lastCpuTimes.idle;
|
|
21
|
+
const totalDelta = total - lastCpuTimes.total;
|
|
22
|
+
lastCpuTimes = { idle, total };
|
|
23
|
+
if (totalDelta === 0)
|
|
24
|
+
return 0;
|
|
25
|
+
return Math.round(((totalDelta - idleDelta) / totalDelta) * 100);
|
|
26
|
+
}
|
|
27
|
+
// ── System info collector ────────────────────────────────────────
|
|
28
|
+
function collectSystemInfo() {
|
|
29
|
+
const coreList = cpus();
|
|
30
|
+
return {
|
|
31
|
+
hostname: hostname(),
|
|
32
|
+
os_type: platform(),
|
|
33
|
+
os_version: release(),
|
|
34
|
+
arch: arch(),
|
|
35
|
+
cpu_count: coreList.length,
|
|
36
|
+
cpu_model: coreList[0]?.model ?? "unknown",
|
|
37
|
+
total_memory_mb: Math.round(totalmem() / 1024 / 1024),
|
|
38
|
+
free_memory_mb: Math.round(freemem() / 1024 / 1024),
|
|
39
|
+
cpu_usage_percent: getCpuUsage(),
|
|
40
|
+
uptime_seconds: Math.round(process.uptime()),
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
// ── Heartbeat service ────────────────────────────────────────────
|
|
44
|
+
export class HeartbeatService {
|
|
45
|
+
client;
|
|
46
|
+
gateway;
|
|
47
|
+
manager;
|
|
48
|
+
intervalMs;
|
|
49
|
+
timer = null;
|
|
50
|
+
logLevel;
|
|
51
|
+
constructor(client, gateway, manager, intervalMs, logLevel = "info") {
|
|
52
|
+
this.client = client;
|
|
53
|
+
this.gateway = gateway;
|
|
54
|
+
this.manager = manager;
|
|
55
|
+
this.intervalMs = intervalMs;
|
|
56
|
+
this.logLevel = logLevel;
|
|
57
|
+
}
|
|
58
|
+
start() {
|
|
59
|
+
if (this.timer)
|
|
60
|
+
return;
|
|
61
|
+
this.log("info", `Heartbeat started (every ${this.intervalMs / 1000}s)`);
|
|
62
|
+
// Send immediately, then on interval
|
|
63
|
+
this.send();
|
|
64
|
+
this.timer = setInterval(() => this.send(), this.intervalMs);
|
|
65
|
+
}
|
|
66
|
+
stop() {
|
|
67
|
+
if (this.timer) {
|
|
68
|
+
clearInterval(this.timer);
|
|
69
|
+
this.timer = null;
|
|
70
|
+
this.log("info", "Heartbeat stopped");
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
send() {
|
|
74
|
+
if (!this.client.isConnected)
|
|
75
|
+
return;
|
|
76
|
+
const sysInfo = collectSystemInfo();
|
|
77
|
+
const gatewayConnected = this.gateway.isConnected;
|
|
78
|
+
const gatewayRunning = this.manager.isRunning;
|
|
79
|
+
let status = "online";
|
|
80
|
+
if (!gatewayRunning)
|
|
81
|
+
status = "error";
|
|
82
|
+
else if (!gatewayConnected)
|
|
83
|
+
status = "busy"; // gateway running but RPC not connected yet
|
|
84
|
+
this.client.send({
|
|
85
|
+
type: "heartbeat",
|
|
86
|
+
status,
|
|
87
|
+
meta: {
|
|
88
|
+
...sysInfo,
|
|
89
|
+
gateway_running: gatewayRunning,
|
|
90
|
+
gateway_connected: gatewayConnected,
|
|
91
|
+
gateway_pid: this.manager.pid,
|
|
92
|
+
},
|
|
93
|
+
});
|
|
94
|
+
this.log("debug", `Heartbeat sent: status=${status} cpu=${sysInfo.cpu_usage_percent}%`);
|
|
95
|
+
}
|
|
96
|
+
/** Send one-time system info (used after initial connection). */
|
|
97
|
+
sendSystemInfo() {
|
|
98
|
+
const info = collectSystemInfo();
|
|
99
|
+
this.client.send({
|
|
100
|
+
type: "status_update",
|
|
101
|
+
status: "online",
|
|
102
|
+
user_id: "", // filled by server from instance record
|
|
103
|
+
system_info: info,
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
// ── Logging ────────────────────────────────────────────────────
|
|
107
|
+
log(level, msg) {
|
|
108
|
+
const levels = ["debug", "info", "warn", "error"];
|
|
109
|
+
if (levels.indexOf(level) >= levels.indexOf(this.logLevel)) {
|
|
110
|
+
const ts = new Date().toISOString();
|
|
111
|
+
const prefix = `[${ts}] [Heartbeat] [${level.toUpperCase()}]`;
|
|
112
|
+
console.log(`${prefix} ${msg}`);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
//# sourceMappingURL=heartbeat.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"heartbeat.js","sourceRoot":"","sources":["../src/heartbeat.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenClaw process manager — start, stop, and monitor the local
|
|
3
|
+
* OpenClaw Gateway subprocess.
|
|
4
|
+
*
|
|
5
|
+
* Handles:
|
|
6
|
+
* - Locating the openclaw binary
|
|
7
|
+
* - Starting the Gateway process (openclaw gateway --port <port>)
|
|
8
|
+
* - Setting environment variables for LLM API keys
|
|
9
|
+
* - Monitoring the process (restart on crash)
|
|
10
|
+
* - Graceful shutdown
|
|
11
|
+
*/
|
|
12
|
+
import { EventEmitter } from "node:events";
|
|
13
|
+
import type { LLMConfig } from "./config.js";
|
|
14
|
+
interface ManagerOptions {
|
|
15
|
+
port: number;
|
|
16
|
+
openclawBin: string | null;
|
|
17
|
+
logLevel: string;
|
|
18
|
+
}
|
|
19
|
+
export declare class OpenClawManager extends EventEmitter {
|
|
20
|
+
private process;
|
|
21
|
+
private port;
|
|
22
|
+
private binPath;
|
|
23
|
+
private logLevel;
|
|
24
|
+
private shouldRestart;
|
|
25
|
+
private restartDelay;
|
|
26
|
+
private restartTimer;
|
|
27
|
+
private envOverrides;
|
|
28
|
+
constructor(options: ManagerOptions);
|
|
29
|
+
/** Binary names to search for, in priority order. */
|
|
30
|
+
private static readonly BIN_NAMES;
|
|
31
|
+
private resolveBin;
|
|
32
|
+
applyLLMConfig(config: LLMConfig): void;
|
|
33
|
+
start(): Promise<void>;
|
|
34
|
+
stop(): Promise<void>;
|
|
35
|
+
restart(): Promise<void>;
|
|
36
|
+
get isRunning(): boolean;
|
|
37
|
+
get pid(): number | null;
|
|
38
|
+
private log;
|
|
39
|
+
}
|
|
40
|
+
export {};
|
|
41
|
+
//# sourceMappingURL=openclaw-manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openclaw-manager.d.ts","sourceRoot":"","sources":["../src/openclaw-manager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAIH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAI7C,UAAU,cAAc;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,QAAQ,EAAE,MAAM,CAAC;CAClB;AAkBD,qBAAa,eAAgB,SAAQ,YAAY;IAC/C,OAAO,CAAC,OAAO,CAA6B;IAC5C,OAAO,CAAC,IAAI,CAAS;IACrB,OAAO,CAAC,OAAO,CAAgB;IAC/B,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,aAAa,CAAQ;IAC7B,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,YAAY,CAA8C;IAClE,OAAO,CAAC,YAAY,CAA8B;gBAEtC,OAAO,EAAE,cAAc;IASnC,qDAAqD;IACrD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAwC;IAEzE,OAAO,CAAC,UAAU;IA0BlB,cAAc,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI;IAuBjC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAoEtB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAkCrB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAS9B,IAAI,SAAS,IAAI,OAAO,CAEvB;IAED,IAAI,GAAG,IAAI,MAAM,GAAG,IAAI,CAEvB;IAID,OAAO,CAAC,GAAG;CAUZ"}
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenClaw process manager — start, stop, and monitor the local
|
|
3
|
+
* OpenClaw Gateway subprocess.
|
|
4
|
+
*
|
|
5
|
+
* Handles:
|
|
6
|
+
* - Locating the openclaw binary
|
|
7
|
+
* - Starting the Gateway process (openclaw gateway --port <port>)
|
|
8
|
+
* - Setting environment variables for LLM API keys
|
|
9
|
+
* - Monitoring the process (restart on crash)
|
|
10
|
+
* - Graceful shutdown
|
|
11
|
+
*/
|
|
12
|
+
import { spawn, execSync } from "node:child_process";
|
|
13
|
+
import { existsSync } from "node:fs";
|
|
14
|
+
import { EventEmitter } from "node:events";
|
|
15
|
+
// ── LLM Provider → Env var mapping ────────────────────────────────
|
|
16
|
+
const PROVIDER_ENV_MAP = {
|
|
17
|
+
openai: "OPENAI_API_KEY",
|
|
18
|
+
anthropic: "ANTHROPIC_API_KEY",
|
|
19
|
+
groq: "GROQ_API_KEY",
|
|
20
|
+
google: "GOOGLE_API_KEY",
|
|
21
|
+
mistral: "MISTRAL_API_KEY",
|
|
22
|
+
cohere: "COHERE_API_KEY",
|
|
23
|
+
together: "TOGETHER_API_KEY",
|
|
24
|
+
fireworks: "FIREWORKS_API_KEY",
|
|
25
|
+
openrouter: "OPENROUTER_API_KEY",
|
|
26
|
+
};
|
|
27
|
+
// ── Manager ────────────────────────────────────────────────────────
|
|
28
|
+
export class OpenClawManager extends EventEmitter {
|
|
29
|
+
process = null;
|
|
30
|
+
port;
|
|
31
|
+
binPath;
|
|
32
|
+
logLevel;
|
|
33
|
+
shouldRestart = true;
|
|
34
|
+
restartDelay = 3_000;
|
|
35
|
+
restartTimer = null;
|
|
36
|
+
envOverrides = {};
|
|
37
|
+
constructor(options) {
|
|
38
|
+
super();
|
|
39
|
+
this.port = options.port;
|
|
40
|
+
this.binPath = options.openclawBin;
|
|
41
|
+
this.logLevel = options.logLevel;
|
|
42
|
+
}
|
|
43
|
+
// ── Binary resolution ──────────────────────────────────────────
|
|
44
|
+
/** Binary names to search for, in priority order. */
|
|
45
|
+
static BIN_NAMES = ["clawdbot", "openclaw", "m2f-claw"];
|
|
46
|
+
resolveBin() {
|
|
47
|
+
if (this.binPath && existsSync(this.binPath)) {
|
|
48
|
+
return this.binPath;
|
|
49
|
+
}
|
|
50
|
+
// Try to find via `which` (Unix) or `where` (Windows)
|
|
51
|
+
const whichCmd = process.platform === "win32" ? "where" : "which";
|
|
52
|
+
for (const name of OpenClawManager.BIN_NAMES) {
|
|
53
|
+
try {
|
|
54
|
+
const result = execSync(`${whichCmd} ${name}`, { encoding: "utf-8" }).trim();
|
|
55
|
+
if (result) {
|
|
56
|
+
this.log("info", `Found gateway binary at: ${result}`);
|
|
57
|
+
return result.split("\n")[0]; // first match
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
// not found — try next
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
// Try npx fallback with the correct npm package name
|
|
65
|
+
this.log("warn", "Gateway binary not found in PATH — will try npx @mind2flow/claw");
|
|
66
|
+
return "npx";
|
|
67
|
+
}
|
|
68
|
+
// ── LLM env var management ─────────────────────────────────────
|
|
69
|
+
applyLLMConfig(config) {
|
|
70
|
+
// Clear previous provider env vars
|
|
71
|
+
for (const envVar of Object.values(PROVIDER_ENV_MAP)) {
|
|
72
|
+
delete this.envOverrides[envVar];
|
|
73
|
+
}
|
|
74
|
+
// Set the new provider's key
|
|
75
|
+
const envVar = PROVIDER_ENV_MAP[config.provider.toLowerCase()];
|
|
76
|
+
if (envVar && config.apiKey) {
|
|
77
|
+
this.envOverrides[envVar] = config.apiKey;
|
|
78
|
+
this.log("info", `Set ${envVar} for provider ${config.provider}`);
|
|
79
|
+
}
|
|
80
|
+
// For custom base URLs
|
|
81
|
+
if (config.baseUrl) {
|
|
82
|
+
this.envOverrides["OPENAI_BASE_URL"] = config.baseUrl;
|
|
83
|
+
}
|
|
84
|
+
this.emit("llm-config-applied", config);
|
|
85
|
+
}
|
|
86
|
+
// ── Start ──────────────────────────────────────────────────────
|
|
87
|
+
async start() {
|
|
88
|
+
if (this.process) {
|
|
89
|
+
this.log("warn", "Gateway already running");
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
this.shouldRestart = true;
|
|
93
|
+
const bin = this.resolveBin();
|
|
94
|
+
// --allow-unconfigured: skip config gate if ~/.clawdbot/clawdbot.json is missing
|
|
95
|
+
// --force: skip port-in-use check (daemon manages lifecycle)
|
|
96
|
+
// --bind loopback: only listen on 127.0.0.1 for security
|
|
97
|
+
const args = bin === "npx"
|
|
98
|
+
? ["@mind2flow/claw", "gateway", "--port", String(this.port), "--bind", "loopback", "--allow-unconfigured", "--force"]
|
|
99
|
+
: ["gateway", "--port", String(this.port), "--bind", "loopback", "--allow-unconfigured", "--force"];
|
|
100
|
+
this.log("info", `Starting OpenClaw Gateway: ${bin} ${args.join(" ")}`);
|
|
101
|
+
const env = {
|
|
102
|
+
...process.env,
|
|
103
|
+
...this.envOverrides,
|
|
104
|
+
};
|
|
105
|
+
this.process = spawn(bin, args, {
|
|
106
|
+
env,
|
|
107
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
108
|
+
detached: false,
|
|
109
|
+
});
|
|
110
|
+
this.process.stdout?.on("data", (data) => {
|
|
111
|
+
const line = data.toString().trim();
|
|
112
|
+
if (line)
|
|
113
|
+
this.log("debug", `[gateway] ${line}`);
|
|
114
|
+
});
|
|
115
|
+
this.process.stderr?.on("data", (data) => {
|
|
116
|
+
const line = data.toString().trim();
|
|
117
|
+
if (line)
|
|
118
|
+
this.log("warn", `[gateway:err] ${line}`);
|
|
119
|
+
});
|
|
120
|
+
this.process.on("exit", (code, signal) => {
|
|
121
|
+
this.log("info", `Gateway exited (code=${code} signal=${signal})`);
|
|
122
|
+
this.process = null;
|
|
123
|
+
this.emit("exited", { code, signal });
|
|
124
|
+
if (this.shouldRestart && code !== 0) {
|
|
125
|
+
this.log("info", `Restarting Gateway in ${this.restartDelay / 1000}s…`);
|
|
126
|
+
this.restartTimer = setTimeout(() => {
|
|
127
|
+
this.restartTimer = null;
|
|
128
|
+
this.start();
|
|
129
|
+
}, this.restartDelay);
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
this.process.on("error", (err) => {
|
|
133
|
+
this.log("error", `Failed to start Gateway: ${err.message}`);
|
|
134
|
+
this.process = null;
|
|
135
|
+
this.emit("error", err);
|
|
136
|
+
});
|
|
137
|
+
// Wait briefly for startup
|
|
138
|
+
await new Promise((resolve) => setTimeout(resolve, 2_000));
|
|
139
|
+
if (this.process) {
|
|
140
|
+
this.emit("started");
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
// ── Stop ───────────────────────────────────────────────────────
|
|
144
|
+
async stop() {
|
|
145
|
+
this.shouldRestart = false;
|
|
146
|
+
if (this.restartTimer) {
|
|
147
|
+
clearTimeout(this.restartTimer);
|
|
148
|
+
this.restartTimer = null;
|
|
149
|
+
}
|
|
150
|
+
if (!this.process)
|
|
151
|
+
return;
|
|
152
|
+
this.log("info", "Stopping OpenClaw Gateway…");
|
|
153
|
+
return new Promise((resolve) => {
|
|
154
|
+
const forceKill = setTimeout(() => {
|
|
155
|
+
if (this.process) {
|
|
156
|
+
this.log("warn", "Force-killing Gateway");
|
|
157
|
+
this.process.kill("SIGKILL");
|
|
158
|
+
}
|
|
159
|
+
resolve();
|
|
160
|
+
}, 5_000);
|
|
161
|
+
this.process.once("exit", () => {
|
|
162
|
+
clearTimeout(forceKill);
|
|
163
|
+
this.process = null;
|
|
164
|
+
resolve();
|
|
165
|
+
});
|
|
166
|
+
// Graceful signal
|
|
167
|
+
this.process.kill("SIGTERM");
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
// ── Restart (for config changes) ───────────────────────────────
|
|
171
|
+
async restart() {
|
|
172
|
+
this.log("info", "Restarting Gateway for config change…");
|
|
173
|
+
await this.stop();
|
|
174
|
+
this.shouldRestart = true;
|
|
175
|
+
await this.start();
|
|
176
|
+
}
|
|
177
|
+
// ── State ──────────────────────────────────────────────────────
|
|
178
|
+
get isRunning() {
|
|
179
|
+
return this.process !== null && !this.process.killed;
|
|
180
|
+
}
|
|
181
|
+
get pid() {
|
|
182
|
+
return this.process?.pid ?? null;
|
|
183
|
+
}
|
|
184
|
+
// ── Logging ────────────────────────────────────────────────────
|
|
185
|
+
log(level, msg) {
|
|
186
|
+
const levels = ["debug", "info", "warn", "error"];
|
|
187
|
+
if (levels.indexOf(level) >= levels.indexOf(this.logLevel)) {
|
|
188
|
+
const ts = new Date().toISOString();
|
|
189
|
+
const prefix = `[${ts}] [OC-Manager] [${level.toUpperCase()}]`;
|
|
190
|
+
if (level === "error")
|
|
191
|
+
console.error(`${prefix} ${msg}`);
|
|
192
|
+
else if (level === "warn")
|
|
193
|
+
console.warn(`${prefix} ${msg}`);
|
|
194
|
+
else
|
|
195
|
+
console.log(`${prefix} ${msg}`);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
//# sourceMappingURL=openclaw-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openclaw-manager.js","sourceRoot":"","sources":["../src/openclaw-manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Protocol adapters barrel export + factory.
|
|
3
|
+
*
|
|
4
|
+
* Usage:
|
|
5
|
+
* import { createProtocol } from "./protocols/index.js";
|
|
6
|
+
* const protocol = createProtocol("openclaw");
|
|
7
|
+
*/
|
|
8
|
+
export type { ProtocolAdapter, GatewayRequest, GatewayResponse, GatewayEvent, ParsedMessage, HandshakeOptions } from "./types.js";
|
|
9
|
+
export { type ProtocolType } from "./types.js";
|
|
10
|
+
export { OpenClawProtocol } from "./openclaw-protocol.js";
|
|
11
|
+
export { JsonRpcProtocol } from "./jsonrpc-protocol.js";
|
|
12
|
+
import type { ProtocolAdapter } from "./types.js";
|
|
13
|
+
import type { ProtocolType } from "./types.js";
|
|
14
|
+
/**
|
|
15
|
+
* Factory — create a protocol adapter by name.
|
|
16
|
+
*
|
|
17
|
+
* @param type - "openclaw" for the native OpenClaw wire format,
|
|
18
|
+
* "jsonrpc" for standard JSON-RPC 2.0
|
|
19
|
+
*/
|
|
20
|
+
export declare function createProtocol(type: ProtocolType): ProtocolAdapter;
|
|
21
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/protocols/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,YAAY,EAAE,eAAe,EAAE,cAAc,EAAE,eAAe,EAAE,YAAY,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAClI,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAExD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAClD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAI/C;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,YAAY,GAAG,eAAe,CAWlE"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Protocol adapters barrel export + factory.
|
|
3
|
+
*
|
|
4
|
+
* Usage:
|
|
5
|
+
* import { createProtocol } from "./protocols/index.js";
|
|
6
|
+
* const protocol = createProtocol("openclaw");
|
|
7
|
+
*/
|
|
8
|
+
export { OpenClawProtocol } from "./openclaw-protocol.js";
|
|
9
|
+
export { JsonRpcProtocol } from "./jsonrpc-protocol.js";
|
|
10
|
+
import { OpenClawProtocol } from "./openclaw-protocol.js";
|
|
11
|
+
import { JsonRpcProtocol } from "./jsonrpc-protocol.js";
|
|
12
|
+
/**
|
|
13
|
+
* Factory — create a protocol adapter by name.
|
|
14
|
+
*
|
|
15
|
+
* @param type - "openclaw" for the native OpenClaw wire format,
|
|
16
|
+
* "jsonrpc" for standard JSON-RPC 2.0
|
|
17
|
+
*/
|
|
18
|
+
export function createProtocol(type) {
|
|
19
|
+
switch (type) {
|
|
20
|
+
case "openclaw":
|
|
21
|
+
return new OpenClawProtocol();
|
|
22
|
+
case "jsonrpc":
|
|
23
|
+
return new JsonRpcProtocol();
|
|
24
|
+
default: {
|
|
25
|
+
const exhaustive = type;
|
|
26
|
+
throw new Error(`Unknown protocol type: ${exhaustive}`);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/protocols/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAIxD,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAExD;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAAC,IAAkB;IAC/C,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,UAAU;YACb,OAAO,IAAI,gBAAgB,EAAE,CAAC;QAChC,KAAK,SAAS;YACZ,OAAO,IAAI,eAAe,EAAE,CAAC;QAC/B,OAAO,CAAC,CAAC,CAAC;YACR,MAAM,UAAU,GAAU,IAAI,CAAC;YAC/B,MAAM,IAAI,KAAK,CAAC,0BAA0B,UAAU,EAAE,CAAC,CAAC;QAC1D,CAAC;IACH,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Standard JSON-RPC 2.0 protocol adapter.
|
|
3
|
+
*
|
|
4
|
+
* For gateways that implement the JSON-RPC 2.0 specification:
|
|
5
|
+
* https://www.jsonrpc.org/specification
|
|
6
|
+
*
|
|
7
|
+
* Wire format:
|
|
8
|
+
* Request: { jsonrpc: "2.0", id: string, method: string, params?: object }
|
|
9
|
+
* Response: { jsonrpc: "2.0", id: string, result?: unknown } (success)
|
|
10
|
+
* { jsonrpc: "2.0", id: string, error: { code, message, data? } } (error)
|
|
11
|
+
* Notification: { jsonrpc: "2.0", method: string, params?: object } (no id)
|
|
12
|
+
*
|
|
13
|
+
* No handshake required — client can send requests immediately after
|
|
14
|
+
* WebSocket connection is open.
|
|
15
|
+
*/
|
|
16
|
+
import type { ProtocolAdapter, GatewayRequest, ParsedMessage, HandshakeOptions } from "./types.js";
|
|
17
|
+
export declare class JsonRpcProtocol implements ProtocolAdapter {
|
|
18
|
+
readonly name = "jsonrpc";
|
|
19
|
+
buildHandshake(_opts: HandshakeOptions): string | null;
|
|
20
|
+
encodeRequest(req: GatewayRequest): string;
|
|
21
|
+
parseMessage(raw: string): ParsedMessage;
|
|
22
|
+
isHandshakeResponse(_raw: string): boolean | null;
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=jsonrpc-protocol.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jsonrpc-protocol.d.ts","sourceRoot":"","sources":["../../src/protocols/jsonrpc-protocol.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EACV,eAAe,EACf,cAAc,EAGd,aAAa,EACb,gBAAgB,EACjB,MAAM,YAAY,CAAC;AA8BpB,qBAAa,eAAgB,YAAW,eAAe;IACrD,QAAQ,CAAC,IAAI,aAAa;IAE1B,cAAc,CAAC,KAAK,EAAE,gBAAgB,GAAG,MAAM,GAAG,IAAI;IAKtD,aAAa,CAAC,GAAG,EAAE,cAAc,GAAG,MAAM;IAY1C,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,aAAa;IAkDxC,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI;CAIlD"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Standard JSON-RPC 2.0 protocol adapter.
|
|
3
|
+
*
|
|
4
|
+
* For gateways that implement the JSON-RPC 2.0 specification:
|
|
5
|
+
* https://www.jsonrpc.org/specification
|
|
6
|
+
*
|
|
7
|
+
* Wire format:
|
|
8
|
+
* Request: { jsonrpc: "2.0", id: string, method: string, params?: object }
|
|
9
|
+
* Response: { jsonrpc: "2.0", id: string, result?: unknown } (success)
|
|
10
|
+
* { jsonrpc: "2.0", id: string, error: { code, message, data? } } (error)
|
|
11
|
+
* Notification: { jsonrpc: "2.0", method: string, params?: object } (no id)
|
|
12
|
+
*
|
|
13
|
+
* No handshake required — client can send requests immediately after
|
|
14
|
+
* WebSocket connection is open.
|
|
15
|
+
*/
|
|
16
|
+
// ── Adapter implementation ─────────────────────────────────────
|
|
17
|
+
export class JsonRpcProtocol {
|
|
18
|
+
name = "jsonrpc";
|
|
19
|
+
buildHandshake(_opts) {
|
|
20
|
+
// JSON-RPC 2.0 has no handshake — connection is usable immediately
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
encodeRequest(req) {
|
|
24
|
+
const frame = {
|
|
25
|
+
jsonrpc: "2.0",
|
|
26
|
+
id: req.id,
|
|
27
|
+
method: req.method,
|
|
28
|
+
};
|
|
29
|
+
if (req.params && Object.keys(req.params).length > 0) {
|
|
30
|
+
frame.params = req.params;
|
|
31
|
+
}
|
|
32
|
+
return JSON.stringify(frame);
|
|
33
|
+
}
|
|
34
|
+
parseMessage(raw) {
|
|
35
|
+
let parsed;
|
|
36
|
+
try {
|
|
37
|
+
parsed = JSON.parse(raw);
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
return { kind: "unknown", raw };
|
|
41
|
+
}
|
|
42
|
+
if (!parsed || typeof parsed !== "object") {
|
|
43
|
+
return { kind: "unknown", raw: parsed };
|
|
44
|
+
}
|
|
45
|
+
const msg = parsed;
|
|
46
|
+
// Must be JSON-RPC 2.0
|
|
47
|
+
if (msg.jsonrpc !== "2.0") {
|
|
48
|
+
return { kind: "unknown", raw: parsed };
|
|
49
|
+
}
|
|
50
|
+
// Response (has id)
|
|
51
|
+
if ("id" in msg && msg.id !== undefined) {
|
|
52
|
+
const rpcMsg = msg;
|
|
53
|
+
const response = {
|
|
54
|
+
id: String(rpcMsg.id),
|
|
55
|
+
ok: !("error" in msg),
|
|
56
|
+
result: rpcMsg.result,
|
|
57
|
+
};
|
|
58
|
+
if (rpcMsg.error) {
|
|
59
|
+
response.error = {
|
|
60
|
+
code: rpcMsg.error.code,
|
|
61
|
+
message: rpcMsg.error.message,
|
|
62
|
+
data: rpcMsg.error.data,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
return { kind: "response", response };
|
|
66
|
+
}
|
|
67
|
+
// Notification (no id, has method) — map to event
|
|
68
|
+
if ("method" in msg && !("id" in msg)) {
|
|
69
|
+
const notif = msg;
|
|
70
|
+
const event = {
|
|
71
|
+
event: notif.method,
|
|
72
|
+
payload: notif.params,
|
|
73
|
+
};
|
|
74
|
+
return { kind: "event", event };
|
|
75
|
+
}
|
|
76
|
+
return { kind: "unknown", raw: parsed };
|
|
77
|
+
}
|
|
78
|
+
isHandshakeResponse(_raw) {
|
|
79
|
+
// JSON-RPC has no handshake — return null to indicate N/A
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=jsonrpc-protocol.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jsonrpc-protocol.js","sourceRoot":"","sources":["../../src/protocols/jsonrpc-protocol.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAqCH,kEAAkE;AAElE,MAAM,OAAO,eAAe;IACjB,IAAI,GAAG,SAAS,CAAC;IAE1B,cAAc,CAAC,KAAuB;QACpC,mEAAmE;QACnE,OAAO,IAAI,CAAC;IACd,CAAC;IAED,aAAa,CAAC,GAAmB;QAC/B,MAAM,KAAK,GAAmB;YAC5B,OAAO,EAAE,KAAK;YACd,EAAE,EAAE,GAAG,CAAC,EAAE;YACV,MAAM,EAAE,GAAG,CAAC,MAAM;SACnB,CAAC;QACF,IAAI,GAAG,CAAC,MAAM,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACrD,KAAK,CAAC,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC;QAC5B,CAAC;QACD,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IAC/B,CAAC;IAED,YAAY,CAAC,GAAW;QACtB,IAAI,MAAe,CAAC;QACpB,IAAI,CAAC;YACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC3B,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC;QAClC,CAAC;QAED,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;YAC1C,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC;QAC1C,CAAC;QAED,MAAM,GAAG,GAAG,MAAiC,CAAC;QAE9C,uBAAuB;QACvB,IAAI,GAAG,CAAC,OAAO,KAAK,KAAK,EAAE,CAAC;YAC1B,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC;QAC1C,CAAC;QAED,oBAAoB;QACpB,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,CAAC,EAAE,KAAK,SAAS,EAAE,CAAC;YACxC,MAAM,MAAM,GAAG,GAAiC,CAAC;YACjD,MAAM,QAAQ,GAAoB;gBAChC,EAAE,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;gBACrB,EAAE,EAAE,CAAC,CAAC,OAAO,IAAI,GAAG,CAAC;gBACrB,MAAM,EAAE,MAAM,CAAC,MAAM;aACtB,CAAC;YACF,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;gBACjB,QAAQ,CAAC,KAAK,GAAG;oBACf,IAAI,EAAE,MAAM,CAAC,KAAK,CAAC,IAAI;oBACvB,OAAO,EAAE,MAAM,CAAC,KAAK,CAAC,OAAO;oBAC7B,IAAI,EAAE,MAAM,CAAC,KAAK,CAAC,IAAI;iBACxB,CAAC;YACJ,CAAC;YACD,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,CAAC;QACxC,CAAC;QAED,kDAAkD;QAClD,IAAI,QAAQ,IAAI,GAAG,IAAI,CAAC,CAAC,IAAI,IAAI,GAAG,CAAC,EAAE,CAAC;YACtC,MAAM,KAAK,GAAG,GAAqC,CAAC;YACpD,MAAM,KAAK,GAAiB;gBAC1B,KAAK,EAAE,KAAK,CAAC,MAAM;gBACnB,OAAO,EAAE,KAAK,CAAC,MAAM;aACtB,CAAC;YACF,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;QAClC,CAAC;QAED,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC;IAC1C,CAAC;IAED,mBAAmB,CAAC,IAAY;QAC9B,0DAA0D;QAC1D,OAAO,IAAI,CAAC;IACd,CAAC;CACF"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenClaw native protocol adapter.
|
|
3
|
+
*
|
|
4
|
+
* Implements the OpenClaw Gateway WebSocket protocol as documented in:
|
|
5
|
+
* https://github.com/openclaw/openclaw/blob/main/docs/gateway/protocol.md
|
|
6
|
+
*
|
|
7
|
+
* Wire format:
|
|
8
|
+
* Request: { type: "req", id: string, method: string, params?: unknown }
|
|
9
|
+
* Response: { type: "res", id: string, ok: boolean, payload?: unknown, error?: ErrorShape }
|
|
10
|
+
* Event: { type: "event", event: string, payload?: unknown, seq?: number }
|
|
11
|
+
*
|
|
12
|
+
* Connection lifecycle:
|
|
13
|
+
* 1. Gateway may send a "connect.challenge" event with a nonce
|
|
14
|
+
* 2. Client MUST send a "connect" request as the first frame
|
|
15
|
+
* 3. Gateway responds with hello-ok (ok: true) or error + close
|
|
16
|
+
* 4. After handshake, normal req/res flow
|
|
17
|
+
*
|
|
18
|
+
* Key differences from JSON-RPC 2.0:
|
|
19
|
+
* - Uses `type: "req"` instead of `jsonrpc: "2.0"`
|
|
20
|
+
* - Uses `ok: boolean` + `payload` instead of `result`
|
|
21
|
+
* - String IDs only (not numeric)
|
|
22
|
+
* - `additionalProperties: false` — no extra keys allowed
|
|
23
|
+
* - Mandatory connect handshake as first frame
|
|
24
|
+
*/
|
|
25
|
+
import type { ProtocolAdapter, GatewayRequest, ParsedMessage, HandshakeOptions } from "./types.js";
|
|
26
|
+
export declare class OpenClawProtocol implements ProtocolAdapter {
|
|
27
|
+
readonly name = "openclaw";
|
|
28
|
+
buildHandshake(opts: HandshakeOptions): string;
|
|
29
|
+
encodeRequest(req: GatewayRequest): string;
|
|
30
|
+
parseMessage(raw: string): ParsedMessage;
|
|
31
|
+
isHandshakeResponse(raw: string): boolean | null;
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=openclaw-protocol.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openclaw-protocol.d.ts","sourceRoot":"","sources":["../../src/protocols/openclaw-protocol.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,KAAK,EACV,eAAe,EACf,cAAc,EAGd,aAAa,EACb,gBAAgB,EACjB,MAAM,YAAY,CAAC;AAwCpB,qBAAa,gBAAiB,YAAW,eAAe;IACtD,QAAQ,CAAC,IAAI,cAAc;IAE3B,cAAc,CAAC,IAAI,EAAE,gBAAgB,GAAG,MAAM;IAwB9C,aAAa,CAAC,GAAG,EAAE,cAAc,GAAG,MAAM;IAY1C,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,aAAa;IA8CxC,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI;CA0BjD"}
|