jishushell 0.4.10 → 0.4.24

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 (248) hide show
  1. package/Dockerfile.hermes-slim +193 -0
  2. package/INSTALL-NOTICE +10 -12
  3. package/apps/hermes-container.yaml +35 -0
  4. package/apps/ollama-binary.yaml +200 -0
  5. package/apps/ollama-cpu-container.yaml +37 -0
  6. package/apps/ollama-with-hollama-binary.yaml +195 -0
  7. package/apps/openclaw-binary.yaml +69 -0
  8. package/apps/openclaw-container.yaml +37 -0
  9. package/apps/openclaw-with-ollama-container.yaml +42 -0
  10. package/apps/openclaw-with-searxng-container.yaml +136 -0
  11. package/apps/openwebui-container.yaml +53 -0
  12. package/apps/playwright-container.yaml +120 -0
  13. package/apps/searxng-container.yaml +115 -0
  14. package/dist/auth.d.ts +1 -0
  15. package/dist/auth.js +15 -14
  16. package/dist/auth.js.map +1 -1
  17. package/dist/cli/app.d.ts +4 -0
  18. package/dist/cli/app.js +814 -0
  19. package/dist/cli/app.js.map +1 -0
  20. package/dist/cli/backup.d.ts +3 -0
  21. package/dist/cli/backup.js +434 -0
  22. package/dist/cli/backup.js.map +1 -0
  23. package/dist/{doctor.d.ts → cli/doctor.d.ts} +7 -1
  24. package/dist/{doctor.js → cli/doctor.js} +377 -22
  25. package/dist/cli/doctor.js.map +1 -0
  26. package/dist/cli/helpers.d.ts +4 -0
  27. package/dist/cli/helpers.js +32 -0
  28. package/dist/cli/helpers.js.map +1 -0
  29. package/dist/cli/job.d.ts +4 -0
  30. package/dist/cli/job.js +198 -0
  31. package/dist/cli/job.js.map +1 -0
  32. package/dist/cli/llm.d.ts +25 -0
  33. package/dist/cli/llm.js +599 -0
  34. package/dist/cli/llm.js.map +1 -0
  35. package/dist/cli/managed-list.d.ts +30 -0
  36. package/dist/cli/managed-list.js +129 -0
  37. package/dist/cli/managed-list.js.map +1 -0
  38. package/dist/cli/panel.d.ts +26 -0
  39. package/dist/cli/panel.js +804 -0
  40. package/dist/cli/panel.js.map +1 -0
  41. package/dist/cli/version.d.ts +1 -0
  42. package/dist/cli/version.js +12 -0
  43. package/dist/cli/version.js.map +1 -0
  44. package/dist/cli.js +48 -776
  45. package/dist/cli.js.map +1 -1
  46. package/dist/config.d.ts +69 -0
  47. package/dist/config.js +268 -7
  48. package/dist/config.js.map +1 -1
  49. package/dist/control.d.ts +17 -41
  50. package/dist/control.js +61 -1323
  51. package/dist/control.js.map +1 -1
  52. package/dist/install.d.ts +16 -0
  53. package/dist/install.js +75 -26
  54. package/dist/install.js.map +1 -1
  55. package/dist/routes/agent-apps.d.ts +15 -0
  56. package/dist/routes/agent-apps.js +78 -0
  57. package/dist/routes/agent-apps.js.map +1 -0
  58. package/dist/routes/apps.d.ts +3 -0
  59. package/dist/routes/apps.js +278 -0
  60. package/dist/routes/apps.js.map +1 -0
  61. package/dist/routes/backup.js +3 -3
  62. package/dist/routes/backup.js.map +1 -1
  63. package/dist/routes/instances.d.ts +6 -0
  64. package/dist/routes/instances.js +863 -874
  65. package/dist/routes/instances.js.map +1 -1
  66. package/dist/routes/llm.d.ts +15 -0
  67. package/dist/routes/llm.js +247 -0
  68. package/dist/routes/llm.js.map +1 -0
  69. package/dist/routes/runtime.d.ts +15 -0
  70. package/dist/routes/runtime.js +69 -0
  71. package/dist/routes/runtime.js.map +1 -0
  72. package/dist/routes/setup.js +131 -9
  73. package/dist/routes/setup.js.map +1 -1
  74. package/dist/routes/system.js +56 -9
  75. package/dist/routes/system.js.map +1 -1
  76. package/dist/server.js +107 -7
  77. package/dist/server.js.map +1 -1
  78. package/dist/services/agent-apps/catalog.d.ts +30 -0
  79. package/dist/services/agent-apps/catalog.js +60 -0
  80. package/dist/services/agent-apps/catalog.js.map +1 -0
  81. package/dist/services/agent-apps/index.d.ts +36 -0
  82. package/dist/services/agent-apps/index.js +171 -0
  83. package/dist/services/agent-apps/index.js.map +1 -0
  84. package/dist/services/agent-apps/installers/adapter-probes.d.ts +49 -0
  85. package/dist/services/agent-apps/installers/adapter-probes.js +223 -0
  86. package/dist/services/agent-apps/installers/adapter-probes.js.map +1 -0
  87. package/dist/services/agent-apps/installers/adapter.d.ts +30 -0
  88. package/dist/services/agent-apps/installers/adapter.js +171 -0
  89. package/dist/services/agent-apps/installers/adapter.js.map +1 -0
  90. package/dist/services/agent-apps/installers/registry-probe.d.ts +38 -0
  91. package/dist/services/agent-apps/installers/registry-probe.js +183 -0
  92. package/dist/services/agent-apps/installers/registry-probe.js.map +1 -0
  93. package/dist/services/agent-apps/installers/shell-script.d.ts +47 -0
  94. package/dist/services/agent-apps/installers/shell-script.js +471 -0
  95. package/dist/services/agent-apps/installers/shell-script.js.map +1 -0
  96. package/dist/services/agent-apps/types.d.ts +125 -0
  97. package/dist/services/agent-apps/types.js +17 -0
  98. package/dist/services/agent-apps/types.js.map +1 -0
  99. package/dist/services/app/app-compiler.d.ts +15 -0
  100. package/dist/services/app/app-compiler.js +172 -0
  101. package/dist/services/app/app-compiler.js.map +1 -0
  102. package/dist/services/app/app-manager.d.ts +142 -0
  103. package/dist/services/app/app-manager.js +1988 -0
  104. package/dist/services/app/app-manager.js.map +1 -0
  105. package/dist/services/app/custom-manager.d.ts +27 -0
  106. package/dist/services/app/custom-manager.js +285 -0
  107. package/dist/services/app/custom-manager.js.map +1 -0
  108. package/dist/services/app/hermes-agent-manager.d.ts +20 -0
  109. package/dist/services/app/hermes-agent-manager.js +289 -0
  110. package/dist/services/app/hermes-agent-manager.js.map +1 -0
  111. package/dist/services/app/id-normalizer.d.ts +27 -0
  112. package/dist/services/app/id-normalizer.js +77 -0
  113. package/dist/services/app/id-normalizer.js.map +1 -0
  114. package/dist/services/app/ollama-manager.d.ts +18 -0
  115. package/dist/services/app/ollama-manager.js +207 -0
  116. package/dist/services/app/ollama-manager.js.map +1 -0
  117. package/dist/services/app/openclaw-manager.d.ts +63 -0
  118. package/dist/services/app/openclaw-manager.js +1178 -0
  119. package/dist/services/app/openclaw-manager.js.map +1 -0
  120. package/dist/services/app/paths.d.ts +47 -0
  121. package/dist/services/app/paths.js +68 -0
  122. package/dist/services/app/paths.js.map +1 -0
  123. package/dist/services/app/registry.d.ts +17 -0
  124. package/dist/services/app/registry.js +31 -0
  125. package/dist/services/app/registry.js.map +1 -0
  126. package/dist/services/app/remote-spec.d.ts +14 -0
  127. package/dist/services/app/remote-spec.js +58 -0
  128. package/dist/services/app/remote-spec.js.map +1 -0
  129. package/dist/services/app/terminal-session-manager.d.ts +27 -0
  130. package/dist/services/app/terminal-session-manager.js +157 -0
  131. package/dist/services/app/terminal-session-manager.js.map +1 -0
  132. package/dist/services/app/types.d.ts +72 -0
  133. package/dist/services/app/types.js +16 -0
  134. package/dist/services/app/types.js.map +1 -0
  135. package/dist/services/backup-manager.js +60 -22
  136. package/dist/services/backup-manager.js.map +1 -1
  137. package/dist/services/instance-manager.d.ts +125 -34
  138. package/dist/services/instance-manager.js +679 -1043
  139. package/dist/services/instance-manager.js.map +1 -1
  140. package/dist/services/llm-proxy/adapters.js +5 -1
  141. package/dist/services/llm-proxy/adapters.js.map +1 -1
  142. package/dist/services/llm-proxy/circuit-breaker.js +10 -2
  143. package/dist/services/llm-proxy/circuit-breaker.js.map +1 -1
  144. package/dist/services/llm-proxy/index.d.ts +43 -0
  145. package/dist/services/llm-proxy/index.js +120 -5
  146. package/dist/services/llm-proxy/index.js.map +1 -1
  147. package/dist/services/llm-proxy/ssrf.js +1 -1
  148. package/dist/services/llm-proxy/ssrf.js.map +1 -1
  149. package/dist/services/nomad-manager.d.ts +260 -3
  150. package/dist/services/nomad-manager.js +2921 -341
  151. package/dist/services/nomad-manager.js.map +1 -1
  152. package/dist/services/panel-manager.d.ts +50 -0
  153. package/dist/services/panel-manager.js +443 -0
  154. package/dist/services/panel-manager.js.map +1 -0
  155. package/dist/services/plugin-installer.js +28 -2
  156. package/dist/services/plugin-installer.js.map +1 -1
  157. package/dist/services/process-manager.js +42 -7
  158. package/dist/services/process-manager.js.map +1 -1
  159. package/dist/services/runtime/adapters/custom.d.ts +20 -0
  160. package/dist/services/runtime/adapters/custom.js +90 -0
  161. package/dist/services/runtime/adapters/custom.js.map +1 -0
  162. package/dist/services/runtime/adapters/hermes.d.ts +174 -0
  163. package/dist/services/runtime/adapters/hermes.js +1316 -0
  164. package/dist/services/runtime/adapters/hermes.js.map +1 -0
  165. package/dist/services/runtime/adapters/openclaw-routes.d.ts +17 -0
  166. package/dist/services/runtime/adapters/openclaw-routes.js +946 -0
  167. package/dist/services/runtime/adapters/openclaw-routes.js.map +1 -0
  168. package/dist/services/runtime/adapters/openclaw.d.ts +188 -0
  169. package/dist/services/runtime/adapters/openclaw.js +2195 -0
  170. package/dist/services/runtime/adapters/openclaw.js.map +1 -0
  171. package/dist/services/runtime/errors.d.ts +28 -0
  172. package/dist/services/runtime/errors.js +31 -0
  173. package/dist/services/runtime/errors.js.map +1 -0
  174. package/dist/services/runtime/index.d.ts +34 -0
  175. package/dist/services/runtime/index.js +51 -0
  176. package/dist/services/runtime/index.js.map +1 -0
  177. package/dist/services/runtime/instance.d.ts +24 -0
  178. package/dist/services/runtime/instance.js +143 -0
  179. package/dist/services/runtime/instance.js.map +1 -0
  180. package/dist/services/runtime/migrations.d.ts +15 -0
  181. package/dist/services/runtime/migrations.js +25 -0
  182. package/dist/services/runtime/migrations.js.map +1 -0
  183. package/dist/services/runtime/registry.d.ts +13 -0
  184. package/dist/services/runtime/registry.js +32 -0
  185. package/dist/services/runtime/registry.js.map +1 -0
  186. package/dist/services/runtime/types.d.ts +545 -0
  187. package/dist/services/runtime/types.js +14 -0
  188. package/dist/services/runtime/types.js.map +1 -0
  189. package/dist/services/setup-manager.d.ts +70 -29
  190. package/dist/services/setup-manager.js +591 -625
  191. package/dist/services/setup-manager.js.map +1 -1
  192. package/dist/services/task-registry.d.ts +44 -0
  193. package/dist/services/task-registry.js +74 -0
  194. package/dist/services/task-registry.js.map +1 -0
  195. package/dist/services/telemetry/heartbeat.d.ts +6 -6
  196. package/dist/services/telemetry/heartbeat.js +29 -30
  197. package/dist/services/telemetry/heartbeat.js.map +1 -1
  198. package/dist/services/update-manager.d.ts +47 -0
  199. package/dist/services/update-manager.js +305 -0
  200. package/dist/services/update-manager.js.map +1 -0
  201. package/dist/types.d.ts +222 -0
  202. package/dist/utils/docker-host.d.ts +15 -0
  203. package/dist/utils/docker-host.js +64 -0
  204. package/dist/utils/docker-host.js.map +1 -0
  205. package/install/jishu-install.sh +303 -37
  206. package/install/post-install.sh +64 -5
  207. package/package.json +19 -5
  208. package/public/assets/Dashboard-B-JoOjBQ.js +1 -0
  209. package/public/assets/HermesChatPanel-mFSureyc.js +1 -0
  210. package/public/assets/HermesConfigForm-DvR05LK1.js +4 -0
  211. package/public/assets/InitPassword-CVA8wQA6.js +1 -0
  212. package/public/assets/InstanceDetail-DcZW2QGO.js +91 -0
  213. package/public/assets/{Login-CUoEZOWR.js → Login-BWsZH2mu.js} +1 -1
  214. package/public/assets/NewInstance-BCIrAd86.js +1 -0
  215. package/public/assets/Settings-xkDcduFz.js +1 -0
  216. package/public/assets/Setup-Cfuwj4gV.js +1 -0
  217. package/public/assets/WeixinLoginPanel-CnjR8xMu.js +9 -0
  218. package/public/assets/index-CPhVFEsx.css +1 -0
  219. package/public/assets/index-DQsM6Joa.js +19 -0
  220. package/public/assets/input-paste-CrNVAyOy.js +1 -0
  221. package/public/assets/{providers-lBSOjUWy.js → providers-V-vwrExZ.js} +1 -1
  222. package/public/assets/registry-B4UFJdpA.js +2 -0
  223. package/public/assets/{usePolling-CK0DfI4h.js → usePolling-Do5Erqm_.js} +1 -1
  224. package/public/assets/vendor-i18n-ucpM0OR0.js +9 -0
  225. package/public/assets/{vendor-react-B1-3Yrt-.js → vendor-react-Bk1hRGiY.js} +1 -1
  226. package/public/favicon.png +0 -0
  227. package/public/index.html +9 -4
  228. package/public/logos/hermes.png +0 -0
  229. package/public/logos/ollama.png +0 -0
  230. package/public/logos/openclaw.svg +60 -0
  231. package/scripts/build-hermes-image.sh +21 -0
  232. package/scripts/build-local.sh +54 -0
  233. package/scripts/check-adapter-isolation.ts +293 -0
  234. package/scripts/fixtures/instances/hermes-sample/instance.json +37 -0
  235. package/scripts/fixtures/instances/legacy-openclaw-sample/instance.json +7 -0
  236. package/scripts/smoke/hermes-bootstrap.sh +195 -0
  237. package/templates/hermes-entrypoint.sh +154 -0
  238. package/dist/doctor.js.map +0 -1
  239. package/install/jishu-install-china.sh +0 -3092
  240. package/public/assets/Dashboard-DhsrzJ4F.js +0 -1
  241. package/public/assets/InitPassword-BjubiVdd.js +0 -1
  242. package/public/assets/InstanceDetail-DMcywsof.js +0 -17
  243. package/public/assets/NewInstance-Bk0G4EiJ.js +0 -1
  244. package/public/assets/Settings-D5tHL_h5.js +0 -1
  245. package/public/assets/Setup-4t6E3Rut.js +0 -1
  246. package/public/assets/index-BJ47MWpF.css +0 -1
  247. package/public/assets/index-DbX85irc.js +0 -16
  248. package/public/assets/vendor-i18n-CfW0RvgE.js +0 -9
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Runtime catalog endpoint (§32.2.2 / §32.8).
3
+ *
4
+ * `GET /api/runtime/catalog` returns the declarative manifest + live install
5
+ * status for every registered adapter. Frontend code iterates over the
6
+ * response to render NewInstance cards, Setup wizard rows, and runtime
7
+ * badges — no per-runtime branches in the UI.
8
+ *
9
+ * The payload is intentionally static (plus one installed/imageReady flag
10
+ * per adapter) so it can be cached by the browser for the session.
11
+ * Dynamic state like the active install task id keeps living on
12
+ * `/api/setup/status`.
13
+ */
14
+ import { listRegisteredAdapters } from "../services/runtime/index.js";
15
+ // Per-adapter install-status probe budget. Adapters may run `docker image
16
+ // inspect` or npm metadata reads; if any of those hangs (slow docker
17
+ // socket, fs contention, DNS) the catalog endpoint would stall too. Cap
18
+ // each probe and treat a timeout as "unknown install status".
19
+ const INSTALL_STATUS_TIMEOUT_MS = 2500;
20
+ async function probeInstallStatus(adapter) {
21
+ if (!adapter.getInstallStatus)
22
+ return null;
23
+ try {
24
+ return (await Promise.race([
25
+ Promise.resolve(adapter.getInstallStatus()),
26
+ new Promise((_, reject) => setTimeout(() => reject(new Error("install-status probe timed out")), INSTALL_STATUS_TIMEOUT_MS)),
27
+ ]));
28
+ }
29
+ catch {
30
+ return null;
31
+ }
32
+ }
33
+ export async function runtimeCatalogRoutes(app) {
34
+ app.get("/api/runtime/catalog", async () => {
35
+ const adapters = await Promise.all(listRegisteredAdapters().map(async (adapter) => {
36
+ // Manifest is the adapter's self-declared metadata. `manifest` is
37
+ // optional on the contract, so back-fill missing fields from the
38
+ // adapter's top-level properties.
39
+ const manifest = adapter.manifest ?? {
40
+ agentType: adapter.agentType,
41
+ displayName: adapter.displayName,
42
+ description: "",
43
+ defaultCapabilities: adapter.defaultCapabilities,
44
+ };
45
+ const installStatus = await probeInstallStatus(adapter);
46
+ const chatPanel = adapter.defaultCapabilities?.gateway?.chatPanel;
47
+ const hasInlineChatDescriptor = !!adapter.inlineChatDescriptor;
48
+ return {
49
+ agentType: adapter.agentType,
50
+ displayName: manifest.displayName ?? adapter.displayName,
51
+ description: manifest.description ?? "",
52
+ defaultCapabilities: manifest.defaultCapabilities ?? adapter.defaultCapabilities,
53
+ defaultCatalogEntry: manifest.defaultCatalogEntry ?? null,
54
+ requiresNomadDocker: manifest.requiresNomadDocker ?? false,
55
+ diskSpaceMB: manifest.diskSpaceMB ?? null,
56
+ providerPresets: manifest.providerPresets ?? [],
57
+ required: adapter.required === true,
58
+ nomadJobPrefix: adapter.nomadJobPrefix ?? null,
59
+ nomadVariablePath: adapter.nomadVariablePath ?? null,
60
+ defaultGatewayPort: adapter.defaultGatewayPort ?? null,
61
+ chatPanel: chatPanel ?? null,
62
+ supportsInlineChat: hasInlineChatDescriptor,
63
+ installStatus,
64
+ };
65
+ }));
66
+ return { adapters };
67
+ });
68
+ }
69
+ //# sourceMappingURL=runtime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime.js","sourceRoot":"","sources":["../../src/routes/runtime.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,EAAE,sBAAsB,EAAE,MAAM,8BAA8B,CAAC;AAEtE,0EAA0E;AAC1E,qEAAqE;AACrE,wEAAwE;AACxE,8DAA8D;AAC9D,MAAM,yBAAyB,GAAG,IAAI,CAAC;AAEvC,KAAK,UAAU,kBAAkB,CAC/B,OAA0D;IAI1D,IAAI,CAAC,OAAO,CAAC,gBAAgB;QAAE,OAAO,IAAI,CAAC;IAC3C,IAAI,CAAC;QACH,OAAO,CAAC,MAAM,OAAO,CAAC,IAAI,CAAC;YACzB,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,gBAAgB,EAAE,CAAC;YAC3C,IAAI,OAAO,CAAO,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,CAC9B,UAAU,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC,EAAE,yBAAyB,CAAC,CACjG;SACF,CAAC,CAA0F,CAAC;IAC/F,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,GAAoB;IAC7D,GAAG,CAAC,GAAG,CAAC,sBAAsB,EAAE,KAAK,IAAI,EAAE;QACzC,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,GAAG,CAChC,sBAAsB,EAAE,CAAC,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;YAC7C,kEAAkE;YAClE,iEAAiE;YACjE,kCAAkC;YAClC,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI;gBACnC,SAAS,EAAE,OAAO,CAAC,SAAS;gBAC5B,WAAW,EAAE,OAAO,CAAC,WAAW;gBAChC,WAAW,EAAE,EAAE;gBACf,mBAAmB,EAAE,OAAO,CAAC,mBAAmB;aACjD,CAAC;YACF,MAAM,aAAa,GAAG,MAAM,kBAAkB,CAAC,OAAO,CAAC,CAAC;YACxD,MAAM,SAAS,GAAG,OAAO,CAAC,mBAAmB,EAAE,OAAO,EAAE,SAAS,CAAC;YAClE,MAAM,uBAAuB,GAAG,CAAC,CAAC,OAAO,CAAC,oBAAoB,CAAC;YAC/D,OAAO;gBACL,SAAS,EAAE,OAAO,CAAC,SAAS;gBAC5B,WAAW,EAAE,QAAQ,CAAC,WAAW,IAAI,OAAO,CAAC,WAAW;gBACxD,WAAW,EAAE,QAAQ,CAAC,WAAW,IAAI,EAAE;gBACvC,mBAAmB,EAAE,QAAQ,CAAC,mBAAmB,IAAI,OAAO,CAAC,mBAAmB;gBAChF,mBAAmB,EAAE,QAAQ,CAAC,mBAAmB,IAAI,IAAI;gBACzD,mBAAmB,EAAE,QAAQ,CAAC,mBAAmB,IAAI,KAAK;gBAC1D,WAAW,EAAE,QAAQ,CAAC,WAAW,IAAI,IAAI;gBACzC,eAAe,EAAE,QAAQ,CAAC,eAAe,IAAI,EAAE;gBAC/C,QAAQ,EAAE,OAAO,CAAC,QAAQ,KAAK,IAAI;gBACnC,cAAc,EAAE,OAAO,CAAC,cAAc,IAAI,IAAI;gBAC9C,iBAAiB,EAAE,OAAO,CAAC,iBAAiB,IAAI,IAAI;gBACpD,kBAAkB,EAAE,OAAO,CAAC,kBAAkB,IAAI,IAAI;gBACtD,SAAS,EAAE,SAAS,IAAI,IAAI;gBAC5B,kBAAkB,EAAE,uBAAuB;gBAC3C,aAAa;aACd,CAAC;QACJ,CAAC,CAAC,CACH,CAAC;QACF,OAAO,EAAE,QAAQ,EAAE,CAAC;IACtB,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -1,7 +1,51 @@
1
1
  import * as setupManager from "../services/setup-manager.js";
2
- import { encryptApiKey } from "../services/llm-proxy/index.js";
2
+ import { encryptApiKey, pushDefaultProviderToInstances } from "../services/llm-proxy/index.js";
3
3
  import { isInitialized, verifyToken } from "../auth.js";
4
4
  import { getPanelConfig, savePanelConfig } from "../config.js";
5
+ import { getAdapter, hasAdapter, listRegisteredAdapters } from "../services/runtime/index.js";
6
+ /**
7
+ * Unauthenticated ready-state probe. Used by the public `/api/setup/status`
8
+ * branch when no session token is present. Must NOT leak system details.
9
+ *
10
+ * Readiness = "service_manager chosen AND every `required: true` adapter
11
+ * reports installed + imageReady". We dispatch through the adapter
12
+ * registry instead of reading runtime-specific panel fields (legacy
13
+ * `config.openclaw_image`) so adding a new required runtime does not
14
+ * require touching this route.
15
+ */
16
+ async function computeUnauthReadiness() {
17
+ const config = getPanelConfig();
18
+ let anyRuntimeReady = false;
19
+ for (const adapter of listRegisteredAdapters()) {
20
+ if (typeof adapter.getInstallStatus !== "function")
21
+ continue;
22
+ let status;
23
+ try {
24
+ const raw = await adapter.getInstallStatus();
25
+ status = raw;
26
+ }
27
+ catch {
28
+ status = undefined;
29
+ }
30
+ if (!status)
31
+ continue;
32
+ if (status.installed && status.imageReady)
33
+ anyRuntimeReady = true;
34
+ }
35
+ return {
36
+ // "Panel is ready" = service_manager picked AND at least one runtime is
37
+ // installed. This lets users uninstall individual runtimes (e.g. openclaw)
38
+ // from the Apps page as long as another runtime is present, without the
39
+ // panel redirecting them back to the Setup wizard.
40
+ // `adapter.required` still governs first-time Setup defaults — it is
41
+ // intentionally NOT a readiness gate anymore.
42
+ ready: !!config.service_manager && anyRuntimeReady,
43
+ providerConfigured: !!config.default_provider,
44
+ // Kept for back-compat with legacy frontend code paths that still peek
45
+ // at this flag. Represents "at least one runtime has its image ready".
46
+ dockerImageReady: anyRuntimeReady,
47
+ };
48
+ }
5
49
  export async function setupRoutes(app) {
6
50
  // Get dependency status
7
51
  // - Not initialized: full status (needed for setup wizard)
@@ -9,7 +53,7 @@ export async function setupRoutes(app) {
9
53
  // - Initialized + not authenticated: only expose ready state (no system details)
10
54
  app.get("/api/setup/status", async (request) => {
11
55
  if (!isInitialized()) {
12
- return setupManager.getSetupStatus();
56
+ return await setupManager.getSetupStatus();
13
57
  }
14
58
  // Check both Authorization header AND httpOnly cookie (unified auth)
15
59
  const authHeader = request.headers.authorization || "";
@@ -20,13 +64,9 @@ export async function setupRoutes(app) {
20
64
  token = cookieMatch?.[1] || "";
21
65
  }
22
66
  if (token && verifyToken(token)) {
23
- return setupManager.getSetupStatus();
67
+ return await setupManager.getSetupStatus();
24
68
  }
25
- // Not authenticated — only reveal whether setup is truly complete
26
- const config = getPanelConfig();
27
- const hasImage = !!config.openclaw_image;
28
- const ready = !!config.service_manager && hasImage;
29
- return { ready, providerConfigured: !!config.default_provider, dockerImageReady: hasImage };
69
+ return computeUnauthReadiness();
30
70
  });
31
71
  // Upgrade Node.js
32
72
  app.post("/api/setup/upgrade/node", async (req, reply) => {
@@ -60,6 +100,55 @@ export async function setupRoutes(app) {
60
100
  return reply.status(400).send(result);
61
101
  return result;
62
102
  });
103
+ /**
104
+ * Generic runtime install endpoint — drives setup-manager dispatch
105
+ * through the adapter contract so new runtimes are reachable without
106
+ * adding a route per agent. The adapter decides whether installation
107
+ * means "docker build" (`startBuildRuntimeImage`) or "docker pull +
108
+ * catalog entry" (`startInstallRuntime`); we prefer the build entry
109
+ * when both are present so OpenClaw's legacy flow stays unchanged.
110
+ */
111
+ app.post("/api/setup/install/runtime/:agentType", async (req, reply) => {
112
+ const { agentType } = req.params;
113
+ if (!hasAdapter(agentType)) {
114
+ return reply.status(404).send({ detail: `Unknown agentType "${agentType}"` });
115
+ }
116
+ // Idempotent dedup: if this runtime already has an install task
117
+ // running (e.g. user left the page mid-install and clicked install
118
+ // again), return the existing taskId so the frontend rejoins the
119
+ // progress stream instead of starting a duplicate.
120
+ // Adapters name their install tasks by agentType prefix
121
+ // (OpenClaw uses `openclaw-docker-pull`, Hermes uses `hermes`), so a
122
+ // plain prefix match covers both naming styles without per-adapter
123
+ // branching.
124
+ const existing = setupManager.getRunningTasks(agentType);
125
+ if (existing.length > 0) {
126
+ return {
127
+ ok: true,
128
+ message: `${agentType} install already in progress`,
129
+ taskId: existing[0].id,
130
+ reused: true,
131
+ };
132
+ }
133
+ const adapter = getAdapter(agentType);
134
+ let result;
135
+ if (typeof adapter.startBuildRuntimeImage === "function") {
136
+ result = (await adapter.startBuildRuntimeImage(req.body || {}));
137
+ }
138
+ else if (typeof adapter.startInstallRuntime === "function") {
139
+ result = adapter.startInstallRuntime(req.body || {});
140
+ }
141
+ else {
142
+ return reply
143
+ .status(501)
144
+ .send({ detail: `Runtime "${agentType}" does not implement install` });
145
+ }
146
+ if (!result.ok)
147
+ return reply.status(400).send(result);
148
+ return result;
149
+ });
150
+ // Back-compat aliases — existing clients still call the legacy paths.
151
+ // New code should POST /api/setup/install/runtime/<agentType> instead.
63
152
  app.post("/api/setup/install/openclaw", async (req, reply) => {
64
153
  const result = setupManager.startBuildSlimOpenclawImage();
65
154
  if (!result.ok)
@@ -72,6 +161,12 @@ export async function setupRoutes(app) {
72
161
  return reply.status(400).send(result);
73
162
  return result;
74
163
  });
164
+ app.post("/api/setup/install/hermes", async (req, reply) => {
165
+ const result = setupManager.startInstallHermes();
166
+ if (!result.ok)
167
+ return reply.status(400).send(result);
168
+ return result;
169
+ });
75
170
  app.get("/api/setup/tasks/:id", async (req, reply) => {
76
171
  const task = setupManager.getTaskSnapshot(req.params.id);
77
172
  if (!task)
@@ -124,13 +219,40 @@ export async function setupRoutes(app) {
124
219
  else {
125
220
  const { providerId, baseUrl, api, authHeader, models, selectedModelId, apiKey } = body;
126
221
  const existingKey = config.default_provider?.apiKey;
222
+ const encryptedKey = apiKey ? encryptApiKey(apiKey) : (existingKey || "");
127
223
  config.default_provider = {
128
224
  providerId, baseUrl, api, authHeader,
129
225
  models, selectedModelId,
130
- apiKey: apiKey ? encryptApiKey(apiKey) : (existingKey || ""),
226
+ apiKey: encryptedKey,
227
+ };
228
+ // Also sync to providers[] so loadProviders() returns updated data regardless
229
+ // of whether config.providers was previously initialised.
230
+ const providers = Array.isArray(config.providers) ? [...config.providers] : [];
231
+ const existingIdx = providers.findIndex((p) => p.id === providerId);
232
+ const entry = {
233
+ id: providerId,
234
+ name: providerId,
235
+ baseUrl, api, authHeader,
236
+ models, selectedModelId,
237
+ apiKey: encryptedKey,
238
+ isDefault: true,
131
239
  };
240
+ if (existingIdx >= 0) {
241
+ providers[existingIdx] = entry;
242
+ }
243
+ else {
244
+ providers.forEach((p) => { p.isDefault = false; });
245
+ providers.push(entry);
246
+ }
247
+ config.providers = providers;
132
248
  }
133
249
  savePanelConfig(config);
250
+ // Propagate new provider/model to all existing instances so they
251
+ // immediately use the updated model without requiring a restart.
252
+ if (!body.skipped) {
253
+ const { providerId, baseUrl, api, authHeader, models, selectedModelId, apiKey } = body;
254
+ await pushDefaultProviderToInstances({ providerId, baseUrl, api, authHeader, models, selectedModelId, apiKey });
255
+ }
134
256
  return { ok: true };
135
257
  });
136
258
  }
@@ -1 +1 @@
1
- {"version":3,"file":"setup.js","sourceRoot":"","sources":["../../src/routes/setup.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"setup.js","sourceRoot":"","sources":["../../src/routes/setup.ts"],"names":[],"mappings":"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"}
@@ -1,12 +1,12 @@
1
1
  import { execFileSync } from "child_process";
2
2
  import { existsSync } from "fs";
3
3
  import { join, dirname } from "path";
4
- import { getDeviceId } from "../config.js";
4
+ import { getDeviceId, getPanelConfig } from "../config.js";
5
5
  import { getSystemStatus } from "../services/system-monitor.js";
6
- import { getResolvedOpenclawBin } from "../services/instance-manager.js";
6
+ import { getResolvedOpenclawBin } from "../services/app/app-manager.js";
7
7
  import { TtlCache } from "../utils/ttl-cache.js";
8
8
  import { stopNomad, startNomad } from "../services/setup-manager.js";
9
- import { checkUpdate, runUpdate } from "../control.js";
9
+ import { checkUpdate, getUpdateStatus, startBackgroundUpgrade } from "../services/update-manager.js";
10
10
  const _versionCache = new TtlCache(3_600_000); // 1 hour
11
11
  function getOpenclawVersion() {
12
12
  return _versionCache.get(() => {
@@ -19,10 +19,32 @@ function getOpenclawVersion() {
19
19
  }
20
20
  });
21
21
  }
22
+ /**
23
+ * Aggregate per-runtime version strings for the panel status payload.
24
+ * OpenClaw version comes from the installed binary's `--version` output.
25
+ * Other runtimes (Hermes et al.) report their pinned Docker image digest
26
+ * from `panel.runtime_catalog`. Unknown / uninstalled entries are omitted.
27
+ */
28
+ function getRuntimeVersions() {
29
+ const out = { openclaw: getOpenclawVersion() };
30
+ const catalog = (getPanelConfig().runtime_catalog ?? {});
31
+ for (const [agentType, entry] of Object.entries(catalog)) {
32
+ if (!entry)
33
+ continue;
34
+ const tag = entry.defaultImageDigest || entry.defaultImage;
35
+ if (tag)
36
+ out[agentType] = tag;
37
+ }
38
+ return out;
39
+ }
22
40
  export async function systemRoutes(app) {
23
41
  app.get("/api/system/status", async () => {
24
42
  const status = await getSystemStatus();
43
+ // `openclaw_version` is preserved as the legacy single-runtime field;
44
+ // new clients should read `runtime_versions` which covers every
45
+ // installed adapter uniformly.
25
46
  status.openclaw_version = getOpenclawVersion();
47
+ status.runtime_versions = getRuntimeVersions();
26
48
  status.device_id = getDeviceId();
27
49
  return status;
28
50
  });
@@ -42,13 +64,38 @@ export async function systemRoutes(app) {
42
64
  return reply.status(500).send({ detail: err.message });
43
65
  }
44
66
  });
67
+ app.get("/api/system/update-status", async (_req, reply) => {
68
+ try {
69
+ return getUpdateStatus();
70
+ }
71
+ catch (err) {
72
+ return reply.status(500).send({ detail: err.message });
73
+ }
74
+ });
45
75
  app.post("/api/system/update", async (_req, reply) => {
46
- // Run update synchronously so errors reach the client.
47
- // The restart at the end will terminate this process — that's expected.
48
76
  try {
49
- await runUpdate();
50
- // If we somehow get here before restart, tell the client it's done.
51
- return reply.send({ ok: true, message: "Update complete; restarting." });
77
+ const info = await checkUpdate();
78
+ if (!info.hasUpdate) {
79
+ return reply.send({
80
+ ok: true,
81
+ status: "completed",
82
+ currentVersion: info.currentVersion,
83
+ targetVersion: info.currentVersion,
84
+ message: "Already up to date.",
85
+ });
86
+ }
87
+ const status = getUpdateStatus();
88
+ if (status.inProgress) {
89
+ return reply.status(409).send({ detail: status.message || "Update already in progress" });
90
+ }
91
+ const started = startBackgroundUpgrade(info);
92
+ return reply.send({
93
+ ok: true,
94
+ status: started.status,
95
+ currentVersion: info.currentVersion,
96
+ targetVersion: info.latestVersion,
97
+ message: `Update started: ${info.currentVersion} -> ${info.latestVersion}`,
98
+ });
52
99
  }
53
100
  catch (err) {
54
101
  return reply.status(500).send({ detail: err.message });
@@ -60,7 +107,7 @@ export async function systemRoutes(app) {
60
107
  // times; keys already using the current key are skipped. This completes the
61
108
  // JWT/AES decoupling described in docs/secrets-architecture.md §6.
62
109
  app.post("/api/admin/migrate-api-keys", async (_req, reply) => {
63
- const { listInstances, getRuntimeEnvFiles, parseEnvFile, updateEnvFile, } = await import("../services/instance-manager.js");
110
+ const { listInstances, getRuntimeEnvFiles, parseEnvFile, updateEnvFile, } = await import("../services/app/app-manager.js");
64
111
  const { decryptApiKeyWithInfo, encryptApiKey } = await import("../services/llm-proxy/encryption.js");
65
112
  const instances = listInstances();
66
113
  const results = [];
@@ -1 +1 @@
1
- {"version":3,"file":"system.js","sourceRoot":"","sources":["../../src/routes/system.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"system.js","sourceRoot":"","sources":["../../src/routes/system.ts"],"names":[],"mappings":"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"}
package/dist/server.js CHANGED
@@ -7,22 +7,30 @@ import { fileURLToPath } from "url";
7
7
  import { request as httpRequest } from "http";
8
8
  const __filename = fileURLToPath(import.meta.url);
9
9
  const __dirname = dirname(__filename);
10
- import { ensureDirs, ensurePanelConfig, getPanelConfig, migrateOpenclawImageTagIfNeeded } from "./config.js";
10
+ import { ensureDirs, ensurePanelConfig, getPanelConfig, migrateCatalogSchemaIfNeeded, migrateHermesShimOutIfNeeded, migrateOpenclawCatalogIfNeeded, migrateOpenclawImageTagIfNeeded, } from "./config.js";
11
+ import { runStartupMigrations } from "./services/runtime/index.js";
11
12
  import { verifyToken } from "./auth.js";
12
13
  import { authRoutes } from "./routes/auth.js";
13
14
  import { instanceRoutes } from "./routes/instances.js";
14
15
  import { systemRoutes } from "./routes/system.js";
15
16
  import { setupRoutes } from "./routes/setup.js";
17
+ import { runtimeCatalogRoutes } from "./routes/runtime.js";
18
+ import { appRoutes } from "./routes/apps.js";
19
+ import { agentAppRoutes } from "./routes/agent-apps.js";
20
+ import { llmRoutes } from "./routes/llm.js";
21
+ import * as appManager from "./services/app/app-manager.js";
16
22
  import backupRoutes from "./routes/backup.js";
17
23
  import * as llmProxy from "./services/llm-proxy/index.js";
18
24
  import * as nomadManager from "./services/nomad-manager.js";
19
- import * as instanceManager from "./services/instance-manager.js";
25
+ import * as instanceManager from "./services/app/app-manager.js";
20
26
  import * as setupManager from "./services/setup-manager.js";
21
27
  import { startTmpCleanupScheduler, initAutoBackup } from "./services/backup-manager.js";
28
+ import { checkUpdate } from "./services/panel-manager.js";
22
29
  import { PROXY_IDENTITY_HEADERS } from "./constants.js";
23
- const PUBLIC_PATHS = new Set(["/api/auth/status", "/api/auth/init", "/api/auth/login", "/api/setup/status"]);
30
+ import { supportsGatewayWebsocket } from "./services/runtime/instance.js";
31
+ const PUBLIC_PATHS = new Set(["/api/auth/status", "/api/auth/init", "/api/auth/login", "/api/setup/status", "/api/apps/validate-sudo-password"]);
24
32
  export async function createServer(options = {}) {
25
- const port = options.port || 8090;
33
+ const port = options.port ?? 8090;
26
34
  const host = options.host || "0.0.0.0";
27
35
  ensureDirs();
28
36
  startTmpCleanupScheduler();
@@ -47,6 +55,10 @@ export async function createServer(options = {}) {
47
55
  }
48
56
  }
49
57
  });
58
+ // Parse text/plain and application/x-yaml as raw string (for app install endpoint)
59
+ app.addContentTypeParser(["text/plain", "application/x-yaml"], { parseAs: "string" }, (req, body, done) => {
60
+ done(null, body);
61
+ });
50
62
  // Auth middleware
51
63
  app.addHook("onRequest", async (request, reply) => {
52
64
  const path = request.url.split("?")[0];
@@ -103,6 +115,10 @@ export async function createServer(options = {}) {
103
115
  await app.register(instanceRoutes);
104
116
  await app.register(systemRoutes);
105
117
  await app.register(setupRoutes);
118
+ await app.register(runtimeCatalogRoutes);
119
+ await app.register(appRoutes);
120
+ await app.register(agentAppRoutes);
121
+ await app.register(llmRoutes);
106
122
  await app.register(backupRoutes);
107
123
  // Serve frontend static files
108
124
  // Look for frontend dist in multiple locations
@@ -154,10 +170,30 @@ export async function createServer(options = {}) {
154
170
  setTimeout(async () => {
155
171
  try {
156
172
  ensurePanelConfig();
173
+ // One-shot: if panel.json only has the legacy `openclaw_image` field
174
+ // (older release, OpenClaw pre-runtime-catalog), mirror it into
175
+ // `runtime_catalog.openclaw` so the unified read path sees it.
176
+ migrateOpenclawCatalogIfNeeded();
177
+ // One-shot: drop runtime_catalog.hermes.shimPath and delete the
178
+ // orphaned ~/.jishushell/runtimes/hermes/ dir. The Hermes shim is
179
+ // now baked into the image (PR3c) and the adapter refuses to
180
+ // launch without runtime.protocol.version on the image LABEL, so
181
+ // the host shim is dead weight.
182
+ migrateHermesShimOutIfNeeded();
183
+ // Stamp the runtime_catalog schema version so panel.json carries a
184
+ // provenance marker. Warns (but doesn't crash) on detected panel
185
+ // downgrade where the stored version exceeds what we support.
186
+ migrateCatalogSchemaIfNeeded();
157
187
  // One-shot: if panel.json still stores a mutable image tag (:latest
158
188
  // or :slim) from an older release, rewrite it to the pinned
159
189
  // :${version} form so Nomad stops re-pulling on each restart.
160
190
  migrateOpenclawImageTagIfNeeded();
191
+ // Same one-shot for per-adapter migrations (Hermes rewrites
192
+ // runtime_catalog.hermes.defaultImage from `:latest` to the pinned
193
+ // :${LABEL org.opencontainers.image.version} form). Runs every
194
+ // registered adapter's migrateStartup() hook so server.ts never
195
+ // imports a specific adapter (check-adapter-isolation §32.2.1).
196
+ runStartupMigrations();
161
197
  const config = getPanelConfig();
162
198
  if (config.service_manager === "nomad") {
163
199
  const nomadResult = await setupManager.startNomad();
@@ -201,6 +237,30 @@ export async function createServer(options = {}) {
201
237
  catch (e) {
202
238
  console.warn("[startup] openclaw image tag migration skipped:", e);
203
239
  }
240
+ // Second adapter-migration sweep — after Nomad auto-start the
241
+ // runtime images may finally be locally present so `:latest` →
242
+ // pinned digest tag rewrite can now succeed.
243
+ runStartupMigrations();
244
+ }
245
+ // Rebuild capability registry from running app instances
246
+ try {
247
+ for (const inst of instanceManager.listInstances()) {
248
+ if (!inst.id || !inst.app_id)
249
+ continue;
250
+ const appData = appManager.getApp(inst.app_id);
251
+ if (!appData || !appData.spec.provides?.length)
252
+ continue;
253
+ // Use the generic framework helper — it dispatches through
254
+ // the runtime adapter and handles both OpenClaw (env var)
255
+ // and adapter-based (runtime.ports[]) port discovery.
256
+ const port = instanceManager.getGatewayPort(inst.id);
257
+ if (port > 0) {
258
+ appManager.registerCapabilities(inst.id, appData.spec, port);
259
+ }
260
+ }
261
+ }
262
+ catch (e) {
263
+ console.error("[startup] Capability registry rebuild failed:", e);
204
264
  }
205
265
  }
206
266
  catch (e) {
@@ -212,6 +272,10 @@ export async function createServer(options = {}) {
212
272
  // Assign the rebind implementation now that the server is listening.
213
273
  // Called by /api/auth/init to switch from 127.0.0.1 → 0.0.0.0 in-process.
214
274
  _rebind = async (newHost) => {
275
+ if (host === newHost)
276
+ return;
277
+ const addr = app.server.address();
278
+ const boundPort = addr && typeof addr === "object" ? addr.port : port;
215
279
  await new Promise((resolve, reject) => {
216
280
  app.server.close((err) => { if (err)
217
281
  reject(err);
@@ -219,8 +283,8 @@ export async function createServer(options = {}) {
219
283
  resolve(); });
220
284
  });
221
285
  await new Promise((resolve, reject) => {
222
- app.server.listen(port, newHost, () => {
223
- console.log(`[server] Rebound to http://${newHost}:${port}`);
286
+ app.server.listen(boundPort, newHost, () => {
287
+ console.log(`[server] Rebound to http://${newHost}:${boundPort}`);
224
288
  resolve();
225
289
  });
226
290
  app.server.once("error", reject);
@@ -273,8 +337,20 @@ export async function createServer(options = {}) {
273
337
  socket.destroy();
274
338
  return;
275
339
  }
340
+ if (!(await supportsGatewayWebsocket(id, inst))) {
341
+ try {
342
+ socket.write("HTTP/1.1 501 Not Implemented\r\nConnection: close\r\n\r\n");
343
+ }
344
+ catch { }
345
+ socket.destroy();
346
+ return;
347
+ }
276
348
  const gwPort = instanceManager.getGatewayPort(id);
277
349
  const gwHost = await instanceManager.getGatewayHost(id);
350
+ // Bracket IPv6 literals for Host-header use. Node's http.request accepts
351
+ // a bare `::1` in `hostname`, but the `host` header field is a URL-style
352
+ // `<host>:<port>` where v6 must be bracketed.
353
+ const hostHeader = `${instanceManager.urlHost(gwHost)}:${gwPort}`;
278
354
  const suffix = match[2] || "";
279
355
  const qs = url.includes("?") ? url.slice(url.indexOf("?")) : "";
280
356
  const targetPath = `/${suffix}${qs}`;
@@ -291,6 +367,10 @@ export async function createServer(options = {}) {
291
367
  continue;
292
368
  upstreamHeaders[key] = value;
293
369
  }
370
+ // Forward the browser's Origin unchanged. The panel auto-adds it to
371
+ // `gateway.controlUi.allowedOrigins` via ensureControlUiAllowedOrigin
372
+ // + restart; rewriting to the upstream host (as cli 94163bc did)
373
+ // breaks that allowlist match.
294
374
  // Prevent any HTTP-level timeouts from killing this long-lived connection
295
375
  socket.setTimeout?.(0);
296
376
  socket.setNoDelay?.(true);
@@ -305,7 +385,7 @@ export async function createServer(options = {}) {
305
385
  timeout: 10000, // 10s timeout for upstream upgrade handshake
306
386
  headers: {
307
387
  ...upstreamHeaders,
308
- host: `${gwHost}:${gwPort}`,
388
+ host: hostHeader,
309
389
  },
310
390
  });
311
391
  }
@@ -398,9 +478,20 @@ export async function createServer(options = {}) {
398
478
  setupManager.setServerPort(port);
399
479
  nomadManager.setPanelPort(port);
400
480
  console.log(`JishuShell listening on http://${host}:${port}`);
481
+ // Background update check — runs the update probe (which piggybacks telemetry
482
+ // heartbeat + activation) so headless deployments report without the frontend.
483
+ // Safe by design: checkUpdate swallows all errors, has a 30s in-memory cache,
484
+ // and heartbeat/activation dedupe by UTC date / persisted flag.
485
+ const bgUpdateCheck = () => { checkUpdate().catch(() => { }); };
486
+ const bgInitial = setTimeout(bgUpdateCheck, 30_000);
487
+ const bgInterval = setInterval(bgUpdateCheck, 4 * 60 * 60 * 1000);
488
+ bgInitial.unref();
489
+ bgInterval.unref();
401
490
  // Graceful shutdown — let in-flight requests finish before exiting
402
491
  const shutdown = async () => {
403
492
  console.log("[server] Shutting down gracefully...");
493
+ clearTimeout(bgInitial);
494
+ clearInterval(bgInterval);
404
495
  llmProxy.flushUsage();
405
496
  // Destroy all active WebSocket proxy connections
406
497
  for (const s of activeWsSockets) {
@@ -410,6 +501,15 @@ export async function createServer(options = {}) {
410
501
  catch { }
411
502
  }
412
503
  activeWsSockets.clear();
504
+ // Force-close keep-alive idle sockets AND hijacked SSE streams
505
+ // (reply.hijack() detaches from Fastify so app.close() can't reach them).
506
+ // Without this, app.close() waits until every open socket drains, which
507
+ // for LLM proxy chat streams / capability SSE can be up to 30 minutes
508
+ // and triggers systemd TimeoutStopSec → SIGKILL.
509
+ try {
510
+ app.server.closeAllConnections();
511
+ }
512
+ catch { /* Node <18.2 */ }
413
513
  await app.close();
414
514
  process.exit(0);
415
515
  };