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.
- package/Dockerfile.hermes-slim +193 -0
- package/INSTALL-NOTICE +10 -12
- package/apps/hermes-container.yaml +35 -0
- package/apps/ollama-binary.yaml +200 -0
- package/apps/ollama-cpu-container.yaml +37 -0
- package/apps/ollama-with-hollama-binary.yaml +195 -0
- package/apps/openclaw-binary.yaml +69 -0
- package/apps/openclaw-container.yaml +37 -0
- package/apps/openclaw-with-ollama-container.yaml +42 -0
- package/apps/openclaw-with-searxng-container.yaml +136 -0
- package/apps/openwebui-container.yaml +53 -0
- package/apps/playwright-container.yaml +120 -0
- package/apps/searxng-container.yaml +115 -0
- package/dist/auth.d.ts +1 -0
- package/dist/auth.js +15 -14
- package/dist/auth.js.map +1 -1
- package/dist/cli/app.d.ts +4 -0
- package/dist/cli/app.js +814 -0
- package/dist/cli/app.js.map +1 -0
- package/dist/cli/backup.d.ts +3 -0
- package/dist/cli/backup.js +434 -0
- package/dist/cli/backup.js.map +1 -0
- package/dist/{doctor.d.ts → cli/doctor.d.ts} +7 -1
- package/dist/{doctor.js → cli/doctor.js} +377 -22
- package/dist/cli/doctor.js.map +1 -0
- package/dist/cli/helpers.d.ts +4 -0
- package/dist/cli/helpers.js +32 -0
- package/dist/cli/helpers.js.map +1 -0
- package/dist/cli/job.d.ts +4 -0
- package/dist/cli/job.js +198 -0
- package/dist/cli/job.js.map +1 -0
- package/dist/cli/llm.d.ts +25 -0
- package/dist/cli/llm.js +599 -0
- package/dist/cli/llm.js.map +1 -0
- package/dist/cli/managed-list.d.ts +30 -0
- package/dist/cli/managed-list.js +129 -0
- package/dist/cli/managed-list.js.map +1 -0
- package/dist/cli/panel.d.ts +26 -0
- package/dist/cli/panel.js +804 -0
- package/dist/cli/panel.js.map +1 -0
- package/dist/cli/version.d.ts +1 -0
- package/dist/cli/version.js +12 -0
- package/dist/cli/version.js.map +1 -0
- package/dist/cli.js +48 -776
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +69 -0
- package/dist/config.js +268 -7
- package/dist/config.js.map +1 -1
- package/dist/control.d.ts +17 -41
- package/dist/control.js +61 -1323
- package/dist/control.js.map +1 -1
- package/dist/install.d.ts +16 -0
- package/dist/install.js +75 -26
- package/dist/install.js.map +1 -1
- package/dist/routes/agent-apps.d.ts +15 -0
- package/dist/routes/agent-apps.js +78 -0
- package/dist/routes/agent-apps.js.map +1 -0
- package/dist/routes/apps.d.ts +3 -0
- package/dist/routes/apps.js +278 -0
- package/dist/routes/apps.js.map +1 -0
- package/dist/routes/backup.js +3 -3
- package/dist/routes/backup.js.map +1 -1
- package/dist/routes/instances.d.ts +6 -0
- package/dist/routes/instances.js +863 -874
- package/dist/routes/instances.js.map +1 -1
- package/dist/routes/llm.d.ts +15 -0
- package/dist/routes/llm.js +247 -0
- package/dist/routes/llm.js.map +1 -0
- package/dist/routes/runtime.d.ts +15 -0
- package/dist/routes/runtime.js +69 -0
- package/dist/routes/runtime.js.map +1 -0
- package/dist/routes/setup.js +131 -9
- package/dist/routes/setup.js.map +1 -1
- package/dist/routes/system.js +56 -9
- package/dist/routes/system.js.map +1 -1
- package/dist/server.js +107 -7
- package/dist/server.js.map +1 -1
- package/dist/services/agent-apps/catalog.d.ts +30 -0
- package/dist/services/agent-apps/catalog.js +60 -0
- package/dist/services/agent-apps/catalog.js.map +1 -0
- package/dist/services/agent-apps/index.d.ts +36 -0
- package/dist/services/agent-apps/index.js +171 -0
- package/dist/services/agent-apps/index.js.map +1 -0
- package/dist/services/agent-apps/installers/adapter-probes.d.ts +49 -0
- package/dist/services/agent-apps/installers/adapter-probes.js +223 -0
- package/dist/services/agent-apps/installers/adapter-probes.js.map +1 -0
- package/dist/services/agent-apps/installers/adapter.d.ts +30 -0
- package/dist/services/agent-apps/installers/adapter.js +171 -0
- package/dist/services/agent-apps/installers/adapter.js.map +1 -0
- package/dist/services/agent-apps/installers/registry-probe.d.ts +38 -0
- package/dist/services/agent-apps/installers/registry-probe.js +183 -0
- package/dist/services/agent-apps/installers/registry-probe.js.map +1 -0
- package/dist/services/agent-apps/installers/shell-script.d.ts +47 -0
- package/dist/services/agent-apps/installers/shell-script.js +471 -0
- package/dist/services/agent-apps/installers/shell-script.js.map +1 -0
- package/dist/services/agent-apps/types.d.ts +125 -0
- package/dist/services/agent-apps/types.js +17 -0
- package/dist/services/agent-apps/types.js.map +1 -0
- package/dist/services/app/app-compiler.d.ts +15 -0
- package/dist/services/app/app-compiler.js +172 -0
- package/dist/services/app/app-compiler.js.map +1 -0
- package/dist/services/app/app-manager.d.ts +142 -0
- package/dist/services/app/app-manager.js +1988 -0
- package/dist/services/app/app-manager.js.map +1 -0
- package/dist/services/app/custom-manager.d.ts +27 -0
- package/dist/services/app/custom-manager.js +285 -0
- package/dist/services/app/custom-manager.js.map +1 -0
- package/dist/services/app/hermes-agent-manager.d.ts +20 -0
- package/dist/services/app/hermes-agent-manager.js +289 -0
- package/dist/services/app/hermes-agent-manager.js.map +1 -0
- package/dist/services/app/id-normalizer.d.ts +27 -0
- package/dist/services/app/id-normalizer.js +77 -0
- package/dist/services/app/id-normalizer.js.map +1 -0
- package/dist/services/app/ollama-manager.d.ts +18 -0
- package/dist/services/app/ollama-manager.js +207 -0
- package/dist/services/app/ollama-manager.js.map +1 -0
- package/dist/services/app/openclaw-manager.d.ts +63 -0
- package/dist/services/app/openclaw-manager.js +1178 -0
- package/dist/services/app/openclaw-manager.js.map +1 -0
- package/dist/services/app/paths.d.ts +47 -0
- package/dist/services/app/paths.js +68 -0
- package/dist/services/app/paths.js.map +1 -0
- package/dist/services/app/registry.d.ts +17 -0
- package/dist/services/app/registry.js +31 -0
- package/dist/services/app/registry.js.map +1 -0
- package/dist/services/app/remote-spec.d.ts +14 -0
- package/dist/services/app/remote-spec.js +58 -0
- package/dist/services/app/remote-spec.js.map +1 -0
- package/dist/services/app/terminal-session-manager.d.ts +27 -0
- package/dist/services/app/terminal-session-manager.js +157 -0
- package/dist/services/app/terminal-session-manager.js.map +1 -0
- package/dist/services/app/types.d.ts +72 -0
- package/dist/services/app/types.js +16 -0
- package/dist/services/app/types.js.map +1 -0
- package/dist/services/backup-manager.js +60 -22
- package/dist/services/backup-manager.js.map +1 -1
- package/dist/services/instance-manager.d.ts +125 -34
- package/dist/services/instance-manager.js +679 -1043
- package/dist/services/instance-manager.js.map +1 -1
- package/dist/services/llm-proxy/adapters.js +5 -1
- package/dist/services/llm-proxy/adapters.js.map +1 -1
- package/dist/services/llm-proxy/circuit-breaker.js +10 -2
- package/dist/services/llm-proxy/circuit-breaker.js.map +1 -1
- package/dist/services/llm-proxy/index.d.ts +43 -0
- package/dist/services/llm-proxy/index.js +120 -5
- package/dist/services/llm-proxy/index.js.map +1 -1
- package/dist/services/llm-proxy/ssrf.js +1 -1
- package/dist/services/llm-proxy/ssrf.js.map +1 -1
- package/dist/services/nomad-manager.d.ts +260 -3
- package/dist/services/nomad-manager.js +2921 -341
- package/dist/services/nomad-manager.js.map +1 -1
- package/dist/services/panel-manager.d.ts +50 -0
- package/dist/services/panel-manager.js +443 -0
- package/dist/services/panel-manager.js.map +1 -0
- package/dist/services/plugin-installer.js +28 -2
- package/dist/services/plugin-installer.js.map +1 -1
- package/dist/services/process-manager.js +42 -7
- package/dist/services/process-manager.js.map +1 -1
- package/dist/services/runtime/adapters/custom.d.ts +20 -0
- package/dist/services/runtime/adapters/custom.js +90 -0
- package/dist/services/runtime/adapters/custom.js.map +1 -0
- package/dist/services/runtime/adapters/hermes.d.ts +174 -0
- package/dist/services/runtime/adapters/hermes.js +1316 -0
- package/dist/services/runtime/adapters/hermes.js.map +1 -0
- package/dist/services/runtime/adapters/openclaw-routes.d.ts +17 -0
- package/dist/services/runtime/adapters/openclaw-routes.js +946 -0
- package/dist/services/runtime/adapters/openclaw-routes.js.map +1 -0
- package/dist/services/runtime/adapters/openclaw.d.ts +188 -0
- package/dist/services/runtime/adapters/openclaw.js +2195 -0
- package/dist/services/runtime/adapters/openclaw.js.map +1 -0
- package/dist/services/runtime/errors.d.ts +28 -0
- package/dist/services/runtime/errors.js +31 -0
- package/dist/services/runtime/errors.js.map +1 -0
- package/dist/services/runtime/index.d.ts +34 -0
- package/dist/services/runtime/index.js +51 -0
- package/dist/services/runtime/index.js.map +1 -0
- package/dist/services/runtime/instance.d.ts +24 -0
- package/dist/services/runtime/instance.js +143 -0
- package/dist/services/runtime/instance.js.map +1 -0
- package/dist/services/runtime/migrations.d.ts +15 -0
- package/dist/services/runtime/migrations.js +25 -0
- package/dist/services/runtime/migrations.js.map +1 -0
- package/dist/services/runtime/registry.d.ts +13 -0
- package/dist/services/runtime/registry.js +32 -0
- package/dist/services/runtime/registry.js.map +1 -0
- package/dist/services/runtime/types.d.ts +545 -0
- package/dist/services/runtime/types.js +14 -0
- package/dist/services/runtime/types.js.map +1 -0
- package/dist/services/setup-manager.d.ts +70 -29
- package/dist/services/setup-manager.js +591 -625
- package/dist/services/setup-manager.js.map +1 -1
- package/dist/services/task-registry.d.ts +44 -0
- package/dist/services/task-registry.js +74 -0
- package/dist/services/task-registry.js.map +1 -0
- package/dist/services/telemetry/heartbeat.d.ts +6 -6
- package/dist/services/telemetry/heartbeat.js +29 -30
- package/dist/services/telemetry/heartbeat.js.map +1 -1
- package/dist/services/update-manager.d.ts +47 -0
- package/dist/services/update-manager.js +305 -0
- package/dist/services/update-manager.js.map +1 -0
- package/dist/types.d.ts +222 -0
- package/dist/utils/docker-host.d.ts +15 -0
- package/dist/utils/docker-host.js +64 -0
- package/dist/utils/docker-host.js.map +1 -0
- package/install/jishu-install.sh +303 -37
- package/install/post-install.sh +64 -5
- package/package.json +19 -5
- package/public/assets/Dashboard-B-JoOjBQ.js +1 -0
- package/public/assets/HermesChatPanel-mFSureyc.js +1 -0
- package/public/assets/HermesConfigForm-DvR05LK1.js +4 -0
- package/public/assets/InitPassword-CVA8wQA6.js +1 -0
- package/public/assets/InstanceDetail-DcZW2QGO.js +91 -0
- package/public/assets/{Login-CUoEZOWR.js → Login-BWsZH2mu.js} +1 -1
- package/public/assets/NewInstance-BCIrAd86.js +1 -0
- package/public/assets/Settings-xkDcduFz.js +1 -0
- package/public/assets/Setup-Cfuwj4gV.js +1 -0
- package/public/assets/WeixinLoginPanel-CnjR8xMu.js +9 -0
- package/public/assets/index-CPhVFEsx.css +1 -0
- package/public/assets/index-DQsM6Joa.js +19 -0
- package/public/assets/input-paste-CrNVAyOy.js +1 -0
- package/public/assets/{providers-lBSOjUWy.js → providers-V-vwrExZ.js} +1 -1
- package/public/assets/registry-B4UFJdpA.js +2 -0
- package/public/assets/{usePolling-CK0DfI4h.js → usePolling-Do5Erqm_.js} +1 -1
- package/public/assets/vendor-i18n-ucpM0OR0.js +9 -0
- package/public/assets/{vendor-react-B1-3Yrt-.js → vendor-react-Bk1hRGiY.js} +1 -1
- package/public/favicon.png +0 -0
- package/public/index.html +9 -4
- package/public/logos/hermes.png +0 -0
- package/public/logos/ollama.png +0 -0
- package/public/logos/openclaw.svg +60 -0
- package/scripts/build-hermes-image.sh +21 -0
- package/scripts/build-local.sh +54 -0
- package/scripts/check-adapter-isolation.ts +293 -0
- package/scripts/fixtures/instances/hermes-sample/instance.json +37 -0
- package/scripts/fixtures/instances/legacy-openclaw-sample/instance.json +7 -0
- package/scripts/smoke/hermes-bootstrap.sh +195 -0
- package/templates/hermes-entrypoint.sh +154 -0
- package/dist/doctor.js.map +0 -1
- package/install/jishu-install-china.sh +0 -3092
- package/public/assets/Dashboard-DhsrzJ4F.js +0 -1
- package/public/assets/InitPassword-BjubiVdd.js +0 -1
- package/public/assets/InstanceDetail-DMcywsof.js +0 -17
- package/public/assets/NewInstance-Bk0G4EiJ.js +0 -1
- package/public/assets/Settings-D5tHL_h5.js +0 -1
- package/public/assets/Setup-4t6E3Rut.js +0 -1
- package/public/assets/index-BJ47MWpF.css +0 -1
- package/public/assets/index-DbX85irc.js +0 -16
- 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"}
|
package/dist/routes/setup.js
CHANGED
|
@@ -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
|
-
|
|
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:
|
|
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
|
}
|
package/dist/routes/setup.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"setup.js","sourceRoot":"","sources":["../../src/routes/setup.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,YAAY,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AAC/
|
|
1
|
+
{"version":3,"file":"setup.js","sourceRoot":"","sources":["../../src/routes/setup.ts"],"names":[],"mappings":"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"}
|
package/dist/routes/system.js
CHANGED
|
@@ -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/
|
|
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,
|
|
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
|
|
50
|
-
|
|
51
|
-
|
|
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/
|
|
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":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAChC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AACrC,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;
|
|
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/
|
|
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
|
-
|
|
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
|
|
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(
|
|
223
|
-
console.log(`[server] Rebound to http://${newHost}:${
|
|
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:
|
|
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
|
};
|