@okclaw-build/cli 1.0.0-beta.5 → 1.0.0-beta.50

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 (85) hide show
  1. package/dist/commands/backup.d.ts +16 -0
  2. package/dist/commands/backup.js +72 -0
  3. package/dist/commands/backup.js.map +1 -0
  4. package/dist/commands/check.js +22 -6
  5. package/dist/commands/check.js.map +1 -1
  6. package/dist/commands/edit.d.ts +2 -7
  7. package/dist/commands/edit.js +27 -15
  8. package/dist/commands/edit.js.map +1 -1
  9. package/dist/commands/feed.js +63 -19
  10. package/dist/commands/feed.js.map +1 -1
  11. package/dist/commands/install.js +57 -9
  12. package/dist/commands/install.js.map +1 -1
  13. package/dist/commands/migration.d.ts +1 -0
  14. package/dist/commands/migration.js +205 -0
  15. package/dist/commands/migration.js.map +1 -0
  16. package/dist/commands/restore.d.ts +16 -0
  17. package/dist/commands/restore.js +67 -0
  18. package/dist/commands/restore.js.map +1 -0
  19. package/dist/commands/service.js +56 -13
  20. package/dist/commands/service.js.map +1 -1
  21. package/dist/commands/show.d.ts +13 -0
  22. package/dist/commands/show.js +70 -0
  23. package/dist/commands/show.js.map +1 -0
  24. package/dist/commands/skill.d.ts +1 -0
  25. package/dist/commands/skill.js +114 -0
  26. package/dist/commands/skill.js.map +1 -0
  27. package/dist/commands/uninstall.d.ts +1 -0
  28. package/dist/commands/uninstall.js +46 -0
  29. package/dist/commands/uninstall.js.map +1 -0
  30. package/dist/index.js +100 -7
  31. package/dist/index.js.map +1 -1
  32. package/dist/installers/base.d.ts +1 -0
  33. package/dist/installers/channel.d.ts +16 -1
  34. package/dist/installers/channel.js +143 -9
  35. package/dist/installers/channel.js.map +1 -1
  36. package/dist/installers/openclaw.d.ts +10 -2
  37. package/dist/installers/openclaw.js +140 -51
  38. package/dist/installers/openclaw.js.map +1 -1
  39. package/dist/installers/openviking-purge.d.ts +52 -0
  40. package/dist/installers/openviking-purge.js +380 -0
  41. package/dist/installers/openviking-purge.js.map +1 -0
  42. package/dist/installers/openviking.js +1 -2
  43. package/dist/installers/openviking.js.map +1 -1
  44. package/dist/installers/skill.d.ts +2 -0
  45. package/dist/installers/skill.js +35 -5
  46. package/dist/installers/skill.js.map +1 -1
  47. package/dist/migration/archive.d.ts +14 -0
  48. package/dist/migration/archive.js +84 -0
  49. package/dist/migration/archive.js.map +1 -0
  50. package/dist/migration/crypto.d.ts +16 -0
  51. package/dist/migration/crypto.js +56 -0
  52. package/dist/migration/crypto.js.map +1 -0
  53. package/dist/migration/manifest.d.ts +39 -0
  54. package/dist/migration/manifest.js +140 -0
  55. package/dist/migration/manifest.js.map +1 -0
  56. package/dist/openclaw-user-data.d.ts +66 -0
  57. package/dist/openclaw-user-data.js +283 -0
  58. package/dist/openclaw-user-data.js.map +1 -0
  59. package/dist/output/mode.d.ts +11 -0
  60. package/dist/output/mode.js +27 -0
  61. package/dist/output/mode.js.map +1 -0
  62. package/dist/output/ndjson.d.ts +57 -0
  63. package/dist/output/ndjson.js +136 -0
  64. package/dist/output/ndjson.js.map +1 -0
  65. package/dist/utils/constants.d.ts +8 -5
  66. package/dist/utils/constants.js +32 -7
  67. package/dist/utils/constants.js.map +1 -1
  68. package/dist/utils/deps.d.ts +34 -3
  69. package/dist/utils/deps.js +62 -100
  70. package/dist/utils/deps.js.map +1 -1
  71. package/dist/utils/logger.d.ts +10 -0
  72. package/dist/utils/logger.js +31 -4
  73. package/dist/utils/logger.js.map +1 -1
  74. package/dist/utils/mirror.js +14 -0
  75. package/dist/utils/mirror.js.map +1 -1
  76. package/dist/utils/openclaw-config-cli.d.ts +19 -0
  77. package/dist/utils/openclaw-config-cli.js +81 -0
  78. package/dist/utils/openclaw-config-cli.js.map +1 -0
  79. package/dist/utils/openclaw-daemon.d.ts +58 -0
  80. package/dist/utils/openclaw-daemon.js +154 -0
  81. package/dist/utils/openclaw-daemon.js.map +1 -0
  82. package/dist/utils/shell.d.ts +12 -2
  83. package/dist/utils/shell.js +80 -5
  84. package/dist/utils/shell.js.map +1 -1
  85. package/package.json +3 -2
@@ -0,0 +1 @@
1
+ {"version":3,"file":"archive.js","sourceRoot":"","sources":["../../src/migration/archive.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ export declare const AUTHENTICATED_ENCRYPTION_TOOL = "age";
2
+ export declare const AUTHENTICATED_ENCRYPTION_CONTRACT = "age-v1-X25519-ChaCha20Poly1305";
3
+ export declare function buildAgeEncryptArgs(keyFile: string, inputPath: string, outputPath: string): string[];
4
+ export declare function buildAgeDecryptArgs(keyFile: string, inputPath: string, outputPath: string): string[];
5
+ export declare function buildAgeCommand(args: string[]): string;
6
+ export declare function assertAuthenticatedEncryptionAvailable(): Promise<void>;
7
+ export declare function quoteShellArg(value: string): string;
8
+ /**
9
+ * export 用 `--recipient-file`,必须是 age 公钥;若误传私钥(identity),age 会在运行期才报错。
10
+ * 提前在 CLI 层显式校验,避免操作人把私钥当公钥用。
11
+ */
12
+ export declare function assertAgeRecipientContent(content: string, keyFile: string): void;
13
+ /**
14
+ * restore 用 `--identity`,必须是 age 私钥;若误传只含公钥的文件,提前报错而不是等 age 运行期失败。
15
+ */
16
+ export declare function assertAgeIdentityContent(content: string, keyFile: string): void;
@@ -0,0 +1,56 @@
1
+ import { commandExists } from '../utils/shell.js';
2
+ export const AUTHENTICATED_ENCRYPTION_TOOL = 'age';
3
+ export const AUTHENTICATED_ENCRYPTION_CONTRACT = 'age-v1-X25519-ChaCha20Poly1305';
4
+ export function buildAgeEncryptArgs(keyFile, inputPath, outputPath) {
5
+ return [
6
+ '--encrypt',
7
+ '--recipient-file',
8
+ keyFile,
9
+ '--output',
10
+ outputPath,
11
+ inputPath,
12
+ ];
13
+ }
14
+ export function buildAgeDecryptArgs(keyFile, inputPath, outputPath) {
15
+ return [
16
+ '--decrypt',
17
+ '--identity',
18
+ keyFile,
19
+ '--output',
20
+ outputPath,
21
+ inputPath,
22
+ ];
23
+ }
24
+ export function buildAgeCommand(args) {
25
+ return [AUTHENTICATED_ENCRYPTION_TOOL, ...args.map(quoteShellArg)].join(' ');
26
+ }
27
+ export async function assertAuthenticatedEncryptionAvailable() {
28
+ if (!await commandExists(AUTHENTICATED_ENCRYPTION_TOOL)) {
29
+ throw new Error('Missing authenticated encryption tool: age');
30
+ }
31
+ }
32
+ export function quoteShellArg(value) {
33
+ return `'${value.replace(/'/g, `'\\''`)}'`;
34
+ }
35
+ const AGE_SECRET_KEY_MARKER = /AGE-SECRET-KEY-/;
36
+ const OPENSSH_PRIVATE_KEY_MARKER = /BEGIN OPENSSH PRIVATE KEY/;
37
+ const AGE_RECIPIENT_MARKER = /(^|\n)\s*age1[0-9a-z]/;
38
+ /**
39
+ * export 用 `--recipient-file`,必须是 age 公钥;若误传私钥(identity),age 会在运行期才报错。
40
+ * 提前在 CLI 层显式校验,避免操作人把私钥当公钥用。
41
+ */
42
+ export function assertAgeRecipientContent(content, keyFile) {
43
+ if (AGE_SECRET_KEY_MARKER.test(content)) {
44
+ throw new Error(`--key-file 应为 age 公钥(recipient)文件,但 ${keyFile} 含 age 私钥;export 加密只需公钥`);
45
+ }
46
+ }
47
+ /**
48
+ * restore 用 `--identity`,必须是 age 私钥;若误传只含公钥的文件,提前报错而不是等 age 运行期失败。
49
+ */
50
+ export function assertAgeIdentityContent(content, keyFile) {
51
+ const hasIdentity = AGE_SECRET_KEY_MARKER.test(content) || OPENSSH_PRIVATE_KEY_MARKER.test(content);
52
+ if (!hasIdentity && AGE_RECIPIENT_MARKER.test(content)) {
53
+ throw new Error(`--key-file 应为 age 私钥(identity)文件,但 ${keyFile} 仅含 age 公钥;restore 解密需要私钥`);
54
+ }
55
+ }
56
+ //# sourceMappingURL=crypto.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crypto.js","sourceRoot":"","sources":["../../src/migration/crypto.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAElD,MAAM,CAAC,MAAM,6BAA6B,GAAG,KAAK,CAAC;AACnD,MAAM,CAAC,MAAM,iCAAiC,GAAG,gCAAgC,CAAC;AAElF,MAAM,UAAU,mBAAmB,CAAC,OAAe,EAAE,SAAiB,EAAE,UAAkB;IACxF,OAAO;QACL,WAAW;QACX,kBAAkB;QAClB,OAAO;QACP,UAAU;QACV,UAAU;QACV,SAAS;KACV,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,OAAe,EAAE,SAAiB,EAAE,UAAkB;IACxF,OAAO;QACL,WAAW;QACX,YAAY;QACZ,OAAO;QACP,UAAU;QACV,UAAU;QACV,SAAS;KACV,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,IAAc;IAC5C,OAAO,CAAC,6BAA6B,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC/E,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,sCAAsC;IAC1D,IAAI,CAAC,MAAM,aAAa,CAAC,6BAA6B,CAAC,EAAE,CAAC;QACxD,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC;IAChE,CAAC;AACH,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,KAAa;IACzC,OAAO,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC;AAC7C,CAAC;AAED,MAAM,qBAAqB,GAAG,iBAAiB,CAAC;AAChD,MAAM,0BAA0B,GAAG,2BAA2B,CAAC;AAC/D,MAAM,oBAAoB,GAAG,uBAAuB,CAAC;AAErD;;;GAGG;AACH,MAAM,UAAU,yBAAyB,CAAC,OAAe,EAAE,OAAe;IACxE,IAAI,qBAAqB,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QACxC,MAAM,IAAI,KAAK,CAAC,uCAAuC,OAAO,yBAAyB,CAAC,CAAC;IAC3F,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,wBAAwB,CAAC,OAAe,EAAE,OAAe;IACvE,MAAM,WAAW,GAAG,qBAAqB,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,0BAA0B,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACpG,IAAI,CAAC,WAAW,IAAI,oBAAoB,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QACvD,MAAM,IAAI,KAAK,CAAC,sCAAsC,OAAO,2BAA2B,CAAC,CAAC;IAC5F,CAAC;AACH,CAAC"}
@@ -0,0 +1,39 @@
1
+ export declare const MIGRATION_MANIFEST_VERSION = "openclaw-runtime-v1";
2
+ export declare const LEGACY_OPENCLAW_WORKSPACE = "/root/openclaw/workspace";
3
+ export declare const includePaths: string[];
4
+ export declare const excludePatterns: string[];
5
+ export declare const requiredRuntimeFiles: string[];
6
+ export interface MigrationManifestPath {
7
+ path: string;
8
+ status: 'included' | 'missing';
9
+ type?: 'file' | 'directory' | 'symlink' | 'other';
10
+ mode?: number;
11
+ uid?: number;
12
+ gid?: number;
13
+ }
14
+ export interface MigrationManifest {
15
+ version: typeof MIGRATION_MANIFEST_VERSION;
16
+ createdAt: string;
17
+ taskId: string;
18
+ shrimpId: string;
19
+ sourceHostId: string;
20
+ targetHostId: string;
21
+ includePaths: string[];
22
+ excludePatterns: string[];
23
+ requiredRuntimeFiles: string[];
24
+ missingPaths: string[];
25
+ paths: MigrationManifestPath[];
26
+ }
27
+ export interface MigrationIdentity {
28
+ taskId: string;
29
+ shrimpId: string;
30
+ sourceHostId: string;
31
+ targetHostId: string;
32
+ }
33
+ export interface BuildManifestOptions extends MigrationIdentity {
34
+ rootDir?: string;
35
+ createdAt?: string;
36
+ }
37
+ export declare function buildMigrationManifest(options: BuildManifestOptions): MigrationManifest;
38
+ export declare function existingManifestPaths(manifest: MigrationManifest): string[];
39
+ export declare function validateMigrationManifest(value: unknown, expected: MigrationIdentity): MigrationManifest;
@@ -0,0 +1,140 @@
1
+ import { existsSync, lstatSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ import { OKCLAW_BACKUP_DIR, OKCLAW_CONFIG_DIR, OPENCLAW_HOME, OPENCLAW_WORKSPACE, OPENVIKING_HOME, } from '../utils/constants.js';
4
+ export const MIGRATION_MANIFEST_VERSION = 'openclaw-runtime-v1';
5
+ export const LEGACY_OPENCLAW_WORKSPACE = '/root/openclaw/workspace';
6
+ export const includePaths = [
7
+ OPENCLAW_HOME,
8
+ OPENCLAW_WORKSPACE,
9
+ LEGACY_OPENCLAW_WORKSPACE,
10
+ OKCLAW_CONFIG_DIR,
11
+ OKCLAW_BACKUP_DIR,
12
+ OPENVIKING_HOME,
13
+ ];
14
+ export const excludePatterns = [
15
+ '**/*.sock',
16
+ '**/*.pid',
17
+ '**/*.lock',
18
+ '**/tmp/**',
19
+ '**/.cache/**',
20
+ '**/node_modules/.cache/**',
21
+ ];
22
+ export const requiredRuntimeFiles = [
23
+ `${OPENCLAW_HOME}/openclaw.json`,
24
+ ];
25
+ export function buildMigrationManifest(options) {
26
+ const rootDir = options.rootDir ?? '/';
27
+ const missingCritical = requiredRuntimeFiles.filter((path) => !existsSync(toHostPath(rootDir, path)));
28
+ if (missingCritical.length > 0) {
29
+ throw new Error(`Missing critical runtime file: ${missingCritical.join(', ')}`);
30
+ }
31
+ const paths = includePaths.map((path) => {
32
+ const hostPath = toHostPath(rootDir, path);
33
+ if (!existsSync(hostPath)) {
34
+ return { path, status: 'missing' };
35
+ }
36
+ const stat = lstatSync(hostPath);
37
+ return {
38
+ path,
39
+ status: 'included',
40
+ type: stat.isDirectory() ? 'directory' : stat.isFile() ? 'file' : stat.isSymbolicLink() ? 'symlink' : 'other',
41
+ mode: stat.mode,
42
+ uid: stat.uid,
43
+ gid: stat.gid,
44
+ };
45
+ });
46
+ return {
47
+ version: MIGRATION_MANIFEST_VERSION,
48
+ createdAt: options.createdAt ?? new Date().toISOString(),
49
+ taskId: options.taskId,
50
+ shrimpId: options.shrimpId,
51
+ sourceHostId: options.sourceHostId,
52
+ targetHostId: options.targetHostId,
53
+ includePaths: [...includePaths],
54
+ excludePatterns: [...excludePatterns],
55
+ requiredRuntimeFiles: [...requiredRuntimeFiles],
56
+ missingPaths: paths.filter((item) => item.status === 'missing').map((item) => item.path),
57
+ paths,
58
+ };
59
+ }
60
+ export function existingManifestPaths(manifest) {
61
+ return manifest.paths.filter((item) => item.status === 'included').map((item) => item.path);
62
+ }
63
+ export function validateMigrationManifest(value, expected) {
64
+ if (!isManifest(value)) {
65
+ throw new Error('Invalid migration manifest');
66
+ }
67
+ if (value.version !== MIGRATION_MANIFEST_VERSION) {
68
+ throw new Error(`Unsupported manifest version: ${value.version}`);
69
+ }
70
+ assertEqual('taskId', value.taskId, expected.taskId);
71
+ assertEqual('shrimpId', value.shrimpId, expected.shrimpId);
72
+ assertEqual('sourceHostId', value.sourceHostId, expected.sourceHostId);
73
+ assertEqual('targetHostId', value.targetHostId, expected.targetHostId);
74
+ /*
75
+ * Restore cannot trust the archive's manifest to define its own allowed roots.
76
+ * The tar safety check extracts to /, so a malicious package that declares /etc
77
+ * as an included path would otherwise turn the manifest into an allow-list bypass.
78
+ * Keep the manifest useful for audit, but require every path list to match the
79
+ * hard-coded runtime contract compiled into this CLI version.
80
+ */
81
+ assertStringArrayEqual('includePaths', value.includePaths, includePaths);
82
+ assertStringArrayEqual('excludePatterns', value.excludePatterns, excludePatterns);
83
+ assertStringArrayEqual('requiredRuntimeFiles', value.requiredRuntimeFiles, requiredRuntimeFiles);
84
+ validateManifestPathSet(value);
85
+ return value;
86
+ }
87
+ function assertEqual(field, actual, expected) {
88
+ if (actual !== expected) {
89
+ throw new Error(`Manifest ${field} mismatch: expected ${expected}, got ${actual}`);
90
+ }
91
+ }
92
+ function isManifest(value) {
93
+ if (typeof value !== 'object' || value === null)
94
+ return false;
95
+ const candidate = value;
96
+ return typeof candidate.version === 'string'
97
+ && typeof candidate.taskId === 'string'
98
+ && typeof candidate.shrimpId === 'string'
99
+ && typeof candidate.sourceHostId === 'string'
100
+ && typeof candidate.targetHostId === 'string'
101
+ && Array.isArray(candidate.includePaths)
102
+ && Array.isArray(candidate.excludePatterns)
103
+ && Array.isArray(candidate.requiredRuntimeFiles)
104
+ && Array.isArray(candidate.missingPaths)
105
+ && Array.isArray(candidate.paths);
106
+ }
107
+ function assertStringArrayEqual(field, actual, expected) {
108
+ if (!Array.isArray(actual) || actual.length !== expected.length
109
+ || actual.some((item, index) => item !== expected[index])) {
110
+ throw new Error(`Manifest ${field} does not match CLI runtime contract`);
111
+ }
112
+ }
113
+ function validateManifestPathSet(manifest) {
114
+ const allowed = new Set(includePaths);
115
+ const seen = new Set();
116
+ const missing = new Set();
117
+ for (const item of manifest.paths) {
118
+ if (!item || typeof item.path !== 'string' || !allowed.has(item.path)) {
119
+ throw new Error(`Manifest path outside CLI runtime contract: ${item?.path ?? '<invalid>'}`);
120
+ }
121
+ if (seen.has(item.path)) {
122
+ throw new Error(`Manifest path duplicated: ${item.path}`);
123
+ }
124
+ seen.add(item.path);
125
+ if (item.status !== 'included' && item.status !== 'missing') {
126
+ throw new Error(`Manifest path has invalid status: ${item.path}`);
127
+ }
128
+ if (item.status === 'missing') {
129
+ missing.add(item.path);
130
+ }
131
+ }
132
+ if (manifest.missingPaths.length !== missing.size
133
+ || manifest.missingPaths.some((path) => !missing.has(path))) {
134
+ throw new Error('Manifest missingPaths does not match path statuses');
135
+ }
136
+ }
137
+ function toHostPath(rootDir, absolutePath) {
138
+ return join(rootDir, absolutePath.replace(/^\/+/, ''));
139
+ }
140
+ //# sourceMappingURL=manifest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manifest.js","sourceRoot":"","sources":["../../src/migration/manifest.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,66 @@
1
+ export declare const OPENCLAW_USER_DATA_FILES: readonly ["MEMORY.md", "USER.md", "IDENTITY.md", "SOUL.md", "TOOLS.md", "AGENTS.md", "HEARTBEAT.md"];
2
+ export declare const LEGACY_OPENCLAW_WORKSPACE = "/root/openclaw/workspace";
3
+ export type BackupFs = {
4
+ existsSync(path: string): boolean;
5
+ mkdirSync(path: string, options?: {
6
+ recursive?: boolean;
7
+ }): unknown;
8
+ cpSync(src: string, dest: string, options?: {
9
+ recursive?: boolean;
10
+ }): unknown;
11
+ statSync(path: string): {
12
+ isDirectory(): boolean;
13
+ };
14
+ };
15
+ export type ArchiveFs = BackupFs & {
16
+ readdirSync(path: string, options?: {
17
+ withFileTypes?: boolean;
18
+ }): Array<DirentLike>;
19
+ };
20
+ export type RestoreFs = BackupFs & {
21
+ rmSync(path: string, options?: {
22
+ recursive?: boolean;
23
+ force?: boolean;
24
+ }): unknown;
25
+ chmodSync(path: string, mode: number): unknown;
26
+ lstatSync(path: string): {
27
+ isSymbolicLink(): boolean;
28
+ };
29
+ readdirSync(path: string, options?: {
30
+ withFileTypes?: boolean;
31
+ }): Array<DirentLike>;
32
+ };
33
+ type DirentLike = {
34
+ name: string;
35
+ isDirectory(): boolean;
36
+ isFile(): boolean;
37
+ };
38
+ export type ArchiveResult = {
39
+ backupDir: string | null;
40
+ archivePath: string | null;
41
+ includedFiles: string[];
42
+ };
43
+ export type RestoreResult = {
44
+ stagingDir: string;
45
+ archivePath: string;
46
+ restoredFiles: string[];
47
+ };
48
+ type ShellOps = {
49
+ shell(command: string): Promise<void>;
50
+ capture?(command: string): Promise<string>;
51
+ };
52
+ export declare function formatBackupTimestamp(now: Date): string;
53
+ export declare function backupOpenclawUserData(now?: Date, fsOps?: BackupFs): string | null;
54
+ export declare function createOpenclawUserDataArchive(options?: {
55
+ archivePath?: string;
56
+ now?: Date;
57
+ fsOps?: ArchiveFs;
58
+ shellOps?: ShellOps;
59
+ }): Promise<ArchiveResult>;
60
+ export declare function restoreOpenclawUserDataArchive(options: {
61
+ archivePath: string;
62
+ now?: Date;
63
+ fsOps?: RestoreFs;
64
+ shellOps?: ShellOps;
65
+ }): Promise<RestoreResult>;
66
+ export {};
@@ -0,0 +1,283 @@
1
+ import { existsSync, cpSync, mkdirSync, rmSync, statSync, lstatSync, chmodSync, readdirSync, } from 'node:fs';
2
+ import { posix as pathPosix } from 'node:path';
3
+ import { shell, shellCapture } from './utils/shell.js';
4
+ import { OKCLAW_BACKUP_DIR, OPENCLAW_WORKSPACE } from './utils/constants.js';
5
+ export const OPENCLAW_USER_DATA_FILES = [
6
+ 'MEMORY.md',
7
+ 'USER.md',
8
+ 'IDENTITY.md',
9
+ 'SOUL.md',
10
+ 'TOOLS.md',
11
+ 'AGENTS.md',
12
+ 'HEARTBEAT.md',
13
+ ];
14
+ export const LEGACY_OPENCLAW_WORKSPACE = '/root/openclaw/workspace';
15
+ const WORKSPACE_BACKUP_DIR = 'workspace';
16
+ const LEGACY_WORKSPACE_BACKUP_DIR = 'workspace-root-openclaw';
17
+ const SKILLS_DIR = 'skills';
18
+ const OPENCLAW_CONFIG_FILE = 'openclaw.json';
19
+ const realBackupFs = { existsSync, mkdirSync, cpSync, statSync };
20
+ const realArchiveFs = { ...realBackupFs, readdirSync: readdirSync };
21
+ const realRestoreFs = {
22
+ ...realBackupFs,
23
+ rmSync,
24
+ chmodSync,
25
+ lstatSync,
26
+ readdirSync: readdirSync,
27
+ };
28
+ export function formatBackupTimestamp(now) {
29
+ return now.toISOString().replace(/\.\d{3}Z$/, 'Z').replace(/:/g, '');
30
+ }
31
+ function copyIfExists(fsOps, src, dest, recursive = false) {
32
+ if (!fsOps.existsSync(src))
33
+ return false;
34
+ fsOps.cpSync(src, dest, recursive ? { recursive: true } : undefined);
35
+ return true;
36
+ }
37
+ export function backupOpenclawUserData(now = new Date(), fsOps = realBackupFs) {
38
+ const backupDir = `${OKCLAW_BACKUP_DIR}/openclaw-user-data-${formatBackupTimestamp(now)}`;
39
+ const workspaces = Array.from(new Set([OPENCLAW_WORKSPACE, LEGACY_OPENCLAW_WORKSPACE]));
40
+ let copiedItems = 0;
41
+ let copiedWorkspaces = 0;
42
+ for (const workspace of workspaces) {
43
+ if (!fsOps.existsSync(workspace))
44
+ continue;
45
+ const workspaceBackupName = copiedWorkspaces === 0 ? WORKSPACE_BACKUP_DIR : LEGACY_WORKSPACE_BACKUP_DIR;
46
+ const workspaceBackupDir = `${backupDir}/${workspaceBackupName}`;
47
+ let workspaceDirCreated = false;
48
+ const ensureWorkspaceBackupDir = () => {
49
+ if (workspaceDirCreated)
50
+ return;
51
+ fsOps.mkdirSync(workspaceBackupDir, { recursive: true });
52
+ workspaceDirCreated = true;
53
+ };
54
+ for (const file of OPENCLAW_USER_DATA_FILES) {
55
+ const src = `${workspace}/${file}`;
56
+ if (!fsOps.existsSync(src))
57
+ continue;
58
+ ensureWorkspaceBackupDir();
59
+ if (copyIfExists(fsOps, src, `${workspaceBackupDir}/${file}`)) {
60
+ copiedItems += 1;
61
+ }
62
+ }
63
+ const skillsDir = `${workspace}/${SKILLS_DIR}`;
64
+ if (fsOps.existsSync(skillsDir) && fsOps.statSync(skillsDir).isDirectory()) {
65
+ ensureWorkspaceBackupDir();
66
+ if (copyIfExists(fsOps, skillsDir, `${workspaceBackupDir}/${SKILLS_DIR}`, true)) {
67
+ copiedItems += 1;
68
+ }
69
+ }
70
+ if (workspaceDirCreated) {
71
+ copiedWorkspaces += 1;
72
+ }
73
+ }
74
+ return copiedItems > 0 ? backupDir : null;
75
+ }
76
+ export async function createOpenclawUserDataArchive(options = {}) {
77
+ const now = options.now ?? new Date();
78
+ const fsOps = options.fsOps ?? realArchiveFs;
79
+ const shellOps = options.shellOps ?? { shell };
80
+ const backupDir = backupOpenclawUserData(now, fsOps);
81
+ if (!backupDir) {
82
+ return { backupDir: null, archivePath: null, includedFiles: [] };
83
+ }
84
+ const includedFiles = listRelativeFiles(fsOps, backupDir);
85
+ validateArchiveEntries(includedFiles);
86
+ const archivePath = options.archivePath ?? `/tmp/openclaw-user-data-${formatBackupTimestamp(now)}.tar.gz`;
87
+ try {
88
+ await shellOps.shell(`tar -czf ${shellSingleQuote(archivePath)} -C ${shellSingleQuote(backupDir)} .`);
89
+ }
90
+ catch (error) {
91
+ attachContext(error, { backupDir, archivePath });
92
+ throw error;
93
+ }
94
+ return { backupDir, archivePath, includedFiles };
95
+ }
96
+ export async function restoreOpenclawUserDataArchive(options) {
97
+ const now = options.now ?? new Date();
98
+ const fsOps = options.fsOps ?? realRestoreFs;
99
+ const shellOps = options.shellOps ?? { shell };
100
+ const stagingDir = `/tmp/openclaw-user-data-restore-${formatBackupTimestamp(now)}`;
101
+ try {
102
+ fsOps.rmSync(stagingDir, { recursive: true, force: true });
103
+ fsOps.mkdirSync(stagingDir, { recursive: true });
104
+ const tarEntries = await listArchiveEntries(shellOps, options.archivePath);
105
+ validateArchiveEntries(tarEntries.map((entry) => entry.path));
106
+ validateArchiveEntryTypes(tarEntries);
107
+ await shellOps.shell(`tar -xzf ${shellSingleQuote(options.archivePath)} -C ${shellSingleQuote(stagingDir)}`);
108
+ const entries = listRelativeFiles(fsOps, stagingDir);
109
+ validateArchiveEntries(entries);
110
+ fsOps.mkdirSync(OPENCLAW_WORKSPACE, { recursive: true });
111
+ fsOps.chmodSync(OPENCLAW_WORKSPACE, 0o755);
112
+ const restored = new Set();
113
+ restoreWorkspaceBackup(fsOps, `${stagingDir}/${WORKSPACE_BACKUP_DIR}`, restored);
114
+ restoreWorkspaceBackup(fsOps, `${stagingDir}/${LEGACY_WORKSPACE_BACKUP_DIR}`, restored);
115
+ const restoredFiles = Array.from(restored).sort();
116
+ for (const file of restoredFiles) {
117
+ const path = `${OPENCLAW_WORKSPACE}/${file}`;
118
+ if (file === SKILLS_DIR) {
119
+ applyRestoredPermissions(fsOps, path);
120
+ }
121
+ else {
122
+ fsOps.chmodSync(path, 0o644);
123
+ }
124
+ }
125
+ await shellOps.shell(`chown -R root:root ${shellSingleQuote(OPENCLAW_WORKSPACE)}`);
126
+ return { stagingDir, archivePath: options.archivePath, restoredFiles };
127
+ }
128
+ catch (error) {
129
+ attachContext(error, { stagingDir, archivePath: options.archivePath });
130
+ throw error;
131
+ }
132
+ }
133
+ async function listArchiveEntries(shellOps, archivePath) {
134
+ if (shellOps.capture) {
135
+ const stdout = await shellOps.capture(`tar -tvzf ${shellSingleQuote(archivePath)}`);
136
+ return parseTarVerboseEntries(stdout);
137
+ }
138
+ const result = await shellCapture(`tar -tvzf ${shellSingleQuote(archivePath)}`);
139
+ if (result.code !== 0) {
140
+ throw new Error(`Command failed (exit ${result.code}): tar -tvzf ${archivePath}`);
141
+ }
142
+ return parseTarVerboseEntries(result.stdout);
143
+ }
144
+ function parseTarVerboseEntries(stdout) {
145
+ return stdout.split(/\r?\n/)
146
+ .map((line) => line.trim())
147
+ .filter(Boolean)
148
+ .map((line) => {
149
+ const modeType = line[0];
150
+ const tokens = line.split(/\s+/);
151
+ const rawPath = tokens.slice(5).join(' ');
152
+ const linkIndex = rawPath.indexOf(' -> ');
153
+ const path = linkIndex >= 0 ? rawPath.slice(0, linkIndex) : rawPath;
154
+ const linkTarget = linkIndex >= 0 ? rawPath.slice(linkIndex + ' -> '.length) : undefined;
155
+ const type = modeType === '-' ? 'file'
156
+ : modeType === 'd' ? 'directory'
157
+ : modeType === 'l' ? 'symlink'
158
+ : 'unsupported';
159
+ return { type, path, linkTarget, raw: line };
160
+ });
161
+ }
162
+ function validateArchiveEntryTypes(entries) {
163
+ for (const entry of entries) {
164
+ if (entry.type === 'unsupported') {
165
+ throw new Error(`unsupported archive entry type: ${entry.raw}`);
166
+ }
167
+ // 备份会把 skills 目录整包打进归档,其中的 node_modules/.bin/* 是符号链接。
168
+ // 放行指向 workspace 内部的软链(迁移需要它们原样还原),仍拒绝逃逸到 workspace 之外的软链。
169
+ if (entry.type === 'symlink') {
170
+ assertSymlinkWithinWorkspace(entry);
171
+ }
172
+ }
173
+ }
174
+ function assertSymlinkWithinWorkspace(entry) {
175
+ const relative = workspaceRelativePath(entry.path);
176
+ const target = entry.linkTarget ?? '';
177
+ if (relative === null || !target) {
178
+ throw new Error(`unsafe archive symlink: ${entry.raw}`);
179
+ }
180
+ const linkDir = pathPosix.dirname(`${OPENCLAW_WORKSPACE}/${relative}`);
181
+ const resolvedTarget = target.startsWith('/')
182
+ ? pathPosix.normalize(target)
183
+ : pathPosix.normalize(pathPosix.join(linkDir, target));
184
+ if (resolvedTarget !== OPENCLAW_WORKSPACE && !resolvedTarget.startsWith(`${OPENCLAW_WORKSPACE}/`)) {
185
+ throw new Error(`unsafe archive symlink target: ${entry.raw}`);
186
+ }
187
+ }
188
+ function workspaceRelativePath(entryPath) {
189
+ const normalized = normalizeArchiveEntry(entryPath);
190
+ for (const prefix of [WORKSPACE_BACKUP_DIR, LEGACY_WORKSPACE_BACKUP_DIR]) {
191
+ if (normalized === prefix)
192
+ return '';
193
+ if (normalized.startsWith(`${prefix}/`))
194
+ return normalized.slice(prefix.length + 1);
195
+ }
196
+ return null;
197
+ }
198
+ function restoreWorkspaceBackup(fsOps, backupWorkspaceDir, restored) {
199
+ if (!fsOps.existsSync(backupWorkspaceDir))
200
+ return;
201
+ for (const file of OPENCLAW_USER_DATA_FILES) {
202
+ if (restored.has(file))
203
+ continue;
204
+ const src = `${backupWorkspaceDir}/${file}`;
205
+ if (!fsOps.existsSync(src))
206
+ continue;
207
+ fsOps.cpSync(src, `${OPENCLAW_WORKSPACE}/${file}`);
208
+ restored.add(file);
209
+ }
210
+ const skillsSrc = `${backupWorkspaceDir}/${SKILLS_DIR}`;
211
+ if (!restored.has(SKILLS_DIR) && fsOps.existsSync(skillsSrc) && fsOps.statSync(skillsSrc).isDirectory()) {
212
+ fsOps.rmSync(`${OPENCLAW_WORKSPACE}/${SKILLS_DIR}`, { recursive: true, force: true });
213
+ fsOps.cpSync(skillsSrc, `${OPENCLAW_WORKSPACE}/${SKILLS_DIR}`, { recursive: true });
214
+ restored.add(SKILLS_DIR);
215
+ }
216
+ }
217
+ function applyRestoredPermissions(fsOps, path) {
218
+ if (!fsOps.existsSync(path))
219
+ return;
220
+ // 不跟随符号链接:软链自身权限在 Linux 上无意义,跟随会 chmod 到 target,
221
+ // 且指向祖先目录的 workspace 内软链(如 skills/loop -> skills)会让 statSync+readdir 递归死循环。
222
+ if (fsOps.lstatSync(path).isSymbolicLink())
223
+ return;
224
+ if (fsOps.statSync(path).isDirectory()) {
225
+ fsOps.chmodSync(path, 0o755);
226
+ for (const entry of fsOps.readdirSync(path, { withFileTypes: true })) {
227
+ applyRestoredPermissions(fsOps, `${path}/${entry.name}`);
228
+ }
229
+ return;
230
+ }
231
+ fsOps.chmodSync(path, 0o644);
232
+ }
233
+ function listRelativeFiles(fsOps, root) {
234
+ if (!fsOps.existsSync(root))
235
+ return [];
236
+ const files = [];
237
+ const visit = (dir, prefix) => {
238
+ for (const entry of fsOps.readdirSync(dir, { withFileTypes: true })) {
239
+ const relative = prefix ? `${prefix}/${entry.name}` : entry.name;
240
+ const path = `${dir}/${entry.name}`;
241
+ if (entry.isDirectory()) {
242
+ visit(path, relative);
243
+ }
244
+ else if (entry.isFile()) {
245
+ files.push(relative);
246
+ }
247
+ }
248
+ };
249
+ visit(root, '');
250
+ return files.sort();
251
+ }
252
+ function validateArchiveEntries(entries) {
253
+ for (const entry of entries) {
254
+ const normalized = normalizeArchiveEntry(entry);
255
+ if (!normalized)
256
+ continue;
257
+ const parts = normalized.split('/');
258
+ if (entry.startsWith('/') ||
259
+ parts.includes('..') ||
260
+ parts.includes(OPENCLAW_CONFIG_FILE)) {
261
+ throw new Error(`unsafe archive entry: ${entry}`);
262
+ }
263
+ }
264
+ }
265
+ function normalizeArchiveEntry(entry) {
266
+ let normalized = entry.trim();
267
+ while (normalized.startsWith('./')) {
268
+ normalized = normalized.slice(2);
269
+ }
270
+ while (normalized.endsWith('/')) {
271
+ normalized = normalized.slice(0, -1);
272
+ }
273
+ return normalized === '.' ? '' : normalized;
274
+ }
275
+ function shellSingleQuote(value) {
276
+ return `'${value.replace(/'/g, `'\\''`)}'`;
277
+ }
278
+ function attachContext(error, context) {
279
+ if (error && typeof error === 'object') {
280
+ Object.assign(error, context);
281
+ }
282
+ }
283
+ //# sourceMappingURL=openclaw-user-data.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openclaw-user-data.js","sourceRoot":"","sources":["../src/openclaw-user-data.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * CLI 输出模式全局状态。index.ts 解析 --output / --op-id 后注入;
3
+ * ndjson.ts 与 logger.ts 读取以决定行为。
4
+ */
5
+ export type OutputMode = 'text' | 'ndjson';
6
+ export declare function setOutputMode(mode: OutputMode, opId?: string): void;
7
+ export declare function setNdjsonPath(path: string | undefined): void;
8
+ export declare function getOutputMode(): OutputMode;
9
+ export declare function getOpId(): string | undefined;
10
+ export declare function getNdjsonPath(): string | undefined;
11
+ export declare function isNdjson(): boolean;