jishushell 0.6.5 → 0.7.3

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 (1207) hide show
  1. package/apps/anythingllm-container.yaml +16 -170
  2. package/apps/browserless-chromium-container.yaml +16 -10
  3. package/apps/filebrowser-container.yaml +15 -9
  4. package/apps/hermes-container.yaml +20 -5
  5. package/apps/immich-container-lite.yaml +337 -0
  6. package/apps/immich-container.yaml +371 -0
  7. package/apps/jishu-kb-container.yaml +50 -177
  8. package/apps/ollama-binary.yaml +33 -28
  9. package/apps/ollama-cpu-container.yaml +6 -0
  10. package/apps/ollama-with-hollama-binary.yaml +35 -28
  11. package/apps/openclaw-binary.yaml +35 -15
  12. package/apps/openclaw-container.yaml +29 -11
  13. package/apps/openclaw-with-ollama-container.yaml +9 -2
  14. package/apps/openclaw-with-searxng-container.yaml +38 -6
  15. package/apps/searxng-container.yaml +31 -6
  16. package/apps/weknora-container.yaml +26 -21
  17. package/dependencies/jishushell-panel-0.7.3.tgz +0 -0
  18. package/dist/cli/app.js +244 -213
  19. package/dist/cli/app.js.map +1 -1
  20. package/dist/cli/backup.js +15 -12
  21. package/dist/cli/backup.js.map +1 -1
  22. package/dist/cli/core.d.ts +4 -3
  23. package/dist/cli/core.js +392 -227
  24. package/dist/cli/core.js.map +1 -1
  25. package/dist/cli/doctor.d.ts +1 -1
  26. package/dist/cli/doctor.js +113 -10
  27. package/dist/cli/doctor.js.map +1 -1
  28. package/dist/cli/job.js +62 -14
  29. package/dist/cli/job.js.map +1 -1
  30. package/dist/cli/llm.js +80 -11
  31. package/dist/cli/llm.js.map +1 -1
  32. package/dist/cli/managed-list.d.ts +1 -3
  33. package/dist/cli/managed-list.js +18 -16
  34. package/dist/cli/managed-list.js.map +1 -1
  35. package/dist/cli/migrate.d.ts +2 -0
  36. package/dist/cli/migrate.js +160 -0
  37. package/dist/cli/migrate.js.map +1 -0
  38. package/dist/cli.js +1 -0
  39. package/dist/cli.js.map +1 -1
  40. package/dist/config.d.ts +32 -20
  41. package/dist/config.js +132 -51
  42. package/dist/config.js.map +1 -1
  43. package/dist/control.d.ts +6 -6
  44. package/dist/control.js +31 -23
  45. package/dist/control.js.map +1 -1
  46. package/dist/core.d.ts +5 -5
  47. package/dist/core.js +5 -5
  48. package/dist/core.js.map +1 -1
  49. package/dist/install.d.ts +2 -2
  50. package/dist/install.js +78 -37
  51. package/dist/install.js.map +1 -1
  52. package/dist/routes/admin.d.ts +2 -0
  53. package/dist/routes/admin.js +72 -0
  54. package/dist/routes/admin.js.map +1 -0
  55. package/dist/routes/apps.d.ts +1 -1
  56. package/dist/routes/apps.js +101 -193
  57. package/dist/routes/apps.js.map +1 -1
  58. package/dist/routes/auth.js +1 -1
  59. package/dist/routes/auth.js.map +1 -1
  60. package/dist/routes/backup.js +1 -1
  61. package/dist/routes/backup.js.map +1 -1
  62. package/dist/routes/docker.d.ts +2 -0
  63. package/dist/routes/docker.js +58 -0
  64. package/dist/routes/docker.js.map +1 -0
  65. package/dist/routes/external-mounts.d.ts +1 -1
  66. package/dist/routes/external-mounts.js +1 -1
  67. package/dist/routes/external-mounts.js.map +1 -1
  68. package/dist/routes/file-mounts.d.ts +4 -3
  69. package/dist/routes/file-mounts.js +49 -31
  70. package/dist/routes/file-mounts.js.map +1 -1
  71. package/dist/routes/files-organize.d.ts +2 -2
  72. package/dist/routes/files-organize.js +5 -5
  73. package/dist/routes/files-organize.js.map +1 -1
  74. package/dist/routes/files.d.ts +1 -1
  75. package/dist/routes/files.js +1 -1
  76. package/dist/routes/files.js.map +1 -1
  77. package/dist/routes/instances.d.ts +0 -8
  78. package/dist/routes/instances.js +202 -1560
  79. package/dist/routes/instances.js.map +1 -1
  80. package/dist/routes/integration-apps.d.ts +14 -0
  81. package/dist/routes/integration-apps.js +81 -0
  82. package/dist/routes/integration-apps.js.map +1 -0
  83. package/dist/routes/integrations.d.ts +9 -0
  84. package/dist/routes/integrations.js +12 -0
  85. package/dist/routes/integrations.js.map +1 -0
  86. package/dist/routes/llm-proxy.js +26 -3
  87. package/dist/routes/llm-proxy.js.map +1 -1
  88. package/dist/routes/setup.js +53 -38
  89. package/dist/routes/setup.js.map +1 -1
  90. package/dist/routes/system.js +108 -68
  91. package/dist/routes/system.js.map +1 -1
  92. package/dist/routes/webdav.d.ts +1 -1
  93. package/dist/routes/webdav.js +2 -2
  94. package/dist/routes/webdav.js.map +1 -1
  95. package/dist/server.d.ts +6 -0
  96. package/dist/server.js +368 -233
  97. package/dist/server.js.map +1 -1
  98. package/dist/services/app-common/app-compiler.js +186 -0
  99. package/dist/services/app-common/app-compiler.js.map +1 -0
  100. package/dist/services/app-common/app-shared.d.ts +15 -0
  101. package/dist/services/app-common/app-shared.js +64 -0
  102. package/dist/services/app-common/app-shared.js.map +1 -0
  103. package/dist/services/app-common/capability-service.d.ts +45 -0
  104. package/dist/services/app-common/capability-service.js +331 -0
  105. package/dist/services/app-common/capability-service.js.map +1 -0
  106. package/dist/services/app-common/catalog-service.d.ts +59 -0
  107. package/dist/services/app-common/catalog-service.js +318 -0
  108. package/dist/services/app-common/catalog-service.js.map +1 -0
  109. package/dist/services/app-common/create-pipeline.d.ts +26 -0
  110. package/dist/services/app-common/create-pipeline.js +298 -0
  111. package/dist/services/app-common/create-pipeline.js.map +1 -0
  112. package/dist/services/app-common/delete-service.d.ts +5 -0
  113. package/dist/services/app-common/delete-service.js +109 -0
  114. package/dist/services/app-common/delete-service.js.map +1 -0
  115. package/dist/services/app-common/execution-owner.d.ts +23 -0
  116. package/dist/services/app-common/execution-owner.js +124 -0
  117. package/dist/services/app-common/execution-owner.js.map +1 -0
  118. package/dist/services/app-common/execution-service.d.ts +23 -0
  119. package/dist/services/app-common/execution-service.js +105 -0
  120. package/dist/services/app-common/execution-service.js.map +1 -0
  121. package/dist/services/app-common/id-normalizer.d.ts +31 -0
  122. package/dist/services/app-common/id-normalizer.js +83 -0
  123. package/dist/services/app-common/id-normalizer.js.map +1 -0
  124. package/dist/services/app-common/install-store.d.ts +34 -0
  125. package/dist/services/app-common/install-store.js +261 -0
  126. package/dist/services/app-common/install-store.js.map +1 -0
  127. package/dist/services/app-common/instance-store.d.ts +78 -0
  128. package/dist/services/app-common/instance-store.js +498 -0
  129. package/dist/services/app-common/instance-store.js.map +1 -0
  130. package/dist/services/app-common/integration-refs.d.ts +17 -0
  131. package/dist/services/app-common/integration-refs.js +47 -0
  132. package/dist/services/app-common/integration-refs.js.map +1 -0
  133. package/dist/services/app-common/lifecycle-pipeline.d.ts +62 -0
  134. package/dist/services/app-common/lifecycle-pipeline.js +317 -0
  135. package/dist/services/app-common/lifecycle-pipeline.js.map +1 -0
  136. package/dist/services/app-common/lifecycle-scripts.d.ts +38 -0
  137. package/dist/services/app-common/lifecycle-scripts.js +935 -0
  138. package/dist/services/app-common/lifecycle-scripts.js.map +1 -0
  139. package/dist/services/app-common/lifecycle-service.d.ts +68 -0
  140. package/dist/services/app-common/lifecycle-service.js +475 -0
  141. package/dist/services/app-common/lifecycle-service.js.map +1 -0
  142. package/dist/services/app-common/ownership.d.ts +3 -0
  143. package/dist/services/app-common/ownership.js +11 -0
  144. package/dist/services/app-common/ownership.js.map +1 -0
  145. package/dist/services/app-common/paths.d.ts +29 -0
  146. package/dist/services/app-common/paths.js +34 -0
  147. package/dist/services/app-common/paths.js.map +1 -0
  148. package/dist/services/app-common/platform-transform.d.ts +32 -0
  149. package/dist/services/app-common/platform-transform.js +65 -0
  150. package/dist/services/app-common/platform-transform.js.map +1 -0
  151. package/dist/services/app-common/provide-resolver.d.ts +29 -0
  152. package/dist/services/app-common/provide-resolver.js +129 -0
  153. package/dist/services/app-common/provide-resolver.js.map +1 -0
  154. package/dist/services/app-common/remote-spec.d.ts +14 -0
  155. package/dist/services/app-common/remote-spec.js +58 -0
  156. package/dist/services/app-common/remote-spec.js.map +1 -0
  157. package/dist/services/app-common/runtime-builder.d.ts +1 -0
  158. package/dist/services/app-common/runtime-builder.js +2 -0
  159. package/dist/services/app-common/runtime-builder.js.map +1 -0
  160. package/dist/services/app-common/runtime-facts.d.ts +19 -0
  161. package/dist/services/app-common/runtime-facts.js +128 -0
  162. package/dist/services/app-common/runtime-facts.js.map +1 -0
  163. package/dist/services/app-common/service.d.ts +9 -0
  164. package/dist/services/app-common/service.js +10 -0
  165. package/dist/services/app-common/service.js.map +1 -0
  166. package/dist/services/app-common/spec-materializer.d.ts +8 -0
  167. package/dist/services/app-common/spec-materializer.js +295 -0
  168. package/dist/services/app-common/spec-materializer.js.map +1 -0
  169. package/dist/services/app-common/status-refresh.d.ts +33 -0
  170. package/dist/services/app-common/status-refresh.js +771 -0
  171. package/dist/services/app-common/status-refresh.js.map +1 -0
  172. package/dist/services/app-common/task-service.d.ts +29 -0
  173. package/dist/services/app-common/task-service.js +93 -0
  174. package/dist/services/app-common/task-service.js.map +1 -0
  175. package/dist/services/app-common/terminal-session-manager.js +157 -0
  176. package/dist/services/app-common/terminal-session-manager.js.map +1 -0
  177. package/dist/services/app-modules/browserless/routes.d.ts +9 -0
  178. package/dist/services/app-modules/browserless/routes.js +519 -0
  179. package/dist/services/app-modules/browserless/routes.js.map +1 -0
  180. package/dist/services/app-modules/routes.d.ts +2 -0
  181. package/dist/services/app-modules/routes.js +5 -0
  182. package/dist/services/app-modules/routes.js.map +1 -0
  183. package/dist/services/backup/backup-admin.d.ts +95 -0
  184. package/dist/services/backup/backup-admin.js +246 -0
  185. package/dist/services/backup/backup-admin.js.map +1 -0
  186. package/dist/services/backup/backup-manager.d.ts +264 -0
  187. package/dist/services/backup/backup-manager.js +2318 -0
  188. package/dist/services/backup/backup-manager.js.map +1 -0
  189. package/dist/services/backup/backup-verify.js +240 -0
  190. package/dist/services/backup/backup-verify.js.map +1 -0
  191. package/dist/services/capabilities/browser-policy.d.ts +14 -0
  192. package/dist/services/capabilities/browser-policy.js +141 -0
  193. package/dist/services/capabilities/browser-policy.js.map +1 -0
  194. package/dist/services/capabilities/contract.d.ts +49 -0
  195. package/dist/services/capabilities/contract.js +119 -0
  196. package/dist/services/capabilities/contract.js.map +1 -0
  197. package/dist/services/capabilities/endpoint-validator.d.ts +42 -0
  198. package/dist/services/capabilities/endpoint-validator.js +113 -0
  199. package/dist/services/capabilities/endpoint-validator.js.map +1 -0
  200. package/dist/services/capabilities/health.d.ts +16 -0
  201. package/dist/services/capabilities/health.js +121 -0
  202. package/dist/services/capabilities/health.js.map +1 -0
  203. package/dist/services/capabilities/registry.d.ts +56 -0
  204. package/dist/services/capabilities/registry.js +222 -0
  205. package/dist/services/capabilities/registry.js.map +1 -0
  206. package/dist/services/capabilities/sync.d.ts +7 -0
  207. package/dist/services/capabilities/sync.js +223 -0
  208. package/dist/services/capabilities/sync.js.map +1 -0
  209. package/dist/services/capability-proxy/html-rewriters/browserless.d.ts +1 -0
  210. package/dist/services/capability-proxy/html-rewriters/browserless.js +83 -0
  211. package/dist/services/capability-proxy/html-rewriters/browserless.js.map +1 -0
  212. package/dist/services/capability-proxy/html-rewriters/index.d.ts +12 -0
  213. package/dist/services/capability-proxy/html-rewriters/index.js +25 -0
  214. package/dist/services/capability-proxy/html-rewriters/index.js.map +1 -0
  215. package/dist/services/capability-proxy/html-rewriters/jishukb.d.ts +1 -0
  216. package/dist/services/capability-proxy/html-rewriters/jishukb.js +161 -0
  217. package/dist/services/capability-proxy/html-rewriters/jishukb.js.map +1 -0
  218. package/dist/services/capability-proxy/http.d.ts +7 -0
  219. package/dist/services/capability-proxy/http.js +555 -0
  220. package/dist/services/capability-proxy/http.js.map +1 -0
  221. package/dist/services/capability-proxy/terminal.d.ts +4 -0
  222. package/dist/services/capability-proxy/terminal.js +179 -0
  223. package/dist/services/capability-proxy/terminal.js.map +1 -0
  224. package/dist/services/connections/admin.d.ts +80 -0
  225. package/dist/services/connections/admin.js +337 -0
  226. package/dist/services/connections/admin.js.map +1 -0
  227. package/dist/services/connections/apply.d.ts +104 -0
  228. package/dist/services/connections/apply.js +415 -0
  229. package/dist/services/connections/apply.js.map +1 -0
  230. package/dist/services/connections/resolver.d.ts +82 -0
  231. package/dist/services/connections/resolver.js +289 -0
  232. package/dist/services/connections/resolver.js.map +1 -0
  233. package/dist/services/connections/transactor.d.ts +39 -0
  234. package/dist/services/connections/transactor.js +307 -0
  235. package/dist/services/connections/transactor.js.map +1 -0
  236. package/dist/services/files/bootstrap.d.ts +7 -0
  237. package/dist/services/files/bootstrap.js +16 -0
  238. package/dist/services/files/bootstrap.js.map +1 -0
  239. package/dist/services/files/external-mounts.js +187 -0
  240. package/dist/services/files/external-mounts.js.map +1 -0
  241. package/dist/services/files/files-manager.d.ts +265 -0
  242. package/dist/services/files/files-manager.js +1189 -0
  243. package/dist/services/files/files-manager.js.map +1 -0
  244. package/dist/services/files/files-mounts.d.ts +42 -0
  245. package/dist/services/files/files-mounts.js +207 -0
  246. package/dist/services/files/files-mounts.js.map +1 -0
  247. package/dist/services/files/organize/applier.js +218 -0
  248. package/dist/services/files/organize/applier.js.map +1 -0
  249. package/dist/services/files/organize/rules.js +286 -0
  250. package/dist/services/files/organize/rules.js.map +1 -0
  251. package/dist/services/files/organize/scanner.js +366 -0
  252. package/dist/services/files/organize/scanner.js.map +1 -0
  253. package/dist/services/files/organize/store.js +82 -0
  254. package/dist/services/files/organize/store.js.map +1 -0
  255. package/dist/services/files/photos/upload-page.d.ts +2 -0
  256. package/dist/services/files/photos/upload-page.js +248 -0
  257. package/dist/services/files/photos/upload-page.js.map +1 -0
  258. package/dist/services/files/photos/upload-store.d.ts +74 -0
  259. package/dist/services/files/photos/upload-store.js +432 -0
  260. package/dist/services/files/photos/upload-store.js.map +1 -0
  261. package/dist/services/files/webdav/server.d.ts +47 -0
  262. package/dist/services/files/webdav/server.js +329 -0
  263. package/dist/services/files/webdav/server.js.map +1 -0
  264. package/dist/services/files/webdav/xml-builder.js.map +1 -0
  265. package/dist/services/http/proxy-utils.d.ts +7 -0
  266. package/dist/services/http/proxy-utils.js +29 -0
  267. package/dist/services/http/proxy-utils.js.map +1 -0
  268. package/dist/services/http/request-utils.d.ts +3 -0
  269. package/dist/services/http/request-utils.js +23 -0
  270. package/dist/services/http/request-utils.js.map +1 -0
  271. package/dist/services/instances/admin.d.ts +23 -0
  272. package/dist/services/instances/admin.js +218 -0
  273. package/dist/services/instances/admin.js.map +1 -0
  274. package/dist/services/instances/clone.d.ts +26 -0
  275. package/dist/services/instances/clone.js +78 -0
  276. package/dist/services/instances/clone.js.map +1 -0
  277. package/dist/services/instances/config-admin.d.ts +17 -0
  278. package/dist/services/instances/config-admin.js +181 -0
  279. package/dist/services/instances/config-admin.js.map +1 -0
  280. package/dist/services/instances/manager.d.ts +232 -0
  281. package/dist/services/instances/manager.js +1342 -0
  282. package/dist/services/instances/manager.js.map +1 -0
  283. package/dist/services/instances/pairing.d.ts +17 -0
  284. package/dist/services/instances/pairing.js +53 -0
  285. package/dist/services/instances/pairing.js.map +1 -0
  286. package/dist/services/instances/passwords.js +173 -0
  287. package/dist/services/instances/passwords.js.map +1 -0
  288. package/dist/services/instances/status.d.ts +2 -0
  289. package/dist/services/instances/status.js +11 -0
  290. package/dist/services/instances/status.js.map +1 -0
  291. package/dist/services/instances/types.d.ts +21 -0
  292. package/dist/services/instances/types.js +2 -0
  293. package/dist/services/instances/types.js.map +1 -0
  294. package/dist/services/integrations/anythingllm/integration.d.ts +25 -0
  295. package/dist/services/integrations/anythingllm/integration.js +251 -0
  296. package/dist/services/integrations/anythingllm/integration.js.map +1 -0
  297. package/dist/services/integrations/catalog.d.ts +3 -0
  298. package/dist/services/integrations/catalog.js +73 -0
  299. package/dist/services/integrations/catalog.js.map +1 -0
  300. package/dist/services/integrations/custom/integration.d.ts +28 -0
  301. package/dist/services/integrations/custom/integration.js +179 -0
  302. package/dist/services/integrations/custom/integration.js.map +1 -0
  303. package/dist/services/integrations/hermes/integration.d.ts +194 -0
  304. package/dist/services/integrations/hermes/integration.js +1668 -0
  305. package/dist/services/integrations/hermes/integration.js.map +1 -0
  306. package/dist/services/integrations/immich/client.d.ts +93 -0
  307. package/dist/services/integrations/immich/client.js +458 -0
  308. package/dist/services/integrations/immich/client.js.map +1 -0
  309. package/dist/services/integrations/immich/config.d.ts +15 -0
  310. package/dist/services/integrations/immich/config.js +178 -0
  311. package/dist/services/integrations/immich/config.js.map +1 -0
  312. package/dist/services/integrations/immich/discovery.d.ts +9 -0
  313. package/dist/services/integrations/immich/discovery.js +101 -0
  314. package/dist/services/integrations/immich/discovery.js.map +1 -0
  315. package/dist/services/integrations/immich/gallery-renderer.d.ts +5 -0
  316. package/dist/services/integrations/immich/gallery-renderer.js +150 -0
  317. package/dist/services/integrations/immich/gallery-renderer.js.map +1 -0
  318. package/dist/services/integrations/immich/immich-shim.d.ts +11 -0
  319. package/dist/services/integrations/immich/immich-shim.js +439 -0
  320. package/dist/services/integrations/immich/immich-shim.js.map +1 -0
  321. package/dist/services/integrations/immich/integration.d.ts +18 -0
  322. package/dist/services/integrations/immich/integration.js +64 -0
  323. package/dist/services/integrations/immich/integration.js.map +1 -0
  324. package/dist/services/integrations/immich/photo-library.d.ts +4 -0
  325. package/dist/services/integrations/immich/photo-library.js +63 -0
  326. package/dist/services/integrations/immich/photo-library.js.map +1 -0
  327. package/dist/services/integrations/immich/review-executor.d.ts +3 -0
  328. package/dist/services/integrations/immich/review-executor.js +41 -0
  329. package/dist/services/integrations/immich/review-executor.js.map +1 -0
  330. package/dist/services/integrations/immich/review-session-service.d.ts +27 -0
  331. package/dist/services/integrations/immich/review-session-service.js +206 -0
  332. package/dist/services/integrations/immich/review-session-service.js.map +1 -0
  333. package/dist/services/integrations/immich/review-store.d.ts +47 -0
  334. package/dist/services/integrations/immich/review-store.js +347 -0
  335. package/dist/services/integrations/immich/review-store.js.map +1 -0
  336. package/dist/services/integrations/immich/routes.d.ts +7 -0
  337. package/dist/services/integrations/immich/routes.js +363 -0
  338. package/dist/services/integrations/immich/routes.js.map +1 -0
  339. package/dist/services/integrations/immich/types.d.ts +186 -0
  340. package/dist/services/integrations/immich/types.js +2 -0
  341. package/dist/services/integrations/immich/types.js.map +1 -0
  342. package/dist/services/integrations/index.d.ts +41 -0
  343. package/dist/services/integrations/index.js +60 -0
  344. package/dist/services/integrations/index.js.map +1 -0
  345. package/dist/services/integrations/installable/catalog.d.ts +33 -0
  346. package/dist/services/integrations/installable/catalog.js +88 -0
  347. package/dist/services/integrations/installable/catalog.js.map +1 -0
  348. package/dist/services/integrations/installable/index.d.ts +35 -0
  349. package/dist/services/integrations/installable/index.js +170 -0
  350. package/dist/services/integrations/installable/index.js.map +1 -0
  351. package/dist/services/integrations/installable/installers/integration-probes.d.ts +50 -0
  352. package/dist/services/integrations/installable/installers/integration-probes.js +231 -0
  353. package/dist/services/integrations/installable/installers/integration-probes.js.map +1 -0
  354. package/dist/services/integrations/installable/installers/integration.d.ts +30 -0
  355. package/dist/services/integrations/installable/installers/integration.js +283 -0
  356. package/dist/services/integrations/installable/installers/integration.js.map +1 -0
  357. package/dist/services/integrations/installable/installers/registry-probe.js.map +1 -0
  358. package/dist/services/integrations/installable/installers/shell-script.d.ts +46 -0
  359. package/dist/services/integrations/installable/installers/shell-script.js +487 -0
  360. package/dist/services/integrations/installable/installers/shell-script.js.map +1 -0
  361. package/dist/services/integrations/installable/types.d.ts +130 -0
  362. package/dist/services/integrations/installable/types.js +19 -0
  363. package/dist/services/integrations/installable/types.js.map +1 -0
  364. package/dist/services/integrations/jishukb/integration.d.ts +24 -0
  365. package/dist/services/integrations/jishukb/integration.js +300 -0
  366. package/dist/services/integrations/jishukb/integration.js.map +1 -0
  367. package/dist/services/integrations/openclaw/anythingllm-shim.d.ts +46 -0
  368. package/dist/services/integrations/openclaw/anythingllm-shim.js +281 -0
  369. package/dist/services/integrations/openclaw/anythingllm-shim.js.map +1 -0
  370. package/dist/services/integrations/openclaw/drive-shim.js +490 -0
  371. package/dist/services/integrations/openclaw/drive-shim.js.map +1 -0
  372. package/dist/services/integrations/openclaw/integration.d.ts +438 -0
  373. package/dist/services/integrations/openclaw/integration.js +4629 -0
  374. package/dist/services/integrations/openclaw/integration.js.map +1 -0
  375. package/dist/services/integrations/openclaw/jishukb-native-mcp.d.ts +58 -0
  376. package/dist/services/integrations/openclaw/jishukb-native-mcp.js +373 -0
  377. package/dist/services/integrations/openclaw/jishukb-native-mcp.js.map +1 -0
  378. package/dist/services/integrations/openclaw/jishukb-shim.d.ts +52 -0
  379. package/dist/services/integrations/openclaw/jishukb-shim.js +1357 -0
  380. package/dist/services/integrations/openclaw/jishukb-shim.js.map +1 -0
  381. package/dist/services/integrations/openclaw/mcporter-lite.js +276 -0
  382. package/dist/services/integrations/openclaw/mcporter-lite.js.map +1 -0
  383. package/dist/services/integrations/openclaw/mcporter.d.ts +59 -0
  384. package/dist/services/integrations/openclaw/mcporter.js +143 -0
  385. package/dist/services/integrations/openclaw/mcporter.js.map +1 -0
  386. package/dist/services/integrations/openclaw/native-mcp.d.ts +48 -0
  387. package/dist/services/integrations/openclaw/native-mcp.js +125 -0
  388. package/dist/services/integrations/openclaw/native-mcp.js.map +1 -0
  389. package/dist/services/integrations/openclaw/routes.d.ts +21 -0
  390. package/dist/services/integrations/openclaw/routes.js +1194 -0
  391. package/dist/services/integrations/openclaw/routes.js.map +1 -0
  392. package/dist/services/integrations/registry.d.ts +17 -0
  393. package/dist/services/integrations/registry.js +36 -0
  394. package/dist/services/integrations/registry.js.map +1 -0
  395. package/dist/services/integrations/routes.d.ts +2 -0
  396. package/dist/services/integrations/routes.js +9 -0
  397. package/dist/services/integrations/routes.js.map +1 -0
  398. package/dist/services/integrations/types.d.ts +457 -0
  399. package/dist/services/integrations/types.js +2 -0
  400. package/dist/services/integrations/types.js.map +1 -0
  401. package/dist/services/legacy-migrator/classifier.d.ts +44 -0
  402. package/dist/services/legacy-migrator/classifier.js +309 -0
  403. package/dist/services/legacy-migrator/classifier.js.map +1 -0
  404. package/dist/services/legacy-migrator/executor.d.ts +42 -0
  405. package/dist/services/legacy-migrator/executor.js +637 -0
  406. package/dist/services/legacy-migrator/executor.js.map +1 -0
  407. package/dist/services/legacy-migrator/index.d.ts +31 -0
  408. package/dist/services/legacy-migrator/index.js +34 -0
  409. package/dist/services/legacy-migrator/index.js.map +1 -0
  410. package/dist/services/legacy-migrator/planner.d.ts +8 -0
  411. package/dist/services/legacy-migrator/planner.js +154 -0
  412. package/dist/services/legacy-migrator/planner.js.map +1 -0
  413. package/dist/services/legacy-migrator/provider-settings.d.ts +6 -0
  414. package/dist/services/legacy-migrator/provider-settings.js +72 -0
  415. package/dist/services/legacy-migrator/provider-settings.js.map +1 -0
  416. package/dist/services/legacy-migrator/report.d.ts +9 -0
  417. package/dist/services/legacy-migrator/report.js +99 -0
  418. package/dist/services/legacy-migrator/report.js.map +1 -0
  419. package/dist/services/legacy-migrator/scanner.d.ts +13 -0
  420. package/dist/services/legacy-migrator/scanner.js +157 -0
  421. package/dist/services/legacy-migrator/scanner.js.map +1 -0
  422. package/dist/services/legacy-migrator/types.d.ts +97 -0
  423. package/dist/services/legacy-migrator/types.js +23 -0
  424. package/dist/services/legacy-migrator/types.js.map +1 -0
  425. package/dist/services/llm-proxy/instance-proxy.d.ts +17 -1
  426. package/dist/services/llm-proxy/instance-proxy.js +171 -44
  427. package/dist/services/llm-proxy/instance-proxy.js.map +1 -1
  428. package/dist/services/llm-proxy/probe.js +5 -14
  429. package/dist/services/llm-proxy/probe.js.map +1 -1
  430. package/dist/services/llm-proxy/providers.js +23 -31
  431. package/dist/services/llm-proxy/providers.js.map +1 -1
  432. package/dist/services/llm-proxy/ssrf.d.ts +11 -4
  433. package/dist/services/llm-proxy/ssrf.js +45 -7
  434. package/dist/services/llm-proxy/ssrf.js.map +1 -1
  435. package/dist/services/llm-proxy/validate-key.js +16 -37
  436. package/dist/services/llm-proxy/validate-key.js.map +1 -1
  437. package/dist/services/repair/runtime-repair.d.ts +22 -0
  438. package/dist/services/repair/runtime-repair.js +374 -0
  439. package/dist/services/repair/runtime-repair.js.map +1 -0
  440. package/dist/services/runtime/docker-network.d.ts +8 -0
  441. package/dist/services/runtime/docker-network.js +123 -0
  442. package/dist/services/runtime/docker-network.js.map +1 -0
  443. package/dist/services/runtime/driver-registry.d.ts +25 -0
  444. package/dist/services/runtime/driver-registry.js +22 -0
  445. package/dist/services/runtime/driver-registry.js.map +1 -0
  446. package/dist/services/runtime/drivers/nomad.d.ts +261 -0
  447. package/dist/services/runtime/drivers/nomad.js +3122 -0
  448. package/dist/services/runtime/drivers/nomad.js.map +1 -0
  449. package/dist/services/runtime/errors.d.ts +3 -3
  450. package/dist/services/runtime/errors.js +3 -3
  451. package/dist/services/runtime/instance.d.ts +14 -16
  452. package/dist/services/runtime/instance.js +93 -123
  453. package/dist/services/runtime/instance.js.map +1 -1
  454. package/dist/services/runtime/job-id.d.ts +1 -1
  455. package/dist/services/runtime/job-id.js +1 -1
  456. package/dist/services/runtime/mcp-shims/firewall.d.ts +2 -2
  457. package/dist/services/runtime/mcp-shims/firewall.js +2 -2
  458. package/dist/services/runtime/mcp-shims/searxng-shim.d.ts +3 -5
  459. package/dist/services/runtime/mcp-shims/searxng-shim.js +3 -5
  460. package/dist/services/runtime/mcp-shims/searxng-shim.js.map +1 -1
  461. package/dist/services/runtime/mcp-shims/write-mcp-entry.d.ts +20 -20
  462. package/dist/services/runtime/mcp-shims/write-mcp-entry.js +16 -16
  463. package/dist/services/runtime/mcp-shims/write-mcp-entry.js.map +1 -1
  464. package/dist/services/runtime/ownership-marker.d.ts +83 -0
  465. package/dist/services/runtime/ownership-marker.js +109 -0
  466. package/dist/services/runtime/ownership-marker.js.map +1 -0
  467. package/dist/services/runtime/service-manager.d.ts +2 -0
  468. package/dist/services/runtime/service-manager.js +18 -0
  469. package/dist/services/runtime/service-manager.js.map +1 -0
  470. package/dist/services/runtime/types.d.ts +23 -501
  471. package/dist/services/runtime/types.js +0 -12
  472. package/dist/services/runtime/types.js.map +1 -1
  473. package/dist/services/runtime/workload-compiler.d.ts +17 -0
  474. package/dist/services/runtime/workload-compiler.js +550 -0
  475. package/dist/services/runtime/workload-compiler.js.map +1 -0
  476. package/dist/services/runtime/workload-types.d.ts +11 -0
  477. package/dist/services/runtime/workload-types.js +2 -0
  478. package/dist/services/runtime/workload-types.js.map +1 -0
  479. package/dist/services/setup/core-manager.d.ts +50 -0
  480. package/dist/services/setup/core-manager.js +456 -0
  481. package/dist/services/setup/core-manager.js.map +1 -0
  482. package/dist/services/setup/plugin-installer.js +136 -0
  483. package/dist/services/setup/plugin-installer.js.map +1 -0
  484. package/dist/services/setup/setup-manager.d.ts +158 -0
  485. package/dist/services/setup/setup-manager.js +2724 -0
  486. package/dist/services/setup/setup-manager.js.map +1 -0
  487. package/dist/services/system/cli-command.d.ts +5 -0
  488. package/dist/services/system/cli-command.js +18 -0
  489. package/dist/services/system/cli-command.js.map +1 -0
  490. package/dist/services/system/macos-launchd.js +312 -0
  491. package/dist/services/system/macos-launchd.js.map +1 -0
  492. package/dist/services/system/repair-orchestrator.d.ts +71 -0
  493. package/dist/services/system/repair-orchestrator.js +412 -0
  494. package/dist/services/system/repair-orchestrator.js.map +1 -0
  495. package/dist/services/system/runtime-ownership.d.ts +36 -0
  496. package/dist/services/system/runtime-ownership.js +250 -0
  497. package/dist/services/system/runtime-ownership.js.map +1 -0
  498. package/dist/services/system/system-monitor.js +96 -0
  499. package/dist/services/system/system-monitor.js.map +1 -0
  500. package/dist/services/system/system-ollama-provider.d.ts +14 -0
  501. package/dist/services/system/system-ollama-provider.js +129 -0
  502. package/dist/services/system/system-ollama-provider.js.map +1 -0
  503. package/dist/services/system/system-reconciler.d.ts +59 -0
  504. package/dist/services/system/system-reconciler.js +763 -0
  505. package/dist/services/system/system-reconciler.js.map +1 -0
  506. package/dist/services/system/update-manager.d.ts +43 -0
  507. package/dist/services/system/update-manager.js +315 -0
  508. package/dist/services/system/update-manager.js.map +1 -0
  509. package/dist/services/system/upgrade-finalize.d.ts +80 -0
  510. package/dist/services/system/upgrade-finalize.js +507 -0
  511. package/dist/services/system/upgrade-finalize.js.map +1 -0
  512. package/dist/services/tasks/registry.d.ts +44 -0
  513. package/dist/services/tasks/registry.js +90 -0
  514. package/dist/services/tasks/registry.js.map +1 -0
  515. package/dist/services/telemetry/activation.d.ts +6 -2
  516. package/dist/services/telemetry/activation.js +6 -2
  517. package/dist/services/telemetry/activation.js.map +1 -1
  518. package/dist/services/telemetry/heartbeat.d.ts +6 -2
  519. package/dist/services/telemetry/heartbeat.js +6 -2
  520. package/dist/services/telemetry/heartbeat.js.map +1 -1
  521. package/dist/services/workspaces/builder.d.ts +29 -0
  522. package/dist/services/workspaces/builder.js +186 -0
  523. package/dist/services/workspaces/builder.js.map +1 -0
  524. package/dist/types.d.ts +350 -48
  525. package/dist/utils/instance-lock.d.ts +2 -2
  526. package/dist/utils/instance-lock.js +2 -2
  527. package/dist/utils/path-safety.js +1 -1
  528. package/dist/utils/service-user.d.ts +13 -0
  529. package/dist/utils/service-user.js +129 -0
  530. package/dist/utils/service-user.js.map +1 -0
  531. package/install/jishu-install.sh +107 -27
  532. package/install/jishu-uninstall.sh +8 -0
  533. package/install/post-install.sh +162 -185
  534. package/install/post-uninstall.sh +6 -0
  535. package/node_modules/@fastify/static/.github/workflows/ci.yml +1 -1
  536. package/node_modules/@fastify/static/.github/workflows/lock-threads.yml +19 -0
  537. package/node_modules/@fastify/static/LICENSE +1 -3
  538. package/node_modules/@fastify/static/example/server-benchmark.js +39 -0
  539. package/node_modules/@fastify/static/index.js +169 -23
  540. package/node_modules/@fastify/static/lib/dirList.js +20 -6
  541. package/node_modules/@fastify/static/package.json +10 -8
  542. package/node_modules/@fastify/static/test/dir-list.test.js +82 -0
  543. package/node_modules/@fastify/static/test/static.test.js +326 -4
  544. package/node_modules/@fastify/static/types/index.d.ts +0 -4
  545. package/node_modules/@fastify/static/types/index.test-d.ts +1 -1
  546. package/node_modules/brace-expansion/dist/commonjs/index.js +24 -14
  547. package/node_modules/brace-expansion/dist/commonjs/index.js.map +1 -1
  548. package/node_modules/brace-expansion/dist/esm/index.js +24 -14
  549. package/node_modules/brace-expansion/dist/esm/index.js.map +1 -1
  550. package/node_modules/brace-expansion/package.json +2 -2
  551. package/node_modules/content-disposition/README.md +21 -22
  552. package/node_modules/content-disposition/index.js +122 -44
  553. package/node_modules/content-disposition/package.json +16 -20
  554. package/node_modules/fast-uri/index.js +1 -1
  555. package/node_modules/fast-uri/package.json +1 -1
  556. package/node_modules/fast-uri/test/security.test.js +28 -0
  557. package/node_modules/fastify/SECURITY.md +1 -1
  558. package/node_modules/fastify/SPONSORS.md +6 -4
  559. package/node_modules/fastify/docs/Guides/Database.md +0 -28
  560. package/node_modules/fastify/docs/Guides/Ecosystem.md +13 -2
  561. package/node_modules/fastify/docs/Guides/Serverless.md +2 -2
  562. package/node_modules/fastify/docs/Guides/Write-Plugin.md +1 -1
  563. package/node_modules/fastify/docs/Reference/Encapsulation.md +27 -26
  564. package/node_modules/fastify/docs/Reference/Errors.md +10 -4
  565. package/node_modules/fastify/docs/Reference/HTTP2.md +10 -10
  566. package/node_modules/fastify/docs/Reference/Hooks.md +4 -4
  567. package/node_modules/fastify/docs/Reference/Index.md +14 -16
  568. package/node_modules/fastify/docs/Reference/LTS.md +12 -13
  569. package/node_modules/fastify/docs/Reference/Lifecycle.md +9 -8
  570. package/node_modules/fastify/docs/Reference/Logging.md +44 -39
  571. package/node_modules/fastify/docs/Reference/Middleware.md +21 -25
  572. package/node_modules/fastify/docs/Reference/Principles.md +2 -2
  573. package/node_modules/fastify/docs/Reference/Reply.md +6 -1
  574. package/node_modules/fastify/docs/Reference/Request.md +27 -16
  575. package/node_modules/fastify/docs/Reference/Routes.md +5 -2
  576. package/node_modules/fastify/docs/Reference/Server.md +31 -3
  577. package/node_modules/fastify/docs/Reference/Type-Providers.md +29 -5
  578. package/node_modules/fastify/docs/Reference/Validation-and-Serialization.md +15 -2
  579. package/node_modules/fastify/docs/Reference/Warnings.md +7 -6
  580. package/node_modules/fastify/eslint.config.js +7 -2
  581. package/node_modules/fastify/fastify.d.ts +8 -3
  582. package/node_modules/fastify/fastify.js +43 -14
  583. package/node_modules/fastify/lib/content-type-parser.js +13 -1
  584. package/node_modules/fastify/lib/decorate.js +11 -3
  585. package/node_modules/fastify/lib/error-handler.js +4 -3
  586. package/node_modules/fastify/lib/error-serializer.js +59 -59
  587. package/node_modules/fastify/lib/errors.js +16 -1
  588. package/node_modules/fastify/lib/four-oh-four.js +14 -9
  589. package/node_modules/fastify/lib/handle-request.js +11 -5
  590. package/node_modules/fastify/lib/plugin-override.js +2 -1
  591. package/node_modules/fastify/lib/plugin-utils.js +5 -5
  592. package/node_modules/fastify/lib/reply.js +63 -8
  593. package/node_modules/fastify/lib/request.js +14 -4
  594. package/node_modules/fastify/lib/route.js +20 -6
  595. package/node_modules/fastify/lib/schema-controller.js +1 -1
  596. package/node_modules/fastify/lib/schemas.js +37 -30
  597. package/node_modules/fastify/lib/symbols.js +3 -1
  598. package/node_modules/fastify/lib/validation.js +1 -13
  599. package/node_modules/fastify/lib/warnings.js +3 -3
  600. package/node_modules/fastify/package.json +13 -15
  601. package/node_modules/fastify/scripts/validate-ecosystem-links.js +1 -0
  602. package/node_modules/fastify/test/bundler/esbuild/package.json +1 -1
  603. package/node_modules/fastify/test/close-pipelining.test.js +1 -2
  604. package/node_modules/fastify/test/custom-http-server.test.js +38 -0
  605. package/node_modules/fastify/test/decorator-instance-properties.test.js +63 -0
  606. package/node_modules/fastify/test/diagnostics-channel/async-error-handler.test.js +74 -0
  607. package/node_modules/fastify/test/hooks.test.js +23 -0
  608. package/node_modules/fastify/test/http-methods/get.test.js +1 -1
  609. package/node_modules/fastify/test/http2/plain.test.js +135 -0
  610. package/node_modules/fastify/test/http2/secure-with-fallback.test.js +1 -1
  611. package/node_modules/fastify/test/https/https.test.js +1 -2
  612. package/node_modules/fastify/test/internals/errors.test.js +31 -1
  613. package/node_modules/fastify/test/internals/plugin.test.js +3 -1
  614. package/node_modules/fastify/test/internals/request.test.js +27 -3
  615. package/node_modules/fastify/test/internals/schema-controller-perf.test.js +33 -0
  616. package/node_modules/fastify/test/logger/logging.test.js +18 -1
  617. package/node_modules/fastify/test/logger/options.test.js +38 -1
  618. package/node_modules/fastify/test/reply-error.test.js +1 -1
  619. package/node_modules/fastify/test/reply-trailers.test.js +70 -0
  620. package/node_modules/fastify/test/request-media-type.test.js +105 -0
  621. package/node_modules/fastify/test/route-prefix.test.js +34 -0
  622. package/node_modules/fastify/test/router-options.test.js +222 -11
  623. package/node_modules/fastify/test/schema-serialization.test.js +108 -0
  624. package/node_modules/fastify/test/schema-validation.test.js +24 -0
  625. package/node_modules/fastify/test/scripts/validate-ecosystem-links.test.js +40 -57
  626. package/node_modules/fastify/test/throw.test.js +14 -0
  627. package/node_modules/fastify/test/trust-proxy.test.js +21 -0
  628. package/node_modules/fastify/test/types/content-type-parser.tst.ts +70 -0
  629. package/node_modules/fastify/test/types/decorate-request-reply.tst.ts +18 -0
  630. package/node_modules/fastify/test/types/dummy-plugin.mts +9 -0
  631. package/node_modules/fastify/test/types/errors.tst.ts +91 -0
  632. package/node_modules/fastify/test/types/fastify.tst.ts +351 -0
  633. package/node_modules/fastify/test/types/hooks.tst.ts +578 -0
  634. package/node_modules/fastify/test/types/instance.tst.ts +597 -0
  635. package/node_modules/fastify/test/types/logger.tst.ts +276 -0
  636. package/node_modules/fastify/test/types/plugin.tst.ts +96 -0
  637. package/node_modules/fastify/test/types/register.tst.ts +245 -0
  638. package/node_modules/fastify/test/types/reply.tst.ts +297 -0
  639. package/node_modules/fastify/test/types/request.tst.ts +199 -0
  640. package/node_modules/fastify/test/types/route.tst.ts +576 -0
  641. package/node_modules/fastify/test/types/schema.tst.ts +135 -0
  642. package/node_modules/fastify/test/types/serverFactory.tst.ts +37 -0
  643. package/node_modules/fastify/test/types/tsconfig.json +9 -0
  644. package/node_modules/fastify/test/types/type-provider.tst.ts +1219 -0
  645. package/node_modules/fastify/test/types/using.tst.ts +14 -0
  646. package/node_modules/fastify/types/errors.d.ts +3 -0
  647. package/node_modules/fastify/types/request.d.ts +23 -2
  648. package/node_modules/glob/README.md +39 -130
  649. package/node_modules/glob/dist/commonjs/glob.d.ts +8 -0
  650. package/node_modules/glob/dist/commonjs/glob.d.ts.map +1 -1
  651. package/node_modules/glob/dist/commonjs/glob.js +2 -1
  652. package/node_modules/glob/dist/commonjs/glob.js.map +1 -1
  653. package/node_modules/glob/dist/commonjs/index.min.js +4 -0
  654. package/node_modules/glob/dist/commonjs/index.min.js.map +7 -0
  655. package/node_modules/glob/dist/commonjs/pattern.d.ts +3 -0
  656. package/node_modules/glob/dist/commonjs/pattern.d.ts.map +1 -1
  657. package/node_modules/glob/dist/commonjs/pattern.js +4 -0
  658. package/node_modules/glob/dist/commonjs/pattern.js.map +1 -1
  659. package/node_modules/glob/dist/esm/glob.d.ts +8 -0
  660. package/node_modules/glob/dist/esm/glob.d.ts.map +1 -1
  661. package/node_modules/glob/dist/esm/glob.js +2 -1
  662. package/node_modules/glob/dist/esm/glob.js.map +1 -1
  663. package/node_modules/glob/dist/esm/index.min.js +4 -0
  664. package/node_modules/glob/dist/esm/index.min.js.map +7 -0
  665. package/node_modules/glob/dist/esm/pattern.d.ts +3 -0
  666. package/node_modules/glob/dist/esm/pattern.d.ts.map +1 -1
  667. package/node_modules/glob/dist/esm/pattern.js +4 -0
  668. package/node_modules/glob/dist/esm/pattern.js.map +1 -1
  669. package/node_modules/glob/package.json +38 -37
  670. package/node_modules/jishushell-panel/README.md +4 -4
  671. package/node_modules/jishushell-panel/output/dist/server.js +17 -6
  672. package/node_modules/jishushell-panel/output/dist/server.js.map +1 -1
  673. package/node_modules/jishushell-panel/output/public/assets/ApiKeyField-Ce5d1xna.js +1 -0
  674. package/node_modules/jishushell-panel/output/public/assets/Dashboard-BXame3yg.js +1 -0
  675. package/node_modules/jishushell-panel/output/public/assets/HermesChatPanel-BHZtPCJd.js +1 -0
  676. package/node_modules/jishushell-panel/output/public/assets/HermesConfigForm-CB3GbNX9.js +4 -0
  677. package/node_modules/jishushell-panel/output/public/assets/InitPassword-Boab9F6g.js +1 -0
  678. package/node_modules/jishushell-panel/output/public/assets/InstanceDetail-DrIWCqo-.js +14 -0
  679. package/node_modules/jishushell-panel/output/public/assets/Login-CzpOkNau.js +1 -0
  680. package/node_modules/jishushell-panel/output/public/assets/NewInstance-CANXyCcL.js +1 -0
  681. package/node_modules/jishushell-panel/output/public/assets/ProviderRecommendations-BABo9VOC.js +1 -0
  682. package/node_modules/jishushell-panel/output/public/assets/Settings-CKp5XxFh.js +1 -0
  683. package/node_modules/jishushell-panel/output/public/assets/Setup-C7xVDPow.js +1 -0
  684. package/node_modules/jishushell-panel/output/public/assets/WeixinLoginPanel-B765Xz4C.js +1 -0
  685. package/node_modules/jishushell-panel/output/public/assets/api-C70Gt678.js +4 -0
  686. package/node_modules/jishushell-panel/output/public/assets/index-Bs6DSbiR.js +23 -0
  687. package/node_modules/jishushell-panel/output/public/assets/index-DnnqTf7s.css +1 -0
  688. package/node_modules/jishushell-panel/output/public/assets/registry-sWIZsIEF.js +2 -0
  689. package/node_modules/jishushell-panel/output/public/assets/rolldown-runtime-QTnfLwEv.js +1 -0
  690. package/node_modules/jishushell-panel/output/public/assets/setup-task-q21GnI0E.js +1 -0
  691. package/node_modules/jishushell-panel/output/public/assets/usePolling-D4IDOQd_.js +1 -0
  692. package/node_modules/jishushell-panel/output/public/assets/vendor-i18n-Df8aUdv8.js +1 -0
  693. package/node_modules/jishushell-panel/output/public/assets/vendor-react-0L0rjmYG.js +8 -0
  694. package/node_modules/jishushell-panel/output/public/index.html +6 -4
  695. package/node_modules/jishushell-panel/package.json +2 -2
  696. package/node_modules/semver/classes/range.js +17 -4
  697. package/node_modules/semver/package.json +2 -2
  698. package/package.json +12 -64
  699. package/scripts/check-app-path-boundaries.mjs +121 -0
  700. package/scripts/check-app-spec.mjs +123 -29
  701. package/scripts/check-architecture-boundaries.mjs +178 -0
  702. package/scripts/check-colima-launchd.mjs +10 -8
  703. package/scripts/check-integration-isolation.ts +541 -0
  704. package/scripts/check-new-file-tests.mjs +11 -3
  705. package/scripts/check-open-core-boundaries.mjs +60 -10
  706. package/scripts/check-test-layering.sh +1 -1
  707. package/scripts/fixtures/instances/hermes-sample/instance.json +3 -2
  708. package/scripts/fixtures/instances/legacy-openclaw-sample/instance.json +1 -1
  709. package/scripts/local-web-upgrade-test.README +4 -3
  710. package/scripts/local-web-upgrade-test.example.env +2 -2
  711. package/scripts/local-web-upgrade-test.sh +14 -1
  712. package/scripts/pack-gui-and-send-pi.sh +43 -0
  713. package/scripts/perf/instances.js +1 -1
  714. package/scripts/prune-open-core-dist.mjs +89 -2
  715. package/scripts/smoke/hermes-bootstrap.sh +5 -5
  716. package/templates/hermes-entrypoint.sh +19 -29
  717. package/apps/openwebui-container.yaml +0 -97
  718. package/apps/playwright-container.yaml +0 -126
  719. package/dependencies/jishushell-panel-0.6.5.tgz +0 -0
  720. package/dist/crypto-shim.d.ts +0 -1
  721. package/dist/crypto-shim.js +0 -2
  722. package/dist/crypto-shim.js.map +0 -1
  723. package/dist/routes/agent-apps.d.ts +0 -14
  724. package/dist/routes/agent-apps.js +0 -77
  725. package/dist/routes/agent-apps.js.map +0 -1
  726. package/dist/routes/internal.d.ts +0 -2
  727. package/dist/routes/internal.js +0 -55
  728. package/dist/routes/internal.js.map +0 -1
  729. package/dist/routes/openclaw-routes.d.ts +0 -22
  730. package/dist/routes/openclaw-routes.js +0 -1020
  731. package/dist/routes/openclaw-routes.js.map +0 -1
  732. package/dist/routes/runtime.d.ts +0 -15
  733. package/dist/routes/runtime.js +0 -76
  734. package/dist/routes/runtime.js.map +0 -1
  735. package/dist/services/agent-apps/catalog.d.ts +0 -33
  736. package/dist/services/agent-apps/catalog.js +0 -88
  737. package/dist/services/agent-apps/catalog.js.map +0 -1
  738. package/dist/services/agent-apps/index.d.ts +0 -36
  739. package/dist/services/agent-apps/index.js +0 -171
  740. package/dist/services/agent-apps/index.js.map +0 -1
  741. package/dist/services/agent-apps/installers/adapter-probes.d.ts +0 -49
  742. package/dist/services/agent-apps/installers/adapter-probes.js +0 -230
  743. package/dist/services/agent-apps/installers/adapter-probes.js.map +0 -1
  744. package/dist/services/agent-apps/installers/adapter.d.ts +0 -30
  745. package/dist/services/agent-apps/installers/adapter.js +0 -171
  746. package/dist/services/agent-apps/installers/adapter.js.map +0 -1
  747. package/dist/services/agent-apps/installers/registry-probe.js.map +0 -1
  748. package/dist/services/agent-apps/installers/shell-script.d.ts +0 -47
  749. package/dist/services/agent-apps/installers/shell-script.js +0 -488
  750. package/dist/services/agent-apps/installers/shell-script.js.map +0 -1
  751. package/dist/services/agent-apps/types.d.ts +0 -128
  752. package/dist/services/agent-apps/types.js +0 -17
  753. package/dist/services/agent-apps/types.js.map +0 -1
  754. package/dist/services/app/app-compiler.js +0 -185
  755. package/dist/services/app/app-compiler.js.map +0 -1
  756. package/dist/services/app/app-manager.d.ts +0 -184
  757. package/dist/services/app/app-manager.js +0 -2933
  758. package/dist/services/app/app-manager.js.map +0 -1
  759. package/dist/services/app/custom-manager.d.ts +0 -27
  760. package/dist/services/app/custom-manager.js +0 -382
  761. package/dist/services/app/custom-manager.js.map +0 -1
  762. package/dist/services/app/hermes-agent-manager.d.ts +0 -20
  763. package/dist/services/app/hermes-agent-manager.js +0 -299
  764. package/dist/services/app/hermes-agent-manager.js.map +0 -1
  765. package/dist/services/app/id-normalizer.d.ts +0 -27
  766. package/dist/services/app/id-normalizer.js +0 -77
  767. package/dist/services/app/id-normalizer.js.map +0 -1
  768. package/dist/services/app/ollama-manager.d.ts +0 -18
  769. package/dist/services/app/ollama-manager.js +0 -224
  770. package/dist/services/app/ollama-manager.js.map +0 -1
  771. package/dist/services/app/openclaw-manager.d.ts +0 -63
  772. package/dist/services/app/openclaw-manager.js +0 -1215
  773. package/dist/services/app/openclaw-manager.js.map +0 -1
  774. package/dist/services/app/paths.d.ts +0 -27
  775. package/dist/services/app/paths.js +0 -40
  776. package/dist/services/app/paths.js.map +0 -1
  777. package/dist/services/app/platform-transform.d.ts +0 -32
  778. package/dist/services/app/platform-transform.js +0 -65
  779. package/dist/services/app/platform-transform.js.map +0 -1
  780. package/dist/services/app/provide-resolver.d.ts +0 -29
  781. package/dist/services/app/provide-resolver.js +0 -135
  782. package/dist/services/app/provide-resolver.js.map +0 -1
  783. package/dist/services/app/registry.d.ts +0 -17
  784. package/dist/services/app/registry.js +0 -31
  785. package/dist/services/app/registry.js.map +0 -1
  786. package/dist/services/app/remote-spec.d.ts +0 -14
  787. package/dist/services/app/remote-spec.js +0 -58
  788. package/dist/services/app/remote-spec.js.map +0 -1
  789. package/dist/services/app/terminal-session-manager.js +0 -157
  790. package/dist/services/app/terminal-session-manager.js.map +0 -1
  791. package/dist/services/app/types.d.ts +0 -74
  792. package/dist/services/app/types.js +0 -16
  793. package/dist/services/app/types.js.map +0 -1
  794. package/dist/services/app-config-admin.d.ts +0 -17
  795. package/dist/services/app-config-admin.js +0 -177
  796. package/dist/services/app-config-admin.js.map +0 -1
  797. package/dist/services/app-create-from-installed.d.ts +0 -23
  798. package/dist/services/app-create-from-installed.js +0 -75
  799. package/dist/services/app-create-from-installed.js.map +0 -1
  800. package/dist/services/app-passwords.js +0 -173
  801. package/dist/services/app-passwords.js.map +0 -1
  802. package/dist/services/backup-admin.d.ts +0 -101
  803. package/dist/services/backup-admin.js +0 -259
  804. package/dist/services/backup-admin.js.map +0 -1
  805. package/dist/services/backup-manager.d.ts +0 -264
  806. package/dist/services/backup-manager.js +0 -2263
  807. package/dist/services/backup-manager.js.map +0 -1
  808. package/dist/services/backup-verify.js +0 -240
  809. package/dist/services/backup-verify.js.map +0 -1
  810. package/dist/services/capability-endpoint-validator.d.ts +0 -41
  811. package/dist/services/capability-endpoint-validator.js +0 -114
  812. package/dist/services/capability-endpoint-validator.js.map +0 -1
  813. package/dist/services/capability-health.d.ts +0 -16
  814. package/dist/services/capability-health.js +0 -121
  815. package/dist/services/capability-health.js.map +0 -1
  816. package/dist/services/capability-registry.d.ts +0 -29
  817. package/dist/services/capability-registry.js +0 -176
  818. package/dist/services/capability-registry.js.map +0 -1
  819. package/dist/services/capability-sync.d.ts +0 -4
  820. package/dist/services/capability-sync.js +0 -220
  821. package/dist/services/capability-sync.js.map +0 -1
  822. package/dist/services/connection-admin.d.ts +0 -74
  823. package/dist/services/connection-admin.js +0 -287
  824. package/dist/services/connection-admin.js.map +0 -1
  825. package/dist/services/connection-apply.d.ts +0 -91
  826. package/dist/services/connection-apply.js +0 -471
  827. package/dist/services/connection-apply.js.map +0 -1
  828. package/dist/services/connection-resolver.d.ts +0 -65
  829. package/dist/services/connection-resolver.js +0 -281
  830. package/dist/services/connection-resolver.js.map +0 -1
  831. package/dist/services/connection-transactor.d.ts +0 -39
  832. package/dist/services/connection-transactor.js +0 -354
  833. package/dist/services/connection-transactor.js.map +0 -1
  834. package/dist/services/core-manager.d.ts +0 -50
  835. package/dist/services/core-manager.js +0 -411
  836. package/dist/services/core-manager.js.map +0 -1
  837. package/dist/services/external-mounts.js +0 -187
  838. package/dist/services/external-mounts.js.map +0 -1
  839. package/dist/services/files-manager.d.ts +0 -252
  840. package/dist/services/files-manager.js +0 -1156
  841. package/dist/services/files-manager.js.map +0 -1
  842. package/dist/services/files-mounts.d.ts +0 -42
  843. package/dist/services/files-mounts.js +0 -207
  844. package/dist/services/files-mounts.js.map +0 -1
  845. package/dist/services/instance-admin.d.ts +0 -26
  846. package/dist/services/instance-admin.js +0 -218
  847. package/dist/services/instance-admin.js.map +0 -1
  848. package/dist/services/instance-manager.d.ts +0 -192
  849. package/dist/services/instance-manager.js +0 -1289
  850. package/dist/services/instance-manager.js.map +0 -1
  851. package/dist/services/macos-launchd.js +0 -312
  852. package/dist/services/macos-launchd.js.map +0 -1
  853. package/dist/services/nomad-manager.d.ts +0 -307
  854. package/dist/services/nomad-manager.js +0 -3958
  855. package/dist/services/nomad-manager.js.map +0 -1
  856. package/dist/services/organize/applier.js +0 -218
  857. package/dist/services/organize/applier.js.map +0 -1
  858. package/dist/services/organize/rules.js +0 -286
  859. package/dist/services/organize/rules.js.map +0 -1
  860. package/dist/services/organize/scanner.js +0 -366
  861. package/dist/services/organize/scanner.js.map +0 -1
  862. package/dist/services/organize/store.js +0 -82
  863. package/dist/services/organize/store.js.map +0 -1
  864. package/dist/services/plugin-installer.js +0 -128
  865. package/dist/services/plugin-installer.js.map +0 -1
  866. package/dist/services/process-manager.d.ts +0 -25
  867. package/dist/services/process-manager.js +0 -568
  868. package/dist/services/process-manager.js.map +0 -1
  869. package/dist/services/runtime/adapters/custom.d.ts +0 -20
  870. package/dist/services/runtime/adapters/custom.js +0 -188
  871. package/dist/services/runtime/adapters/custom.js.map +0 -1
  872. package/dist/services/runtime/adapters/hermes.d.ts +0 -204
  873. package/dist/services/runtime/adapters/hermes.js +0 -1684
  874. package/dist/services/runtime/adapters/hermes.js.map +0 -1
  875. package/dist/services/runtime/adapters/openclaw-mcporter.d.ts +0 -45
  876. package/dist/services/runtime/adapters/openclaw-mcporter.js +0 -108
  877. package/dist/services/runtime/adapters/openclaw-mcporter.js.map +0 -1
  878. package/dist/services/runtime/adapters/openclaw.d.ts +0 -426
  879. package/dist/services/runtime/adapters/openclaw.js +0 -3975
  880. package/dist/services/runtime/adapters/openclaw.js.map +0 -1
  881. package/dist/services/runtime/index.d.ts +0 -34
  882. package/dist/services/runtime/index.js +0 -51
  883. package/dist/services/runtime/index.js.map +0 -1
  884. package/dist/services/runtime/mcp-shims/anythingllm-shim.d.ts +0 -46
  885. package/dist/services/runtime/mcp-shims/anythingllm-shim.js +0 -281
  886. package/dist/services/runtime/mcp-shims/anythingllm-shim.js.map +0 -1
  887. package/dist/services/runtime/mcp-shims/drive-shim.js +0 -490
  888. package/dist/services/runtime/mcp-shims/drive-shim.js.map +0 -1
  889. package/dist/services/runtime/mcp-shims/jishukb-shim.d.ts +0 -48
  890. package/dist/services/runtime/mcp-shims/jishukb-shim.js +0 -723
  891. package/dist/services/runtime/mcp-shims/jishukb-shim.js.map +0 -1
  892. package/dist/services/runtime/mcp-shims/mcporter-lite.js +0 -276
  893. package/dist/services/runtime/mcp-shims/mcporter-lite.js.map +0 -1
  894. package/dist/services/runtime/migrations.d.ts +0 -23
  895. package/dist/services/runtime/migrations.js +0 -125
  896. package/dist/services/runtime/migrations.js.map +0 -1
  897. package/dist/services/runtime/registry.d.ts +0 -13
  898. package/dist/services/runtime/registry.js +0 -32
  899. package/dist/services/runtime/registry.js.map +0 -1
  900. package/dist/services/runtime-identity.d.ts +0 -13
  901. package/dist/services/runtime-identity.js +0 -166
  902. package/dist/services/runtime-identity.js.map +0 -1
  903. package/dist/services/runtime-repair.d.ts +0 -52
  904. package/dist/services/runtime-repair.js +0 -352
  905. package/dist/services/runtime-repair.js.map +0 -1
  906. package/dist/services/setup-manager.d.ts +0 -158
  907. package/dist/services/setup-manager.js +0 -2740
  908. package/dist/services/setup-manager.js.map +0 -1
  909. package/dist/services/suggestions.d.ts +0 -27
  910. package/dist/services/suggestions.js +0 -133
  911. package/dist/services/suggestions.js.map +0 -1
  912. package/dist/services/system-monitor.js +0 -79
  913. package/dist/services/system-monitor.js.map +0 -1
  914. package/dist/services/system-ollama-provider.d.ts +0 -14
  915. package/dist/services/system-ollama-provider.js +0 -125
  916. package/dist/services/system-ollama-provider.js.map +0 -1
  917. package/dist/services/system-reconciler.d.ts +0 -72
  918. package/dist/services/system-reconciler.js +0 -600
  919. package/dist/services/system-reconciler.js.map +0 -1
  920. package/dist/services/task-registry.d.ts +0 -44
  921. package/dist/services/task-registry.js +0 -76
  922. package/dist/services/task-registry.js.map +0 -1
  923. package/dist/services/types-shim.d.ts +0 -16
  924. package/dist/services/types-shim.js +0 -2
  925. package/dist/services/types-shim.js.map +0 -1
  926. package/dist/services/update-manager.d.ts +0 -47
  927. package/dist/services/update-manager.js +0 -351
  928. package/dist/services/update-manager.js.map +0 -1
  929. package/dist/services/webdav/server.d.ts +0 -24
  930. package/dist/services/webdav/server.js +0 -420
  931. package/dist/services/webdav/server.js.map +0 -1
  932. package/dist/services/webdav/xml-builder.js.map +0 -1
  933. package/dist/services/workspace-builder.d.ts +0 -29
  934. package/dist/services/workspace-builder.js +0 -188
  935. package/dist/services/workspace-builder.js.map +0 -1
  936. package/node_modules/@fastify/static/.github/stale.yml +0 -21
  937. package/node_modules/@isaacs/cliui/LICENSE.md +0 -63
  938. package/node_modules/@isaacs/cliui/README.md +0 -151
  939. package/node_modules/@isaacs/cliui/dist/commonjs/ansi-regex/index.d.ts +0 -4
  940. package/node_modules/@isaacs/cliui/dist/commonjs/ansi-regex/index.d.ts.map +0 -1
  941. package/node_modules/@isaacs/cliui/dist/commonjs/ansi-regex/index.js +0 -16
  942. package/node_modules/@isaacs/cliui/dist/commonjs/ansi-regex/index.js.map +0 -1
  943. package/node_modules/@isaacs/cliui/dist/commonjs/ansi-styles/index.d.ts +0 -34
  944. package/node_modules/@isaacs/cliui/dist/commonjs/ansi-styles/index.d.ts.map +0 -1
  945. package/node_modules/@isaacs/cliui/dist/commonjs/ansi-styles/index.js +0 -170
  946. package/node_modules/@isaacs/cliui/dist/commonjs/ansi-styles/index.js.map +0 -1
  947. package/node_modules/@isaacs/cliui/dist/commonjs/eastasianwidth/index.d.ts +0 -6
  948. package/node_modules/@isaacs/cliui/dist/commonjs/eastasianwidth/index.d.ts.map +0 -1
  949. package/node_modules/@isaacs/cliui/dist/commonjs/eastasianwidth/index.js +0 -307
  950. package/node_modules/@isaacs/cliui/dist/commonjs/eastasianwidth/index.js.map +0 -1
  951. package/node_modules/@isaacs/cliui/dist/commonjs/emoji-regex/index.d.ts +0 -2
  952. package/node_modules/@isaacs/cliui/dist/commonjs/emoji-regex/index.d.ts.map +0 -1
  953. package/node_modules/@isaacs/cliui/dist/commonjs/emoji-regex/index.js +0 -7
  954. package/node_modules/@isaacs/cliui/dist/commonjs/emoji-regex/index.js.map +0 -1
  955. package/node_modules/@isaacs/cliui/dist/commonjs/index.d.ts +0 -41
  956. package/node_modules/@isaacs/cliui/dist/commonjs/index.d.ts.map +0 -1
  957. package/node_modules/@isaacs/cliui/dist/commonjs/index.js +0 -322
  958. package/node_modules/@isaacs/cliui/dist/commonjs/index.js.map +0 -1
  959. package/node_modules/@isaacs/cliui/dist/commonjs/index.min.js +0 -12
  960. package/node_modules/@isaacs/cliui/dist/commonjs/index.min.js.map +0 -7
  961. package/node_modules/@isaacs/cliui/dist/commonjs/package.json +0 -3
  962. package/node_modules/@isaacs/cliui/dist/commonjs/string-width/index.d.ts +0 -5
  963. package/node_modules/@isaacs/cliui/dist/commonjs/string-width/index.d.ts.map +0 -1
  964. package/node_modules/@isaacs/cliui/dist/commonjs/string-width/index.js +0 -49
  965. package/node_modules/@isaacs/cliui/dist/commonjs/string-width/index.js.map +0 -1
  966. package/node_modules/@isaacs/cliui/dist/commonjs/strip-ansi/index.d.ts +0 -2
  967. package/node_modules/@isaacs/cliui/dist/commonjs/strip-ansi/index.d.ts.map +0 -1
  968. package/node_modules/@isaacs/cliui/dist/commonjs/strip-ansi/index.js +0 -8
  969. package/node_modules/@isaacs/cliui/dist/commonjs/strip-ansi/index.js.map +0 -1
  970. package/node_modules/@isaacs/cliui/dist/commonjs/wrap-ansi/index.d.ts +0 -7
  971. package/node_modules/@isaacs/cliui/dist/commonjs/wrap-ansi/index.d.ts.map +0 -1
  972. package/node_modules/@isaacs/cliui/dist/commonjs/wrap-ansi/index.js +0 -176
  973. package/node_modules/@isaacs/cliui/dist/commonjs/wrap-ansi/index.js.map +0 -1
  974. package/node_modules/@isaacs/cliui/dist/esm/ansi-regex/index.d.ts +0 -4
  975. package/node_modules/@isaacs/cliui/dist/esm/ansi-regex/index.d.ts.map +0 -1
  976. package/node_modules/@isaacs/cliui/dist/esm/ansi-regex/index.js +0 -12
  977. package/node_modules/@isaacs/cliui/dist/esm/ansi-regex/index.js.map +0 -1
  978. package/node_modules/@isaacs/cliui/dist/esm/ansi-styles/index.d.ts +0 -34
  979. package/node_modules/@isaacs/cliui/dist/esm/ansi-styles/index.d.ts.map +0 -1
  980. package/node_modules/@isaacs/cliui/dist/esm/ansi-styles/index.js +0 -167
  981. package/node_modules/@isaacs/cliui/dist/esm/ansi-styles/index.js.map +0 -1
  982. package/node_modules/@isaacs/cliui/dist/esm/eastasianwidth/index.d.ts +0 -6
  983. package/node_modules/@isaacs/cliui/dist/esm/eastasianwidth/index.d.ts.map +0 -1
  984. package/node_modules/@isaacs/cliui/dist/esm/eastasianwidth/index.js +0 -299
  985. package/node_modules/@isaacs/cliui/dist/esm/eastasianwidth/index.js.map +0 -1
  986. package/node_modules/@isaacs/cliui/dist/esm/emoji-regex/index.d.ts +0 -2
  987. package/node_modules/@isaacs/cliui/dist/esm/emoji-regex/index.d.ts.map +0 -1
  988. package/node_modules/@isaacs/cliui/dist/esm/emoji-regex/index.js +0 -3
  989. package/node_modules/@isaacs/cliui/dist/esm/emoji-regex/index.js.map +0 -1
  990. package/node_modules/@isaacs/cliui/dist/esm/index.d.ts +0 -41
  991. package/node_modules/@isaacs/cliui/dist/esm/index.d.ts.map +0 -1
  992. package/node_modules/@isaacs/cliui/dist/esm/index.js +0 -317
  993. package/node_modules/@isaacs/cliui/dist/esm/index.js.map +0 -1
  994. package/node_modules/@isaacs/cliui/dist/esm/index.min.js +0 -12
  995. package/node_modules/@isaacs/cliui/dist/esm/index.min.js.map +0 -7
  996. package/node_modules/@isaacs/cliui/dist/esm/package.json +0 -3
  997. package/node_modules/@isaacs/cliui/dist/esm/string-width/index.d.ts +0 -5
  998. package/node_modules/@isaacs/cliui/dist/esm/string-width/index.d.ts.map +0 -1
  999. package/node_modules/@isaacs/cliui/dist/esm/string-width/index.js +0 -46
  1000. package/node_modules/@isaacs/cliui/dist/esm/string-width/index.js.map +0 -1
  1001. package/node_modules/@isaacs/cliui/dist/esm/strip-ansi/index.d.ts +0 -2
  1002. package/node_modules/@isaacs/cliui/dist/esm/strip-ansi/index.d.ts.map +0 -1
  1003. package/node_modules/@isaacs/cliui/dist/esm/strip-ansi/index.js +0 -4
  1004. package/node_modules/@isaacs/cliui/dist/esm/strip-ansi/index.js.map +0 -1
  1005. package/node_modules/@isaacs/cliui/dist/esm/wrap-ansi/index.d.ts +0 -7
  1006. package/node_modules/@isaacs/cliui/dist/esm/wrap-ansi/index.d.ts.map +0 -1
  1007. package/node_modules/@isaacs/cliui/dist/esm/wrap-ansi/index.js +0 -172
  1008. package/node_modules/@isaacs/cliui/dist/esm/wrap-ansi/index.js.map +0 -1
  1009. package/node_modules/@isaacs/cliui/package.json +0 -163
  1010. package/node_modules/content-disposition/HISTORY.md +0 -60
  1011. package/node_modules/cross-spawn/LICENSE +0 -21
  1012. package/node_modules/cross-spawn/README.md +0 -89
  1013. package/node_modules/cross-spawn/index.js +0 -39
  1014. package/node_modules/cross-spawn/lib/enoent.js +0 -59
  1015. package/node_modules/cross-spawn/lib/parse.js +0 -91
  1016. package/node_modules/cross-spawn/lib/util/escape.js +0 -47
  1017. package/node_modules/cross-spawn/lib/util/readShebang.js +0 -23
  1018. package/node_modules/cross-spawn/lib/util/resolveCommand.js +0 -52
  1019. package/node_modules/cross-spawn/package.json +0 -73
  1020. package/node_modules/fastify/test/types/content-type-parser.test-d.ts +0 -72
  1021. package/node_modules/fastify/test/types/decorate-request-reply.test-d.ts +0 -18
  1022. package/node_modules/fastify/test/types/dummy-plugin.ts +0 -9
  1023. package/node_modules/fastify/test/types/errors.test-d.ts +0 -90
  1024. package/node_modules/fastify/test/types/fastify.test-d.ts +0 -352
  1025. package/node_modules/fastify/test/types/hooks.test-d.ts +0 -550
  1026. package/node_modules/fastify/test/types/import.ts +0 -2
  1027. package/node_modules/fastify/test/types/instance.test-d.ts +0 -588
  1028. package/node_modules/fastify/test/types/logger.test-d.ts +0 -277
  1029. package/node_modules/fastify/test/types/plugin.test-d.ts +0 -97
  1030. package/node_modules/fastify/test/types/register.test-d.ts +0 -237
  1031. package/node_modules/fastify/test/types/reply.test-d.ts +0 -254
  1032. package/node_modules/fastify/test/types/request.test-d.ts +0 -188
  1033. package/node_modules/fastify/test/types/route.test-d.ts +0 -553
  1034. package/node_modules/fastify/test/types/schema.test-d.ts +0 -135
  1035. package/node_modules/fastify/test/types/serverFactory.test-d.ts +0 -37
  1036. package/node_modules/fastify/test/types/type-provider.test-d.ts +0 -1213
  1037. package/node_modules/fastify/test/types/using.test-d.ts +0 -17
  1038. package/node_modules/foreground-child/LICENSE +0 -15
  1039. package/node_modules/foreground-child/README.md +0 -128
  1040. package/node_modules/foreground-child/dist/commonjs/all-signals.d.ts +0 -2
  1041. package/node_modules/foreground-child/dist/commonjs/all-signals.d.ts.map +0 -1
  1042. package/node_modules/foreground-child/dist/commonjs/all-signals.js +0 -58
  1043. package/node_modules/foreground-child/dist/commonjs/all-signals.js.map +0 -1
  1044. package/node_modules/foreground-child/dist/commonjs/index.d.ts +0 -58
  1045. package/node_modules/foreground-child/dist/commonjs/index.d.ts.map +0 -1
  1046. package/node_modules/foreground-child/dist/commonjs/index.js +0 -123
  1047. package/node_modules/foreground-child/dist/commonjs/index.js.map +0 -1
  1048. package/node_modules/foreground-child/dist/commonjs/package.json +0 -3
  1049. package/node_modules/foreground-child/dist/commonjs/proxy-signals.d.ts +0 -6
  1050. package/node_modules/foreground-child/dist/commonjs/proxy-signals.d.ts.map +0 -1
  1051. package/node_modules/foreground-child/dist/commonjs/proxy-signals.js +0 -38
  1052. package/node_modules/foreground-child/dist/commonjs/proxy-signals.js.map +0 -1
  1053. package/node_modules/foreground-child/dist/commonjs/watchdog.d.ts +0 -10
  1054. package/node_modules/foreground-child/dist/commonjs/watchdog.d.ts.map +0 -1
  1055. package/node_modules/foreground-child/dist/commonjs/watchdog.js +0 -50
  1056. package/node_modules/foreground-child/dist/commonjs/watchdog.js.map +0 -1
  1057. package/node_modules/foreground-child/dist/esm/all-signals.d.ts +0 -2
  1058. package/node_modules/foreground-child/dist/esm/all-signals.d.ts.map +0 -1
  1059. package/node_modules/foreground-child/dist/esm/all-signals.js +0 -52
  1060. package/node_modules/foreground-child/dist/esm/all-signals.js.map +0 -1
  1061. package/node_modules/foreground-child/dist/esm/index.d.ts +0 -58
  1062. package/node_modules/foreground-child/dist/esm/index.d.ts.map +0 -1
  1063. package/node_modules/foreground-child/dist/esm/index.js +0 -115
  1064. package/node_modules/foreground-child/dist/esm/index.js.map +0 -1
  1065. package/node_modules/foreground-child/dist/esm/package.json +0 -3
  1066. package/node_modules/foreground-child/dist/esm/proxy-signals.d.ts +0 -6
  1067. package/node_modules/foreground-child/dist/esm/proxy-signals.d.ts.map +0 -1
  1068. package/node_modules/foreground-child/dist/esm/proxy-signals.js +0 -34
  1069. package/node_modules/foreground-child/dist/esm/proxy-signals.js.map +0 -1
  1070. package/node_modules/foreground-child/dist/esm/watchdog.d.ts +0 -10
  1071. package/node_modules/foreground-child/dist/esm/watchdog.d.ts.map +0 -1
  1072. package/node_modules/foreground-child/dist/esm/watchdog.js +0 -46
  1073. package/node_modules/foreground-child/dist/esm/watchdog.js.map +0 -1
  1074. package/node_modules/foreground-child/package.json +0 -106
  1075. package/node_modules/glob/dist/esm/bin.d.mts +0 -3
  1076. package/node_modules/glob/dist/esm/bin.d.mts.map +0 -1
  1077. package/node_modules/glob/dist/esm/bin.mjs +0 -346
  1078. package/node_modules/glob/dist/esm/bin.mjs.map +0 -1
  1079. package/node_modules/isexe/.npmignore +0 -2
  1080. package/node_modules/isexe/LICENSE +0 -15
  1081. package/node_modules/isexe/README.md +0 -51
  1082. package/node_modules/isexe/index.js +0 -57
  1083. package/node_modules/isexe/mode.js +0 -41
  1084. package/node_modules/isexe/package.json +0 -31
  1085. package/node_modules/isexe/test/basic.js +0 -221
  1086. package/node_modules/isexe/windows.js +0 -42
  1087. package/node_modules/jackspeak/LICENSE.md +0 -55
  1088. package/node_modules/jackspeak/README.md +0 -394
  1089. package/node_modules/jackspeak/dist/commonjs/index.d.ts +0 -323
  1090. package/node_modules/jackspeak/dist/commonjs/index.d.ts.map +0 -1
  1091. package/node_modules/jackspeak/dist/commonjs/index.js +0 -944
  1092. package/node_modules/jackspeak/dist/commonjs/index.js.map +0 -1
  1093. package/node_modules/jackspeak/dist/commonjs/index.min.js +0 -33
  1094. package/node_modules/jackspeak/dist/commonjs/index.min.js.map +0 -7
  1095. package/node_modules/jackspeak/dist/commonjs/package.json +0 -3
  1096. package/node_modules/jackspeak/dist/esm/index.d.ts +0 -323
  1097. package/node_modules/jackspeak/dist/esm/index.d.ts.map +0 -1
  1098. package/node_modules/jackspeak/dist/esm/index.js +0 -936
  1099. package/node_modules/jackspeak/dist/esm/index.js.map +0 -1
  1100. package/node_modules/jackspeak/dist/esm/index.min.js +0 -33
  1101. package/node_modules/jackspeak/dist/esm/index.min.js.map +0 -7
  1102. package/node_modules/jackspeak/dist/esm/package.json +0 -3
  1103. package/node_modules/jackspeak/package.json +0 -115
  1104. package/node_modules/jishushell-panel/output/public/assets/ApiKeyField-D1i7zWXR.js +0 -1
  1105. package/node_modules/jishushell-panel/output/public/assets/Dashboard-sWIvL43F.js +0 -1
  1106. package/node_modules/jishushell-panel/output/public/assets/HermesChatPanel-DQ8RyvQY.js +0 -1
  1107. package/node_modules/jishushell-panel/output/public/assets/HermesConfigForm-tIbPP1sB.js +0 -4
  1108. package/node_modules/jishushell-panel/output/public/assets/InitPassword-C3Slq3Dd.js +0 -1
  1109. package/node_modules/jishushell-panel/output/public/assets/InstanceDetail-7JqY9tq4.js +0 -92
  1110. package/node_modules/jishushell-panel/output/public/assets/Login-BXLDJlQN.js +0 -1
  1111. package/node_modules/jishushell-panel/output/public/assets/NewInstance-dLc5Xrpx.js +0 -1
  1112. package/node_modules/jishushell-panel/output/public/assets/ProviderRecommendations-DIAXxesl.js +0 -1
  1113. package/node_modules/jishushell-panel/output/public/assets/Settings-Bd5utbBh.js +0 -1
  1114. package/node_modules/jishushell-panel/output/public/assets/Setup-Yn9_20FL.js +0 -1
  1115. package/node_modules/jishushell-panel/output/public/assets/WeixinLoginPanel-C21doQTJ.js +0 -9
  1116. package/node_modules/jishushell-panel/output/public/assets/index-CCkaIEjn.js +0 -20
  1117. package/node_modules/jishushell-panel/output/public/assets/index-D7qxy-Vh.css +0 -1
  1118. package/node_modules/jishushell-panel/output/public/assets/registry-B2ZQZXWL.js +0 -2
  1119. package/node_modules/jishushell-panel/output/public/assets/usePolling-BFZm4do_.js +0 -1
  1120. package/node_modules/jishushell-panel/output/public/assets/vendor-i18n-DqPtOicc.js +0 -9
  1121. package/node_modules/jishushell-panel/output/public/assets/vendor-react-DW5juQin.js +0 -59
  1122. package/node_modules/package-json-from-dist/LICENSE.md +0 -63
  1123. package/node_modules/package-json-from-dist/README.md +0 -110
  1124. package/node_modules/package-json-from-dist/dist/commonjs/index.d.ts +0 -89
  1125. package/node_modules/package-json-from-dist/dist/commonjs/index.d.ts.map +0 -1
  1126. package/node_modules/package-json-from-dist/dist/commonjs/index.js +0 -134
  1127. package/node_modules/package-json-from-dist/dist/commonjs/index.js.map +0 -1
  1128. package/node_modules/package-json-from-dist/dist/commonjs/package.json +0 -3
  1129. package/node_modules/package-json-from-dist/dist/esm/index.d.ts +0 -89
  1130. package/node_modules/package-json-from-dist/dist/esm/index.d.ts.map +0 -1
  1131. package/node_modules/package-json-from-dist/dist/esm/index.js +0 -129
  1132. package/node_modules/package-json-from-dist/dist/esm/index.js.map +0 -1
  1133. package/node_modules/package-json-from-dist/dist/esm/package.json +0 -3
  1134. package/node_modules/package-json-from-dist/package.json +0 -68
  1135. package/node_modules/path-key/index.d.ts +0 -40
  1136. package/node_modules/path-key/index.js +0 -16
  1137. package/node_modules/path-key/license +0 -9
  1138. package/node_modules/path-key/package.json +0 -39
  1139. package/node_modules/path-key/readme.md +0 -61
  1140. package/node_modules/safe-buffer/LICENSE +0 -21
  1141. package/node_modules/safe-buffer/README.md +0 -584
  1142. package/node_modules/safe-buffer/index.d.ts +0 -187
  1143. package/node_modules/safe-buffer/index.js +0 -65
  1144. package/node_modules/safe-buffer/package.json +0 -51
  1145. package/node_modules/shebang-command/index.js +0 -19
  1146. package/node_modules/shebang-command/license +0 -9
  1147. package/node_modules/shebang-command/package.json +0 -34
  1148. package/node_modules/shebang-command/readme.md +0 -34
  1149. package/node_modules/shebang-regex/index.d.ts +0 -22
  1150. package/node_modules/shebang-regex/index.js +0 -2
  1151. package/node_modules/shebang-regex/license +0 -9
  1152. package/node_modules/shebang-regex/package.json +0 -35
  1153. package/node_modules/shebang-regex/readme.md +0 -33
  1154. package/node_modules/signal-exit/LICENSE.txt +0 -16
  1155. package/node_modules/signal-exit/README.md +0 -74
  1156. package/node_modules/signal-exit/dist/cjs/browser.d.ts +0 -12
  1157. package/node_modules/signal-exit/dist/cjs/browser.d.ts.map +0 -1
  1158. package/node_modules/signal-exit/dist/cjs/browser.js +0 -10
  1159. package/node_modules/signal-exit/dist/cjs/browser.js.map +0 -1
  1160. package/node_modules/signal-exit/dist/cjs/index.d.ts +0 -48
  1161. package/node_modules/signal-exit/dist/cjs/index.d.ts.map +0 -1
  1162. package/node_modules/signal-exit/dist/cjs/index.js +0 -279
  1163. package/node_modules/signal-exit/dist/cjs/index.js.map +0 -1
  1164. package/node_modules/signal-exit/dist/cjs/package.json +0 -3
  1165. package/node_modules/signal-exit/dist/cjs/signals.d.ts +0 -29
  1166. package/node_modules/signal-exit/dist/cjs/signals.d.ts.map +0 -1
  1167. package/node_modules/signal-exit/dist/cjs/signals.js +0 -42
  1168. package/node_modules/signal-exit/dist/cjs/signals.js.map +0 -1
  1169. package/node_modules/signal-exit/dist/mjs/browser.d.ts +0 -12
  1170. package/node_modules/signal-exit/dist/mjs/browser.d.ts.map +0 -1
  1171. package/node_modules/signal-exit/dist/mjs/browser.js +0 -4
  1172. package/node_modules/signal-exit/dist/mjs/browser.js.map +0 -1
  1173. package/node_modules/signal-exit/dist/mjs/index.d.ts +0 -48
  1174. package/node_modules/signal-exit/dist/mjs/index.d.ts.map +0 -1
  1175. package/node_modules/signal-exit/dist/mjs/index.js +0 -275
  1176. package/node_modules/signal-exit/dist/mjs/index.js.map +0 -1
  1177. package/node_modules/signal-exit/dist/mjs/package.json +0 -3
  1178. package/node_modules/signal-exit/dist/mjs/signals.d.ts +0 -29
  1179. package/node_modules/signal-exit/dist/mjs/signals.d.ts.map +0 -1
  1180. package/node_modules/signal-exit/dist/mjs/signals.js +0 -39
  1181. package/node_modules/signal-exit/dist/mjs/signals.js.map +0 -1
  1182. package/node_modules/signal-exit/package.json +0 -106
  1183. package/node_modules/which/CHANGELOG.md +0 -166
  1184. package/node_modules/which/LICENSE +0 -15
  1185. package/node_modules/which/README.md +0 -54
  1186. package/node_modules/which/bin/node-which +0 -52
  1187. package/node_modules/which/package.json +0 -43
  1188. package/node_modules/which/which.js +0 -125
  1189. package/scripts/check-adapter-isolation.ts +0 -293
  1190. /package/dist/services/{app → app-common}/app-compiler.d.ts +0 -0
  1191. /package/dist/services/{app → app-common}/terminal-session-manager.d.ts +0 -0
  1192. /package/dist/services/{backup-verify.d.ts → backup/backup-verify.d.ts} +0 -0
  1193. /package/dist/services/{external-mounts.d.ts → files/external-mounts.d.ts} +0 -0
  1194. /package/dist/services/{organize → files/organize}/applier.d.ts +0 -0
  1195. /package/dist/services/{organize → files/organize}/rules.d.ts +0 -0
  1196. /package/dist/services/{organize → files/organize}/scanner.d.ts +0 -0
  1197. /package/dist/services/{organize → files/organize}/store.d.ts +0 -0
  1198. /package/dist/services/{webdav → files/webdav}/xml-builder.d.ts +0 -0
  1199. /package/dist/services/{webdav → files/webdav}/xml-builder.js +0 -0
  1200. /package/dist/services/{app-passwords.d.ts → instances/passwords.d.ts} +0 -0
  1201. /package/dist/services/{agent-apps → integrations/installable}/installers/registry-probe.d.ts +0 -0
  1202. /package/dist/services/{agent-apps → integrations/installable}/installers/registry-probe.js +0 -0
  1203. /package/dist/services/{runtime/mcp-shims → integrations/openclaw}/drive-shim.d.ts +0 -0
  1204. /package/dist/services/{runtime/mcp-shims → integrations/openclaw}/mcporter-lite.d.ts +0 -0
  1205. /package/dist/services/{plugin-installer.d.ts → setup/plugin-installer.d.ts} +0 -0
  1206. /package/dist/services/{macos-launchd.d.ts → system/macos-launchd.d.ts} +0 -0
  1207. /package/dist/services/{system-monitor.d.ts → system/system-monitor.d.ts} +0 -0
@@ -1,2740 +0,0 @@
1
- import { execFileSync, execSync, spawn as nodeSpawn } from "child_process";
2
- import { chmodSync, copyFileSync, existsSync, lstatSync, mkdtempSync, readFileSync, renameSync, rmSync, symlinkSync, unlinkSync } from "fs";
3
- import { userInfo, platform as osPlatform, arch as osArch, cpus as osCpus } from "node:os";
4
- import { randomBytes } from "node:crypto";
5
- import { tmpdir } from "node:os";
6
- import { basename, dirname, join } from "path";
7
- import { StringDecoder } from "string_decoder";
8
- import { fileURLToPath } from "url";
9
- import { JISHUSHELL_HOME, getCoreConfig, saveCoreConfig, setOpenclawDockerImage, getOpenclawDockerImage, DEFAULT_OPENCLAW_DOCKER_IMAGE, getRuntimeCatalogEntry, OPENCLAW_MODULES, OPENCLAW_BIN_DIR, } from "../config.js";
10
- import { ensureDirContainer, ensureDirHost, writeConfigFile, writeSecretFile, writeExecutableFile, writeSystemTmpFile } from "../utils/fs.js";
11
- import { buildDockerClientEnv, managedColimaSocketPath, managedColimaDockerHost, resolveDockerHost } from "../utils/docker-host.js";
12
- import { appleSiliconGuard, buildColimaWrapperScript, buildColimaPlist, buildNomadWaitWrapper, buildNomadPlist, buildCoreGateWrapper, buildCorePlist, buildPanelPlist, } from "./macos-launchd.js";
13
- import { getAdapter, listRegisteredAdapters } from "./runtime/index.js";
14
- import { hasLlmProviderSetup } from "./llm-proxy/providers.js";
15
- // Internal usage of task primitives — re-exports further down preserve the
16
- // public import surface used by runtime/adapters/*, routes, and CLI.
17
- import { createTask, emitTask, getRunningTasks } from "./task-registry.js";
18
- const __filename = fileURLToPath(import.meta.url);
19
- const __dirname = dirname(__filename);
20
- // ── Paths ──────────────────────────────────────────────────────────
21
- const BIN_DIR = join(JISHUSHELL_HOME, "bin");
22
- const NOMAD_BIN = join(BIN_DIR, "nomad");
23
- const NOMAD_CONFIG_DIR = join(JISHUSHELL_HOME, "nomad");
24
- const NOMAD_DATA_DIR = join(JISHUSHELL_HOME, "nomad", "data");
25
- const NOMAD_ALLOC_DIR = join(JISHUSHELL_HOME, "nomad", "data", "alloc");
26
- const _COLIMA_DIR = join(JISHUSHELL_HOME, "colima");
27
- const COLIMA_PROFILE = "jishushell";
28
- const _COLIMA_SOCKET = managedColimaSocketPath(JISHUSHELL_HOME, COLIMA_PROFILE);
29
- const NOMAD_VERSION = "1.6.5";
30
- const DEFAULT_CORE_PORT = 8091;
31
- const DEFAULT_PANEL_PORT = 8090;
32
- const SYSTEMD_CORE_SERVICE_PATH = "/etc/systemd/system/jishushell.service";
33
- const SYSTEMD_PANEL_SERVICE_PATH = "/etc/systemd/system/jishushell-panel.service";
34
- const SYSTEMD_NOMAD_SERVICE_PATH = "/etc/systemd/system/nomad.service";
35
- let _serverPort = DEFAULT_CORE_PORT;
36
- export function setServerPort(port) { _serverPort = port; }
37
- function shellQuote(value) {
38
- return `'${value.replace(/'/g, "'\\''")}'`;
39
- }
40
- function sudoCopySystemFile(content, destination, mode) {
41
- const stagingDir = mkdtempSync(join(tmpdir(), "jishushell-system-"));
42
- const stagingPath = join(stagingDir, basename(destination));
43
- try {
44
- writeSystemTmpFile(stagingPath, content);
45
- execFileSync("sudo", ["cp", stagingPath, destination], { timeout: 5000 });
46
- execFileSync("sudo", ["chown", "root:root", destination], { timeout: 5000 });
47
- execFileSync("sudo", ["chmod", mode, destination], { timeout: 5000 });
48
- }
49
- finally {
50
- rmSync(stagingDir, { recursive: true, force: true });
51
- }
52
- }
53
- function removeSymlinkIfPresent(path) {
54
- try {
55
- if (lstatSync(path).isSymbolicLink())
56
- unlinkSync(path);
57
- }
58
- catch (e) {
59
- if (e?.code !== "ENOENT")
60
- throw e;
61
- }
62
- }
63
- function chownToUser(path, user) {
64
- if (!user)
65
- return;
66
- const args = [`${user}:`, path];
67
- if (typeof process.getuid === "function" && process.getuid() === 0) {
68
- execFileSync("chown", args, { timeout: 5000 });
69
- }
70
- else {
71
- execFileSync("sudo", ["chown", ...args], { timeout: 5000 });
72
- }
73
- }
74
- function writeManagedExecutableFile(path, content, ownerUser) {
75
- try {
76
- writeExecutableFile(path, content);
77
- }
78
- catch (e) {
79
- if (e?.code !== "EACCES" || !ownerUser)
80
- throw e;
81
- sudoCopySystemFile(content, path, "755");
82
- }
83
- chownToUser(path, ownerUser);
84
- }
85
- function resolveCoreCliBin() {
86
- const candidates = [
87
- process.env.JISHUSHELL_CORE_BIN,
88
- join(__dirname, "..", "cli.js"),
89
- ]
90
- .map((candidate) => candidate?.trim())
91
- .filter((candidate) => Boolean(candidate));
92
- for (const candidate of candidates) {
93
- if (existsSync(candidate))
94
- return candidate;
95
- }
96
- throw new Error("Cannot locate jishushell entrypoint. Set JISHUSHELL_CORE_BIN to the bundled CLI path.");
97
- }
98
- function resolveBundledPanelServerBin() {
99
- const packageRoot = join(__dirname, "..", "..");
100
- const candidates = [
101
- process.env.JISHUSHELL_PANEL_BIN,
102
- join(packageRoot, "node_modules", "jishushell-panel", "output", "dist", "server.js"),
103
- ]
104
- .map((candidate) => candidate?.trim())
105
- .filter((candidate) => Boolean(candidate));
106
- for (const candidate of candidates) {
107
- if (existsSync(candidate))
108
- return candidate;
109
- }
110
- throw new Error("Cannot locate bundled jishushell-panel entrypoint. Install the Core+Panel jishushell-gui package or set JISHUSHELL_PANEL_BIN.");
111
- }
112
- function buildWrapperEnvPrelude() {
113
- return `_WRAPPER_DIR="$(cd "$(dirname "$0")" && pwd)"
114
- _DEFAULT_JISHUSHELL_HOME="$(cd "$_WRAPPER_DIR/.." && pwd)"
115
- JISHUSHELL_HOME=\${JISHUSHELL_HOME:-$_DEFAULT_JISHUSHELL_HOME}
116
-
117
- _resolve_home() {
118
- if [ -n "\${SUDO_UID:-}" ] && command -v getent >/dev/null 2>&1; then
119
- _entry="$(getent passwd "$SUDO_UID" 2>/dev/null || true)"
120
- if [ -n "$_entry" ]; then
121
- printf '%s\\n' "$_entry" | cut -d: -f6
122
- return
123
- fi
124
- fi
125
- case "$JISHUSHELL_HOME" in
126
- */.jishushell) printf '%s\\n' "\${JISHUSHELL_HOME%/.jishushell}" ;;
127
- *) printf '%s\\n' "\${HOME:-$PWD}" ;;
128
- esac
129
- }
130
- HOME="$(_resolve_home)"
131
- export JISHUSHELL_HOME HOME`;
132
- }
133
- function buildCoreStartWrapperContent(opts) {
134
- const pathPrefix = [
135
- "/opt/homebrew/bin",
136
- "/opt/homebrew/sbin",
137
- "/usr/local/bin",
138
- "/usr/local/sbin",
139
- "/usr/bin",
140
- "/bin",
141
- "/usr/sbin",
142
- "/sbin",
143
- dirname(opts.nodeBin),
144
- dirname(opts.cliBin),
145
- ].join(":");
146
- const cliExec = opts.cliBin.endsWith(".js")
147
- ? `${shellQuote(opts.nodeBin)} ${shellQuote(opts.cliBin)}`
148
- : shellQuote(opts.cliBin);
149
- return `#!/bin/sh
150
- set -eu
151
- ${buildWrapperEnvPrelude()}
152
- [ -f "\${JISHUSHELL_HOME}/nomad.env" ] && . "\${JISHUSHELL_HOME}/nomad.env"
153
- export JISHUSHELL_CORE_BIN=${shellQuote(opts.cliBin)}
154
- export JISHUSHELL_CORE_PORT=${opts.port}
155
- export NODE_ENV=production
156
- export PATH=${shellQuote(pathPrefix)}\${PATH:+:\$PATH}
157
- if command -v ss >/dev/null 2>&1 && ss -tln 2>/dev/null | grep -Eq '(^|[[:space:]])[^[:space:]]*:${opts.port}[[:space:]]'; then
158
- echo "JishuShell core port ${opts.port} is already listening; not starting another core."
159
- exit 0
160
- fi
161
- exec ${cliExec} serve --port ${opts.port}
162
- `;
163
- }
164
- function buildCoreCliWrapperContent(opts) {
165
- const pathPrefix = [
166
- "/opt/homebrew/bin",
167
- "/opt/homebrew/sbin",
168
- "/usr/local/bin",
169
- "/usr/local/sbin",
170
- "/usr/bin",
171
- "/bin",
172
- "/usr/sbin",
173
- "/sbin",
174
- dirname(opts.nodeBin),
175
- dirname(opts.cliBin),
176
- ].join(":");
177
- const cliExec = opts.cliBin.endsWith(".js")
178
- ? `${shellQuote(opts.nodeBin)} ${shellQuote(opts.cliBin)}`
179
- : shellQuote(opts.cliBin);
180
- return `#!/bin/sh
181
- set -eu
182
- ${buildWrapperEnvPrelude()}
183
- [ -f "\${JISHUSHELL_HOME}/nomad.env" ] && . "\${JISHUSHELL_HOME}/nomad.env"
184
- export JISHUSHELL_CORE_BIN=${shellQuote(opts.cliBin)}
185
- export JISHUSHELL_CORE_PORT=${opts.port}
186
- export NODE_ENV=\${NODE_ENV:-production}
187
- export PATH=${shellQuote(pathPrefix)}\${PATH:+:\$PATH}
188
- exec ${cliExec} "$@"
189
- `;
190
- }
191
- function buildPanelStartWrapperContent(opts) {
192
- const manageCoreDefault = opts.manageCoreDefault ? "1" : "0";
193
- const pathPrefix = [
194
- "/opt/homebrew/bin",
195
- "/opt/homebrew/sbin",
196
- "/usr/local/bin",
197
- "/usr/local/sbin",
198
- "/usr/bin",
199
- "/bin",
200
- "/usr/sbin",
201
- "/sbin",
202
- dirname(opts.nodeBin),
203
- dirname(opts.panelBin),
204
- ].join(":");
205
- return `#!/bin/sh
206
- set -eu
207
- ${buildWrapperEnvPrelude()}
208
- export NODE_ENV=\${NODE_ENV:-production}
209
- export JISHUSHELL_CORE_BASE_URL=\${JISHUSHELL_CORE_BASE_URL:-http://127.0.0.1:${opts.corePort}}
210
- export JISHUSHELL_PANEL_PORT=\${JISHUSHELL_PANEL_PORT:-${opts.panelPort}}
211
- export JISHUSHELL_PANEL_MANAGE_CORE=\${JISHUSHELL_PANEL_MANAGE_CORE:-${manageCoreDefault}}
212
- export PATH=${shellQuote(pathPrefix)}\${PATH:+:\$PATH}
213
- exec ${shellQuote(opts.nodeBin)} ${shellQuote(opts.panelBin)} "$@"
214
- `;
215
- }
216
- // ── Resolve non-root service user (board-agnostic) ─────────────────
217
- /**
218
- * Determine which user the systemd service should run as.
219
- *
220
- * Strategy (in order):
221
- * 1. If current process is NOT root, return the real username directly.
222
- * 2. Under sudo, trust the kernel-set SUDO_UID (numeric, hard to spoof)
223
- * and reverse-lookup via `getent passwd <uid>`.
224
- * 3. Fallback: scan /etc/passwd for the first user with UID >= 1000
225
- * (works on any board — pi, orangepi, rock, nvidia, etc.).
226
- * 4. Throw instead of guessing — running as the wrong user is worse
227
- * than a visible installation error.
228
- */
229
- function resolveServiceUser() {
230
- const current = userInfo();
231
- if (current.uid !== 0)
232
- return current.username;
233
- // Under sudo: SUDO_UID is set by the kernel and is numeric
234
- const sudoUid = parseInt(process.env.SUDO_UID || "", 10);
235
- if (Number.isFinite(sudoUid) && sudoUid >= 1000) {
236
- try {
237
- const entry = execFileSync("getent", ["passwd", String(sudoUid)], {
238
- encoding: "utf8",
239
- timeout: 3000,
240
- }).trim();
241
- const name = entry.split(":")[0];
242
- if (name)
243
- return name;
244
- }
245
- catch { /* getent failed, continue */ }
246
- }
247
- // Board-agnostic fallback: first real user (UID >= 1000, exclude nobody)
248
- try {
249
- const firstUser = execFileSync("getent", ["passwd"], {
250
- encoding: "utf8",
251
- timeout: 3000,
252
- })
253
- .split("\n")
254
- .map((line) => line.split(":"))
255
- .find((cols) => {
256
- const uid = parseInt(cols[2], 10);
257
- return uid >= 1000 && uid < 65534;
258
- });
259
- if (firstUser?.[0])
260
- return firstUser[0];
261
- }
262
- catch { /* /etc/passwd unreadable */ }
263
- throw new Error("Cannot determine service user. Run with a non-root user or set SUDO_UID.");
264
- }
265
- function resolveRealHome() {
266
- return dirname(JISHUSHELL_HOME);
267
- }
268
- function resolveLaunchAgentsDir(realHome = resolveRealHome()) {
269
- return join(process.env.HOME || realHome, "Library/LaunchAgents");
270
- }
271
- function resolveNomadExecutable() {
272
- if (existsSync(NOMAD_BIN))
273
- return NOMAD_BIN;
274
- try {
275
- return execFileSync("which", ["nomad"], { encoding: "utf-8", timeout: 5000 }).trim();
276
- }
277
- catch {
278
- return "nomad";
279
- }
280
- }
281
- function resolveColimaExecutable() {
282
- try {
283
- return execFileSync("which", ["colima"], { encoding: "utf-8", timeout: 5000 }).trim().split("\n")[0];
284
- }
285
- catch {
286
- if (existsSync("/opt/homebrew/bin/colima"))
287
- return "/opt/homebrew/bin/colima";
288
- if (existsSync("/usr/local/bin/colima"))
289
- return "/usr/local/bin/colima";
290
- return "colima";
291
- }
292
- }
293
- function buildJishushellCoreSystemdUnit(opts) {
294
- return `[Unit]
295
- Description=JishuShell Core
296
- After=network-online.target
297
- Wants=network-online.target
298
-
299
- [Service]
300
- Type=simple
301
- User=${opts.currentUser}
302
- SupplementaryGroups=docker
303
- Environment=HOME=${opts.realHome}
304
- Environment=JISHUSHELL_HOME=${JISHUSHELL_HOME}
305
- EnvironmentFile=-/etc/jishushell/jishushell.env
306
- EnvironmentFile=-/etc/jishushell/nomad.env
307
- ExecStart=${opts.coreStartWrapperPath}
308
- Restart=on-failure
309
- RestartSec=5
310
- Environment=NODE_ENV=production
311
-
312
- [Install]
313
- WantedBy=multi-user.target
314
- `;
315
- }
316
- function buildJishushellPanelSystemdUnit(opts) {
317
- return `[Unit]
318
- Description=JishuShell Panel
319
- After=network-online.target jishushell.service
320
- Wants=network-online.target jishushell.service
321
-
322
- [Service]
323
- Type=simple
324
- User=${opts.currentUser}
325
- Environment=HOME=${opts.realHome}
326
- Environment=JISHUSHELL_HOME=${JISHUSHELL_HOME}
327
- Environment=JISHUSHELL_CORE_BASE_URL=http://127.0.0.1:${opts.corePort}
328
- Environment=JISHUSHELL_PANEL_PORT=${opts.panelPort}
329
- Environment=JISHUSHELL_PANEL_MANAGE_CORE=0
330
- Environment=NODE_ENV=production
331
- ExecStart=${opts.panelStartWrapperPath}
332
- Restart=on-failure
333
- RestartSec=5
334
- ProtectSystem=strict
335
- PrivateTmp=true
336
- ReadWritePaths=${JISHUSHELL_HOME}
337
-
338
- [Install]
339
- WantedBy=multi-user.target
340
- `;
341
- }
342
- function buildNomadSystemdUnit(opts) {
343
- return `[Unit]
344
- Description=Nomad Agent
345
- After=network-online.target docker.service
346
- Wants=network-online.target
347
-
348
- [Service]
349
- User=root
350
- Type=simple
351
- EnvironmentFile=-/etc/jishushell/nomad.env
352
- ExecStart=${opts.nomadPath} agent -config=${opts.configPath}
353
- Restart=on-failure
354
- RestartSec=3
355
- Delegate=yes
356
- TasksMax=infinity
357
-
358
- [Install]
359
- WantedBy=multi-user.target
360
- `;
361
- }
362
- export function hasBundledPanel() {
363
- try {
364
- resolveBundledPanelServerBin();
365
- return true;
366
- }
367
- catch {
368
- return false;
369
- }
370
- }
371
- export function getExpectedCoreSystemFiles(port = _serverPort) {
372
- const nodeBin = process.execPath;
373
- const cliBin = resolveCoreCliBin();
374
- const realHome = resolveRealHome();
375
- const coreStartWrapperPath = join(BIN_DIR, "jishushell-core-start");
376
- const coreCliWrapperPath = join(BIN_DIR, "jishushell");
377
- const files = [
378
- {
379
- component: "wrapper",
380
- id: "core.start-wrapper",
381
- path: coreStartWrapperPath,
382
- content: buildCoreStartWrapperContent({ nodeBin, cliBin, realHome, port }),
383
- installScope: "core",
384
- requiresSudo: false,
385
- reloadRequired: true,
386
- fix: "system-reload",
387
- },
388
- {
389
- component: "wrapper",
390
- id: "core.cli-wrapper",
391
- path: coreCliWrapperPath,
392
- content: buildCoreCliWrapperContent({ nodeBin, cliBin, realHome, port }),
393
- installScope: "core",
394
- requiresSudo: false,
395
- reloadRequired: true,
396
- fix: "system-reload",
397
- },
398
- ];
399
- if (process.platform === "darwin") {
400
- const gateWrapperPath = join(BIN_DIR, "core-launchd-wrapper.sh");
401
- files.push({
402
- component: "wrapper",
403
- id: "core.launchd-gate-wrapper",
404
- path: gateWrapperPath,
405
- content: buildCoreGateWrapper({
406
- socket: managedColimaSocketPath(JISHUSHELL_HOME, COLIMA_PROFILE),
407
- coreStartWrapper: coreStartWrapperPath,
408
- }),
409
- installScope: "core",
410
- requiresSudo: false,
411
- reloadRequired: true,
412
- fix: "system-reload",
413
- }, {
414
- component: "launchd",
415
- id: "core.launchd-agent",
416
- path: join(resolveLaunchAgentsDir(realHome), "com.jishushell.core.plist"),
417
- content: buildCorePlist({
418
- gateWrapperPath,
419
- logPath: join(JISHUSHELL_HOME, "jishushell-core.log"),
420
- }),
421
- installScope: "core",
422
- requiresSudo: false,
423
- reloadRequired: true,
424
- fix: "system-reload",
425
- });
426
- return files;
427
- }
428
- files.push({
429
- component: "systemd",
430
- id: "core.systemd-unit",
431
- path: SYSTEMD_CORE_SERVICE_PATH,
432
- content: buildJishushellCoreSystemdUnit({
433
- currentUser: resolveServiceUser(),
434
- realHome,
435
- coreStartWrapperPath,
436
- }),
437
- installScope: "core",
438
- requiresSudo: true,
439
- reloadRequired: true,
440
- fix: "system-reload",
441
- });
442
- return files;
443
- }
444
- export function getExpectedPanelSystemFiles(corePort = _serverPort, panelPort = DEFAULT_PANEL_PORT) {
445
- const nodeBin = process.execPath;
446
- const panelBin = resolveBundledPanelServerBin();
447
- const realHome = resolveRealHome();
448
- const panelStartWrapperPath = join(BIN_DIR, "jishushell-panel-start");
449
- const files = [
450
- {
451
- component: "wrapper",
452
- id: "panel.start-wrapper",
453
- path: panelStartWrapperPath,
454
- content: buildPanelStartWrapperContent({
455
- nodeBin,
456
- panelBin,
457
- realHome,
458
- corePort,
459
- panelPort,
460
- }),
461
- installScope: "panel",
462
- requiresSudo: false,
463
- reloadRequired: true,
464
- fix: "system-reload",
465
- },
466
- ];
467
- if (process.platform === "darwin") {
468
- files.push({
469
- component: "launchd",
470
- id: "panel.launchd-agent",
471
- path: join(resolveLaunchAgentsDir(realHome), "com.jishushell.panel.plist"),
472
- content: buildPanelPlist({
473
- panelWrapperPath: panelStartWrapperPath,
474
- logPath: join(JISHUSHELL_HOME, "jishushell-panel.log"),
475
- home: realHome,
476
- jishuHome: JISHUSHELL_HOME,
477
- corePort,
478
- panelPort,
479
- }),
480
- installScope: "panel",
481
- requiresSudo: false,
482
- reloadRequired: true,
483
- fix: "system-reload",
484
- });
485
- return files;
486
- }
487
- files.push({
488
- component: "systemd",
489
- id: "panel.systemd-unit",
490
- path: SYSTEMD_PANEL_SERVICE_PATH,
491
- content: buildJishushellPanelSystemdUnit({
492
- currentUser: resolveServiceUser(),
493
- realHome,
494
- panelStartWrapperPath,
495
- corePort,
496
- panelPort,
497
- }),
498
- installScope: "panel",
499
- requiresSudo: true,
500
- reloadRequired: true,
501
- fix: "system-reload",
502
- });
503
- return files;
504
- }
505
- export function getExpectedNomadSystemFiles() {
506
- const configPath = join(NOMAD_CONFIG_DIR, "nomad.hcl");
507
- const files = [
508
- {
509
- component: "nomad",
510
- id: "nomad.config",
511
- path: configPath,
512
- content: buildExpectedNomadConfigContent(),
513
- installScope: "nomad",
514
- requiresSudo: false,
515
- reloadRequired: true,
516
- fix: "system-reload",
517
- },
518
- ];
519
- const nomadPath = resolveNomadExecutable();
520
- if (process.platform === "darwin") {
521
- const laDir = resolveLaunchAgentsDir();
522
- const colimaSocket = managedColimaSocketPath(JISHUSHELL_HOME, COLIMA_PROFILE);
523
- const colimaDockerHost = managedColimaDockerHost(JISHUSHELL_HOME, COLIMA_PROFILE);
524
- const colimaWrapperPath = join(BIN_DIR, "colima-launchd-wrapper.sh");
525
- const nomadWrapperPath = join(BIN_DIR, "nomad-launchd-wrapper.sh");
526
- files.push({
527
- component: "wrapper",
528
- id: "nomad.colima-wrapper",
529
- path: colimaWrapperPath,
530
- content: buildColimaWrapperScript({
531
- colimaHome: _COLIMA_DIR,
532
- profile: COLIMA_PROFILE,
533
- socket: colimaSocket,
534
- colimaBin: resolveColimaExecutable(),
535
- }),
536
- installScope: "nomad",
537
- requiresSudo: false,
538
- reloadRequired: true,
539
- fix: "system-reload",
540
- }, {
541
- component: "launchd",
542
- id: "nomad.colima-launchd-agent",
543
- path: join(laDir, "com.jishushell.colima.plist"),
544
- content: buildColimaPlist({
545
- wrapperPath: colimaWrapperPath,
546
- colimaHome: _COLIMA_DIR,
547
- logPath: join(_COLIMA_DIR, "colima-launchd.log"),
548
- }),
549
- installScope: "nomad",
550
- requiresSudo: false,
551
- reloadRequired: true,
552
- fix: "system-reload",
553
- }, {
554
- component: "wrapper",
555
- id: "nomad.launchd-wrapper",
556
- path: nomadWrapperPath,
557
- content: buildNomadWaitWrapper({
558
- dockerHost: colimaDockerHost,
559
- nomadBin: nomadPath,
560
- configPath,
561
- }),
562
- installScope: "nomad",
563
- requiresSudo: false,
564
- reloadRequired: true,
565
- fix: "system-reload",
566
- }, {
567
- component: "launchd",
568
- id: "nomad.launchd-agent",
569
- path: join(laDir, "com.jishushell.nomad.plist"),
570
- content: buildNomadPlist({
571
- wrapperPath: nomadWrapperPath,
572
- dockerHost: colimaDockerHost,
573
- logPath: join(NOMAD_CONFIG_DIR, "nomad.log"),
574
- }),
575
- installScope: "nomad",
576
- requiresSudo: false,
577
- reloadRequired: true,
578
- fix: "system-reload",
579
- });
580
- return files;
581
- }
582
- files.push({
583
- component: "systemd",
584
- id: "nomad.systemd-unit",
585
- path: SYSTEMD_NOMAD_SERVICE_PATH,
586
- content: buildNomadSystemdUnit({ nomadPath, configPath }),
587
- installScope: "nomad",
588
- requiresSudo: true,
589
- reloadRequired: true,
590
- fix: "system-reload",
591
- });
592
- return files;
593
- }
594
- export function getExpectedSystemFiles(options = {}) {
595
- const config = getCoreConfig();
596
- const envCorePort = Number(process.env.JISHUSHELL_CORE_PORT);
597
- const corePort = options.corePort ??
598
- (Number.isFinite(envCorePort) && envCorePort > 0 ? envCorePort : Number(config.core_port) || _serverPort);
599
- const panelPort = options.panelPort ?? DEFAULT_PANEL_PORT;
600
- const includePanel = options.includePanel ?? hasBundledPanel();
601
- const includeNomad = options.includeNomad ?? config.service_manager === "nomad";
602
- const files = getExpectedCoreSystemFiles(corePort);
603
- if (includePanel)
604
- files.push(...getExpectedPanelSystemFiles(corePort, panelPort));
605
- if (includeNomad)
606
- files.push(...getExpectedNomadSystemFiles());
607
- return files;
608
- }
609
- function persistCoreServicePort(port) {
610
- const config = getCoreConfig();
611
- if (Number(config.core_port) === port)
612
- return;
613
- config.core_port = port;
614
- saveCoreConfig(config);
615
- }
616
- // ── Task tracker (for SSE progress) ────────────────────────────────
617
- // Storage, event dispatch, and subscribe plumbing now live in
618
- // task-registry.ts so non-setup callers (runtime-apps/*) can publish
619
- // tasks without pulling in the rest of setup-manager's bootstrap
620
- // surface. These re-exports preserve the original import surface used
621
- // by runtime/adapters/*, routes, and CLI.
622
- export { createTask, emitTask, getTask, getTaskSnapshot, getRunningTasks, subscribeTask, } from "./task-registry.js";
623
- const ANSI_ESCAPE_RE = /\u001B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])/g;
624
- function sanitizeTaskLine(line) {
625
- return line
626
- .replace(ANSI_ESCAPE_RE, "")
627
- .replace(/[\u0000-\u0008\u000B-\u001F\u007F]/g, "")
628
- .trimEnd();
629
- }
630
- /** Run a shell command as a spawned process, streaming output to a task */
631
- export function spawnWithTask(task, cmd, args, options = {}) {
632
- return new Promise((resolve) => {
633
- const env = { ...process.env, ...options.env };
634
- const child = nodeSpawn(cmd, args, {
635
- env,
636
- cwd: options.cwd,
637
- timeout: options.timeout || 600000,
638
- });
639
- let output = "";
640
- const stdoutDecoder = new StringDecoder("utf8");
641
- const stderrDecoder = new StringDecoder("utf8");
642
- let stdoutPending = "";
643
- let stderrPending = "";
644
- const emitLine = (rawLine) => {
645
- const line = sanitizeTaskLine(rawLine);
646
- if (!line.trim())
647
- return;
648
- // Try to parse progress
649
- if (options.progressParser) {
650
- const pct = options.progressParser(line);
651
- if (pct !== null) {
652
- emitTask(task, { type: "progress", message: line, progress: pct });
653
- return;
654
- }
655
- }
656
- emitTask(task, { type: "log", message: line });
657
- };
658
- const handleDecodedText = (text, stream) => {
659
- if (!text)
660
- return;
661
- output += text;
662
- const normalized = `${stream === "stdout" ? stdoutPending : stderrPending}${text}`
663
- .replace(/\r\n/g, "\n")
664
- .replace(/\r/g, "\n");
665
- const lines = normalized.split("\n");
666
- const pending = lines.pop() ?? "";
667
- if (stream === "stdout")
668
- stdoutPending = pending;
669
- else
670
- stderrPending = pending;
671
- for (const line of lines) {
672
- emitLine(line);
673
- }
674
- };
675
- child.stdout?.on("data", (data) => {
676
- handleDecodedText(stdoutDecoder.write(data), "stdout");
677
- });
678
- child.stderr?.on("data", (data) => {
679
- handleDecodedText(stderrDecoder.write(data), "stderr");
680
- });
681
- child.on("close", (code) => {
682
- handleDecodedText(stdoutDecoder.end(), "stdout");
683
- handleDecodedText(stderrDecoder.end(), "stderr");
684
- emitLine(stdoutPending);
685
- emitLine(stderrPending);
686
- resolve({ ok: code === 0, output });
687
- });
688
- child.on("error", (err) => {
689
- emitTask(task, { type: "log", message: `Error: ${err.message}` });
690
- resolve({ ok: false, output: err.message });
691
- });
692
- });
693
- }
694
- // ── Progress parsers ───────────────────────────────────────────────
695
- export function npmProgressParser(line) {
696
- // npm shows "added X packages" at the end
697
- if (line.includes("added") && line.includes("packages"))
698
- return 100;
699
- // npm progress: "reify:packagename: timing"
700
- if (line.includes("reify:"))
701
- return null; // just a log line
702
- return null;
703
- }
704
- export function dockerBuildProgressParser(line) {
705
- // Docker build steps: "Step 1/6", "Step 2/6", etc.
706
- const legacyMatch = line.match(/Step\s+(\d+)\/(\d+)/);
707
- if (legacyMatch) {
708
- return Math.round((parseInt(legacyMatch[1], 10) / parseInt(legacyMatch[2], 10)) * 100);
709
- }
710
- // BuildKit plain output: "#5 [2/4] COPY node_modules ..."
711
- const buildkitMatch = line.match(/\[(\d+)\/(\d+)\]/);
712
- if (buildkitMatch) {
713
- return Math.round((parseInt(buildkitMatch[1], 10) / parseInt(buildkitMatch[2], 10)) * 100);
714
- }
715
- if (/exporting to image/i.test(line))
716
- return 95;
717
- if (/naming to /i.test(line))
718
- return 98;
719
- return null;
720
- }
721
- function curlProgressParser(line) {
722
- // curl with -# shows progress
723
- const match = line.match(/(\d+\.?\d*)%/);
724
- if (match)
725
- return Math.round(parseFloat(match[1]));
726
- return null;
727
- }
728
- // ── Dir size tracker for npm installs ──────────────────────────────
729
- export function getDirSizeMB(dir) {
730
- try {
731
- const result = execFileSync("du", ["-sm", dir], { encoding: "utf-8", timeout: 5000, stdio: ["pipe", "pipe", "pipe"] });
732
- return parseInt(result.split("\t")[0], 10) || 0;
733
- }
734
- catch {
735
- return 0;
736
- }
737
- }
738
- function checkCommand(cmd, versionFlag = "--version") {
739
- try {
740
- const version = execFileSync(cmd, [versionFlag], { encoding: "utf-8", timeout: 10000, stdio: ["pipe", "pipe", "pipe"] }).trim();
741
- let cmdPath = "";
742
- try {
743
- cmdPath = execFileSync("which", [cmd], { encoding: "utf-8", timeout: 5000, stdio: ["pipe", "pipe", "pipe"] }).trim();
744
- }
745
- catch { }
746
- return { ok: true, version, path: cmdPath };
747
- }
748
- catch {
749
- return { ok: false, version: "", path: "" };
750
- }
751
- }
752
- function isPortListening(port) {
753
- if (!Number.isInteger(port) || port < 1 || port > 65535)
754
- return false;
755
- const p = String(port);
756
- const matchesPort = (output) => new RegExp(`:${p}\\s`).test(output);
757
- try {
758
- if (process.platform === "darwin") {
759
- try {
760
- const result = execFileSync("lsof", ["-iTCP:" + p, "-sTCP:LISTEN", "-t"], { encoding: "utf-8", timeout: 5000, stdio: ["pipe", "pipe", "pipe"] });
761
- if (result.trim().length > 0)
762
- return true;
763
- }
764
- catch {
765
- }
766
- try {
767
- const result = execFileSync("ss", ["-tlnp"], { encoding: "utf-8", timeout: 5000, stdio: ["pipe", "pipe", "pipe"] });
768
- if (matchesPort(result))
769
- return true;
770
- }
771
- catch {
772
- }
773
- const result = execFileSync("netstat", ["-tlnp"], { encoding: "utf-8", timeout: 5000, stdio: ["pipe", "pipe", "pipe"] });
774
- return matchesPort(result);
775
- }
776
- // Linux: prefer ss, fall back to netstat
777
- try {
778
- const result = execFileSync("ss", ["-tlnp"], { encoding: "utf-8", timeout: 5000, stdio: ["pipe", "pipe", "pipe"] });
779
- return matchesPort(result);
780
- }
781
- catch {
782
- const result = execFileSync("netstat", ["-tlnp"], { encoding: "utf-8", timeout: 5000, stdio: ["pipe", "pipe", "pipe"] });
783
- return matchesPort(result);
784
- }
785
- }
786
- catch {
787
- return false;
788
- }
789
- }
790
- function waitForListeningPort(port, timeoutSeconds) {
791
- const deadline = Date.now() + timeoutSeconds * 1000;
792
- while (Date.now() < deadline) {
793
- if (isPortListening(port))
794
- return true;
795
- try {
796
- execFileSync("sleep", ["1"], { timeout: 2000 });
797
- }
798
- catch {
799
- return isPortListening(port);
800
- }
801
- }
802
- return isPortListening(port);
803
- }
804
- function checkSudo() {
805
- try {
806
- execSync("sudo -n true 2>/dev/null", { timeout: 3000 });
807
- return true;
808
- }
809
- catch {
810
- return false;
811
- }
812
- }
813
- /** Check if kernel memory cgroup is enabled (required for Docker memory stats on RPi) */
814
- function isCgroupMemoryEnabled() {
815
- try {
816
- const cgroups = readFileSync("/proc/cgroups", "utf-8");
817
- const memLine = cgroups.split("\n").find(l => l.startsWith("memory\t"));
818
- if (!memLine)
819
- return false;
820
- // Format: name hierarchy num_cgroups enabled
821
- return memLine.trim().endsWith("1");
822
- }
823
- catch {
824
- return true; /* non-Linux or unreadable — assume ok */
825
- }
826
- }
827
- /** Enable cgroup memory in boot cmdline if not already enabled. Returns true if a reboot is needed. */
828
- export function ensureCgroupMemory() {
829
- if (isCgroupMemoryEnabled())
830
- return false;
831
- const candidates = ["/boot/firmware/cmdline.txt", "/boot/cmdline.txt"];
832
- for (const f of candidates) {
833
- if (!existsSync(f))
834
- continue;
835
- try {
836
- const content = readFileSync(f, "utf-8").trim();
837
- if (content.includes("cgroup_memory=1"))
838
- return false; // already in cmdline, just needs reboot
839
- const patched = `${content} cgroup_memory=1 cgroup_enable=memory`;
840
- execFileSync("sudo", ["cp", f, f + ".bak"], { timeout: 5000 });
841
- sudoCopySystemFile(patched + "\n", f, "644");
842
- console.log(`[setup] enabled cgroup memory in ${f} (reboot required)`);
843
- return true;
844
- }
845
- catch (e) {
846
- console.warn(`[setup] failed to patch ${f}:`, e.message);
847
- }
848
- }
849
- return false;
850
- }
851
- function canAccessDockerDaemon(timeout = 10000) {
852
- const env = buildDockerClientEnv({
853
- jishuHome: JISHUSHELL_HOME,
854
- colimaProfile: COLIMA_PROFILE,
855
- });
856
- try {
857
- execFileSync("docker", ["info"], { timeout, stdio: "ignore", env });
858
- return true;
859
- }
860
- catch { }
861
- try {
862
- execFileSync("sudo", ["-n", "docker", "info"], { timeout, stdio: "ignore", env });
863
- return true;
864
- }
865
- catch { }
866
- return false;
867
- }
868
- function getDockerVersionLine(timeout = 10000) {
869
- try {
870
- return execFileSync("docker", ["--version"], { encoding: "utf-8", timeout }).trim();
871
- }
872
- catch { }
873
- try {
874
- return execFileSync("sudo", ["-n", "docker", "--version"], { encoding: "utf-8", timeout }).trim();
875
- }
876
- catch { }
877
- return "installed";
878
- }
879
- export async function getSetupStatus() {
880
- // Fast path: if setup is already complete, do lightweight checks before returning cached result
881
- const config = getCoreConfig();
882
- if (config.service_manager) {
883
- const localBin = join(OPENCLAW_BIN_DIR, "openclaw");
884
- const localBinOk = existsSync(localBin);
885
- const fastDockerImageReady = checkDockerImageExists();
886
- const openclawOk = localBinOk || fastDockerImageReady;
887
- // Lightweight validation: verify critical services are actually available
888
- const dockerOk = canAccessDockerDaemon(5000);
889
- const nomadOk = isPortListening(4646);
890
- const hasSudo = checkSudo();
891
- // If any critical check fails, fall through to the slow full check path
892
- if (!openclawOk || !dockerOk || !nomadOk || !hasSudo) {
893
- // Fall through to full check below
894
- }
895
- else {
896
- // Fetch real versions (cheap execs, no fallback to slow path)
897
- let dockerVer = "installed";
898
- try {
899
- dockerVer = execFileSync("docker", ["--version"], { encoding: "utf-8", timeout: 5000, stdio: ["pipe", "pipe", "pipe"] }).trim().split("\n")[0];
900
- }
901
- catch { }
902
- let nomadVer = "installed";
903
- try {
904
- nomadVer = execFileSync(NOMAD_BIN, ["--version"], { encoding: "utf-8", timeout: 5000, stdio: ["pipe", "pipe", "pipe"] }).trim().split("\n")[0];
905
- }
906
- catch { }
907
- let openclawVer = "installed";
908
- let openclawPath = localBin;
909
- // Prefer npm package.json for accurate OpenClaw version.
910
- try {
911
- const pkg = join(OPENCLAW_MODULES, "openclaw", "package.json");
912
- if (existsSync(pkg))
913
- openclawVer = JSON.parse(readFileSync(pkg, "utf-8")).version || openclawVer;
914
- }
915
- catch { }
916
- const ready = openclawOk && fastDockerImageReady;
917
- return {
918
- node: { name: "Node.js", installed: true, running: true, version: process.version, path: process.execPath },
919
- docker: { name: "Docker", installed: true, running: true, version: dockerVer, path: "" },
920
- nomad: { name: "Nomad", installed: true, running: true, version: nomadVer, path: NOMAD_BIN },
921
- openclaw: { name: "OpenClaw", installed: openclawOk, running: false, version: openclawVer, path: openclawPath },
922
- runtimeImageReady: fastDockerImageReady,
923
- ready,
924
- providerConfigured: hasLlmProviderSetup(),
925
- hasSudo: true,
926
- runtimes: await buildRuntimesStatus(),
927
- };
928
- }
929
- }
930
- const NODE_MINIMUM_MAJOR = 22;
931
- // Use the currently-running Node binary (process.execPath) as the ground
932
- // truth — avoids false-negative when PATH doesn't include nvm's bin dir
933
- // (e.g. when started via systemd with a minimal environment).
934
- const nodeVersion = process.version;
935
- const nodeMajor = parseInt(nodeVersion.replace("v", "").split(".")[0], 10);
936
- const nodeStatus = {
937
- name: "Node.js",
938
- installed: true,
939
- running: true,
940
- version: nodeVersion,
941
- path: process.execPath,
942
- needsUpgrade: nodeMajor < NODE_MINIMUM_MAJOR,
943
- };
944
- const docker = checkCommand("docker");
945
- // Use docker info to verify daemon accessibility (not just process existence)
946
- // Also try sudo in case the user hasn't logged out since being added to the docker group
947
- const dockerRunning = canAccessDockerDaemon(10000);
948
- const dockerStatus = {
949
- name: "Docker",
950
- installed: docker.ok,
951
- running: dockerRunning,
952
- version: docker.version.split("\n")[0],
953
- path: docker.path,
954
- };
955
- let nomad = checkCommand("nomad");
956
- if (!nomad.ok && existsSync(NOMAD_BIN)) {
957
- nomad = checkCommand(NOMAD_BIN);
958
- }
959
- const nomadRunning = isPortListening(4646);
960
- const nomadStatus = {
961
- name: "Nomad",
962
- installed: nomad.ok,
963
- running: nomadRunning,
964
- version: nomad.version.split("\n")[0],
965
- path: nomad.path || NOMAD_BIN,
966
- };
967
- let openclaw = checkCommand("openclaw");
968
- if (!openclaw.ok) {
969
- const localBin = join(OPENCLAW_BIN_DIR, "openclaw");
970
- if (existsSync(localBin)) {
971
- let ver = "installed";
972
- try {
973
- const pkg = join(OPENCLAW_MODULES, "openclaw", "package.json");
974
- if (existsSync(pkg)) {
975
- const pkgJson = JSON.parse(readFileSync(pkg, "utf-8"));
976
- ver = pkgJson.version || "installed";
977
- }
978
- }
979
- catch { }
980
- openclaw = { ok: true, version: ver, path: localBin };
981
- }
982
- }
983
- const runtimeImageReady = checkDockerImageExists();
984
- // If the Docker image already exists, treat openclaw as installed even when
985
- // the local npm package is absent — the image is all that's needed to run instances.
986
- if (!openclaw.ok && runtimeImageReady) {
987
- const imageTag = resolveDockerImageTag();
988
- const tagVersion = imageTag.split(":").pop() || "local";
989
- openclaw = { ok: true, version: tagVersion, path: imageTag };
990
- }
991
- const openclawStatus = {
992
- name: "OpenClaw",
993
- installed: openclaw.ok,
994
- running: false,
995
- version: openclaw.version.split("\n")[0],
996
- path: openclaw.path,
997
- };
998
- const ready = nodeStatus.installed && !nodeStatus.needsUpgrade && dockerStatus.installed && dockerStatus.running && nomadStatus.installed && nomadStatus.running && openclawStatus.installed && runtimeImageReady;
999
- const providerConfigured = hasLlmProviderSetup();
1000
- // Read-only check: report whether cgroup memory needs fixing (actual fix is in POST install routes)
1001
- let needsReboot;
1002
- if (dockerStatus.installed && !isCgroupMemoryEnabled()) {
1003
- needsReboot = true;
1004
- }
1005
- const runningTasks = getRunningTasks();
1006
- return { node: nodeStatus, docker: dockerStatus, nomad: nomadStatus, openclaw: openclawStatus, ready, providerConfigured, runtimeImageReady, hasSudo: checkSudo(), needsReboot, runningTasks: runningTasks.length ? runningTasks : undefined, runtimes: await buildRuntimesStatus() };
1007
- }
1008
- /**
1009
- * Build the per-runtime install status block by iterating over every
1010
- * registered adapter. A new adapter that implements `getInstallStatus()`
1011
- * automatically appears here — no change required in this function.
1012
- *
1013
- * Each probe is bounded by a short timeout so a hung adapter (slow docker
1014
- * socket, DNS stall) cannot block the `/api/setup/status` endpoint. This
1015
- * mirrors the pattern used by `routes/runtime.ts:probeInstallStatus` so
1016
- * Setup wizard and `/api/runtime/catalog` see a consistent view.
1017
- */
1018
- const BUILD_RUNTIMES_PROBE_TIMEOUT_MS = 2500;
1019
- async function buildRuntimesStatus() {
1020
- const adapters = listRegisteredAdapters().filter((a) => typeof a.getInstallStatus === "function");
1021
- const probes = adapters.map(async (adapter) => {
1022
- let timer;
1023
- try {
1024
- const status = await Promise.race([
1025
- Promise.resolve(adapter.getInstallStatus()),
1026
- new Promise((_, reject) => {
1027
- timer = setTimeout(() => reject(new Error("install-status probe timed out")), BUILD_RUNTIMES_PROBE_TIMEOUT_MS);
1028
- }),
1029
- ]);
1030
- if (!status)
1031
- return null;
1032
- const sync = status;
1033
- return [adapter.agentType, { ...sync, required: !!adapter.required }];
1034
- }
1035
- catch {
1036
- return null;
1037
- }
1038
- finally {
1039
- if (timer)
1040
- clearTimeout(timer);
1041
- }
1042
- });
1043
- const out = {};
1044
- for (const result of await Promise.all(probes)) {
1045
- if (result)
1046
- out[result[0]] = result[1];
1047
- }
1048
- return Object.keys(out).length ? out : undefined;
1049
- }
1050
- // ── Upgrade Node.js ────────────────────────────────────────────────
1051
- export async function upgradeNode(targetMajor = 22) {
1052
- try {
1053
- const current = process.version; // e.g. "v20.20.1"
1054
- const currentMajor = parseInt(current.replace("v", "").split(".")[0], 10);
1055
- if (currentMajor >= targetMajor) {
1056
- return { ok: true, message: `Node.js ${current} already meets requirement (>= ${targetMajor})` };
1057
- }
1058
- const task = createTask("node-upgrade");
1059
- emitTask(task, { type: "progress", message: `升级 Node.js: ${current} → v${targetMajor}`, progress: 0 });
1060
- if (process.platform === "darwin") {
1061
- try {
1062
- execSync("brew --version", { timeout: 5000 });
1063
- }
1064
- catch {
1065
- emitTask(task, { type: "error", message: "未找到 Homebrew" });
1066
- task.status = "error";
1067
- return { ok: false, message: "Homebrew not found", error: "Install Homebrew first: https://brew.sh", taskId: task.id };
1068
- }
1069
- emitTask(task, { type: "progress", message: `安装 Node.js ${targetMajor} (brew)...`, progress: 20 });
1070
- const installResult = await spawnWithTask(task, "brew", ["install", `node@${targetMajor}`], { timeout: 300000 });
1071
- if (!installResult.ok) {
1072
- emitTask(task, { type: "error", message: "Node.js 安装失败" });
1073
- task.status = "error";
1074
- return { ok: false, message: "Node.js install failed", error: installResult.output, taskId: task.id };
1075
- }
1076
- emitTask(task, { type: "progress", message: "链接 Node.js...", progress: 80 });
1077
- try {
1078
- execSync(`brew link --overwrite --force node@${targetMajor}`, { timeout: 30000 });
1079
- }
1080
- catch { }
1081
- }
1082
- else {
1083
- // Use NodeSource setup script
1084
- emitTask(task, { type: "log", message: "下载 NodeSource 安装脚本..." });
1085
- emitTask(task, { type: "progress", message: "配置软件源...", progress: 10 });
1086
- // Use a unique temp path to prevent TOCTOU race: a fixed name like
1087
- // /tmp/nodesource_setup_22.sh could be replaced by another process
1088
- // between download (curl) and execution (sudo bash).
1089
- const nsScriptPath = join(tmpdir(), `nodesource_setup_${targetMajor}_${randomBytes(8).toString("hex")}.sh`);
1090
- const dlResult = await spawnWithTask(task, "curl", ["-fsSL", `https://deb.nodesource.com/setup_${targetMajor}.x`, "-o", nsScriptPath], { timeout: 60000 });
1091
- if (!dlResult.ok) {
1092
- emitTask(task, { type: "error", message: "NodeSource 脚本下载失败" });
1093
- task.status = "error";
1094
- return { ok: false, message: "NodeSource script download failed", error: dlResult.output, taskId: task.id };
1095
- }
1096
- const setupResult = await spawnWithTask(task, "sudo", ["-E", "bash", nsScriptPath], { timeout: 120000 });
1097
- if (!setupResult.ok) {
1098
- emitTask(task, { type: "error", message: "NodeSource 配置失败" });
1099
- task.status = "error";
1100
- return { ok: false, message: "Node.js source setup failed", error: setupResult.output, taskId: task.id };
1101
- }
1102
- emitTask(task, { type: "progress", message: "安装 Node.js...", progress: 50 });
1103
- const installResult = await spawnWithTask(task, "sudo", ["apt-get", "install", "-y", "nodejs"], { timeout: 300000 });
1104
- if (!installResult.ok) {
1105
- emitTask(task, { type: "error", message: "Node.js 安装失败" });
1106
- task.status = "error";
1107
- return { ok: false, message: "Node.js install failed", error: installResult.output, taskId: task.id };
1108
- }
1109
- }
1110
- const newVersion = execSync("node --version", { encoding: "utf-8", timeout: 5000 }).trim();
1111
- emitTask(task, { type: "done", message: `Node.js 升级完成: ${newVersion}`, progress: 100 });
1112
- task.status = "done";
1113
- return { ok: true, message: `Node.js upgraded to ${newVersion}. 请重启 JishuShell 以使用新版本。`, taskId: task.id };
1114
- }
1115
- catch (e) {
1116
- return { ok: false, message: "Node.js upgrade failed", error: e.message };
1117
- }
1118
- }
1119
- // ── Install Docker (async with progress) ───────────────────────────
1120
- async function installDockerWithTask(task) {
1121
- try {
1122
- emitTask(task, { type: "progress", message: "开始安装 Docker...", progress: 0 });
1123
- // macOS short-circuit: the rest of this function targets apt/get.docker.com,
1124
- // both of which silently no-op or hard-fail on Darwin. Docker on macOS is
1125
- // provided by Colima (auto-installed by the bash installer at
1126
- // install/jishu-install.sh) — not by this code path. Refuse early with a
1127
- // clear pointer so the user doesn't see a confusing apt error.
1128
- if (process.platform === "darwin") {
1129
- const msg = "macOS Docker 需要 Colima。请运行 shell 安装器 (curl -fsSL https://raw.githubusercontent.com/nicepkg/jishushell/main/install/jishu-install.sh | bash),或参阅 docs/macos-colima.md 手动安装 Colima。";
1130
- emitTask(task, { type: "error", message: msg });
1131
- task.status = "error";
1132
- return { ok: false, message: msg, error: "darwin-not-supported-via-this-path" };
1133
- }
1134
- const user = execSync("whoami", { encoding: "utf-8", timeout: 5000 }).trim();
1135
- // ── Try the get.docker.com convenience script ─────────────────
1136
- emitTask(task, { type: "log", message: "下载 Docker 安装脚本..." });
1137
- emitTask(task, { type: "progress", message: "下载中...", progress: 5 });
1138
- // Unique temp path prevents TOCTOU: another user can't swap a fixed /tmp/get-docker.sh
1139
- // between our download and the sudo sh invocation.
1140
- const dockerScriptPath = join(tmpdir(), `get-docker_${randomBytes(8).toString("hex")}.sh`);
1141
- const dlResult = await spawnWithTask(task, "curl", ["-fsSL", "https://get.docker.com", "-o", dockerScriptPath], {
1142
- timeout: 60000,
1143
- });
1144
- let scriptOk = false;
1145
- if (dlResult.ok) {
1146
- emitTask(task, { type: "log", message: "运行 Docker 安装脚本..." });
1147
- const scriptResult = await spawnWithTask(task, "sudo", ["sh", dockerScriptPath], {
1148
- timeout: 600000,
1149
- progressParser: (line) => {
1150
- if (line.includes("Executing docker install script"))
1151
- return 10;
1152
- if (line.includes("apt-get update"))
1153
- return 20;
1154
- if (line.includes("Installing packages"))
1155
- return 40;
1156
- if (line.includes("docker-ce"))
1157
- return 60;
1158
- if (line.includes("containerd"))
1159
- return 70;
1160
- if (line.includes("Created symlink"))
1161
- return 85;
1162
- return null;
1163
- },
1164
- });
1165
- scriptOk = scriptResult.ok;
1166
- if (!scriptOk) {
1167
- emitTask(task, { type: "log", message: "便捷脚本安装失败,尝试 apt 仓库方式..." });
1168
- }
1169
- }
1170
- else {
1171
- emitTask(task, { type: "log", message: "下载便捷脚本失败,尝试 apt 仓库方式..." });
1172
- }
1173
- // ── Fallback: apt-repo manual install (handles Debian trixie pre-releases) ─
1174
- if (!scriptOk) {
1175
- emitTask(task, { type: "progress", message: "通过 apt 仓库安装 Docker...", progress: 15 });
1176
- // Detect system ID + codename; downgrade trixie/sid to bookworm.
1177
- let codename = "bookworm";
1178
- let repoOs = "debian";
1179
- try {
1180
- const osRelease = readFileSync("/etc/os-release", "utf-8");
1181
- const codenameMatch = osRelease.match(/^VERSION_CODENAME=(.+)$/m);
1182
- const distroId = (osRelease.match(/^ID=(.+)$/m)?.[1] || "debian").trim();
1183
- const raw = (codenameMatch?.[1] || "").trim();
1184
- repoOs = (distroId === "ubuntu") ? "ubuntu" : "debian";
1185
- // Debian testing/unstable (trixie, sid) → use the previous stable repo.
1186
- const unstableCodenames = new Set(["trixie", "forky", "sid", "unstable", "testing"]);
1187
- const ubuntuFallback = "noble";
1188
- if (distroId === "ubuntu" && unstableCodenames.has(raw)) {
1189
- codename = ubuntuFallback;
1190
- }
1191
- else if (unstableCodenames.has(raw)) {
1192
- codename = "bookworm";
1193
- }
1194
- else {
1195
- codename = raw || "bookworm";
1196
- }
1197
- }
1198
- catch { }
1199
- emitTask(task, { type: "log", message: `使用仓库 codename: ${codename} (OS: ${repoOs})` });
1200
- const aptSteps = [
1201
- ["sudo", ["apt-get", "update", "-qq"]],
1202
- ["sudo", ["apt-get", "install", "-y", "-qq", "ca-certificates", "curl", "gnupg"]],
1203
- ["sudo", ["install", "-m", "0755", "-d", "/etc/apt/keyrings"]],
1204
- ["sudo", ["bash", "-c",
1205
- `curl -fsSL https://download.docker.com/linux/${repoOs}/gpg | gpg --dearmor --yes -o /etc/apt/keyrings/docker.gpg && chmod a+r /etc/apt/keyrings/docker.gpg`
1206
- ]],
1207
- ["sudo", ["bash", "-c",
1208
- `echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/${repoOs} ${codename} stable" > /etc/apt/sources.list.d/docker.list`
1209
- ]],
1210
- ["sudo", ["apt-get", "update", "-qq"]],
1211
- ["sudo", ["apt-get", "install", "-y", "-qq",
1212
- "docker-ce", "docker-ce-cli", "containerd.io", "docker-buildx-plugin", "docker-compose-plugin"
1213
- ]],
1214
- ];
1215
- const progressSteps = [5, 15, 20, 30, 35, 45, 80];
1216
- for (let i = 0; i < aptSteps.length; i++) {
1217
- const [cmd, args] = aptSteps[i];
1218
- emitTask(task, { type: "progress", message: `${cmd} ${args[0]}...`, progress: progressSteps[i] });
1219
- const r = await spawnWithTask(task, cmd, args, { timeout: 300000 });
1220
- if (!r.ok) {
1221
- emitTask(task, { type: "error", message: `apt 安装失败 (步骤 ${i + 1}): ${args.join(" ")}` });
1222
- task.status = "error";
1223
- return { ok: false, message: "Docker apt installation failed", error: r.output, taskId: task.id };
1224
- }
1225
- }
1226
- }
1227
- // ── Wrap up ────────────────────────────────────────────────────
1228
- emitTask(task, { type: "progress", message: "配置用户权限...", progress: 90 });
1229
- try {
1230
- execFileSync("sudo", ["groupadd", "docker"], { timeout: 10000 });
1231
- }
1232
- catch { }
1233
- try {
1234
- execFileSync("sudo", ["usermod", "-aG", "docker", user], { timeout: 10000 });
1235
- }
1236
- catch { }
1237
- emitTask(task, { type: "log", message: "注意: Docker 用户组变更可能需要重新登录才能生效" });
1238
- emitTask(task, { type: "progress", message: "启动 Docker 服务...", progress: 93 });
1239
- try {
1240
- execSync("sudo systemctl enable --now docker", { timeout: 30000 });
1241
- }
1242
- catch { }
1243
- // Enable cgroup memory for Docker stats (RPi default has it disabled)
1244
- const needsReboot = ensureCgroupMemory();
1245
- if (needsReboot) {
1246
- emitTask(task, { type: "log", message: "已启用内存 cgroup(需要重启生效,Docker 内存统计才会正常)" });
1247
- }
1248
- const version = getDockerVersionLine(10000);
1249
- // Verify the daemon via `sudo docker` (needed when the current user is not in the docker group yet).
1250
- const daemonOk = canAccessDockerDaemon(10000);
1251
- if (daemonOk) {
1252
- const doneMsg = needsReboot
1253
- ? `Docker 安装完成: ${version}(需要重启以启用内存统计)`
1254
- : `Docker 安装完成: ${version}`;
1255
- emitTask(task, { type: "done", message: doneMsg, progress: 100 });
1256
- task.status = "done";
1257
- return { ok: true, message: `Docker installed: ${version}`, needsReboot, taskId: task.id };
1258
- }
1259
- else {
1260
- emitTask(task, { type: "error", message: `Docker 已安装但 daemon 未运行: ${version}` });
1261
- task.status = "error";
1262
- return { ok: false, message: `Docker installed but daemon not accessible`, error: "Try: sudo systemctl start docker", taskId: task.id };
1263
- }
1264
- }
1265
- catch (e) {
1266
- return { ok: false, message: "Docker installation failed", error: e.message };
1267
- }
1268
- }
1269
- /** Ensure current user is in docker group and service is enabled (idempotent) */
1270
- function ensureDockerPostInstall() {
1271
- try {
1272
- const user = execSync("whoami", { encoding: "utf-8", timeout: 5000 }).trim();
1273
- try {
1274
- execFileSync("sudo", ["groupadd", "docker"], { timeout: 5000, stdio: "pipe" });
1275
- }
1276
- catch { }
1277
- try {
1278
- execFileSync("sudo", ["usermod", "-aG", "docker", user], { timeout: 5000 });
1279
- }
1280
- catch { }
1281
- try {
1282
- execFileSync("sudo", ["systemctl", "enable", "--now", "docker"], { timeout: 10000 });
1283
- }
1284
- catch { }
1285
- }
1286
- catch { }
1287
- }
1288
- export async function installDocker() {
1289
- if (canAccessDockerDaemon(5000)) {
1290
- ensureDockerPostInstall();
1291
- const needsReboot = ensureCgroupMemory();
1292
- return { ok: true, message: "Docker already installed", needsReboot };
1293
- }
1294
- const task = createTask("docker");
1295
- return installDockerWithTask(task);
1296
- }
1297
- export function startInstallDocker() {
1298
- if (canAccessDockerDaemon(5000)) {
1299
- ensureDockerPostInstall();
1300
- ensureCgroupMemory();
1301
- return { ok: true, message: "Docker already installed" };
1302
- }
1303
- const task = createTask("docker");
1304
- void installDockerWithTask(task).catch((err) => {
1305
- emitTask(task, { type: "error", message: `Docker 安装失败: ${err?.message || err}` });
1306
- task.status = "error";
1307
- });
1308
- return { ok: true, message: "Docker install started", taskId: task.id };
1309
- }
1310
- // ── Install Nomad (async with progress) ────────────────────────────
1311
- function getNomadDownloadUrl() {
1312
- const arch = process.arch === "arm64" ? "arm64" : "amd64";
1313
- const os = process.platform === "linux" ? "linux" : "darwin";
1314
- return `https://releases.hashicorp.com/nomad/${NOMAD_VERSION}/nomad_${NOMAD_VERSION}_${os}_${arch}.zip`;
1315
- }
1316
- /**
1317
- * Signal nomad agents by exact process name (pgrep -x nomad) to avoid the
1318
- * classic pkill -f self-match bug: a command line like "pkill -f 'nomad agent'"
1319
- * literally contains the pattern and pkill kills itself before reaching the
1320
- * real nomad process. pgrep's own comm is "pgrep" (not "nomad") so -x nomad
1321
- * cannot self-match. Unprivileged kill is tried first; sudo -n as a fallback
1322
- * if the running nomad is owned by root (1.6.5 User=root unit).
1323
- */
1324
- function killNomadByProcName() {
1325
- const collect = () => {
1326
- try {
1327
- const out = execSync("pgrep -x nomad 2>/dev/null || true", { encoding: "utf-8" }).trim();
1328
- return out.split("\n").filter(Boolean);
1329
- }
1330
- catch {
1331
- return [];
1332
- }
1333
- };
1334
- const sendSignal = (sig, pids) => {
1335
- if (pids.length === 0)
1336
- return;
1337
- try {
1338
- execFileSync("sudo", ["-n", "kill", `-${sig}`, ...pids], { timeout: 5000, stdio: "pipe" });
1339
- return;
1340
- }
1341
- catch { }
1342
- try {
1343
- execSync(`kill -${sig} ${pids.join(" ")} 2>/dev/null || true`, { timeout: 5000 });
1344
- }
1345
- catch { }
1346
- };
1347
- let pids = collect();
1348
- sendSignal("TERM", pids);
1349
- if (pids.length > 0) {
1350
- // Short grace period, then SIGKILL any survivors.
1351
- execSync("sleep 2");
1352
- pids = collect();
1353
- sendSignal("KILL", pids);
1354
- }
1355
- }
1356
- /** Compare two "a.b.c" semver strings; returns a > b. */
1357
- function isNomadVersionGreater(a, b) {
1358
- const parse = (v) => v.replace(/^v/, "").split(".").map(n => parseInt(n, 10) || 0);
1359
- const [aMaj, aMin, aPat] = parse(a);
1360
- const [bMaj, bMin, bPat] = parse(b);
1361
- if (aMaj !== bMaj)
1362
- return aMaj > bMaj;
1363
- if (aMin !== bMin)
1364
- return aMin > bMin;
1365
- return aPat > bPat;
1366
- }
1367
- /**
1368
- * Auto-migrate from a higher Nomad version (e.g. 1.11.3 BSL) back to the
1369
- * jishushell target (1.6.5 MPL). Called when installNomad detects a local
1370
- * binary whose semver is > NOMAD_VERSION. Destructive to Nomad's raft state
1371
- * (schema is not backward compatible) but preserves instance configs under
1372
- * ~/.jishushell/instances/*. A single tar.gz snapshot of the old data_dir
1373
- * is kept under ~/.jishushell/nomad/backups/ for forensic inspection.
1374
- *
1375
- * Safe-first: the new binary is downloaded and verified BEFORE any existing
1376
- * state is touched. If any stage 1 step fails, state is untouched.
1377
- *
1378
- * Throws on failure so the caller's outer catch reports the error.
1379
- */
1380
- async function migrateNomadToTarget(currentVersion) {
1381
- console.log(`[nomad] Auto-migrating v${currentVersion} → v${NOMAD_VERSION} (BSL → MPL)`);
1382
- console.log("[nomad] Raft state is not backward-compatible; allocation history will be reset.");
1383
- console.log("[nomad] Instance configs under ~/.jishushell/instances/ are preserved.");
1384
- // ── Stage 1: download + verify new binary into a staging dir ─────────
1385
- const stageDir = mkdtempSync(join(tmpdir(), "nomad-migrate-"));
1386
- let backupFile = "";
1387
- try {
1388
- const stagedBin = join(stageDir, "nomad");
1389
- const zipPath = join(stageDir, "nomad.zip");
1390
- const url = getNomadDownloadUrl();
1391
- const arch = process.arch === "arm64" ? "arm64" : "amd64";
1392
- const os = process.platform === "linux" ? "linux" : "darwin";
1393
- const sumsUrl = `https://releases.hashicorp.com/nomad/${NOMAD_VERSION}/nomad_${NOMAD_VERSION}_SHA256SUMS`;
1394
- const sumsPath = join(stageDir, "SHA256SUMS");
1395
- console.log(`[nomad] Staging v${NOMAD_VERSION} (${os}/${arch})...`);
1396
- execFileSync("curl", ["-fsSL", url, "-o", zipPath], { timeout: 300000, stdio: "pipe" });
1397
- execFileSync("curl", ["-fsSL", sumsUrl, "-o", sumsPath], { timeout: 30000, stdio: "pipe" });
1398
- const sums = readFileSync(sumsPath, "utf-8");
1399
- const sumLine = sums.split("\n").find(l => l.includes(`nomad_${NOMAD_VERSION}_${os}_${arch}.zip`));
1400
- if (!sumLine)
1401
- throw new Error(`No checksum entry for nomad_${NOMAD_VERSION}_${os}_${arch}.zip`);
1402
- const expected = sumLine.split(/\s+/)[0];
1403
- // Match the bash installer: prefer sha256sum (GNU coreutils, Linux),
1404
- // fall back to shasum -a 256 (BSD, macOS default — sha256sum is not
1405
- // preinstalled there). Without this, triggering auto-migration from
1406
- // the WebUI / Node path on macOS would fail even though the shell
1407
- // installer works fine.
1408
- let actual;
1409
- try {
1410
- actual = execSync(`sha256sum "${zipPath}" | awk '{print $1}'`, { encoding: "utf-8" }).trim();
1411
- }
1412
- catch {
1413
- actual = execSync(`shasum -a 256 "${zipPath}" | awk '{print $1}'`, { encoding: "utf-8" }).trim();
1414
- }
1415
- if (expected !== actual) {
1416
- throw new Error(`Nomad checksum mismatch: expected ${expected}, got ${actual}`);
1417
- }
1418
- console.log("[nomad] Checksum verified");
1419
- execFileSync("unzip", ["-o", zipPath, "-d", stageDir], { timeout: 30000 });
1420
- chmodSync(stagedBin, 0o755);
1421
- const stagedVersionLine = execFileSync(stagedBin, ["version"], { encoding: "utf-8", timeout: 5000 }).trim().split("\n")[0];
1422
- if (!stagedVersionLine.includes(`v${NOMAD_VERSION}`)) {
1423
- throw new Error(`Staged binary reports "${stagedVersionLine}", expected v${NOMAD_VERSION}`);
1424
- }
1425
- console.log(`[nomad] Staged ${stagedVersionLine}`);
1426
- // ── Stage 2: destructive state changes begin ───────────────────────
1427
- console.log("[nomad] Stopping services...");
1428
- try {
1429
- execFileSync("sudo", ["-n", "systemctl", "stop", "jishushell"], { timeout: 15000, stdio: "pipe" });
1430
- }
1431
- catch { }
1432
- try {
1433
- execFileSync("sudo", ["-n", "systemctl", "stop", "nomad"], { timeout: 15000, stdio: "pipe" });
1434
- }
1435
- catch { }
1436
- // pkill -f 'nomad agent' matches pkill's own cmdline and self-terminates
1437
- // before reaching the real nomad process. Use pgrep -x nomad (exact proc
1438
- // name match; pgrep's comm is "pgrep") to avoid the self-match bug.
1439
- killNomadByProcName();
1440
- await new Promise(r => setTimeout(r, 2000));
1441
- // ── Stage 3: tar backup (single snapshot, overwrite any previous) ──
1442
- const backupDir = join(NOMAD_CONFIG_DIR, "backups");
1443
- if (existsSync(NOMAD_DATA_DIR)) {
1444
- try {
1445
- ensureDirHost(backupDir);
1446
- }
1447
- catch { }
1448
- const ts = new Date().toISOString().replace(/[-:]/g, "").replace(/\..+/, "").replace("T", "-");
1449
- const candidate = join(backupDir, `data-${ts}.tar.gz`);
1450
- console.log(`[nomad] Backing up raft state → ${candidate}`);
1451
- try {
1452
- execSync(`tar czf "${candidate}" -C "${NOMAD_CONFIG_DIR}" data 2>/dev/null`, { timeout: 120000 });
1453
- backupFile = candidate;
1454
- // Keep only the most recent snapshot
1455
- try {
1456
- const list = execSync(`ls -t "${backupDir}"/data-*.tar.gz 2>/dev/null | tail -n +2 || true`, { encoding: "utf-8" }).trim();
1457
- for (const old of list.split("\n").filter(Boolean)) {
1458
- try {
1459
- unlinkSync(old);
1460
- }
1461
- catch { }
1462
- }
1463
- }
1464
- catch { }
1465
- }
1466
- catch {
1467
- console.warn("[nomad] Backup tar failed — continuing (raft state will still be wiped)");
1468
- }
1469
- }
1470
- // ── Stage 4: wipe raft state + env files (schema incompatible) ─────
1471
- try {
1472
- execFileSync("sudo", ["-n", "rm", "-rf", NOMAD_DATA_DIR], { timeout: 15000, stdio: "pipe" });
1473
- }
1474
- catch {
1475
- try {
1476
- rmSync(NOMAD_DATA_DIR, { recursive: true, force: true });
1477
- }
1478
- catch { }
1479
- }
1480
- try {
1481
- unlinkSync(join(JISHUSHELL_HOME, "nomad.env"));
1482
- }
1483
- catch { }
1484
- try {
1485
- execFileSync("sudo", ["-n", "rm", "-f", "/etc/jishushell/nomad.env"], { timeout: 5000, stdio: "pipe" });
1486
- }
1487
- catch { }
1488
- // ── Stage 5: orphaned gateway containers ───────────────────────────
1489
- // Panel normally has docker group via jishushell.service SupplementaryGroups,
1490
- // but postinstall may run this helper from a shell where the invoking
1491
- // user is not in docker group. Probe first, fall back to sudo docker.
1492
- try {
1493
- let dockerCmd = "docker";
1494
- try {
1495
- execSync("docker ps >/dev/null 2>&1", { timeout: 5000 });
1496
- }
1497
- catch {
1498
- dockerCmd = "sudo -n docker";
1499
- }
1500
- const names = execSync(`${dockerCmd} ps -a --format '{{.Names}}' 2>/dev/null | grep '^gateway-' || true`, { encoding: "utf-8" }).trim();
1501
- if (names) {
1502
- const rows = names.split("\n").filter(Boolean);
1503
- for (const name of rows) {
1504
- try {
1505
- execSync(`${dockerCmd} rm -f "${name}" 2>/dev/null`, { timeout: 10000 });
1506
- }
1507
- catch { }
1508
- }
1509
- console.log(`[nomad] Removed ${rows.length} orphaned gateway container(s)`);
1510
- }
1511
- }
1512
- catch { }
1513
- // ── Stage 6: swap binary into place (atomic via temp name + rename)
1514
- ensureDirHost(BIN_DIR);
1515
- const destTmp = `${NOMAD_BIN}.tmp.${process.pid}`;
1516
- copyFileSync(stagedBin, destTmp);
1517
- chmodSync(destTmp, 0o755);
1518
- renameSync(destTmp, NOMAD_BIN);
1519
- console.log(`[nomad] Migrated to v${NOMAD_VERSION}`);
1520
- if (backupFile)
1521
- console.log(`[nomad] Backup (forensic, not self-recovery): ${backupFile}`);
1522
- console.log("[nomad] JishuShell will re-bootstrap ACL and resubmit jobs on next start.");
1523
- }
1524
- catch (err) {
1525
- if (backupFile) {
1526
- console.error(`[nomad] Migration failed — backup preserved at ${backupFile}`);
1527
- }
1528
- throw err;
1529
- }
1530
- finally {
1531
- try {
1532
- rmSync(stageDir, { recursive: true, force: true });
1533
- }
1534
- catch { }
1535
- }
1536
- }
1537
- export async function installNomad() {
1538
- try {
1539
- if (existsSync(NOMAD_BIN)) {
1540
- // Boundary check 1: is it a regular file?
1541
- try {
1542
- const stat = (await import("fs")).statSync(NOMAD_BIN);
1543
- if (!stat.isFile()) {
1544
- try {
1545
- unlinkSync(NOMAD_BIN);
1546
- }
1547
- catch { }
1548
- }
1549
- }
1550
- catch { }
1551
- if (existsSync(NOMAD_BIN)) {
1552
- // Boundary check 2: is it executable?
1553
- try {
1554
- chmodSync(NOMAD_BIN, 0o755);
1555
- }
1556
- catch { }
1557
- // Boundary check 3: does it actually run?
1558
- let versionLine = "";
1559
- try {
1560
- versionLine = execSync(`"${NOMAD_BIN}" version`, { encoding: "utf-8", timeout: 5000 }).trim().split("\n")[0];
1561
- }
1562
- catch {
1563
- // Binary is corrupt or wrong arch — remove and reinstall
1564
- try {
1565
- unlinkSync(NOMAD_BIN);
1566
- }
1567
- catch { }
1568
- }
1569
- if (versionLine) {
1570
- const match = versionLine.match(/v(\d+\.\d+\.\d+)/);
1571
- const currentVersion = match ? match[1] : "";
1572
- let migrated = false;
1573
- if (currentVersion && isNomadVersionGreater(currentVersion, NOMAD_VERSION)) {
1574
- // Current > target — auto-migrate (nomad 1.11.3 BSL → 1.6.5 MPL).
1575
- // Migration failure is a hard stop: the old state has been
1576
- // partially mutated (or about to be), returning falls through
1577
- // to the reinstall path which would make a bad situation worse.
1578
- try {
1579
- await migrateNomadToTarget(currentVersion);
1580
- }
1581
- catch (migErr) {
1582
- return {
1583
- ok: false,
1584
- message: "Nomad auto-migration failed",
1585
- error: migErr?.message || String(migErr),
1586
- };
1587
- }
1588
- migrated = true;
1589
- versionLine = execSync(`"${NOMAD_BIN}" version`, { encoding: "utf-8", timeout: 5000 }).trim().split("\n")[0];
1590
- }
1591
- // Always (re)write config so the installed nomad.hcl stays up-to-date
1592
- // with the current defaults (e.g. raw_exec plugin, acl, limits).
1593
- writeNomadConfig();
1594
- // Ensure Nomad is started even if already installed
1595
- if (!isPortListening(4646)) {
1596
- try {
1597
- installNomadSystemd();
1598
- }
1599
- catch { }
1600
- if (!isPortListening(4646)) {
1601
- await startNomad();
1602
- }
1603
- }
1604
- return migrated
1605
- ? { ok: true, message: `Nomad migrated to ${versionLine}` }
1606
- : { ok: true, message: `Nomad already installed: ${versionLine}` };
1607
- }
1608
- }
1609
- }
1610
- // Fallback: if NOMAD_BIN still doesn't exist, check for a system-installed Nomad
1611
- // (e.g. installed via apt/dnf) and create a symlink so the systemd service path resolves.
1612
- if (!existsSync(NOMAD_BIN)) {
1613
- try {
1614
- const systemNomad = execSync("which nomad 2>/dev/null", { encoding: "utf-8" }).trim();
1615
- if (systemNomad && existsSync(systemNomad)) {
1616
- ensureDirHost(BIN_DIR);
1617
- symlinkSync(systemNomad, NOMAD_BIN);
1618
- const version = execSync(`${NOMAD_BIN} version`, { encoding: "utf-8", timeout: 5000 }).trim();
1619
- console.log(`[nomad] Linked system nomad ${systemNomad} → ${NOMAD_BIN}`);
1620
- writeNomadConfig();
1621
- return { ok: true, message: `Nomad linked from system: ${version.split("\n")[0]}` };
1622
- }
1623
- }
1624
- catch { /* system nomad not found — proceed to download */ }
1625
- }
1626
- const task = createTask("nomad");
1627
- ensureDirHost(BIN_DIR);
1628
- const url = getNomadDownloadUrl();
1629
- const zipPath = join(BIN_DIR, "nomad.zip");
1630
- emitTask(task, { type: "progress", message: "下载 Nomad...", progress: 0 });
1631
- const result = await spawnWithTask(task, "curl", ["-fL", "--progress-bar", url, "-o", zipPath], {
1632
- timeout: 300000,
1633
- progressParser: curlProgressParser,
1634
- });
1635
- if (!result.ok) {
1636
- emitTask(task, { type: "error", message: "Nomad 下载失败" });
1637
- task.status = "error";
1638
- return { ok: false, message: "Nomad download failed", error: result.output, taskId: task.id };
1639
- }
1640
- emitTask(task, { type: "progress", message: "解压 Nomad...", progress: 80 });
1641
- try {
1642
- execSync("which unzip", { stdio: "ignore" });
1643
- }
1644
- catch {
1645
- emitTask(task, { type: "log", message: "未找到 unzip,尝试安装..." });
1646
- try {
1647
- if (process.platform === "linux") {
1648
- execSync("sudo apt-get update -qq && sudo apt-get install -y -qq unzip", { timeout: 60000 });
1649
- }
1650
- else if (process.platform === "darwin") {
1651
- execSync("brew install unzip", { timeout: 60000 });
1652
- }
1653
- }
1654
- catch (e) {
1655
- emitTask(task, { type: "error", message: "安装 unzip 失败,请手动安装后重试" });
1656
- throw e;
1657
- }
1658
- }
1659
- execFileSync("unzip", ["-o", zipPath, "-d", BIN_DIR], { timeout: 30000 });
1660
- chmodSync(NOMAD_BIN, 0o755);
1661
- try {
1662
- unlinkSync(zipPath);
1663
- }
1664
- catch { }
1665
- const version = execFileSync(NOMAD_BIN, ["version"], { encoding: "utf-8", timeout: 5000 }).trim();
1666
- emitTask(task, { type: "done", message: `Nomad 安装完成: ${version}`, progress: 100 });
1667
- task.status = "done";
1668
- return { ok: true, message: `Nomad installed: ${version}`, taskId: task.id };
1669
- }
1670
- catch (e) {
1671
- return { ok: false, message: "Nomad installation failed", error: e.message };
1672
- }
1673
- }
1674
- // ── Configure & start Nomad ────────────────────────────────────────
1675
- /** Fix ~/.jishushell dirs if they were accidentally created as root (e.g. from an old sudo install). */
1676
- function fixNomadDirOwnership() {
1677
- try {
1678
- const { statSync } = require("fs");
1679
- const stat = statSync(NOMAD_CONFIG_DIR);
1680
- if (stat.uid === 0) {
1681
- // Directory is owned by root — try to repair with sudo -n (non-interactive)
1682
- const currentUser = process.env.USER || process.env.LOGNAME || "";
1683
- if (currentUser) {
1684
- try {
1685
- execFileSync("sudo", ["-n", "chown", "-R", `${currentUser}:${currentUser}`, JISHUSHELL_HOME], { timeout: 10000, stdio: "pipe" });
1686
- }
1687
- catch { /* sudo not available or no NOPASSWD — ignore */ }
1688
- }
1689
- }
1690
- }
1691
- catch { /* stat failed — dir doesn't exist yet, no action needed */ }
1692
- }
1693
- export function buildExpectedNomadConfigContent() {
1694
- const platform = osPlatform();
1695
- const loopbackIface = platform === "darwin" ? "lo0" : "lo";
1696
- const externalIface = detectNomadExternalInterface(loopbackIface);
1697
- const externalHostNetworkBlock = externalIface
1698
- ? `
1699
- host_network "external" {
1700
- interface = "${externalIface}"
1701
- }
1702
- `
1703
- : "";
1704
- // Detect docker0 bridge CIDR so multi-container apps (weknora etc.) can
1705
- // declare `host_network: docker_bridge` on their ports and have Nomad
1706
- // publish them on the docker0 IP — which is what `host.docker.internal`
1707
- // resolves to inside peer containers. Hardcoding 172.17.0.0/16 would
1708
- // break setups where docker daemon.json overrides `bip` /
1709
- // `default-address-pools`. Fall back to the Docker default if detection
1710
- // fails (e.g. docker not yet installed at panel install time; doctor
1711
- // will regenerate later).
1712
- const dockerBridgeCidr = detectDockerBridgeCidr() || "172.17.0.0/16";
1713
- const dockerBridgeHostNetworkBlock = `
1714
- host_network "docker_bridge" {
1715
- cidr = "${dockerBridgeCidr}"
1716
- }
1717
- `;
1718
- // Apple Silicon CPU fingerprint workaround. Nomad 1.6.x on darwin/arm64
1719
- // reads `hw.tbfrequency` (timebase, e.g. 24 MHz on M-series) as the CPU
1720
- // clock, so a 14-core M4 Max reports as 48 MHz total compute and every
1721
- // job that asks for CPU>48 gets rejected with "Resources exhausted on
1722
- // dimension cpu". Override with a conservative estimate (cores × 2500
1723
- // MHz) — M-series base clock is at least 2.5 GHz, so this never
1724
- // overcommits relative to actual silicon. Intel Macs fingerprint
1725
- // correctly and don't need the override.
1726
- const cpuTotalComputeBlock = platform === "darwin" && osArch() === "arm64"
1727
- ? ` cpu_total_compute = ${osCpus().length * 2500} # Apple Silicon workaround: Nomad mis-fingerprints CPU freq via tbfrequency\n`
1728
- : "";
1729
- // macOS docker driver endpoint. macOS users run Docker via Colima
1730
- // (managed by this panel under `~/.jishushell/colima/jishushell/`) or
1731
- // Docker Desktop (`~/.docker/run/docker.sock`); neither exposes
1732
- // `/var/run/docker.sock` out of the box. Resolve the correct host once
1733
- // and bake it into the HCL so Nomad doesn't fall back to the default
1734
- // `unix:///var/run/docker.sock` and fail. Linux keeps the default
1735
- // (empty endpoint = Docker's standard /var/run/docker.sock).
1736
- const dockerHost = platform === "darwin"
1737
- ? resolveDockerHost({ jishuHome: JISHUSHELL_HOME, colimaProfile: COLIMA_PROFILE })
1738
- : undefined;
1739
- const dockerEndpointLine = dockerHost ? `\n endpoint = "${dockerHost}"` : "";
1740
- const config = `
1741
- data_dir = "${NOMAD_DATA_DIR}"
1742
-
1743
- bind_addr = "127.0.0.1"
1744
-
1745
- leave_on_terminate = false
1746
-
1747
- advertise {
1748
- http = "127.0.0.1"
1749
- rpc = "127.0.0.1"
1750
- serf = "127.0.0.1"
1751
- }
1752
-
1753
- server {
1754
- enabled = true
1755
- bootstrap_expect = 1
1756
- }
1757
-
1758
- client {
1759
- ${cpuTotalComputeBlock} enabled = true
1760
- servers = ["127.0.0.1:4647"]
1761
- network_interface = "${loopbackIface}"
1762
- alloc_dir = "${NOMAD_ALLOC_DIR}"
1763
- ${externalHostNetworkBlock}${dockerBridgeHostNetworkBlock}
1764
-
1765
- # drain_on_shutdown intentionally omitted: on single-node Pi there is
1766
- # nowhere to drain workloads to, and draining on every systemctl restart
1767
- # would kill every running OpenClaw instance. Without this block Nomad
1768
- # leaves allocations running across client restarts — the docker driver
1769
- # re-attaches to the existing containers on startup.
1770
- }
1771
-
1772
- plugin "docker" {
1773
- config {${dockerEndpointLine}
1774
- gc {
1775
- image = false
1776
- }
1777
- volumes {
1778
- enabled = true
1779
- }
1780
- }
1781
- }
1782
-
1783
- plugin "raw_exec" {
1784
- config {
1785
- enabled = true
1786
- }
1787
- }
1788
-
1789
- acl {
1790
- enabled = true
1791
- }
1792
-
1793
- limits {
1794
- http_max_conns_per_client = 0
1795
- }
1796
- `;
1797
- return config;
1798
- }
1799
- function writeNomadConfig() {
1800
- fixNomadDirOwnership();
1801
- ensureDirHost(NOMAD_CONFIG_DIR);
1802
- ensureDirContainer(NOMAD_DATA_DIR);
1803
- ensureDirContainer(NOMAD_ALLOC_DIR);
1804
- writeConfigFile(join(NOMAD_CONFIG_DIR, "nomad.hcl"), buildExpectedNomadConfigContent());
1805
- }
1806
- function detectDockerBridgeCidr() {
1807
- // `docker network inspect bridge` returns the CIDR for docker0. The exact
1808
- // value depends on /etc/docker/daemon.json `bip` / `default-address-pools`
1809
- // — Docker's default is 172.17.0.0/16 but isn't guaranteed. We need the
1810
- // real value because Nomad uses `host_network "docker_bridge" { cidr = …}`
1811
- // to pick which interface to publish a port on for specs that declare
1812
- // `host_network: docker_bridge`. Wrong CIDR → port silently published on
1813
- // wrong interface → cross-task host.docker.internal calls get refused.
1814
- try {
1815
- const raw = execFileSync("docker", ["network", "inspect", "bridge", "--format", "{{(index .IPAM.Config 0).Subnet}}"], { encoding: "utf8", timeout: 3000, stdio: ["pipe", "pipe", "pipe"] }).trim();
1816
- return /^\d{1,3}(\.\d{1,3}){3}\/\d{1,2}$/.test(raw) ? raw : "";
1817
- }
1818
- catch {
1819
- return "";
1820
- }
1821
- }
1822
- function detectNomadExternalInterface(loopbackIface) {
1823
- try {
1824
- if (osPlatform() === "darwin") {
1825
- const route = execFileSync("route", ["-n", "get", "default"], {
1826
- encoding: "utf8",
1827
- timeout: 3000,
1828
- });
1829
- const match = route.match(/interface:\s*(\S+)/);
1830
- const iface = match?.[1]?.trim() ?? "";
1831
- return iface && iface !== loopbackIface ? iface : "";
1832
- }
1833
- const route = execFileSync("ip", ["route", "show", "default"], {
1834
- encoding: "utf8",
1835
- timeout: 3000,
1836
- });
1837
- const match = route.match(/\bdev\s+(\S+)/);
1838
- const iface = match?.[1]?.trim() ?? "";
1839
- return iface && iface !== loopbackIface ? iface : "";
1840
- }
1841
- catch {
1842
- return "";
1843
- }
1844
- }
1845
- export function loadNomadToken() {
1846
- if (process.env.NOMAD_TOKEN)
1847
- return;
1848
- const candidates = [
1849
- join(JISHUSHELL_HOME, "nomad.env"),
1850
- "/etc/jishushell/nomad.env",
1851
- ];
1852
- for (const envFile of candidates) {
1853
- if (!existsSync(envFile))
1854
- continue;
1855
- try {
1856
- const match = readFileSync(envFile, "utf-8").match(/^NOMAD_TOKEN=(.+)$/m);
1857
- if (match) {
1858
- process.env.NOMAD_TOKEN = match[1].trim();
1859
- return;
1860
- }
1861
- }
1862
- catch {
1863
- // no read permission, try next candidate
1864
- }
1865
- }
1866
- const legacy = getCoreConfig().nomad_token;
1867
- if (legacy)
1868
- process.env.NOMAD_TOKEN = legacy;
1869
- }
1870
- /** Verify the current NOMAD_TOKEN is accepted by the Nomad API. Returns false if it is missing or rejected (HTTP 403/401). */
1871
- async function isNomadTokenValid() {
1872
- const token = process.env.NOMAD_TOKEN || getCoreConfig().nomad_token;
1873
- if (!token)
1874
- return false;
1875
- try {
1876
- const resp = await fetch("http://127.0.0.1:4646/v1/acl/token/self", {
1877
- headers: { "X-Nomad-Token": token },
1878
- signal: AbortSignal.timeout(5000),
1879
- });
1880
- return resp.status === 200;
1881
- }
1882
- catch {
1883
- return false;
1884
- }
1885
- }
1886
- function nomadApiHeaders(extra = {}) {
1887
- const token = process.env.NOMAD_TOKEN || getCoreConfig().nomad_token;
1888
- return token ? { "X-Nomad-Token": token, ...extra } : extra;
1889
- }
1890
- export async function ensureNomadMemoryOversubscriptionEnabled() {
1891
- try {
1892
- const resp = await fetch("http://127.0.0.1:4646/v1/operator/scheduler/configuration", {
1893
- headers: nomadApiHeaders(),
1894
- signal: AbortSignal.timeout(5000),
1895
- });
1896
- if (resp.status !== 200)
1897
- return;
1898
- const payload = await resp.json();
1899
- const scheduler = payload?.SchedulerConfig;
1900
- if (!scheduler || typeof scheduler !== "object")
1901
- return;
1902
- if (scheduler.MemoryOversubscriptionEnabled === true)
1903
- return;
1904
- const putResp = await fetch("http://127.0.0.1:4646/v1/operator/scheduler/configuration", {
1905
- method: "PUT",
1906
- headers: nomadApiHeaders({ "Content-Type": "application/json" }),
1907
- body: JSON.stringify({ ...scheduler, MemoryOversubscriptionEnabled: true }),
1908
- signal: AbortSignal.timeout(5000),
1909
- });
1910
- if (putResp.status === 200) {
1911
- console.log("[nomad] Enabled memory oversubscription so MemoryMaxMB becomes an actual task limit.");
1912
- }
1913
- else {
1914
- console.warn(`[nomad] Failed to enable memory oversubscription: HTTP ${putResp.status}`);
1915
- }
1916
- }
1917
- catch (e) {
1918
- console.warn("[nomad] Failed to enable memory oversubscription:", e.message);
1919
- }
1920
- }
1921
- /** Shared post-start sequence: load token, bootstrap ACL, enable oversubscription, enable node. */
1922
- async function finalizeNomadStartup() {
1923
- loadNomadToken();
1924
- await bootstrapNomadACL();
1925
- await ensureNomadMemoryOversubscriptionEnabled();
1926
- enableNomadNodeEligibility();
1927
- }
1928
- async function bootstrapNomadACL() {
1929
- // If a token is already loaded, verify it's still valid before trusting it.
1930
- if (process.env.NOMAD_TOKEN || getCoreConfig().nomad_token) {
1931
- if (await isNomadTokenValid())
1932
- return;
1933
- console.log("[nomad] Stored ACL token is invalid — re-bootstrapping...");
1934
- delete process.env.NOMAD_TOKEN;
1935
- }
1936
- const nomadPath = existsSync(NOMAD_BIN) ? NOMAD_BIN : "nomad";
1937
- const doBootstrap = async () => {
1938
- try {
1939
- const raw = execFileSync(nomadPath, ["acl", "bootstrap", "-json"], {
1940
- timeout: 10000,
1941
- encoding: "utf-8",
1942
- env: { ...process.env, NOMAD_ADDR: "http://127.0.0.1:4646" },
1943
- });
1944
- return JSON.parse(raw).SecretID ?? null;
1945
- }
1946
- catch (e) {
1947
- // Return the raw stderr/stdout so caller can inspect it
1948
- throw e;
1949
- }
1950
- };
1951
- const saveToken = (token) => {
1952
- const envFile = join(JISHUSHELL_HOME, "nomad.env");
1953
- const envContent = `NOMAD_TOKEN=${token}\n`;
1954
- writeSecretFile(envFile, envContent);
1955
- try {
1956
- execFileSync("sudo", ["-n", "mkdir", "-p", "/etc/jishushell"], { timeout: 5000, stdio: "pipe" });
1957
- sudoCopySystemFile(envContent, "/etc/jishushell/nomad.env", "600");
1958
- }
1959
- catch (copyErr) {
1960
- console.warn("[nomad] Could not sync token to /etc/jishushell/nomad.env:", copyErr.message);
1961
- }
1962
- process.env.NOMAD_TOKEN = token;
1963
- console.log("[nomad] ACL token saved to", envFile);
1964
- };
1965
- try {
1966
- const token = await doBootstrap();
1967
- if (token)
1968
- saveToken(token);
1969
- return;
1970
- }
1971
- catch (e) {
1972
- const msg = (e.stderr || e.stdout || e.message || "").toString();
1973
- // "ACL bootstrap already done" — extract reset index and perform a reset
1974
- const resetMatch = msg.match(/reset index[:\s]+(\d+)/i);
1975
- if (!resetMatch) {
1976
- if (!msg.includes("bootstrap"))
1977
- console.warn("[nomad] ACL bootstrap warning:", msg);
1978
- return;
1979
- }
1980
- const resetIndex = resetMatch[1];
1981
- console.log(`[nomad] Bootstrap already done (reset index: ${resetIndex}). Performing ACL bootstrap reset...`);
1982
- // Write the reset trigger file (Nomad reads this on startup to allow re-bootstrap).
1983
- // NOMAD_DATA_DIR/server is owned by root because nomad.service runs as User=root
1984
- // (docker driver on 1.6.5 requires euid==0). The panel runs as a non-root user, so
1985
- // plain writeConfigFile would fail with EACCES — route through `sudo tee` instead.
1986
- const resetFile = join(NOMAD_DATA_DIR, "server", "acl-bootstrap-reset");
1987
- try {
1988
- writeConfigFile(resetFile, resetIndex);
1989
- }
1990
- catch (writeErr) {
1991
- try {
1992
- execFileSync("sudo", ["-n", "mkdir", "-p", dirname(resetFile)], { timeout: 5000, stdio: "pipe" });
1993
- execFileSync("sudo", ["-n", "tee", resetFile], {
1994
- timeout: 5000,
1995
- input: resetIndex,
1996
- stdio: ["pipe", "ignore", "pipe"],
1997
- });
1998
- }
1999
- catch (sudoErr) {
2000
- console.warn("[nomad] Could not write acl-bootstrap-reset file:", sudoErr.message || writeErr.message);
2001
- return;
2002
- }
2003
- }
2004
- // Restart Nomad so it picks up the reset file
2005
- try {
2006
- execFileSync("sudo", ["-n", "systemctl", "restart", "nomad"], { timeout: 15000, stdio: "pipe" });
2007
- }
2008
- catch {
2009
- // No passwordless sudo — try pkill/re-spawn path (best effort)
2010
- try {
2011
- execFileSync("sudo", ["-n", "pkill", "-TERM", "-f", "nomad agent"], { stdio: "pipe" });
2012
- }
2013
- catch {
2014
- try {
2015
- execFileSync("pkill", ["-TERM", "-f", "nomad agent"], { stdio: "pipe" });
2016
- }
2017
- catch { }
2018
- }
2019
- }
2020
- // Wait for Nomad to come back
2021
- for (let i = 0; i < 20; i++) {
2022
- await new Promise(r => setTimeout(r, 1000));
2023
- if (isPortListening(4646))
2024
- break;
2025
- }
2026
- // Bootstrap again — reset file is consumed by Nomad on first start after restart
2027
- try {
2028
- const token = await doBootstrap();
2029
- if (token)
2030
- saveToken(token);
2031
- }
2032
- catch (e2) {
2033
- console.warn("[nomad] ACL bootstrap after reset failed:", (e2.stderr || e2.message || "").toString().split("\n")[0]);
2034
- }
2035
- }
2036
- }
2037
- function enableNomadNodeEligibility() {
2038
- const nomadPath = existsSync(NOMAD_BIN) ? NOMAD_BIN : "nomad";
2039
- try {
2040
- const raw = execSync(`${nomadPath} node status -self -json`, {
2041
- timeout: 5000,
2042
- encoding: "utf-8",
2043
- env: { ...process.env, NOMAD_ADDR: "http://127.0.0.1:4646" },
2044
- });
2045
- const nodeId = JSON.parse(raw).ID;
2046
- if (!nodeId)
2047
- return;
2048
- execSync(`${nomadPath} node eligibility -enable ${nodeId}`, {
2049
- timeout: 5000,
2050
- env: { ...process.env, NOMAD_ADDR: "http://127.0.0.1:4646" },
2051
- });
2052
- }
2053
- catch {
2054
- }
2055
- }
2056
- export async function startNomad() {
2057
- try {
2058
- const configPath = join(NOMAD_CONFIG_DIR, "nomad.hcl");
2059
- const readConfig = () => {
2060
- try {
2061
- return existsSync(configPath) ? readFileSync(configPath, "utf-8") : "";
2062
- }
2063
- catch {
2064
- return "";
2065
- }
2066
- };
2067
- const oldConfig = readConfig();
2068
- writeNomadConfig();
2069
- const newConfig = readConfig();
2070
- const drifted = oldConfig.length > 0 && newConfig.length > 0 && oldConfig !== newConfig;
2071
- if (isPortListening(4646)) {
2072
- // Nomad already running, but if the rewritten config differs (typically
2073
- // because detectNomadExternalInterface() now resolves to a different
2074
- // interface — e.g. older install missing the host_network block, or
2075
- // network interface renamed across reboots), reload nomad so allocations
2076
- // bind to the right host network on next placement.
2077
- if (drifted) {
2078
- try {
2079
- execFileSync("sudo", ["-n", "systemctl", "restart", "nomad"], { stdio: "pipe", timeout: 15000 });
2080
- for (let i = 0; i < 15; i++) {
2081
- await new Promise(r => setTimeout(r, 1000));
2082
- if (isPortListening(4646)) {
2083
- await finalizeNomadStartup();
2084
- return { ok: true, message: "Nomad restarted (config reconciled)" };
2085
- }
2086
- }
2087
- return { ok: false, message: "Nomad restart timed out after config reconcile", error: "Port 4646 not listening after 15s" };
2088
- }
2089
- catch (e) {
2090
- console.warn(`[nomad] config drift detected but restart failed (${e.message}); existing nomad continues with stale config`);
2091
- }
2092
- }
2093
- await finalizeNomadStartup();
2094
- return { ok: true, message: "Nomad already running" };
2095
- }
2096
- // If systemd manages nomad, delegate to systemctl to avoid spawning a competing process
2097
- const isSystemdManaged = (() => {
2098
- try {
2099
- const result = execFileSync("systemctl", ["is-enabled", "nomad"], { stdio: "pipe", timeout: 3000 });
2100
- return result.toString().trim() === "enabled";
2101
- }
2102
- catch {
2103
- return false;
2104
- }
2105
- })();
2106
- if (isSystemdManaged) {
2107
- try {
2108
- execFileSync("sudo", ["-n", "systemctl", "start", "nomad"], { stdio: "pipe", timeout: 10000 });
2109
- }
2110
- catch {
2111
- // sudo -n failed (no passwordless sudo); service may start on its own
2112
- }
2113
- for (let i = 0; i < 15; i++) {
2114
- await new Promise(r => setTimeout(r, 1000));
2115
- if (isPortListening(4646)) {
2116
- await finalizeNomadStartup();
2117
- return { ok: true, message: "Nomad started via systemd" };
2118
- }
2119
- }
2120
- return { ok: false, message: "Nomad start timed out", error: "Port 4646 not listening after 15s" };
2121
- }
2122
- if (process.platform === "darwin") {
2123
- const launchdPlist = join(process.env.HOME || dirname(JISHUSHELL_HOME), "Library/LaunchAgents/com.jishushell.nomad.plist");
2124
- if (existsSync(launchdPlist)) {
2125
- for (let i = 0; i < 30; i++) {
2126
- await new Promise(r => setTimeout(r, 1000));
2127
- if (isPortListening(4646)) {
2128
- await finalizeNomadStartup();
2129
- return { ok: true, message: "Nomad started" };
2130
- }
2131
- }
2132
- return { ok: false, message: "Nomad start timed out", error: "Port 4646 not listening after 30s" };
2133
- }
2134
- }
2135
- const nomadPath = existsSync(NOMAD_BIN) ? NOMAD_BIN : "nomad";
2136
- try {
2137
- execFileSync(nomadPath, ["version"], { timeout: 5000, stdio: "pipe" });
2138
- }
2139
- catch {
2140
- return { ok: false, message: "Nomad not installed", error: "Install Nomad first" };
2141
- }
2142
- const logPath = join(NOMAD_CONFIG_DIR, "nomad.log");
2143
- // Use spawn with detached to avoid execSync shell injection and ensure proper daemonization
2144
- try {
2145
- const { openSync, closeSync } = await import("fs");
2146
- const logFd = openSync(logPath, "a");
2147
- // Run as current (non-root) user — Nomad only binds to 127.0.0.1:4646/4647/4648
2148
- // (non-privileged ports) and all data dirs live under ~/.jishushell/, so sudo is not needed.
2149
- const cmd = nomadPath;
2150
- const args = ["agent", `-config=${configPath}`];
2151
- const child = nodeSpawn(cmd, args, {
2152
- detached: true,
2153
- stdio: ["ignore", logFd, logFd],
2154
- });
2155
- child.unref();
2156
- closeSync(logFd);
2157
- }
2158
- catch (e) {
2159
- return { ok: false, message: "Failed to start Nomad", error: `launch failed: ${e.message}. Check sudo/permissions.` };
2160
- }
2161
- for (let i = 0; i < 15; i++) {
2162
- await new Promise(r => setTimeout(r, 1000));
2163
- if (isPortListening(4646)) {
2164
- await finalizeNomadStartup();
2165
- return { ok: true, message: "Nomad started" };
2166
- }
2167
- }
2168
- return { ok: false, message: "Nomad start timed out", error: "Port 4646 not listening after 15s" };
2169
- }
2170
- catch (e) {
2171
- return { ok: false, message: "Failed to start Nomad", error: e.message };
2172
- }
2173
- }
2174
- export async function stopNomad() {
2175
- try {
2176
- if (!isPortListening(4646))
2177
- return { ok: true, message: "Nomad not running" };
2178
- // SIGTERM: graceful shutdown — Nomad flushes state and detaches from
2179
- // running allocs without killing them (drain_on_shutdown is deliberately
2180
- // not configured, so the docker containers keep running and will be
2181
- // re-attached when Nomad comes back).
2182
- // Use killNomadByProcName (pgrep -x) to avoid pkill -f self-matching.
2183
- killNomadByProcName();
2184
- // Wait up to 10s for the process to exit. No drain means shutdown is
2185
- // near-instant — most of this budget is slack for slow disks on Pi.
2186
- for (let i = 0; i < 10; i++) {
2187
- await new Promise(r => setTimeout(r, 1000));
2188
- if (!isPortListening(4646))
2189
- return { ok: true, message: "Nomad stopped" };
2190
- }
2191
- return { ok: true, message: "Nomad stop requested" };
2192
- }
2193
- catch (e) {
2194
- return { ok: false, message: "Failed to stop Nomad", error: e.message };
2195
- }
2196
- }
2197
- // ── Install Nomad as systemd service ───────────────────────────────
2198
- export function installNomadSystemd() {
2199
- try {
2200
- const nomadPath = resolveNomadExecutable();
2201
- const configPath = join(NOMAD_CONFIG_DIR, "nomad.hcl");
2202
- writeNomadConfig();
2203
- if (process.platform === "darwin") {
2204
- // macOS is Apple Silicon only — fail fast (mirrors the bash uname guard).
2205
- const guard = appleSiliconGuard();
2206
- if (!guard.ok)
2207
- return { ok: false, message: guard.message };
2208
- const laDir = join(process.env.HOME || dirname(JISHUSHELL_HOME), "Library/LaunchAgents");
2209
- // Always use JishuShell's private Colima socket — hardcoded, not
2210
- // runtime-detected. Colima may not be running yet when the plist is
2211
- // written; runtime fallback would pick the wrong socket (Docker
2212
- // Desktop or /var/run/docker.sock). Mirrors the bash _COLIMA_SOCKET use.
2213
- const colimaSocket = managedColimaSocketPath(JISHUSHELL_HOME, COLIMA_PROFILE);
2214
- const colimaDockerHost = managedColimaDockerHost(JISHUSHELL_HOME, COLIMA_PROFILE);
2215
- // ── 1. Colima self-retrying launchd agent ───────────────────────
2216
- // colima binary: prefer PATH, fall back to both Homebrew prefixes
2217
- // (mirrors the bash COLIMA_BIN resolution).
2218
- const colimaBin = resolveColimaExecutable();
2219
- const colimaWrapperPath = join(BIN_DIR, "colima-launchd-wrapper.sh");
2220
- writeExecutableFile(colimaWrapperPath, buildColimaWrapperScript({
2221
- colimaHome: _COLIMA_DIR,
2222
- profile: COLIMA_PROFILE,
2223
- socket: colimaSocket,
2224
- colimaBin,
2225
- }));
2226
- const colimaPlistPath = join(laDir, "com.jishushell.colima.plist");
2227
- writeConfigFile(colimaPlistPath, buildColimaPlist({
2228
- wrapperPath: colimaWrapperPath,
2229
- colimaHome: _COLIMA_DIR,
2230
- logPath: join(_COLIMA_DIR, "colima-launchd.log"),
2231
- }));
2232
- try {
2233
- execSync(`launchctl unload "${colimaPlistPath}" 2>/dev/null`);
2234
- }
2235
- catch { }
2236
- try {
2237
- execSync(`launchctl load -w "${colimaPlistPath}"`, { timeout: 15000 });
2238
- }
2239
- catch { }
2240
- // ── 2. Nomad gated behind a docker-readiness wrapper ────────────
2241
- const logPath = join(NOMAD_CONFIG_DIR, "nomad.log");
2242
- const nomadWrapperPath = join(BIN_DIR, "nomad-launchd-wrapper.sh");
2243
- writeExecutableFile(nomadWrapperPath, buildNomadWaitWrapper({
2244
- dockerHost: colimaDockerHost,
2245
- nomadBin: nomadPath,
2246
- configPath,
2247
- }));
2248
- const plistContent = buildNomadPlist({
2249
- wrapperPath: nomadWrapperPath,
2250
- dockerHost: colimaDockerHost,
2251
- logPath,
2252
- });
2253
- const plistPath = join(laDir, "com.jishushell.nomad.plist");
2254
- writeConfigFile(plistPath, plistContent);
2255
- try {
2256
- execSync(`launchctl unload "${plistPath}" 2>/dev/null`);
2257
- }
2258
- catch { }
2259
- execSync(`launchctl load -w "${plistPath}"`, { timeout: 15000 });
2260
- return { ok: true, message: "Nomad launchd agent installed and started (Colima gated)" };
2261
- }
2262
- // Nomad 1.6.5's docker driver fingerprint requires euid==0 — PR #18197 lifted
2263
- // that restriction only in 1.7+, and we intentionally stay on the 1.6 MPL line.
2264
- // The core server stays as the installing user via a separate jishushell.service unit;
2265
- // it talks to this agent over HTTP, so no files under ~/.jishushell/nomad/data/
2266
- // are read directly by the core process.
2267
- const serviceContent = buildNomadSystemdUnit({ nomadPath, configPath });
2268
- const servicePath = SYSTEMD_NOMAD_SERVICE_PATH;
2269
- execFileSync("sudo", ["mkdir", "-p", "/etc/jishushell"], { timeout: 5000 });
2270
- sudoCopySystemFile(serviceContent, servicePath, "644");
2271
- execFileSync("sudo", ["systemctl", "daemon-reload"], { timeout: 5000 });
2272
- execFileSync("sudo", ["systemctl", "enable", "--now", "nomad"], { timeout: 15000 });
2273
- // Also restart if already running so it picks up the new User= directive
2274
- try {
2275
- execFileSync("sudo", ["systemctl", "restart", "nomad"], { timeout: 15000 });
2276
- }
2277
- catch { }
2278
- return { ok: true, message: "Nomad systemd service installed and started" };
2279
- }
2280
- catch (e) {
2281
- return { ok: false, message: "Failed to install Nomad systemd service", error: e.message };
2282
- }
2283
- }
2284
- // ── Install JishuShell as systemd service ─────────────────────────
2285
- export function installJishushellSystemd(port, startNow = false) {
2286
- try {
2287
- const resolvedPort = port || _serverPort;
2288
- persistCoreServicePort(resolvedPort);
2289
- const serviceUser = process.platform === "darwin" ? undefined : resolveServiceUser();
2290
- // Use the node binary that is currently running this process — avoids
2291
- // "which node" failing when PATH doesn't include nvm's bin dir.
2292
- const nodeBin = process.execPath;
2293
- const cliBin = resolveCoreCliBin();
2294
- // The real owner home: prefer JISHUSHELL_HOME's parent so we don't rely on $HOME.
2295
- const realHome = resolveRealHome();
2296
- const coreStartWrapperPath = join(BIN_DIR, "jishushell-core-start");
2297
- const coreCliWrapperPath = join(BIN_DIR, "jishushell");
2298
- removeSymlinkIfPresent(coreCliWrapperPath);
2299
- writeManagedExecutableFile(coreStartWrapperPath, buildCoreStartWrapperContent({
2300
- nodeBin,
2301
- cliBin,
2302
- realHome,
2303
- port: resolvedPort,
2304
- }), serviceUser);
2305
- writeManagedExecutableFile(coreCliWrapperPath, buildCoreCliWrapperContent({
2306
- nodeBin,
2307
- cliBin,
2308
- realHome,
2309
- port: resolvedPort,
2310
- }), serviceUser);
2311
- if (process.platform === "darwin") {
2312
- // macOS is Apple Silicon only — fail fast (mirrors the bash uname guard).
2313
- const guard = appleSiliconGuard();
2314
- if (!guard.ok)
2315
- return { ok: false, message: guard.message };
2316
- const logPath = join(JISHUSHELL_HOME, "jishushell-core.log");
2317
- // 60s docker-readiness gate before core starts; on timeout it starts anyway.
2318
- const gateWrapperPath = join(BIN_DIR, "core-launchd-wrapper.sh");
2319
- writeExecutableFile(gateWrapperPath, buildCoreGateWrapper({
2320
- socket: managedColimaSocketPath(JISHUSHELL_HOME, COLIMA_PROFILE),
2321
- coreStartWrapper: coreStartWrapperPath,
2322
- }));
2323
- const plistContent = buildCorePlist({
2324
- gateWrapperPath,
2325
- logPath,
2326
- });
2327
- // Symmetric with installNomadSystemd()'s laDir (realHome === dirname(JISHUSHELL_HOME),
2328
- // so process.env.HOME || dirname(JISHUSHELL_HOME) is provably the same path).
2329
- const laDir = resolveLaunchAgentsDir(realHome);
2330
- const plistPath = join(laDir, "com.jishushell.core.plist");
2331
- writeConfigFile(plistPath, plistContent);
2332
- if (startNow || !isPortListening(resolvedPort)) {
2333
- try {
2334
- execSync(`launchctl unload "${plistPath}" 2>/dev/null`);
2335
- }
2336
- catch { }
2337
- execSync(`launchctl load -w "${plistPath}"`, { timeout: 15000 });
2338
- if (!waitForListeningPort(resolvedPort, 30)) {
2339
- return {
2340
- ok: false,
2341
- message: "JishuShell core launchd agent installed, but the core port is not ready yet",
2342
- };
2343
- }
2344
- return { ok: true, message: "JishuShell core launchd agent installed and started (port " + resolvedPort + ")" };
2345
- }
2346
- return { ok: true, message: "JishuShell core launchd agent installed and enabled (port " + resolvedPort + ")" };
2347
- }
2348
- const currentUser = serviceUser ?? resolveServiceUser();
2349
- const serviceContent = buildJishushellCoreSystemdUnit({
2350
- currentUser,
2351
- realHome,
2352
- coreStartWrapperPath,
2353
- });
2354
- execFileSync("sudo", ["mkdir", "-p", "/etc/jishushell"], { timeout: 5000 });
2355
- sudoCopySystemFile(serviceContent, SYSTEMD_CORE_SERVICE_PATH, "644");
2356
- execFileSync("sudo", ["systemctl", "daemon-reload"], { timeout: 5000 });
2357
- execFileSync("sudo", ["systemctl", "enable", "jishushell"], { timeout: 15000, stdio: "pipe" });
2358
- if (!startNow) {
2359
- return { ok: true, message: "JishuShell core systemd service installed and enabled (port " + resolvedPort + ")" };
2360
- }
2361
- execFileSync("sudo", ["systemctl", "restart", "jishushell"], { timeout: 15000 });
2362
- if (!waitForListeningPort(resolvedPort, 30)) {
2363
- return {
2364
- ok: false,
2365
- message: "JishuShell core systemd service installed, but the core port is not ready yet",
2366
- };
2367
- }
2368
- return { ok: true, message: "JishuShell core systemd service installed and started (port " + resolvedPort + ")" };
2369
- }
2370
- catch (e) {
2371
- return { ok: false, message: "Failed to install JishuShell systemd service", error: e.message };
2372
- }
2373
- }
2374
- export function installJishushellPanelSystemd(corePort, panelPort = DEFAULT_PANEL_PORT, startNow = true) {
2375
- try {
2376
- const resolvedCorePort = corePort || _serverPort;
2377
- const serviceUser = process.platform === "darwin" ? undefined : resolveServiceUser();
2378
- const nodeBin = process.execPath;
2379
- const panelBin = resolveBundledPanelServerBin();
2380
- const realHome = resolveRealHome();
2381
- const panelStartWrapperPath = join(BIN_DIR, "jishushell-panel-start");
2382
- writeManagedExecutableFile(panelStartWrapperPath, buildPanelStartWrapperContent({
2383
- nodeBin,
2384
- panelBin,
2385
- realHome,
2386
- corePort: resolvedCorePort,
2387
- panelPort,
2388
- }), serviceUser);
2389
- if (process.platform === "darwin") {
2390
- const guard = appleSiliconGuard();
2391
- if (!guard.ok)
2392
- return { ok: false, message: guard.message };
2393
- const laDir = resolveLaunchAgentsDir(realHome);
2394
- const plistPath = join(laDir, "com.jishushell.panel.plist");
2395
- writeConfigFile(plistPath, buildPanelPlist({
2396
- panelWrapperPath: panelStartWrapperPath,
2397
- logPath: join(JISHUSHELL_HOME, "jishushell-panel.log"),
2398
- home: realHome,
2399
- jishuHome: JISHUSHELL_HOME,
2400
- corePort: resolvedCorePort,
2401
- panelPort,
2402
- }));
2403
- if (!waitForListeningPort(resolvedCorePort, 30)) {
2404
- return {
2405
- ok: false,
2406
- message: "JishuShell Panel launchd agent was written but not started because the core port is not ready",
2407
- };
2408
- }
2409
- try {
2410
- execSync(`launchctl unload "${plistPath}" 2>/dev/null`);
2411
- }
2412
- catch { }
2413
- execSync(`launchctl load -w "${plistPath}"`, { timeout: 15000 });
2414
- if (!waitForListeningPort(panelPort, 15)) {
2415
- return {
2416
- ok: false,
2417
- message: "JishuShell Panel launchd agent started, but the panel port is not ready yet",
2418
- };
2419
- }
2420
- return { ok: true, message: "JishuShell Panel launchd agent installed and started (port " + panelPort + ")" };
2421
- }
2422
- const currentUser = serviceUser ?? resolveServiceUser();
2423
- const serviceContent = buildJishushellPanelSystemdUnit({
2424
- currentUser,
2425
- realHome,
2426
- panelStartWrapperPath,
2427
- corePort: resolvedCorePort,
2428
- panelPort,
2429
- });
2430
- execFileSync("sudo", ["mkdir", "-p", "/etc/jishushell"], { timeout: 5000 });
2431
- sudoCopySystemFile(serviceContent, SYSTEMD_PANEL_SERVICE_PATH, "644");
2432
- execFileSync("sudo", ["systemctl", "daemon-reload"], { timeout: 5000 });
2433
- execFileSync("sudo", ["systemctl", "enable", "jishushell-panel"], { timeout: 15000, stdio: "pipe" });
2434
- if (!startNow) {
2435
- return { ok: true, message: "JishuShell Panel systemd service installed and enabled (port " + panelPort + ")" };
2436
- }
2437
- if (!waitForListeningPort(resolvedCorePort, 30)) {
2438
- return {
2439
- ok: false,
2440
- message: "JishuShell Panel systemd service was enabled but not started because the core port is not ready",
2441
- };
2442
- }
2443
- execFileSync("sudo", ["systemctl", "restart", "jishushell-panel"], { timeout: 15000 });
2444
- if (!waitForListeningPort(panelPort, 15)) {
2445
- return {
2446
- ok: false,
2447
- message: "JishuShell Panel systemd service started, but the panel port is not ready yet",
2448
- };
2449
- }
2450
- return { ok: true, message: "JishuShell Panel systemd service installed and started (port " + panelPort + ")" };
2451
- }
2452
- catch (e) {
2453
- return { ok: false, message: "Failed to install JishuShell Panel systemd service", error: e.message };
2454
- }
2455
- }
2456
- // ── Install OpenClaw (async with progress) ─────────────────────────
2457
- /**
2458
- * Install OpenClaw runtime — thin dispatch wrapper.
2459
- *
2460
- * The heavy lifting lives in `OpenClawAdapter.installRuntime()` (§32.2.4).
2461
- * This wrapper is kept only for back-compat with the existing
2462
- * `routes/setup.ts` endpoint and the CLI installer.
2463
- */
2464
- export async function installOpenclaw(version = "latest") {
2465
- const adapter = getAdapter("openclaw");
2466
- if (typeof adapter.installRuntime !== "function") {
2467
- return { ok: false, message: "OpenClawAdapter.installRuntime is not implemented" };
2468
- }
2469
- return adapter.installRuntime({ version });
2470
- }
2471
- // ── Hermes install (§32.1 / §32.3) ─────────────────────────────────
2472
- //
2473
- // Hermes constants (HERMES_DEFAULT_IMAGE, HERMES_RUNTIME_DIR,
2474
- // HERMES_SHIM_FILENAME) and the shim template resolver have moved to
2475
- // `src/config.ts` (§32 Phase 8). setup-manager no longer defines them.
2476
- // The HermesAdapter imports them directly from config.ts.
2477
- /**
2478
- * Capture the immutable digest of a locally-present image so HermesAdapter
2479
- * can pin via digest rather than the mutable tag. Returns undefined if the
2480
- * image has no RepoDigests (e.g. locally-built image) — caller may still
2481
- * proceed using the tag alone.
2482
- */
2483
- export function captureImageDigest(imageRef) {
2484
- try {
2485
- const raw = execFileSync("docker", [
2486
- "image",
2487
- "inspect",
2488
- "--format",
2489
- "{{range .RepoDigests}}{{.}}{{\"\\n\"}}{{end}}",
2490
- imageRef,
2491
- ], { encoding: "utf-8", timeout: 10000, stdio: ["pipe", "pipe", "pipe"] });
2492
- const first = raw.split("\n").map((l) => l.trim()).find(Boolean);
2493
- return first || undefined;
2494
- }
2495
- catch {
2496
- return undefined;
2497
- }
2498
- }
2499
- /**
2500
- * Install Hermes runtime — thin dispatch wrapper.
2501
- *
2502
- * Heavy lifting lives in `HermesAdapter.installRuntime()` (§32.2.4).
2503
- */
2504
- export async function installHermes() {
2505
- const adapter = getAdapter("hermes");
2506
- if (typeof adapter.installRuntime !== "function") {
2507
- return { ok: false, message: "HermesAdapter.installRuntime is not implemented" };
2508
- }
2509
- return adapter.installRuntime();
2510
- }
2511
- /**
2512
- * Non-blocking variant — returns a task id immediately. Implementation
2513
- * dispatches via `HermesAdapter.startInstallRuntime()`.
2514
- */
2515
- export function startInstallHermes() {
2516
- const adapter = getAdapter("hermes");
2517
- if (typeof adapter.startInstallRuntime !== "function") {
2518
- return { ok: false, message: "HermesAdapter.startInstallRuntime is not implemented" };
2519
- }
2520
- return adapter.startInstallRuntime();
2521
- }
2522
- /** Helper for setup status — true when runtime catalog has hermes entry. */
2523
- export function isHermesInstalled() {
2524
- const entry = getRuntimeCatalogEntry("hermes");
2525
- return !!entry && !!entry.defaultImage;
2526
- }
2527
- export function resolveDockerInvocation() {
2528
- try {
2529
- execFileSync("docker", ["info"], { timeout: 5000, stdio: "ignore" });
2530
- return { cmd: "docker", argsPrefix: [] };
2531
- }
2532
- catch { }
2533
- try {
2534
- execFileSync("sudo", ["-n", "docker", "info"], { timeout: 5000, stdio: "ignore" });
2535
- return { cmd: "sudo", argsPrefix: ["-n", "docker"] };
2536
- }
2537
- catch { }
2538
- return { cmd: "docker", argsPrefix: [] };
2539
- }
2540
- function checkDockerImageExists() {
2541
- const tag = resolveDockerImageTag();
2542
- try {
2543
- const invocation = resolveDockerInvocation();
2544
- execFileSync(invocation.cmd, [...invocation.argsPrefix, "image", "inspect", tag], { timeout: 5000, stdio: "ignore" });
2545
- return true;
2546
- }
2547
- catch {
2548
- // Fallback scan: list all local images and try to find any known runtime image.
2549
- // This handles two scenarios:
2550
- // 1. core.json was wiped (e.g. after `jishushell reset`) and the pinned version
2551
- // tag is no longer stored, causing getOpenclawDockerImage() to return the default
2552
- // `:latest` tag which may have been removed locally during the first-run migration.
2553
- // 2. The environment uses a locally built runtime image (e.g. jishushell-hermes:latest)
2554
- // that differs from the registry default.
2555
- // When a candidate is found we restore core.json (self-heal) so the fast path works next time.
2556
- try {
2557
- const invocation = resolveDockerInvocation();
2558
- const out = execFileSync(invocation.cmd, [...invocation.argsPrefix, "images", "--format", "{{.Repository}}:{{.Tag}}"], { encoding: "utf8", timeout: 5000 });
2559
- const lines = out.split("\n").map((l) => l.trim()).filter(Boolean);
2560
- // 1. Same repository as DEFAULT_OPENCLAW_DOCKER_IMAGE (e.g. after pinned-tag migration).
2561
- const defaultImage = DEFAULT_OPENCLAW_DOCKER_IMAGE;
2562
- const repoColonIdx = defaultImage.lastIndexOf(":");
2563
- const repoSlashIdx = defaultImage.lastIndexOf("/");
2564
- if (repoColonIdx > repoSlashIdx) {
2565
- const repo = defaultImage.slice(0, repoColonIdx);
2566
- const repoPrefix = repo + ":";
2567
- const found = lines.find((l) => l.startsWith(repoPrefix) && !l.endsWith(":<none>") && !l.endsWith(":none"));
2568
- if (found) {
2569
- setOpenclawDockerImage(found);
2570
- return true;
2571
- }
2572
- }
2573
- // 2. Backward compat: older locally-built jishushell-openclaw:* image names.
2574
- // These use the same slim base architecture as ghcr.io/x-aijishu/openclaw-runtime:*
2575
- // and are fully compatible. Self-heal core.json so the tag stored there becomes
2576
- // the concrete existing tag, preventing repeated DEFAULT-migration side effects.
2577
- const legacyFound = lines.find((l) => /^jishushell-openclaw:[^\s]+/.test(l) && !l.endsWith(":<none>") && !l.endsWith(":none"));
2578
- if (legacyFound) {
2579
- setOpenclawDockerImage(legacyFound);
2580
- return true;
2581
- }
2582
- }
2583
- catch { }
2584
- return false;
2585
- }
2586
- }
2587
- // The stable tag for the JishuShell base image. Reads core.json — framework-level.
2588
- function resolveDockerImageTag() {
2589
- return getOpenclawDockerImage();
2590
- }
2591
- // ── Docker image build dispatch wrappers ───────────────────────────────
2592
- //
2593
- // All OpenClaw-specific image build logic now lives in
2594
- // `OpenClawAdapter.buildRuntimeImage()` (§32.2.4 physical migration). These
2595
- // exports remain as thin wrappers so `routes/setup.ts` and
2596
- // `install.ts` callers don't need to learn adapter dispatch.
2597
- /** Blocking: pull or build the OpenClaw docker image. */
2598
- export async function buildSlimOpenclawImage(tag) {
2599
- const adapter = getAdapter("openclaw");
2600
- if (typeof adapter.buildRuntimeImage !== "function") {
2601
- return { ok: false, message: "OpenClawAdapter.buildRuntimeImage is not implemented" };
2602
- }
2603
- return adapter.buildRuntimeImage({ tag });
2604
- }
2605
- /** Non-blocking: returns immediately with a task id for SSE polling. */
2606
- export function startBuildSlimOpenclawImage(tag) {
2607
- const adapter = getAdapter("openclaw");
2608
- if (typeof adapter.startBuildRuntimeImage !== "function") {
2609
- return { ok: false, message: "OpenClawAdapter.startBuildRuntimeImage is not implemented" };
2610
- }
2611
- return adapter.startBuildRuntimeImage({ tag });
2612
- }
2613
- /** @deprecated Use buildSlimOpenclawImage instead */
2614
- export async function buildCustomOpenclawImage(tag) {
2615
- return buildSlimOpenclawImage(tag);
2616
- }
2617
- /** @deprecated Use startBuildSlimOpenclawImage instead */
2618
- export function startBuildCustomOpenclawImage(tag) {
2619
- return startBuildSlimOpenclawImage(tag);
2620
- }
2621
- export async function runFullSetup(options = {}) {
2622
- const steps = [];
2623
- let allOk = true;
2624
- const defaults = {
2625
- installNomad: true,
2626
- buildDockerImage: true,
2627
- ...options,
2628
- };
2629
- // Check Docker by daemon accessibility (docker info), not just binary existence
2630
- const dockerReady = canAccessDockerDaemon(10000);
2631
- if (!dockerReady) {
2632
- steps.push({ step: "docker", status: "running", message: "Installing Docker..." });
2633
- const result = await installDocker();
2634
- steps[steps.length - 1].status = result.ok ? "done" : "error";
2635
- steps[steps.length - 1].message = result.message;
2636
- if (!result.ok)
2637
- allOk = false;
2638
- }
2639
- if (defaults.installNomad) {
2640
- steps.push({ step: "nomad", status: "running", message: "Installing Nomad..." });
2641
- const result = await installNomad();
2642
- steps[steps.length - 1].status = result.ok ? "done" : "error";
2643
- steps[steps.length - 1].message = result.message;
2644
- if (!result.ok)
2645
- allOk = false;
2646
- if (result.ok) {
2647
- steps.push({ step: "nomad-systemd", status: "running", message: "Configuring Nomad auto-start..." });
2648
- const sysResult = installNomadSystemd();
2649
- steps[steps.length - 1].status = sysResult.ok ? "done" : "error";
2650
- steps[steps.length - 1].message = sysResult.message;
2651
- if (!sysResult.ok) {
2652
- // Fallback to manual start if systemd fails
2653
- steps.push({ step: "nomad-start", status: "running", message: "Starting Nomad..." });
2654
- const startResult = await startNomad();
2655
- steps[steps.length - 1].status = startResult.ok ? "done" : "error";
2656
- steps[steps.length - 1].message = startResult.message;
2657
- if (!startResult.ok)
2658
- allOk = false;
2659
- }
2660
- }
2661
- }
2662
- // Prepare each registered agent's runtime artefacts (docker image, shim,
2663
- // etc.). This loops over every adapter so onboarding a new agent only
2664
- // requires implementing `buildRuntimeImage` or `installRuntime` in its
2665
- // adapter — runFullSetup picks it up automatically.
2666
- if (defaults.buildDockerImage) {
2667
- // Restart Nomad so it re-detects Docker driver after Docker was installed
2668
- try {
2669
- execSync("sudo systemctl restart nomad 2>/dev/null || true", { timeout: 15000 });
2670
- for (let i = 0; i < 10; i++) {
2671
- await new Promise(r => setTimeout(r, 2000));
2672
- if (isPortListening(4646))
2673
- break;
2674
- }
2675
- }
2676
- catch { }
2677
- for (const adapter of listRegisteredAdapters()) {
2678
- const stepName = `runtime-${adapter.agentType}`;
2679
- // Prefer buildRuntimeImage (pure docker image prep) over
2680
- // installRuntime (legacy host-mode npm install). Adapters that only
2681
- // implement one will use whichever is present; adapters with neither
2682
- // are skipped silently.
2683
- const runner = adapter.buildRuntimeImage
2684
- ? adapter.buildRuntimeImage.bind(adapter)
2685
- : adapter.installRuntime
2686
- ? adapter.installRuntime.bind(adapter)
2687
- : null;
2688
- if (!runner)
2689
- continue;
2690
- const isRequired = !!adapter.required;
2691
- steps.push({
2692
- step: stepName,
2693
- status: "running",
2694
- message: `Preparing ${adapter.agentType} runtime…`,
2695
- });
2696
- try {
2697
- const imgResult = (await runner());
2698
- const okStep = !!imgResult.ok;
2699
- steps[steps.length - 1].status = okStep ? "done" : "error";
2700
- steps[steps.length - 1].message = okStep
2701
- ? imgResult.message
2702
- : isRequired
2703
- ? imgResult.message
2704
- : `${imgResult.message} (optional — panel will continue)`;
2705
- // Required adapter failures abort the overall setup; optional ones
2706
- // are warnings so that upgrade paths don't break when a third-party
2707
- // agent's registry is unreachable.
2708
- if (!okStep && isRequired)
2709
- allOk = false;
2710
- }
2711
- catch (e) {
2712
- const msg = e?.message || "runtime prepare failed";
2713
- steps[steps.length - 1].status = "error";
2714
- steps[steps.length - 1].message = isRequired
2715
- ? msg
2716
- : `${msg} (optional — panel will continue)`;
2717
- if (isRequired)
2718
- allOk = false;
2719
- }
2720
- }
2721
- }
2722
- if (isPortListening(4646)) {
2723
- await finalizeNomadStartup();
2724
- }
2725
- // Only mark setup as complete if all critical steps succeeded
2726
- if (!allOk) {
2727
- return { ok: false, steps };
2728
- }
2729
- const config = getCoreConfig();
2730
- config.service_manager = "nomad";
2731
- config.nomad_driver = "docker";
2732
- saveCoreConfig(config);
2733
- // Install jishushell systemd service (best-effort — does not block setup completion)
2734
- steps.push({ step: "jishushell-systemd", status: "running", message: "Configuring JishuShell auto-start..." });
2735
- const jsResult = installJishushellSystemd();
2736
- steps[steps.length - 1].status = jsResult.ok ? "done" : "error";
2737
- steps[steps.length - 1].message = jsResult.message;
2738
- return { ok: allOk, steps };
2739
- }
2740
- //# sourceMappingURL=setup-manager.js.map