@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.
Files changed (41) hide show
  1. package/dist/command-center-client.d.ts +32 -0
  2. package/dist/command-center-client.d.ts.map +1 -0
  3. package/dist/command-center-client.js +137 -0
  4. package/dist/command-center-client.js.map +1 -0
  5. package/dist/config.d.ts +51 -0
  6. package/dist/config.d.ts.map +1 -0
  7. package/dist/config.js +89 -0
  8. package/dist/config.js.map +1 -0
  9. package/dist/daemon.d.ts +21 -0
  10. package/dist/daemon.d.ts.map +1 -0
  11. package/dist/daemon.js +1937 -0
  12. package/dist/daemon.js.map +1 -0
  13. package/dist/gateway-client.d.ts +175 -0
  14. package/dist/gateway-client.d.ts.map +1 -0
  15. package/dist/gateway-client.js +494 -0
  16. package/dist/gateway-client.js.map +1 -0
  17. package/dist/heartbeat.d.ts +35 -0
  18. package/dist/heartbeat.d.ts.map +1 -0
  19. package/dist/heartbeat.js +116 -0
  20. package/dist/heartbeat.js.map +1 -0
  21. package/dist/openclaw-manager.d.ts +41 -0
  22. package/dist/openclaw-manager.d.ts.map +1 -0
  23. package/dist/openclaw-manager.js +199 -0
  24. package/dist/openclaw-manager.js.map +1 -0
  25. package/dist/protocols/index.d.ts +21 -0
  26. package/dist/protocols/index.d.ts.map +1 -0
  27. package/dist/protocols/index.js +30 -0
  28. package/dist/protocols/index.js.map +1 -0
  29. package/dist/protocols/jsonrpc-protocol.d.ts +24 -0
  30. package/dist/protocols/jsonrpc-protocol.d.ts.map +1 -0
  31. package/dist/protocols/jsonrpc-protocol.js +83 -0
  32. package/dist/protocols/jsonrpc-protocol.js.map +1 -0
  33. package/dist/protocols/openclaw-protocol.d.ts +33 -0
  34. package/dist/protocols/openclaw-protocol.d.ts.map +1 -0
  35. package/dist/protocols/openclaw-protocol.js +131 -0
  36. package/dist/protocols/openclaw-protocol.js.map +1 -0
  37. package/dist/protocols/types.d.ts +86 -0
  38. package/dist/protocols/types.d.ts.map +1 -0
  39. package/dist/protocols/types.js +13 -0
  40. package/dist/protocols/types.js.map +1 -0
  41. package/package.json +40 -0
@@ -0,0 +1,131 @@
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
+ // ── Protocol constants ─────────────────────────────────────────
26
+ const PROTOCOL_VERSION = 3;
27
+ const CONNECT_ID = "__m2f_connect__";
28
+ // ── Adapter implementation ─────────────────────────────────────
29
+ export class OpenClawProtocol {
30
+ name = "openclaw";
31
+ buildHandshake(opts) {
32
+ const frame = {
33
+ type: "req",
34
+ id: CONNECT_ID,
35
+ method: "connect",
36
+ params: {
37
+ minProtocol: PROTOCOL_VERSION,
38
+ maxProtocol: PROTOCOL_VERSION,
39
+ client: {
40
+ id: opts.clientId ?? "cli",
41
+ displayName: opts.displayName ?? "Mind2Flow Daemon",
42
+ version: opts.clientVersion ?? "0.1.0",
43
+ platform: opts.platform ?? process.platform,
44
+ mode: "cli",
45
+ },
46
+ role: "operator",
47
+ scopes: ["operator.read", "operator.write"],
48
+ caps: [],
49
+ ...(opts.token ? { auth: { token: opts.token } } : {}),
50
+ },
51
+ };
52
+ return JSON.stringify(frame);
53
+ }
54
+ encodeRequest(req) {
55
+ const frame = {
56
+ type: "req",
57
+ id: req.id,
58
+ method: req.method,
59
+ };
60
+ if (req.params && Object.keys(req.params).length > 0) {
61
+ frame.params = req.params;
62
+ }
63
+ return JSON.stringify(frame);
64
+ }
65
+ parseMessage(raw) {
66
+ let parsed;
67
+ try {
68
+ parsed = JSON.parse(raw);
69
+ }
70
+ catch {
71
+ return { kind: "unknown", raw };
72
+ }
73
+ if (!parsed || typeof parsed !== "object") {
74
+ return { kind: "unknown", raw: parsed };
75
+ }
76
+ const frame = parsed;
77
+ // Response frame
78
+ if (frame.type === "res") {
79
+ const resFrame = frame;
80
+ const response = {
81
+ id: String(resFrame.id),
82
+ ok: resFrame.ok,
83
+ result: resFrame.payload,
84
+ };
85
+ if (resFrame.error) {
86
+ response.error = {
87
+ code: resFrame.error.code,
88
+ message: resFrame.error.message,
89
+ data: resFrame.error.details,
90
+ };
91
+ }
92
+ return { kind: "response", response };
93
+ }
94
+ // Event frame
95
+ if (frame.type === "event") {
96
+ const evtFrame = frame;
97
+ const event = {
98
+ event: evtFrame.event,
99
+ payload: evtFrame.payload,
100
+ seq: evtFrame.seq,
101
+ };
102
+ return { kind: "event", event };
103
+ }
104
+ return { kind: "unknown", raw: parsed };
105
+ }
106
+ isHandshakeResponse(raw) {
107
+ let parsed;
108
+ try {
109
+ parsed = JSON.parse(raw);
110
+ }
111
+ catch {
112
+ return null;
113
+ }
114
+ if (!parsed || typeof parsed !== "object")
115
+ return null;
116
+ const frame = parsed;
117
+ if (frame.type === "res" && frame.id === CONNECT_ID) {
118
+ return frame.ok === true;
119
+ }
120
+ // connect.challenge event — not a handshake *response*, ignore for now
121
+ // (in production we'd handle nonce signing)
122
+ if (frame.type === "event") {
123
+ const evt = frame;
124
+ if (evt.event === "connect.challenge") {
125
+ return null; // Not a response, keep waiting
126
+ }
127
+ }
128
+ return null; // Not a handshake message
129
+ }
130
+ }
131
+ //# sourceMappingURL=openclaw-protocol.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openclaw-protocol.js","sourceRoot":"","sources":["../../src/protocols/openclaw-protocol.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,86 @@
1
+ /**
2
+ * Protocol adapter types for the Gateway client.
3
+ *
4
+ * The daemon supports multiple wire protocols for communicating with
5
+ * local agent gateways. Each protocol adapter translates between our
6
+ * internal request/response model and the gateway's native framing.
7
+ *
8
+ * Supported protocols:
9
+ * - "openclaw" — OpenClaw native WS protocol (type:"req"/"res", connect handshake)
10
+ * - "jsonrpc" — Standard JSON-RPC 2.0 over WebSocket (no handshake)
11
+ */
12
+ /** Outgoing request from daemon → gateway */
13
+ export interface GatewayRequest {
14
+ id: string;
15
+ method: string;
16
+ params?: Record<string, unknown>;
17
+ }
18
+ /** Incoming response from gateway → daemon */
19
+ export interface GatewayResponse {
20
+ id: string;
21
+ ok: boolean;
22
+ result?: unknown;
23
+ error?: {
24
+ code: string | number;
25
+ message: string;
26
+ data?: unknown;
27
+ };
28
+ }
29
+ /** Server-initiated notification/event (no id) */
30
+ export interface GatewayEvent {
31
+ event: string;
32
+ payload?: unknown;
33
+ seq?: number;
34
+ }
35
+ export type ParsedMessage = {
36
+ kind: "response";
37
+ response: GatewayResponse;
38
+ } | {
39
+ kind: "event";
40
+ event: GatewayEvent;
41
+ } | {
42
+ kind: "unknown";
43
+ raw: unknown;
44
+ };
45
+ export interface ProtocolAdapter {
46
+ /** Human-readable name for logging */
47
+ readonly name: string;
48
+ /**
49
+ * Generate the initial handshake frame(s) to send on connect.
50
+ * Returns null if the protocol has no handshake (e.g. JSON-RPC 2.0).
51
+ */
52
+ buildHandshake(opts: HandshakeOptions): string | null;
53
+ /**
54
+ * Serialize an outgoing request into a wire-format JSON string.
55
+ */
56
+ encodeRequest(req: GatewayRequest): string;
57
+ /**
58
+ * Parse a raw incoming message into our internal types.
59
+ */
60
+ parseMessage(raw: string): ParsedMessage;
61
+ /**
62
+ * Check if a parsed response is a handshake-ok response.
63
+ * Returns true if it is (and the connection is now established).
64
+ * Returns false for non-handshake responses, or null if the
65
+ * protocol has no handshake concept.
66
+ */
67
+ isHandshakeResponse(raw: string): boolean | null;
68
+ }
69
+ export interface HandshakeOptions {
70
+ /** Auth token for the gateway */
71
+ token?: string;
72
+ /**
73
+ * Client identifier — must be a value from OpenClaw's GATEWAY_CLIENT_IDS
74
+ * allowlist: "cli", "gateway-client", "webchat", "node-host", "test", etc.
75
+ * Default: "cli"
76
+ */
77
+ clientId?: string;
78
+ /** Human-readable display name for this instance (no validation constraints) */
79
+ displayName?: string;
80
+ /** Client version */
81
+ clientVersion?: string;
82
+ /** Platform (node, macos, linux, etc.) */
83
+ platform?: string;
84
+ }
85
+ export type ProtocolType = "openclaw" | "jsonrpc";
86
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/protocols/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAIH,6CAA6C;AAC7C,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC;AAED,8CAA8C;AAC9C,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;CACpE;AAED,kDAAkD;AAClD,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAID,MAAM,MAAM,aAAa,GACrB;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,QAAQ,EAAE,eAAe,CAAA;CAAE,GAC/C;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,YAAY,CAAA;CAAE,GACtC;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,GAAG,EAAE,OAAO,CAAA;CAAE,CAAC;AAItC,MAAM,WAAW,eAAe;IAC9B,sCAAsC;IACtC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAEtB;;;OAGG;IACH,cAAc,CAAC,IAAI,EAAE,gBAAgB,GAAG,MAAM,GAAG,IAAI,CAAC;IAEtD;;OAEG;IACH,aAAa,CAAC,GAAG,EAAE,cAAc,GAAG,MAAM,CAAC;IAE3C;;OAEG;IACH,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,aAAa,CAAC;IAEzC;;;;;OAKG;IACH,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI,CAAC;CAClD;AAID,MAAM,WAAW,gBAAgB;IAC/B,iCAAiC;IACjC,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB,gFAAgF;IAChF,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,qBAAqB;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB,0CAA0C;IAC1C,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAID,MAAM,MAAM,YAAY,GAAG,UAAU,GAAG,SAAS,CAAC"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Protocol adapter types for the Gateway client.
3
+ *
4
+ * The daemon supports multiple wire protocols for communicating with
5
+ * local agent gateways. Each protocol adapter translates between our
6
+ * internal request/response model and the gateway's native framing.
7
+ *
8
+ * Supported protocols:
9
+ * - "openclaw" — OpenClaw native WS protocol (type:"req"/"res", connect handshake)
10
+ * - "jsonrpc" — Standard JSON-RPC 2.0 over WebSocket (no handshake)
11
+ */
12
+ export {};
13
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/protocols/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG"}
package/package.json ADDED
@@ -0,0 +1,40 @@
1
+ {
2
+ "name": "@mind2flow/daemon",
3
+ "version": "0.1.0",
4
+ "description": "Mind2Flow Command Center — Agent daemon (bridge between Command Center and local OpenClaw Gateway)",
5
+ "type": "module",
6
+ "main": "dist/daemon.js",
7
+ "bin": {
8
+ "m2f-daemon": "dist/daemon.js"
9
+ },
10
+ "scripts": {
11
+ "build": "tsc",
12
+ "dev": "tsx watch src/daemon.ts",
13
+ "start": "node dist/daemon.js",
14
+ "lint": "eslint src/",
15
+ "clean": "rm -rf dist"
16
+ },
17
+ "engines": {
18
+ "node": ">=22.0.0"
19
+ },
20
+ "dependencies": {
21
+ "ws": "^8.18.0",
22
+ "systeminformation": "^5.23.0",
23
+ "screenshot-desktop": "^1.15.0",
24
+ "chalk": "^5.3.0",
25
+ "commander": "^12.1.0",
26
+ "dotenv": "^16.4.5"
27
+ },
28
+ "devDependencies": {
29
+ "@types/node": "^22.0.0",
30
+ "@types/ws": "^8.5.12",
31
+ "tsx": "^4.19.0",
32
+ "typescript": "^5.6.0"
33
+ },
34
+ "files": [
35
+ "dist/",
36
+ "package.json",
37
+ "README.md"
38
+ ],
39
+ "license": "UNLICENSED"
40
+ }