jishushell 0.4.2 → 0.4.17

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 (136) hide show
  1. package/Dockerfile.openclaw-slim +58 -0
  2. package/INSTALL-NOTICE +45 -0
  3. package/dist/auth.js +3 -3
  4. package/dist/auth.js.map +1 -1
  5. package/dist/cli/app.d.ts +3 -0
  6. package/dist/cli/app.js +156 -0
  7. package/dist/cli/app.js.map +1 -0
  8. package/dist/{doctor.d.ts → cli/doctor.d.ts} +6 -1
  9. package/dist/{doctor.js → cli/doctor.js} +389 -27
  10. package/dist/cli/doctor.js.map +1 -0
  11. package/dist/cli/helpers.d.ts +4 -0
  12. package/dist/cli/helpers.js +32 -0
  13. package/dist/cli/helpers.js.map +1 -0
  14. package/dist/cli/job.d.ts +3 -0
  15. package/dist/cli/job.js +260 -0
  16. package/dist/cli/job.js.map +1 -0
  17. package/dist/cli/llm.d.ts +24 -0
  18. package/dist/cli/llm.js +593 -0
  19. package/dist/cli/llm.js.map +1 -0
  20. package/dist/cli/openclaw.d.ts +12 -0
  21. package/dist/cli/openclaw.js +156 -0
  22. package/dist/cli/openclaw.js.map +1 -0
  23. package/dist/cli/panel.d.ts +25 -0
  24. package/dist/cli/panel.js +734 -0
  25. package/dist/cli/panel.js.map +1 -0
  26. package/dist/cli.js +476 -219
  27. package/dist/cli.js.map +1 -1
  28. package/dist/config.d.ts +22 -4
  29. package/dist/config.js +96 -55
  30. package/dist/config.js.map +1 -1
  31. package/dist/control.d.ts +13 -41
  32. package/dist/control.js +12 -1355
  33. package/dist/control.js.map +1 -1
  34. package/dist/install.d.ts +1 -1
  35. package/dist/install.js +15 -29
  36. package/dist/install.js.map +1 -1
  37. package/dist/routes/apps.d.ts +3 -0
  38. package/dist/routes/apps.js +99 -0
  39. package/dist/routes/apps.js.map +1 -0
  40. package/dist/routes/backup.d.ts +2 -0
  41. package/dist/routes/backup.js +370 -0
  42. package/dist/routes/backup.js.map +1 -0
  43. package/dist/routes/instances.d.ts +1 -0
  44. package/dist/routes/instances.js +61 -15
  45. package/dist/routes/instances.js.map +1 -1
  46. package/dist/routes/llm.d.ts +15 -0
  47. package/dist/routes/llm.js +246 -0
  48. package/dist/routes/llm.js.map +1 -0
  49. package/dist/routes/setup.js +32 -7
  50. package/dist/routes/setup.js.map +1 -1
  51. package/dist/routes/system.js +31 -6
  52. package/dist/routes/system.js.map +1 -1
  53. package/dist/server.js +69 -5
  54. package/dist/server.js.map +1 -1
  55. package/dist/services/app-compiler.d.ts +15 -0
  56. package/dist/services/app-compiler.js +169 -0
  57. package/dist/services/app-compiler.js.map +1 -0
  58. package/dist/services/app-manager.d.ts +17 -0
  59. package/dist/services/app-manager.js +168 -0
  60. package/dist/services/app-manager.js.map +1 -0
  61. package/dist/services/backup-manager.d.ts +253 -0
  62. package/dist/services/backup-manager.js +2014 -0
  63. package/dist/services/backup-manager.js.map +1 -0
  64. package/dist/services/backup-verify.d.ts +26 -0
  65. package/dist/services/backup-verify.js +240 -0
  66. package/dist/services/backup-verify.js.map +1 -0
  67. package/dist/services/instance-manager.d.ts +73 -5
  68. package/dist/services/instance-manager.js +446 -74
  69. package/dist/services/instance-manager.js.map +1 -1
  70. package/dist/services/job-manager.d.ts +22 -0
  71. package/dist/services/job-manager.js +102 -0
  72. package/dist/services/job-manager.js.map +1 -0
  73. package/dist/services/llm-proxy/adapters.js +5 -1
  74. package/dist/services/llm-proxy/adapters.js.map +1 -1
  75. package/dist/services/llm-proxy/index.d.ts +30 -0
  76. package/dist/services/llm-proxy/index.js +71 -1
  77. package/dist/services/llm-proxy/index.js.map +1 -1
  78. package/dist/services/llm-proxy/ssrf.js +1 -1
  79. package/dist/services/llm-proxy/ssrf.js.map +1 -1
  80. package/dist/services/nomad-manager.js +263 -159
  81. package/dist/services/nomad-manager.js.map +1 -1
  82. package/dist/services/panel-manager.d.ts +40 -0
  83. package/dist/services/panel-manager.js +346 -0
  84. package/dist/services/panel-manager.js.map +1 -0
  85. package/dist/services/process-manager.js +24 -10
  86. package/dist/services/process-manager.js.map +1 -1
  87. package/dist/services/setup-manager.d.ts +4 -2
  88. package/dist/services/setup-manager.js +578 -154
  89. package/dist/services/setup-manager.js.map +1 -1
  90. package/dist/services/telemetry/activation.js +10 -7
  91. package/dist/services/telemetry/activation.js.map +1 -1
  92. package/dist/services/telemetry/client.js +7 -18
  93. package/dist/services/telemetry/client.js.map +1 -1
  94. package/dist/services/telemetry/heartbeat.js +12 -6
  95. package/dist/services/telemetry/heartbeat.js.map +1 -1
  96. package/dist/services/update-manager.d.ts +47 -0
  97. package/dist/services/update-manager.js +305 -0
  98. package/dist/services/update-manager.js.map +1 -0
  99. package/dist/types.d.ts +62 -0
  100. package/dist/utils/fs.d.ts +85 -0
  101. package/dist/utils/fs.js +111 -0
  102. package/dist/utils/fs.js.map +1 -0
  103. package/dist/utils/safe-json.d.ts +2 -0
  104. package/dist/utils/safe-json.js +22 -16
  105. package/dist/utils/safe-json.js.map +1 -1
  106. package/install/jishu-install.sh +582 -138
  107. package/install/jishu-uninstall.sh +276 -391
  108. package/install/post-install.sh +85 -3
  109. package/openclaw-entry.sh +15 -0
  110. package/package.json +12 -5
  111. package/public/assets/Dashboard-CQsp1Mr9.js +1 -0
  112. package/public/assets/InitPassword-BEC8SE4A.js +1 -0
  113. package/public/assets/InstanceDetail-B5wTgNEg.js +17 -0
  114. package/public/assets/{Login-RkjzTNWg.js → Login-D1Bt-Lyk.js} +1 -1
  115. package/public/assets/NewInstance-GQzm3K9D.js +1 -0
  116. package/public/assets/Settings-ByjGlqhP.js +1 -0
  117. package/public/assets/Setup-cMF21Y-8.js +1 -0
  118. package/public/assets/index-B6qQP4mH.css +1 -0
  119. package/public/assets/index-BuTQtuNy.js +16 -0
  120. package/public/assets/logo-black-theme-DywLAtFy.png +0 -0
  121. package/public/assets/logo-white-theme-DXffFAWw.png +0 -0
  122. package/public/assets/{providers-lBSOjUWy.js → providers-V-vwrExZ.js} +1 -1
  123. package/public/assets/{usePolling-CqQ8hrNc.js → usePolling-CK0DfI4h.js} +1 -1
  124. package/public/assets/{vendor-i18n-Bvxxh8Di.js → vendor-i18n-CfW0RvgE.js} +1 -1
  125. package/public/assets/vendor-react-B1-3Yrt-.js +59 -0
  126. package/public/index.html +4 -4
  127. package/dist/doctor.js.map +0 -1
  128. package/public/assets/Dashboard-CAOQDYDR.js +0 -1
  129. package/public/assets/InitPassword-CkehIkJG.js +0 -1
  130. package/public/assets/InstanceDetail-CzW2S95J.js +0 -14
  131. package/public/assets/NewInstance-DdbErdjA.js +0 -1
  132. package/public/assets/Settings-BUD7zwv9.js +0 -1
  133. package/public/assets/Setup-RRTIERGG.js +0 -1
  134. package/public/assets/index-77Ug7feY.css +0 -1
  135. package/public/assets/index-DfRnVUQR.js +0 -16
  136. package/public/assets/vendor-react-DONn7uBV.js +0 -59
@@ -0,0 +1,305 @@
1
+ /**
2
+ * src/services/update-manager.ts
3
+ *
4
+ * Version checking and package upgrade — no console.log, returns data.
5
+ * Both the CLI and the HTTP API can safely call these functions.
6
+ */
7
+ import { execFileSync, spawn } from "child_process";
8
+ import { existsSync, readFileSync, writeFileSync } from "fs";
9
+ import { join, dirname } from "path";
10
+ import { fileURLToPath } from "url";
11
+ import * as http from "http";
12
+ import * as https from "https";
13
+ import { getPanelConfig, JISHUSHELL_HOME } from "../config.js";
14
+ import { checkAndReport, checkAndReportHeartbeat } from "./telemetry/index.js";
15
+ const __filename = fileURLToPath(import.meta.url);
16
+ // services/ is one level below root; cli.js lives at ../../cli.js from dist/services/
17
+ const CLI_PATH = join(dirname(__filename), "../cli.js");
18
+ const UPDATE_STATE_FILE = join(JISHUSHELL_HOME, "update-state.json");
19
+ const UPDATE_RESTART_TIMEOUT_MS = 5 * 60_000;
20
+ // ── Internal helpers ───────────────────────────────────────────────────────
21
+ let _updateCache = null;
22
+ const UPDATE_CACHE_TTL = 30_000;
23
+ function getNpmBinPath() {
24
+ return join(dirname(process.execPath), "npm");
25
+ }
26
+ function getCurrentPackageVersion() {
27
+ try {
28
+ const pkgPath = join(dirname(fileURLToPath(import.meta.url)), "../../package.json");
29
+ return JSON.parse(readFileSync(pkgPath, "utf-8")).version ?? "0.0.0";
30
+ }
31
+ catch {
32
+ return "0.0.0";
33
+ }
34
+ }
35
+ function parseVersion(version) {
36
+ const [major = 0, minor = 0, patch = 0] = version
37
+ .replace(/^v/, "")
38
+ .split(".")
39
+ .map((part) => parseInt(part, 10) || 0);
40
+ return [major, minor, patch];
41
+ }
42
+ export function compareVersions(a, b) {
43
+ const [aMaj, aMin, aPat] = parseVersion(a);
44
+ const [bMaj, bMin, bPat] = parseVersion(b);
45
+ if (aMaj !== bMaj)
46
+ return aMaj - bMaj;
47
+ if (aMin !== bMin)
48
+ return aMin - bMin;
49
+ return aPat - bPat;
50
+ }
51
+ export function isVersionAtLeast(version, expected) {
52
+ return compareVersions(version, expected) >= 0;
53
+ }
54
+ function readPersistedUpdateState() {
55
+ if (!existsSync(UPDATE_STATE_FILE))
56
+ return null;
57
+ try {
58
+ return JSON.parse(readFileSync(UPDATE_STATE_FILE, "utf-8"));
59
+ }
60
+ catch {
61
+ return null;
62
+ }
63
+ }
64
+ function writePersistedUpdateState(state) {
65
+ writeFileSync(UPDATE_STATE_FILE, `${JSON.stringify(state, null, 2)}\n`, "utf-8");
66
+ }
67
+ export function getInstalledGlobalVersion() {
68
+ try {
69
+ const npmRoot = execFileSync(getNpmBinPath(), ["root", "-g"], {
70
+ encoding: "utf-8",
71
+ timeout: 5000,
72
+ stdio: ["ignore", "pipe", "ignore"],
73
+ }).trim();
74
+ if (!npmRoot)
75
+ return getCurrentPackageVersion();
76
+ const pkgPath = join(npmRoot, "jishushell", "package.json");
77
+ if (!existsSync(pkgPath))
78
+ return getCurrentPackageVersion();
79
+ return JSON.parse(readFileSync(pkgPath, "utf-8")).version ?? getCurrentPackageVersion();
80
+ }
81
+ catch {
82
+ return getCurrentPackageVersion();
83
+ }
84
+ }
85
+ export function markUpdateRestarting(targetVersion, currentVersion, installedVersion) {
86
+ const previous = readPersistedUpdateState();
87
+ writePersistedUpdateState({
88
+ status: "restarting",
89
+ currentVersion,
90
+ targetVersion,
91
+ installedVersion,
92
+ startedAt: previous?.startedAt ?? Date.now(),
93
+ updatedAt: Date.now(),
94
+ message: `Updated to ${installedVersion}; waiting for panel restart`,
95
+ });
96
+ }
97
+ export function markUpdateFailed(error, currentVersion = getCurrentPackageVersion()) {
98
+ const previous = readPersistedUpdateState();
99
+ writePersistedUpdateState({
100
+ status: "failed",
101
+ currentVersion,
102
+ targetVersion: previous?.targetVersion,
103
+ installedVersion: getInstalledGlobalVersion(),
104
+ startedAt: previous?.startedAt ?? Date.now(),
105
+ updatedAt: Date.now(),
106
+ message: "Update failed",
107
+ error,
108
+ });
109
+ }
110
+ export function startBackgroundUpgrade(info) {
111
+ const status = getUpdateStatus();
112
+ if (status.inProgress) {
113
+ throw new Error("Update already in progress");
114
+ }
115
+ writePersistedUpdateState({
116
+ status: "running",
117
+ currentVersion: info.currentVersion,
118
+ targetVersion: info.latestVersion,
119
+ installedVersion: getInstalledGlobalVersion(),
120
+ startedAt: Date.now(),
121
+ updatedAt: Date.now(),
122
+ message: `Updating JishuShell to ${info.latestVersion}`,
123
+ });
124
+ const nodeBinDir = dirname(process.execPath);
125
+ const childEnv = {
126
+ ...process.env,
127
+ PATH: `${nodeBinDir}${process.env.PATH ? `:${process.env.PATH}` : ""}`,
128
+ JISHUSHELL_WEB_UPDATE: "1",
129
+ JISHUSHELL_UPDATE_CURRENT_VERSION: info.currentVersion,
130
+ JISHUSHELL_UPDATE_TARGET_VERSION: info.latestVersion,
131
+ };
132
+ try {
133
+ const child = spawn(process.execPath, [CLI_PATH, "update"], {
134
+ detached: true,
135
+ stdio: "ignore",
136
+ env: childEnv,
137
+ });
138
+ child.unref();
139
+ }
140
+ catch (err) {
141
+ markUpdateFailed(err.message || "Failed to start update worker", info.currentVersion);
142
+ throw err;
143
+ }
144
+ return getUpdateStatus();
145
+ }
146
+ export function getUpdateStatus() {
147
+ const currentVersion = getCurrentPackageVersion();
148
+ const installedVersion = getInstalledGlobalVersion();
149
+ let state = readPersistedUpdateState();
150
+ if (state?.status === "running" && state.targetVersion && isVersionAtLeast(installedVersion, state.targetVersion)) {
151
+ state = {
152
+ ...state,
153
+ status: "restarting",
154
+ installedVersion,
155
+ updatedAt: Date.now(),
156
+ message: `Updated to ${installedVersion}; waiting for panel restart`,
157
+ };
158
+ writePersistedUpdateState(state);
159
+ }
160
+ if (state?.status === "restarting" && state.targetVersion) {
161
+ if (currentVersion === installedVersion && isVersionAtLeast(installedVersion, state.targetVersion)) {
162
+ state = {
163
+ ...state,
164
+ status: "completed",
165
+ currentVersion,
166
+ installedVersion,
167
+ updatedAt: Date.now(),
168
+ message: `Update applied: ${installedVersion}`,
169
+ };
170
+ writePersistedUpdateState(state);
171
+ }
172
+ else if (Date.now() - (state.updatedAt || state.startedAt) > UPDATE_RESTART_TIMEOUT_MS) {
173
+ state = {
174
+ ...state,
175
+ status: "failed",
176
+ currentVersion,
177
+ installedVersion,
178
+ updatedAt: Date.now(),
179
+ message: "Update failed",
180
+ error: `Panel did not restart into ${state.targetVersion}`,
181
+ };
182
+ writePersistedUpdateState(state);
183
+ }
184
+ }
185
+ if (!state) {
186
+ return {
187
+ status: "idle",
188
+ currentVersion,
189
+ installedVersion,
190
+ inProgress: false,
191
+ };
192
+ }
193
+ return {
194
+ status: state.status,
195
+ currentVersion,
196
+ installedVersion,
197
+ targetVersion: state.targetVersion,
198
+ startedAt: state.startedAt,
199
+ updatedAt: state.updatedAt,
200
+ message: state.message,
201
+ error: state.error,
202
+ inProgress: state.status === "running" || state.status === "restarting",
203
+ };
204
+ }
205
+ function getNpmRegistryUrl() {
206
+ const panelReg = getPanelConfig().npm_registry;
207
+ if (typeof panelReg === "string" && panelReg.trim())
208
+ return panelReg.trim().replace(/\/+$/, "");
209
+ try {
210
+ const reg = execFileSync(getNpmBinPath(), ["config", "get", "registry"], {
211
+ encoding: "utf-8", timeout: 5000,
212
+ }).trim();
213
+ if (reg && reg !== "undefined")
214
+ return reg.replace(/\/+$/, "");
215
+ }
216
+ catch { /* fall through */ }
217
+ return "https://registry.npmjs.org";
218
+ }
219
+ // ── Public API ─────────────────────────────────────────────────────────────
220
+ /**
221
+ * Check for a newer jishushell version on npm.
222
+ * Caches for 30 s; safe to call from both CLI and HTTP routes.
223
+ */
224
+ export async function checkUpdate() {
225
+ if (_updateCache && Date.now() - _updateCache.ts < UPDATE_CACHE_TTL) {
226
+ return _updateCache.info;
227
+ }
228
+ const currentVersion = getCurrentPackageVersion();
229
+ let latestVersion = currentVersion;
230
+ let hasUpdate = false;
231
+ try {
232
+ const registryUrl = getNpmRegistryUrl();
233
+ const metaUrl = new URL(`/jishushell/latest`, registryUrl);
234
+ const transport = metaUrl.protocol === "https:" ? https : http;
235
+ latestVersion = await new Promise((resolve, reject) => {
236
+ const req = transport.get(metaUrl, { headers: { accept: "application/json" }, timeout: 8000 }, (res) => {
237
+ let body = "";
238
+ res.on("data", (d) => (body += d));
239
+ res.on("end", () => {
240
+ try {
241
+ resolve(JSON.parse(body).version ?? currentVersion);
242
+ }
243
+ catch {
244
+ reject(new Error("parse error"));
245
+ }
246
+ });
247
+ });
248
+ req.on("error", reject);
249
+ req.on("timeout", () => { req.destroy(); reject(new Error("timeout")); });
250
+ });
251
+ hasUpdate = compareVersions(latestVersion, currentVersion) > 0;
252
+ }
253
+ catch { /* network unavailable — return no-update */ }
254
+ const info = { hasUpdate, currentVersion, latestVersion };
255
+ _updateCache = { ts: Date.now(), info };
256
+ // Piggyback telemetry on update checks (fire-and-forget)
257
+ checkAndReport();
258
+ checkAndReportHeartbeat();
259
+ return info;
260
+ }
261
+ /**
262
+ * Run `npm install -g jishushell`.
263
+ * Throws on failure; returns trimmed npm stdout on success.
264
+ */
265
+ export async function upgradePackage() {
266
+ const nodeBinDir = dirname(process.execPath);
267
+ const npmBin = getNpmBinPath();
268
+ const childEnv = {
269
+ ...process.env,
270
+ PATH: `${nodeBinDir}${process.env.PATH ? `:${process.env.PATH}` : ""}`,
271
+ };
272
+ // JISHU_RUNNING_IN_INSTALLER=1 tells post-install.sh it is managed by a
273
+ // parent installer and should skip the interactive sudo / TTY checks,
274
+ // do only the minimal wrapper+service update, then exit 0. This works
275
+ // with every published version of jishushell (the env-var guard predates
276
+ // the JISHUSHELL_WEB_UPDATE check added later).
277
+ const npmEnv = {
278
+ ...childEnv,
279
+ JISHU_RUNNING_IN_INSTALLER: "1",
280
+ };
281
+ try {
282
+ const out = execFileSync(npmBin, ["install", "-g", "jishushell", "--registry", getNpmRegistryUrl() + "/"], { encoding: "utf-8", timeout: 120_000, stdio: ["ignore", "pipe", "pipe"], env: npmEnv });
283
+ _updateCache = null; // invalidate
284
+ return { output: out?.trim() ?? "" };
285
+ }
286
+ catch (err) {
287
+ const detail = err.stderr ? err.stderr.trim() : err.message;
288
+ throw new Error(detail || err.message);
289
+ }
290
+ }
291
+ /**
292
+ * Spawn a detached `jishushell restart` after `delayMs` ms, then return.
293
+ * The spawned child outlives the current process (useful after upgrade).
294
+ */
295
+ export function scheduleRestart(delayMs = 2000) {
296
+ const nodeBinDir = dirname(process.execPath);
297
+ const childEnv = {
298
+ ...process.env,
299
+ PATH: `${nodeBinDir}${process.env.PATH ? `:${process.env.PATH}` : ""}`,
300
+ };
301
+ const delaySecs = Math.max(1, Math.round(delayMs / 1000));
302
+ const child = spawn("sh", ["-c", `sleep ${delaySecs} && exec ${JSON.stringify(process.execPath)} ${JSON.stringify(CLI_PATH)} restart`], { detached: true, stdio: "ignore", env: childEnv });
303
+ child.unref();
304
+ }
305
+ //# sourceMappingURL=update-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update-manager.js","sourceRoot":"","sources":["../../src/services/update-manager.ts"],"names":[],"mappings":"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"}
package/dist/types.d.ts CHANGED
@@ -49,3 +49,65 @@ export interface PanelConfig {
49
49
  activation_reported?: boolean;
50
50
  [key: string]: any;
51
51
  }
52
+ export type AppTaskRuntime = "container" | "process" | "vm";
53
+ export type AppTaskRole = "service" | "init" | "sidecar" | "cleanup";
54
+ export interface AppTaskResources {
55
+ cpu?: string;
56
+ memory?: string;
57
+ }
58
+ export interface AppTaskPort {
59
+ name: string;
60
+ port: number;
61
+ visibility?: "public" | "internal";
62
+ }
63
+ export interface AppTaskHealth {
64
+ http?: {
65
+ path: string;
66
+ port: number;
67
+ };
68
+ interval?: string;
69
+ timeout?: string;
70
+ retries?: number;
71
+ }
72
+ export interface AppTask {
73
+ name: string;
74
+ role: AppTaskRole;
75
+ runtime: AppTaskRuntime;
76
+ image?: string;
77
+ command?: string;
78
+ args?: string[];
79
+ env?: Record<string, string>;
80
+ resources?: AppTaskResources;
81
+ ports?: AppTaskPort[];
82
+ health?: AppTaskHealth;
83
+ after?: string[];
84
+ }
85
+ export interface AppProvide {
86
+ capability: string;
87
+ port?: number;
88
+ path?: string;
89
+ visibility?: string;
90
+ description?: string;
91
+ }
92
+ export interface AppRequire {
93
+ capability: string;
94
+ inject_as: string;
95
+ required?: boolean;
96
+ }
97
+ export interface AppSpec {
98
+ id: string;
99
+ name?: string;
100
+ version?: string;
101
+ description?: string;
102
+ tasks: AppTask[];
103
+ provides?: AppProvide[];
104
+ requires?: AppRequire[];
105
+ openclaw?: Record<string, any>;
106
+ _engine?: Record<string, any>;
107
+ }
108
+ export interface AppManifest {
109
+ id: string;
110
+ installed_at: string;
111
+ source?: string;
112
+ spec_hash?: string;
113
+ }
@@ -0,0 +1,85 @@
1
+ /**
2
+ * Semantic file-system primitives for JishuShell.
3
+ *
4
+ * Every file write in the codebase should go through one of these functions.
5
+ * The function name describes the *kind* of file being written; the correct
6
+ * permissions follow from that classification — callers never touch raw mode
7
+ * numbers.
8
+ *
9
+ * Classification:
10
+ *
11
+ * writeConfigFile 0o644 Config / state files (openclaw.json, instance.json, …)
12
+ * writeSecretFile 0o600 Cryptographic keys, tokens, hashes (jwt-secret, …)
13
+ * writeExecutableFile 0o755 Shell scripts and binary wrappers
14
+ * writeSystemTmpFile 0o600 Temp files for privileged hand-off (sudo cp)
15
+ *
16
+ * ensureDirHost 0o755 Host-only directories never bind-mounted into
17
+ * (Linux) containers (JISHUSHELL_HOME, bin/, nomad/,
18
+ * 0o755 packages/). 0o755 on both platforms: Linux
19
+ * (macOS) Docker daemon (root) bypasses DAC so tighter
20
+ * modes would only inconvenience the host user;
21
+ * on macOS, VirtioFS requires the execute bit on
22
+ * every ancestor of a bind-mount. The write bit
23
+ * is withheld from group/other on both platforms,
24
+ * so containers cannot create files in host dirs.
25
+ *
26
+ * ensureDirContainer 0o755 Directories bind-mounted into Docker containers.
27
+ * (Linux) Docker Desktop's VirtioFS uses virtiofsd in
28
+ * 0o755 passthrough mode: macOS host uid numbers are
29
+ * (macOS) exposed verbatim inside the Linux VM and the
30
+ * container, so a process running as --user 502
31
+ * sees files owned by host uid 502 as "owner".
32
+ * 0o755 therefore suffices on macOS just as on
33
+ * Linux — the container process hits owner bits,
34
+ * not "other" bits. (Confirmed by lima-vm/lima
35
+ * #4053: Docker Desktop correctly shows uid=501
36
+ * from host as uid=501 in the container, unlike
37
+ * Lima's VirtioFS which squashes to root.)
38
+ */
39
+ /**
40
+ * Create a host-only directory (never bind-mounted into containers).
41
+ * 0o755 on both Linux and macOS: on Linux the Docker daemon runs as root and
42
+ * bypasses DAC, so stricter modes only inconvenience the local user; on macOS,
43
+ * VirtioFS requires the execute bit on every ancestor of a bind-mounted path.
44
+ * Write is withheld from group/other on both platforms, so containers cannot
45
+ * create files inside host directories.
46
+ */
47
+ export declare function ensureDirHost(path: string): void;
48
+ /**
49
+ * Create a directory bind-mounted into Docker containers.
50
+ *
51
+ * Docker Desktop's VirtioFS runs virtiofsd in passthrough mode: the macOS host
52
+ * uid is exposed verbatim inside the Linux VM, so a container process running
53
+ * as --user 502 sees bind-mounted files owned by host uid 502 as "owner" and
54
+ * gets owner-class permission bits. 0o755 (rwxr-xr-x) is therefore sufficient
55
+ * on macOS, same as on Linux.
56
+ *
57
+ * chmodSync is called after mkdirSync so that the mode is applied
58
+ * unconditionally regardless of the process umask (mkdirSync mode is masked by
59
+ * umask; chmodSync / chmod(2) is not). This is safe on already-existing
60
+ * directories — it only updates the mode bits, it does not fail.
61
+ */
62
+ export declare function ensureDirContainer(path: string): void;
63
+ /**
64
+ * Write a config/state file with 0o644.
65
+ * Creates parent directories if they do not yet exist, but does NOT chmod an
66
+ * already-existing parent — the caller owns the directory lifecycle.
67
+ */
68
+ export declare function writeConfigFile(path: string, content: string | Buffer): void;
69
+ /**
70
+ * Write a secret file with 0o600.
71
+ * Creates parent directories if they do not yet exist, but does NOT chmod an
72
+ * already-existing parent.
73
+ */
74
+ export declare function writeSecretFile(path: string, content: string | Buffer): void;
75
+ /**
76
+ * Write an executable file (script or binary wrapper) with 0o755.
77
+ * Creates parent directories if they do not yet exist, but does NOT chmod an
78
+ * already-existing parent.
79
+ */
80
+ export declare function writeExecutableFile(path: string, content: string): void;
81
+ /**
82
+ * Write a temporary file to /tmp with 0o600 for privileged hand-off (sudo cp).
83
+ * /tmp already exists; no directory creation needed.
84
+ */
85
+ export declare function writeSystemTmpFile(path: string, content: string): void;
@@ -0,0 +1,111 @@
1
+ /**
2
+ * Semantic file-system primitives for JishuShell.
3
+ *
4
+ * Every file write in the codebase should go through one of these functions.
5
+ * The function name describes the *kind* of file being written; the correct
6
+ * permissions follow from that classification — callers never touch raw mode
7
+ * numbers.
8
+ *
9
+ * Classification:
10
+ *
11
+ * writeConfigFile 0o644 Config / state files (openclaw.json, instance.json, …)
12
+ * writeSecretFile 0o600 Cryptographic keys, tokens, hashes (jwt-secret, …)
13
+ * writeExecutableFile 0o755 Shell scripts and binary wrappers
14
+ * writeSystemTmpFile 0o600 Temp files for privileged hand-off (sudo cp)
15
+ *
16
+ * ensureDirHost 0o755 Host-only directories never bind-mounted into
17
+ * (Linux) containers (JISHUSHELL_HOME, bin/, nomad/,
18
+ * 0o755 packages/). 0o755 on both platforms: Linux
19
+ * (macOS) Docker daemon (root) bypasses DAC so tighter
20
+ * modes would only inconvenience the host user;
21
+ * on macOS, VirtioFS requires the execute bit on
22
+ * every ancestor of a bind-mount. The write bit
23
+ * is withheld from group/other on both platforms,
24
+ * so containers cannot create files in host dirs.
25
+ *
26
+ * ensureDirContainer 0o755 Directories bind-mounted into Docker containers.
27
+ * (Linux) Docker Desktop's VirtioFS uses virtiofsd in
28
+ * 0o755 passthrough mode: macOS host uid numbers are
29
+ * (macOS) exposed verbatim inside the Linux VM and the
30
+ * container, so a process running as --user 502
31
+ * sees files owned by host uid 502 as "owner".
32
+ * 0o755 therefore suffices on macOS just as on
33
+ * Linux — the container process hits owner bits,
34
+ * not "other" bits. (Confirmed by lima-vm/lima
35
+ * #4053: Docker Desktop correctly shows uid=501
36
+ * from host as uid=501 in the container, unlike
37
+ * Lima's VirtioFS which squashes to root.)
38
+ */
39
+ import { chmodSync, mkdirSync, writeFileSync } from "fs";
40
+ import { dirname } from "path";
41
+ // ── Directories ────────────────────────────────────────────────────────────
42
+ /**
43
+ * Create a host-only directory (never bind-mounted into containers).
44
+ * 0o755 on both Linux and macOS: on Linux the Docker daemon runs as root and
45
+ * bypasses DAC, so stricter modes only inconvenience the local user; on macOS,
46
+ * VirtioFS requires the execute bit on every ancestor of a bind-mounted path.
47
+ * Write is withheld from group/other on both platforms, so containers cannot
48
+ * create files inside host directories.
49
+ */
50
+ export function ensureDirHost(path) {
51
+ mkdirSync(path, { recursive: true, mode: 0o755 });
52
+ chmodSync(path, 0o755);
53
+ }
54
+ /**
55
+ * Create a directory bind-mounted into Docker containers.
56
+ *
57
+ * Docker Desktop's VirtioFS runs virtiofsd in passthrough mode: the macOS host
58
+ * uid is exposed verbatim inside the Linux VM, so a container process running
59
+ * as --user 502 sees bind-mounted files owned by host uid 502 as "owner" and
60
+ * gets owner-class permission bits. 0o755 (rwxr-xr-x) is therefore sufficient
61
+ * on macOS, same as on Linux.
62
+ *
63
+ * chmodSync is called after mkdirSync so that the mode is applied
64
+ * unconditionally regardless of the process umask (mkdirSync mode is masked by
65
+ * umask; chmodSync / chmod(2) is not). This is safe on already-existing
66
+ * directories — it only updates the mode bits, it does not fail.
67
+ */
68
+ export function ensureDirContainer(path) {
69
+ mkdirSync(path, { recursive: true, mode: 0o755 });
70
+ chmodSync(path, 0o755);
71
+ }
72
+ // ── Files ──────────────────────────────────────────────────────────────────
73
+ /**
74
+ * Write a config/state file with 0o644.
75
+ * Creates parent directories if they do not yet exist, but does NOT chmod an
76
+ * already-existing parent — the caller owns the directory lifecycle.
77
+ */
78
+ export function writeConfigFile(path, content) {
79
+ mkdirSync(dirname(path), { recursive: true });
80
+ writeFileSync(path, content, { mode: 0o644 });
81
+ chmodSync(path, 0o644);
82
+ }
83
+ /**
84
+ * Write a secret file with 0o600.
85
+ * Creates parent directories if they do not yet exist, but does NOT chmod an
86
+ * already-existing parent.
87
+ */
88
+ export function writeSecretFile(path, content) {
89
+ mkdirSync(dirname(path), { recursive: true });
90
+ writeFileSync(path, content, { mode: 0o600 });
91
+ chmodSync(path, 0o600);
92
+ }
93
+ /**
94
+ * Write an executable file (script or binary wrapper) with 0o755.
95
+ * Creates parent directories if they do not yet exist, but does NOT chmod an
96
+ * already-existing parent.
97
+ */
98
+ export function writeExecutableFile(path, content) {
99
+ mkdirSync(dirname(path), { recursive: true });
100
+ writeFileSync(path, content, { mode: 0o755 });
101
+ chmodSync(path, 0o755);
102
+ }
103
+ /**
104
+ * Write a temporary file to /tmp with 0o600 for privileged hand-off (sudo cp).
105
+ * /tmp already exists; no directory creation needed.
106
+ */
107
+ export function writeSystemTmpFile(path, content) {
108
+ writeFileSync(path, content, { mode: 0o600 });
109
+ chmodSync(path, 0o600);
110
+ }
111
+ //# sourceMappingURL=fs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fs.js","sourceRoot":"","sources":["../../src/utils/fs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AAEH,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,IAAI,CAAC;AACzD,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAE/B,8EAA8E;AAE9E;;;;;;;GAOG;AACH,MAAM,UAAU,aAAa,CAAC,IAAY;IACxC,SAAS,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IAClD,SAAS,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;AACzB,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,kBAAkB,CAAC,IAAY;IAC7C,SAAS,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IAClD,SAAS,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;AACzB,CAAC;AAED,8EAA8E;AAE9E;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAAC,IAAY,EAAE,OAAwB;IACpE,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC9C,aAAa,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IAC9C,SAAS,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;AACzB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAAC,IAAY,EAAE,OAAwB;IACpE,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC9C,aAAa,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IAC9C,SAAS,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;AACzB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CAAC,IAAY,EAAE,OAAe;IAC/D,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC9C,aAAa,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IAC9C,SAAS,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;AACzB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAAC,IAAY,EAAE,OAAe;IAC9D,aAAa,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IAC9C,SAAS,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;AACzB,CAAC"}
@@ -1,2 +1,4 @@
1
1
  export declare function safeReadJson<T = Record<string, any>>(path: string, label: string): T | null;
2
+ export declare function safeReadSecretJson<T = Record<string, any>>(path: string, label: string): T | null;
2
3
  export declare function safeWriteJson(path: string, data: any, fsync?: boolean): void;
4
+ export declare function safeWriteSecretJson(path: string, data: any, fsync?: boolean): void;