jishushell 0.4.2 → 0.4.10
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/Dockerfile.openclaw-slim +58 -0
- package/INSTALL-NOTICE +47 -0
- package/dist/auth.js +3 -3
- package/dist/auth.js.map +1 -1
- package/dist/cli.js +517 -1
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +21 -4
- package/dist/config.js +88 -54
- package/dist/config.js.map +1 -1
- package/dist/control.js +5 -5
- package/dist/control.js.map +1 -1
- package/dist/doctor.js +47 -14
- package/dist/doctor.js.map +1 -1
- package/dist/install.d.ts +1 -1
- package/dist/install.js +15 -29
- package/dist/install.js.map +1 -1
- package/dist/routes/backup.d.ts +2 -0
- package/dist/routes/backup.js +370 -0
- package/dist/routes/backup.js.map +1 -0
- package/dist/routes/instances.d.ts +1 -0
- package/dist/routes/instances.js +51 -11
- package/dist/routes/instances.js.map +1 -1
- package/dist/routes/setup.js +3 -5
- package/dist/routes/setup.js.map +1 -1
- package/dist/server.js +29 -1
- package/dist/server.js.map +1 -1
- package/dist/services/backup-manager.d.ts +253 -0
- package/dist/services/backup-manager.js +2014 -0
- package/dist/services/backup-manager.js.map +1 -0
- package/dist/services/backup-verify.d.ts +26 -0
- package/dist/services/backup-verify.js +240 -0
- package/dist/services/backup-verify.js.map +1 -0
- package/dist/services/instance-manager.d.ts +24 -4
- package/dist/services/instance-manager.js +218 -49
- package/dist/services/instance-manager.js.map +1 -1
- package/dist/services/nomad-manager.js +72 -131
- package/dist/services/nomad-manager.js.map +1 -1
- package/dist/services/process-manager.js +4 -3
- package/dist/services/process-manager.js.map +1 -1
- package/dist/services/setup-manager.d.ts +4 -2
- package/dist/services/setup-manager.js +268 -129
- package/dist/services/setup-manager.js.map +1 -1
- package/dist/services/telemetry/activation.js +10 -7
- package/dist/services/telemetry/activation.js.map +1 -1
- package/dist/services/telemetry/client.js +7 -18
- package/dist/services/telemetry/client.js.map +1 -1
- package/dist/services/telemetry/heartbeat.js +12 -6
- package/dist/services/telemetry/heartbeat.js.map +1 -1
- package/dist/utils/fs.d.ts +85 -0
- package/dist/utils/fs.js +111 -0
- package/dist/utils/fs.js.map +1 -0
- package/dist/utils/safe-json.d.ts +2 -0
- package/dist/utils/safe-json.js +22 -16
- package/dist/utils/safe-json.js.map +1 -1
- package/install/jishu-install-china.sh +3092 -0
- package/install/jishu-install.sh +310 -108
- package/install/jishu-uninstall.sh +276 -391
- package/install/post-install.sh +23 -0
- package/openclaw-entry.sh +15 -0
- package/package.json +7 -4
- package/public/assets/Dashboard-DhsrzJ4F.js +1 -0
- package/public/assets/{InitPassword-CkehIkJG.js → InitPassword-BjubiVdd.js} +1 -1
- package/public/assets/InstanceDetail-DMcywsof.js +17 -0
- package/public/assets/{Login-RkjzTNWg.js → Login-CUoEZOWR.js} +1 -1
- package/public/assets/NewInstance-Bk0G4EiJ.js +1 -0
- package/public/assets/Settings-D5tHL_h5.js +1 -0
- package/public/assets/Setup-4t6E3Rut.js +1 -0
- package/public/assets/index-BJ47MWpF.css +1 -0
- package/public/assets/index-DbX85irc.js +16 -0
- package/public/assets/logo-black-theme-DywLAtFy.png +0 -0
- package/public/assets/logo-white-theme-DXffFAWw.png +0 -0
- package/public/assets/{usePolling-CqQ8hrNc.js → usePolling-CK0DfI4h.js} +1 -1
- package/public/assets/{vendor-i18n-Bvxxh8Di.js → vendor-i18n-CfW0RvgE.js} +1 -1
- package/public/assets/vendor-react-B1-3Yrt-.js +59 -0
- package/public/index.html +4 -4
- package/public/assets/Dashboard-CAOQDYDR.js +0 -1
- package/public/assets/InstanceDetail-CzW2S95J.js +0 -14
- package/public/assets/NewInstance-DdbErdjA.js +0 -1
- package/public/assets/Settings-BUD7zwv9.js +0 -1
- package/public/assets/Setup-RRTIERGG.js +0 -1
- package/public/assets/index-77Ug7feY.css +0 -1
- package/public/assets/index-DfRnVUQR.js +0 -16
- package/public/assets/vendor-react-DONn7uBV.js +0 -59
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Encode an absolute filesystem path for use inside backup archives.
|
|
3
|
+
* Ported from OpenClaw official: encodeAbsolutePathForBackupArchive.
|
|
4
|
+
*/
|
|
5
|
+
export declare function encodeAbsolutePathForArchive(sourcePath: string): string;
|
|
6
|
+
export interface CallOpenclawBackupResult {
|
|
7
|
+
ok: boolean;
|
|
8
|
+
archivePath?: string;
|
|
9
|
+
error?: string;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Try to create a backup by calling the official `openclaw backup create` CLI.
|
|
13
|
+
* Returns ok:false if the binary is missing or the command fails.
|
|
14
|
+
*/
|
|
15
|
+
export declare function callOpenclawBackup(instanceId: string, outputDir: string, opts: {
|
|
16
|
+
onlyConfig?: boolean;
|
|
17
|
+
noWorkspace?: boolean;
|
|
18
|
+
}): Promise<CallOpenclawBackupResult>;
|
|
19
|
+
/** Ensure backup and tmp directories exist */
|
|
20
|
+
export declare function ensureBackupDirs(): void;
|
|
21
|
+
/**
|
|
22
|
+
* Get the per-instance export output directory (TMP_DIR/exports/<id>/).
|
|
23
|
+
* Exports live in an isolated subdirectory so the download route can enforce
|
|
24
|
+
* `:id` → file ownership and one instance's URL can't reach another's archive.
|
|
25
|
+
*/
|
|
26
|
+
export declare function getInstanceExportDir(instanceId: string): string;
|
|
27
|
+
/** Clean up stale tmp files older than 30 minutes. Call on startup and periodically. */
|
|
28
|
+
export declare function cleanupStaleTmpFiles(): number;
|
|
29
|
+
/** Start periodic tmp cleanup. Call once at server startup. */
|
|
30
|
+
export declare function startTmpCleanupScheduler(): void;
|
|
31
|
+
/** Stop the cleanup scheduler (for graceful shutdown). */
|
|
32
|
+
export declare function stopTmpCleanupScheduler(): void;
|
|
33
|
+
/** Get the backup directory for an instance (creates if needed) */
|
|
34
|
+
export declare function getInstanceBackupDir(instanceId: string): string;
|
|
35
|
+
/** List all backup files for an instance, sorted by mtime descending (newest first) */
|
|
36
|
+
export declare function listInstanceBackups(instanceId: string): Array<{
|
|
37
|
+
filename: string;
|
|
38
|
+
size: number;
|
|
39
|
+
created_at: string;
|
|
40
|
+
type: "auto-backup" | "manual-backup" | "pre-restore";
|
|
41
|
+
}>;
|
|
42
|
+
/** List all instance IDs that have backups (including orphans) */
|
|
43
|
+
export declare function listAllBackupInstanceIds(): string[];
|
|
44
|
+
/** Acquire an exclusive lock for an instance. Returns false if already locked. */
|
|
45
|
+
export declare function acquireInstanceLock(instanceId: string, operation: string): boolean;
|
|
46
|
+
/** Update heartbeat for a held lock. Call periodically during long operations. */
|
|
47
|
+
export declare function touchInstanceLock(instanceId: string): void;
|
|
48
|
+
/** Release the lock for an instance. */
|
|
49
|
+
export declare function releaseInstanceLock(instanceId: string): void;
|
|
50
|
+
/** Get current lock status for an instance (for status API). */
|
|
51
|
+
export declare function getInstanceLockStatus(instanceId: string): {
|
|
52
|
+
locked: boolean;
|
|
53
|
+
operation?: string;
|
|
54
|
+
} | null;
|
|
55
|
+
/** Start a heartbeat interval for long operations. Returns a cleanup function. */
|
|
56
|
+
export declare function startLockHeartbeat(instanceId: string, intervalMs?: number): () => void;
|
|
57
|
+
/** Check if instance is locked. Throws with 409 status if locked. */
|
|
58
|
+
export declare function assertNotLocked(instanceId: string): void;
|
|
59
|
+
/** Detect whether system tar is GNU or BSD. Cached after first call. */
|
|
60
|
+
export declare function detectTarVariant(): "gnu" | "bsd";
|
|
61
|
+
interface TarEntry {
|
|
62
|
+
type: string;
|
|
63
|
+
size: number;
|
|
64
|
+
path: string;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Pre-scan a tar.gz archive for security threats.
|
|
68
|
+
* Throws on: path traversal, symlinks, hardlinks, absolute paths, oversized.
|
|
69
|
+
*/
|
|
70
|
+
export declare function preScanArchive(archivePath: string): {
|
|
71
|
+
entries: TarEntry[];
|
|
72
|
+
totalSize: number;
|
|
73
|
+
};
|
|
74
|
+
/**
|
|
75
|
+
* Safely extract a tar.gz archive to destDir.
|
|
76
|
+
* Pre-scans for security threats, then extracts with safety flags.
|
|
77
|
+
*/
|
|
78
|
+
export declare function safeExtract(archivePath: string, destDir: string): Promise<{
|
|
79
|
+
entries: TarEntry[];
|
|
80
|
+
totalSize: number;
|
|
81
|
+
}>;
|
|
82
|
+
export interface PackResult {
|
|
83
|
+
filename: string;
|
|
84
|
+
filepath: string;
|
|
85
|
+
size: number;
|
|
86
|
+
manifest: Record<string, any>;
|
|
87
|
+
}
|
|
88
|
+
/** Create a manual or auto backup of an instance */
|
|
89
|
+
export declare function backupInstance(instanceId: string, opts?: {
|
|
90
|
+
includeSessions?: boolean;
|
|
91
|
+
includeWorkspace?: boolean;
|
|
92
|
+
onlyConfig?: boolean;
|
|
93
|
+
outputPath?: string;
|
|
94
|
+
type?: "manual-backup" | "auto-backup";
|
|
95
|
+
scope?: "state" | "home";
|
|
96
|
+
}): Promise<PackResult>;
|
|
97
|
+
export interface SelfPackOptions {
|
|
98
|
+
type: "manual-backup" | "auto-backup" | "pre-restore" | "export";
|
|
99
|
+
scope?: "state" | "home";
|
|
100
|
+
includeSessions?: boolean;
|
|
101
|
+
includeWorkspace?: boolean;
|
|
102
|
+
onlyConfig?: boolean;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Pack an instance in the official OpenClaw backup archive format.
|
|
106
|
+
* Layout: manifest.json at root + payload/<encoded-path>/.openclaw/...
|
|
107
|
+
* This is the fallback when `openclaw backup create` CLI is unavailable.
|
|
108
|
+
*/
|
|
109
|
+
export declare function selfPackOfficialFormat(instanceId: string, outputPath: string, opts: SelfPackOptions): Promise<PackResult>;
|
|
110
|
+
export interface RestoreResult {
|
|
111
|
+
ok: boolean;
|
|
112
|
+
warnings: string[];
|
|
113
|
+
api_key_status: "preserved" | "lost" | "not_applicable";
|
|
114
|
+
rolled_back?: boolean;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Restore an instance from a backup file.
|
|
118
|
+
* Full flow: lock -> extract -> validate -> pre-restore backup -> stop -> restore -> rebuild -> start -> healthcheck -> rollback on failure
|
|
119
|
+
*/
|
|
120
|
+
export declare function restoreInstance(instanceId: string, backupFilePath: string): Promise<RestoreResult>;
|
|
121
|
+
/**
|
|
122
|
+
* Create a new instance from a backup file.
|
|
123
|
+
* Does NOT copy model.env (new proxy token), provider.env (can't decrypt), or IM credentials.
|
|
124
|
+
* Hard rule: provider.env is always ignored — no decrypt attempt, no migration.
|
|
125
|
+
*/
|
|
126
|
+
export declare function createFromBackup(backupFilePath: string, opts: {
|
|
127
|
+
newId: string;
|
|
128
|
+
newName: string;
|
|
129
|
+
newDescription?: string;
|
|
130
|
+
}): Promise<{
|
|
131
|
+
ok: boolean;
|
|
132
|
+
instance_id: string;
|
|
133
|
+
warnings: string[];
|
|
134
|
+
}>;
|
|
135
|
+
/**
|
|
136
|
+
* Export an instance for sharing. Uses WHITELIST strategy — only safe directories included.
|
|
137
|
+
* API keys and credentials are stripped. Sensitive fields in openclaw.json are scrubbed.
|
|
138
|
+
*/
|
|
139
|
+
export declare function exportInstance(instanceId: string, opts?: {
|
|
140
|
+
includeSessions?: boolean;
|
|
141
|
+
outputPath?: string;
|
|
142
|
+
}): Promise<PackResult>;
|
|
143
|
+
/** Step 1: Store uploaded file to tmp. Returns temp_id for subsequent calls. */
|
|
144
|
+
export declare function storeUpload(filePath: string): Promise<{
|
|
145
|
+
temp_id: string;
|
|
146
|
+
}>;
|
|
147
|
+
/** Step 2: Preview an uploaded archive without creating an instance. */
|
|
148
|
+
export declare function previewImport(tempId: string): Promise<{
|
|
149
|
+
manifest: Record<string, any> | null;
|
|
150
|
+
warnings: string[];
|
|
151
|
+
estimated_size: number;
|
|
152
|
+
format: "official" | "unknown";
|
|
153
|
+
}>;
|
|
154
|
+
/** Step 3: Create a new instance from a previously uploaded archive. */
|
|
155
|
+
export declare function importInstance(tempId: string, opts: {
|
|
156
|
+
id: string;
|
|
157
|
+
name: string;
|
|
158
|
+
description?: string;
|
|
159
|
+
}): Promise<{
|
|
160
|
+
ok: boolean;
|
|
161
|
+
instance_id: string;
|
|
162
|
+
warnings: string[];
|
|
163
|
+
}>;
|
|
164
|
+
/**
|
|
165
|
+
* Resolve the effective "archive root" inside an extracted tarball.
|
|
166
|
+
*
|
|
167
|
+
* Returns the directory where `manifest.json` and `payload/` live. Two
|
|
168
|
+
* archive layouts are supported:
|
|
169
|
+
*
|
|
170
|
+
* 1. **JishuShell self-pack** (`selfPackOfficialFormat`): writes
|
|
171
|
+
* `manifest.json` and `payload/` directly at the archive root, so the
|
|
172
|
+
* effective root is the extraction dir itself.
|
|
173
|
+
*
|
|
174
|
+
* 2. **Official OpenClaw `backup create`**: wraps everything inside a
|
|
175
|
+
* single top-level directory named after the archive basename, e.g.
|
|
176
|
+
* `2026-04-10T03-06-23.257Z-openclaw-backup/`. The wrapper name is
|
|
177
|
+
* also advertised via `manifest.archiveRoot`.
|
|
178
|
+
*
|
|
179
|
+
* Detection strategy (cheapest first):
|
|
180
|
+
* a. If `<tmpDir>/manifest.json` exists → self-pack → return tmpDir.
|
|
181
|
+
* b. Else scan top-level entries; if exactly one is a directory containing
|
|
182
|
+
* `manifest.json`, that's the official CLI wrapper → return it.
|
|
183
|
+
* c. Fall back to tmpDir; the caller will throw its own missing-manifest
|
|
184
|
+
* error with a meaningful path.
|
|
185
|
+
*
|
|
186
|
+
* Without this helper, `restoreInstance` / `importInstance` / `verifyArchive`
|
|
187
|
+
* would throw "Archive missing manifest.json" on every state-scope archive
|
|
188
|
+
* produced by the official CLI.
|
|
189
|
+
*/
|
|
190
|
+
export declare function resolveArchiveRoot(tmpDir: string): string;
|
|
191
|
+
/**
|
|
192
|
+
* Locate the OpenClaw state directory inside an extracted archive.
|
|
193
|
+
*
|
|
194
|
+
* Finds a directory **literally named `.openclaw`** that contains an
|
|
195
|
+
* `openclaw.json` file. Uses BFS so the shallowest match wins, which guards
|
|
196
|
+
* against nested copies inside extensions/ or workspace/.
|
|
197
|
+
*
|
|
198
|
+
* This is intentionally stricter than "any directory containing
|
|
199
|
+
* openclaw.json". JishuShell's `saveConfig` double-writes the config to both
|
|
200
|
+
* `.openclaw/openclaw.json` and an outer legacy alias at
|
|
201
|
+
* `openclaw-home/openclaw.json`, so a naive "first dir with openclaw.json"
|
|
202
|
+
* search would incorrectly pick the `openclaw-home/` root for home-scope
|
|
203
|
+
* archives.
|
|
204
|
+
*/
|
|
205
|
+
export declare function findStateDir(rootDir: string): string | null;
|
|
206
|
+
interface AutoBackupConfig {
|
|
207
|
+
enabled: boolean;
|
|
208
|
+
interval_hours: number;
|
|
209
|
+
keep_count: number;
|
|
210
|
+
last_backup_at?: string;
|
|
211
|
+
last_backup_ok?: boolean;
|
|
212
|
+
consecutive_failures?: number;
|
|
213
|
+
warnings?: string[];
|
|
214
|
+
}
|
|
215
|
+
/** Get auto-backup config from instance.json */
|
|
216
|
+
export declare function getAutoBackupConfig(instanceId: string): Promise<AutoBackupConfig | null>;
|
|
217
|
+
/** Clean old auto-backup files, keeping only the newest `keepCount` */
|
|
218
|
+
export declare function cleanOldAutoBackups(instanceId: string, keepCount: number): Promise<number>;
|
|
219
|
+
export interface BackupJob {
|
|
220
|
+
id: string;
|
|
221
|
+
instanceId: string;
|
|
222
|
+
operation: "manual-backup" | "auto-backup" | "export" | "restore" | "import" | "create-from-backup";
|
|
223
|
+
status: "queued" | "running" | "completed" | "failed";
|
|
224
|
+
createdAt: number;
|
|
225
|
+
startedAt?: number;
|
|
226
|
+
completedAt?: number;
|
|
227
|
+
progress?: string;
|
|
228
|
+
error?: string;
|
|
229
|
+
result?: any;
|
|
230
|
+
}
|
|
231
|
+
/** Enqueue a backup operation. Returns the job immediately (non-blocking). */
|
|
232
|
+
export declare function enqueueJob(instanceId: string, operation: BackupJob["operation"], executeFn: (job: BackupJob) => Promise<any>): BackupJob;
|
|
233
|
+
/** Enqueue and wait for completion. Returns the completed job. */
|
|
234
|
+
export declare function enqueueJobAndWait(instanceId: string, operation: BackupJob["operation"], executeFn: (job: BackupJob) => Promise<any>): Promise<BackupJob>;
|
|
235
|
+
/** Update progress message for the currently running job */
|
|
236
|
+
export declare function updateJobProgress(jobId: string, progress: string): void;
|
|
237
|
+
/** Get full queue status */
|
|
238
|
+
export declare function getQueueStatus(): {
|
|
239
|
+
current: BackupJob | null;
|
|
240
|
+
queued: BackupJob[];
|
|
241
|
+
recent: BackupJob[];
|
|
242
|
+
};
|
|
243
|
+
/** Get a specific job by ID (checks current, queue, and history) */
|
|
244
|
+
export declare function getJob(jobId: string): BackupJob | null;
|
|
245
|
+
/** Cancel a queued job (cannot cancel running jobs) */
|
|
246
|
+
export declare function cancelJob(jobId: string): boolean;
|
|
247
|
+
/** Schedule auto-backup for an instance */
|
|
248
|
+
export declare function scheduleAutoBackup(instanceId: string, config: AutoBackupConfig): void;
|
|
249
|
+
/** Cancel auto-backup for an instance */
|
|
250
|
+
export declare function cancelAutoBackup(instanceId: string): void;
|
|
251
|
+
/** Initialize auto-backup for all instances (call on server startup) */
|
|
252
|
+
export declare function initAutoBackup(): Promise<void>;
|
|
253
|
+
export {};
|