@rethinkingstudio/clawpilot 1.1.17 → 2.0.0-beta.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.
Files changed (43) hide show
  1. package/dist/commands/install.js +17 -18
  2. package/dist/commands/install.js.map +1 -1
  3. package/dist/commands/openclaw-cli.js +23 -3
  4. package/dist/commands/openclaw-cli.js.map +1 -1
  5. package/dist/commands/pair.js +8 -1
  6. package/dist/commands/pair.js.map +1 -1
  7. package/dist/commands/status.js +3 -0
  8. package/dist/commands/status.js.map +1 -1
  9. package/dist/i18n/index.js +6 -0
  10. package/dist/i18n/index.js.map +1 -1
  11. package/dist/index.js +1 -1
  12. package/dist/index.js.map +1 -1
  13. package/dist/platform/service-manager.d.ts +6 -0
  14. package/dist/platform/service-manager.js +384 -42
  15. package/dist/platform/service-manager.js.map +1 -1
  16. package/package.json +8 -1
  17. package/src/commands/assistant-send.ts +0 -91
  18. package/src/commands/install.ts +0 -128
  19. package/src/commands/local-handlers.ts +0 -533
  20. package/src/commands/openclaw-cli.ts +0 -329
  21. package/src/commands/pair.ts +0 -120
  22. package/src/commands/provider-config.ts +0 -275
  23. package/src/commands/provider-handlers.ts +0 -184
  24. package/src/commands/provider-registry.ts +0 -138
  25. package/src/commands/run.ts +0 -34
  26. package/src/commands/send.ts +0 -42
  27. package/src/commands/session-key.ts +0 -77
  28. package/src/commands/set-token.ts +0 -45
  29. package/src/commands/status.ts +0 -154
  30. package/src/commands/upload.ts +0 -141
  31. package/src/config/config.ts +0 -137
  32. package/src/generated/build-config.ts +0 -1
  33. package/src/i18n/index.ts +0 -179
  34. package/src/index.ts +0 -166
  35. package/src/media/assistant-attachments.ts +0 -205
  36. package/src/media/oss-uploader.ts +0 -306
  37. package/src/platform/service-manager.ts +0 -570
  38. package/src/relay/gateway-client.ts +0 -359
  39. package/src/relay/reconnect.ts +0 -37
  40. package/src/relay/relay-manager.ts +0 -328
  41. package/test-chat.mjs +0 -64
  42. package/test-direct.mjs +0 -171
  43. package/tsconfig.json +0 -16
@@ -1,533 +0,0 @@
1
- import { cpSync, copyFileSync, existsSync, mkdirSync, readdirSync, readFileSync, statSync } from "fs";
2
- import { basename, dirname, join } from "path";
3
- import { homedir } from "os";
4
- import { execOpenclaw, resolveOpenclawConfigPath, resolveOpenclawDir } from "./openclaw-cli.js";
5
-
6
- export type LocalResult =
7
- | { ok: true; payload?: unknown }
8
- | { ok: false; error: string };
9
-
10
- type LocalCommandParams = Record<string, unknown>;
11
-
12
- type BackupListItem = {
13
- id: string;
14
- createdAt: number;
15
- files: number;
16
- };
17
-
18
- // ---------------------------------------------------------------------------
19
-
20
- export function handleLocalCommand(method: string, params: unknown): LocalResult | null {
21
- const commandParams = isRecord(params) ? params : {};
22
- switch (method) {
23
- case "clawpilot.config": return readOpenclawConfig();
24
- case "clawpilot.fix.tools.2026_3_2": return fixToolsPermissions202632();
25
- case "clawpilot.restore.config": return restoreConfig();
26
- case "clawpilot.watchskill": return watchSkill();
27
- case "clawpilot.doctor": return runDoctor();
28
- case "clawpilot.doctor.fix": return runDoctorFix();
29
- case "clawpilot.logs": return readLogs();
30
- case "clawpilot.gateway.restart": return restartGateway();
31
- case "clawpilot.version": return getOpenclawVersion();
32
- case "clawpilot.update": return updateOpenclaw();
33
- case "clawpilot.backup.create": return createBackup();
34
- case "clawpilot.backup.list": return listBackups();
35
- case "clawpilot.backup.restore": return restoreBackup(commandParams);
36
- default: return null;
37
- }
38
- }
39
-
40
- // ---------------------------------------------------------------------------
41
- // Helpers
42
- // ---------------------------------------------------------------------------
43
-
44
- function execErrorOutput(err: unknown): string {
45
- const e = err as { stdout?: Buffer | string; stderr?: Buffer | string };
46
- const out = e.stdout?.toString() ?? "";
47
- const errStr = e.stderr?.toString() ?? "";
48
- if (out && errStr) return `${out}\n${errStr}`;
49
- return out || errStr;
50
- }
51
-
52
- /** Run openclaw with the resolved path and the enriched subprocess environment. */
53
- function openclaw(args: string): Buffer {
54
- return execOpenclaw(args);
55
- }
56
-
57
- function isRecord(value: unknown): value is Record<string, unknown> {
58
- return !!value && typeof value === "object" && !Array.isArray(value);
59
- }
60
-
61
- function backupsDir(): string {
62
- return join(homedir(), ".clawai", "backups");
63
- }
64
-
65
- function formatBackupId(date = new Date(), prefix = ""): string {
66
- const pad = (value: number) => String(value).padStart(2, "0");
67
- return `${prefix}${date.getFullYear()}${pad(date.getMonth() + 1)}${pad(date.getDate())}-${pad(date.getHours())}${pad(date.getMinutes())}${pad(date.getSeconds())}`;
68
- }
69
-
70
- function countFilesRecursive(path: string): number {
71
- const stats = statSync(path);
72
- if (stats.isFile()) return 1;
73
- return readdirSync(path).reduce((count, name) => count + countFilesRecursive(join(path, name)), 0);
74
- }
75
-
76
- function listWorkspaceMarkdownFiles(workspaceDir: string): string[] {
77
- if (!existsSync(workspaceDir)) return [];
78
- return readdirSync(workspaceDir)
79
- .filter((name) => name.endsWith(".md"))
80
- .filter((name) => statSync(join(workspaceDir, name)).isFile());
81
- }
82
-
83
- function copyWithParents(from: string, to: string): void {
84
- mkdirSync(dirname(to), { recursive: true });
85
- cpSync(from, to, { recursive: true });
86
- }
87
-
88
- function createBackupSnapshot(prefix = ""): {
89
- backupId: string;
90
- path: string;
91
- copied: string[];
92
- skipped: string[];
93
- } {
94
- const openclawDir = resolveOpenclawDir();
95
- const configPath = resolveOpenclawConfigPath();
96
- if (!existsSync(configPath)) {
97
- throw new Error(`openclaw config not found: ${configPath}`);
98
- }
99
-
100
- const backupId = formatBackupId(new Date(), prefix);
101
- const targetDir = join(backupsDir(), backupId);
102
- const copied: string[] = [];
103
- const skipped: string[] = [];
104
-
105
- mkdirSync(targetDir, { recursive: true });
106
-
107
- copyWithParents(configPath, join(targetDir, "openclaw.json"));
108
- copied.push("openclaw.json");
109
-
110
- const cronPath = join(openclawDir, "cron", "jobs.json");
111
- if (existsSync(cronPath)) {
112
- copyWithParents(cronPath, join(targetDir, "cron", "jobs.json"));
113
- copied.push("cron/jobs.json");
114
- } else {
115
- skipped.push("cron/jobs.json");
116
- }
117
-
118
- const workspaceDir = join(openclawDir, "workspace");
119
- const workspaceMarkdownFiles = listWorkspaceMarkdownFiles(workspaceDir);
120
- if (workspaceMarkdownFiles.length > 0) {
121
- for (const name of workspaceMarkdownFiles) {
122
- copyWithParents(join(workspaceDir, name), join(targetDir, "workspace", name));
123
- copied.push(`workspace/${name}`);
124
- }
125
- } else {
126
- skipped.push("workspace/*.md");
127
- }
128
-
129
- const credentialsDir = join(openclawDir, "credentials");
130
- if (existsSync(credentialsDir)) {
131
- copyWithParents(credentialsDir, join(targetDir, "credentials"));
132
- copied.push("credentials/*");
133
- } else {
134
- skipped.push("credentials/*");
135
- }
136
-
137
- return { backupId, path: targetDir, copied, skipped };
138
- }
139
-
140
- function backupSummary(action: string, backupId: string, copied: string[], skipped: string[], extraLines: string[] = []): string {
141
- const lines = [
142
- `${action}: ${backupId}`,
143
- "",
144
- "Copied:",
145
- ...(copied.length > 0 ? copied.map((item) => `- ${item}`) : ["- (none)"]),
146
- ];
147
-
148
- if (skipped.length > 0) {
149
- lines.push("", "Skipped:", ...skipped.map((item) => `- ${item}`));
150
- }
151
-
152
- if (extraLines.length > 0) {
153
- lines.push("", ...extraLines);
154
- }
155
-
156
- return lines.join("\n");
157
- }
158
-
159
- function maskSensitive(value: unknown, parentKey?: string): unknown {
160
- if (Array.isArray(value)) {
161
- return value.map(item => maskSensitive(item));
162
- }
163
-
164
- if (value && typeof value === "object") {
165
- const out: Record<string, unknown> = {};
166
- for (const [key, child] of Object.entries(value as Record<string, unknown>)) {
167
- const normalized = key.toLowerCase();
168
- if (
169
- normalized.includes("token")
170
- || normalized.includes("secret")
171
- || normalized.includes("password")
172
- || normalized == "apikey"
173
- || normalized == "api_key"
174
- ) {
175
- out[key] = maskString(typeof child === "string" ? child : String(child ?? ""));
176
- } else {
177
- out[key] = maskSensitive(child, key);
178
- }
179
- }
180
- return out;
181
- }
182
-
183
- if (typeof value === "string" && parentKey) {
184
- const normalized = parentKey.toLowerCase();
185
- if (
186
- normalized.includes("token")
187
- || normalized.includes("secret")
188
- || normalized.includes("password")
189
- || normalized == "apikey"
190
- || normalized == "api_key"
191
- ) {
192
- return maskString(value);
193
- }
194
- }
195
-
196
- return value;
197
- }
198
-
199
- function maskString(value: string): string {
200
- if (!value) return value;
201
- if (value.length <= 8) return "******";
202
- return `${value.slice(0, 4)}******${value.slice(-2)}`;
203
- }
204
-
205
- // ---------------------------------------------------------------------------
206
- // Command implementations
207
- // ---------------------------------------------------------------------------
208
-
209
- function readOpenclawConfig(): LocalResult {
210
- try {
211
- const configPath = resolveOpenclawConfigPath();
212
- if (!existsSync(configPath)) {
213
- return { ok: false, error: `openclaw config not found: ${configPath}` };
214
- }
215
-
216
- const raw = readFileSync(configPath, "utf-8");
217
- const parsed = JSON.parse(raw) as Record<string, unknown>;
218
- const masked = maskSensitive(parsed);
219
- const output = JSON.stringify(masked, null, 2);
220
-
221
- return { ok: true, payload: { output: `[${configPath}]\n${output}` } };
222
- } catch (err) {
223
- return { ok: false, error: String(err) };
224
- }
225
- }
226
-
227
- function fixToolsPermissions202632(): LocalResult {
228
- const steps = [
229
- "config set tools.profile full",
230
- "config set tools.sessions.visibility all",
231
- "config set tools.exec.security full",
232
- "config set tools.exec.ask off",
233
- "gateway restart",
234
- ];
235
-
236
- try {
237
- const outputs: string[] = [];
238
-
239
- for (const step of steps) {
240
- const output = openclaw(step).toString().trim();
241
- if (output) {
242
- outputs.push(output);
243
- }
244
- }
245
-
246
- const summary = [
247
- "Applied OpenClaw 2026.3.2 tool permission fix.",
248
- "Configured:",
249
- "- tools.profile = full",
250
- "- tools.sessions.visibility = all",
251
- "- tools.exec.security = full",
252
- "- tools.exec.ask = off",
253
- "",
254
- "Gateway restarted.",
255
- ].join("\n");
256
-
257
- const output = outputs.length > 0 ? `${summary}\n\n${outputs.join("\n\n")}` : summary;
258
- return { ok: true, payload: { output } };
259
- } catch (err) {
260
- const output = execErrorOutput(err);
261
- return output ? { ok: true, payload: { output } } : { ok: false, error: String(err) };
262
- }
263
- }
264
-
265
- function restoreConfig(): LocalResult {
266
- try {
267
- const openclawDir = resolveOpenclawDir();
268
- const configPath = resolveOpenclawConfigPath();
269
- if (!existsSync(openclawDir)) {
270
- return { ok: false, error: `openclaw config dir not found: ${openclawDir}` };
271
- }
272
- const configFileName = basename(configPath) || "openclaw.json";
273
- const bakFiles = readdirSync(openclawDir)
274
- .filter(name => name.startsWith("openclaw.json.bak"))
275
- .map(name => {
276
- const path = join(openclawDir, name);
277
- return { name, path, mtime: statSync(path).mtimeMs };
278
- })
279
- .sort((a, b) => b.mtime - a.mtime);
280
-
281
- if (bakFiles.length === 0) {
282
- return { ok: false, error: "No backup files found in ~/.openclaw/" };
283
- }
284
- const latest = bakFiles[0];
285
- copyFileSync(latest.path, configPath);
286
- console.log(`[clawpilot] Config restored from ${latest.name}`);
287
- return { ok: true, payload: { restoredFrom: latest.name, config: configFileName } };
288
- } catch (err) {
289
- return { ok: false, error: String(err) };
290
- }
291
- }
292
-
293
- function watchSkill(): LocalResult {
294
- try {
295
- openclaw("config set skills.load.watch true");
296
- openclaw("gateway restart");
297
- console.log("[clawpilot] skills.load.watch set to true and gateway restarted");
298
- return { ok: true, payload: { message: "skills.load.watch enabled and gateway restarted" } };
299
- } catch (err) {
300
- return { ok: false, error: String(err) };
301
- }
302
- }
303
-
304
- function runDoctor(): LocalResult {
305
- try {
306
- const output = openclaw("doctor").toString();
307
- console.log("[clawpilot] doctor completed");
308
- return { ok: true, payload: { output } };
309
- } catch (err) {
310
- const output = execErrorOutput(err);
311
- return output ? { ok: true, payload: { output } } : { ok: false, error: String(err) };
312
- }
313
- }
314
-
315
- function runDoctorFix(): LocalResult {
316
- try {
317
- const output = openclaw("doctor --fix").toString();
318
- console.log("[clawpilot] doctor --fix completed");
319
- return { ok: true, payload: { output } };
320
- } catch (err) {
321
- const output = execErrorOutput(err);
322
- return output ? { ok: true, payload: { output } } : { ok: false, error: String(err) };
323
- }
324
- }
325
-
326
- function readLogs(): LocalResult {
327
- try {
328
- const openclawDir = resolveOpenclawDir();
329
- const logsDir = join(openclawDir, "logs");
330
- let logFiles: string[] = [];
331
-
332
- if (existsSync(logsDir)) {
333
- logFiles = readdirSync(logsDir)
334
- .filter(f => f.endsWith(".log"))
335
- .map(f => join(logsDir, f));
336
- } else {
337
- logFiles = readdirSync(openclawDir)
338
- .filter(f => f.endsWith(".log"))
339
- .map(f => join(openclawDir, f));
340
- }
341
-
342
- if (logFiles.length === 0) {
343
- return { ok: true, payload: { output: "No log files found." } };
344
- }
345
-
346
- const logFilesWithMtime = logFiles.map(f => ({ path: f, mtime: statSync(f).mtimeMs }));
347
- logFilesWithMtime.sort((a, b) => b.mtime - a.mtime);
348
- const latest = logFilesWithMtime[0].path;
349
- const allLines = readFileSync(latest, "utf-8").split("\n");
350
- const last100 = allLines.slice(-100).join("\n");
351
-
352
- console.log(`[clawpilot] logs read from ${latest}`);
353
- return { ok: true, payload: { output: `[${latest}]\n${last100}` } };
354
- } catch (err) {
355
- return { ok: false, error: String(err) };
356
- }
357
- }
358
-
359
- function restartGateway(): LocalResult {
360
- try {
361
- const output = openclaw("gateway restart").toString();
362
- console.log("[clawpilot] gateway restarted");
363
- return { ok: true, payload: { output: output || "Gateway restarted successfully." } };
364
- } catch (err) {
365
- const output = execErrorOutput(err);
366
- return output ? { ok: true, payload: { output } } : { ok: false, error: String(err) };
367
- }
368
- }
369
-
370
- function getOpenclawVersion(): LocalResult {
371
- const candidates = ["--version", "version"];
372
-
373
- for (const args of candidates) {
374
- try {
375
- const output = openclaw(args).toString().trim();
376
- const version = output
377
- .split("\n")
378
- .map(line => line.trim())
379
- .find(line => line.length > 0);
380
-
381
- if (version) {
382
- console.log(`[clawpilot] openclaw version detected via "${args}": ${version}`);
383
- return { ok: true, payload: { version, output } };
384
- }
385
- } catch (err) {
386
- const output = execErrorOutput(err).trim();
387
- const version = output
388
- .split("\n")
389
- .map(line => line.trim())
390
- .find(line => /^v?\d+\./.test(line) || /openclaw/i.test(line));
391
-
392
- if (version) {
393
- console.log(`[clawpilot] openclaw version parsed from error output via "${args}": ${version}`);
394
- return { ok: true, payload: { version, output } };
395
- }
396
- }
397
- }
398
-
399
- return { ok: false, error: "Unable to determine openclaw version." };
400
- }
401
-
402
- function updateOpenclaw(): LocalResult {
403
- try {
404
- const output = openclaw("update").toString();
405
- console.log("[clawpilot] openclaw updated");
406
- return { ok: true, payload: { output: output || "openclaw updated successfully." } };
407
- } catch (err) {
408
- const output = execErrorOutput(err);
409
- return output ? { ok: true, payload: { output } } : { ok: false, error: String(err) };
410
- }
411
- }
412
-
413
- function createBackup(): LocalResult {
414
- try {
415
- const snapshot = createBackupSnapshot();
416
- console.log(`[clawpilot] backup created: ${snapshot.backupId}`);
417
- return {
418
- ok: true,
419
- payload: {
420
- backupId: snapshot.backupId,
421
- output: backupSummary("Backup created", snapshot.backupId, snapshot.copied, snapshot.skipped),
422
- },
423
- };
424
- } catch (err) {
425
- return { ok: false, error: String(err) };
426
- }
427
- }
428
-
429
- function listBackups(): LocalResult {
430
- try {
431
- const root = backupsDir();
432
- if (!existsSync(root)) {
433
- return { ok: true, payload: { items: [] as BackupListItem[] } };
434
- }
435
-
436
- const items = readdirSync(root)
437
- .map((name) => join(root, name))
438
- .filter((path) => statSync(path).isDirectory())
439
- .map((path) => {
440
- const id = basename(path) || path;
441
- return {
442
- id,
443
- createdAt: statSync(path).mtimeMs,
444
- files: countFilesRecursive(path),
445
- } satisfies BackupListItem;
446
- })
447
- .sort((a, b) => b.createdAt - a.createdAt);
448
-
449
- return { ok: true, payload: { items } };
450
- } catch (err) {
451
- return { ok: false, error: String(err) };
452
- }
453
- }
454
-
455
- function restoreBackup(params: LocalCommandParams): LocalResult {
456
- try {
457
- const backupId = typeof params.backupId === "string" ? params.backupId.trim() : "";
458
- if (!backupId) {
459
- return { ok: false, error: "backupId is required." };
460
- }
461
- if (!/^[A-Za-z0-9_-]+$/.test(backupId)) {
462
- return { ok: false, error: "Invalid backupId." };
463
- }
464
-
465
- const sourceDir = join(backupsDir(), backupId);
466
- if (!existsSync(sourceDir) || !statSync(sourceDir).isDirectory()) {
467
- return { ok: false, error: `Backup not found: ${backupId}` };
468
- }
469
-
470
- const preRestoreSnapshot = createBackupSnapshot("pre-restore-");
471
- const openclawDir = resolveOpenclawDir();
472
- const configPath = resolveOpenclawConfigPath();
473
- const restored: string[] = [];
474
- const skipped: string[] = [];
475
-
476
- const backupConfigPath = join(sourceDir, "openclaw.json");
477
- if (existsSync(backupConfigPath)) {
478
- copyWithParents(backupConfigPath, configPath);
479
- restored.push("openclaw.json");
480
- } else {
481
- skipped.push("openclaw.json");
482
- }
483
-
484
- const backupCronPath = join(sourceDir, "cron", "jobs.json");
485
- if (existsSync(backupCronPath)) {
486
- copyWithParents(backupCronPath, join(openclawDir, "cron", "jobs.json"));
487
- restored.push("cron/jobs.json");
488
- } else {
489
- skipped.push("cron/jobs.json");
490
- }
491
-
492
- const backupWorkspaceDir = join(sourceDir, "workspace");
493
- if (existsSync(backupWorkspaceDir)) {
494
- const workspaceMarkdownFiles = listWorkspaceMarkdownFiles(backupWorkspaceDir);
495
- if (workspaceMarkdownFiles.length > 0) {
496
- for (const name of workspaceMarkdownFiles) {
497
- copyWithParents(join(backupWorkspaceDir, name), join(openclawDir, "workspace", name));
498
- restored.push(`workspace/${name}`);
499
- }
500
- } else {
501
- skipped.push("workspace/*.md");
502
- }
503
- } else {
504
- skipped.push("workspace/*.md");
505
- }
506
-
507
- const backupCredentialsDir = join(sourceDir, "credentials");
508
- if (existsSync(backupCredentialsDir)) {
509
- copyWithParents(backupCredentialsDir, join(openclawDir, "credentials"));
510
- restored.push("credentials/*");
511
- } else {
512
- skipped.push("credentials/*");
513
- }
514
-
515
- console.log(`[clawpilot] backup restored: ${backupId}`);
516
- return {
517
- ok: true,
518
- payload: {
519
- backupId,
520
- preRestoreBackupId: preRestoreSnapshot.backupId,
521
- output: backupSummary(
522
- "Backup restored",
523
- backupId,
524
- restored,
525
- skipped,
526
- [`Pre-restore backup: ${preRestoreSnapshot.backupId}`]
527
- ),
528
- },
529
- };
530
- } catch (err) {
531
- return { ok: false, error: String(err) };
532
- }
533
- }