@earzbook/openclaw 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 (42) hide show
  1. package/README.md +46 -0
  2. package/dist/adapter.d.ts +29 -0
  3. package/dist/adapter.d.ts.map +1 -0
  4. package/dist/adapter.js +368 -0
  5. package/dist/adapter.js.map +1 -0
  6. package/dist/config.d.ts +7 -0
  7. package/dist/config.d.ts.map +1 -0
  8. package/dist/config.js +84 -0
  9. package/dist/config.js.map +1 -0
  10. package/dist/dispatch.d.ts +48 -0
  11. package/dist/dispatch.d.ts.map +1 -0
  12. package/dist/dispatch.js +261 -0
  13. package/dist/dispatch.js.map +1 -0
  14. package/dist/index.d.ts +2 -0
  15. package/dist/index.d.ts.map +1 -0
  16. package/dist/index.js +571 -0
  17. package/dist/index.js.map +1 -0
  18. package/dist/lockfile.d.ts +20 -0
  19. package/dist/lockfile.d.ts.map +1 -0
  20. package/dist/lockfile.js +113 -0
  21. package/dist/lockfile.js.map +1 -0
  22. package/dist/logging.d.ts +5 -0
  23. package/dist/logging.d.ts.map +1 -0
  24. package/dist/logging.js +98 -0
  25. package/dist/logging.js.map +1 -0
  26. package/dist/platform/launchd.d.ts +12 -0
  27. package/dist/platform/launchd.d.ts.map +1 -0
  28. package/dist/platform/launchd.js +37 -0
  29. package/dist/platform/launchd.js.map +1 -0
  30. package/dist/platform/systemd.d.ts +10 -0
  31. package/dist/platform/systemd.d.ts.map +1 -0
  32. package/dist/platform/systemd.js +18 -0
  33. package/dist/platform/systemd.js.map +1 -0
  34. package/dist/self-update.d.ts +36 -0
  35. package/dist/self-update.d.ts.map +1 -0
  36. package/dist/self-update.js +151 -0
  37. package/dist/self-update.js.map +1 -0
  38. package/dist/types.d.ts +236 -0
  39. package/dist/types.d.ts.map +1 -0
  40. package/dist/types.js +22 -0
  41. package/dist/types.js.map +1 -0
  42. package/package.json +48 -0
package/dist/index.js ADDED
@@ -0,0 +1,571 @@
1
+ #!/usr/bin/env node
2
+ // Earzbook ↔ OpenClaw sidecar entry.
3
+ //
4
+ // Invoked by launchd/systemd as `earzbook-openclaw --config <path>`.
5
+ //
6
+ // Flow:
7
+ // 1. Parse argv → resolve config path.
8
+ // 2. Acquire single-instance lock (exit cleanly if held).
9
+ // 3. Load + validate config.
10
+ // 4. Run a startup self-update check (force-update path may exit(0) so
11
+ // the supervisor relaunches with the new binary).
12
+ // 5. Start the WS adapter against the relay; on every inbound user_
13
+ // message, enqueue → spawn `openclaw agent` → emit agent_reply.
14
+ // 6. On SIGTERM/SIGINT, close cleanly. On fatal protocol errors, exit
15
+ // with code 75 (EX_TEMPFAIL) so supervisors throttle restarts.
16
+ import { createRequire } from "node:module";
17
+ import * as fs from "node:fs";
18
+ import * as os from "node:os";
19
+ import * as path from "node:path";
20
+ import { createAdapter } from "./adapter.js";
21
+ import { ConfigError, DEFAULT_CONFIG_PATH, loadConfig } from "./config.js";
22
+ import { dispatchToAgent } from "./dispatch.js";
23
+ import { acquireLock, LockHeldError } from "./lockfile.js";
24
+ import { log, warn, errLog, LOG_PATH } from "./logging.js";
25
+ import { createSelfUpdateRunner } from "./self-update.js";
26
+ /**
27
+ * OpenClaw stores sessions on disk like this (verified on real install):
28
+ *
29
+ * ~/.openclaw/agents/<agentId>/sessions/
30
+ * ├─ sessions.json ← manifest (THIS is the index)
31
+ * ├─ <uuid>.jsonl ← user-message log
32
+ * ├─ <uuid>.trajectory.jsonl ← full agent trajectory
33
+ * └─ <uuid>.trajectory-path.json ← pointer metadata
34
+ *
35
+ * `sessions.json` is a dict keyed by `agent:<agentId>:<sessionKey>` (the
36
+ * exact string we pass to `--session-key`). Each value carries the
37
+ * `sessionFile` absolute path which points to the `<uuid>.jsonl`. Both
38
+ * `.trajectory.jsonl` and `.trajectory-path.json` share the same `<uuid>`
39
+ * basename and live in the same directory.
40
+ *
41
+ * Earzbook sessions live under the namespace `earzbook-app:<sessionKey>`
42
+ * — when invoked with `--session-key earzbook-app:c_abc123` the manifest
43
+ * key becomes `agent:<agentId>:earzbook-app:c_abc123`. The helpers below
44
+ * filter to that namespace so we never touch the user's other OpenClaw
45
+ * sessions (e.g. `agent:main:main` from non-Earzbook use of the CLI).
46
+ */
47
+ const EARZBOOK_SESSION_KEY_PREFIX = "earzbook-app:";
48
+ function openClawSessionsDir(agentId) {
49
+ return path.join(os.homedir(), ".openclaw", "agents", agentId, "sessions");
50
+ }
51
+ function openClawManifestPath(agentId) {
52
+ return path.join(openClawSessionsDir(agentId), "sessions.json");
53
+ }
54
+ /**
55
+ * Read OpenClaw's sessions.json manifest. Returns an empty dict when
56
+ * the file is missing (fresh install) or unreadable (treat as "no
57
+ * sessions" — the most useful default).
58
+ */
59
+ async function readOpenClawManifest(agentId) {
60
+ const filePath = openClawManifestPath(agentId);
61
+ try {
62
+ const raw = await fs.promises.readFile(filePath, "utf8");
63
+ const parsed = JSON.parse(raw);
64
+ if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
65
+ return parsed;
66
+ }
67
+ warn(TAG, `manifest at ${filePath} is not an object — treating as empty`);
68
+ return {};
69
+ }
70
+ catch (e) {
71
+ const errno = e?.code;
72
+ if (errno === "ENOENT") {
73
+ log(TAG, `manifest ${filePath} not present (fresh install) — empty list`);
74
+ return {};
75
+ }
76
+ errLog(TAG, `readOpenClawManifest failed (${filePath}):`, e);
77
+ return {};
78
+ }
79
+ }
80
+ /**
81
+ * List the session-keys currently on disk for our `earzbook-app:` namespace.
82
+ * Returns the BARE keys (prefix stripped) so the app can compare directly
83
+ * to its Watermelon `openclaw_session_key` column.
84
+ */
85
+ async function listOpenClawSessions(agentId) {
86
+ const manifest = await readOpenClawManifest(agentId);
87
+ const expectedKeyPrefix = `agent:${agentId}:${EARZBOOK_SESSION_KEY_PREFIX}`;
88
+ const out = [];
89
+ for (const manifestKey of Object.keys(manifest)) {
90
+ if (!manifestKey.startsWith(expectedKeyPrefix))
91
+ continue;
92
+ const bare = manifestKey.slice(expectedKeyPrefix.length);
93
+ if (bare.length === 0)
94
+ continue; // skip the legacy bare `earzbook-app` entry
95
+ out.push(bare);
96
+ }
97
+ log(TAG, `listOpenClawSessions agentId=${agentId} count=${out.length}`);
98
+ return out;
99
+ }
100
+ /**
101
+ * Remove all on-disk artifacts for one session-key:
102
+ * 1. Resolve the manifest entry → get the file basename
103
+ * 2. Unlink <uuid>.jsonl, <uuid>.trajectory.jsonl, <uuid>.trajectory-path.json
104
+ * 3. Scrub the entry from sessions.json + write back
105
+ *
106
+ * Idempotent: missing files are treated as success (user already deleted
107
+ * them, or OpenClaw never created some). Returns success: true even
108
+ * when the manifest entry was absent — the desired end state ("nothing
109
+ * on disk for this key") is satisfied.
110
+ */
111
+ async function removeOpenClawSession(opts) {
112
+ const manifestKey = `agent:${opts.agentId}:${EARZBOOK_SESSION_KEY_PREFIX}${opts.sessionKey}`;
113
+ const dir = openClawSessionsDir(opts.agentId);
114
+ const manifestPath = openClawManifestPath(opts.agentId);
115
+ const manifest = await readOpenClawManifest(opts.agentId);
116
+ const entry = manifest[manifestKey];
117
+ if (!entry) {
118
+ log(TAG, `removeOpenClawSession: no manifest entry for ${manifestKey} — treating as success`);
119
+ return { success: true };
120
+ }
121
+ // Determine the file basename. Prefer the manifest's sessionFile path
122
+ // (the absolute path to <uuid>.jsonl). Fall back to sessionId if path
123
+ // is missing (defensive — older manifest formats might omit it).
124
+ let basename = null;
125
+ if (typeof entry.sessionFile === "string" && entry.sessionFile) {
126
+ const fileName = path.basename(entry.sessionFile);
127
+ basename = fileName.replace(/\.jsonl$/, "");
128
+ }
129
+ else if (typeof entry.sessionId === "string" && entry.sessionId) {
130
+ basename = entry.sessionId;
131
+ }
132
+ let filesUnlinked = 0;
133
+ if (basename) {
134
+ const candidates = [
135
+ `${basename}.jsonl`,
136
+ `${basename}.trajectory.jsonl`,
137
+ `${basename}.trajectory-path.json`,
138
+ ];
139
+ for (const fileName of candidates) {
140
+ const filePath = path.join(dir, fileName);
141
+ try {
142
+ await fs.promises.unlink(filePath);
143
+ filesUnlinked++;
144
+ log(TAG, `unlinked ${filePath}`);
145
+ }
146
+ catch (e) {
147
+ const errno = e?.code;
148
+ if (errno === "ENOENT") {
149
+ log(TAG, `file already gone ${filePath}`);
150
+ }
151
+ else {
152
+ const msg = e instanceof Error ? e.message : String(e);
153
+ errLog(TAG, `unlink failed ${filePath}: ${msg}`);
154
+ // Continue best-effort; manifest scrub below is still useful.
155
+ }
156
+ }
157
+ }
158
+ }
159
+ else {
160
+ warn(TAG, `removeOpenClawSession: no basename derivable for ${manifestKey} — skipping file unlink, will still scrub manifest`);
161
+ }
162
+ // Scrub the manifest entry + write back. Best-effort: any error here
163
+ // we surface as failure so the app can warn the user.
164
+ delete manifest[manifestKey];
165
+ try {
166
+ const tmp = `${manifestPath}.tmp`;
167
+ await fs.promises.writeFile(tmp, JSON.stringify(manifest, null, 2), "utf8");
168
+ await fs.promises.rename(tmp, manifestPath);
169
+ log(TAG, `removeOpenClawSession ok sessionKey=${opts.sessionKey} files=${filesUnlinked} manifestScrubbed=true`);
170
+ return { success: true };
171
+ }
172
+ catch (e) {
173
+ const msg = e instanceof Error ? e.message : String(e);
174
+ errLog(TAG, `manifest write failed: ${msg}`);
175
+ return { success: false, error: `manifest update failed: ${msg}` };
176
+ }
177
+ }
178
+ /**
179
+ * Cap on how many messages we restore per session. Keeps the `history`
180
+ * wire frame bounded (a runaway trajectory can't blow up the WS payload)
181
+ * and the app-side batch write reasonable. We keep the MOST RECENT N.
182
+ */
183
+ const HISTORY_MAX_MESSAGES = 500;
184
+ /**
185
+ * Read + parse one session's on-disk trajectory into displayable messages.
186
+ *
187
+ * Restores chats after the user cleared app data / reinstalled / re-paired:
188
+ * OpenClaw chat is local-only (no server copy), so this `.jsonl` is the
189
+ * only surviving record. We surface ONLY user + assistant visible text —
190
+ * thinking blocks, tool_use blocks, and toolResult turns are dropped so the
191
+ * restored conversation matches what the user originally saw in-app.
192
+ *
193
+ * Path resolution mirrors removeOpenClawSession(): manifest key
194
+ * `agent:<agentId>:earzbook-app:<sessionKey>` → entry.sessionFile.
195
+ *
196
+ * Returns {messages:[]} (no error) when the manifest references a file that
197
+ * has since been deleted — a stale entry, not a failure.
198
+ */
199
+ async function readOpenClawSessionHistory(opts) {
200
+ const maxMessages = opts.maxMessages ?? HISTORY_MAX_MESSAGES;
201
+ const manifestKey = `agent:${opts.agentId}:${EARZBOOK_SESSION_KEY_PREFIX}${opts.sessionKey}`;
202
+ const dir = openClawSessionsDir(opts.agentId);
203
+ const manifest = await readOpenClawManifest(opts.agentId);
204
+ const entry = manifest[manifestKey];
205
+ if (!entry) {
206
+ log(TAG, `readOpenClawSessionHistory: no manifest entry for ${manifestKey}`);
207
+ return { messages: [], error: "no manifest entry for session" };
208
+ }
209
+ // Resolve the trajectory .jsonl path (same precedence as removeOpenClawSession).
210
+ let filePath = null;
211
+ if (typeof entry.sessionFile === "string" && entry.sessionFile) {
212
+ filePath = entry.sessionFile;
213
+ }
214
+ else if (typeof entry.sessionId === "string" && entry.sessionId) {
215
+ filePath = path.join(dir, `${entry.sessionId}.jsonl`);
216
+ }
217
+ if (!filePath) {
218
+ warn(TAG, `readOpenClawSessionHistory: no sessionFile for ${manifestKey}`);
219
+ return { messages: [], error: "session file path unresolved" };
220
+ }
221
+ let raw;
222
+ try {
223
+ raw = await fs.promises.readFile(filePath, "utf8");
224
+ }
225
+ catch (e) {
226
+ const errno = e?.code;
227
+ if (errno === "ENOENT") {
228
+ log(TAG, `readOpenClawSessionHistory: file gone ${filePath} — empty (stale manifest)`);
229
+ return { messages: [] };
230
+ }
231
+ const msg = e instanceof Error ? e.message : String(e);
232
+ errLog(TAG, `readOpenClawSessionHistory read failed ${filePath}: ${msg}`);
233
+ return { messages: [], error: `read failed: ${msg}` };
234
+ }
235
+ // Parse newline-delimited JSON. Preserve on-disk (chronological) order —
236
+ // do NOT re-sort by timestamp (timestamps can be absent or duplicated).
237
+ const lines = raw.split("\n");
238
+ let rawLines = 0;
239
+ const messages = [];
240
+ for (const line of lines) {
241
+ const trimmed = line.trim();
242
+ if (trimmed.length === 0)
243
+ continue;
244
+ rawLines++;
245
+ let obj;
246
+ try {
247
+ obj = JSON.parse(trimmed);
248
+ }
249
+ catch {
250
+ continue; // skip malformed lines (partial writes etc.)
251
+ }
252
+ if (obj.type !== "message")
253
+ continue; // skip session/model_change/thinking/custom
254
+ const message = obj.message;
255
+ if (!message || typeof message !== "object")
256
+ continue;
257
+ const role = message.role;
258
+ if (role !== "user" && role !== "assistant")
259
+ continue; // drop toolResult etc.
260
+ const content = Array.isArray(message.content) ? message.content : [];
261
+ let text;
262
+ if (role === "user") {
263
+ // Every user content block is visible text.
264
+ text = content
265
+ .map(b => (b && typeof b === "object" ? b.text : undefined))
266
+ .filter((t) => typeof t === "string")
267
+ .join("");
268
+ }
269
+ else {
270
+ // Assistant: keep ONLY type:"text" blocks (drop thinking / tool_use).
271
+ text = content
272
+ .filter(b => b !== null &&
273
+ typeof b === "object" &&
274
+ b.type === "text" &&
275
+ typeof b.text === "string")
276
+ .map(b => b.text)
277
+ .join("");
278
+ }
279
+ if (text.trim().length === 0)
280
+ continue; // skip empty / pure-tool turns
281
+ const at = Number(message.timestamp);
282
+ messages.push({ role, text, at: Number.isFinite(at) ? at : 0 });
283
+ }
284
+ const capped = messages.length > maxMessages;
285
+ const out = capped ? messages.slice(-maxMessages) : messages;
286
+ log(TAG, `readOpenClawSessionHistory sessionKey=${opts.sessionKey} rawLines=${rawLines} kept=${out.length} capped=${capped}`);
287
+ return { messages: out };
288
+ }
289
+ const TAG = "[earzbook-sidecar]";
290
+ // Read our own version from package.json (resolved relative to dist/).
291
+ const require = createRequire(import.meta.url);
292
+ const pkg = require("../package.json");
293
+ const SIDECAR_VERSION = pkg.version;
294
+ function parseArgs(argv) {
295
+ const out = {
296
+ configPath: DEFAULT_CONFIG_PATH,
297
+ showHelp: false,
298
+ showVersion: false,
299
+ };
300
+ for (let i = 2; i < argv.length; i++) {
301
+ const a = argv[i];
302
+ if (a === "--config" || a === "-c") {
303
+ const next = argv[++i];
304
+ if (!next)
305
+ throw new Error("--config requires a path argument");
306
+ out.configPath = next;
307
+ }
308
+ else if (a === "--help" || a === "-h") {
309
+ out.showHelp = true;
310
+ }
311
+ else if (a === "--version" || a === "-v") {
312
+ out.showVersion = true;
313
+ }
314
+ else {
315
+ throw new Error(`unknown argument: ${a}`);
316
+ }
317
+ }
318
+ return out;
319
+ }
320
+ function printHelp() {
321
+ process.stdout.write(`earzbook-openclaw v${SIDECAR_VERSION}\n\n` +
322
+ `Earzbook OpenClaw daemon. Bridges the Earzbook mobile app to a\n` +
323
+ `locally-running OpenClaw agent via a WebSocket relay.\n\n` +
324
+ `Usage:\n` +
325
+ ` earzbook-openclaw --config <path>\n\n` +
326
+ `Options:\n` +
327
+ ` -c, --config <path> Path to config JSON (default: ${DEFAULT_CONFIG_PATH})\n` +
328
+ ` -v, --version Print version and exit\n` +
329
+ ` -h, --help Show this help and exit\n\n` +
330
+ `Logs: ${LOG_PATH}\n` +
331
+ `Set EARZBOOK_SIDECAR_DEBUG=1 for verbose logs.\n`);
332
+ }
333
+ /**
334
+ * Sequential inbound dispatcher. Inbound messages are enqueued in arrival
335
+ * order; the worker drains the queue one at a time, spawning the agent
336
+ * per item. This protects OpenClaw's single-session model from concurrent
337
+ * `openclaw agent` invocations.
338
+ */
339
+ function createDispatchQueue(opts) {
340
+ const queue = [];
341
+ let running = false;
342
+ async function pump() {
343
+ if (running)
344
+ return;
345
+ running = true;
346
+ try {
347
+ while (queue.length > 0) {
348
+ const item = queue.shift();
349
+ const result = await dispatchToAgent({
350
+ agentId: opts.cfg.agentId,
351
+ text: item.text,
352
+ // v1 multi-session: per-frame sessionKey isolates each chat into
353
+ // its own OpenClaw trajectory file. When absent (legacy app
354
+ // versions), dispatch falls back to the bare `earzbook-app` key.
355
+ sessionKey: item.sessionKey,
356
+ timeoutMs: opts.cfg.agentTimeoutMs,
357
+ });
358
+ const replyText = result.ok ? result.replyText : `⚠️ ${result.userVisibleError}`;
359
+ try {
360
+ await opts.adapter().sendAgentReply({
361
+ conversationId: item.conversationId,
362
+ chunkSeq: 0,
363
+ text: replyText,
364
+ isFinal: true,
365
+ inReplyTo: item.clientMessageId,
366
+ // Echo sessionKey so the app can persist this reply under
367
+ // the correct chat-scoped Conversation row (v2 flat sessions).
368
+ sessionKey: item.sessionKey,
369
+ });
370
+ }
371
+ catch (e) {
372
+ errLog(TAG, "sendAgentReply threw:", e);
373
+ }
374
+ }
375
+ }
376
+ finally {
377
+ running = false;
378
+ }
379
+ }
380
+ return (envelope) => {
381
+ queue.push(envelope);
382
+ void pump();
383
+ };
384
+ }
385
+ /**
386
+ * Validate the bare sessionKey portion (after the `earzbook-app:`
387
+ * namespace prefix) before it touches the filesystem layer. Only
388
+ * UUID-ish characters allowed — prevents path traversal and matches
389
+ * what the app generates via generateClientMessageId().
390
+ */
391
+ const SESSION_KEY_REGEX = /^[a-zA-Z0-9_-]+$/;
392
+ /**
393
+ * Handle a delete_session request from the app — wipe all on-disk
394
+ * artifacts for the chat (sessions.json entry + 3 file unlinks) using
395
+ * the OpenClaw-native manifest format we discovered.
396
+ */
397
+ async function handleDeleteSession(opts) {
398
+ if (!SESSION_KEY_REGEX.test(opts.sessionKey)) {
399
+ warn(TAG, `delete_session rejected — sessionKey failed regex: ${opts.sessionKey}`);
400
+ return { success: false, error: "invalid sessionKey format" };
401
+ }
402
+ log(TAG, `delete_session sessionKey=${opts.sessionKey}`);
403
+ return removeOpenClawSession({
404
+ agentId: opts.agentId,
405
+ sessionKey: opts.sessionKey,
406
+ });
407
+ }
408
+ /**
409
+ * Handle a fetch_history request from the app — read the chat's on-disk
410
+ * trajectory and return its user+assistant messages so the app can restore
411
+ * a conversation it lost (cleared app data / reinstall / re-pair). Same
412
+ * path-traversal guard as delete_session before any filesystem access.
413
+ */
414
+ async function handleFetchHistory(opts) {
415
+ if (!SESSION_KEY_REGEX.test(opts.sessionKey)) {
416
+ warn(TAG, `fetch_history rejected — sessionKey failed regex: ${opts.sessionKey}`);
417
+ return { messages: [], error: "invalid sessionKey format" };
418
+ }
419
+ log(TAG, `fetch_history sessionKey=${opts.sessionKey}`);
420
+ return readOpenClawSessionHistory({
421
+ agentId: opts.agentId,
422
+ sessionKey: opts.sessionKey,
423
+ });
424
+ }
425
+ async function main() {
426
+ // 1. argv parse — done before we touch the filesystem so --help / --version
427
+ // work even if the config is missing.
428
+ let args;
429
+ try {
430
+ args = parseArgs(process.argv);
431
+ }
432
+ catch (e) {
433
+ const msg = e instanceof Error ? e.message : String(e);
434
+ process.stderr.write(`earzbook-openclaw: ${msg}\nRun with --help for usage.\n`);
435
+ process.exit(64); // EX_USAGE
436
+ return;
437
+ }
438
+ if (args.showHelp) {
439
+ printHelp();
440
+ process.exit(0);
441
+ return;
442
+ }
443
+ if (args.showVersion) {
444
+ process.stdout.write(`${SIDECAR_VERSION}\n`);
445
+ process.exit(0);
446
+ return;
447
+ }
448
+ log(TAG, `starting earzbook-openclaw v${SIDECAR_VERSION} pid=${process.pid}`);
449
+ // 2. Lock — prevent duplicate sidecars.
450
+ let lock;
451
+ try {
452
+ lock = acquireLock();
453
+ }
454
+ catch (e) {
455
+ if (e instanceof LockHeldError) {
456
+ errLog(TAG, e.message);
457
+ process.exit(0); // not an error — another sidecar is running. Exit cleanly.
458
+ return;
459
+ }
460
+ errLog(TAG, "lock acquire failed:", e);
461
+ process.exit(75); // EX_TEMPFAIL
462
+ return;
463
+ }
464
+ // 3. Config.
465
+ let cfg;
466
+ try {
467
+ cfg = loadConfig(args.configPath);
468
+ }
469
+ catch (e) {
470
+ if (e instanceof ConfigError) {
471
+ errLog(TAG, e.message);
472
+ // Bad config is operator error — exit with a stable code so the
473
+ // supervisor doesn't tight-loop trying to start us.
474
+ lock.release();
475
+ process.exit(78); // EX_CONFIG
476
+ return;
477
+ }
478
+ throw e;
479
+ }
480
+ log(TAG, `config loaded relayUrl=${cfg.relayUrl} userId=${cfg.userId} agentId=${cfg.agentId}`);
481
+ // 4. Startup self-update check.
482
+ const updater = createSelfUpdateRunner({
483
+ versionEndpoint: cfg.versionEndpoint,
484
+ installedVersion: SIDECAR_VERSION,
485
+ });
486
+ try {
487
+ const result = await updater.checkNow();
488
+ if (result.action === "force-update") {
489
+ log(TAG, `force-update to ${result.targetVersion} complete — exiting for supervisor relaunch`);
490
+ lock.release();
491
+ process.exit(0);
492
+ return;
493
+ }
494
+ if (result.action === "soft-update") {
495
+ log(TAG, `soft-updated to ${result.targetVersion} — continuing on current process until next restart`);
496
+ }
497
+ }
498
+ catch (e) {
499
+ warn(TAG, "startup update check failed (non-fatal):", e);
500
+ }
501
+ updater.startDailyTimer();
502
+ // 5. Adapter + dispatch queue.
503
+ let adapter = null;
504
+ const adapterGetter = () => {
505
+ if (!adapter)
506
+ throw new Error("adapter not yet created");
507
+ return adapter;
508
+ };
509
+ const enqueue = createDispatchQueue({ cfg, adapter: adapterGetter });
510
+ adapter = createAdapter({
511
+ relayUrl: cfg.relayUrl,
512
+ deviceToken: cfg.deviceToken,
513
+ sidecarVersion: SIDECAR_VERSION,
514
+ pingIntervalMs: cfg.pingIntervalMs,
515
+ reconnectBaseMs: cfg.reconnectBaseMs,
516
+ reconnectMaxMs: cfg.reconnectMaxMs,
517
+ }, {
518
+ onMessage: enqueue,
519
+ onConnected(welcome) {
520
+ log(TAG, `relay welcome userId=${welcome.userId} serverTime=${welcome.serverTime}`);
521
+ },
522
+ onDisconnected(info) {
523
+ log(TAG, `relay disconnected fatal=${info.fatal} reason=${info.reason}`);
524
+ if (info.fatal) {
525
+ // Server told us our token is bad / device revoked. Exit so the
526
+ // supervisor's throttling kicks in instead of tight-reconnecting.
527
+ errLog(TAG, "fatal protocol error — exiting for backoff restart");
528
+ updater.stop();
529
+ lock.release();
530
+ process.exit(75); // EX_TEMPFAIL — restartable but slow down
531
+ }
532
+ },
533
+ onListSessions: () => listOpenClawSessions(cfg.agentId),
534
+ onDeleteSession: frame => handleDeleteSession({
535
+ sessionKey: frame.sessionKey,
536
+ agentId: cfg.agentId,
537
+ }),
538
+ onFetchHistory: frame => handleFetchHistory({
539
+ sessionKey: frame.sessionKey,
540
+ agentId: cfg.agentId,
541
+ }),
542
+ });
543
+ // 6. Signal handling.
544
+ const shutdown = (signal) => {
545
+ log(TAG, `received ${signal} — shutting down`);
546
+ updater.stop();
547
+ if (adapter) {
548
+ void adapter.close(`signal:${signal}`).then(() => {
549
+ lock.release();
550
+ process.exit(0);
551
+ });
552
+ }
553
+ else {
554
+ lock.release();
555
+ process.exit(0);
556
+ }
557
+ };
558
+ process.once("SIGTERM", () => shutdown("SIGTERM"));
559
+ process.once("SIGINT", () => shutdown("SIGINT"));
560
+ // 7. Hold the process alive until a signal. Adapter and timers keep
561
+ // Node's event loop spinning; this empty interval is belt-and-suspenders.
562
+ setInterval(() => {
563
+ /* keep-alive */
564
+ }, 60_000).unref();
565
+ log(TAG, "ready");
566
+ }
567
+ main().catch(e => {
568
+ errLog(TAG, "fatal:", e);
569
+ process.exit(70); // EX_SOFTWARE
570
+ });
571
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ export declare class LockHeldError extends Error {
2
+ constructor(path: string);
3
+ }
4
+ interface LockHandle {
5
+ fd: number;
6
+ release(): void;
7
+ }
8
+ /**
9
+ * Acquire an exclusive lock on the sidecar lockfile. Throws LockHeldError
10
+ * if another process already holds it.
11
+ *
12
+ * We try to use proper-lockfile semantics via flock if available, but Node
13
+ * lacks a stable flock binding in the stdlib. The fallback is O_CREAT |
14
+ * O_EXCL: if the file exists, we treat that as held UNLESS the recorded
15
+ * pid is no longer running (stale lock → take it over).
16
+ */
17
+ export declare function acquireLock(): LockHandle;
18
+ export declare const LOCK_FILE_PATH: string;
19
+ export {};
20
+ //# sourceMappingURL=lockfile.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lockfile.d.ts","sourceRoot":"","sources":["../src/lockfile.ts"],"names":[],"mappings":"AA2BA,qBAAa,aAAc,SAAQ,KAAK;gBAC1B,IAAI,EAAE,MAAM;CAIzB;AAED,UAAU,UAAU;IAClB,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,IAAI,IAAI,CAAC;CACjB;AAED;;;;;;;;GAQG;AACH,wBAAgB,WAAW,IAAI,UAAU,CAsCxC;AAkCD,eAAO,MAAM,cAAc,QAAY,CAAC"}