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.
- package/apps/anythingllm-container.yaml +16 -170
- package/apps/browserless-chromium-container.yaml +16 -10
- package/apps/filebrowser-container.yaml +15 -9
- package/apps/hermes-container.yaml +20 -5
- package/apps/immich-container-lite.yaml +337 -0
- package/apps/immich-container.yaml +371 -0
- package/apps/jishu-kb-container.yaml +50 -177
- package/apps/ollama-binary.yaml +33 -28
- package/apps/ollama-cpu-container.yaml +6 -0
- package/apps/ollama-with-hollama-binary.yaml +35 -28
- package/apps/openclaw-binary.yaml +35 -15
- package/apps/openclaw-container.yaml +29 -11
- package/apps/openclaw-with-ollama-container.yaml +9 -2
- package/apps/openclaw-with-searxng-container.yaml +38 -6
- package/apps/searxng-container.yaml +31 -6
- package/apps/weknora-container.yaml +26 -21
- package/dependencies/jishushell-panel-0.7.3.tgz +0 -0
- package/dist/cli/app.js +244 -213
- package/dist/cli/app.js.map +1 -1
- package/dist/cli/backup.js +15 -12
- package/dist/cli/backup.js.map +1 -1
- package/dist/cli/core.d.ts +4 -3
- package/dist/cli/core.js +392 -227
- package/dist/cli/core.js.map +1 -1
- package/dist/cli/doctor.d.ts +1 -1
- package/dist/cli/doctor.js +113 -10
- package/dist/cli/doctor.js.map +1 -1
- package/dist/cli/job.js +62 -14
- package/dist/cli/job.js.map +1 -1
- package/dist/cli/llm.js +80 -11
- package/dist/cli/llm.js.map +1 -1
- package/dist/cli/managed-list.d.ts +1 -3
- package/dist/cli/managed-list.js +18 -16
- package/dist/cli/managed-list.js.map +1 -1
- package/dist/cli/migrate.d.ts +2 -0
- package/dist/cli/migrate.js +160 -0
- package/dist/cli/migrate.js.map +1 -0
- package/dist/cli.js +1 -0
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +32 -20
- package/dist/config.js +132 -51
- package/dist/config.js.map +1 -1
- package/dist/control.d.ts +6 -6
- package/dist/control.js +31 -23
- package/dist/control.js.map +1 -1
- package/dist/core.d.ts +5 -5
- package/dist/core.js +5 -5
- package/dist/core.js.map +1 -1
- package/dist/install.d.ts +2 -2
- package/dist/install.js +78 -37
- package/dist/install.js.map +1 -1
- package/dist/routes/admin.d.ts +2 -0
- package/dist/routes/admin.js +72 -0
- package/dist/routes/admin.js.map +1 -0
- package/dist/routes/apps.d.ts +1 -1
- package/dist/routes/apps.js +101 -193
- package/dist/routes/apps.js.map +1 -1
- package/dist/routes/auth.js +1 -1
- package/dist/routes/auth.js.map +1 -1
- package/dist/routes/backup.js +1 -1
- package/dist/routes/backup.js.map +1 -1
- package/dist/routes/docker.d.ts +2 -0
- package/dist/routes/docker.js +58 -0
- package/dist/routes/docker.js.map +1 -0
- package/dist/routes/external-mounts.d.ts +1 -1
- package/dist/routes/external-mounts.js +1 -1
- package/dist/routes/external-mounts.js.map +1 -1
- package/dist/routes/file-mounts.d.ts +4 -3
- package/dist/routes/file-mounts.js +49 -31
- package/dist/routes/file-mounts.js.map +1 -1
- package/dist/routes/files-organize.d.ts +2 -2
- package/dist/routes/files-organize.js +5 -5
- package/dist/routes/files-organize.js.map +1 -1
- package/dist/routes/files.d.ts +1 -1
- package/dist/routes/files.js +1 -1
- package/dist/routes/files.js.map +1 -1
- package/dist/routes/instances.d.ts +0 -8
- package/dist/routes/instances.js +202 -1560
- package/dist/routes/instances.js.map +1 -1
- package/dist/routes/integration-apps.d.ts +14 -0
- package/dist/routes/integration-apps.js +81 -0
- package/dist/routes/integration-apps.js.map +1 -0
- package/dist/routes/integrations.d.ts +9 -0
- package/dist/routes/integrations.js +12 -0
- package/dist/routes/integrations.js.map +1 -0
- package/dist/routes/llm-proxy.js +26 -3
- package/dist/routes/llm-proxy.js.map +1 -1
- package/dist/routes/setup.js +53 -38
- package/dist/routes/setup.js.map +1 -1
- package/dist/routes/system.js +108 -68
- package/dist/routes/system.js.map +1 -1
- package/dist/routes/webdav.d.ts +1 -1
- package/dist/routes/webdav.js +2 -2
- package/dist/routes/webdav.js.map +1 -1
- package/dist/server.d.ts +6 -0
- package/dist/server.js +368 -233
- package/dist/server.js.map +1 -1
- package/dist/services/app-common/app-compiler.js +186 -0
- package/dist/services/app-common/app-compiler.js.map +1 -0
- package/dist/services/app-common/app-shared.d.ts +15 -0
- package/dist/services/app-common/app-shared.js +64 -0
- package/dist/services/app-common/app-shared.js.map +1 -0
- package/dist/services/app-common/capability-service.d.ts +45 -0
- package/dist/services/app-common/capability-service.js +331 -0
- package/dist/services/app-common/capability-service.js.map +1 -0
- package/dist/services/app-common/catalog-service.d.ts +59 -0
- package/dist/services/app-common/catalog-service.js +318 -0
- package/dist/services/app-common/catalog-service.js.map +1 -0
- package/dist/services/app-common/create-pipeline.d.ts +26 -0
- package/dist/services/app-common/create-pipeline.js +298 -0
- package/dist/services/app-common/create-pipeline.js.map +1 -0
- package/dist/services/app-common/delete-service.d.ts +5 -0
- package/dist/services/app-common/delete-service.js +109 -0
- package/dist/services/app-common/delete-service.js.map +1 -0
- package/dist/services/app-common/execution-owner.d.ts +23 -0
- package/dist/services/app-common/execution-owner.js +124 -0
- package/dist/services/app-common/execution-owner.js.map +1 -0
- package/dist/services/app-common/execution-service.d.ts +23 -0
- package/dist/services/app-common/execution-service.js +105 -0
- package/dist/services/app-common/execution-service.js.map +1 -0
- package/dist/services/app-common/id-normalizer.d.ts +31 -0
- package/dist/services/app-common/id-normalizer.js +83 -0
- package/dist/services/app-common/id-normalizer.js.map +1 -0
- package/dist/services/app-common/install-store.d.ts +34 -0
- package/dist/services/app-common/install-store.js +261 -0
- package/dist/services/app-common/install-store.js.map +1 -0
- package/dist/services/app-common/instance-store.d.ts +78 -0
- package/dist/services/app-common/instance-store.js +498 -0
- package/dist/services/app-common/instance-store.js.map +1 -0
- package/dist/services/app-common/integration-refs.d.ts +17 -0
- package/dist/services/app-common/integration-refs.js +47 -0
- package/dist/services/app-common/integration-refs.js.map +1 -0
- package/dist/services/app-common/lifecycle-pipeline.d.ts +62 -0
- package/dist/services/app-common/lifecycle-pipeline.js +317 -0
- package/dist/services/app-common/lifecycle-pipeline.js.map +1 -0
- package/dist/services/app-common/lifecycle-scripts.d.ts +38 -0
- package/dist/services/app-common/lifecycle-scripts.js +935 -0
- package/dist/services/app-common/lifecycle-scripts.js.map +1 -0
- package/dist/services/app-common/lifecycle-service.d.ts +68 -0
- package/dist/services/app-common/lifecycle-service.js +475 -0
- package/dist/services/app-common/lifecycle-service.js.map +1 -0
- package/dist/services/app-common/ownership.d.ts +3 -0
- package/dist/services/app-common/ownership.js +11 -0
- package/dist/services/app-common/ownership.js.map +1 -0
- package/dist/services/app-common/paths.d.ts +29 -0
- package/dist/services/app-common/paths.js +34 -0
- package/dist/services/app-common/paths.js.map +1 -0
- package/dist/services/app-common/platform-transform.d.ts +32 -0
- package/dist/services/app-common/platform-transform.js +65 -0
- package/dist/services/app-common/platform-transform.js.map +1 -0
- package/dist/services/app-common/provide-resolver.d.ts +29 -0
- package/dist/services/app-common/provide-resolver.js +129 -0
- package/dist/services/app-common/provide-resolver.js.map +1 -0
- package/dist/services/app-common/remote-spec.d.ts +14 -0
- package/dist/services/app-common/remote-spec.js +58 -0
- package/dist/services/app-common/remote-spec.js.map +1 -0
- package/dist/services/app-common/runtime-builder.d.ts +1 -0
- package/dist/services/app-common/runtime-builder.js +2 -0
- package/dist/services/app-common/runtime-builder.js.map +1 -0
- package/dist/services/app-common/runtime-facts.d.ts +19 -0
- package/dist/services/app-common/runtime-facts.js +128 -0
- package/dist/services/app-common/runtime-facts.js.map +1 -0
- package/dist/services/app-common/service.d.ts +9 -0
- package/dist/services/app-common/service.js +10 -0
- package/dist/services/app-common/service.js.map +1 -0
- package/dist/services/app-common/spec-materializer.d.ts +8 -0
- package/dist/services/app-common/spec-materializer.js +295 -0
- package/dist/services/app-common/spec-materializer.js.map +1 -0
- package/dist/services/app-common/status-refresh.d.ts +33 -0
- package/dist/services/app-common/status-refresh.js +771 -0
- package/dist/services/app-common/status-refresh.js.map +1 -0
- package/dist/services/app-common/task-service.d.ts +29 -0
- package/dist/services/app-common/task-service.js +93 -0
- package/dist/services/app-common/task-service.js.map +1 -0
- package/dist/services/app-common/terminal-session-manager.js +157 -0
- package/dist/services/app-common/terminal-session-manager.js.map +1 -0
- package/dist/services/app-modules/browserless/routes.d.ts +9 -0
- package/dist/services/app-modules/browserless/routes.js +519 -0
- package/dist/services/app-modules/browserless/routes.js.map +1 -0
- package/dist/services/app-modules/routes.d.ts +2 -0
- package/dist/services/app-modules/routes.js +5 -0
- package/dist/services/app-modules/routes.js.map +1 -0
- package/dist/services/backup/backup-admin.d.ts +95 -0
- package/dist/services/backup/backup-admin.js +246 -0
- package/dist/services/backup/backup-admin.js.map +1 -0
- package/dist/services/backup/backup-manager.d.ts +264 -0
- package/dist/services/backup/backup-manager.js +2318 -0
- package/dist/services/backup/backup-manager.js.map +1 -0
- package/dist/services/backup/backup-verify.js +240 -0
- package/dist/services/backup/backup-verify.js.map +1 -0
- package/dist/services/capabilities/browser-policy.d.ts +14 -0
- package/dist/services/capabilities/browser-policy.js +141 -0
- package/dist/services/capabilities/browser-policy.js.map +1 -0
- package/dist/services/capabilities/contract.d.ts +49 -0
- package/dist/services/capabilities/contract.js +119 -0
- package/dist/services/capabilities/contract.js.map +1 -0
- package/dist/services/capabilities/endpoint-validator.d.ts +42 -0
- package/dist/services/capabilities/endpoint-validator.js +113 -0
- package/dist/services/capabilities/endpoint-validator.js.map +1 -0
- package/dist/services/capabilities/health.d.ts +16 -0
- package/dist/services/capabilities/health.js +121 -0
- package/dist/services/capabilities/health.js.map +1 -0
- package/dist/services/capabilities/registry.d.ts +56 -0
- package/dist/services/capabilities/registry.js +222 -0
- package/dist/services/capabilities/registry.js.map +1 -0
- package/dist/services/capabilities/sync.d.ts +7 -0
- package/dist/services/capabilities/sync.js +223 -0
- package/dist/services/capabilities/sync.js.map +1 -0
- package/dist/services/capability-proxy/html-rewriters/browserless.d.ts +1 -0
- package/dist/services/capability-proxy/html-rewriters/browserless.js +83 -0
- package/dist/services/capability-proxy/html-rewriters/browserless.js.map +1 -0
- package/dist/services/capability-proxy/html-rewriters/index.d.ts +12 -0
- package/dist/services/capability-proxy/html-rewriters/index.js +25 -0
- package/dist/services/capability-proxy/html-rewriters/index.js.map +1 -0
- package/dist/services/capability-proxy/html-rewriters/jishukb.d.ts +1 -0
- package/dist/services/capability-proxy/html-rewriters/jishukb.js +161 -0
- package/dist/services/capability-proxy/html-rewriters/jishukb.js.map +1 -0
- package/dist/services/capability-proxy/http.d.ts +7 -0
- package/dist/services/capability-proxy/http.js +555 -0
- package/dist/services/capability-proxy/http.js.map +1 -0
- package/dist/services/capability-proxy/terminal.d.ts +4 -0
- package/dist/services/capability-proxy/terminal.js +179 -0
- package/dist/services/capability-proxy/terminal.js.map +1 -0
- package/dist/services/connections/admin.d.ts +80 -0
- package/dist/services/connections/admin.js +337 -0
- package/dist/services/connections/admin.js.map +1 -0
- package/dist/services/connections/apply.d.ts +104 -0
- package/dist/services/connections/apply.js +415 -0
- package/dist/services/connections/apply.js.map +1 -0
- package/dist/services/connections/resolver.d.ts +82 -0
- package/dist/services/connections/resolver.js +289 -0
- package/dist/services/connections/resolver.js.map +1 -0
- package/dist/services/connections/transactor.d.ts +39 -0
- package/dist/services/connections/transactor.js +307 -0
- package/dist/services/connections/transactor.js.map +1 -0
- package/dist/services/files/bootstrap.d.ts +7 -0
- package/dist/services/files/bootstrap.js +16 -0
- package/dist/services/files/bootstrap.js.map +1 -0
- package/dist/services/files/external-mounts.js +187 -0
- package/dist/services/files/external-mounts.js.map +1 -0
- package/dist/services/files/files-manager.d.ts +265 -0
- package/dist/services/files/files-manager.js +1189 -0
- package/dist/services/files/files-manager.js.map +1 -0
- package/dist/services/files/files-mounts.d.ts +42 -0
- package/dist/services/files/files-mounts.js +207 -0
- package/dist/services/files/files-mounts.js.map +1 -0
- package/dist/services/files/organize/applier.js +218 -0
- package/dist/services/files/organize/applier.js.map +1 -0
- package/dist/services/files/organize/rules.js +286 -0
- package/dist/services/files/organize/rules.js.map +1 -0
- package/dist/services/files/organize/scanner.js +366 -0
- package/dist/services/files/organize/scanner.js.map +1 -0
- package/dist/services/files/organize/store.js +82 -0
- package/dist/services/files/organize/store.js.map +1 -0
- package/dist/services/files/photos/upload-page.d.ts +2 -0
- package/dist/services/files/photos/upload-page.js +248 -0
- package/dist/services/files/photos/upload-page.js.map +1 -0
- package/dist/services/files/photos/upload-store.d.ts +74 -0
- package/dist/services/files/photos/upload-store.js +432 -0
- package/dist/services/files/photos/upload-store.js.map +1 -0
- package/dist/services/files/webdav/server.d.ts +47 -0
- package/dist/services/files/webdav/server.js +329 -0
- package/dist/services/files/webdav/server.js.map +1 -0
- package/dist/services/files/webdav/xml-builder.js.map +1 -0
- package/dist/services/http/proxy-utils.d.ts +7 -0
- package/dist/services/http/proxy-utils.js +29 -0
- package/dist/services/http/proxy-utils.js.map +1 -0
- package/dist/services/http/request-utils.d.ts +3 -0
- package/dist/services/http/request-utils.js +23 -0
- package/dist/services/http/request-utils.js.map +1 -0
- package/dist/services/instances/admin.d.ts +23 -0
- package/dist/services/instances/admin.js +218 -0
- package/dist/services/instances/admin.js.map +1 -0
- package/dist/services/instances/clone.d.ts +26 -0
- package/dist/services/instances/clone.js +78 -0
- package/dist/services/instances/clone.js.map +1 -0
- package/dist/services/instances/config-admin.d.ts +17 -0
- package/dist/services/instances/config-admin.js +181 -0
- package/dist/services/instances/config-admin.js.map +1 -0
- package/dist/services/instances/manager.d.ts +232 -0
- package/dist/services/instances/manager.js +1342 -0
- package/dist/services/instances/manager.js.map +1 -0
- package/dist/services/instances/pairing.d.ts +17 -0
- package/dist/services/instances/pairing.js +53 -0
- package/dist/services/instances/pairing.js.map +1 -0
- package/dist/services/instances/passwords.js +173 -0
- package/dist/services/instances/passwords.js.map +1 -0
- package/dist/services/instances/status.d.ts +2 -0
- package/dist/services/instances/status.js +11 -0
- package/dist/services/instances/status.js.map +1 -0
- package/dist/services/instances/types.d.ts +21 -0
- package/dist/services/instances/types.js +2 -0
- package/dist/services/instances/types.js.map +1 -0
- package/dist/services/integrations/anythingllm/integration.d.ts +25 -0
- package/dist/services/integrations/anythingllm/integration.js +251 -0
- package/dist/services/integrations/anythingllm/integration.js.map +1 -0
- package/dist/services/integrations/catalog.d.ts +3 -0
- package/dist/services/integrations/catalog.js +73 -0
- package/dist/services/integrations/catalog.js.map +1 -0
- package/dist/services/integrations/custom/integration.d.ts +28 -0
- package/dist/services/integrations/custom/integration.js +179 -0
- package/dist/services/integrations/custom/integration.js.map +1 -0
- package/dist/services/integrations/hermes/integration.d.ts +194 -0
- package/dist/services/integrations/hermes/integration.js +1668 -0
- package/dist/services/integrations/hermes/integration.js.map +1 -0
- package/dist/services/integrations/immich/client.d.ts +93 -0
- package/dist/services/integrations/immich/client.js +458 -0
- package/dist/services/integrations/immich/client.js.map +1 -0
- package/dist/services/integrations/immich/config.d.ts +15 -0
- package/dist/services/integrations/immich/config.js +178 -0
- package/dist/services/integrations/immich/config.js.map +1 -0
- package/dist/services/integrations/immich/discovery.d.ts +9 -0
- package/dist/services/integrations/immich/discovery.js +101 -0
- package/dist/services/integrations/immich/discovery.js.map +1 -0
- package/dist/services/integrations/immich/gallery-renderer.d.ts +5 -0
- package/dist/services/integrations/immich/gallery-renderer.js +150 -0
- package/dist/services/integrations/immich/gallery-renderer.js.map +1 -0
- package/dist/services/integrations/immich/immich-shim.d.ts +11 -0
- package/dist/services/integrations/immich/immich-shim.js +439 -0
- package/dist/services/integrations/immich/immich-shim.js.map +1 -0
- package/dist/services/integrations/immich/integration.d.ts +18 -0
- package/dist/services/integrations/immich/integration.js +64 -0
- package/dist/services/integrations/immich/integration.js.map +1 -0
- package/dist/services/integrations/immich/photo-library.d.ts +4 -0
- package/dist/services/integrations/immich/photo-library.js +63 -0
- package/dist/services/integrations/immich/photo-library.js.map +1 -0
- package/dist/services/integrations/immich/review-executor.d.ts +3 -0
- package/dist/services/integrations/immich/review-executor.js +41 -0
- package/dist/services/integrations/immich/review-executor.js.map +1 -0
- package/dist/services/integrations/immich/review-session-service.d.ts +27 -0
- package/dist/services/integrations/immich/review-session-service.js +206 -0
- package/dist/services/integrations/immich/review-session-service.js.map +1 -0
- package/dist/services/integrations/immich/review-store.d.ts +47 -0
- package/dist/services/integrations/immich/review-store.js +347 -0
- package/dist/services/integrations/immich/review-store.js.map +1 -0
- package/dist/services/integrations/immich/routes.d.ts +7 -0
- package/dist/services/integrations/immich/routes.js +363 -0
- package/dist/services/integrations/immich/routes.js.map +1 -0
- package/dist/services/integrations/immich/types.d.ts +186 -0
- package/dist/services/integrations/immich/types.js +2 -0
- package/dist/services/integrations/immich/types.js.map +1 -0
- package/dist/services/integrations/index.d.ts +41 -0
- package/dist/services/integrations/index.js +60 -0
- package/dist/services/integrations/index.js.map +1 -0
- package/dist/services/integrations/installable/catalog.d.ts +33 -0
- package/dist/services/integrations/installable/catalog.js +88 -0
- package/dist/services/integrations/installable/catalog.js.map +1 -0
- package/dist/services/integrations/installable/index.d.ts +35 -0
- package/dist/services/integrations/installable/index.js +170 -0
- package/dist/services/integrations/installable/index.js.map +1 -0
- package/dist/services/integrations/installable/installers/integration-probes.d.ts +50 -0
- package/dist/services/integrations/installable/installers/integration-probes.js +231 -0
- package/dist/services/integrations/installable/installers/integration-probes.js.map +1 -0
- package/dist/services/integrations/installable/installers/integration.d.ts +30 -0
- package/dist/services/integrations/installable/installers/integration.js +283 -0
- package/dist/services/integrations/installable/installers/integration.js.map +1 -0
- package/dist/services/integrations/installable/installers/registry-probe.js.map +1 -0
- package/dist/services/integrations/installable/installers/shell-script.d.ts +46 -0
- package/dist/services/integrations/installable/installers/shell-script.js +487 -0
- package/dist/services/integrations/installable/installers/shell-script.js.map +1 -0
- package/dist/services/integrations/installable/types.d.ts +130 -0
- package/dist/services/integrations/installable/types.js +19 -0
- package/dist/services/integrations/installable/types.js.map +1 -0
- package/dist/services/integrations/jishukb/integration.d.ts +24 -0
- package/dist/services/integrations/jishukb/integration.js +300 -0
- package/dist/services/integrations/jishukb/integration.js.map +1 -0
- package/dist/services/integrations/openclaw/anythingllm-shim.d.ts +46 -0
- package/dist/services/integrations/openclaw/anythingllm-shim.js +281 -0
- package/dist/services/integrations/openclaw/anythingllm-shim.js.map +1 -0
- package/dist/services/integrations/openclaw/drive-shim.js +490 -0
- package/dist/services/integrations/openclaw/drive-shim.js.map +1 -0
- package/dist/services/integrations/openclaw/integration.d.ts +438 -0
- package/dist/services/integrations/openclaw/integration.js +4629 -0
- package/dist/services/integrations/openclaw/integration.js.map +1 -0
- package/dist/services/integrations/openclaw/jishukb-native-mcp.d.ts +58 -0
- package/dist/services/integrations/openclaw/jishukb-native-mcp.js +373 -0
- package/dist/services/integrations/openclaw/jishukb-native-mcp.js.map +1 -0
- package/dist/services/integrations/openclaw/jishukb-shim.d.ts +52 -0
- package/dist/services/integrations/openclaw/jishukb-shim.js +1357 -0
- package/dist/services/integrations/openclaw/jishukb-shim.js.map +1 -0
- package/dist/services/integrations/openclaw/mcporter-lite.js +276 -0
- package/dist/services/integrations/openclaw/mcporter-lite.js.map +1 -0
- package/dist/services/integrations/openclaw/mcporter.d.ts +59 -0
- package/dist/services/integrations/openclaw/mcporter.js +143 -0
- package/dist/services/integrations/openclaw/mcporter.js.map +1 -0
- package/dist/services/integrations/openclaw/native-mcp.d.ts +48 -0
- package/dist/services/integrations/openclaw/native-mcp.js +125 -0
- package/dist/services/integrations/openclaw/native-mcp.js.map +1 -0
- package/dist/services/integrations/openclaw/routes.d.ts +21 -0
- package/dist/services/integrations/openclaw/routes.js +1194 -0
- package/dist/services/integrations/openclaw/routes.js.map +1 -0
- package/dist/services/integrations/registry.d.ts +17 -0
- package/dist/services/integrations/registry.js +36 -0
- package/dist/services/integrations/registry.js.map +1 -0
- package/dist/services/integrations/routes.d.ts +2 -0
- package/dist/services/integrations/routes.js +9 -0
- package/dist/services/integrations/routes.js.map +1 -0
- package/dist/services/integrations/types.d.ts +457 -0
- package/dist/services/integrations/types.js +2 -0
- package/dist/services/integrations/types.js.map +1 -0
- package/dist/services/legacy-migrator/classifier.d.ts +44 -0
- package/dist/services/legacy-migrator/classifier.js +309 -0
- package/dist/services/legacy-migrator/classifier.js.map +1 -0
- package/dist/services/legacy-migrator/executor.d.ts +42 -0
- package/dist/services/legacy-migrator/executor.js +637 -0
- package/dist/services/legacy-migrator/executor.js.map +1 -0
- package/dist/services/legacy-migrator/index.d.ts +31 -0
- package/dist/services/legacy-migrator/index.js +34 -0
- package/dist/services/legacy-migrator/index.js.map +1 -0
- package/dist/services/legacy-migrator/planner.d.ts +8 -0
- package/dist/services/legacy-migrator/planner.js +154 -0
- package/dist/services/legacy-migrator/planner.js.map +1 -0
- package/dist/services/legacy-migrator/provider-settings.d.ts +6 -0
- package/dist/services/legacy-migrator/provider-settings.js +72 -0
- package/dist/services/legacy-migrator/provider-settings.js.map +1 -0
- package/dist/services/legacy-migrator/report.d.ts +9 -0
- package/dist/services/legacy-migrator/report.js +99 -0
- package/dist/services/legacy-migrator/report.js.map +1 -0
- package/dist/services/legacy-migrator/scanner.d.ts +13 -0
- package/dist/services/legacy-migrator/scanner.js +157 -0
- package/dist/services/legacy-migrator/scanner.js.map +1 -0
- package/dist/services/legacy-migrator/types.d.ts +97 -0
- package/dist/services/legacy-migrator/types.js +23 -0
- package/dist/services/legacy-migrator/types.js.map +1 -0
- package/dist/services/llm-proxy/instance-proxy.d.ts +17 -1
- package/dist/services/llm-proxy/instance-proxy.js +171 -44
- package/dist/services/llm-proxy/instance-proxy.js.map +1 -1
- package/dist/services/llm-proxy/probe.js +5 -14
- package/dist/services/llm-proxy/probe.js.map +1 -1
- package/dist/services/llm-proxy/providers.js +23 -31
- package/dist/services/llm-proxy/providers.js.map +1 -1
- package/dist/services/llm-proxy/ssrf.d.ts +11 -4
- package/dist/services/llm-proxy/ssrf.js +45 -7
- package/dist/services/llm-proxy/ssrf.js.map +1 -1
- package/dist/services/llm-proxy/validate-key.js +16 -37
- package/dist/services/llm-proxy/validate-key.js.map +1 -1
- package/dist/services/repair/runtime-repair.d.ts +22 -0
- package/dist/services/repair/runtime-repair.js +374 -0
- package/dist/services/repair/runtime-repair.js.map +1 -0
- package/dist/services/runtime/docker-network.d.ts +8 -0
- package/dist/services/runtime/docker-network.js +123 -0
- package/dist/services/runtime/docker-network.js.map +1 -0
- package/dist/services/runtime/driver-registry.d.ts +25 -0
- package/dist/services/runtime/driver-registry.js +22 -0
- package/dist/services/runtime/driver-registry.js.map +1 -0
- package/dist/services/runtime/drivers/nomad.d.ts +261 -0
- package/dist/services/runtime/drivers/nomad.js +3122 -0
- package/dist/services/runtime/drivers/nomad.js.map +1 -0
- package/dist/services/runtime/errors.d.ts +3 -3
- package/dist/services/runtime/errors.js +3 -3
- package/dist/services/runtime/instance.d.ts +14 -16
- package/dist/services/runtime/instance.js +93 -123
- package/dist/services/runtime/instance.js.map +1 -1
- package/dist/services/runtime/job-id.d.ts +1 -1
- package/dist/services/runtime/job-id.js +1 -1
- package/dist/services/runtime/mcp-shims/firewall.d.ts +2 -2
- package/dist/services/runtime/mcp-shims/firewall.js +2 -2
- package/dist/services/runtime/mcp-shims/searxng-shim.d.ts +3 -5
- package/dist/services/runtime/mcp-shims/searxng-shim.js +3 -5
- package/dist/services/runtime/mcp-shims/searxng-shim.js.map +1 -1
- package/dist/services/runtime/mcp-shims/write-mcp-entry.d.ts +20 -20
- package/dist/services/runtime/mcp-shims/write-mcp-entry.js +16 -16
- package/dist/services/runtime/mcp-shims/write-mcp-entry.js.map +1 -1
- package/dist/services/runtime/ownership-marker.d.ts +83 -0
- package/dist/services/runtime/ownership-marker.js +109 -0
- package/dist/services/runtime/ownership-marker.js.map +1 -0
- package/dist/services/runtime/service-manager.d.ts +2 -0
- package/dist/services/runtime/service-manager.js +18 -0
- package/dist/services/runtime/service-manager.js.map +1 -0
- package/dist/services/runtime/types.d.ts +23 -501
- package/dist/services/runtime/types.js +0 -12
- package/dist/services/runtime/types.js.map +1 -1
- package/dist/services/runtime/workload-compiler.d.ts +17 -0
- package/dist/services/runtime/workload-compiler.js +550 -0
- package/dist/services/runtime/workload-compiler.js.map +1 -0
- package/dist/services/runtime/workload-types.d.ts +11 -0
- package/dist/services/runtime/workload-types.js +2 -0
- package/dist/services/runtime/workload-types.js.map +1 -0
- package/dist/services/setup/core-manager.d.ts +50 -0
- package/dist/services/setup/core-manager.js +456 -0
- package/dist/services/setup/core-manager.js.map +1 -0
- package/dist/services/setup/plugin-installer.js +136 -0
- package/dist/services/setup/plugin-installer.js.map +1 -0
- package/dist/services/setup/setup-manager.d.ts +158 -0
- package/dist/services/setup/setup-manager.js +2724 -0
- package/dist/services/setup/setup-manager.js.map +1 -0
- package/dist/services/system/cli-command.d.ts +5 -0
- package/dist/services/system/cli-command.js +18 -0
- package/dist/services/system/cli-command.js.map +1 -0
- package/dist/services/system/macos-launchd.js +312 -0
- package/dist/services/system/macos-launchd.js.map +1 -0
- package/dist/services/system/repair-orchestrator.d.ts +71 -0
- package/dist/services/system/repair-orchestrator.js +412 -0
- package/dist/services/system/repair-orchestrator.js.map +1 -0
- package/dist/services/system/runtime-ownership.d.ts +36 -0
- package/dist/services/system/runtime-ownership.js +250 -0
- package/dist/services/system/runtime-ownership.js.map +1 -0
- package/dist/services/system/system-monitor.js +96 -0
- package/dist/services/system/system-monitor.js.map +1 -0
- package/dist/services/system/system-ollama-provider.d.ts +14 -0
- package/dist/services/system/system-ollama-provider.js +129 -0
- package/dist/services/system/system-ollama-provider.js.map +1 -0
- package/dist/services/system/system-reconciler.d.ts +59 -0
- package/dist/services/system/system-reconciler.js +763 -0
- package/dist/services/system/system-reconciler.js.map +1 -0
- package/dist/services/system/update-manager.d.ts +43 -0
- package/dist/services/system/update-manager.js +315 -0
- package/dist/services/system/update-manager.js.map +1 -0
- package/dist/services/system/upgrade-finalize.d.ts +80 -0
- package/dist/services/system/upgrade-finalize.js +507 -0
- package/dist/services/system/upgrade-finalize.js.map +1 -0
- package/dist/services/tasks/registry.d.ts +44 -0
- package/dist/services/tasks/registry.js +90 -0
- package/dist/services/tasks/registry.js.map +1 -0
- package/dist/services/telemetry/activation.d.ts +6 -2
- package/dist/services/telemetry/activation.js +6 -2
- package/dist/services/telemetry/activation.js.map +1 -1
- package/dist/services/telemetry/heartbeat.d.ts +6 -2
- package/dist/services/telemetry/heartbeat.js +6 -2
- package/dist/services/telemetry/heartbeat.js.map +1 -1
- package/dist/services/workspaces/builder.d.ts +29 -0
- package/dist/services/workspaces/builder.js +186 -0
- package/dist/services/workspaces/builder.js.map +1 -0
- package/dist/types.d.ts +350 -48
- package/dist/utils/instance-lock.d.ts +2 -2
- package/dist/utils/instance-lock.js +2 -2
- package/dist/utils/path-safety.js +1 -1
- package/dist/utils/service-user.d.ts +13 -0
- package/dist/utils/service-user.js +129 -0
- package/dist/utils/service-user.js.map +1 -0
- package/install/jishu-install.sh +107 -27
- package/install/jishu-uninstall.sh +8 -0
- package/install/post-install.sh +162 -185
- package/install/post-uninstall.sh +6 -0
- package/node_modules/@fastify/static/.github/workflows/ci.yml +1 -1
- package/node_modules/@fastify/static/.github/workflows/lock-threads.yml +19 -0
- package/node_modules/@fastify/static/LICENSE +1 -3
- package/node_modules/@fastify/static/example/server-benchmark.js +39 -0
- package/node_modules/@fastify/static/index.js +169 -23
- package/node_modules/@fastify/static/lib/dirList.js +20 -6
- package/node_modules/@fastify/static/package.json +10 -8
- package/node_modules/@fastify/static/test/dir-list.test.js +82 -0
- package/node_modules/@fastify/static/test/static.test.js +326 -4
- package/node_modules/@fastify/static/types/index.d.ts +0 -4
- package/node_modules/@fastify/static/types/index.test-d.ts +1 -1
- package/node_modules/brace-expansion/dist/commonjs/index.js +24 -14
- package/node_modules/brace-expansion/dist/commonjs/index.js.map +1 -1
- package/node_modules/brace-expansion/dist/esm/index.js +24 -14
- package/node_modules/brace-expansion/dist/esm/index.js.map +1 -1
- package/node_modules/brace-expansion/package.json +2 -2
- package/node_modules/content-disposition/README.md +21 -22
- package/node_modules/content-disposition/index.js +122 -44
- package/node_modules/content-disposition/package.json +16 -20
- package/node_modules/fast-uri/index.js +1 -1
- package/node_modules/fast-uri/package.json +1 -1
- package/node_modules/fast-uri/test/security.test.js +28 -0
- package/node_modules/fastify/SECURITY.md +1 -1
- package/node_modules/fastify/SPONSORS.md +6 -4
- package/node_modules/fastify/docs/Guides/Database.md +0 -28
- package/node_modules/fastify/docs/Guides/Ecosystem.md +13 -2
- package/node_modules/fastify/docs/Guides/Serverless.md +2 -2
- package/node_modules/fastify/docs/Guides/Write-Plugin.md +1 -1
- package/node_modules/fastify/docs/Reference/Encapsulation.md +27 -26
- package/node_modules/fastify/docs/Reference/Errors.md +10 -4
- package/node_modules/fastify/docs/Reference/HTTP2.md +10 -10
- package/node_modules/fastify/docs/Reference/Hooks.md +4 -4
- package/node_modules/fastify/docs/Reference/Index.md +14 -16
- package/node_modules/fastify/docs/Reference/LTS.md +12 -13
- package/node_modules/fastify/docs/Reference/Lifecycle.md +9 -8
- package/node_modules/fastify/docs/Reference/Logging.md +44 -39
- package/node_modules/fastify/docs/Reference/Middleware.md +21 -25
- package/node_modules/fastify/docs/Reference/Principles.md +2 -2
- package/node_modules/fastify/docs/Reference/Reply.md +6 -1
- package/node_modules/fastify/docs/Reference/Request.md +27 -16
- package/node_modules/fastify/docs/Reference/Routes.md +5 -2
- package/node_modules/fastify/docs/Reference/Server.md +31 -3
- package/node_modules/fastify/docs/Reference/Type-Providers.md +29 -5
- package/node_modules/fastify/docs/Reference/Validation-and-Serialization.md +15 -2
- package/node_modules/fastify/docs/Reference/Warnings.md +7 -6
- package/node_modules/fastify/eslint.config.js +7 -2
- package/node_modules/fastify/fastify.d.ts +8 -3
- package/node_modules/fastify/fastify.js +43 -14
- package/node_modules/fastify/lib/content-type-parser.js +13 -1
- package/node_modules/fastify/lib/decorate.js +11 -3
- package/node_modules/fastify/lib/error-handler.js +4 -3
- package/node_modules/fastify/lib/error-serializer.js +59 -59
- package/node_modules/fastify/lib/errors.js +16 -1
- package/node_modules/fastify/lib/four-oh-four.js +14 -9
- package/node_modules/fastify/lib/handle-request.js +11 -5
- package/node_modules/fastify/lib/plugin-override.js +2 -1
- package/node_modules/fastify/lib/plugin-utils.js +5 -5
- package/node_modules/fastify/lib/reply.js +63 -8
- package/node_modules/fastify/lib/request.js +14 -4
- package/node_modules/fastify/lib/route.js +20 -6
- package/node_modules/fastify/lib/schema-controller.js +1 -1
- package/node_modules/fastify/lib/schemas.js +37 -30
- package/node_modules/fastify/lib/symbols.js +3 -1
- package/node_modules/fastify/lib/validation.js +1 -13
- package/node_modules/fastify/lib/warnings.js +3 -3
- package/node_modules/fastify/package.json +13 -15
- package/node_modules/fastify/scripts/validate-ecosystem-links.js +1 -0
- package/node_modules/fastify/test/bundler/esbuild/package.json +1 -1
- package/node_modules/fastify/test/close-pipelining.test.js +1 -2
- package/node_modules/fastify/test/custom-http-server.test.js +38 -0
- package/node_modules/fastify/test/decorator-instance-properties.test.js +63 -0
- package/node_modules/fastify/test/diagnostics-channel/async-error-handler.test.js +74 -0
- package/node_modules/fastify/test/hooks.test.js +23 -0
- package/node_modules/fastify/test/http-methods/get.test.js +1 -1
- package/node_modules/fastify/test/http2/plain.test.js +135 -0
- package/node_modules/fastify/test/http2/secure-with-fallback.test.js +1 -1
- package/node_modules/fastify/test/https/https.test.js +1 -2
- package/node_modules/fastify/test/internals/errors.test.js +31 -1
- package/node_modules/fastify/test/internals/plugin.test.js +3 -1
- package/node_modules/fastify/test/internals/request.test.js +27 -3
- package/node_modules/fastify/test/internals/schema-controller-perf.test.js +33 -0
- package/node_modules/fastify/test/logger/logging.test.js +18 -1
- package/node_modules/fastify/test/logger/options.test.js +38 -1
- package/node_modules/fastify/test/reply-error.test.js +1 -1
- package/node_modules/fastify/test/reply-trailers.test.js +70 -0
- package/node_modules/fastify/test/request-media-type.test.js +105 -0
- package/node_modules/fastify/test/route-prefix.test.js +34 -0
- package/node_modules/fastify/test/router-options.test.js +222 -11
- package/node_modules/fastify/test/schema-serialization.test.js +108 -0
- package/node_modules/fastify/test/schema-validation.test.js +24 -0
- package/node_modules/fastify/test/scripts/validate-ecosystem-links.test.js +40 -57
- package/node_modules/fastify/test/throw.test.js +14 -0
- package/node_modules/fastify/test/trust-proxy.test.js +21 -0
- package/node_modules/fastify/test/types/content-type-parser.tst.ts +70 -0
- package/node_modules/fastify/test/types/decorate-request-reply.tst.ts +18 -0
- package/node_modules/fastify/test/types/dummy-plugin.mts +9 -0
- package/node_modules/fastify/test/types/errors.tst.ts +91 -0
- package/node_modules/fastify/test/types/fastify.tst.ts +351 -0
- package/node_modules/fastify/test/types/hooks.tst.ts +578 -0
- package/node_modules/fastify/test/types/instance.tst.ts +597 -0
- package/node_modules/fastify/test/types/logger.tst.ts +276 -0
- package/node_modules/fastify/test/types/plugin.tst.ts +96 -0
- package/node_modules/fastify/test/types/register.tst.ts +245 -0
- package/node_modules/fastify/test/types/reply.tst.ts +297 -0
- package/node_modules/fastify/test/types/request.tst.ts +199 -0
- package/node_modules/fastify/test/types/route.tst.ts +576 -0
- package/node_modules/fastify/test/types/schema.tst.ts +135 -0
- package/node_modules/fastify/test/types/serverFactory.tst.ts +37 -0
- package/node_modules/fastify/test/types/tsconfig.json +9 -0
- package/node_modules/fastify/test/types/type-provider.tst.ts +1219 -0
- package/node_modules/fastify/test/types/using.tst.ts +14 -0
- package/node_modules/fastify/types/errors.d.ts +3 -0
- package/node_modules/fastify/types/request.d.ts +23 -2
- package/node_modules/glob/README.md +39 -130
- package/node_modules/glob/dist/commonjs/glob.d.ts +8 -0
- package/node_modules/glob/dist/commonjs/glob.d.ts.map +1 -1
- package/node_modules/glob/dist/commonjs/glob.js +2 -1
- package/node_modules/glob/dist/commonjs/glob.js.map +1 -1
- package/node_modules/glob/dist/commonjs/index.min.js +4 -0
- package/node_modules/glob/dist/commonjs/index.min.js.map +7 -0
- package/node_modules/glob/dist/commonjs/pattern.d.ts +3 -0
- package/node_modules/glob/dist/commonjs/pattern.d.ts.map +1 -1
- package/node_modules/glob/dist/commonjs/pattern.js +4 -0
- package/node_modules/glob/dist/commonjs/pattern.js.map +1 -1
- package/node_modules/glob/dist/esm/glob.d.ts +8 -0
- package/node_modules/glob/dist/esm/glob.d.ts.map +1 -1
- package/node_modules/glob/dist/esm/glob.js +2 -1
- package/node_modules/glob/dist/esm/glob.js.map +1 -1
- package/node_modules/glob/dist/esm/index.min.js +4 -0
- package/node_modules/glob/dist/esm/index.min.js.map +7 -0
- package/node_modules/glob/dist/esm/pattern.d.ts +3 -0
- package/node_modules/glob/dist/esm/pattern.d.ts.map +1 -1
- package/node_modules/glob/dist/esm/pattern.js +4 -0
- package/node_modules/glob/dist/esm/pattern.js.map +1 -1
- package/node_modules/glob/package.json +38 -37
- package/node_modules/jishushell-panel/README.md +4 -4
- package/node_modules/jishushell-panel/output/dist/server.js +17 -6
- package/node_modules/jishushell-panel/output/dist/server.js.map +1 -1
- package/node_modules/jishushell-panel/output/public/assets/ApiKeyField-Ce5d1xna.js +1 -0
- package/node_modules/jishushell-panel/output/public/assets/Dashboard-BXame3yg.js +1 -0
- package/node_modules/jishushell-panel/output/public/assets/HermesChatPanel-BHZtPCJd.js +1 -0
- package/node_modules/jishushell-panel/output/public/assets/HermesConfigForm-CB3GbNX9.js +4 -0
- package/node_modules/jishushell-panel/output/public/assets/InitPassword-Boab9F6g.js +1 -0
- package/node_modules/jishushell-panel/output/public/assets/InstanceDetail-DrIWCqo-.js +14 -0
- package/node_modules/jishushell-panel/output/public/assets/Login-CzpOkNau.js +1 -0
- package/node_modules/jishushell-panel/output/public/assets/NewInstance-CANXyCcL.js +1 -0
- package/node_modules/jishushell-panel/output/public/assets/ProviderRecommendations-BABo9VOC.js +1 -0
- package/node_modules/jishushell-panel/output/public/assets/Settings-CKp5XxFh.js +1 -0
- package/node_modules/jishushell-panel/output/public/assets/Setup-C7xVDPow.js +1 -0
- package/node_modules/jishushell-panel/output/public/assets/WeixinLoginPanel-B765Xz4C.js +1 -0
- package/node_modules/jishushell-panel/output/public/assets/api-C70Gt678.js +4 -0
- package/node_modules/jishushell-panel/output/public/assets/index-Bs6DSbiR.js +23 -0
- package/node_modules/jishushell-panel/output/public/assets/index-DnnqTf7s.css +1 -0
- package/node_modules/jishushell-panel/output/public/assets/registry-sWIZsIEF.js +2 -0
- package/node_modules/jishushell-panel/output/public/assets/rolldown-runtime-QTnfLwEv.js +1 -0
- package/node_modules/jishushell-panel/output/public/assets/setup-task-q21GnI0E.js +1 -0
- package/node_modules/jishushell-panel/output/public/assets/usePolling-D4IDOQd_.js +1 -0
- package/node_modules/jishushell-panel/output/public/assets/vendor-i18n-Df8aUdv8.js +1 -0
- package/node_modules/jishushell-panel/output/public/assets/vendor-react-0L0rjmYG.js +8 -0
- package/node_modules/jishushell-panel/output/public/index.html +6 -4
- package/node_modules/jishushell-panel/package.json +2 -2
- package/node_modules/semver/classes/range.js +17 -4
- package/node_modules/semver/package.json +2 -2
- package/package.json +12 -64
- package/scripts/check-app-path-boundaries.mjs +121 -0
- package/scripts/check-app-spec.mjs +123 -29
- package/scripts/check-architecture-boundaries.mjs +178 -0
- package/scripts/check-colima-launchd.mjs +10 -8
- package/scripts/check-integration-isolation.ts +541 -0
- package/scripts/check-new-file-tests.mjs +11 -3
- package/scripts/check-open-core-boundaries.mjs +60 -10
- package/scripts/check-test-layering.sh +1 -1
- package/scripts/fixtures/instances/hermes-sample/instance.json +3 -2
- package/scripts/fixtures/instances/legacy-openclaw-sample/instance.json +1 -1
- package/scripts/local-web-upgrade-test.README +4 -3
- package/scripts/local-web-upgrade-test.example.env +2 -2
- package/scripts/local-web-upgrade-test.sh +14 -1
- package/scripts/pack-gui-and-send-pi.sh +43 -0
- package/scripts/perf/instances.js +1 -1
- package/scripts/prune-open-core-dist.mjs +89 -2
- package/scripts/smoke/hermes-bootstrap.sh +5 -5
- package/templates/hermes-entrypoint.sh +19 -29
- package/apps/openwebui-container.yaml +0 -97
- package/apps/playwright-container.yaml +0 -126
- package/dependencies/jishushell-panel-0.6.5.tgz +0 -0
- package/dist/crypto-shim.d.ts +0 -1
- package/dist/crypto-shim.js +0 -2
- package/dist/crypto-shim.js.map +0 -1
- package/dist/routes/agent-apps.d.ts +0 -14
- package/dist/routes/agent-apps.js +0 -77
- package/dist/routes/agent-apps.js.map +0 -1
- package/dist/routes/internal.d.ts +0 -2
- package/dist/routes/internal.js +0 -55
- package/dist/routes/internal.js.map +0 -1
- package/dist/routes/openclaw-routes.d.ts +0 -22
- package/dist/routes/openclaw-routes.js +0 -1020
- package/dist/routes/openclaw-routes.js.map +0 -1
- package/dist/routes/runtime.d.ts +0 -15
- package/dist/routes/runtime.js +0 -76
- package/dist/routes/runtime.js.map +0 -1
- package/dist/services/agent-apps/catalog.d.ts +0 -33
- package/dist/services/agent-apps/catalog.js +0 -88
- package/dist/services/agent-apps/catalog.js.map +0 -1
- package/dist/services/agent-apps/index.d.ts +0 -36
- package/dist/services/agent-apps/index.js +0 -171
- package/dist/services/agent-apps/index.js.map +0 -1
- package/dist/services/agent-apps/installers/adapter-probes.d.ts +0 -49
- package/dist/services/agent-apps/installers/adapter-probes.js +0 -230
- package/dist/services/agent-apps/installers/adapter-probes.js.map +0 -1
- package/dist/services/agent-apps/installers/adapter.d.ts +0 -30
- package/dist/services/agent-apps/installers/adapter.js +0 -171
- package/dist/services/agent-apps/installers/adapter.js.map +0 -1
- package/dist/services/agent-apps/installers/registry-probe.js.map +0 -1
- package/dist/services/agent-apps/installers/shell-script.d.ts +0 -47
- package/dist/services/agent-apps/installers/shell-script.js +0 -488
- package/dist/services/agent-apps/installers/shell-script.js.map +0 -1
- package/dist/services/agent-apps/types.d.ts +0 -128
- package/dist/services/agent-apps/types.js +0 -17
- package/dist/services/agent-apps/types.js.map +0 -1
- package/dist/services/app/app-compiler.js +0 -185
- package/dist/services/app/app-compiler.js.map +0 -1
- package/dist/services/app/app-manager.d.ts +0 -184
- package/dist/services/app/app-manager.js +0 -2933
- package/dist/services/app/app-manager.js.map +0 -1
- package/dist/services/app/custom-manager.d.ts +0 -27
- package/dist/services/app/custom-manager.js +0 -382
- package/dist/services/app/custom-manager.js.map +0 -1
- package/dist/services/app/hermes-agent-manager.d.ts +0 -20
- package/dist/services/app/hermes-agent-manager.js +0 -299
- package/dist/services/app/hermes-agent-manager.js.map +0 -1
- package/dist/services/app/id-normalizer.d.ts +0 -27
- package/dist/services/app/id-normalizer.js +0 -77
- package/dist/services/app/id-normalizer.js.map +0 -1
- package/dist/services/app/ollama-manager.d.ts +0 -18
- package/dist/services/app/ollama-manager.js +0 -224
- package/dist/services/app/ollama-manager.js.map +0 -1
- package/dist/services/app/openclaw-manager.d.ts +0 -63
- package/dist/services/app/openclaw-manager.js +0 -1215
- package/dist/services/app/openclaw-manager.js.map +0 -1
- package/dist/services/app/paths.d.ts +0 -27
- package/dist/services/app/paths.js +0 -40
- package/dist/services/app/paths.js.map +0 -1
- package/dist/services/app/platform-transform.d.ts +0 -32
- package/dist/services/app/platform-transform.js +0 -65
- package/dist/services/app/platform-transform.js.map +0 -1
- package/dist/services/app/provide-resolver.d.ts +0 -29
- package/dist/services/app/provide-resolver.js +0 -135
- package/dist/services/app/provide-resolver.js.map +0 -1
- package/dist/services/app/registry.d.ts +0 -17
- package/dist/services/app/registry.js +0 -31
- package/dist/services/app/registry.js.map +0 -1
- package/dist/services/app/remote-spec.d.ts +0 -14
- package/dist/services/app/remote-spec.js +0 -58
- package/dist/services/app/remote-spec.js.map +0 -1
- package/dist/services/app/terminal-session-manager.js +0 -157
- package/dist/services/app/terminal-session-manager.js.map +0 -1
- package/dist/services/app/types.d.ts +0 -74
- package/dist/services/app/types.js +0 -16
- package/dist/services/app/types.js.map +0 -1
- package/dist/services/app-config-admin.d.ts +0 -17
- package/dist/services/app-config-admin.js +0 -177
- package/dist/services/app-config-admin.js.map +0 -1
- package/dist/services/app-create-from-installed.d.ts +0 -23
- package/dist/services/app-create-from-installed.js +0 -75
- package/dist/services/app-create-from-installed.js.map +0 -1
- package/dist/services/app-passwords.js +0 -173
- package/dist/services/app-passwords.js.map +0 -1
- package/dist/services/backup-admin.d.ts +0 -101
- package/dist/services/backup-admin.js +0 -259
- package/dist/services/backup-admin.js.map +0 -1
- package/dist/services/backup-manager.d.ts +0 -264
- package/dist/services/backup-manager.js +0 -2263
- package/dist/services/backup-manager.js.map +0 -1
- package/dist/services/backup-verify.js +0 -240
- package/dist/services/backup-verify.js.map +0 -1
- package/dist/services/capability-endpoint-validator.d.ts +0 -41
- package/dist/services/capability-endpoint-validator.js +0 -114
- package/dist/services/capability-endpoint-validator.js.map +0 -1
- package/dist/services/capability-health.d.ts +0 -16
- package/dist/services/capability-health.js +0 -121
- package/dist/services/capability-health.js.map +0 -1
- package/dist/services/capability-registry.d.ts +0 -29
- package/dist/services/capability-registry.js +0 -176
- package/dist/services/capability-registry.js.map +0 -1
- package/dist/services/capability-sync.d.ts +0 -4
- package/dist/services/capability-sync.js +0 -220
- package/dist/services/capability-sync.js.map +0 -1
- package/dist/services/connection-admin.d.ts +0 -74
- package/dist/services/connection-admin.js +0 -287
- package/dist/services/connection-admin.js.map +0 -1
- package/dist/services/connection-apply.d.ts +0 -91
- package/dist/services/connection-apply.js +0 -471
- package/dist/services/connection-apply.js.map +0 -1
- package/dist/services/connection-resolver.d.ts +0 -65
- package/dist/services/connection-resolver.js +0 -281
- package/dist/services/connection-resolver.js.map +0 -1
- package/dist/services/connection-transactor.d.ts +0 -39
- package/dist/services/connection-transactor.js +0 -354
- package/dist/services/connection-transactor.js.map +0 -1
- package/dist/services/core-manager.d.ts +0 -50
- package/dist/services/core-manager.js +0 -411
- package/dist/services/core-manager.js.map +0 -1
- package/dist/services/external-mounts.js +0 -187
- package/dist/services/external-mounts.js.map +0 -1
- package/dist/services/files-manager.d.ts +0 -252
- package/dist/services/files-manager.js +0 -1156
- package/dist/services/files-manager.js.map +0 -1
- package/dist/services/files-mounts.d.ts +0 -42
- package/dist/services/files-mounts.js +0 -207
- package/dist/services/files-mounts.js.map +0 -1
- package/dist/services/instance-admin.d.ts +0 -26
- package/dist/services/instance-admin.js +0 -218
- package/dist/services/instance-admin.js.map +0 -1
- package/dist/services/instance-manager.d.ts +0 -192
- package/dist/services/instance-manager.js +0 -1289
- package/dist/services/instance-manager.js.map +0 -1
- package/dist/services/macos-launchd.js +0 -312
- package/dist/services/macos-launchd.js.map +0 -1
- package/dist/services/nomad-manager.d.ts +0 -307
- package/dist/services/nomad-manager.js +0 -3958
- package/dist/services/nomad-manager.js.map +0 -1
- package/dist/services/organize/applier.js +0 -218
- package/dist/services/organize/applier.js.map +0 -1
- package/dist/services/organize/rules.js +0 -286
- package/dist/services/organize/rules.js.map +0 -1
- package/dist/services/organize/scanner.js +0 -366
- package/dist/services/organize/scanner.js.map +0 -1
- package/dist/services/organize/store.js +0 -82
- package/dist/services/organize/store.js.map +0 -1
- package/dist/services/plugin-installer.js +0 -128
- package/dist/services/plugin-installer.js.map +0 -1
- package/dist/services/process-manager.d.ts +0 -25
- package/dist/services/process-manager.js +0 -568
- package/dist/services/process-manager.js.map +0 -1
- package/dist/services/runtime/adapters/custom.d.ts +0 -20
- package/dist/services/runtime/adapters/custom.js +0 -188
- package/dist/services/runtime/adapters/custom.js.map +0 -1
- package/dist/services/runtime/adapters/hermes.d.ts +0 -204
- package/dist/services/runtime/adapters/hermes.js +0 -1684
- package/dist/services/runtime/adapters/hermes.js.map +0 -1
- package/dist/services/runtime/adapters/openclaw-mcporter.d.ts +0 -45
- package/dist/services/runtime/adapters/openclaw-mcporter.js +0 -108
- package/dist/services/runtime/adapters/openclaw-mcporter.js.map +0 -1
- package/dist/services/runtime/adapters/openclaw.d.ts +0 -426
- package/dist/services/runtime/adapters/openclaw.js +0 -3975
- package/dist/services/runtime/adapters/openclaw.js.map +0 -1
- package/dist/services/runtime/index.d.ts +0 -34
- package/dist/services/runtime/index.js +0 -51
- package/dist/services/runtime/index.js.map +0 -1
- package/dist/services/runtime/mcp-shims/anythingllm-shim.d.ts +0 -46
- package/dist/services/runtime/mcp-shims/anythingllm-shim.js +0 -281
- package/dist/services/runtime/mcp-shims/anythingllm-shim.js.map +0 -1
- package/dist/services/runtime/mcp-shims/drive-shim.js +0 -490
- package/dist/services/runtime/mcp-shims/drive-shim.js.map +0 -1
- package/dist/services/runtime/mcp-shims/jishukb-shim.d.ts +0 -48
- package/dist/services/runtime/mcp-shims/jishukb-shim.js +0 -723
- package/dist/services/runtime/mcp-shims/jishukb-shim.js.map +0 -1
- package/dist/services/runtime/mcp-shims/mcporter-lite.js +0 -276
- package/dist/services/runtime/mcp-shims/mcporter-lite.js.map +0 -1
- package/dist/services/runtime/migrations.d.ts +0 -23
- package/dist/services/runtime/migrations.js +0 -125
- package/dist/services/runtime/migrations.js.map +0 -1
- package/dist/services/runtime/registry.d.ts +0 -13
- package/dist/services/runtime/registry.js +0 -32
- package/dist/services/runtime/registry.js.map +0 -1
- package/dist/services/runtime-identity.d.ts +0 -13
- package/dist/services/runtime-identity.js +0 -166
- package/dist/services/runtime-identity.js.map +0 -1
- package/dist/services/runtime-repair.d.ts +0 -52
- package/dist/services/runtime-repair.js +0 -352
- package/dist/services/runtime-repair.js.map +0 -1
- package/dist/services/setup-manager.d.ts +0 -158
- package/dist/services/setup-manager.js +0 -2740
- package/dist/services/setup-manager.js.map +0 -1
- package/dist/services/suggestions.d.ts +0 -27
- package/dist/services/suggestions.js +0 -133
- package/dist/services/suggestions.js.map +0 -1
- package/dist/services/system-monitor.js +0 -79
- package/dist/services/system-monitor.js.map +0 -1
- package/dist/services/system-ollama-provider.d.ts +0 -14
- package/dist/services/system-ollama-provider.js +0 -125
- package/dist/services/system-ollama-provider.js.map +0 -1
- package/dist/services/system-reconciler.d.ts +0 -72
- package/dist/services/system-reconciler.js +0 -600
- package/dist/services/system-reconciler.js.map +0 -1
- package/dist/services/task-registry.d.ts +0 -44
- package/dist/services/task-registry.js +0 -76
- package/dist/services/task-registry.js.map +0 -1
- package/dist/services/types-shim.d.ts +0 -16
- package/dist/services/types-shim.js +0 -2
- package/dist/services/types-shim.js.map +0 -1
- package/dist/services/update-manager.d.ts +0 -47
- package/dist/services/update-manager.js +0 -351
- package/dist/services/update-manager.js.map +0 -1
- package/dist/services/webdav/server.d.ts +0 -24
- package/dist/services/webdav/server.js +0 -420
- package/dist/services/webdav/server.js.map +0 -1
- package/dist/services/webdav/xml-builder.js.map +0 -1
- package/dist/services/workspace-builder.d.ts +0 -29
- package/dist/services/workspace-builder.js +0 -188
- package/dist/services/workspace-builder.js.map +0 -1
- package/node_modules/@fastify/static/.github/stale.yml +0 -21
- package/node_modules/@isaacs/cliui/LICENSE.md +0 -63
- package/node_modules/@isaacs/cliui/README.md +0 -151
- package/node_modules/@isaacs/cliui/dist/commonjs/ansi-regex/index.d.ts +0 -4
- package/node_modules/@isaacs/cliui/dist/commonjs/ansi-regex/index.d.ts.map +0 -1
- package/node_modules/@isaacs/cliui/dist/commonjs/ansi-regex/index.js +0 -16
- package/node_modules/@isaacs/cliui/dist/commonjs/ansi-regex/index.js.map +0 -1
- package/node_modules/@isaacs/cliui/dist/commonjs/ansi-styles/index.d.ts +0 -34
- package/node_modules/@isaacs/cliui/dist/commonjs/ansi-styles/index.d.ts.map +0 -1
- package/node_modules/@isaacs/cliui/dist/commonjs/ansi-styles/index.js +0 -170
- package/node_modules/@isaacs/cliui/dist/commonjs/ansi-styles/index.js.map +0 -1
- package/node_modules/@isaacs/cliui/dist/commonjs/eastasianwidth/index.d.ts +0 -6
- package/node_modules/@isaacs/cliui/dist/commonjs/eastasianwidth/index.d.ts.map +0 -1
- package/node_modules/@isaacs/cliui/dist/commonjs/eastasianwidth/index.js +0 -307
- package/node_modules/@isaacs/cliui/dist/commonjs/eastasianwidth/index.js.map +0 -1
- package/node_modules/@isaacs/cliui/dist/commonjs/emoji-regex/index.d.ts +0 -2
- package/node_modules/@isaacs/cliui/dist/commonjs/emoji-regex/index.d.ts.map +0 -1
- package/node_modules/@isaacs/cliui/dist/commonjs/emoji-regex/index.js +0 -7
- package/node_modules/@isaacs/cliui/dist/commonjs/emoji-regex/index.js.map +0 -1
- package/node_modules/@isaacs/cliui/dist/commonjs/index.d.ts +0 -41
- package/node_modules/@isaacs/cliui/dist/commonjs/index.d.ts.map +0 -1
- package/node_modules/@isaacs/cliui/dist/commonjs/index.js +0 -322
- package/node_modules/@isaacs/cliui/dist/commonjs/index.js.map +0 -1
- package/node_modules/@isaacs/cliui/dist/commonjs/index.min.js +0 -12
- package/node_modules/@isaacs/cliui/dist/commonjs/index.min.js.map +0 -7
- package/node_modules/@isaacs/cliui/dist/commonjs/package.json +0 -3
- package/node_modules/@isaacs/cliui/dist/commonjs/string-width/index.d.ts +0 -5
- package/node_modules/@isaacs/cliui/dist/commonjs/string-width/index.d.ts.map +0 -1
- package/node_modules/@isaacs/cliui/dist/commonjs/string-width/index.js +0 -49
- package/node_modules/@isaacs/cliui/dist/commonjs/string-width/index.js.map +0 -1
- package/node_modules/@isaacs/cliui/dist/commonjs/strip-ansi/index.d.ts +0 -2
- package/node_modules/@isaacs/cliui/dist/commonjs/strip-ansi/index.d.ts.map +0 -1
- package/node_modules/@isaacs/cliui/dist/commonjs/strip-ansi/index.js +0 -8
- package/node_modules/@isaacs/cliui/dist/commonjs/strip-ansi/index.js.map +0 -1
- package/node_modules/@isaacs/cliui/dist/commonjs/wrap-ansi/index.d.ts +0 -7
- package/node_modules/@isaacs/cliui/dist/commonjs/wrap-ansi/index.d.ts.map +0 -1
- package/node_modules/@isaacs/cliui/dist/commonjs/wrap-ansi/index.js +0 -176
- package/node_modules/@isaacs/cliui/dist/commonjs/wrap-ansi/index.js.map +0 -1
- package/node_modules/@isaacs/cliui/dist/esm/ansi-regex/index.d.ts +0 -4
- package/node_modules/@isaacs/cliui/dist/esm/ansi-regex/index.d.ts.map +0 -1
- package/node_modules/@isaacs/cliui/dist/esm/ansi-regex/index.js +0 -12
- package/node_modules/@isaacs/cliui/dist/esm/ansi-regex/index.js.map +0 -1
- package/node_modules/@isaacs/cliui/dist/esm/ansi-styles/index.d.ts +0 -34
- package/node_modules/@isaacs/cliui/dist/esm/ansi-styles/index.d.ts.map +0 -1
- package/node_modules/@isaacs/cliui/dist/esm/ansi-styles/index.js +0 -167
- package/node_modules/@isaacs/cliui/dist/esm/ansi-styles/index.js.map +0 -1
- package/node_modules/@isaacs/cliui/dist/esm/eastasianwidth/index.d.ts +0 -6
- package/node_modules/@isaacs/cliui/dist/esm/eastasianwidth/index.d.ts.map +0 -1
- package/node_modules/@isaacs/cliui/dist/esm/eastasianwidth/index.js +0 -299
- package/node_modules/@isaacs/cliui/dist/esm/eastasianwidth/index.js.map +0 -1
- package/node_modules/@isaacs/cliui/dist/esm/emoji-regex/index.d.ts +0 -2
- package/node_modules/@isaacs/cliui/dist/esm/emoji-regex/index.d.ts.map +0 -1
- package/node_modules/@isaacs/cliui/dist/esm/emoji-regex/index.js +0 -3
- package/node_modules/@isaacs/cliui/dist/esm/emoji-regex/index.js.map +0 -1
- package/node_modules/@isaacs/cliui/dist/esm/index.d.ts +0 -41
- package/node_modules/@isaacs/cliui/dist/esm/index.d.ts.map +0 -1
- package/node_modules/@isaacs/cliui/dist/esm/index.js +0 -317
- package/node_modules/@isaacs/cliui/dist/esm/index.js.map +0 -1
- package/node_modules/@isaacs/cliui/dist/esm/index.min.js +0 -12
- package/node_modules/@isaacs/cliui/dist/esm/index.min.js.map +0 -7
- package/node_modules/@isaacs/cliui/dist/esm/package.json +0 -3
- package/node_modules/@isaacs/cliui/dist/esm/string-width/index.d.ts +0 -5
- package/node_modules/@isaacs/cliui/dist/esm/string-width/index.d.ts.map +0 -1
- package/node_modules/@isaacs/cliui/dist/esm/string-width/index.js +0 -46
- package/node_modules/@isaacs/cliui/dist/esm/string-width/index.js.map +0 -1
- package/node_modules/@isaacs/cliui/dist/esm/strip-ansi/index.d.ts +0 -2
- package/node_modules/@isaacs/cliui/dist/esm/strip-ansi/index.d.ts.map +0 -1
- package/node_modules/@isaacs/cliui/dist/esm/strip-ansi/index.js +0 -4
- package/node_modules/@isaacs/cliui/dist/esm/strip-ansi/index.js.map +0 -1
- package/node_modules/@isaacs/cliui/dist/esm/wrap-ansi/index.d.ts +0 -7
- package/node_modules/@isaacs/cliui/dist/esm/wrap-ansi/index.d.ts.map +0 -1
- package/node_modules/@isaacs/cliui/dist/esm/wrap-ansi/index.js +0 -172
- package/node_modules/@isaacs/cliui/dist/esm/wrap-ansi/index.js.map +0 -1
- package/node_modules/@isaacs/cliui/package.json +0 -163
- package/node_modules/content-disposition/HISTORY.md +0 -60
- package/node_modules/cross-spawn/LICENSE +0 -21
- package/node_modules/cross-spawn/README.md +0 -89
- package/node_modules/cross-spawn/index.js +0 -39
- package/node_modules/cross-spawn/lib/enoent.js +0 -59
- package/node_modules/cross-spawn/lib/parse.js +0 -91
- package/node_modules/cross-spawn/lib/util/escape.js +0 -47
- package/node_modules/cross-spawn/lib/util/readShebang.js +0 -23
- package/node_modules/cross-spawn/lib/util/resolveCommand.js +0 -52
- package/node_modules/cross-spawn/package.json +0 -73
- package/node_modules/fastify/test/types/content-type-parser.test-d.ts +0 -72
- package/node_modules/fastify/test/types/decorate-request-reply.test-d.ts +0 -18
- package/node_modules/fastify/test/types/dummy-plugin.ts +0 -9
- package/node_modules/fastify/test/types/errors.test-d.ts +0 -90
- package/node_modules/fastify/test/types/fastify.test-d.ts +0 -352
- package/node_modules/fastify/test/types/hooks.test-d.ts +0 -550
- package/node_modules/fastify/test/types/import.ts +0 -2
- package/node_modules/fastify/test/types/instance.test-d.ts +0 -588
- package/node_modules/fastify/test/types/logger.test-d.ts +0 -277
- package/node_modules/fastify/test/types/plugin.test-d.ts +0 -97
- package/node_modules/fastify/test/types/register.test-d.ts +0 -237
- package/node_modules/fastify/test/types/reply.test-d.ts +0 -254
- package/node_modules/fastify/test/types/request.test-d.ts +0 -188
- package/node_modules/fastify/test/types/route.test-d.ts +0 -553
- package/node_modules/fastify/test/types/schema.test-d.ts +0 -135
- package/node_modules/fastify/test/types/serverFactory.test-d.ts +0 -37
- package/node_modules/fastify/test/types/type-provider.test-d.ts +0 -1213
- package/node_modules/fastify/test/types/using.test-d.ts +0 -17
- package/node_modules/foreground-child/LICENSE +0 -15
- package/node_modules/foreground-child/README.md +0 -128
- package/node_modules/foreground-child/dist/commonjs/all-signals.d.ts +0 -2
- package/node_modules/foreground-child/dist/commonjs/all-signals.d.ts.map +0 -1
- package/node_modules/foreground-child/dist/commonjs/all-signals.js +0 -58
- package/node_modules/foreground-child/dist/commonjs/all-signals.js.map +0 -1
- package/node_modules/foreground-child/dist/commonjs/index.d.ts +0 -58
- package/node_modules/foreground-child/dist/commonjs/index.d.ts.map +0 -1
- package/node_modules/foreground-child/dist/commonjs/index.js +0 -123
- package/node_modules/foreground-child/dist/commonjs/index.js.map +0 -1
- package/node_modules/foreground-child/dist/commonjs/package.json +0 -3
- package/node_modules/foreground-child/dist/commonjs/proxy-signals.d.ts +0 -6
- package/node_modules/foreground-child/dist/commonjs/proxy-signals.d.ts.map +0 -1
- package/node_modules/foreground-child/dist/commonjs/proxy-signals.js +0 -38
- package/node_modules/foreground-child/dist/commonjs/proxy-signals.js.map +0 -1
- package/node_modules/foreground-child/dist/commonjs/watchdog.d.ts +0 -10
- package/node_modules/foreground-child/dist/commonjs/watchdog.d.ts.map +0 -1
- package/node_modules/foreground-child/dist/commonjs/watchdog.js +0 -50
- package/node_modules/foreground-child/dist/commonjs/watchdog.js.map +0 -1
- package/node_modules/foreground-child/dist/esm/all-signals.d.ts +0 -2
- package/node_modules/foreground-child/dist/esm/all-signals.d.ts.map +0 -1
- package/node_modules/foreground-child/dist/esm/all-signals.js +0 -52
- package/node_modules/foreground-child/dist/esm/all-signals.js.map +0 -1
- package/node_modules/foreground-child/dist/esm/index.d.ts +0 -58
- package/node_modules/foreground-child/dist/esm/index.d.ts.map +0 -1
- package/node_modules/foreground-child/dist/esm/index.js +0 -115
- package/node_modules/foreground-child/dist/esm/index.js.map +0 -1
- package/node_modules/foreground-child/dist/esm/package.json +0 -3
- package/node_modules/foreground-child/dist/esm/proxy-signals.d.ts +0 -6
- package/node_modules/foreground-child/dist/esm/proxy-signals.d.ts.map +0 -1
- package/node_modules/foreground-child/dist/esm/proxy-signals.js +0 -34
- package/node_modules/foreground-child/dist/esm/proxy-signals.js.map +0 -1
- package/node_modules/foreground-child/dist/esm/watchdog.d.ts +0 -10
- package/node_modules/foreground-child/dist/esm/watchdog.d.ts.map +0 -1
- package/node_modules/foreground-child/dist/esm/watchdog.js +0 -46
- package/node_modules/foreground-child/dist/esm/watchdog.js.map +0 -1
- package/node_modules/foreground-child/package.json +0 -106
- package/node_modules/glob/dist/esm/bin.d.mts +0 -3
- package/node_modules/glob/dist/esm/bin.d.mts.map +0 -1
- package/node_modules/glob/dist/esm/bin.mjs +0 -346
- package/node_modules/glob/dist/esm/bin.mjs.map +0 -1
- package/node_modules/isexe/.npmignore +0 -2
- package/node_modules/isexe/LICENSE +0 -15
- package/node_modules/isexe/README.md +0 -51
- package/node_modules/isexe/index.js +0 -57
- package/node_modules/isexe/mode.js +0 -41
- package/node_modules/isexe/package.json +0 -31
- package/node_modules/isexe/test/basic.js +0 -221
- package/node_modules/isexe/windows.js +0 -42
- package/node_modules/jackspeak/LICENSE.md +0 -55
- package/node_modules/jackspeak/README.md +0 -394
- package/node_modules/jackspeak/dist/commonjs/index.d.ts +0 -323
- package/node_modules/jackspeak/dist/commonjs/index.d.ts.map +0 -1
- package/node_modules/jackspeak/dist/commonjs/index.js +0 -944
- package/node_modules/jackspeak/dist/commonjs/index.js.map +0 -1
- package/node_modules/jackspeak/dist/commonjs/index.min.js +0 -33
- package/node_modules/jackspeak/dist/commonjs/index.min.js.map +0 -7
- package/node_modules/jackspeak/dist/commonjs/package.json +0 -3
- package/node_modules/jackspeak/dist/esm/index.d.ts +0 -323
- package/node_modules/jackspeak/dist/esm/index.d.ts.map +0 -1
- package/node_modules/jackspeak/dist/esm/index.js +0 -936
- package/node_modules/jackspeak/dist/esm/index.js.map +0 -1
- package/node_modules/jackspeak/dist/esm/index.min.js +0 -33
- package/node_modules/jackspeak/dist/esm/index.min.js.map +0 -7
- package/node_modules/jackspeak/dist/esm/package.json +0 -3
- package/node_modules/jackspeak/package.json +0 -115
- package/node_modules/jishushell-panel/output/public/assets/ApiKeyField-D1i7zWXR.js +0 -1
- package/node_modules/jishushell-panel/output/public/assets/Dashboard-sWIvL43F.js +0 -1
- package/node_modules/jishushell-panel/output/public/assets/HermesChatPanel-DQ8RyvQY.js +0 -1
- package/node_modules/jishushell-panel/output/public/assets/HermesConfigForm-tIbPP1sB.js +0 -4
- package/node_modules/jishushell-panel/output/public/assets/InitPassword-C3Slq3Dd.js +0 -1
- package/node_modules/jishushell-panel/output/public/assets/InstanceDetail-7JqY9tq4.js +0 -92
- package/node_modules/jishushell-panel/output/public/assets/Login-BXLDJlQN.js +0 -1
- package/node_modules/jishushell-panel/output/public/assets/NewInstance-dLc5Xrpx.js +0 -1
- package/node_modules/jishushell-panel/output/public/assets/ProviderRecommendations-DIAXxesl.js +0 -1
- package/node_modules/jishushell-panel/output/public/assets/Settings-Bd5utbBh.js +0 -1
- package/node_modules/jishushell-panel/output/public/assets/Setup-Yn9_20FL.js +0 -1
- package/node_modules/jishushell-panel/output/public/assets/WeixinLoginPanel-C21doQTJ.js +0 -9
- package/node_modules/jishushell-panel/output/public/assets/index-CCkaIEjn.js +0 -20
- package/node_modules/jishushell-panel/output/public/assets/index-D7qxy-Vh.css +0 -1
- package/node_modules/jishushell-panel/output/public/assets/registry-B2ZQZXWL.js +0 -2
- package/node_modules/jishushell-panel/output/public/assets/usePolling-BFZm4do_.js +0 -1
- package/node_modules/jishushell-panel/output/public/assets/vendor-i18n-DqPtOicc.js +0 -9
- package/node_modules/jishushell-panel/output/public/assets/vendor-react-DW5juQin.js +0 -59
- package/node_modules/package-json-from-dist/LICENSE.md +0 -63
- package/node_modules/package-json-from-dist/README.md +0 -110
- package/node_modules/package-json-from-dist/dist/commonjs/index.d.ts +0 -89
- package/node_modules/package-json-from-dist/dist/commonjs/index.d.ts.map +0 -1
- package/node_modules/package-json-from-dist/dist/commonjs/index.js +0 -134
- package/node_modules/package-json-from-dist/dist/commonjs/index.js.map +0 -1
- package/node_modules/package-json-from-dist/dist/commonjs/package.json +0 -3
- package/node_modules/package-json-from-dist/dist/esm/index.d.ts +0 -89
- package/node_modules/package-json-from-dist/dist/esm/index.d.ts.map +0 -1
- package/node_modules/package-json-from-dist/dist/esm/index.js +0 -129
- package/node_modules/package-json-from-dist/dist/esm/index.js.map +0 -1
- package/node_modules/package-json-from-dist/dist/esm/package.json +0 -3
- package/node_modules/package-json-from-dist/package.json +0 -68
- package/node_modules/path-key/index.d.ts +0 -40
- package/node_modules/path-key/index.js +0 -16
- package/node_modules/path-key/license +0 -9
- package/node_modules/path-key/package.json +0 -39
- package/node_modules/path-key/readme.md +0 -61
- package/node_modules/safe-buffer/LICENSE +0 -21
- package/node_modules/safe-buffer/README.md +0 -584
- package/node_modules/safe-buffer/index.d.ts +0 -187
- package/node_modules/safe-buffer/index.js +0 -65
- package/node_modules/safe-buffer/package.json +0 -51
- package/node_modules/shebang-command/index.js +0 -19
- package/node_modules/shebang-command/license +0 -9
- package/node_modules/shebang-command/package.json +0 -34
- package/node_modules/shebang-command/readme.md +0 -34
- package/node_modules/shebang-regex/index.d.ts +0 -22
- package/node_modules/shebang-regex/index.js +0 -2
- package/node_modules/shebang-regex/license +0 -9
- package/node_modules/shebang-regex/package.json +0 -35
- package/node_modules/shebang-regex/readme.md +0 -33
- package/node_modules/signal-exit/LICENSE.txt +0 -16
- package/node_modules/signal-exit/README.md +0 -74
- package/node_modules/signal-exit/dist/cjs/browser.d.ts +0 -12
- package/node_modules/signal-exit/dist/cjs/browser.d.ts.map +0 -1
- package/node_modules/signal-exit/dist/cjs/browser.js +0 -10
- package/node_modules/signal-exit/dist/cjs/browser.js.map +0 -1
- package/node_modules/signal-exit/dist/cjs/index.d.ts +0 -48
- package/node_modules/signal-exit/dist/cjs/index.d.ts.map +0 -1
- package/node_modules/signal-exit/dist/cjs/index.js +0 -279
- package/node_modules/signal-exit/dist/cjs/index.js.map +0 -1
- package/node_modules/signal-exit/dist/cjs/package.json +0 -3
- package/node_modules/signal-exit/dist/cjs/signals.d.ts +0 -29
- package/node_modules/signal-exit/dist/cjs/signals.d.ts.map +0 -1
- package/node_modules/signal-exit/dist/cjs/signals.js +0 -42
- package/node_modules/signal-exit/dist/cjs/signals.js.map +0 -1
- package/node_modules/signal-exit/dist/mjs/browser.d.ts +0 -12
- package/node_modules/signal-exit/dist/mjs/browser.d.ts.map +0 -1
- package/node_modules/signal-exit/dist/mjs/browser.js +0 -4
- package/node_modules/signal-exit/dist/mjs/browser.js.map +0 -1
- package/node_modules/signal-exit/dist/mjs/index.d.ts +0 -48
- package/node_modules/signal-exit/dist/mjs/index.d.ts.map +0 -1
- package/node_modules/signal-exit/dist/mjs/index.js +0 -275
- package/node_modules/signal-exit/dist/mjs/index.js.map +0 -1
- package/node_modules/signal-exit/dist/mjs/package.json +0 -3
- package/node_modules/signal-exit/dist/mjs/signals.d.ts +0 -29
- package/node_modules/signal-exit/dist/mjs/signals.d.ts.map +0 -1
- package/node_modules/signal-exit/dist/mjs/signals.js +0 -39
- package/node_modules/signal-exit/dist/mjs/signals.js.map +0 -1
- package/node_modules/signal-exit/package.json +0 -106
- package/node_modules/which/CHANGELOG.md +0 -166
- package/node_modules/which/LICENSE +0 -15
- package/node_modules/which/README.md +0 -54
- package/node_modules/which/bin/node-which +0 -52
- package/node_modules/which/package.json +0 -43
- package/node_modules/which/which.js +0 -125
- package/scripts/check-adapter-isolation.ts +0 -293
- /package/dist/services/{app → app-common}/app-compiler.d.ts +0 -0
- /package/dist/services/{app → app-common}/terminal-session-manager.d.ts +0 -0
- /package/dist/services/{backup-verify.d.ts → backup/backup-verify.d.ts} +0 -0
- /package/dist/services/{external-mounts.d.ts → files/external-mounts.d.ts} +0 -0
- /package/dist/services/{organize → files/organize}/applier.d.ts +0 -0
- /package/dist/services/{organize → files/organize}/rules.d.ts +0 -0
- /package/dist/services/{organize → files/organize}/scanner.d.ts +0 -0
- /package/dist/services/{organize → files/organize}/store.d.ts +0 -0
- /package/dist/services/{webdav → files/webdav}/xml-builder.d.ts +0 -0
- /package/dist/services/{webdav → files/webdav}/xml-builder.js +0 -0
- /package/dist/services/{app-passwords.d.ts → instances/passwords.d.ts} +0 -0
- /package/dist/services/{agent-apps → integrations/installable}/installers/registry-probe.d.ts +0 -0
- /package/dist/services/{agent-apps → integrations/installable}/installers/registry-probe.js +0 -0
- /package/dist/services/{runtime/mcp-shims → integrations/openclaw}/drive-shim.d.ts +0 -0
- /package/dist/services/{runtime/mcp-shims → integrations/openclaw}/mcporter-lite.d.ts +0 -0
- /package/dist/services/{plugin-installer.d.ts → setup/plugin-installer.d.ts} +0 -0
- /package/dist/services/{macos-launchd.d.ts → system/macos-launchd.d.ts} +0 -0
- /package/dist/services/{system-monitor.d.ts → system/system-monitor.d.ts} +0 -0
package/dist/routes/instances.js
CHANGED
|
@@ -1,1075 +1,33 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
3
|
-
import * as
|
|
4
|
-
import { cleanupInstance as cleanupProxyInstance, getLastProxyError,
|
|
5
|
-
import { createInstance, isInstanceAdminError, validateId, } from "../services/
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
//
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
]
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
* value, preserving any other cookies for upstream forwarding.
|
|
26
|
-
*/
|
|
27
|
-
function stripPanelSessionCookie(value) {
|
|
28
|
-
if (value === undefined)
|
|
29
|
-
return undefined;
|
|
30
|
-
const cookie = Array.isArray(value) ? value.join("; ") : value;
|
|
31
|
-
const preserved = cookie
|
|
32
|
-
.split(";")
|
|
33
|
-
.map((part) => part.trim())
|
|
34
|
-
.filter((part) => part && !/^jishushell_session=/i.test(part));
|
|
35
|
-
return preserved.length ? preserved.join("; ") : undefined;
|
|
36
|
-
}
|
|
37
|
-
function readHeaderValue(value) {
|
|
38
|
-
const header = Array.isArray(value) ? value[0] : value;
|
|
39
|
-
return typeof header === "string" && header.trim() ? header.trim() : null;
|
|
40
|
-
}
|
|
41
|
-
function parseHttpOrigin(value) {
|
|
42
|
-
if (!value)
|
|
43
|
-
return null;
|
|
44
|
-
try {
|
|
45
|
-
const parsed = new URL(value);
|
|
46
|
-
return parsed.protocol === "http:" || parsed.protocol === "https:" ? parsed.origin : null;
|
|
47
|
-
}
|
|
48
|
-
catch {
|
|
49
|
-
return null;
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
export function inferRequestOrigin(request) {
|
|
53
|
-
// Only trust browser-sent Origin/Referer for auto-allowlisting. Host and
|
|
54
|
-
// X-Forwarded-* are proxy metadata and should not become persisted origin
|
|
55
|
-
// policy by themselves.
|
|
56
|
-
return (parseHttpOrigin(readHeaderValue(request?.headers?.origin))
|
|
57
|
-
?? parseHttpOrigin(readHeaderValue(request?.headers?.referer)));
|
|
58
|
-
}
|
|
59
|
-
function capabilityProxyPath(instanceId, capability) {
|
|
60
|
-
return `/api/instances/${encodeURIComponent(instanceId)}/provides/${encodeURIComponent(capability)}`;
|
|
61
|
-
}
|
|
62
|
-
function joinProxyPath(basePath, suffix) {
|
|
63
|
-
const normalizedBase = basePath.replace(/\/+$/, "");
|
|
64
|
-
const normalizedSuffix = suffix.replace(/^\/+/, "");
|
|
65
|
-
if (!normalizedSuffix)
|
|
66
|
-
return normalizedBase;
|
|
67
|
-
return `${normalizedBase}/${normalizedSuffix}`;
|
|
68
|
-
}
|
|
69
|
-
function canonicalCapabilityProxyBase(basePath, capabilityPath) {
|
|
70
|
-
const normalizedCapabilityPath = typeof capabilityPath === "string" ? capabilityPath.trim() : "";
|
|
71
|
-
const needsTrailingSlash = !normalizedCapabilityPath || normalizedCapabilityPath.endsWith("/");
|
|
72
|
-
return needsTrailingSlash ? `${basePath}/` : basePath;
|
|
73
|
-
}
|
|
74
|
-
function rewriteCapabilityLocation(basePath, canonicalBasePath, pathname, search = "", hash = "") {
|
|
75
|
-
const rewrittenPath = pathname === "/"
|
|
76
|
-
? canonicalBasePath
|
|
77
|
-
: joinProxyPath(basePath, pathname);
|
|
78
|
-
return `${rewrittenPath}${search}${hash}`;
|
|
79
|
-
}
|
|
80
|
-
function joinUpstreamPath(basePath, suffix) {
|
|
81
|
-
const normalizedBase = typeof basePath === "string" && basePath.trim()
|
|
82
|
-
? (basePath.startsWith("/") ? basePath : `/${basePath}`)
|
|
83
|
-
: "/";
|
|
84
|
-
const normalizedSuffix = suffix.replace(/^\/+/, "");
|
|
85
|
-
if (!normalizedSuffix)
|
|
86
|
-
return normalizedBase;
|
|
87
|
-
return `${normalizedBase.replace(/\/+$/, "")}/${normalizedSuffix}`;
|
|
88
|
-
}
|
|
89
|
-
function shouldRewriteProxyResponse(contentType) {
|
|
90
|
-
const value = (contentType ?? "").toLowerCase();
|
|
91
|
-
return value.includes("text/html") || value.includes("text/css");
|
|
92
|
-
}
|
|
93
|
-
function browserlessDebuggerBootstrap(instanceId) {
|
|
94
|
-
const apiProxyPath = `${capabilityProxyPath(instanceId, "browserless-api")}`;
|
|
95
|
-
const escapedPath = JSON.stringify(apiProxyPath + "/");
|
|
96
|
-
const escapedProxyBase = JSON.stringify(apiProxyPath);
|
|
97
|
-
const escapedWorkerPrelude = JSON.stringify([
|
|
98
|
-
"(function(){",
|
|
99
|
-
`var P=${escapedProxyBase};`,
|
|
100
|
-
"var _WS=self.WebSocket;",
|
|
101
|
-
"if(typeof _WS!=='function')return;",
|
|
102
|
-
"self.WebSocket=function(url,protocols){",
|
|
103
|
-
"try{var p=new URL(url,self.location.origin);",
|
|
104
|
-
"if(p.host===self.location.host&&!p.pathname.startsWith('/api/')){",
|
|
105
|
-
"var s=self.location.protocol==='https:'?'wss:':'ws:';",
|
|
106
|
-
"url=s+'//'+self.location.host+P+p.pathname+p.search;",
|
|
107
|
-
"}}catch(_e){}",
|
|
108
|
-
"return protocols!==undefined?new _WS(url,protocols):new _WS(url);",
|
|
109
|
-
"};",
|
|
110
|
-
"self.WebSocket.prototype=_WS.prototype;",
|
|
111
|
-
"self.WebSocket.CONNECTING=_WS.CONNECTING;",
|
|
112
|
-
"self.WebSocket.OPEN=_WS.OPEN;",
|
|
113
|
-
"self.WebSocket.CLOSING=_WS.CLOSING;",
|
|
114
|
-
"self.WebSocket.CLOSED=_WS.CLOSED;",
|
|
115
|
-
"})();",
|
|
116
|
-
].join(""));
|
|
117
|
-
// 1) Set baseURL in localStorage so the debugger's HTTP API calls go through
|
|
118
|
-
// the capability proxy.
|
|
119
|
-
// 2) Monkey-patch WebSocket in the page and any same-origin workers so that
|
|
120
|
-
// Browserless connections targeting the panel origin (e.g.
|
|
121
|
-
// ws://panel:8090/?launch=...) are rewritten through the capability proxy.
|
|
122
|
-
return [
|
|
123
|
-
"<script>(function(){",
|
|
124
|
-
// --- localStorage apiSettings.baseURL ---
|
|
125
|
-
// Browserless reads `state.apiSettings.baseURL` (a NESTED object); writing
|
|
126
|
-
// a flat `state.baseURL` is silently ignored, and the SPA falls back to
|
|
127
|
-
// `window.location.origin` (no proxy prefix) — producing connect URLs like
|
|
128
|
-
// `ws://panel:8090/?launch=...` that bypass the capability proxy.
|
|
129
|
-
"try{var key='browserless-debugger:'+window.location.origin+window.location.pathname;",
|
|
130
|
-
"var raw=window.localStorage.getItem(key)||'{}';",
|
|
131
|
-
"var state={};try{state=JSON.parse(raw)||{}}catch(_e){}",
|
|
132
|
-
`var base=new URL(${escapedPath},window.location.origin);`,
|
|
133
|
-
"var token=new URL(window.location.href).searchParams.get('token');",
|
|
134
|
-
"if(token)base.searchParams.set('token',token);",
|
|
135
|
-
"var settings=(state&&typeof state.apiSettings==='object'&&state.apiSettings)?state.apiSettings:{};",
|
|
136
|
-
"settings.baseURL=base.href;",
|
|
137
|
-
"state.apiSettings=settings;",
|
|
138
|
-
"window.localStorage.setItem(key,JSON.stringify(state));",
|
|
139
|
-
"}catch(_e){}",
|
|
140
|
-
// --- WebSocket monkey-patch ---
|
|
141
|
-
"var _WS=window.WebSocket;",
|
|
142
|
-
`var _base=${escapedProxyBase};`,
|
|
143
|
-
"window.WebSocket=function(url,protocols){",
|
|
144
|
-
"try{var p=new URL(url,window.location.origin);",
|
|
145
|
-
"if(p.host===window.location.host&&!p.pathname.startsWith('/api/')){",
|
|
146
|
-
"var s=window.location.protocol==='https:'?'wss:':'ws:';",
|
|
147
|
-
"url=s+'//'+window.location.host+_base+p.pathname+p.search;",
|
|
148
|
-
"}}catch(_e){}",
|
|
149
|
-
"return protocols!==undefined?new _WS(url,protocols):new _WS(url);",
|
|
150
|
-
"};",
|
|
151
|
-
"window.WebSocket.prototype=_WS.prototype;",
|
|
152
|
-
"window.WebSocket.CONNECTING=_WS.CONNECTING;",
|
|
153
|
-
"window.WebSocket.OPEN=_WS.OPEN;",
|
|
154
|
-
"window.WebSocket.CLOSING=_WS.CLOSING;",
|
|
155
|
-
"window.WebSocket.CLOSED=_WS.CLOSED;",
|
|
156
|
-
// --- Worker monkey-patch ---
|
|
157
|
-
"var _Worker=window.Worker;",
|
|
158
|
-
`var _workerPrelude=${escapedWorkerPrelude};`,
|
|
159
|
-
"function shouldWrapWorker(url){",
|
|
160
|
-
"try{var p=new URL(String(url),window.location.href);",
|
|
161
|
-
"return p.protocol==='blob:'||p.protocol==='data:'||p.origin===window.location.origin;",
|
|
162
|
-
"}catch(_e){return false;}",
|
|
163
|
-
"}",
|
|
164
|
-
"function wrapWorker(url,options){",
|
|
165
|
-
"if(typeof _Worker!=='function'||!shouldWrapWorker(url))return url;",
|
|
166
|
-
"try{var resolved=new URL(String(url),window.location.href).href;",
|
|
167
|
-
"var isModule=!!(options&&options.type==='module');",
|
|
168
|
-
"var source=isModule?_workerPrelude+'\\nimport '+JSON.stringify(resolved)+';':_workerPrelude+'\\nimportScripts('+JSON.stringify(resolved)+');';",
|
|
169
|
-
"return URL.createObjectURL(new Blob([source],{type:'text/javascript'}));",
|
|
170
|
-
"}catch(_e){return url;}",
|
|
171
|
-
"}",
|
|
172
|
-
"if(typeof _Worker==='function'){",
|
|
173
|
-
"window.Worker=function(url,options){",
|
|
174
|
-
"var wrapped=wrapWorker(url,options);",
|
|
175
|
-
"return options!==undefined?new _Worker(wrapped,options):new _Worker(wrapped);",
|
|
176
|
-
"};",
|
|
177
|
-
"window.Worker.prototype=_Worker.prototype;",
|
|
178
|
-
"}",
|
|
179
|
-
"})();</script>",
|
|
180
|
-
].join("");
|
|
181
|
-
}
|
|
182
|
-
const JISHU_KB_PRELOAD_SESSION_LIMIT = 50;
|
|
183
|
-
const JISHU_KB_PRELOAD_MESSAGE_LIMIT = 20;
|
|
184
|
-
const JISHU_KB_PRELOAD_TIMEOUT_MS = 5_000;
|
|
185
|
-
const JISHU_KB_PRELOAD_GLOBAL = "__JISHU_KB_PRELOADED_SESSIONS__";
|
|
186
|
-
function trimString(value) {
|
|
187
|
-
return typeof value === "string" ? value.trim() : "";
|
|
188
|
-
}
|
|
189
|
-
function parseJishuKbConversationId(value) {
|
|
190
|
-
if (typeof value === "number") {
|
|
191
|
-
return Number.isSafeInteger(value) && value > 0 ? value : null;
|
|
192
|
-
}
|
|
193
|
-
const raw = trimString(value);
|
|
194
|
-
if (!/^\d+$/.test(raw))
|
|
195
|
-
return null;
|
|
196
|
-
const parsed = Number(raw);
|
|
197
|
-
return Number.isSafeInteger(parsed) && parsed > 0 ? parsed : null;
|
|
198
|
-
}
|
|
199
|
-
function parseJishuKbTimestamp(value) {
|
|
200
|
-
const numeric = typeof value === "number" ? value : Number(value);
|
|
201
|
-
return Number.isFinite(numeric) ? numeric : 0;
|
|
202
|
-
}
|
|
203
|
-
function parseJishuKbRole(value) {
|
|
204
|
-
const normalized = trimString(value);
|
|
205
|
-
return normalized === "user" || normalized === "assistant" || normalized === "system"
|
|
206
|
-
? normalized
|
|
207
|
-
: null;
|
|
208
|
-
}
|
|
209
|
-
function parseJishuKbCitations(value) {
|
|
210
|
-
if (Array.isArray(value))
|
|
211
|
-
return value;
|
|
212
|
-
if (typeof value !== "string" || !value.trim())
|
|
213
|
-
return undefined;
|
|
214
|
-
try {
|
|
215
|
-
const parsed = JSON.parse(value);
|
|
216
|
-
return Array.isArray(parsed) ? parsed : undefined;
|
|
217
|
-
}
|
|
218
|
-
catch {
|
|
219
|
-
return undefined;
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
function relayAbort(parentSignal, controller) {
|
|
223
|
-
if (parentSignal.aborted) {
|
|
224
|
-
controller.abort(parentSignal.reason);
|
|
225
|
-
return () => { };
|
|
226
|
-
}
|
|
227
|
-
const abort = () => controller.abort(parentSignal.reason);
|
|
228
|
-
parentSignal.addEventListener("abort", abort, { once: true });
|
|
229
|
-
return () => parentSignal.removeEventListener("abort", abort);
|
|
230
|
-
}
|
|
231
|
-
async function fetchJsonWithTimeout(upstreamOrigin, relativePath, parentSignal) {
|
|
232
|
-
const controller = new AbortController();
|
|
233
|
-
const cleanupAbort = relayAbort(parentSignal, controller);
|
|
234
|
-
const timer = setTimeout(() => controller.abort(new Error("timeout")), JISHU_KB_PRELOAD_TIMEOUT_MS);
|
|
235
|
-
try {
|
|
236
|
-
const response = await fetch(new URL(relativePath, `${upstreamOrigin}/`).toString(), {
|
|
237
|
-
headers: { accept: "application/json" },
|
|
238
|
-
signal: controller.signal,
|
|
239
|
-
});
|
|
240
|
-
if (!response.ok) {
|
|
241
|
-
const detail = (await response.text()).slice(0, 200);
|
|
242
|
-
throw new Error(`${relativePath} -> ${response.status}${detail ? `: ${detail}` : ""}`);
|
|
243
|
-
}
|
|
244
|
-
return await response.json();
|
|
245
|
-
}
|
|
246
|
-
finally {
|
|
247
|
-
clearTimeout(timer);
|
|
248
|
-
cleanupAbort();
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
async function loadJishuKbPreloadedSessions(upstreamOrigin, parentSignal) {
|
|
252
|
-
const kbList = await fetchJsonWithTimeout(upstreamOrigin, "/api/kb", parentSignal);
|
|
253
|
-
const kbIds = Array.from(new Set((Array.isArray(kbList) ? kbList : [])
|
|
254
|
-
.map((kb) => trimString(kb?.id))
|
|
255
|
-
.filter(Boolean)));
|
|
256
|
-
if (!kbIds.length)
|
|
257
|
-
kbIds.push("default");
|
|
258
|
-
const conversationLists = await Promise.all(kbIds.map(async (kbId) => {
|
|
259
|
-
const query = new URLSearchParams({ kb_id: kbId }).toString();
|
|
260
|
-
const rows = await fetchJsonWithTimeout(upstreamOrigin, `/api/conversations?${query}`, parentSignal);
|
|
261
|
-
return Array.isArray(rows)
|
|
262
|
-
? rows.map((row) => ({
|
|
263
|
-
...row,
|
|
264
|
-
kb_id: trimString(row?.kb_id) || kbId,
|
|
265
|
-
}))
|
|
266
|
-
: [];
|
|
267
|
-
}));
|
|
268
|
-
const selected = conversationLists
|
|
269
|
-
.flat()
|
|
270
|
-
.sort((left, right) => parseJishuKbTimestamp(right.updated_at) - parseJishuKbTimestamp(left.updated_at))
|
|
271
|
-
.slice(0, JISHU_KB_PRELOAD_SESSION_LIMIT);
|
|
272
|
-
const hydrated = await Promise.all(selected.map(async (conversation) => {
|
|
273
|
-
const conversationId = parseJishuKbConversationId(conversation.id);
|
|
274
|
-
const kbId = trimString(conversation.kb_id);
|
|
275
|
-
if (!conversationId || !kbId) {
|
|
276
|
-
console.warn("[cap-proxy] skipping jishukb conversation preload with unsupported id/kb", {
|
|
277
|
-
id: conversation.id,
|
|
278
|
-
kbId,
|
|
279
|
-
});
|
|
280
|
-
return null;
|
|
281
|
-
}
|
|
282
|
-
const messages = await fetchJsonWithTimeout(upstreamOrigin, `/api/conversations/${encodeURIComponent(String(conversationId))}/messages`, parentSignal);
|
|
283
|
-
const normalizedMessages = (Array.isArray(messages) ? messages : [])
|
|
284
|
-
.map((message) => {
|
|
285
|
-
const role = parseJishuKbRole(message?.role);
|
|
286
|
-
const content = typeof message?.content === "string" ? message.content : "";
|
|
287
|
-
if (!role || !content)
|
|
288
|
-
return null;
|
|
289
|
-
const cites = parseJishuKbCitations(message?.citations);
|
|
290
|
-
return cites?.length
|
|
291
|
-
? { role, content, cites }
|
|
292
|
-
: { role, content };
|
|
293
|
-
})
|
|
294
|
-
.filter((message) => message !== null)
|
|
295
|
-
.slice(-JISHU_KB_PRELOAD_MESSAGE_LIMIT);
|
|
296
|
-
return {
|
|
297
|
-
id: conversationId,
|
|
298
|
-
kb: kbId,
|
|
299
|
-
title: trimString(conversation.title) || "Untitled",
|
|
300
|
-
msgs: normalizedMessages,
|
|
301
|
-
_syncedMsgIdx: normalizedMessages.length,
|
|
302
|
-
};
|
|
303
|
-
}));
|
|
304
|
-
return hydrated
|
|
305
|
-
.filter((session) => session !== null)
|
|
306
|
-
.sort((left, right) => left.id - right.id);
|
|
307
|
-
}
|
|
308
|
-
function jishuKbConversationBootstrap(preloadedSessions) {
|
|
309
|
-
const serialized = JSON.stringify(preloadedSessions);
|
|
310
|
-
const globalName = JSON.stringify(JISHU_KB_PRELOAD_GLOBAL);
|
|
311
|
-
return [
|
|
312
|
-
"<script>(function(){",
|
|
313
|
-
"try{",
|
|
314
|
-
`var incoming=${serialized};`,
|
|
315
|
-
`window[${globalName}]=incoming;`,
|
|
316
|
-
"var current=[];",
|
|
317
|
-
"try{var raw=window.localStorage.getItem('jkb_sess');current=raw?JSON.parse(raw):[];}catch(_e){current=[];}",
|
|
318
|
-
"if(!Array.isArray(current))current=[];",
|
|
319
|
-
"var seen=Object.create(null);",
|
|
320
|
-
"var merged=[];",
|
|
321
|
-
"function key(entry){return String(entry&&entry.kb||'')+'::'+String(entry&&entry.id||'');}",
|
|
322
|
-
"function push(entry){if(!entry||typeof entry!=='object')return;var k=key(entry);if(seen[k])return;seen[k]=1;merged.push(entry);}",
|
|
323
|
-
"incoming.forEach(push);",
|
|
324
|
-
"current.forEach(push);",
|
|
325
|
-
"merged.sort(function(a,b){return Number(a&&a.id||0)-Number(b&&b.id||0);});",
|
|
326
|
-
`if(merged.length>${JISHU_KB_PRELOAD_SESSION_LIMIT})merged=merged.slice(-${JISHU_KB_PRELOAD_SESSION_LIMIT});`,
|
|
327
|
-
"window.localStorage.setItem('jkb_sess',JSON.stringify(merged));",
|
|
328
|
-
"}catch(_e){}",
|
|
329
|
-
"})();</script>",
|
|
330
|
-
].join("");
|
|
331
|
-
}
|
|
332
|
-
/**
|
|
333
|
-
* Inject a tiny <script> that monkey-patches `fetch`, `XMLHttpRequest.open`,
|
|
334
|
-
* and `Element.prototype.{setAttribute,src,href}` so that same-origin absolute
|
|
335
|
-
* paths (e.g. `/api/v1/...`, `/static/...`) are transparently rewritten to go
|
|
336
|
-
* through the capability proxy prefix.
|
|
337
|
-
*
|
|
338
|
-
* The alternative — rewriting every JS bundle byte-for-byte — is fragile and
|
|
339
|
-
* expensive; a runtime shim at document load is the standard approach used by
|
|
340
|
-
* reverse-proxy front-ends (cf. Cloudflare Access, oauth2-proxy, etc.).
|
|
341
|
-
*/
|
|
342
|
-
function capabilityProxyBootstrap(proxyBasePath) {
|
|
343
|
-
const prefix = JSON.stringify(proxyBasePath.replace(/\/+$/, ""));
|
|
344
|
-
const workerPrelude = JSON.stringify([
|
|
345
|
-
"(function(){",
|
|
346
|
-
`var P=${prefix};`,
|
|
347
|
-
"function px(path){",
|
|
348
|
-
"if(!path||path.charAt(0)!=='/'||path.charAt(1)==='/'||path.indexOf(P)===0||path.indexOf('/api/instances/')===0)return path;",
|
|
349
|
-
"return P+path;",
|
|
350
|
-
"}",
|
|
351
|
-
"function str(u){return typeof u==='string'?u:(u&&typeof u.href==='string'?u.href:null);}",
|
|
352
|
-
"function rwWs(u){",
|
|
353
|
-
"var s0=str(u);if(!s0)return u;",
|
|
354
|
-
"var H=typeof __capProxyHost==='string'?__capProxyHost:self.location.host;",
|
|
355
|
-
"var L=typeof __capProxyProtocol==='string'?__capProxyProtocol:self.location.protocol;",
|
|
356
|
-
"var B=(L==='https:'?'https:':'http:')+'//'+H+'/';",
|
|
357
|
-
"try{var p=new URL(s0,B);",
|
|
358
|
-
"if(p.host===H&&(p.protocol==='ws:'||p.protocol==='wss:'||p.protocol===L)){",
|
|
359
|
-
"var pp=px(p.pathname);",
|
|
360
|
-
"if(pp!==p.pathname){var s=L==='https:'?'wss:':'ws:';return s+'//'+H+pp+p.search+p.hash;}",
|
|
361
|
-
"}}catch(_e){}",
|
|
362
|
-
"return u;",
|
|
363
|
-
"}",
|
|
364
|
-
"var _WS=self.WebSocket;",
|
|
365
|
-
"if(typeof _WS==='function')self.WebSocket=function(url,protocols){url=rwWs(url);return protocols!==undefined?new _WS(url,protocols):new _WS(url);};",
|
|
366
|
-
"if(typeof _WS==='function'){self.WebSocket.prototype=_WS.prototype;self.WebSocket.CONNECTING=_WS.CONNECTING;self.WebSocket.OPEN=_WS.OPEN;self.WebSocket.CLOSING=_WS.CLOSING;self.WebSocket.CLOSED=_WS.CLOSED;}",
|
|
367
|
-
"})();",
|
|
368
|
-
].join(""));
|
|
369
|
-
return [
|
|
370
|
-
"<script>(function(){",
|
|
371
|
-
`var P=${prefix};`,
|
|
372
|
-
"var O=window.location.origin;",
|
|
373
|
-
// --- Service Worker neutralization ---
|
|
374
|
-
// Embedded SPAs like OpenWebUI register a service worker that aggressively
|
|
375
|
-
// caches HTML and JS chunks at the proxy origin. After we update the proxy
|
|
376
|
-
// bootstrap, the SW would keep serving the old (unpatched) HTML, so socket.io
|
|
377
|
-
// never gets the WebSocket monkey-patch and the splash screen spins forever.
|
|
378
|
-
// Unregister any existing SW, purge its caches, and block future
|
|
379
|
-
// registrations for the lifetime of the iframe.
|
|
380
|
-
"try{if(navigator.serviceWorker){",
|
|
381
|
-
"if(navigator.serviceWorker.getRegistrations){",
|
|
382
|
-
"navigator.serviceWorker.getRegistrations().then(function(rs){rs.forEach(function(r){try{r.unregister()}catch(_e){}})}).catch(function(){});",
|
|
383
|
-
"}",
|
|
384
|
-
"navigator.serviceWorker.register=function(){return Promise.reject(new Error('service worker disabled in capability proxy'))};",
|
|
385
|
-
"}}catch(_e){}",
|
|
386
|
-
"try{if(window.caches&&caches.keys){caches.keys().then(function(ks){ks.forEach(function(k){try{caches.delete(k)}catch(_e){}})}).catch(function(){});}}catch(_e){}",
|
|
387
|
-
// Only rewrite paths that do NOT already start with the proxy prefix and
|
|
388
|
-
// that are simple absolute paths (start with `/` but not `//`).
|
|
389
|
-
"function px(path){",
|
|
390
|
-
"if(!path||path.charAt(0)!=='/'||path.charAt(1)==='/'||path.indexOf(P)===0||path.indexOf('/api/instances/')===0)return path;",
|
|
391
|
-
"return P+path;",
|
|
392
|
-
"}",
|
|
393
|
-
"function str(u){return typeof u==='string'?u:(u&&typeof u.href==='string'?u.href:null);}",
|
|
394
|
-
"function rw(u){",
|
|
395
|
-
"var s0=str(u);if(!s0)return u;",
|
|
396
|
-
"var direct=px(s0);",
|
|
397
|
-
"if(direct!==s0)return direct;",
|
|
398
|
-
"try{var p=new URL(s0,window.location.href);",
|
|
399
|
-
"if(p.origin===O){var pp=px(p.pathname);if(pp!==p.pathname)return pp+p.search+p.hash;}",
|
|
400
|
-
"}catch(_e){}",
|
|
401
|
-
"return u;",
|
|
402
|
-
"}",
|
|
403
|
-
"function rwWs(u){",
|
|
404
|
-
"var s0=str(u);if(!s0)return u;",
|
|
405
|
-
"try{var p=new URL(s0,window.location.href);",
|
|
406
|
-
"if(p.host===window.location.host&&(p.protocol==='ws:'||p.protocol==='wss:'||p.protocol===window.location.protocol)){",
|
|
407
|
-
"var pp=px(p.pathname);",
|
|
408
|
-
"if(pp!==p.pathname){var s=window.location.protocol==='https:'?'wss:':'ws:';return s+'//'+window.location.host+pp+p.search+p.hash;}",
|
|
409
|
-
"}}catch(_e){}",
|
|
410
|
-
"return u;",
|
|
411
|
-
"}",
|
|
412
|
-
// --- fetch() ---
|
|
413
|
-
"var _f=window.fetch;",
|
|
414
|
-
"window.fetch=function(r,o){",
|
|
415
|
-
"if(typeof r==='string'||(r&&typeof r.href==='string'))r=rw(r);",
|
|
416
|
-
"else if(r instanceof Request){",
|
|
417
|
-
"var nr=rw(r.url);if(nr!==r.url)r=new Request(nr,r);}",
|
|
418
|
-
"return _f.call(this,r,o);};",
|
|
419
|
-
// --- XMLHttpRequest.open() ---
|
|
420
|
-
"var _xo=XMLHttpRequest.prototype.open;",
|
|
421
|
-
"XMLHttpRequest.prototype.open=function(m,u){",
|
|
422
|
-
"arguments[1]=rw(u);",
|
|
423
|
-
"return _xo.apply(this,arguments);};",
|
|
424
|
-
// --- history.pushState / replaceState ---
|
|
425
|
-
// SPA routers (SvelteKit, React Router, etc.) navigate via pushState.
|
|
426
|
-
// Without this, pushing "/" lands on the panel's own SPA.
|
|
427
|
-
"var _ps=history.pushState;",
|
|
428
|
-
"var _rs=history.replaceState;",
|
|
429
|
-
"history.pushState=function(s,t,u){",
|
|
430
|
-
"if(typeof u==='string')u=rw(u);",
|
|
431
|
-
"return _ps.call(this,s,t,u);};",
|
|
432
|
-
"history.replaceState=function(s,t,u){",
|
|
433
|
-
"if(typeof u==='string')u=rw(u);",
|
|
434
|
-
"return _rs.call(this,s,t,u);};",
|
|
435
|
-
// --- location.assign / location.replace ---
|
|
436
|
-
"var _la=location.assign.bind(location);",
|
|
437
|
-
"var _lr=location.replace.bind(location);",
|
|
438
|
-
"location.assign=function(u){return _la(rw(u));};",
|
|
439
|
-
"location.replace=function(u){return _lr(rw(u));};",
|
|
440
|
-
// --- frame-busting defense ---
|
|
441
|
-
// Embedded SPAs (e.g. WeKnora) frequently do
|
|
442
|
-
// window.top.location.href = '/login'
|
|
443
|
-
// when they see a 401, intending to log the user out. Inside our
|
|
444
|
-
// capability proxy iframe `top` is the panel's main window — that
|
|
445
|
-
// tears the user away from the instance detail page entirely.
|
|
446
|
-
// Redirect `top`/`parent` to the iframe's own window so the
|
|
447
|
-
// navigation stays inside the embed. Safe because the iframe IS
|
|
448
|
-
// same-origin as the panel (our reverse proxy serves it from the
|
|
449
|
-
// panel's host); cross-origin access would throw and fail closed.
|
|
450
|
-
"try{",
|
|
451
|
-
"Object.defineProperty(window,'top',{configurable:true,get:function(){return window;}});",
|
|
452
|
-
"Object.defineProperty(window,'parent',{configurable:true,get:function(){return window;}});",
|
|
453
|
-
"}catch(_e){}",
|
|
454
|
-
// --- dynamic property assignment: img.src = '/static/...' ---
|
|
455
|
-
"function patchProp(tag,prop){",
|
|
456
|
-
"var d=Object.getOwnPropertyDescriptor(tag.prototype,prop);",
|
|
457
|
-
"if(!d||!d.set)return;",
|
|
458
|
-
"var orig=d.set;",
|
|
459
|
-
"Object.defineProperty(tag.prototype,prop,{",
|
|
460
|
-
"set:function(v){return orig.call(this,rw(v));},",
|
|
461
|
-
"get:d.get,configurable:true,enumerable:true});",
|
|
462
|
-
"}",
|
|
463
|
-
"patchProp(HTMLImageElement,'src');",
|
|
464
|
-
"patchProp(HTMLScriptElement,'src');",
|
|
465
|
-
"patchProp(HTMLLinkElement,'href');",
|
|
466
|
-
"patchProp(HTMLSourceElement,'src');",
|
|
467
|
-
// --- Worker monkey-patch ---
|
|
468
|
-
// Some SPA clients create socket.io/WebSocket connections from workers.
|
|
469
|
-
// Patch same-origin workers so the same proxy-prefixing rule applies there.
|
|
470
|
-
"var _Worker=window.Worker;",
|
|
471
|
-
`var _workerPrelude=${workerPrelude};`,
|
|
472
|
-
"function shouldWrapWorker(url){",
|
|
473
|
-
"try{var p=new URL(String(url),window.location.href);return p.protocol==='blob:'||p.protocol==='data:'||p.origin===O;}catch(_e){return false;}",
|
|
474
|
-
"}",
|
|
475
|
-
"function wrapWorker(url,options){",
|
|
476
|
-
"if(typeof _Worker!=='function'||!shouldWrapWorker(url))return url;",
|
|
477
|
-
"try{var resolved=new URL(String(url),window.location.href).href;",
|
|
478
|
-
"var isModule=!!(options&&options.type==='module');",
|
|
479
|
-
"var workerEnv='var __capProxyHost='+JSON.stringify(window.location.host)+';var __capProxyProtocol='+JSON.stringify(window.location.protocol)+';';",
|
|
480
|
-
"var source=isModule?workerEnv+_workerPrelude+'\\nimport '+JSON.stringify(resolved)+';':workerEnv+_workerPrelude+'\\nimportScripts('+JSON.stringify(resolved)+');';",
|
|
481
|
-
"return URL.createObjectURL(new Blob([source],{type:'text/javascript'}));",
|
|
482
|
-
"}catch(_e){return url;}",
|
|
483
|
-
"}",
|
|
484
|
-
"if(typeof _Worker==='function'){",
|
|
485
|
-
"window.Worker=function(url,options){var wrapped=wrapWorker(url,options);return options!==undefined?new _Worker(wrapped,options):new _Worker(wrapped);};",
|
|
486
|
-
"window.Worker.prototype=_Worker.prototype;",
|
|
487
|
-
"}",
|
|
488
|
-
// --- WebSocket ---
|
|
489
|
-
// SPAs like OpenWebUI use socket.io over WebSocket. The socket.io client
|
|
490
|
-
// builds ws:// URLs from window.location and the configured path; the URL
|
|
491
|
-
// ends up pointing at the panel root (e.g. ws://panel:8090/ws/socket.io)
|
|
492
|
-
// instead of the capability proxy. Without this patch the WS upgrade
|
|
493
|
-
// request either gets destroyed (no route) or hits the wrong backend.
|
|
494
|
-
"var _WS=window.WebSocket;",
|
|
495
|
-
"if(typeof _WS==='function'){",
|
|
496
|
-
"window.WebSocket=function(url,protocols){",
|
|
497
|
-
"url=rwWs(url);",
|
|
498
|
-
"return protocols!==undefined?new _WS(url,protocols):new _WS(url);",
|
|
499
|
-
"};",
|
|
500
|
-
"window.WebSocket.prototype=_WS.prototype;",
|
|
501
|
-
"window.WebSocket.CONNECTING=_WS.CONNECTING;",
|
|
502
|
-
"window.WebSocket.OPEN=_WS.OPEN;",
|
|
503
|
-
"window.WebSocket.CLOSING=_WS.CLOSING;",
|
|
504
|
-
"window.WebSocket.CLOSED=_WS.CLOSED;",
|
|
505
|
-
"}",
|
|
506
|
-
// --- EventSource ---
|
|
507
|
-
// Some frameworks use SSE (Server-Sent Events) for real-time updates.
|
|
508
|
-
"var _ES=window.EventSource;",
|
|
509
|
-
"if(typeof _ES==='function'){",
|
|
510
|
-
"window.EventSource=function(url,opts){",
|
|
511
|
-
"if(typeof url==='string')url=rw(url);",
|
|
512
|
-
"return new _ES(url,opts);",
|
|
513
|
-
"};",
|
|
514
|
-
"window.EventSource.prototype=_ES.prototype;",
|
|
515
|
-
"window.EventSource.CONNECTING=_ES.CONNECTING;",
|
|
516
|
-
"window.EventSource.OPEN=_ES.OPEN;",
|
|
517
|
-
"window.EventSource.CLOSED=_ES.CLOSED;",
|
|
518
|
-
"}",
|
|
519
|
-
"})();</script>",
|
|
520
|
-
].join("");
|
|
521
|
-
}
|
|
522
|
-
function rewriteProxyTextBody(body, contentType, proxyBasePath, extraHeadHtml = "") {
|
|
523
|
-
const value = (contentType ?? "").toLowerCase();
|
|
524
|
-
const proxyBaseWithSlash = `${proxyBasePath.replace(/\/+$/, "")}/`;
|
|
525
|
-
let rewritten = body;
|
|
526
|
-
if (value.includes("text/html")) {
|
|
527
|
-
// Rewrite asset URLs FIRST, then optionally inject a <base> tag.
|
|
528
|
-
// Reversing the order would let the regex below match (and double-
|
|
529
|
-
// prefix) the leading slash of the just-inserted `<base href="/api/...">`,
|
|
530
|
-
// producing
|
|
531
|
-
// <base href="/api/instances/X/provides/Y/api/instances/X/provides/Y/">
|
|
532
|
-
// which then resolves every relative asset to a 404.
|
|
533
|
-
rewritten = rewritten.replace(/((?:href|src|action|poster)=['"])\/(?!\/)/gi, `$1${proxyBaseWithSlash}`);
|
|
534
|
-
// Rewrite dynamic import() paths inside inline <script> blocks so that
|
|
535
|
-
// SvelteKit (and similar frameworks) resolve JS modules through the proxy.
|
|
536
|
-
// Matches import("/_app/...") and import('/_app/...').
|
|
537
|
-
rewritten = rewritten.replace(/\bimport\(\s*(['"])\/(?!\/)/g, `import($1${proxyBaseWithSlash}`);
|
|
538
|
-
// Rewrite SvelteKit's client-side base path so that client-side routing
|
|
539
|
-
// and subsequent chunk fetches go through the capability proxy path.
|
|
540
|
-
// Older SvelteKit SSR output: __sveltekit_XXXXX = { base: "" };
|
|
541
|
-
rewritten = rewritten.replace(/(__sveltekit_\w+\s*=\s*\{\s*base\s*:\s*)(["'])["']/, `$1$2${proxyBasePath.replace(/\/+$/, "")}$2`);
|
|
542
|
-
// SvelteKit 2.x start() config: paths: { base: "", assets: "..." }
|
|
543
|
-
rewritten = rewritten.replace(/(paths\s*:\s*\{\s*base\s*:\s*)(["'])["'](\s*,\s*assets\s*:)/, `$1$2${proxyBasePath.replace(/\/+$/, "")}$2$3`);
|
|
544
|
-
if (!/<base\b/i.test(rewritten)) {
|
|
545
|
-
if (/<head[^>]*>/i.test(rewritten)) {
|
|
546
|
-
rewritten = rewritten.replace(/<head([^>]*)>/i, `<head$1><base href="${proxyBaseWithSlash}">`);
|
|
547
|
-
}
|
|
548
|
-
else {
|
|
549
|
-
rewritten = `<base href="${proxyBaseWithSlash}">${rewritten}`;
|
|
550
|
-
}
|
|
551
|
-
}
|
|
552
|
-
if (extraHeadHtml) {
|
|
553
|
-
if (/<base\b/i.test(rewritten)) {
|
|
554
|
-
rewritten = rewritten.replace(/<base\b[^>]*>/i, (match) => `${match}${extraHeadHtml}`);
|
|
555
|
-
}
|
|
556
|
-
else if (/<head[^>]*>/i.test(rewritten)) {
|
|
557
|
-
rewritten = rewritten.replace(/<head([^>]*)>/i, `<head$1>${extraHeadHtml}`);
|
|
558
|
-
}
|
|
559
|
-
else {
|
|
560
|
-
rewritten = `${extraHeadHtml}${rewritten}`;
|
|
561
|
-
}
|
|
562
|
-
}
|
|
563
|
-
}
|
|
564
|
-
if (value.includes("text/css")) {
|
|
565
|
-
rewritten = rewritten.replace(/url\((['"]?)\/(?!\/)/gi, `url($1${proxyBaseWithSlash}`);
|
|
566
|
-
}
|
|
567
|
-
else if (value.includes("text/html")) {
|
|
568
|
-
// HTML can contain inline scripts like new URL("/..."); only rewrite lowercase CSS url(...).
|
|
569
|
-
rewritten = rewritten.replace(/url\((['"]?)\/(?!\/)/g, `url($1${proxyBaseWithSlash}`);
|
|
570
|
-
}
|
|
571
|
-
return rewritten;
|
|
572
|
-
}
|
|
573
|
-
function isReadableBody(value) {
|
|
574
|
-
if (value instanceof Readable)
|
|
575
|
-
return true;
|
|
576
|
-
if (!value || typeof value !== "object")
|
|
577
|
-
return false;
|
|
578
|
-
const candidate = value;
|
|
579
|
-
return (typeof candidate.pipe === "function" &&
|
|
580
|
-
typeof candidate.on === "function" &&
|
|
581
|
-
typeof candidate[Symbol.asyncIterator] === "function");
|
|
582
|
-
}
|
|
583
|
-
async function readProxyBodyStream(stream) {
|
|
584
|
-
const chunks = [];
|
|
585
|
-
for await (const chunk of stream) {
|
|
586
|
-
if (typeof chunk === "string") {
|
|
587
|
-
chunks.push(Buffer.from(chunk));
|
|
588
|
-
}
|
|
589
|
-
else if (chunk instanceof Uint8Array) {
|
|
590
|
-
chunks.push(Buffer.from(chunk));
|
|
591
|
-
}
|
|
592
|
-
else {
|
|
593
|
-
chunks.push(Buffer.from(String(chunk)));
|
|
594
|
-
}
|
|
595
|
-
}
|
|
596
|
-
return Buffer.concat(chunks);
|
|
597
|
-
}
|
|
598
|
-
function bytesToArrayBuffer(bytes) {
|
|
599
|
-
const out = new ArrayBuffer(bytes.byteLength);
|
|
600
|
-
new Uint8Array(out).set(bytes);
|
|
601
|
-
return out;
|
|
602
|
-
}
|
|
603
|
-
function isPlainRecord(value) {
|
|
604
|
-
if (!value || typeof value !== "object")
|
|
605
|
-
return false;
|
|
606
|
-
const proto = Object.getPrototypeOf(value);
|
|
607
|
-
return proto === Object.prototype || proto === null;
|
|
608
|
-
}
|
|
609
|
-
function encodeFormRecord(body) {
|
|
610
|
-
const params = new URLSearchParams();
|
|
611
|
-
for (const [key, value] of Object.entries(body)) {
|
|
612
|
-
if (Array.isArray(value)) {
|
|
613
|
-
for (const item of value)
|
|
614
|
-
params.append(key, String(item));
|
|
615
|
-
}
|
|
616
|
-
else {
|
|
617
|
-
params.append(key, String(value));
|
|
618
|
-
}
|
|
619
|
-
}
|
|
620
|
-
return params.toString();
|
|
621
|
-
}
|
|
622
|
-
async function buildProxyRequestBody(req) {
|
|
623
|
-
if (req.method === "GET" || req.method === "HEAD")
|
|
624
|
-
return undefined;
|
|
625
|
-
const body = req.body;
|
|
626
|
-
if (body == null)
|
|
627
|
-
return undefined;
|
|
628
|
-
if (typeof body === "string") {
|
|
629
|
-
return body;
|
|
630
|
-
}
|
|
631
|
-
if (body instanceof Uint8Array || Buffer.isBuffer(body))
|
|
632
|
-
return bytesToArrayBuffer(body);
|
|
633
|
-
if (isReadableBody(body)) {
|
|
634
|
-
return bytesToArrayBuffer(await readProxyBodyStream(body));
|
|
635
|
-
}
|
|
636
|
-
const contentType = String(req.headers["content-type"] ?? "").toLowerCase();
|
|
637
|
-
if (contentType.includes("application/x-www-form-urlencoded") && isPlainRecord(body)) {
|
|
638
|
-
return encodeFormRecord(body);
|
|
639
|
-
}
|
|
640
|
-
if (contentType.includes("application/json") && isPlainRecord(body)) {
|
|
641
|
-
return JSON.stringify(body);
|
|
642
|
-
}
|
|
643
|
-
if (isPlainRecord(body)) {
|
|
644
|
-
return JSON.stringify(body);
|
|
645
|
-
}
|
|
646
|
-
return undefined;
|
|
647
|
-
}
|
|
648
|
-
function parseCommandLine(input) {
|
|
649
|
-
const trimmed = input.trim();
|
|
650
|
-
if (!trimmed)
|
|
651
|
-
return [];
|
|
652
|
-
const args = [];
|
|
653
|
-
let current = "";
|
|
654
|
-
let quote = null;
|
|
655
|
-
let escaping = false;
|
|
656
|
-
for (const char of trimmed) {
|
|
657
|
-
if (escaping) {
|
|
658
|
-
current += char;
|
|
659
|
-
escaping = false;
|
|
660
|
-
continue;
|
|
661
|
-
}
|
|
662
|
-
if (char === "\\") {
|
|
663
|
-
escaping = true;
|
|
664
|
-
continue;
|
|
665
|
-
}
|
|
666
|
-
if (quote) {
|
|
667
|
-
if (char === quote) {
|
|
668
|
-
quote = null;
|
|
669
|
-
}
|
|
670
|
-
else {
|
|
671
|
-
current += char;
|
|
672
|
-
}
|
|
673
|
-
continue;
|
|
674
|
-
}
|
|
675
|
-
if (char === '"' || char === "'") {
|
|
676
|
-
quote = char;
|
|
677
|
-
continue;
|
|
678
|
-
}
|
|
679
|
-
if (/\s/.test(char)) {
|
|
680
|
-
if (current) {
|
|
681
|
-
args.push(current);
|
|
682
|
-
current = "";
|
|
683
|
-
}
|
|
684
|
-
continue;
|
|
685
|
-
}
|
|
686
|
-
current += char;
|
|
687
|
-
}
|
|
688
|
-
if (escaping)
|
|
689
|
-
current += "\\";
|
|
690
|
-
if (quote)
|
|
691
|
-
throw new Error("Command contains an unterminated quote");
|
|
692
|
-
if (current)
|
|
693
|
-
args.push(current);
|
|
694
|
-
return args;
|
|
695
|
-
}
|
|
696
|
-
function isTerminalProvide(provide) {
|
|
697
|
-
return !!provide && String(provide.protocol).toLowerCase() === "terminal" && !!provide.terminal;
|
|
698
|
-
}
|
|
699
|
-
function resolveTerminalProvide(instanceId, capability) {
|
|
700
|
-
const provide = instanceManager
|
|
701
|
-
.getProvidedCapabilitiesForApp(instanceId)
|
|
702
|
-
.find((entry) => entry.capability === capability);
|
|
703
|
-
if (!provide)
|
|
704
|
-
throw new Error(`Capability '${capability}' not found`);
|
|
705
|
-
if (!isTerminalProvide(provide)) {
|
|
706
|
-
throw new Error(`Capability '${capability}' is not a terminal provide`);
|
|
707
|
-
}
|
|
708
|
-
return provide;
|
|
709
|
-
}
|
|
710
|
-
function buildTerminalCommand(baseCommand, input) {
|
|
711
|
-
if (!Array.isArray(baseCommand) || baseCommand.length === 0 || baseCommand.some((part) => typeof part !== "string" || !part.trim())) {
|
|
712
|
-
throw new Error("Terminal provide is missing a valid base command");
|
|
713
|
-
}
|
|
714
|
-
const parsed = parseCommandLine(input);
|
|
715
|
-
if (!parsed.length)
|
|
716
|
-
throw new Error("Command cannot be empty");
|
|
717
|
-
const baseName = baseCommand[0].split("/").pop() || baseCommand[0];
|
|
718
|
-
const matchesBase = parsed.length >= baseCommand.length && baseCommand.every((part, index) => parsed[index] === part);
|
|
719
|
-
const matchesBaseName = parsed[0] === baseName;
|
|
720
|
-
if (matchesBase)
|
|
721
|
-
return parsed;
|
|
722
|
-
if (matchesBaseName)
|
|
723
|
-
return [baseCommand[0], ...parsed.slice(1)];
|
|
724
|
-
return [...baseCommand, ...parsed];
|
|
725
|
-
}
|
|
726
|
-
async function proxyProvidedCapability(req, reply) {
|
|
727
|
-
const idErr = validateId(req.params.id);
|
|
728
|
-
if (idErr)
|
|
729
|
-
return reply.status(400).send({ detail: idErr });
|
|
730
|
-
const rawInst = instanceManager.getInstance(req.params.id);
|
|
731
|
-
if (!rawInst)
|
|
732
|
-
return reply.status(404).send({ detail: "Instance not found" });
|
|
733
|
-
if (!instanceManager.getApp(req.params.id))
|
|
734
|
-
return reply.status(404).send({ detail: "App not found" });
|
|
735
|
-
const capabilities = instanceManager.getProvidedCapabilitiesForApp(req.params.id);
|
|
736
|
-
const capability = capabilities.find((entry) => entry.capability === req.params.capability);
|
|
737
|
-
if (!capability) {
|
|
738
|
-
return reply.status(404).send({ detail: `Capability '${req.params.capability}' not found` });
|
|
739
|
-
}
|
|
740
|
-
if (capability.visibility === "internal") {
|
|
741
|
-
return reply.status(403).send({ detail: `Capability '${req.params.capability}' is not externally accessible` });
|
|
742
|
-
}
|
|
743
|
-
if (capability.protocol !== "http" && capability.protocol !== "https") {
|
|
744
|
-
return reply.status(400).send({ detail: `Capability '${req.params.capability}' does not use HTTP(S)` });
|
|
745
|
-
}
|
|
746
|
-
// Resolve the runtime port (handles port reallocation) instead of using
|
|
747
|
-
// the declared AppSpec port which may be stale.
|
|
748
|
-
const runtimePort = instanceManager.resolveRuntimeCapabilityPort(req.params.id, req.params.capability)
|
|
749
|
-
?? capability.port;
|
|
750
|
-
if (typeof runtimePort !== "number" || runtimePort < 1) {
|
|
751
|
-
return reply.status(500).send({ detail: `Capability '${req.params.capability}' has no resolved port` });
|
|
752
|
-
}
|
|
753
|
-
const upstreamHost = await instanceManager.getHostForAppPort(req.params.id, runtimePort);
|
|
754
|
-
const upstreamOrigin = `${capability.protocol}://${instanceManager.urlHost(upstreamHost)}:${runtimePort}`;
|
|
755
|
-
const wildcardSuffix = typeof req.params["*"] === "string" ? req.params["*"] : "";
|
|
756
|
-
const proxyBasePath = capabilityProxyPath(req.params.id, req.params.capability);
|
|
757
|
-
const querySuffix = req.raw.url?.includes("?") ? req.raw.url.slice(req.raw.url.indexOf("?")) : "";
|
|
758
|
-
const requestPath = req.raw.url?.split("?")[0] ?? "";
|
|
759
|
-
const canonicalProxyBase = canonicalCapabilityProxyBase(proxyBasePath, capability.path);
|
|
760
|
-
if (!wildcardSuffix && canonicalProxyBase !== proxyBasePath && !requestPath.endsWith("/")) {
|
|
761
|
-
reply.code(308).header("location", `${canonicalProxyBase}${querySuffix}`);
|
|
762
|
-
return reply.send();
|
|
763
|
-
}
|
|
764
|
-
const upstreamPath = joinUpstreamPath(capability.path, wildcardSuffix);
|
|
765
|
-
const targetUrl = `${upstreamOrigin}${upstreamPath}${querySuffix}`;
|
|
766
|
-
const headers = new Headers();
|
|
767
|
-
for (const [key, value] of Object.entries(req.headers)) {
|
|
768
|
-
if (value == null)
|
|
769
|
-
continue;
|
|
770
|
-
const normalizedKey = key.toLowerCase();
|
|
771
|
-
if (HOP_BY_HOP.has(normalizedKey) || normalizedKey === "host" || normalizedKey === "content-length" || normalizedKey === "accept-encoding") {
|
|
772
|
-
continue;
|
|
773
|
-
}
|
|
774
|
-
// Strip panel session credentials to avoid leaking them upstream
|
|
775
|
-
// (consistent with the WebSocket capability proxy in server.ts)
|
|
776
|
-
if (normalizedKey === "authorization")
|
|
777
|
-
continue;
|
|
778
|
-
if (normalizedKey === "cookie") {
|
|
779
|
-
const stripped = stripPanelSessionCookie(value);
|
|
780
|
-
if (stripped)
|
|
781
|
-
headers.set(key, stripped);
|
|
782
|
-
continue;
|
|
783
|
-
}
|
|
784
|
-
if (Array.isArray(value)) {
|
|
785
|
-
for (const item of value)
|
|
786
|
-
headers.append(key, item);
|
|
787
|
-
}
|
|
788
|
-
else {
|
|
789
|
-
headers.set(key, String(value));
|
|
790
|
-
}
|
|
791
|
-
}
|
|
792
|
-
headers.set("accept-encoding", "identity");
|
|
793
|
-
if (headers.has("origin"))
|
|
794
|
-
headers.set("origin", upstreamOrigin);
|
|
795
|
-
// `x-forwarded-prefix` is not a standard reverse-proxy header and some
|
|
796
|
-
// upstream frameworks (notably SvelteKit apps like Hollama) treat it as a
|
|
797
|
-
// deployment base path, which breaks `/_app/*` asset resolution under this
|
|
798
|
-
// generic proxy. The HTML/base rewrite below already handles path prefixing.
|
|
799
|
-
if (req.headers.host)
|
|
800
|
-
headers.set("x-forwarded-host", String(req.headers.host));
|
|
801
|
-
headers.set("x-forwarded-proto", req.protocol);
|
|
802
|
-
const clientIp = typeof req.ip === "string" && req.ip
|
|
803
|
-
? req.ip
|
|
804
|
-
: typeof req.raw?.socket?.remoteAddress === "string"
|
|
805
|
-
? req.raw.socket.remoteAddress
|
|
806
|
-
: "";
|
|
807
|
-
if (clientIp) {
|
|
808
|
-
const forwardedFor = headers.get("x-forwarded-for");
|
|
809
|
-
headers.set("x-forwarded-for", forwardedFor ? `${forwardedFor}, ${clientIp}` : clientIp);
|
|
810
|
-
headers.set("x-real-ip", clientIp);
|
|
811
|
-
}
|
|
812
|
-
// Intercept service worker scripts BEFORE talking to upstream. SPAs like
|
|
813
|
-
// OpenWebUI register a SvelteKit service worker that aggressively caches
|
|
814
|
-
// HTML/JS at the proxy origin; once installed, the SW serves stale bodies
|
|
815
|
-
// and the page never receives our latest bootstrap (WebSocket / fetch
|
|
816
|
-
// monkey-patch). We replace the SW body with a self-unregistration stub so
|
|
817
|
-
// the next browser update cycle removes the offending worker and restores
|
|
818
|
-
// network-backed loading.
|
|
819
|
-
if (/(?:^|\/)(?:service-worker|sw)\.js$/i.test(requestPath)) {
|
|
820
|
-
reply
|
|
821
|
-
.code(200)
|
|
822
|
-
.header("content-type", "application/javascript; charset=utf-8")
|
|
823
|
-
.header("cache-control", "no-store, no-cache, must-revalidate, max-age=0")
|
|
824
|
-
.header("pragma", "no-cache")
|
|
825
|
-
.header("service-worker-allowed", "/");
|
|
826
|
-
return reply.send("// Capability proxy: service worker intentionally disabled.\n" +
|
|
827
|
-
"self.addEventListener('install',function(e){self.skipWaiting()});\n" +
|
|
828
|
-
"self.addEventListener('activate',function(e){\n" +
|
|
829
|
-
" e.waitUntil((async function(){\n" +
|
|
830
|
-
" try{var cs=await caches.keys();for(var i=0;i<cs.length;i++){try{await caches.delete(cs[i])}catch(_e){}}}catch(_e){}\n" +
|
|
831
|
-
" try{var clients=await self.clients.matchAll({includeUncontrolled:true});clients.forEach(function(c){try{c.navigate(c.url)}catch(_e){}})}catch(_e){}\n" +
|
|
832
|
-
" try{await self.registration.unregister()}catch(_e){}\n" +
|
|
833
|
-
" })());\n" +
|
|
834
|
-
"});\n");
|
|
835
|
-
}
|
|
836
|
-
// Single AbortController so we can cancel the upstream when the client
|
|
837
|
-
// disconnects. AbortSignal.timeout() only limits connection establishment;
|
|
838
|
-
// long-poll/SSE bodies (e.g. socket.io) would otherwise pin the fetch
|
|
839
|
-
// promise indefinitely and starve the event loop.
|
|
840
|
-
const upstreamAbort = new AbortController();
|
|
841
|
-
const connectTimer = setTimeout(() => upstreamAbort.abort(new Error("upstream connect timeout")), 30_000);
|
|
842
|
-
const onClientClose = () => {
|
|
843
|
-
if (!reply.raw.writableEnded)
|
|
844
|
-
upstreamAbort.abort(new Error("client disconnected"));
|
|
845
|
-
};
|
|
846
|
-
reply.raw.once("close", onClientClose);
|
|
847
|
-
try {
|
|
848
|
-
console.error("[cap-proxy] PRE buildBody method=", req.method, "bodyType=", typeof req.body, req.body?.constructor?.name, "signalAborted=", upstreamAbort.signal.aborted);
|
|
849
|
-
const requestBody = await buildProxyRequestBody(req);
|
|
850
|
-
console.error("[cap-proxy] POST buildBody size=", requestBody instanceof ArrayBuffer ? requestBody.byteLength : typeof requestBody === "string" ? requestBody.length : "undef", "signalAborted=", upstreamAbort.signal.aborted, "reason=", upstreamAbort.signal.reason?.message);
|
|
851
|
-
const upstream = await fetch(targetUrl, {
|
|
852
|
-
method: req.method,
|
|
853
|
-
headers,
|
|
854
|
-
body: requestBody,
|
|
855
|
-
redirect: "manual",
|
|
856
|
-
signal: upstreamAbort.signal,
|
|
857
|
-
}).finally(() => clearTimeout(connectTimer));
|
|
858
|
-
console.error("[cap-proxy] POST fetch status=", upstream.status);
|
|
859
|
-
const upstreamContentType = upstream.headers.get("content-type");
|
|
860
|
-
const willRewriteBody = shouldRewriteProxyResponse(upstreamContentType);
|
|
861
|
-
const willInjectHtml = (upstreamContentType ?? "").toLowerCase().includes("text/html");
|
|
862
|
-
reply.code(upstream.status);
|
|
863
|
-
upstream.headers.forEach((value, key) => {
|
|
864
|
-
const normalizedKey = key.toLowerCase();
|
|
865
|
-
if (HOP_BY_HOP.has(normalizedKey) || normalizedKey === "content-length" || normalizedKey === "content-encoding") {
|
|
866
|
-
return;
|
|
867
|
-
}
|
|
868
|
-
// When we rewrite the response body (HTML/CSS/JS), the upstream ETag /
|
|
869
|
-
// Cache-Control values describe the *original* upstream bytes — but the
|
|
870
|
-
// body the browser receives is post-rewrite (proxy-prefixed paths, JS
|
|
871
|
-
// hard-coded redirect targets, etc.). Honoring the upstream cache hints
|
|
872
|
-
// lets the browser pin a stale rewrite indefinitely: e.g. an early
|
|
873
|
-
// visit that pre-dated the JS rewrite gets cached and survives across
|
|
874
|
-
// app restarts, breaking the auth redirect logic until a hard refresh.
|
|
875
|
-
// Strip cache validators and force revalidation on every load.
|
|
876
|
-
if (willRewriteBody && (normalizedKey === "cache-control" ||
|
|
877
|
-
normalizedKey === "etag" ||
|
|
878
|
-
normalizedKey === "last-modified" ||
|
|
879
|
-
normalizedKey === "expires" ||
|
|
880
|
-
normalizedKey === "pragma")) {
|
|
881
|
-
return;
|
|
882
|
-
}
|
|
883
|
-
if (willInjectHtml && (normalizedKey === "content-security-policy" ||
|
|
884
|
-
normalizedKey === "content-security-policy-report-only" ||
|
|
885
|
-
normalizedKey === "x-frame-options")) {
|
|
886
|
-
return;
|
|
887
|
-
}
|
|
888
|
-
if (normalizedKey === "location") {
|
|
889
|
-
if (value.startsWith("/")) {
|
|
890
|
-
reply.header(key, rewriteCapabilityLocation(proxyBasePath, canonicalProxyBase, value));
|
|
891
|
-
return;
|
|
892
|
-
}
|
|
893
|
-
try {
|
|
894
|
-
const parsed = new URL(value);
|
|
895
|
-
const upstreamBase = new URL(upstreamOrigin);
|
|
896
|
-
if (parsed.origin === upstreamBase.origin) {
|
|
897
|
-
reply.header(key, rewriteCapabilityLocation(proxyBasePath, canonicalProxyBase, parsed.pathname, parsed.search, parsed.hash));
|
|
898
|
-
return;
|
|
899
|
-
}
|
|
900
|
-
}
|
|
901
|
-
catch {
|
|
902
|
-
// fall through to raw location header
|
|
903
|
-
}
|
|
904
|
-
}
|
|
905
|
-
reply.header(key, value);
|
|
906
|
-
});
|
|
907
|
-
if (req.method === "HEAD") {
|
|
908
|
-
reply.raw.off("close", onClientClose);
|
|
909
|
-
return reply.send();
|
|
910
|
-
}
|
|
911
|
-
if (willRewriteBody) {
|
|
912
|
-
// Pair with the cache-validator strip above.
|
|
913
|
-
reply.header("cache-control", "no-cache, no-store, must-revalidate");
|
|
914
|
-
reply.header("pragma", "no-cache");
|
|
915
|
-
reply.header("expires", "0");
|
|
916
|
-
let extraHeadHtml = "";
|
|
917
|
-
if (req.params.capability === "browserless-debugger") {
|
|
918
|
-
extraHeadHtml = browserlessDebuggerBootstrap(req.params.id);
|
|
919
|
-
}
|
|
920
|
-
if (willInjectHtml && req.params.capability === "web-jishukb") {
|
|
921
|
-
try {
|
|
922
|
-
const preloadedSessions = await loadJishuKbPreloadedSessions(upstreamOrigin, upstreamAbort.signal);
|
|
923
|
-
extraHeadHtml += jishuKbConversationBootstrap(preloadedSessions);
|
|
924
|
-
}
|
|
925
|
-
catch (error) {
|
|
926
|
-
console.warn("[cap-proxy] jishukb conversation preload skipped:", error);
|
|
927
|
-
}
|
|
928
|
-
}
|
|
929
|
-
// Inject a generic fetch/XHR monkey-patch for all capability-proxied
|
|
930
|
-
// HTML pages. SPA frameworks like SvelteKit compile absolute API paths
|
|
931
|
-
// (e.g. `/api/v1/...`, `/ollama/...`) into JS bundles at build time.
|
|
932
|
-
// When the page is served under the proxy path those requests bypass
|
|
933
|
-
// the proxy and hit the panel's own `/api/` routes instead. The patch
|
|
934
|
-
// intercepts fetch() and XMLHttpRequest.open() and rewrites same-origin
|
|
935
|
-
// absolute paths that do NOT already start with the proxy prefix.
|
|
936
|
-
extraHeadHtml += capabilityProxyBootstrap(proxyBasePath);
|
|
937
|
-
// First-visit cleanup: if the browser still has a stale ServiceWorker
|
|
938
|
-
// registered from an earlier panel build (which would intercept this
|
|
939
|
-
// navigation and serve cached HTML *without* the bootstrap patches),
|
|
940
|
-
// emit Clear-Site-Data so the browser drops the SW + its cache and
|
|
941
|
-
// reloads through the proxy. We mark the success with a long-lived
|
|
942
|
-
// cookie scoped to the proxy path to avoid a reload loop.
|
|
943
|
-
// Gate to HTML only — JS/CSS sub-resources also flow through this branch
|
|
944
|
-
// now that we rewrite JS bundles, and emitting Clear-Site-Data on a JS
|
|
945
|
-
// response would clear storage mid-page-load.
|
|
946
|
-
if (willInjectHtml) {
|
|
947
|
-
const cookieHeader = (req.headers.cookie || "").toString();
|
|
948
|
-
const swCleaned = /(?:^|;\s*)cap_proxy_sw_clean=1(?:;|$)/.test(cookieHeader);
|
|
949
|
-
if (!swCleaned) {
|
|
950
|
-
reply.header("Clear-Site-Data", '"cache", "storage"');
|
|
951
|
-
reply.header("Set-Cookie", `cap_proxy_sw_clean=1; Path=${proxyBasePath}; Max-Age=2592000; SameSite=Lax`);
|
|
952
|
-
}
|
|
953
|
-
}
|
|
954
|
-
const rawBody = await upstream.text();
|
|
955
|
-
reply.raw.off("close", onClientClose);
|
|
956
|
-
const rewritten = rewriteProxyTextBody(rawBody, upstreamContentType, proxyBasePath, extraHeadHtml);
|
|
957
|
-
return reply.send(rewritten);
|
|
958
|
-
}
|
|
959
|
-
if (!upstream.body) {
|
|
960
|
-
reply.raw.off("close", onClientClose);
|
|
961
|
-
return reply.send();
|
|
962
|
-
}
|
|
963
|
-
const readable = Readable.fromWeb(upstream.body);
|
|
964
|
-
readable.once("close", () => reply.raw.off("close", onClientClose));
|
|
965
|
-
return reply.send(readable);
|
|
966
|
-
}
|
|
967
|
-
catch (error) {
|
|
968
|
-
console.error("[cap-proxy] CATCH", error?.constructor?.name, error?.name, error?.message, "signalAborted=", upstreamAbort.signal.aborted, "reason=", upstreamAbort.signal.reason?.message, "stack=", error?.stack?.split("\n").slice(0, 4).join(" | "));
|
|
969
|
-
reply.raw.off("close", onClientClose);
|
|
970
|
-
return reply.status(502).send({ detail: error?.message || `Failed to proxy capability '${req.params.capability}'` });
|
|
971
|
-
}
|
|
972
|
-
}
|
|
973
|
-
export async function ensureControlUiAllowedOrigin(instanceId, origin) {
|
|
974
|
-
const normalizedOrigin = origin.trim();
|
|
975
|
-
if (!normalizedOrigin)
|
|
976
|
-
return false;
|
|
977
|
-
const config = instanceManager.getStoredConfig(instanceId);
|
|
978
|
-
if (!config)
|
|
979
|
-
return false;
|
|
980
|
-
const gateway = config.gateway ??= {};
|
|
981
|
-
const controlUi = gateway.controlUi ??= {};
|
|
982
|
-
const existing = Array.isArray(controlUi.allowedOrigins)
|
|
983
|
-
? controlUi.allowedOrigins.map((value) => String(value))
|
|
984
|
-
: [];
|
|
985
|
-
const normalized = new Set(existing.map((value) => value.trim().toLowerCase()).filter(Boolean));
|
|
986
|
-
if (normalized.has("*") || normalized.has(normalizedOrigin.toLowerCase()))
|
|
987
|
-
return false;
|
|
988
|
-
controlUi.allowedOrigins = [...existing.filter((value) => value.trim()), normalizedOrigin];
|
|
989
|
-
await instanceManager.saveConfig(instanceId, config);
|
|
990
|
-
return true;
|
|
991
|
-
}
|
|
992
|
-
// Resolve service manager once at route registration, re-resolve on config change
|
|
993
|
-
let _svc = null;
|
|
994
|
-
let _svcType = "";
|
|
995
|
-
export async function getSvc() {
|
|
996
|
-
const currentType = getServiceManagerType();
|
|
997
|
-
if (_svc && _svcType === currentType)
|
|
998
|
-
return _svc;
|
|
999
|
-
_svc = currentType === "nomad"
|
|
1000
|
-
? await import("../services/nomad-manager.js")
|
|
1001
|
-
: await import("../services/process-manager.js");
|
|
1002
|
-
_svcType = currentType;
|
|
1003
|
-
return _svc;
|
|
1004
|
-
}
|
|
1005
|
-
function getInstanceBackedInstalledApp(instanceId) {
|
|
1006
|
-
return instanceManager.getApp(instanceId);
|
|
1007
|
-
}
|
|
1008
|
-
function shouldUseAppManager(identity) {
|
|
1009
|
-
if (!identity)
|
|
1010
|
-
return false;
|
|
1011
|
-
if (identity.driver === "app-job")
|
|
1012
|
-
return true;
|
|
1013
|
-
return identity.driver === "local-model" && !!getInstanceBackedInstalledApp(identity.id);
|
|
1014
|
-
}
|
|
1015
|
-
function shouldUseAppManagerForId(instanceId, identity) {
|
|
1016
|
-
return shouldUseAppManager(identity) || (!identity && !!getInstanceBackedInstalledApp(instanceId));
|
|
1017
|
-
}
|
|
1018
|
-
function hasRuntimeIdentity(instanceId) {
|
|
1019
|
-
return resolveRuntimeIdentity(instanceId) != null
|
|
1020
|
-
|| !!instanceManager.getInstance(instanceId)
|
|
1021
|
-
|| !!getInstanceBackedInstalledApp(instanceId);
|
|
1022
|
-
}
|
|
1023
|
-
// TTL 15s: outlives the frontend 10s polling interval so most requests hit cache
|
|
1024
|
-
const statusCache = new TtlMap(15_000);
|
|
1025
|
-
const controlUiRestartInFlight = new Map();
|
|
1026
|
-
function getCachedStatus(svc, instanceId) {
|
|
1027
|
-
const cached = statusCache.get(instanceId);
|
|
1028
|
-
if (cached !== undefined)
|
|
1029
|
-
return Promise.resolve(cached);
|
|
1030
|
-
const identity = resolveRuntimeIdentity(instanceId);
|
|
1031
|
-
const statusPromise = shouldUseAppManagerForId(instanceId, identity)
|
|
1032
|
-
? instanceManager.getAppStatus(instanceId).then((data) => ({
|
|
1033
|
-
status: data.status,
|
|
1034
|
-
pid: data.pid,
|
|
1035
|
-
uptime: data.uptime,
|
|
1036
|
-
memory_mb: data.memory_mb,
|
|
1037
|
-
cpu_percent: data.cpu_percent,
|
|
1038
|
-
}))
|
|
1039
|
-
: Promise.resolve(svc.getStatus(instanceId));
|
|
1040
|
-
return statusPromise.then((data) => {
|
|
1041
|
-
statusCache.set(instanceId, data);
|
|
1042
|
-
return data;
|
|
1043
|
-
});
|
|
1044
|
-
}
|
|
1045
|
-
export async function restartRunningInstanceForControlUiOrigin(instanceId, origin) {
|
|
1046
|
-
const inFlight = controlUiRestartInFlight.get(instanceId);
|
|
1047
|
-
if (inFlight)
|
|
1048
|
-
return inFlight;
|
|
1049
|
-
const task = (async () => {
|
|
1050
|
-
const svc = await getSvc();
|
|
1051
|
-
const status = await svc.getStatus(instanceId);
|
|
1052
|
-
if (status.status !== "running")
|
|
1053
|
-
return;
|
|
1054
|
-
const result = await svc.restartInstance(instanceId);
|
|
1055
|
-
statusCache.delete(instanceId);
|
|
1056
|
-
if (!result.ok) {
|
|
1057
|
-
console.warn(`[gateway-launch] failed to auto-restart ${instanceId} after allowing origin ${origin}:`, result.error || "unknown error");
|
|
1058
|
-
return;
|
|
1059
|
-
}
|
|
1060
|
-
console.log(`[gateway-launch] auto-restarted ${instanceId} after allowing origin ${origin}`);
|
|
1061
|
-
})().finally(() => {
|
|
1062
|
-
controlUiRestartInFlight.delete(instanceId);
|
|
1063
|
-
});
|
|
1064
|
-
controlUiRestartInFlight.set(instanceId, task);
|
|
1065
|
-
return task;
|
|
1
|
+
import { assertNotLocked } from "../services/backup/backup-manager.js";
|
|
2
|
+
import * as appService from "../services/app-common/service.js";
|
|
3
|
+
import * as appLifecycle from "../services/app-common/lifecycle-service.js";
|
|
4
|
+
import { cleanupInstance as cleanupProxyInstance, getLastProxyError, } from "../services/llm-proxy/instance-proxy.js";
|
|
5
|
+
import { createInstance, isInstanceAdminError, validateId, } from "../services/instances/admin.js";
|
|
6
|
+
import { cloneInstance, isInstanceCloneError } from "../services/instances/clone.js";
|
|
7
|
+
import { getConnectionStatus, getConnectionSummary, isConnectionAdminError, replaceConnections, } from "../services/connections/admin.js";
|
|
8
|
+
import { getAppConfigMeta, isAppConfigAdminError, readAppConfig, writeAppConfig, } from "../services/instances/config-admin.js";
|
|
9
|
+
import { augmentInstanceMetadata, resolvePrimaryIntegrationKind, } from "../services/runtime/instance.js";
|
|
10
|
+
import { getIntegration } from "../services/integrations/index.js";
|
|
11
|
+
import { invalidateExecutionOwner } from "../services/app-common/execution-owner.js";
|
|
12
|
+
import { markRuntimeRepairRestartApplied } from "../services/repair/runtime-repair.js";
|
|
13
|
+
import { proxyProvidedCapability } from "../services/capability-proxy/http.js";
|
|
14
|
+
import { sendTerminalCapabilityInput, startTerminalCapabilitySession, stopTerminalCapabilitySession, streamTerminalCapabilitySession, } from "../services/capability-proxy/terminal.js";
|
|
15
|
+
import { inferRequestOrigin } from "../services/http/request-utils.js";
|
|
16
|
+
import { getCachedStatus } from "../services/instances/status.js";
|
|
17
|
+
import { approvePairingRequest, isInstancePairingError, listPairingRequests, } from "../services/instances/pairing.js";
|
|
18
|
+
// Generic instance API only. Product-specific HTTP behavior belongs in
|
|
19
|
+
// integrations/<kind> or app-modules/<app>, reached through explicit hooks.
|
|
20
|
+
function getLifecycleActionSource(req) {
|
|
21
|
+
const raw = req.headers["x-jishushell-action-source"];
|
|
22
|
+
const value = Array.isArray(raw) ? raw[0] : raw;
|
|
23
|
+
const source = typeof value === "string" ? value.trim() : "";
|
|
24
|
+
return /^[a-z0-9._:-]{1,80}$/i.test(source) ? source : "unknown";
|
|
1066
25
|
}
|
|
1067
26
|
export async function instanceRoutes(app) {
|
|
1068
27
|
// List
|
|
1069
28
|
app.get("/api/instances", async () => {
|
|
1070
|
-
const
|
|
1071
|
-
const
|
|
1072
|
-
const statuses = await Promise.all(instances.map(inst => getCachedStatus(svc, inst.id).catch(() => ({ status: "unknown" }))));
|
|
29
|
+
const instances = appService.listInstances();
|
|
30
|
+
const statuses = await Promise.all(instances.map(inst => getCachedStatus(inst.id, "api-list").catch(() => ({ status: "unknown", pid: null, uptime: null, memory_mb: null, cpu_percent: null }))));
|
|
1073
31
|
return Promise.all(instances.map(async (inst, i) => ({
|
|
1074
32
|
...(await augmentInstanceMetadata(inst.id, inst)),
|
|
1075
33
|
service: statuses[i],
|
|
@@ -1081,7 +39,7 @@ export async function instanceRoutes(app) {
|
|
|
1081
39
|
return await createInstance(req.body);
|
|
1082
40
|
}
|
|
1083
41
|
catch (e) {
|
|
1084
|
-
// Structured rejection from
|
|
42
|
+
// Structured rejection from integration create policy — return 409 with code
|
|
1085
43
|
if (e && e.name === "InstanceCreationRejected") {
|
|
1086
44
|
return reply.status(409).send({
|
|
1087
45
|
detail: e.hint,
|
|
@@ -1097,16 +55,50 @@ export async function instanceRoutes(app) {
|
|
|
1097
55
|
return reply.status(409).send({ detail: e.message });
|
|
1098
56
|
}
|
|
1099
57
|
});
|
|
58
|
+
app.post("/api/instances/:id/clone", async (req, reply) => {
|
|
59
|
+
const sourceIdError = validateId(req.params.id);
|
|
60
|
+
if (sourceIdError)
|
|
61
|
+
return reply.status(400).send({ detail: sourceIdError });
|
|
62
|
+
const targetId = typeof req.body?.id === "string" ? req.body.id : "";
|
|
63
|
+
const targetIdError = validateId(targetId);
|
|
64
|
+
if (targetIdError)
|
|
65
|
+
return reply.status(400).send({ detail: targetIdError });
|
|
66
|
+
const name = typeof req.body?.name === "string" ? req.body.name.trim() : "";
|
|
67
|
+
if (!name || name.length > 256) {
|
|
68
|
+
return reply.status(400).send({ detail: "Name must be 1-256 characters" });
|
|
69
|
+
}
|
|
70
|
+
if (typeof req.body?.description === "string" && req.body.description.length > 2048) {
|
|
71
|
+
return reply.status(400).send({ detail: "Description must be at most 2048 characters" });
|
|
72
|
+
}
|
|
73
|
+
try {
|
|
74
|
+
const result = await cloneInstance({
|
|
75
|
+
sourceInstanceId: req.params.id,
|
|
76
|
+
targetId,
|
|
77
|
+
name,
|
|
78
|
+
description: req.body?.description,
|
|
79
|
+
cloneOptions: req.body?.clone_options,
|
|
80
|
+
});
|
|
81
|
+
return reply.status(201).send(result);
|
|
82
|
+
}
|
|
83
|
+
catch (error) {
|
|
84
|
+
if (isInstanceCloneError(error)) {
|
|
85
|
+
return reply.status(error.statusCode).send({
|
|
86
|
+
detail: error.message,
|
|
87
|
+
...(error.code ? { code: error.code } : {}),
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
throw error;
|
|
91
|
+
}
|
|
92
|
+
});
|
|
1100
93
|
// Get
|
|
1101
94
|
app.get("/api/instances/:id", async (req, reply) => {
|
|
1102
95
|
const idErr = validateId(req.params.id);
|
|
1103
96
|
if (idErr)
|
|
1104
97
|
return reply.status(400).send({ detail: idErr });
|
|
1105
|
-
const
|
|
1106
|
-
const inst = instanceManager.getInstance(req.params.id);
|
|
98
|
+
const inst = appService.getInstance(req.params.id);
|
|
1107
99
|
if (!inst)
|
|
1108
100
|
return reply.status(404).send({ detail: "Instance not found" });
|
|
1109
|
-
const status = await getCachedStatus(
|
|
101
|
+
const status = await getCachedStatus(req.params.id, "api-detail");
|
|
1110
102
|
return {
|
|
1111
103
|
...(await augmentInstanceMetadata(req.params.id, inst)),
|
|
1112
104
|
service: status,
|
|
@@ -1130,11 +122,11 @@ export async function instanceRoutes(app) {
|
|
|
1130
122
|
catch (e) {
|
|
1131
123
|
return reply.status(e.statusCode || 409).send({ detail: e.message });
|
|
1132
124
|
}
|
|
1133
|
-
const inst =
|
|
125
|
+
const inst = appService.updateInstance(req.params.id, req.body.name, req.body.description);
|
|
1134
126
|
if (!inst)
|
|
1135
127
|
return reply.status(404).send({ detail: "Instance not found" });
|
|
1136
|
-
|
|
1137
|
-
return inst;
|
|
128
|
+
invalidateExecutionOwner(req.params.id);
|
|
129
|
+
return augmentInstanceMetadata(req.params.id, inst);
|
|
1138
130
|
});
|
|
1139
131
|
// Delete
|
|
1140
132
|
app.delete("/api/instances/:id", async (req, reply) => {
|
|
@@ -1147,61 +139,35 @@ export async function instanceRoutes(app) {
|
|
|
1147
139
|
catch (e) {
|
|
1148
140
|
return reply.status(e.statusCode || 409).send({ detail: e.message });
|
|
1149
141
|
}
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
142
|
+
const purgeBackups = req.query.purge_backups === "true";
|
|
143
|
+
const sudoPassword = typeof req.body?.sudoPassword === "string" && req.body.sudoPassword.trim()
|
|
144
|
+
? req.body.sudoPassword
|
|
145
|
+
: undefined;
|
|
146
|
+
const result = await appLifecycle.deleteManagedInstance(req.params.id, {
|
|
147
|
+
purgeBackups,
|
|
148
|
+
...(sudoPassword ? { exec: { sudoPassword } } : {}),
|
|
149
|
+
});
|
|
150
|
+
if (!result.ok) {
|
|
151
|
+
const status = result.code === "TASK_BUSY"
|
|
152
|
+
? 409
|
|
153
|
+
: result.code === "APP_NOT_FOUND" || result.code === "INSTANCE_NOT_FOUND"
|
|
154
|
+
? 404
|
|
155
|
+
: 400;
|
|
156
|
+
return reply.status(status).send({
|
|
157
|
+
detail: result.error,
|
|
158
|
+
...(result.code ? { code: result.code } : {}),
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
invalidateExecutionOwner(req.params.id);
|
|
162
|
+
cleanupProxyInstance(req.params.id);
|
|
163
|
+
if (result.taskId) {
|
|
1163
164
|
return reply.status(202).send({
|
|
1164
165
|
ok: true,
|
|
1165
166
|
taskId: result.taskId,
|
|
1166
|
-
...result.reused ? { reused: true } : {},
|
|
167
|
+
...(result.reused ? { reused: true } : {}),
|
|
1167
168
|
});
|
|
1168
169
|
}
|
|
1169
|
-
|
|
1170
|
-
let stopFailed = false;
|
|
1171
|
-
try {
|
|
1172
|
-
await svc.stopInstance(req.params.id, true);
|
|
1173
|
-
}
|
|
1174
|
-
catch {
|
|
1175
|
-
try {
|
|
1176
|
-
await svc.stopInstance(req.params.id);
|
|
1177
|
-
}
|
|
1178
|
-
catch {
|
|
1179
|
-
stopFailed = true;
|
|
1180
|
-
}
|
|
1181
|
-
}
|
|
1182
|
-
// Also stop any legacy process-manager process that might be lingering
|
|
1183
|
-
try {
|
|
1184
|
-
const { getLegacyStatus, stopInstance: stopLegacy } = await import("../services/process-manager.js");
|
|
1185
|
-
if ((await getLegacyStatus(req.params.id)).status === "running") {
|
|
1186
|
-
await stopLegacy(req.params.id);
|
|
1187
|
-
stopFailed = false;
|
|
1188
|
-
}
|
|
1189
|
-
}
|
|
1190
|
-
catch { /* ignore */ }
|
|
1191
|
-
statusCache.delete(req.params.id);
|
|
1192
|
-
invalidateRuntimeIdentity(req.params.id);
|
|
1193
|
-
cleanupProxyInstance(req.params.id);
|
|
1194
|
-
const purgeBackups = req.query.purge_backups === "true";
|
|
1195
|
-
const result = await instanceManager.deleteInstance(req.params.id, purgeBackups);
|
|
1196
|
-
if (!result.ok && result.warnings?.some(w => w.includes("not found"))) {
|
|
1197
|
-
return reply.status(404).send({ detail: "Instance not found" });
|
|
1198
|
-
}
|
|
1199
|
-
const warnings = result.warnings ? [...result.warnings] : [];
|
|
1200
|
-
if (stopFailed) {
|
|
1201
|
-
console.warn(`[instances] Delete ${req.params.id}: service stop failed, orphaned processes may remain`);
|
|
1202
|
-
warnings.push("Service stop did not complete; verify no orphaned processes remain.");
|
|
1203
|
-
}
|
|
1204
|
-
return { ok: result.ok, warnings: warnings.length ? warnings : undefined };
|
|
170
|
+
return { ok: true, warnings: result.warnings?.length ? result.warnings : undefined };
|
|
1205
171
|
});
|
|
1206
172
|
// Config
|
|
1207
173
|
app.get("/api/instances/:id/config-meta", async (req, reply) => {
|
|
@@ -1245,15 +211,20 @@ export async function instanceRoutes(app) {
|
|
|
1245
211
|
const idErr = validateId(req.params.id);
|
|
1246
212
|
if (idErr)
|
|
1247
213
|
return reply.status(400).send({ detail: idErr });
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
return reply.status(404).send({ detail: "Instance not found" });
|
|
214
|
+
let status;
|
|
215
|
+
try {
|
|
216
|
+
status = await appLifecycle.getManagedStatus(req.params.id);
|
|
1252
217
|
}
|
|
1253
|
-
|
|
1254
|
-
|
|
218
|
+
catch (error) {
|
|
219
|
+
if (appService.isCanonicalRuntimePortRequiredError(error)) {
|
|
220
|
+
return reply.status(error.statusCode || 409).send({ detail: error.message, code: error.code });
|
|
221
|
+
}
|
|
222
|
+
throw error;
|
|
1255
223
|
}
|
|
1256
|
-
|
|
224
|
+
if (!status) {
|
|
225
|
+
return reply.status(404).send({ detail: "Instance not found" });
|
|
226
|
+
}
|
|
227
|
+
return status;
|
|
1257
228
|
});
|
|
1258
229
|
app.post("/api/instances/:id/service/start", async (req, reply) => {
|
|
1259
230
|
const idErr = validateId(req.params.id);
|
|
@@ -1265,21 +236,18 @@ export async function instanceRoutes(app) {
|
|
|
1265
236
|
catch (e) {
|
|
1266
237
|
return reply.status(e.statusCode || 409).send({ detail: e.message });
|
|
1267
238
|
}
|
|
1268
|
-
const
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
: await svc.startInstance(req.params.id);
|
|
1276
|
-
statusCache.delete(req.params.id);
|
|
1277
|
-
invalidateRuntimeIdentity(req.params.id);
|
|
239
|
+
const actionSource = getLifecycleActionSource(req);
|
|
240
|
+
console.log(`[lifecycle] start requested for ${req.params.id} source=${actionSource}`);
|
|
241
|
+
const controlUiOrigin = inferRequestOrigin(req);
|
|
242
|
+
const result = controlUiOrigin
|
|
243
|
+
? await appLifecycle.startInstance(req.params.id, { controlUiOrigin })
|
|
244
|
+
: await appLifecycle.startInstance(req.params.id);
|
|
245
|
+
invalidateExecutionOwner(req.params.id);
|
|
1278
246
|
if (!result.ok) {
|
|
1279
247
|
const resultRecord = result;
|
|
1280
248
|
// Surface the phase tag so the UI can highlight where the start
|
|
1281
249
|
// pipeline failed (running_check / home_conflict / port_alloc /
|
|
1282
|
-
//
|
|
250
|
+
// port allocation / submit). Legacy clients that only read `detail`
|
|
1283
251
|
// keep working.
|
|
1284
252
|
const payload = { detail: result.error };
|
|
1285
253
|
if (resultRecord.phase)
|
|
@@ -1290,6 +258,9 @@ export async function instanceRoutes(app) {
|
|
|
1290
258
|
payload.taskId = resultRecord.taskId;
|
|
1291
259
|
if (resultRecord.code)
|
|
1292
260
|
payload.code = resultRecord.code;
|
|
261
|
+
if (resultRecord.code === "INSTANCE_NOT_FOUND") {
|
|
262
|
+
return reply.status(404).send(payload);
|
|
263
|
+
}
|
|
1293
264
|
// Honor the structured ConnectionError statusCode (412 / 409 / 400)
|
|
1294
265
|
// when present so the UI can distinguish missing-required from
|
|
1295
266
|
// ambiguous-prefix from invalid-binding without parsing the message.
|
|
@@ -1298,7 +269,7 @@ export async function instanceRoutes(app) {
|
|
|
1298
269
|
: 400;
|
|
1299
270
|
return reply.status(statusCode).send(payload);
|
|
1300
271
|
}
|
|
1301
|
-
|
|
272
|
+
markRuntimeRepairRestartApplied(req.params.id);
|
|
1302
273
|
return result;
|
|
1303
274
|
});
|
|
1304
275
|
app.post("/api/instances/:id/service/stop", async (req, reply) => {
|
|
@@ -1311,18 +282,14 @@ export async function instanceRoutes(app) {
|
|
|
1311
282
|
catch (e) {
|
|
1312
283
|
return reply.status(e.statusCode || 409).send({ detail: e.message });
|
|
1313
284
|
}
|
|
1314
|
-
const
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
285
|
+
const actionSource = getLifecycleActionSource(req);
|
|
286
|
+
console.log(`[lifecycle] stop requested for ${req.params.id} source=${actionSource}`);
|
|
287
|
+
const result = await appLifecycle.stopInstance(req.params.id);
|
|
288
|
+
invalidateExecutionOwner(req.params.id);
|
|
289
|
+
if (!result.ok) {
|
|
290
|
+
const statusCode = result.code === "INSTANCE_NOT_FOUND" ? 404 : 400;
|
|
291
|
+
return reply.status(statusCode).send({ detail: result.error, ...(result.code ? { code: result.code } : {}) });
|
|
1318
292
|
}
|
|
1319
|
-
const result = shouldUseAppManagerForId(req.params.id, identity)
|
|
1320
|
-
? await instanceManager.stopApp(req.params.id)
|
|
1321
|
-
: await svc.stopInstance(req.params.id);
|
|
1322
|
-
statusCache.delete(req.params.id);
|
|
1323
|
-
invalidateRuntimeIdentity(req.params.id);
|
|
1324
|
-
if (!result.ok)
|
|
1325
|
-
return reply.status(400).send({ detail: result.error });
|
|
1326
293
|
return result;
|
|
1327
294
|
});
|
|
1328
295
|
app.post("/api/instances/:id/service/restart", async (req, reply) => {
|
|
@@ -1335,19 +302,21 @@ export async function instanceRoutes(app) {
|
|
|
1335
302
|
catch (e) {
|
|
1336
303
|
return reply.status(e.statusCode || 409).send({ detail: e.message });
|
|
1337
304
|
}
|
|
1338
|
-
const
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
305
|
+
const actionSource = getLifecycleActionSource(req);
|
|
306
|
+
console.log(`[lifecycle] restart requested for ${req.params.id} source=${actionSource}`);
|
|
307
|
+
const controlUiOrigin = inferRequestOrigin(req);
|
|
308
|
+
const result = controlUiOrigin
|
|
309
|
+
? await appLifecycle.restartInstance(req.params.id, { controlUiOrigin })
|
|
310
|
+
: await appLifecycle.restartInstance(req.params.id);
|
|
311
|
+
invalidateExecutionOwner(req.params.id);
|
|
312
|
+
if (!result.ok) {
|
|
313
|
+
const statusCode = result.code === "INSTANCE_NOT_FOUND" ? 404 : 400;
|
|
314
|
+
return reply.status(statusCode).send({
|
|
315
|
+
detail: result.error || "Unknown error",
|
|
316
|
+
...(result.code ? { code: result.code } : {}),
|
|
317
|
+
});
|
|
1342
318
|
}
|
|
1343
|
-
|
|
1344
|
-
? await instanceManager.restartApp(req.params.id)
|
|
1345
|
-
: await svc.restartInstance(req.params.id);
|
|
1346
|
-
statusCache.delete(req.params.id);
|
|
1347
|
-
invalidateRuntimeIdentity(req.params.id);
|
|
1348
|
-
if (!result.ok)
|
|
1349
|
-
return reply.status(400).send({ detail: result.error || "Unknown error" });
|
|
1350
|
-
await acknowledgeRuntimeRestartAdvisory(req.params.id);
|
|
319
|
+
markRuntimeRepairRestartApplied(req.params.id);
|
|
1351
320
|
return result;
|
|
1352
321
|
});
|
|
1353
322
|
// ── Pairing ──────────────────────────────────────────────────────────────
|
|
@@ -1359,33 +328,19 @@ export async function instanceRoutes(app) {
|
|
|
1359
328
|
const idErr = validateId(req.params.id);
|
|
1360
329
|
if (idErr)
|
|
1361
330
|
return reply.status(400).send({ detail: idErr });
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
return reply.status(404).send({ detail: "Instance not found" });
|
|
331
|
+
try {
|
|
332
|
+
return await listPairingRequests(req.params.id);
|
|
1365
333
|
}
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
334
|
+
catch (error) {
|
|
335
|
+
if (isInstancePairingError(error))
|
|
336
|
+
return reply.status(error.statusCode).send({ detail: error.message });
|
|
337
|
+
throw error;
|
|
1369
338
|
}
|
|
1370
|
-
const agentType = resolveAgentType(inst);
|
|
1371
|
-
const svc = await getSvc();
|
|
1372
|
-
// Pure adapter dispatch — no hardcoded kind fallback.
|
|
1373
|
-
const cmd = await getAdapter(agentType).buildPairingListCommand(req.params.id);
|
|
1374
|
-
const result = await svc.exec(req.params.id, cmd, 15_000);
|
|
1375
|
-
return { output: result.stdout + result.stderr, exitCode: result.exitCode };
|
|
1376
339
|
});
|
|
1377
340
|
app.post("/api/instances/:id/pairing/approve", async (req, reply) => {
|
|
1378
341
|
const idErr = validateId(req.params.id);
|
|
1379
342
|
if (idErr)
|
|
1380
343
|
return reply.status(400).send({ detail: idErr });
|
|
1381
|
-
const inst = instanceManager.getInstance(req.params.id);
|
|
1382
|
-
if (!inst) {
|
|
1383
|
-
return reply.status(404).send({ detail: "Instance not found" });
|
|
1384
|
-
}
|
|
1385
|
-
const capabilities = await getInstanceCapabilities(req.params.id, inst);
|
|
1386
|
-
if (!capabilities.pairing.approve) {
|
|
1387
|
-
return reply.status(501).send({ detail: "Pairing approve is not supported for this runtime" });
|
|
1388
|
-
}
|
|
1389
344
|
const { channel, code, notify } = req.body ?? {};
|
|
1390
345
|
if (!channel || !PAIRING_CHANNEL_RE.test(channel)) {
|
|
1391
346
|
return reply.status(400).send({ detail: "Invalid channel: must be lowercase alphanumeric/hyphen/underscore" });
|
|
@@ -1393,26 +348,23 @@ export async function instanceRoutes(app) {
|
|
|
1393
348
|
if (!code || !PAIRING_CODE_RE.test(code)) {
|
|
1394
349
|
return reply.status(400).send({ detail: "Invalid pairing code: must be 4-16 uppercase alphanumeric characters" });
|
|
1395
350
|
}
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
const result = await svc.exec(req.params.id, cmd, 15_000);
|
|
1404
|
-
if (result.exitCode !== 0) {
|
|
1405
|
-
return reply.status(400).send({ detail: (result.stderr || result.stdout || "Approval failed").trim() });
|
|
351
|
+
try {
|
|
352
|
+
return await approvePairingRequest(req.params.id, { channel, code, notify });
|
|
353
|
+
}
|
|
354
|
+
catch (error) {
|
|
355
|
+
if (isInstancePairingError(error))
|
|
356
|
+
return reply.status(error.statusCode).send({ detail: error.message });
|
|
357
|
+
throw error;
|
|
1406
358
|
}
|
|
1407
|
-
return { ok: true, output: (result.stdout + result.stderr).trim() };
|
|
1408
359
|
});
|
|
1409
|
-
//
|
|
1410
|
-
//
|
|
1411
|
-
//
|
|
360
|
+
// Inline Chat surface for runtimes that choose the JishuShell-rendered Chat
|
|
361
|
+
// tab instead of an iframe-backed app UI. The runtime declares how Core can
|
|
362
|
+
// reach its chat endpoint via `inlineChatDescriptor`; this route owns only
|
|
363
|
+
// the shared forwarding/SSE wrapper.
|
|
1412
364
|
//
|
|
1413
|
-
// Flow: panel JWT auth
|
|
1414
|
-
// read allocated host port from runtime.ports
|
|
1415
|
-
//
|
|
365
|
+
// Flow: panel JWT auth -> read the declared per-instance secret from
|
|
366
|
+
// integration-home/.env -> read allocated host port from runtime.ports ->
|
|
367
|
+
// POST forward to the declared runtime chat endpoint.
|
|
1416
368
|
//
|
|
1417
369
|
// The response is framed as Server-Sent Events with periodic `: ping`
|
|
1418
370
|
// heartbeats while we wait for the agent to finish. Long-running agent
|
|
@@ -1424,53 +376,62 @@ export async function instanceRoutes(app) {
|
|
|
1424
376
|
// Errors before headers are sent fall back to HTTP 5xx JSON; errors
|
|
1425
377
|
// after hijack go out as an `event: error` SSE payload.
|
|
1426
378
|
//
|
|
1427
|
-
// This is a thin server-side forwarder, NOT a new LLM proxy.
|
|
1428
|
-
//
|
|
1429
|
-
// upstream provider.
|
|
379
|
+
// This is a thin server-side forwarder, NOT a new LLM proxy. Managed model
|
|
380
|
+
// traffic still goes through the runtime's configured Core proxy binding.
|
|
1430
381
|
app.post("/api/instances/:id/agent/chat", async (req, reply) => {
|
|
1431
382
|
const idErr = validateId(req.params.id);
|
|
1432
383
|
if (idErr)
|
|
1433
384
|
return reply.status(400).send({ detail: idErr });
|
|
1434
|
-
const rawInst =
|
|
385
|
+
const rawInst = appService.getInstance(req.params.id);
|
|
1435
386
|
if (!rawInst)
|
|
1436
387
|
return reply.status(404).send({ detail: "Instance not found" });
|
|
1437
|
-
// getInstance returns raw instance.json without `capabilities` (
|
|
1438
|
-
//
|
|
1439
|
-
// read the
|
|
388
|
+
// getInstance returns raw instance.json without `capabilities` (those are
|
|
389
|
+
// synthesized by the integration layer). Use augmentInstanceMetadata so we
|
|
390
|
+
// read the integration's live defaultCapabilities.
|
|
1440
391
|
const inst = await augmentInstanceMetadata(req.params.id, rawInst);
|
|
392
|
+
const integrationKind = resolvePrimaryIntegrationKind(inst);
|
|
1441
393
|
// Only runtimes declaring chatPanel="inline" are supported here
|
|
1442
|
-
const chatPanel = inst?.capabilities?.
|
|
394
|
+
const chatPanel = inst?.capabilities?.ui?.chatPanel;
|
|
1443
395
|
if (chatPanel !== "inline") {
|
|
1444
396
|
return reply.status(400).send({
|
|
1445
|
-
detail: `Runtime "${
|
|
397
|
+
detail: `Runtime "${integrationKind ?? "generic"}" does not support inline chat (chatPanel=${chatPanel})`,
|
|
398
|
+
});
|
|
399
|
+
}
|
|
400
|
+
// Integration-owned dispatch: any integration that declares chatPanel
|
|
401
|
+
// "inline" MUST also supply `inlineChatDescriptor` (secret env var plus
|
|
402
|
+
// optional path/header/timeout) so this forwarder can reach its runtime.
|
|
403
|
+
if (!integrationKind) {
|
|
404
|
+
return reply.status(500).send({
|
|
405
|
+
detail: `Instance "${req.params.id}" has no integration identity but declared chatPanel=inline`,
|
|
1446
406
|
});
|
|
1447
407
|
}
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
// "inline" MUST also supply `inlineChatDescriptor` (api key env var +
|
|
1451
|
-
// optional path/header/timeout) so this forwarder can reach its agent.
|
|
1452
|
-
const agentType = resolveAgentType(inst);
|
|
1453
|
-
const adapter = getAdapter(agentType);
|
|
1454
|
-
const desc = adapter.inlineChatDescriptor;
|
|
408
|
+
const integration = getIntegration(integrationKind);
|
|
409
|
+
const desc = integration.inlineChatDescriptor;
|
|
1455
410
|
if (!desc) {
|
|
1456
411
|
return reply.status(500).send({
|
|
1457
|
-
detail: `Runtime "${
|
|
412
|
+
detail: `Runtime "${integrationKind}" declares chatPanel=inline but no inlineChatDescriptor`,
|
|
1458
413
|
});
|
|
1459
414
|
}
|
|
1460
415
|
// Resolve host port from the persisted RuntimeSpec.ports[] allocation.
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
416
|
+
let hostPort = 0;
|
|
417
|
+
let gwHost = "127.0.0.1";
|
|
418
|
+
try {
|
|
419
|
+
hostPort = appService.getPrimaryHostPort(req.params.id);
|
|
420
|
+
gwHost = await appService.getPrimaryHostForInstance(req.params.id);
|
|
421
|
+
}
|
|
422
|
+
catch (error) {
|
|
423
|
+
if (appService.isCanonicalRuntimePortRequiredError(error)) {
|
|
424
|
+
return reply.status(error.statusCode || 409).send({ detail: error.message, code: error.code });
|
|
425
|
+
}
|
|
426
|
+
throw error;
|
|
1466
427
|
}
|
|
1467
|
-
//
|
|
1468
|
-
// declares which env var holds it
|
|
428
|
+
// The runtime API key lives in the integration-managed secretEnv file.
|
|
429
|
+
// Integration declares which env var holds it.
|
|
1469
430
|
const secretEnv = inst?.paths?.secretEnv;
|
|
1470
431
|
if (!secretEnv) {
|
|
1471
432
|
return reply.status(500).send({ detail: "Instance has no secretEnv path" });
|
|
1472
433
|
}
|
|
1473
|
-
const envVars =
|
|
434
|
+
const envVars = appService.parseEnvFile(secretEnv);
|
|
1474
435
|
const apiKey = envVars[desc.apiKeyEnvVar] || "";
|
|
1475
436
|
if (!apiKey) {
|
|
1476
437
|
return reply.status(500).send({
|
|
@@ -1480,8 +441,8 @@ export async function instanceRoutes(app) {
|
|
|
1480
441
|
const endpointPath = desc.endpointPath ?? "/v1/chat/completions";
|
|
1481
442
|
const authHeader = desc.authHeader ?? "Authorization";
|
|
1482
443
|
const authScheme = desc.authScheme ?? "Bearer ";
|
|
1483
|
-
// Upstream budget: the
|
|
1484
|
-
// a wedged container can't hold the connection forever.
|
|
444
|
+
// Upstream budget: the runtime call still gets a hard ceiling so
|
|
445
|
+
// a wedged container can't hold the connection forever. Integration can
|
|
1485
446
|
// extend this via inlineChatDescriptor.timeoutMs; default is 30 min
|
|
1486
447
|
// which comfortably covers multi-step tool loops.
|
|
1487
448
|
const upstreamTimeoutMs = desc.timeoutMs ?? 30 * 60_000;
|
|
@@ -1490,8 +451,7 @@ export async function instanceRoutes(app) {
|
|
|
1490
451
|
// on modern Linux (Debian 12, Ubuntu 22.04+) that's frequently `::1`
|
|
1491
452
|
// rather than `127.0.0.1` — so a hardcoded IPv4 fetch() returns
|
|
1492
453
|
// ECONNREFUSED and the user sees "Failed to reach agent".
|
|
1493
|
-
const
|
|
1494
|
-
const target = `http://${instanceManager.urlHost(gwHost)}:${hostPort}${endpointPath}`;
|
|
454
|
+
const target = `http://${appService.urlHost(gwHost)}:${hostPort}${endpointPath}`;
|
|
1495
455
|
// Hijack the response so we own the raw socket — lets us flush SSE
|
|
1496
456
|
// headers + heartbeats before the upstream fetch resolves.
|
|
1497
457
|
reply.hijack();
|
|
@@ -1554,101 +514,16 @@ export async function instanceRoutes(app) {
|
|
|
1554
514
|
}
|
|
1555
515
|
});
|
|
1556
516
|
app.post("/api/instances/:id/provides/:capability/terminal/session", async (req, reply) => {
|
|
1557
|
-
|
|
1558
|
-
if (idErr)
|
|
1559
|
-
return reply.status(400).send({ detail: idErr });
|
|
1560
|
-
if (!instanceManager.getInstance(req.params.id) && !getInstanceBackedInstalledApp(req.params.id)) {
|
|
1561
|
-
return reply.status(404).send({ detail: "Instance not found" });
|
|
1562
|
-
}
|
|
1563
|
-
try {
|
|
1564
|
-
const provide = resolveTerminalProvide(req.params.id, req.params.capability);
|
|
1565
|
-
const terminal = provide.terminal;
|
|
1566
|
-
const input = typeof req.body?.input === "string" ? req.body.input : "";
|
|
1567
|
-
const command = buildTerminalCommand(terminal.command, input);
|
|
1568
|
-
const session = startTerminalSession({
|
|
1569
|
-
instanceId: req.params.id,
|
|
1570
|
-
capability: req.params.capability,
|
|
1571
|
-
terminal,
|
|
1572
|
-
command,
|
|
1573
|
-
});
|
|
1574
|
-
return reply.send(session);
|
|
1575
|
-
}
|
|
1576
|
-
catch (error) {
|
|
1577
|
-
return reply.status(400).send({ detail: error?.message || "Failed to start terminal session" });
|
|
1578
|
-
}
|
|
517
|
+
return startTerminalCapabilitySession(req, reply);
|
|
1579
518
|
});
|
|
1580
519
|
app.get("/api/instances/:id/provides/:capability/terminal/session/:sessionId/stream", async (req, reply) => {
|
|
1581
|
-
|
|
1582
|
-
if (idErr)
|
|
1583
|
-
return reply.status(400).send({ detail: idErr });
|
|
1584
|
-
if (!assertTerminalSessionOwner(req.params.sessionId, req.params.id, req.params.capability)) {
|
|
1585
|
-
return reply.status(404).send({ detail: "Terminal session not found" });
|
|
1586
|
-
}
|
|
1587
|
-
const session = getTerminalSession(req.params.sessionId);
|
|
1588
|
-
if (!session)
|
|
1589
|
-
return reply.status(404).send({ detail: "Terminal session not found" });
|
|
1590
|
-
const since = Math.max(parseInt(req.query.since || "0", 10) || 0, 0);
|
|
1591
|
-
reply.hijack();
|
|
1592
|
-
const raw = reply.raw;
|
|
1593
|
-
raw.writeHead(200, {
|
|
1594
|
-
"Content-Type": "text/event-stream; charset=utf-8",
|
|
1595
|
-
"Cache-Control": "no-cache, no-transform",
|
|
1596
|
-
"Connection": "keep-alive",
|
|
1597
|
-
"X-Accel-Buffering": "no",
|
|
1598
|
-
});
|
|
1599
|
-
const writeEvent = (event, data) => {
|
|
1600
|
-
raw.write(`event: ${event}\ndata: ${JSON.stringify(data)}\n\n`);
|
|
1601
|
-
};
|
|
1602
|
-
for (const event of getTerminalSessionEvents(req.params.sessionId, since)) {
|
|
1603
|
-
writeEvent(event.type, event);
|
|
1604
|
-
}
|
|
1605
|
-
if (!session.running) {
|
|
1606
|
-
writeEvent("done", { sessionId: req.params.sessionId });
|
|
1607
|
-
raw.end();
|
|
1608
|
-
return;
|
|
1609
|
-
}
|
|
1610
|
-
const unsubscribe = subscribeTerminalSession(req.params.sessionId, (event) => {
|
|
1611
|
-
writeEvent(event.type, event);
|
|
1612
|
-
if (event.type === "exit" || event.type === "error") {
|
|
1613
|
-
writeEvent("done", { sessionId: req.params.sessionId });
|
|
1614
|
-
unsubscribe?.();
|
|
1615
|
-
raw.end();
|
|
1616
|
-
}
|
|
1617
|
-
});
|
|
1618
|
-
req.raw.on("close", () => {
|
|
1619
|
-
unsubscribe?.();
|
|
1620
|
-
});
|
|
1621
|
-
raw.write(": ping\n\n");
|
|
520
|
+
return streamTerminalCapabilitySession(req, reply);
|
|
1622
521
|
});
|
|
1623
522
|
app.post("/api/instances/:id/provides/:capability/terminal/session/:sessionId/input", async (req, reply) => {
|
|
1624
|
-
|
|
1625
|
-
if (idErr)
|
|
1626
|
-
return reply.status(400).send({ detail: idErr });
|
|
1627
|
-
if (!assertTerminalSessionOwner(req.params.sessionId, req.params.id, req.params.capability)) {
|
|
1628
|
-
return reply.status(404).send({ detail: "Terminal session not found" });
|
|
1629
|
-
}
|
|
1630
|
-
try {
|
|
1631
|
-
sendTerminalSessionInput(req.params.sessionId, typeof req.body?.input === "string" ? req.body.input : "");
|
|
1632
|
-
return reply.send({ ok: true });
|
|
1633
|
-
}
|
|
1634
|
-
catch (error) {
|
|
1635
|
-
return reply.status(400).send({ detail: error?.message || "Failed to send terminal input" });
|
|
1636
|
-
}
|
|
523
|
+
return sendTerminalCapabilityInput(req, reply);
|
|
1637
524
|
});
|
|
1638
525
|
app.post("/api/instances/:id/provides/:capability/terminal/session/:sessionId/stop", async (req, reply) => {
|
|
1639
|
-
|
|
1640
|
-
if (idErr)
|
|
1641
|
-
return reply.status(400).send({ detail: idErr });
|
|
1642
|
-
if (!assertTerminalSessionOwner(req.params.sessionId, req.params.id, req.params.capability)) {
|
|
1643
|
-
return reply.status(404).send({ detail: "Terminal session not found" });
|
|
1644
|
-
}
|
|
1645
|
-
try {
|
|
1646
|
-
stopTerminalSession(req.params.sessionId);
|
|
1647
|
-
return reply.send({ ok: true });
|
|
1648
|
-
}
|
|
1649
|
-
catch (error) {
|
|
1650
|
-
return reply.status(400).send({ detail: error?.message || "Failed to stop terminal session" });
|
|
1651
|
-
}
|
|
526
|
+
return stopTerminalCapabilitySession(req, reply);
|
|
1652
527
|
});
|
|
1653
528
|
app.all("/api/instances/:id/provides/:capability", async (req, reply) => proxyProvidedCapability(req, reply));
|
|
1654
529
|
app.all("/api/instances/:id/provides/:capability/*", async (req, reply) => proxyProvidedCapability(req, reply));
|
|
@@ -1657,145 +532,19 @@ export async function instanceRoutes(app) {
|
|
|
1657
532
|
const idErr = validateId(req.params.id);
|
|
1658
533
|
if (idErr)
|
|
1659
534
|
return reply.status(400).send({ detail: idErr });
|
|
1660
|
-
const svc = await getSvc();
|
|
1661
|
-
const identity = resolveRuntimeIdentity(req.params.id);
|
|
1662
|
-
if (!identity && !hasRuntimeIdentity(req.params.id)) {
|
|
1663
|
-
return reply.status(404).send({ detail: "Instance not found" });
|
|
1664
|
-
}
|
|
1665
535
|
const logType = req.query.log_type || "stderr";
|
|
1666
536
|
if (logType !== "stdout" && logType !== "stderr") {
|
|
1667
537
|
return reply.status(400).send({ detail: "log_type must be stdout or stderr" });
|
|
1668
538
|
}
|
|
1669
539
|
const MAX_LOG_LINES = 5000;
|
|
1670
540
|
const lines = Math.min(parseInt(req.query.lines || "100", 10) || 100, MAX_LOG_LINES);
|
|
1671
|
-
const logLines =
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
return { lines: logLines };
|
|
1675
|
-
});
|
|
1676
|
-
// Admin: re-encrypt all instance secrets with current AES key
|
|
1677
|
-
app.post("/api/admin/migrate-secrets", async (_req, _reply) => {
|
|
1678
|
-
const { getAesKey, getJwtSecret } = await import("../config.js");
|
|
1679
|
-
const { scryptSync, createDecipheriv, createCipheriv, randomBytes } = await import("crypto");
|
|
1680
|
-
const { readFileSync, existsSync: fsExistsSync } = await import("fs");
|
|
1681
|
-
const instances = instanceManager.listInstances();
|
|
1682
|
-
const results = [];
|
|
1683
|
-
const currentKey = getAesKey();
|
|
1684
|
-
const legacyKey = scryptSync(getJwtSecret(), "jishushell-apikey-v1", 32);
|
|
1685
|
-
for (const inst of instances) {
|
|
1686
|
-
const envFiles = instanceManager.getRuntimeEnvFiles(inst.id);
|
|
1687
|
-
const providerEnvFile = envFiles[0]?.replace(/model\.env$/, "provider.env");
|
|
1688
|
-
if (!providerEnvFile || !fsExistsSync(providerEnvFile)) {
|
|
1689
|
-
results.push({ id: inst.id, status: "skipped", error: "no provider.env" });
|
|
1690
|
-
continue;
|
|
1691
|
-
}
|
|
1692
|
-
const envContent = readFileSync(providerEnvFile, "utf-8");
|
|
1693
|
-
const match = envContent.match(/UPSTREAM_API_KEY=(.+)/);
|
|
1694
|
-
if (!match || !match[1]?.startsWith("enc:")) {
|
|
1695
|
-
results.push({ id: inst.id, status: "skipped", error: "no encrypted key" });
|
|
1696
|
-
continue;
|
|
1697
|
-
}
|
|
1698
|
-
const encrypted = match[1];
|
|
1699
|
-
const raw = Buffer.from(encrypted.slice(4), "base64");
|
|
1700
|
-
if (raw.length < 29) {
|
|
1701
|
-
results.push({ id: inst.id, status: "error", error: "encrypted data too short" });
|
|
1702
|
-
continue;
|
|
1703
|
-
}
|
|
1704
|
-
const iv = raw.subarray(0, 12);
|
|
1705
|
-
const tag = raw.subarray(12, 28);
|
|
1706
|
-
const ciphertext = raw.subarray(28);
|
|
1707
|
-
// Try decrypt with current key first
|
|
1708
|
-
let plaintext = null;
|
|
1709
|
-
let needsReEncrypt = false;
|
|
1710
|
-
try {
|
|
1711
|
-
const d = createDecipheriv("aes-256-gcm", currentKey, iv);
|
|
1712
|
-
d.setAuthTag(tag);
|
|
1713
|
-
plaintext = d.update(ciphertext, undefined, "utf-8") + d.final("utf-8");
|
|
1714
|
-
// Already encrypted with current key — no migration needed
|
|
1715
|
-
results.push({ id: inst.id, status: "ok" });
|
|
1716
|
-
continue;
|
|
1717
|
-
}
|
|
1718
|
-
catch {
|
|
1719
|
-
// Current key failed — try legacy
|
|
1720
|
-
needsReEncrypt = true;
|
|
1721
|
-
}
|
|
1722
|
-
if (needsReEncrypt) {
|
|
1723
|
-
try {
|
|
1724
|
-
const d = createDecipheriv("aes-256-gcm", legacyKey, iv);
|
|
1725
|
-
d.setAuthTag(tag);
|
|
1726
|
-
plaintext = d.update(ciphertext, undefined, "utf-8") + d.final("utf-8");
|
|
1727
|
-
}
|
|
1728
|
-
catch {
|
|
1729
|
-
results.push({ id: inst.id, status: "error", error: "decrypt failed with both keys" });
|
|
1730
|
-
continue;
|
|
1731
|
-
}
|
|
1732
|
-
// Re-encrypt with current key
|
|
1733
|
-
const newIv = randomBytes(12);
|
|
1734
|
-
const c = createCipheriv("aes-256-gcm", currentKey, newIv);
|
|
1735
|
-
const enc = Buffer.concat([c.update(plaintext, "utf-8"), c.final()]);
|
|
1736
|
-
const newTag = c.getAuthTag();
|
|
1737
|
-
const newEncrypted = "enc:" + Buffer.concat([newIv, newTag, enc]).toString("base64");
|
|
1738
|
-
// Write back
|
|
1739
|
-
const newContent = envContent.replace(/UPSTREAM_API_KEY=.+/, `UPSTREAM_API_KEY=${newEncrypted}`);
|
|
1740
|
-
writeSecretFile(providerEnvFile, newContent);
|
|
1741
|
-
results.push({ id: inst.id, status: "migrated" });
|
|
1742
|
-
}
|
|
1743
|
-
}
|
|
1744
|
-
// Invalidate proxy config cache for migrated instances
|
|
1745
|
-
for (const r of results) {
|
|
1746
|
-
if (r.status === "migrated")
|
|
1747
|
-
invalidateConfigCache(r.id);
|
|
1748
|
-
}
|
|
1749
|
-
return { ok: true, results };
|
|
1750
|
-
});
|
|
1751
|
-
// ── Docker image check & pull ───────────────────────────────────────────
|
|
1752
|
-
// Generic Docker operations used by NewInstance UI to verify / pull runtime
|
|
1753
|
-
// images before creating an instance. Framework-level (not adapter-scoped)
|
|
1754
|
-
// because every container runtime shares the same docker CLI here.
|
|
1755
|
-
app.get("/api/docker/image-check", async (req, reply) => {
|
|
1756
|
-
const image = req.query.image;
|
|
1757
|
-
if (!image || typeof image !== "string") {
|
|
1758
|
-
return reply.status(400).send({ detail: "Missing 'image' query parameter" });
|
|
1759
|
-
}
|
|
1760
|
-
// Validate image name to prevent command injection
|
|
1761
|
-
if (!/^[a-zA-Z0-9][a-zA-Z0-9\-_.:/@]*$/.test(image) || image.length > 256) {
|
|
1762
|
-
return reply.status(400).send({ detail: "Invalid Docker image name" });
|
|
1763
|
-
}
|
|
1764
|
-
const { inspectDockerImage, toDockerInspectUserError } = await import("../utils/docker-inspect.js");
|
|
1765
|
-
const result = inspectDockerImage(image, { timeout: 10000 });
|
|
1766
|
-
if (result.ok) {
|
|
1767
|
-
return { exists: true, image };
|
|
1768
|
-
}
|
|
1769
|
-
if (result.reason === "not_found")
|
|
1770
|
-
return { exists: false, image };
|
|
1771
|
-
const inspectError = toDockerInspectUserError(image, result);
|
|
1772
|
-
return reply.status(inspectError.statusCode).send({
|
|
1773
|
-
detail: inspectError.message,
|
|
1774
|
-
code: inspectError.code,
|
|
1775
|
-
exists: false,
|
|
1776
|
-
image,
|
|
1777
|
-
});
|
|
1778
|
-
});
|
|
1779
|
-
app.post("/api/docker/image-pull", async (req, reply) => {
|
|
1780
|
-
const image = req.body?.image;
|
|
1781
|
-
if (!image || typeof image !== "string") {
|
|
1782
|
-
return reply.status(400).send({ detail: "Missing 'image' in request body" });
|
|
1783
|
-
}
|
|
1784
|
-
if (!/^[a-zA-Z0-9][a-zA-Z0-9\-_.:/@]*$/.test(image) || image.length > 256) {
|
|
1785
|
-
return reply.status(400).send({ detail: "Invalid Docker image name" });
|
|
1786
|
-
}
|
|
1787
|
-
try {
|
|
1788
|
-
const { execFile } = await import("child_process");
|
|
1789
|
-
const { promisify } = await import("util");
|
|
1790
|
-
const execFileAsync = promisify(execFile);
|
|
1791
|
-
await execFileAsync("docker", ["pull", image], { timeout: 600_000 });
|
|
1792
|
-
return { ok: true, image };
|
|
1793
|
-
}
|
|
1794
|
-
catch (e) {
|
|
1795
|
-
return reply.status(500).send({ detail: `Failed to pull image: ${e.message}` });
|
|
541
|
+
const logLines = await appLifecycle.getManagedLogs(req.params.id, lines, logType);
|
|
542
|
+
if (!logLines) {
|
|
543
|
+
return reply.status(404).send({ detail: "Instance not found" });
|
|
1796
544
|
}
|
|
545
|
+
return { lines: logLines };
|
|
1797
546
|
});
|
|
1798
|
-
// ── Connections REST API
|
|
547
|
+
// ── Connections REST API ────────────────────────────────────────────────
|
|
1799
548
|
/** GET /api/instances/:id/connections — view spec.requires + bindings. */
|
|
1800
549
|
app.get("/api/instances/:id/connections", async (req, reply) => {
|
|
1801
550
|
try {
|
|
@@ -1844,112 +593,5 @@ export async function instanceRoutes(app) {
|
|
|
1844
593
|
return { state: "error", unboundRequired: [], unboundOptional: [], bindable: 0, error: e.message };
|
|
1845
594
|
}
|
|
1846
595
|
});
|
|
1847
|
-
// ── Suggestions API (PR 6) ─────────────────────────────────────────────
|
|
1848
|
-
app.get("/api/suggestions", async () => {
|
|
1849
|
-
const { computeSuggestions } = await import("../services/suggestions.js");
|
|
1850
|
-
return { suggestions: computeSuggestions() };
|
|
1851
|
-
});
|
|
1852
|
-
app.post("/api/suggestions/:id/apply", async (req, reply) => {
|
|
1853
|
-
const { computeSuggestions } = await import("../services/suggestions.js");
|
|
1854
|
-
const all = computeSuggestions();
|
|
1855
|
-
const target = all.find((s) => s.id === req.params.id);
|
|
1856
|
-
if (!target) {
|
|
1857
|
-
return reply.status(404).send({ detail: "Suggestion no longer applies" });
|
|
1858
|
-
}
|
|
1859
|
-
// Apply by issuing the equivalent PUT /connections — read current
|
|
1860
|
-
// bindings, splice in the new one for `slot`, persist via the
|
|
1861
|
-
// transactor.
|
|
1862
|
-
const meta = instanceManager.getInstance(target.consumerInstanceId);
|
|
1863
|
-
if (!meta)
|
|
1864
|
-
return reply.status(404).send({ detail: "Consumer instance not found" });
|
|
1865
|
-
// Resolve consumer spec — app-installed instances have it in the app
|
|
1866
|
-
// registry; legacy instances (no app_id) fall back to the
|
|
1867
|
-
// yaml-template synthesizer used everywhere else for legacy
|
|
1868
|
-
// capability work.
|
|
1869
|
-
let consumerSpec = null;
|
|
1870
|
-
if (target.appId) {
|
|
1871
|
-
const appData = instanceManager.getApp(target.appId);
|
|
1872
|
-
if (!appData)
|
|
1873
|
-
return reply.status(404).send({ detail: "App spec not found" });
|
|
1874
|
-
consumerSpec = appData.spec;
|
|
1875
|
-
}
|
|
1876
|
-
else {
|
|
1877
|
-
const { loadCapabilitySpecForLegacyInstance } = await import("../services/runtime/migrations.js");
|
|
1878
|
-
consumerSpec = loadCapabilitySpecForLegacyInstance(meta);
|
|
1879
|
-
if (!consumerSpec) {
|
|
1880
|
-
return reply.status(404).send({ detail: "No capability spec for legacy instance" });
|
|
1881
|
-
}
|
|
1882
|
-
}
|
|
1883
|
-
const newConnections = {
|
|
1884
|
-
...(meta.connections ?? {}),
|
|
1885
|
-
[target.slot]: {
|
|
1886
|
-
kind: "single",
|
|
1887
|
-
providerId: target.candidate.providerId,
|
|
1888
|
-
capability: target.candidate.capability,
|
|
1889
|
-
},
|
|
1890
|
-
};
|
|
1891
|
-
const { applyConnections } = await import("../services/connection-transactor.js");
|
|
1892
|
-
const safeJson = await import("../utils/safe-json.js");
|
|
1893
|
-
const fs = await import("fs");
|
|
1894
|
-
const path = await import("path");
|
|
1895
|
-
const instancePath = instanceManager.instanceMetaPath(target.consumerInstanceId);
|
|
1896
|
-
const readInstanceJson = async () => (safeJson.safeReadJson(instancePath, `instance:${target.consumerInstanceId}`) ?? {});
|
|
1897
|
-
const saveInstanceJson = async (_id, mutator) => {
|
|
1898
|
-
const cur = (safeJson.safeReadJson(instancePath, `instance:${target.consumerInstanceId}`) ?? {});
|
|
1899
|
-
try {
|
|
1900
|
-
fs.mkdirSync(path.dirname(instancePath), { recursive: true });
|
|
1901
|
-
}
|
|
1902
|
-
catch {
|
|
1903
|
-
/* noop */
|
|
1904
|
-
}
|
|
1905
|
-
safeJson.safeWriteJson(instancePath, mutator(cur));
|
|
1906
|
-
};
|
|
1907
|
-
let adapter = null;
|
|
1908
|
-
try {
|
|
1909
|
-
const agentType = resolveAgentType(meta);
|
|
1910
|
-
if (hasAdapter(agentType)) {
|
|
1911
|
-
adapter = getAdapter(agentType);
|
|
1912
|
-
if (typeof adapter.applyConnectionEnv !== "function")
|
|
1913
|
-
adapter = null;
|
|
1914
|
-
}
|
|
1915
|
-
}
|
|
1916
|
-
catch {
|
|
1917
|
-
adapter = null;
|
|
1918
|
-
}
|
|
1919
|
-
try {
|
|
1920
|
-
const result = await applyConnections({
|
|
1921
|
-
instance: meta,
|
|
1922
|
-
spec: consumerSpec,
|
|
1923
|
-
newConnections,
|
|
1924
|
-
saveInstanceJson,
|
|
1925
|
-
readInstanceJson,
|
|
1926
|
-
adapter,
|
|
1927
|
-
});
|
|
1928
|
-
return { ok: true, applied: target.id, resolved: result.resolved.length };
|
|
1929
|
-
}
|
|
1930
|
-
catch (e) {
|
|
1931
|
-
return reply.status(e?.statusCode ?? 500).send({
|
|
1932
|
-
detail: e?.message ?? "Suggestion apply failed",
|
|
1933
|
-
code: e?.code,
|
|
1934
|
-
});
|
|
1935
|
-
}
|
|
1936
|
-
});
|
|
1937
|
-
app.post("/api/suggestions/:id/dismiss", async (req, reply) => {
|
|
1938
|
-
const { dismissSuggestion } = await import("../services/suggestions.js");
|
|
1939
|
-
try {
|
|
1940
|
-
await dismissSuggestion(req.params.id);
|
|
1941
|
-
return { ok: true };
|
|
1942
|
-
}
|
|
1943
|
-
catch (e) {
|
|
1944
|
-
return reply.status(400).send({ detail: e?.message ?? "Invalid suggestion id" });
|
|
1945
|
-
}
|
|
1946
|
-
});
|
|
1947
|
-
try {
|
|
1948
|
-
const { registerOpenclawRoutes } = await import("./openclaw-routes.js");
|
|
1949
|
-
registerOpenclawRoutes(app);
|
|
1950
|
-
}
|
|
1951
|
-
catch (err) {
|
|
1952
|
-
console.error("[instances] openclaw route registration failed:", err);
|
|
1953
|
-
}
|
|
1954
596
|
}
|
|
1955
597
|
//# sourceMappingURL=instances.js.map
|