@nodetool-ai/websocket 0.7.0-rc.23 → 0.8.1
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/README.md +50 -0
- package/dist/.nodetool-build-stamp +1 -0
- package/dist/agent/run-node-tool.d.ts +39 -0
- package/dist/agent/run-node-tool.d.ts.map +1 -0
- package/dist/agent/run-node-tool.js +55 -0
- package/dist/agent/run-node-tool.js.map +1 -0
- package/dist/chat-prediction-forwarder.d.ts +13 -0
- package/dist/chat-prediction-forwarder.d.ts.map +1 -0
- package/dist/chat-prediction-forwarder.js +22 -0
- package/dist/chat-prediction-forwarder.js.map +1 -0
- package/dist/chat-tool-call-repair.d.ts +45 -0
- package/dist/chat-tool-call-repair.d.ts.map +1 -0
- package/dist/chat-tool-call-repair.js +100 -0
- package/dist/chat-tool-call-repair.js.map +1 -0
- package/dist/chat-turn-registry.d.ts +169 -0
- package/dist/chat-turn-registry.d.ts.map +1 -0
- package/dist/chat-turn-registry.js +326 -0
- package/dist/chat-turn-registry.js.map +1 -0
- package/dist/collection-api.d.ts +2 -2
- package/dist/collection-api.d.ts.map +1 -1
- package/dist/collection-api.js +44 -13
- package/dist/collection-api.js.map +1 -1
- package/dist/configured-providers.d.ts +52 -0
- package/dist/configured-providers.d.ts.map +1 -0
- package/dist/configured-providers.js +85 -0
- package/dist/configured-providers.js.map +1 -0
- package/dist/cors.d.ts +22 -0
- package/dist/cors.d.ts.map +1 -0
- package/dist/cors.js +91 -0
- package/dist/cors.js.map +1 -0
- package/dist/credit-gate.d.ts +36 -0
- package/dist/credit-gate.d.ts.map +1 -0
- package/dist/credit-gate.js +76 -0
- package/dist/credit-gate.js.map +1 -0
- package/dist/custom-providers.d.ts +40 -0
- package/dist/custom-providers.d.ts.map +1 -0
- package/dist/custom-providers.js +134 -0
- package/dist/custom-providers.js.map +1 -0
- package/dist/debug-sessions.d.ts +10 -0
- package/dist/debug-sessions.d.ts.map +1 -0
- package/dist/debug-sessions.js +9 -0
- package/dist/debug-sessions.js.map +1 -0
- package/dist/drain.d.ts +34 -0
- package/dist/drain.d.ts.map +1 -0
- package/dist/drain.js +68 -0
- package/dist/drain.js.map +1 -0
- package/dist/e2e-server.d.ts +30 -0
- package/dist/e2e-server.d.ts.map +1 -0
- package/dist/e2e-server.js +111 -0
- package/dist/e2e-server.js.map +1 -0
- package/dist/example-workflows.d.ts +20 -0
- package/dist/example-workflows.d.ts.map +1 -0
- package/dist/example-workflows.js +123 -0
- package/dist/example-workflows.js.map +1 -0
- package/dist/extension-cdp-bridge.d.ts +85 -0
- package/dist/extension-cdp-bridge.d.ts.map +1 -0
- package/dist/extension-cdp-bridge.js +163 -0
- package/dist/extension-cdp-bridge.js.map +1 -0
- package/dist/external-mcp.d.ts +58 -0
- package/dist/external-mcp.d.ts.map +1 -0
- package/dist/external-mcp.js +288 -0
- package/dist/external-mcp.js.map +1 -0
- package/dist/fake-runtime.d.ts +114 -0
- package/dist/fake-runtime.d.ts.map +1 -0
- package/dist/fake-runtime.js +270 -0
- package/dist/fake-runtime.js.map +1 -0
- package/dist/file-api.d.ts +4 -7
- package/dist/file-api.d.ts.map +1 -1
- package/dist/file-api.js +122 -39
- package/dist/file-api.js.map +1 -1
- package/dist/frontend-renderer-registry.d.ts +75 -0
- package/dist/frontend-renderer-registry.d.ts.map +1 -0
- package/dist/frontend-renderer-registry.js +111 -0
- package/dist/frontend-renderer-registry.js.map +1 -0
- package/dist/generation-recovery.d.ts +13 -0
- package/dist/generation-recovery.d.ts.map +1 -0
- package/dist/generation-recovery.js +197 -0
- package/dist/generation-recovery.js.map +1 -0
- package/dist/headless-job-runner.d.ts +71 -0
- package/dist/headless-job-runner.d.ts.map +1 -0
- package/dist/headless-job-runner.js +198 -0
- package/dist/headless-job-runner.js.map +1 -0
- package/dist/http-api.d.ts +157 -24
- package/dist/http-api.d.ts.map +1 -1
- package/dist/http-api.js +613 -646
- package/dist/http-api.js.map +1 -1
- package/dist/http-body-schemas.d.ts +109 -0
- package/dist/http-body-schemas.d.ts.map +1 -0
- package/dist/http-body-schemas.js +146 -0
- package/dist/http-body-schemas.js.map +1 -0
- package/dist/index.d.ts +11 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -3
- package/dist/index.js.map +1 -1
- package/dist/job-control.d.ts +57 -0
- package/dist/job-control.d.ts.map +1 -0
- package/dist/job-control.js +134 -0
- package/dist/job-control.js.map +1 -0
- package/dist/job-queue.d.ts +47 -0
- package/dist/job-queue.d.ts.map +1 -0
- package/dist/job-queue.js +52 -0
- package/dist/job-queue.js.map +1 -0
- package/dist/job-run-registry.d.ts +176 -0
- package/dist/job-run-registry.d.ts.map +1 -0
- package/dist/job-run-registry.js +312 -0
- package/dist/job-run-registry.js.map +1 -0
- package/dist/lib/app-build-service.d.ts +16 -0
- package/dist/lib/app-build-service.d.ts.map +1 -0
- package/dist/lib/app-build-service.js +39 -0
- package/dist/lib/app-build-service.js.map +1 -0
- package/dist/lib/app-debug-service.d.ts +16 -0
- package/dist/lib/app-debug-service.d.ts.map +1 -0
- package/dist/lib/app-debug-service.js +48 -0
- package/dist/lib/app-debug-service.js.map +1 -0
- package/dist/lib/app-deployment-service.d.ts +82 -0
- package/dist/lib/app-deployment-service.d.ts.map +1 -0
- package/dist/lib/app-deployment-service.js +282 -0
- package/dist/lib/app-deployment-service.js.map +1 -0
- package/dist/lib/app-run-server.d.ts +7 -0
- package/dist/lib/app-run-server.d.ts.map +1 -0
- package/dist/lib/app-run-server.js +6 -0
- package/dist/lib/app-run-server.js.map +1 -0
- package/dist/lib/app-session-scope.d.ts +91 -0
- package/dist/lib/app-session-scope.d.ts.map +1 -0
- package/dist/lib/app-session-scope.js +91 -0
- package/dist/lib/app-session-scope.js.map +1 -0
- package/dist/lib/applications-service.d.ts +173 -0
- package/dist/lib/applications-service.d.ts.map +1 -0
- package/dist/lib/applications-service.js +491 -0
- package/dist/lib/applications-service.js.map +1 -0
- package/dist/lib/asset-duration.d.ts +7 -0
- package/dist/lib/asset-duration.d.ts.map +1 -0
- package/dist/lib/asset-duration.js +24 -0
- package/dist/lib/asset-duration.js.map +1 -0
- package/dist/lib/asset-export.d.ts +34 -0
- package/dist/lib/asset-export.d.ts.map +1 -0
- package/dist/lib/asset-export.js +113 -0
- package/dist/lib/asset-export.js.map +1 -0
- package/dist/lib/asset-model-interface.d.ts +41 -0
- package/dist/lib/asset-model-interface.d.ts.map +1 -0
- package/dist/lib/asset-model-interface.js +74 -0
- package/dist/lib/asset-model-interface.js.map +1 -0
- package/dist/lib/asset-paths.d.ts +52 -0
- package/dist/lib/asset-paths.d.ts.map +1 -1
- package/dist/lib/asset-paths.js +145 -1
- package/dist/lib/asset-paths.js.map +1 -1
- package/dist/lib/asset-response.d.ts +12 -0
- package/dist/lib/asset-response.d.ts.map +1 -0
- package/dist/lib/asset-response.js +88 -0
- package/dist/lib/asset-response.js.map +1 -0
- package/dist/lib/audio-peaks.d.ts +23 -0
- package/dist/lib/audio-peaks.d.ts.map +1 -0
- package/dist/lib/audio-peaks.js +331 -0
- package/dist/lib/audio-peaks.js.map +1 -0
- package/dist/lib/bridge.d.ts +9 -1
- package/dist/lib/bridge.d.ts.map +1 -1
- package/dist/lib/bridge.js +27 -4
- package/dist/lib/bridge.js.map +1 -1
- package/dist/lib/compression.d.ts +3 -0
- package/dist/lib/compression.d.ts.map +1 -0
- package/dist/lib/compression.js +3 -0
- package/dist/lib/compression.js.map +1 -0
- package/dist/lib/document-model-interfaces.d.ts +30 -0
- package/dist/lib/document-model-interfaces.d.ts.map +1 -0
- package/dist/lib/document-model-interfaces.js +295 -0
- package/dist/lib/document-model-interfaces.js.map +1 -0
- package/dist/lib/env-config.d.ts +9 -0
- package/dist/lib/env-config.d.ts.map +1 -0
- package/dist/lib/env-config.js +18 -0
- package/dist/lib/env-config.js.map +1 -0
- package/dist/lib/example-apps.d.ts +43 -0
- package/dist/lib/example-apps.d.ts.map +1 -0
- package/dist/lib/example-apps.js +145 -0
- package/dist/lib/example-apps.js.map +1 -0
- package/dist/lib/example-games.d.ts +5 -0
- package/dist/lib/example-games.d.ts.map +1 -0
- package/dist/lib/example-games.js +13 -0
- package/dist/lib/example-games.js.map +1 -0
- package/dist/lib/example-recipes.d.ts +33 -0
- package/dist/lib/example-recipes.d.ts.map +1 -0
- package/dist/lib/example-recipes.js +213 -0
- package/dist/lib/example-recipes.js.map +1 -0
- package/dist/lib/example-storyboards.d.ts +40 -0
- package/dist/lib/example-storyboards.d.ts.map +1 -0
- package/dist/lib/example-storyboards.js +131 -0
- package/dist/lib/example-storyboards.js.map +1 -0
- package/dist/lib/example-thumbnail.d.ts +21 -0
- package/dist/lib/example-thumbnail.d.ts.map +1 -0
- package/dist/lib/example-thumbnail.js +50 -0
- package/dist/lib/example-thumbnail.js.map +1 -0
- package/dist/lib/example-timelines.d.ts +9 -0
- package/dist/lib/example-timelines.d.ts.map +1 -0
- package/dist/lib/example-timelines.js +25 -0
- package/dist/lib/example-timelines.js.map +1 -0
- package/dist/lib/extension-dist.d.ts +24 -0
- package/dist/lib/extension-dist.d.ts.map +1 -0
- package/dist/lib/extension-dist.js +67 -0
- package/dist/lib/extension-dist.js.map +1 -0
- package/dist/lib/external-asset-lookup.d.ts +30 -0
- package/dist/lib/external-asset-lookup.d.ts.map +1 -0
- package/dist/lib/external-asset-lookup.js +99 -0
- package/dist/lib/external-asset-lookup.js.map +1 -0
- package/dist/lib/external-assets.d.ts +13 -0
- package/dist/lib/external-assets.d.ts.map +1 -0
- package/dist/lib/external-assets.js +46 -0
- package/dist/lib/external-assets.js.map +1 -0
- package/dist/lib/fly-replay.d.ts +34 -0
- package/dist/lib/fly-replay.d.ts.map +1 -0
- package/dist/lib/fly-replay.js +111 -0
- package/dist/lib/fly-replay.js.map +1 -0
- package/dist/lib/http-rate-limit.d.ts +32 -0
- package/dist/lib/http-rate-limit.d.ts.map +1 -0
- package/dist/lib/http-rate-limit.js +47 -0
- package/dist/lib/http-rate-limit.js.map +1 -0
- package/dist/lib/instance-id.d.ts +25 -0
- package/dist/lib/instance-id.d.ts.map +1 -0
- package/dist/lib/instance-id.js +44 -0
- package/dist/lib/instance-id.js.map +1 -0
- package/dist/lib/link-codes.d.ts +82 -0
- package/dist/lib/link-codes.d.ts.map +1 -0
- package/dist/lib/link-codes.js +100 -0
- package/dist/lib/link-codes.js.map +1 -0
- package/dist/lib/local-asset-upload.d.ts +5 -0
- package/dist/lib/local-asset-upload.d.ts.map +1 -0
- package/dist/lib/local-asset-upload.js +69 -0
- package/dist/lib/local-asset-upload.js.map +1 -0
- package/dist/lib/local-file-access.d.ts +31 -0
- package/dist/lib/local-file-access.d.ts.map +1 -0
- package/dist/lib/local-file-access.js +169 -0
- package/dist/lib/local-file-access.js.map +1 -0
- package/dist/lib/localhost-trust.d.ts +59 -0
- package/dist/lib/localhost-trust.d.ts.map +1 -0
- package/dist/lib/localhost-trust.js +139 -0
- package/dist/lib/localhost-trust.js.map +1 -0
- package/dist/lib/mcp-mount.d.ts +25 -0
- package/dist/lib/mcp-mount.d.ts.map +1 -0
- package/dist/lib/mcp-mount.js +32 -0
- package/dist/lib/mcp-mount.js.map +1 -0
- package/dist/lib/media-size.d.ts +21 -0
- package/dist/lib/media-size.d.ts.map +1 -0
- package/dist/lib/media-size.js +48 -0
- package/dist/lib/media-size.js.map +1 -0
- package/dist/lib/media.d.ts +38 -0
- package/dist/lib/media.d.ts.map +1 -0
- package/dist/lib/media.js +146 -0
- package/dist/lib/media.js.map +1 -0
- package/dist/lib/package-asset-export.d.ts +83 -0
- package/dist/lib/package-asset-export.d.ts.map +1 -0
- package/dist/lib/package-asset-export.js +212 -0
- package/dist/lib/package-asset-export.js.map +1 -0
- package/dist/lib/package-assets.d.ts +41 -0
- package/dist/lib/package-assets.d.ts.map +1 -0
- package/dist/lib/package-assets.js +155 -0
- package/dist/lib/package-assets.js.map +1 -0
- package/dist/lib/project-delete.d.ts +11 -0
- package/dist/lib/project-delete.d.ts.map +1 -0
- package/dist/lib/project-delete.js +67 -0
- package/dist/lib/project-delete.js.map +1 -0
- package/dist/lib/project-document-copy.d.ts +31 -0
- package/dist/lib/project-document-copy.d.ts.map +1 -0
- package/dist/lib/project-document-copy.js +473 -0
- package/dist/lib/project-document-copy.js.map +1 -0
- package/dist/lib/public-app-assets.d.ts +8 -0
- package/dist/lib/public-app-assets.d.ts.map +1 -0
- package/dist/lib/public-app-assets.js +77 -0
- package/dist/lib/public-app-assets.js.map +1 -0
- package/dist/lib/public-routes.d.ts +95 -0
- package/dist/lib/public-routes.d.ts.map +1 -0
- package/dist/lib/public-routes.js +154 -0
- package/dist/lib/public-routes.js.map +1 -0
- package/dist/lib/runtime-detection.d.ts +17 -0
- package/dist/lib/runtime-detection.d.ts.map +1 -0
- package/dist/lib/runtime-detection.js +90 -0
- package/dist/lib/runtime-detection.js.map +1 -0
- package/dist/lib/storage-access.d.ts +21 -0
- package/dist/lib/storage-access.d.ts.map +1 -0
- package/dist/lib/storage-access.js +74 -0
- package/dist/lib/storage-access.js.map +1 -0
- package/dist/lib/storage.d.ts +9 -0
- package/dist/lib/storage.d.ts.map +1 -0
- package/dist/lib/storage.js +28 -0
- package/dist/lib/storage.js.map +1 -0
- package/dist/lib/storyboard-export.d.ts +64 -0
- package/dist/lib/storyboard-export.d.ts.map +1 -0
- package/dist/lib/storyboard-export.js +183 -0
- package/dist/lib/storyboard-export.js.map +1 -0
- package/dist/lib/style-presets.d.ts +34 -0
- package/dist/lib/style-presets.d.ts.map +1 -0
- package/dist/lib/style-presets.js +62 -0
- package/dist/lib/style-presets.js.map +1 -0
- package/dist/lib/temp-url-resolver.d.ts +35 -0
- package/dist/lib/temp-url-resolver.d.ts.map +1 -0
- package/dist/lib/temp-url-resolver.js +88 -0
- package/dist/lib/temp-url-resolver.js.map +1 -0
- package/dist/lib/thumbnail.d.ts +74 -0
- package/dist/lib/thumbnail.d.ts.map +1 -0
- package/dist/lib/thumbnail.js +302 -0
- package/dist/lib/thumbnail.js.map +1 -0
- package/dist/lib/timeline-bundle.d.ts +1689 -0
- package/dist/lib/timeline-bundle.d.ts.map +1 -0
- package/dist/lib/timeline-bundle.js +330 -0
- package/dist/lib/timeline-bundle.js.map +1 -0
- package/dist/lib/video-proxy.d.ts +114 -0
- package/dist/lib/video-proxy.d.ts.map +1 -0
- package/dist/lib/video-proxy.js +545 -0
- package/dist/lib/video-proxy.js.map +1 -0
- package/dist/lib/wire-values.d.ts +31 -0
- package/dist/lib/wire-values.d.ts.map +1 -0
- package/dist/lib/wire-values.js +49 -0
- package/dist/lib/wire-values.js.map +1 -0
- package/dist/lib/workflow-bundle.d.ts +102 -0
- package/dist/lib/workflow-bundle.d.ts.map +1 -0
- package/dist/lib/workflow-bundle.js +306 -0
- package/dist/lib/workflow-bundle.js.map +1 -0
- package/dist/lib/workflow-service.d.ts +82 -0
- package/dist/lib/workflow-service.d.ts.map +1 -0
- package/dist/lib/workflow-service.js +194 -0
- package/dist/lib/workflow-service.js.map +1 -0
- package/dist/lib/workflow-workspace.d.ts +20 -0
- package/dist/lib/workflow-workspace.d.ts.map +1 -0
- package/dist/lib/workflow-workspace.js +65 -0
- package/dist/lib/workflow-workspace.js.map +1 -0
- package/dist/lib/ws-connection-health.d.ts +10 -0
- package/dist/lib/ws-connection-health.d.ts.map +1 -0
- package/dist/lib/ws-connection-health.js +38 -0
- package/dist/lib/ws-connection-health.js.map +1 -0
- package/dist/lib/ws-rate-limit.d.ts +22 -0
- package/dist/lib/ws-rate-limit.d.ts.map +1 -0
- package/dist/lib/ws-rate-limit.js +45 -0
- package/dist/lib/ws-rate-limit.js.map +1 -0
- package/dist/lib/ws-upgrade.d.ts +40 -0
- package/dist/lib/ws-upgrade.d.ts.map +1 -0
- package/dist/lib/ws-upgrade.js +66 -0
- package/dist/lib/ws-upgrade.js.map +1 -0
- package/dist/lib/zip-stream.d.ts +46 -0
- package/dist/lib/zip-stream.d.ts.map +1 -0
- package/dist/lib/zip-stream.js +140 -0
- package/dist/lib/zip-stream.js.map +1 -0
- package/dist/mcp-agent-tools.d.ts +56 -0
- package/dist/mcp-agent-tools.d.ts.map +1 -0
- package/dist/mcp-agent-tools.js +1216 -0
- package/dist/mcp-agent-tools.js.map +1 -0
- package/dist/mcp-server.d.ts +56 -7
- package/dist/mcp-server.d.ts.map +1 -1
- package/dist/mcp-server.js +255 -762
- package/dist/mcp-server.js.map +1 -1
- package/dist/mcp-tool-deps.d.ts +20 -0
- package/dist/mcp-tool-deps.d.ts.map +1 -0
- package/dist/mcp-tool-deps.js +61 -0
- package/dist/mcp-tool-deps.js.map +1 -0
- package/dist/messagepack.d.ts +7 -0
- package/dist/messagepack.d.ts.map +1 -0
- package/dist/messagepack.js +19 -0
- package/dist/messagepack.js.map +1 -0
- package/dist/model-download-runtime.d.ts +9 -0
- package/dist/model-download-runtime.d.ts.map +1 -0
- package/dist/model-download-runtime.js +77 -0
- package/dist/model-download-runtime.js.map +1 -0
- package/dist/model-execution-availability.d.ts +14 -0
- package/dist/model-execution-availability.d.ts.map +1 -0
- package/dist/model-execution-availability.js +161 -0
- package/dist/model-execution-availability.js.map +1 -0
- package/dist/models-api.d.ts +51 -5
- package/dist/models-api.d.ts.map +1 -1
- package/dist/models-api.js +160 -690
- package/dist/models-api.js.map +1 -1
- package/dist/node-registry-setup.d.ts +84 -0
- package/dist/node-registry-setup.d.ts.map +1 -0
- package/dist/node-registry-setup.js +256 -0
- package/dist/node-registry-setup.js.map +1 -0
- package/dist/oauth/cimd.d.ts +28 -0
- package/dist/oauth/cimd.d.ts.map +1 -0
- package/dist/oauth/cimd.js +177 -0
- package/dist/oauth/cimd.js.map +1 -0
- package/dist/oauth/gate.d.ts +38 -0
- package/dist/oauth/gate.d.ts.map +1 -0
- package/dist/oauth/gate.js +77 -0
- package/dist/oauth/gate.js.map +1 -0
- package/dist/oauth/metadata.d.ts +35 -0
- package/dist/oauth/metadata.d.ts.map +1 -0
- package/dist/oauth/metadata.js +56 -0
- package/dist/oauth/metadata.js.map +1 -0
- package/dist/oauth/pending-store.d.ts +79 -0
- package/dist/oauth/pending-store.d.ts.map +1 -0
- package/dist/oauth/pending-store.js +133 -0
- package/dist/oauth/pending-store.js.map +1 -0
- package/dist/oauth/pkce.d.ts +16 -0
- package/dist/oauth/pkce.d.ts.map +1 -0
- package/dist/oauth/pkce.js +29 -0
- package/dist/oauth/pkce.js.map +1 -0
- package/dist/oauth/validate.d.ts +25 -0
- package/dist/oauth/validate.d.ts.map +1 -0
- package/dist/oauth/validate.js +62 -0
- package/dist/oauth/validate.js.map +1 -0
- package/dist/oauth/www-authenticate.d.ts +9 -0
- package/dist/oauth/www-authenticate.d.ts.map +1 -0
- package/dist/oauth/www-authenticate.js +33 -0
- package/dist/oauth/www-authenticate.js.map +1 -0
- package/dist/oauth-api.d.ts +19 -0
- package/dist/oauth-api.d.ts.map +1 -1
- package/dist/oauth-api.js +531 -12
- package/dist/oauth-api.js.map +1 -1
- package/dist/openai-api.d.ts.map +1 -1
- package/dist/openai-api.js +4 -9
- package/dist/openai-api.js.map +1 -1
- package/dist/pack-snapshot.d.ts +24 -0
- package/dist/pack-snapshot.d.ts.map +1 -0
- package/dist/pack-snapshot.js +35 -0
- package/dist/pack-snapshot.js.map +1 -0
- package/dist/plugins/websocket.d.ts +21 -4
- package/dist/plugins/websocket.d.ts.map +1 -1
- package/dist/plugins/websocket.js +136 -290
- package/dist/plugins/websocket.js.map +1 -1
- package/dist/resolve-media-urls.d.ts +17 -3
- package/dist/resolve-media-urls.d.ts.map +1 -1
- package/dist/resolve-media-urls.js +117 -31
- package/dist/resolve-media-urls.js.map +1 -1
- package/dist/resource-events.d.ts +28 -0
- package/dist/resource-events.d.ts.map +1 -0
- package/dist/resource-events.js +20 -0
- package/dist/resource-events.js.map +1 -0
- package/dist/routes/account.d.ts +100 -0
- package/dist/routes/account.d.ts.map +1 -0
- package/dist/routes/account.js +197 -0
- package/dist/routes/account.js.map +1 -0
- package/dist/routes/applications.d.ts +36 -0
- package/dist/routes/applications.d.ts.map +1 -0
- package/dist/routes/applications.js +183 -0
- package/dist/routes/applications.js.map +1 -0
- package/dist/routes/assets.d.ts +3 -3
- package/dist/routes/assets.d.ts.map +1 -1
- package/dist/routes/assets.js +78 -44
- package/dist/routes/assets.js.map +1 -1
- package/dist/routes/atlascloud-webhook.d.ts +93 -0
- package/dist/routes/atlascloud-webhook.d.ts.map +1 -0
- package/dist/routes/atlascloud-webhook.js +369 -0
- package/dist/routes/atlascloud-webhook.js.map +1 -0
- package/dist/routes/collections.d.ts.map +1 -1
- package/dist/routes/config.d.ts +26 -0
- package/dist/routes/config.d.ts.map +1 -0
- package/dist/routes/config.js +64 -0
- package/dist/routes/config.js.map +1 -0
- package/dist/routes/documents.d.ts +27 -0
- package/dist/routes/documents.d.ts.map +1 -0
- package/dist/routes/documents.js +155 -0
- package/dist/routes/documents.js.map +1 -0
- package/dist/routes/fal-credits.d.ts +4 -0
- package/dist/routes/fal-credits.d.ts.map +1 -0
- package/dist/routes/fal-credits.js +101 -0
- package/dist/routes/fal-credits.js.map +1 -0
- package/dist/routes/fal-pricing-estimate.d.ts +4 -0
- package/dist/routes/fal-pricing-estimate.d.ts.map +1 -0
- package/dist/routes/fal-pricing-estimate.js +114 -0
- package/dist/routes/fal-pricing-estimate.js.map +1 -0
- package/dist/routes/fal-pricing.d.ts +4 -0
- package/dist/routes/fal-pricing.d.ts.map +1 -0
- package/dist/routes/fal-pricing.js +93 -0
- package/dist/routes/fal-pricing.js.map +1 -0
- package/dist/routes/fal-webhook.d.ts +102 -0
- package/dist/routes/fal-webhook.d.ts.map +1 -0
- package/dist/routes/fal-webhook.js +379 -0
- package/dist/routes/fal-webhook.js.map +1 -0
- package/dist/routes/files.d.ts.map +1 -1
- package/dist/routes/files.js +4 -3
- package/dist/routes/files.js.map +1 -1
- package/dist/routes/health.d.ts +1 -0
- package/dist/routes/health.d.ts.map +1 -1
- package/dist/routes/health.js +41 -7
- package/dist/routes/health.js.map +1 -1
- package/dist/routes/integrations.d.ts +39 -0
- package/dist/routes/integrations.d.ts.map +1 -0
- package/dist/routes/integrations.js +211 -0
- package/dist/routes/integrations.js.map +1 -0
- package/dist/routes/js-scripts.d.ts +26 -0
- package/dist/routes/js-scripts.d.ts.map +1 -0
- package/dist/routes/js-scripts.js +116 -0
- package/dist/routes/js-scripts.js.map +1 -0
- package/dist/routes/kie-credits.d.ts +4 -0
- package/dist/routes/kie-credits.d.ts.map +1 -0
- package/dist/routes/kie-credits.js +93 -0
- package/dist/routes/kie-credits.js.map +1 -0
- package/dist/routes/kie-pricing.d.ts +4 -0
- package/dist/routes/kie-pricing.d.ts.map +1 -0
- package/dist/routes/kie-pricing.js +45 -0
- package/dist/routes/kie-pricing.js.map +1 -0
- package/dist/routes/kie-webhook.d.ts +4 -0
- package/dist/routes/kie-webhook.d.ts.map +1 -0
- package/dist/routes/kie-webhook.js +70 -0
- package/dist/routes/kie-webhook.js.map +1 -0
- package/dist/routes/nodes.d.ts.map +1 -1
- package/dist/routes/nodes.js +6 -59
- package/dist/routes/nodes.js.map +1 -1
- package/dist/routes/oauth-as.d.ts +30 -0
- package/dist/routes/oauth-as.d.ts.map +1 -0
- package/dist/routes/oauth-as.js +412 -0
- package/dist/routes/oauth-as.js.map +1 -0
- package/dist/routes/oauth.d.ts.map +1 -1
- package/dist/routes/openai.d.ts.map +1 -1
- package/dist/routes/public-apps.d.ts +27 -0
- package/dist/routes/public-apps.d.ts.map +1 -0
- package/dist/routes/public-apps.js +99 -0
- package/dist/routes/public-apps.js.map +1 -0
- package/dist/routes/sandbox-modules.d.ts +17 -0
- package/dist/routes/sandbox-modules.d.ts.map +1 -0
- package/dist/routes/sandbox-modules.js +85 -0
- package/dist/routes/sandbox-modules.js.map +1 -0
- package/dist/routes/sdk-v1.d.ts +24 -0
- package/dist/routes/sdk-v1.d.ts.map +1 -0
- package/dist/routes/sdk-v1.js +320 -0
- package/dist/routes/sdk-v1.js.map +1 -0
- package/dist/routes/storage.d.ts.map +1 -1
- package/dist/routes/storyboards.d.ts +16 -0
- package/dist/routes/storyboards.d.ts.map +1 -0
- package/dist/routes/storyboards.js +97 -0
- package/dist/routes/storyboards.js.map +1 -0
- package/dist/routes/timeline-animations.d.ts +23 -0
- package/dist/routes/timeline-animations.d.ts.map +1 -0
- package/dist/routes/timeline-animations.js +99 -0
- package/dist/routes/timeline-animations.js.map +1 -0
- package/dist/routes/timeline-audio-bake.d.ts +51 -0
- package/dist/routes/timeline-audio-bake.d.ts.map +1 -0
- package/dist/routes/timeline-audio-bake.js +110 -0
- package/dist/routes/timeline-audio-bake.js.map +1 -0
- package/dist/routes/timeline-fonts.d.ts +29 -0
- package/dist/routes/timeline-fonts.d.ts.map +1 -0
- package/dist/routes/timeline-fonts.js +64 -0
- package/dist/routes/timeline-fonts.js.map +1 -0
- package/dist/routes/timeline-isolate-subject.d.ts +55 -0
- package/dist/routes/timeline-isolate-subject.d.ts.map +1 -0
- package/dist/routes/timeline-isolate-subject.js +128 -0
- package/dist/routes/timeline-isolate-subject.js.map +1 -0
- package/dist/routes/timeline-track-object.d.ts +39 -0
- package/dist/routes/timeline-track-object.d.ts.map +1 -0
- package/dist/routes/timeline-track-object.js +97 -0
- package/dist/routes/timeline-track-object.js.map +1 -0
- package/dist/routes/timelines.d.ts +18 -0
- package/dist/routes/timelines.d.ts.map +1 -0
- package/dist/routes/timelines.js +191 -0
- package/dist/routes/timelines.js.map +1 -0
- package/dist/routes/workflows.d.ts +6 -9
- package/dist/routes/workflows.d.ts.map +1 -1
- package/dist/routes/workflows.js +100 -11
- package/dist/routes/workflows.js.map +1 -1
- package/dist/routes/workspace.d.ts.map +1 -1
- package/dist/run-supervisor.d.ts +30 -0
- package/dist/run-supervisor.d.ts.map +1 -0
- package/dist/run-supervisor.js +86 -0
- package/dist/run-supervisor.js.map +1 -0
- package/dist/sandbox-catalog.d.ts +28 -0
- package/dist/sandbox-catalog.d.ts.map +1 -0
- package/dist/sandbox-catalog.js +74 -0
- package/dist/sandbox-catalog.js.map +1 -0
- package/dist/screenshot-projects.d.ts +27 -0
- package/dist/screenshot-projects.d.ts.map +1 -0
- package/dist/screenshot-projects.js +880 -0
- package/dist/screenshot-projects.js.map +1 -0
- package/dist/screenshot-server.js +947 -43
- package/dist/screenshot-server.js.map +1 -1
- package/dist/sdk/sdk-cached-model-inventory.d.ts +21 -0
- package/dist/sdk/sdk-cached-model-inventory.d.ts.map +1 -0
- package/dist/sdk/sdk-cached-model-inventory.js +51 -0
- package/dist/sdk/sdk-cached-model-inventory.js.map +1 -0
- package/dist/sdk/sdk-capabilities-service.d.ts +32 -0
- package/dist/sdk/sdk-capabilities-service.d.ts.map +1 -0
- package/dist/sdk/sdk-capabilities-service.js +47 -0
- package/dist/sdk/sdk-capabilities-service.js.map +1 -0
- package/dist/sdk/sdk-execution-readiness-probe.d.ts +19 -0
- package/dist/sdk/sdk-execution-readiness-probe.d.ts.map +1 -0
- package/dist/sdk/sdk-execution-readiness-probe.js +90 -0
- package/dist/sdk/sdk-execution-readiness-probe.js.map +1 -0
- package/dist/sdk/sdk-execution-target-readiness.d.ts +15 -0
- package/dist/sdk/sdk-execution-target-readiness.d.ts.map +1 -0
- package/dist/sdk/sdk-execution-target-readiness.js +50 -0
- package/dist/sdk/sdk-execution-target-readiness.js.map +1 -0
- package/dist/sdk/sdk-feature-flags.d.ts +18 -0
- package/dist/sdk/sdk-feature-flags.d.ts.map +1 -0
- package/dist/sdk/sdk-feature-flags.js +30 -0
- package/dist/sdk/sdk-feature-flags.js.map +1 -0
- package/dist/sdk/sdk-huggingface-download-state.d.ts +15 -0
- package/dist/sdk/sdk-huggingface-download-state.d.ts.map +1 -0
- package/dist/sdk/sdk-huggingface-download-state.js +25 -0
- package/dist/sdk/sdk-huggingface-download-state.js.map +1 -0
- package/dist/sdk/sdk-live-runner-registry.d.ts +21 -0
- package/dist/sdk/sdk-live-runner-registry.d.ts.map +1 -0
- package/dist/sdk/sdk-live-runner-registry.js +26 -0
- package/dist/sdk/sdk-live-runner-registry.js.map +1 -0
- package/dist/sdk/sdk-model-catalog-service.d.ts +20 -0
- package/dist/sdk/sdk-model-catalog-service.d.ts.map +1 -0
- package/dist/sdk/sdk-model-catalog-service.js +219 -0
- package/dist/sdk/sdk-model-catalog-service.js.map +1 -0
- package/dist/sdk/sdk-model-download-service.d.ts +39 -0
- package/dist/sdk/sdk-model-download-service.d.ts.map +1 -0
- package/dist/sdk/sdk-model-download-service.js +274 -0
- package/dist/sdk/sdk-model-download-service.js.map +1 -0
- package/dist/sdk/sdk-model-requirement-probe.d.ts +30 -0
- package/dist/sdk/sdk-model-requirement-probe.d.ts.map +1 -0
- package/dist/sdk/sdk-model-requirement-probe.js +120 -0
- package/dist/sdk/sdk-model-requirement-probe.js.map +1 -0
- package/dist/sdk/sdk-node-package-requirement-probe.d.ts +20 -0
- package/dist/sdk/sdk-node-package-requirement-probe.d.ts.map +1 -0
- package/dist/sdk/sdk-node-package-requirement-probe.js +44 -0
- package/dist/sdk/sdk-node-package-requirement-probe.js.map +1 -0
- package/dist/sdk/sdk-node-type-inventory-service.d.ts +11 -0
- package/dist/sdk/sdk-node-type-inventory-service.d.ts.map +1 -0
- package/dist/sdk/sdk-node-type-inventory-service.js +36 -0
- package/dist/sdk/sdk-node-type-inventory-service.js.map +1 -0
- package/dist/sdk/sdk-preflight-orchestrator.d.ts +54 -0
- package/dist/sdk/sdk-preflight-orchestrator.d.ts.map +1 -0
- package/dist/sdk/sdk-preflight-orchestrator.js +63 -0
- package/dist/sdk/sdk-preflight-orchestrator.js.map +1 -0
- package/dist/sdk/sdk-preflight-requirement-resolver.d.ts +35 -0
- package/dist/sdk/sdk-preflight-requirement-resolver.d.ts.map +1 -0
- package/dist/sdk/sdk-preflight-requirement-resolver.js +67 -0
- package/dist/sdk/sdk-preflight-requirement-resolver.js.map +1 -0
- package/dist/sdk/sdk-preflight-service.d.ts +61 -0
- package/dist/sdk/sdk-preflight-service.d.ts.map +1 -0
- package/dist/sdk/sdk-preflight-service.js +104 -0
- package/dist/sdk/sdk-preflight-service.js.map +1 -0
- package/dist/sdk/sdk-preflight-workflow-source.d.ts +18 -0
- package/dist/sdk/sdk-preflight-workflow-source.d.ts.map +1 -0
- package/dist/sdk/sdk-preflight-workflow-source.js +42 -0
- package/dist/sdk/sdk-preflight-workflow-source.js.map +1 -0
- package/dist/sdk/sdk-route-policy.d.ts +3 -0
- package/dist/sdk/sdk-route-policy.d.ts.map +1 -0
- package/dist/sdk/sdk-route-policy.js +18 -0
- package/dist/sdk/sdk-route-policy.js.map +1 -0
- package/dist/sdk/sdk-runtime-capabilities-service.d.ts +60 -0
- package/dist/sdk/sdk-runtime-capabilities-service.d.ts.map +1 -0
- package/dist/sdk/sdk-runtime-capabilities-service.js +30 -0
- package/dist/sdk/sdk-runtime-capabilities-service.js.map +1 -0
- package/dist/sdk/sdk-runtime-requirement-probe.d.ts +13 -0
- package/dist/sdk/sdk-runtime-requirement-probe.d.ts.map +1 -0
- package/dist/sdk/sdk-runtime-requirement-probe.js +55 -0
- package/dist/sdk/sdk-runtime-requirement-probe.js.map +1 -0
- package/dist/sdk/sdk-static-preflight-service.d.ts +66 -0
- package/dist/sdk/sdk-static-preflight-service.d.ts.map +1 -0
- package/dist/sdk/sdk-static-preflight-service.js +492 -0
- package/dist/sdk/sdk-static-preflight-service.js.map +1 -0
- package/dist/sdk/sdk-temporary-asset-service.d.ts +18 -0
- package/dist/sdk/sdk-temporary-asset-service.d.ts.map +1 -0
- package/dist/sdk/sdk-temporary-asset-service.js +33 -0
- package/dist/sdk/sdk-temporary-asset-service.js.map +1 -0
- package/dist/sdk/sdk-temporary-asset-upload-http-handler.d.ts +9 -0
- package/dist/sdk/sdk-temporary-asset-upload-http-handler.d.ts.map +1 -0
- package/dist/sdk/sdk-temporary-asset-upload-http-handler.js +65 -0
- package/dist/sdk/sdk-temporary-asset-upload-http-handler.js.map +1 -0
- package/dist/sdk/sdk-v1-handler-map.d.ts +44 -0
- package/dist/sdk/sdk-v1-handler-map.d.ts.map +1 -0
- package/dist/sdk/sdk-v1-handler-map.js +37 -0
- package/dist/sdk/sdk-v1-handler-map.js.map +1 -0
- package/dist/sdk/sdk-v1-service-error.d.ts +21 -0
- package/dist/sdk/sdk-v1-service-error.d.ts.map +1 -0
- package/dist/sdk/sdk-v1-service-error.js +62 -0
- package/dist/sdk/sdk-v1-service-error.js.map +1 -0
- package/dist/sdk/sdk-v1-service.d.ts +74 -0
- package/dist/sdk/sdk-v1-service.d.ts.map +1 -0
- package/dist/sdk/sdk-v1-service.js +219 -0
- package/dist/sdk/sdk-v1-service.js.map +1 -0
- package/dist/sdk/sdk-worker-readiness-adapter.d.ts +22 -0
- package/dist/sdk/sdk-worker-readiness-adapter.d.ts.map +1 -0
- package/dist/sdk/sdk-worker-readiness-adapter.js +29 -0
- package/dist/sdk/sdk-worker-readiness-adapter.js.map +1 -0
- package/dist/server.js +1019 -201
- package/dist/server.js.map +1 -1
- package/dist/session/asset-autosave.d.ts +80 -0
- package/dist/session/asset-autosave.d.ts.map +1 -0
- package/dist/session/asset-autosave.js +456 -0
- package/dist/session/asset-autosave.js.map +1 -0
- package/dist/session/chat-compaction.d.ts +107 -0
- package/dist/session/chat-compaction.d.ts.map +1 -0
- package/dist/session/chat-compaction.js +191 -0
- package/dist/session/chat-compaction.js.map +1 -0
- package/dist/session/chat-history.d.ts +75 -0
- package/dist/session/chat-history.d.ts.map +1 -0
- package/dist/session/chat-history.js +194 -0
- package/dist/session/chat-history.js.map +1 -0
- package/dist/session/chat-prompt.d.ts +45 -0
- package/dist/session/chat-prompt.d.ts.map +1 -0
- package/dist/session/chat-prompt.js +480 -0
- package/dist/session/chat-prompt.js.map +1 -0
- package/dist/session/chat-turn.d.ts +336 -0
- package/dist/session/chat-turn.d.ts.map +1 -0
- package/dist/session/chat-turn.js +3516 -0
- package/dist/session/chat-turn.js.map +1 -0
- package/dist/session/client-session.d.ts +59 -0
- package/dist/session/client-session.d.ts.map +1 -0
- package/dist/session/client-session.js +2 -0
- package/dist/session/client-session.js.map +1 -0
- package/dist/session/commands.d.ts +133 -0
- package/dist/session/commands.d.ts.map +1 -0
- package/dist/session/commands.js +778 -0
- package/dist/session/commands.js.map +1 -0
- package/dist/session/inference.d.ts +213 -0
- package/dist/session/inference.d.ts.map +1 -0
- package/dist/session/inference.js +1072 -0
- package/dist/session/inference.js.map +1 -0
- package/dist/session/job-execution.d.ts +477 -0
- package/dist/session/job-execution.d.ts.map +1 -0
- package/dist/session/job-execution.js +2089 -0
- package/dist/session/job-execution.js.map +1 -0
- package/dist/session/media-generation.d.ts +94 -0
- package/dist/session/media-generation.d.ts.map +1 -0
- package/dist/session/media-generation.js +234 -0
- package/dist/session/media-generation.js.map +1 -0
- package/dist/session/model-interfaces.d.ts +27 -0
- package/dist/session/model-interfaces.d.ts.map +1 -0
- package/dist/session/model-interfaces.js +132 -0
- package/dist/session/model-interfaces.js.map +1 -0
- package/dist/session/sanitize.d.ts +7 -0
- package/dist/session/sanitize.d.ts.map +1 -0
- package/dist/session/sanitize.js +64 -0
- package/dist/session/sanitize.js.map +1 -0
- package/dist/settings-registry.d.ts +6 -15
- package/dist/settings-registry.d.ts.map +1 -1
- package/dist/settings-registry.js +6 -103
- package/dist/settings-registry.js.map +1 -1
- package/dist/storage-api.d.ts +20 -0
- package/dist/storage-api.d.ts.map +1 -1
- package/dist/storage-api.js +260 -77
- package/dist/storage-api.js.map +1 -1
- package/dist/storage-retention.d.ts +9 -0
- package/dist/storage-retention.d.ts.map +1 -0
- package/dist/storage-retention.js +74 -0
- package/dist/storage-retention.js.map +1 -0
- package/dist/system-stats.d.ts +52 -0
- package/dist/system-stats.d.ts.map +1 -0
- package/dist/system-stats.js +134 -0
- package/dist/system-stats.js.map +1 -0
- package/dist/test-ui-server.d.ts +46 -0
- package/dist/test-ui-server.d.ts.map +1 -1
- package/dist/test-ui-server.js +188 -41
- package/dist/test-ui-server.js.map +1 -1
- package/dist/triggers/boot.d.ts +73 -0
- package/dist/triggers/boot.d.ts.map +1 -0
- package/dist/triggers/boot.js +149 -0
- package/dist/triggers/boot.js.map +1 -0
- package/dist/triggers/dispatcher.d.ts +234 -0
- package/dist/triggers/dispatcher.d.ts.map +1 -0
- package/dist/triggers/dispatcher.js +525 -0
- package/dist/triggers/dispatcher.js.map +1 -0
- package/dist/triggers/file-watch.d.ts +90 -0
- package/dist/triggers/file-watch.d.ts.map +1 -0
- package/dist/triggers/file-watch.js +405 -0
- package/dist/triggers/file-watch.js.map +1 -0
- package/dist/triggers/registration-sync.d.ts +34 -0
- package/dist/triggers/registration-sync.d.ts.map +1 -0
- package/dist/triggers/registration-sync.js +162 -0
- package/dist/triggers/registration-sync.js.map +1 -0
- package/dist/triggers/schedule-timing.d.ts +52 -0
- package/dist/triggers/schedule-timing.d.ts.map +1 -0
- package/dist/triggers/schedule-timing.js +90 -0
- package/dist/triggers/schedule-timing.js.map +1 -0
- package/dist/triggers/scheduler.d.ts +55 -0
- package/dist/triggers/scheduler.d.ts.map +1 -0
- package/dist/triggers/scheduler.js +122 -0
- package/dist/triggers/scheduler.js.map +1 -0
- package/dist/triggers/settle.d.ts +66 -0
- package/dist/triggers/settle.d.ts.map +1 -0
- package/dist/triggers/settle.js +99 -0
- package/dist/triggers/settle.js.map +1 -0
- package/dist/triggers/stores.d.ts +38 -0
- package/dist/triggers/stores.d.ts.map +1 -0
- package/dist/triggers/stores.js +168 -0
- package/dist/triggers/stores.js.map +1 -0
- package/dist/triggers/webhook-route.d.ts +49 -0
- package/dist/triggers/webhook-route.d.ts.map +1 -0
- package/dist/triggers/webhook-route.js +148 -0
- package/dist/triggers/webhook-route.js.map +1 -0
- package/dist/trpc/context.d.ts +52 -5
- package/dist/trpc/context.d.ts.map +1 -1
- package/dist/trpc/context.js +4 -1
- package/dist/trpc/context.js.map +1 -1
- package/dist/trpc/error-formatter.d.ts.map +1 -1
- package/dist/trpc/error-formatter.js +23 -2
- package/dist/trpc/error-formatter.js.map +1 -1
- package/dist/trpc/error-logging.d.ts +14 -0
- package/dist/trpc/error-logging.d.ts.map +1 -0
- package/dist/trpc/error-logging.js +27 -0
- package/dist/trpc/error-logging.js.map +1 -0
- package/dist/trpc/index.d.ts +2 -2
- package/dist/trpc/index.d.ts.map +1 -1
- package/dist/trpc/index.js +0 -2
- package/dist/trpc/index.js.map +1 -1
- package/dist/trpc/middleware.d.ts +6 -3
- package/dist/trpc/middleware.d.ts.map +1 -1
- package/dist/trpc/router.d.ts +29791 -1303
- package/dist/trpc/router.d.ts.map +1 -1
- package/dist/trpc/router.js +46 -3
- package/dist/trpc/router.js.map +1 -1
- package/dist/trpc/routers/agent-access.d.ts +149 -0
- package/dist/trpc/routers/agent-access.d.ts.map +1 -0
- package/dist/trpc/routers/agent-access.js +224 -0
- package/dist/trpc/routers/agent-access.js.map +1 -0
- package/dist/trpc/routers/applications.d.ts +1117 -0
- package/dist/trpc/routers/applications.d.ts.map +1 -0
- package/dist/trpc/routers/applications.js +218 -0
- package/dist/trpc/routers/applications.js.map +1 -0
- package/dist/trpc/routers/assets.d.ts +184 -42
- package/dist/trpc/routers/assets.d.ts.map +1 -1
- package/dist/trpc/routers/assets.js +499 -105
- package/dist/trpc/routers/assets.js.map +1 -1
- package/dist/trpc/routers/code-gen.d.ts +99 -0
- package/dist/trpc/routers/code-gen.d.ts.map +1 -0
- package/dist/trpc/routers/code-gen.js +164 -0
- package/dist/trpc/routers/code-gen.js.map +1 -0
- package/dist/trpc/routers/collections.d.ts +1 -26
- package/dist/trpc/routers/collections.d.ts.map +1 -1
- package/dist/trpc/routers/collections.js +145 -78
- package/dist/trpc/routers/collections.js.map +1 -1
- package/dist/trpc/routers/costs.d.ts +40 -96
- package/dist/trpc/routers/costs.d.ts.map +1 -1
- package/dist/trpc/routers/costs.js +14 -89
- package/dist/trpc/routers/costs.js.map +1 -1
- package/dist/trpc/routers/credits.d.ts +110 -0
- package/dist/trpc/routers/credits.d.ts.map +1 -0
- package/dist/trpc/routers/credits.js +69 -0
- package/dist/trpc/routers/credits.js.map +1 -0
- package/dist/trpc/routers/custom-providers.d.ts +88 -0
- package/dist/trpc/routers/custom-providers.d.ts.map +1 -0
- package/dist/trpc/routers/custom-providers.js +140 -0
- package/dist/trpc/routers/custom-providers.js.map +1 -0
- package/dist/trpc/routers/documents.d.ts +61 -0
- package/dist/trpc/routers/documents.d.ts.map +1 -0
- package/dist/trpc/routers/documents.js +23 -0
- package/dist/trpc/routers/documents.js.map +1 -0
- package/dist/trpc/routers/extension.d.ts +24 -0
- package/dist/trpc/routers/extension.d.ts.map +1 -0
- package/dist/trpc/routers/extension.js +28 -0
- package/dist/trpc/routers/extension.js.map +1 -0
- package/dist/trpc/routers/external-mcp.d.ts +108 -0
- package/dist/trpc/routers/external-mcp.d.ts.map +1 -0
- package/dist/trpc/routers/external-mcp.js +70 -0
- package/dist/trpc/routers/external-mcp.js.map +1 -0
- package/dist/trpc/routers/files.d.ts +9 -2
- package/dist/trpc/routers/files.d.ts.map +1 -1
- package/dist/trpc/routers/files.js +67 -37
- package/dist/trpc/routers/files.js.map +1 -1
- package/dist/trpc/routers/fonts.d.ts +30 -0
- package/dist/trpc/routers/fonts.d.ts.map +1 -0
- package/dist/trpc/routers/fonts.js +112 -0
- package/dist/trpc/routers/fonts.js.map +1 -0
- package/dist/trpc/routers/games.d.ts +7610 -0
- package/dist/trpc/routers/games.d.ts.map +1 -0
- package/dist/trpc/routers/games.js +456 -0
- package/dist/trpc/routers/games.js.map +1 -0
- package/dist/trpc/routers/integrations.d.ts +86 -0
- package/dist/trpc/routers/integrations.d.ts.map +1 -0
- package/dist/trpc/routers/integrations.js +129 -0
- package/dist/trpc/routers/integrations.js.map +1 -0
- package/dist/trpc/routers/jobs.d.ts +88 -27
- package/dist/trpc/routers/jobs.d.ts.map +1 -1
- package/dist/trpc/routers/jobs.js +113 -35
- package/dist/trpc/routers/jobs.js.map +1 -1
- package/dist/trpc/routers/js-scripts.d.ts +410 -0
- package/dist/trpc/routers/js-scripts.d.ts.map +1 -0
- package/dist/trpc/routers/js-scripts.js +303 -0
- package/dist/trpc/routers/js-scripts.js.map +1 -0
- package/dist/trpc/routers/mcp-config.d.ts +1 -1
- package/dist/trpc/routers/mcp-config.js +5 -3
- package/dist/trpc/routers/mcp-config.js.map +1 -1
- package/dist/trpc/routers/memories.d.ts +79 -0
- package/dist/trpc/routers/memories.d.ts.map +1 -0
- package/dist/trpc/routers/memories.js +66 -0
- package/dist/trpc/routers/memories.js.map +1 -0
- package/dist/trpc/routers/messages.d.ts +4 -77
- package/dist/trpc/routers/messages.d.ts.map +1 -1
- package/dist/trpc/routers/messages.js +9 -58
- package/dist/trpc/routers/messages.js.map +1 -1
- package/dist/trpc/routers/models.d.ts +1403 -238
- package/dist/trpc/routers/models.d.ts.map +1 -1
- package/dist/trpc/routers/models.js +532 -294
- package/dist/trpc/routers/models.js.map +1 -1
- package/dist/trpc/routers/nodes.d.ts +32 -16
- package/dist/trpc/routers/nodes.d.ts.map +1 -1
- package/dist/trpc/routers/nodes.js +70 -31
- package/dist/trpc/routers/nodes.js.map +1 -1
- package/dist/trpc/routers/packs.d.ts +184 -0
- package/dist/trpc/routers/packs.d.ts.map +1 -0
- package/dist/trpc/routers/packs.js +259 -0
- package/dist/trpc/routers/packs.js.map +1 -0
- package/dist/trpc/routers/projects.d.ts +422 -0
- package/dist/trpc/routers/projects.d.ts.map +1 -0
- package/dist/trpc/routers/projects.js +373 -0
- package/dist/trpc/routers/projects.js.map +1 -0
- package/dist/trpc/routers/resources.d.ts +120 -0
- package/dist/trpc/routers/resources.d.ts.map +1 -0
- package/dist/trpc/routers/resources.js +212 -0
- package/dist/trpc/routers/resources.js.map +1 -0
- package/dist/trpc/routers/scripts.d.ts +1116 -0
- package/dist/trpc/routers/scripts.d.ts.map +1 -0
- package/dist/trpc/routers/scripts.js +131 -0
- package/dist/trpc/routers/scripts.js.map +1 -0
- package/dist/trpc/routers/segmentation.d.ts +62 -0
- package/dist/trpc/routers/segmentation.d.ts.map +1 -0
- package/dist/trpc/routers/segmentation.js +146 -0
- package/dist/trpc/routers/segmentation.js.map +1 -0
- package/dist/trpc/routers/settings.d.ts +177 -10
- package/dist/trpc/routers/settings.d.ts.map +1 -1
- package/dist/trpc/routers/settings.js +123 -33
- package/dist/trpc/routers/settings.js.map +1 -1
- package/dist/trpc/routers/sketch.d.ts +854 -0
- package/dist/trpc/routers/sketch.d.ts.map +1 -0
- package/dist/trpc/routers/sketch.js +617 -0
- package/dist/trpc/routers/sketch.js.map +1 -0
- package/dist/trpc/routers/skills.d.ts +76 -22
- package/dist/trpc/routers/skills.d.ts.map +1 -1
- package/dist/trpc/routers/skills.js +195 -170
- package/dist/trpc/routers/skills.js.map +1 -1
- package/dist/trpc/routers/storage.d.ts +3 -30
- package/dist/trpc/routers/storage.d.ts.map +1 -1
- package/dist/trpc/routers/storage.js +60 -117
- package/dist/trpc/routers/storage.js.map +1 -1
- package/dist/trpc/routers/storyboards.d.ts +5907 -0
- package/dist/trpc/routers/storyboards.d.ts.map +1 -0
- package/dist/trpc/routers/storyboards.js +156 -0
- package/dist/trpc/routers/storyboards.js.map +1 -0
- package/dist/trpc/routers/threads.d.ts +33 -21
- package/dist/trpc/routers/threads.d.ts.map +1 -1
- package/dist/trpc/routers/threads.js +36 -30
- package/dist/trpc/routers/threads.js.map +1 -1
- package/dist/trpc/routers/timeline.d.ts +8516 -0
- package/dist/trpc/routers/timeline.d.ts.map +1 -0
- package/dist/trpc/routers/timeline.js +493 -0
- package/dist/trpc/routers/timeline.js.map +1 -0
- package/dist/trpc/routers/triggers.d.ts +46 -0
- package/dist/trpc/routers/triggers.d.ts.map +1 -0
- package/dist/trpc/routers/triggers.js +117 -0
- package/dist/trpc/routers/triggers.js.map +1 -0
- package/dist/trpc/routers/users.d.ts +1 -14
- package/dist/trpc/routers/users.d.ts.map +1 -1
- package/dist/trpc/routers/users.js +1 -12
- package/dist/trpc/routers/users.js.map +1 -1
- package/dist/trpc/routers/worker.d.ts +242 -0
- package/dist/trpc/routers/worker.d.ts.map +1 -0
- package/dist/trpc/routers/worker.js +220 -0
- package/dist/trpc/routers/worker.js.map +1 -0
- package/dist/trpc/routers/workflows.d.ts +385 -197
- package/dist/trpc/routers/workflows.d.ts.map +1 -1
- package/dist/trpc/routers/workflows.js +326 -345
- package/dist/trpc/routers/workflows.js.map +1 -1
- package/dist/trpc/routers/workspace.d.ts +59 -33
- package/dist/trpc/routers/workspace.d.ts.map +1 -1
- package/dist/trpc/routers/workspace.js +230 -93
- package/dist/trpc/routers/workspace.js.map +1 -1
- package/dist/trpc/sandbox-coverage.d.ts +64 -0
- package/dist/trpc/sandbox-coverage.d.ts.map +1 -0
- package/dist/trpc/sandbox-coverage.js +1049 -0
- package/dist/trpc/sandbox-coverage.js.map +1 -0
- package/dist/websocket-client-session.d.ts +320 -0
- package/dist/websocket-client-session.d.ts.map +1 -0
- package/dist/websocket-client-session.js +1253 -0
- package/dist/websocket-client-session.js.map +1 -0
- package/dist/workflow-interface-service.d.ts +87 -0
- package/dist/workflow-interface-service.d.ts.map +1 -0
- package/dist/workflow-interface-service.js +131 -0
- package/dist/workflow-interface-service.js.map +1 -0
- package/dist/workspace-api.d.ts.map +1 -1
- package/dist/workspace-api.js +33 -23
- package/dist/workspace-api.js.map +1 -1
- package/dist/ws-adapter.d.ts +46 -3
- package/dist/ws-adapter.d.ts.map +1 -1
- package/dist/ws-adapter.js +164 -26
- package/dist/ws-adapter.js.map +1 -1
- package/package.json +81 -35
- package/dist/agent/agent-runtime.d.ts +0 -47
- package/dist/agent/agent-runtime.d.ts.map +0 -1
- package/dist/agent/agent-runtime.js +0 -579
- package/dist/agent/agent-runtime.js.map +0 -1
- package/dist/agent/codex-agent.d.ts +0 -41
- package/dist/agent/codex-agent.d.ts.map +0 -1
- package/dist/agent/codex-agent.js +0 -334
- package/dist/agent/codex-agent.js.map +0 -1
- package/dist/agent/index.d.ts +0 -6
- package/dist/agent/index.d.ts.map +0 -1
- package/dist/agent/index.js +0 -4
- package/dist/agent/index.js.map +0 -1
- package/dist/agent/llm-agent.d.ts +0 -51
- package/dist/agent/llm-agent.d.ts.map +0 -1
- package/dist/agent/llm-agent.js +0 -526
- package/dist/agent/llm-agent.js.map +0 -1
- package/dist/agent/mcp-tool-server.d.ts +0 -33
- package/dist/agent/mcp-tool-server.d.ts.map +0 -1
- package/dist/agent/mcp-tool-server.js +0 -292
- package/dist/agent/mcp-tool-server.js.map +0 -1
- package/dist/agent/opencode-agent.d.ts +0 -32
- package/dist/agent/opencode-agent.d.ts.map +0 -1
- package/dist/agent/opencode-agent.js +0 -332
- package/dist/agent/opencode-agent.js.map +0 -1
- package/dist/agent/pi-agent.d.ts +0 -42
- package/dist/agent/pi-agent.d.ts.map +0 -1
- package/dist/agent/pi-agent.js +0 -429
- package/dist/agent/pi-agent.js.map +0 -1
- package/dist/agent/sdk-provider.d.ts +0 -46
- package/dist/agent/sdk-provider.d.ts.map +0 -1
- package/dist/agent/sdk-provider.js +0 -50
- package/dist/agent/sdk-provider.js.map +0 -1
- package/dist/agent/socket-route.d.ts +0 -11
- package/dist/agent/socket-route.d.ts.map +0 -1
- package/dist/agent/socket-route.js +0 -262
- package/dist/agent/socket-route.js.map +0 -1
- package/dist/agent/transport.d.ts +0 -39
- package/dist/agent/transport.d.ts.map +0 -1
- package/dist/agent/transport.js +0 -17
- package/dist/agent/transport.js.map +0 -1
- package/dist/agent/types.d.ts +0 -11
- package/dist/agent/types.d.ts.map +0 -1
- package/dist/agent/types.js +0 -10
- package/dist/agent/types.js.map +0 -1
- package/dist/routes/jobs.d.ts +0 -16
- package/dist/routes/jobs.d.ts.map +0 -1
- package/dist/routes/jobs.js +0 -25
- package/dist/routes/jobs.js.map +0 -1
- package/dist/trpc/routers/sandboxes.d.ts +0 -64
- package/dist/trpc/routers/sandboxes.d.ts.map +0 -1
- package/dist/trpc/routers/sandboxes.js +0 -327
- package/dist/trpc/routers/sandboxes.js.map +0 -1
- package/dist/unified-websocket-runner.d.ts +0 -280
- package/dist/unified-websocket-runner.d.ts.map +0 -1
- package/dist/unified-websocket-runner.js +0 -3840
- package/dist/unified-websocket-runner.js.map +0 -1
|
@@ -0,0 +1,1253 @@
|
|
|
1
|
+
import { getSetting } from "./settings-registry.js";
|
|
2
|
+
import { ConfiguredProviderCache } from "./configured-providers.js";
|
|
3
|
+
import { packWebSocketMessage, unpackWebSocketMessage } from "./messagepack.js";
|
|
4
|
+
import { createLogger, getByteLimitEnv } from "@nodetool-ai/config";
|
|
5
|
+
import { getAssetAdapter } from "./lib/storage.js";
|
|
6
|
+
import { isNonEmptyString, isObjectLike, isString } from "./lib/wire-values.js";
|
|
7
|
+
import { onDrain } from "./drain.js";
|
|
8
|
+
import { resourceEvents } from "./resource-events.js";
|
|
9
|
+
import { createSystemStatsSampler, systemStatsBroadcastEnabled } from "./system-stats.js";
|
|
10
|
+
import { resolveContentUrls } from "./resolve-media-urls.js";
|
|
11
|
+
import { Asset, ModelObserver } from "@nodetool-ai/models";
|
|
12
|
+
import { fetchExternalMedia } from "@nodetool-ai/runtime";
|
|
13
|
+
import { webSocketCommandEnvelopeSchema, commandDataSchemas, controlMessageInSchemas, outboundControlMessageSchemas, processingMessageSchemas } from "@nodetool-ai/protocol";
|
|
14
|
+
import { retrieveAssetBytes } from "./lib/asset-paths.js";
|
|
15
|
+
import { encodeNativeAudioChunks, primaryTextOutputName } from "./session/asset-autosave.js";
|
|
16
|
+
import { buildChatAgentSystemPrompt, CHAT_AGENT_SYSTEM_PROMPT, focusedUiToolNames, normalizeToolCallName, RESIDENT_TOOL_NAMES, unroutableToolMessage } from "./session/chat-prompt.js";
|
|
17
|
+
import { serverModelInterfaces } from "./session/model-interfaces.js";
|
|
18
|
+
import { formatSanitizedError } from "./session/sanitize.js";
|
|
19
|
+
import { DirectInferenceHandler, entityRefResolver, estimateDirectTextSpend, resolveEntityReferenceImages } from "./session/inference.js";
|
|
20
|
+
// The pure helpers moved to ./session/*; re-exported here so every existing
|
|
21
|
+
// import path keeps working.
|
|
22
|
+
export { CHAT_AGENT_SYSTEM_PROMPT, RESIDENT_TOOL_NAMES, buildChatAgentSystemPrompt, estimateDirectTextSpend, focusedUiToolNames, normalizeToolCallName, primaryTextOutputName, serverModelInterfaces, unroutableToolMessage };
|
|
23
|
+
import { DEFAULT_RUN_JOB_EXECUTION_OPTIONS, JobExecutionManager, resolveRunJobExecutionOptions, resolveRunJobUserId } from "./session/job-execution.js";
|
|
24
|
+
// The job region moved to ./session/job-execution.ts; its wire types are
|
|
25
|
+
// re-exported here so every existing import path keeps working.
|
|
26
|
+
export { DEFAULT_RUN_JOB_EXECUTION_OPTIONS, resolveRunJobExecutionOptions, resolveRunJobUserId };
|
|
27
|
+
import { ChatTurnHandler } from "./session/chat-turn.js";
|
|
28
|
+
import { CommandRouter } from "./session/commands.js";
|
|
29
|
+
const log = createLogger("nodetool.websocket.runner");
|
|
30
|
+
/** RFC 6455 "service restart" — what a drained connection is closed with. */
|
|
31
|
+
const DRAIN_CLOSE_CODE = 1012;
|
|
32
|
+
/** How often a draining connection re-checks whether its work has settled. */
|
|
33
|
+
const DRAIN_POLL_MS = 250;
|
|
34
|
+
/**
|
|
35
|
+
* Largest binary (MsgPack) frame accepted from a client before deserialization.
|
|
36
|
+
* MsgPack can amplify a small payload into a huge in-memory structure, so the
|
|
37
|
+
* raw byte length is bounded up front. Override with the
|
|
38
|
+
* `NODETOOL_WS_MAX_MESSAGE_BYTES` environment variable (value in bytes);
|
|
39
|
+
* default 256 MiB.
|
|
40
|
+
*/
|
|
41
|
+
const DEFAULT_MAX_WS_MESSAGE_BYTES = 256 * 1024 * 1024;
|
|
42
|
+
function getMaxWsMessageBytes() {
|
|
43
|
+
return getByteLimitEnv("NODETOOL_WS_MAX_MESSAGE_BYTES", DEFAULT_MAX_WS_MESSAGE_BYTES);
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Outbound (server→client) frame validation gate. Every message `sendMessage`
|
|
47
|
+
* emits whose `type` matches a known `ProcessingMessage` variant or one of
|
|
48
|
+
* the small set of non-`ProcessingMessage` server frames (`pong`,
|
|
49
|
+
* `rpc_response`, `system_stats`, `resource_change`) is safe-parsed against
|
|
50
|
+
* its Zod schema before it goes on the wire; frames with an unrecognized (or
|
|
51
|
+
* absent) `type` — the ad hoc `{ error, details }` command replies — are left
|
|
52
|
+
* alone, as they always have been.
|
|
53
|
+
*
|
|
54
|
+
* Set `NODETOOL_VALIDATE_OUTBOUND_WS=1` to force validation on, `=0` to force
|
|
55
|
+
* it off. Unset, it defaults to on under `NODE_ENV=test` or Vitest (`VITEST`)
|
|
56
|
+
* and off everywhere else — a server bug that produces a malformed frame
|
|
57
|
+
* should fail the test that exercised it, not corrupt a production
|
|
58
|
+
* connection with a thrown error mid-stream. On failure it throws (the
|
|
59
|
+
* caller — `sendMessage` — is already inside the code path the bug is in, so
|
|
60
|
+
* failing loudly there is what surfaces it to the test).
|
|
61
|
+
*/
|
|
62
|
+
function shouldValidateOutboundWs() {
|
|
63
|
+
const override = process.env["NODETOOL_VALIDATE_OUTBOUND_WS"]?.trim();
|
|
64
|
+
if (override === "1" || override === "true")
|
|
65
|
+
return true;
|
|
66
|
+
if (override === "0" || override === "false")
|
|
67
|
+
return false;
|
|
68
|
+
return process.env["NODE_ENV"] === "test" || Boolean(process.env["VITEST"]);
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Throws when outbound validation is enabled and `message` carries a `type`
|
|
72
|
+
* this package can validate but fails to conform to its schema. No-op for
|
|
73
|
+
* unrecognized/absent `type` values — see {@link shouldValidateOutboundWs}.
|
|
74
|
+
*/
|
|
75
|
+
function assertValidOutboundMessage(message) {
|
|
76
|
+
if (!shouldValidateOutboundWs())
|
|
77
|
+
return;
|
|
78
|
+
const type = isString(message["type"]) ? message["type"] : null;
|
|
79
|
+
if (!type)
|
|
80
|
+
return;
|
|
81
|
+
const schema = processingMessageSchemas[type] ??
|
|
82
|
+
outboundControlMessageSchemas[type];
|
|
83
|
+
if (!schema)
|
|
84
|
+
return;
|
|
85
|
+
const parsed = schema.safeParse(message);
|
|
86
|
+
if (!parsed.success) {
|
|
87
|
+
throw new Error(`Outbound WebSocket message failed protocol validation (type: "${type}"): ` +
|
|
88
|
+
parsed.error.issues
|
|
89
|
+
.map((issue) => `${issue.path.join(".") || "<root>"}: ${issue.message}`)
|
|
90
|
+
.join("; "));
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
export class ToolBridge {
|
|
94
|
+
waiters = new Map();
|
|
95
|
+
createWaiter(toolCallId, timeoutMs = 300_000, scope) {
|
|
96
|
+
return new Promise((resolve, reject) => {
|
|
97
|
+
let timer = null;
|
|
98
|
+
const cleanup = () => {
|
|
99
|
+
if (timer)
|
|
100
|
+
clearTimeout(timer);
|
|
101
|
+
this.waiters.delete(toolCallId);
|
|
102
|
+
};
|
|
103
|
+
const wrappedResolve = (value) => {
|
|
104
|
+
cleanup();
|
|
105
|
+
resolve(value);
|
|
106
|
+
};
|
|
107
|
+
const wrappedReject = (reason) => {
|
|
108
|
+
cleanup();
|
|
109
|
+
reject(reason);
|
|
110
|
+
};
|
|
111
|
+
this.waiters.set(toolCallId, {
|
|
112
|
+
resolve: wrappedResolve,
|
|
113
|
+
reject: wrappedReject,
|
|
114
|
+
scope
|
|
115
|
+
});
|
|
116
|
+
if (timeoutMs > 0) {
|
|
117
|
+
timer = setTimeout(() => {
|
|
118
|
+
if (this.waiters.has(toolCallId)) {
|
|
119
|
+
wrappedReject(new Error(`Tool call ${toolCallId} timed out after ${timeoutMs}ms`));
|
|
120
|
+
}
|
|
121
|
+
}, timeoutMs);
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
resolveResult(toolCallId, payload) {
|
|
126
|
+
const waiter = this.waiters.get(toolCallId);
|
|
127
|
+
if (!waiter)
|
|
128
|
+
return;
|
|
129
|
+
waiter.resolve(payload);
|
|
130
|
+
}
|
|
131
|
+
/** Resolve every waiter in `scope` with the same payload. */
|
|
132
|
+
resolveScope(scope, payload) {
|
|
133
|
+
for (const waiter of [...this.waiters.values()]) {
|
|
134
|
+
if (waiter.scope === scope) {
|
|
135
|
+
waiter.resolve(payload);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
rejectResult(toolCallId, error) {
|
|
140
|
+
const waiter = this.waiters.get(toolCallId);
|
|
141
|
+
if (!waiter)
|
|
142
|
+
return;
|
|
143
|
+
waiter.reject(error);
|
|
144
|
+
}
|
|
145
|
+
cancelAll() {
|
|
146
|
+
const error = new Error("All pending tool calls cancelled");
|
|
147
|
+
for (const waiter of this.waiters.values()) {
|
|
148
|
+
waiter.reject(error);
|
|
149
|
+
}
|
|
150
|
+
this.waiters.clear();
|
|
151
|
+
}
|
|
152
|
+
cancelScope(scope) {
|
|
153
|
+
const error = new Error(`Pending tool calls cancelled for ${scope}`);
|
|
154
|
+
for (const [id, waiter] of this.waiters) {
|
|
155
|
+
if (waiter.scope === scope) {
|
|
156
|
+
waiter.reject(error);
|
|
157
|
+
this.waiters.delete(id);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Cancel every pending call except those scoped to `scope`. Used on
|
|
163
|
+
* disconnect when a detached chat turn stays alive: its client tool calls
|
|
164
|
+
* survive (the replay re-delivers the `tool_call` frames, so a reconnecting
|
|
165
|
+
* client can still answer them) while everything else is rejected.
|
|
166
|
+
*/
|
|
167
|
+
cancelAllExcept(scope) {
|
|
168
|
+
const error = new Error("All pending tool calls cancelled");
|
|
169
|
+
for (const [id, waiter] of this.waiters) {
|
|
170
|
+
if (waiter.scope === scope)
|
|
171
|
+
continue;
|
|
172
|
+
waiter.reject(error);
|
|
173
|
+
this.waiters.delete(id);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
export class WebSocketClientSession {
|
|
178
|
+
websocket = null;
|
|
179
|
+
mode = "binary";
|
|
180
|
+
userId;
|
|
181
|
+
authToken;
|
|
182
|
+
/**
|
|
183
|
+
* Set when this connection was opened by a visitor to a deployed app's
|
|
184
|
+
* hidden URL. `userId` is then the app's owner, so nothing downstream can
|
|
185
|
+
* tell the two apart on its own — this is what does.
|
|
186
|
+
*/
|
|
187
|
+
appSession;
|
|
188
|
+
/**
|
|
189
|
+
* Assigned once, in the constructor. `readonly` because JobExecutionManager
|
|
190
|
+
* snapshots both by value into its `defaults`, and a later reassignment here
|
|
191
|
+
* would silently leave the manager on the old pair.
|
|
192
|
+
*/
|
|
193
|
+
defaultModel;
|
|
194
|
+
defaultProvider;
|
|
195
|
+
resolveExecutor;
|
|
196
|
+
resolveNodeType;
|
|
197
|
+
resolveProvider;
|
|
198
|
+
getSystemStats;
|
|
199
|
+
systemStatsEnabled;
|
|
200
|
+
workspaceResolver;
|
|
201
|
+
getNodeMetadata;
|
|
202
|
+
validateNode;
|
|
203
|
+
nodeRegistry;
|
|
204
|
+
pythonBridge;
|
|
205
|
+
frontendRendererRegistry;
|
|
206
|
+
frontendRendererId = null;
|
|
207
|
+
configuredProvidersCache = new ConfiguredProviderCache({});
|
|
208
|
+
sendLock = Promise.resolve();
|
|
209
|
+
/**
|
|
210
|
+
* The job region — run_job through terminal status. It owns `activeJobs`,
|
|
211
|
+
* the concurrency queue and the slot counters; nothing outside it holds a
|
|
212
|
+
* reference to them.
|
|
213
|
+
*/
|
|
214
|
+
jobs;
|
|
215
|
+
heartbeatTimer = null;
|
|
216
|
+
statsTimer = null;
|
|
217
|
+
statsPrimeTimer = null;
|
|
218
|
+
/**
|
|
219
|
+
* Abort controllers for RPC calls that are still waiting on a provider.
|
|
220
|
+
* An RPC has no chat turn to hang off, so a `stop` command and a dropped
|
|
221
|
+
* socket reach an in-flight model call through this set.
|
|
222
|
+
*/
|
|
223
|
+
rpcAborts = new Set();
|
|
224
|
+
/** One-shot model calls: the `inference` stream and the direct-generation RPCs. */
|
|
225
|
+
inference;
|
|
226
|
+
clientToolsManifest = {};
|
|
227
|
+
clientToolsManifestReady = false;
|
|
228
|
+
toolBridge = new ToolBridge();
|
|
229
|
+
/** Separate bridge for connection-level renderer calls; never resolves chat tool_result waiters. */
|
|
230
|
+
rendererToolBridge = new ToolBridge();
|
|
231
|
+
/** Round-trips permission approvals for gated tool calls. */
|
|
232
|
+
approvalBridge = new ToolBridge();
|
|
233
|
+
/** This connection's chat turns: state, permissions, and the turn loop. */
|
|
234
|
+
chat;
|
|
235
|
+
/** The client's command surface: one dispatch table over the wire commands. */
|
|
236
|
+
commands;
|
|
237
|
+
observerRegistered = false;
|
|
238
|
+
/** Unsubscribe from the process drain, held for the life of the socket. */
|
|
239
|
+
drainUnsubscribe = null;
|
|
240
|
+
/** Set while waiting for this connection's own work to settle mid-drain. */
|
|
241
|
+
drainTimer = null;
|
|
242
|
+
/**
|
|
243
|
+
* The detachable session for the chat turn THIS connection is executing.
|
|
244
|
+
* While set (and running), every outbound frame carrying its thread_id is
|
|
245
|
+
* routed through the session: stamped with `chat_seq`, buffered for replay,
|
|
246
|
+
* and delivered to whichever connection is currently attached — which stops
|
|
247
|
+
* being this one if the socket drops mid-turn.
|
|
248
|
+
*/
|
|
249
|
+
chatTurnSession = null;
|
|
250
|
+
/**
|
|
251
|
+
* Turns still executing on a previous connection's runner that THIS
|
|
252
|
+
* connection reattached to via `resume_chat`, keyed by thread id. Client
|
|
253
|
+
* frames for them (`tool_result`, approvals, `stop`) are forwarded to the
|
|
254
|
+
* executing runner through the session's hooks.
|
|
255
|
+
*/
|
|
256
|
+
adoptedSessions = new Map();
|
|
257
|
+
/**
|
|
258
|
+
* This connection's identity as a chat-turn delivery target. A stable
|
|
259
|
+
* object so `detach(target)` only clears the session's attachment when it
|
|
260
|
+
* still points at THIS connection — never a newer one that reattached.
|
|
261
|
+
*/
|
|
262
|
+
chatDeliveryTarget = {
|
|
263
|
+
deliver: (message) => this.sendToSocket(message)
|
|
264
|
+
};
|
|
265
|
+
logError(context, error) {
|
|
266
|
+
log.error(context, formatSanitizedError(error));
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* Hooks a resilient chat-turn session carries so a LATER connection that
|
|
270
|
+
* reattaches can route the client's `tool_result` / approvals / `stop`
|
|
271
|
+
* back to this runner — the one whose bridges own the pending waiters.
|
|
272
|
+
*/
|
|
273
|
+
buildChatTurnHooks() {
|
|
274
|
+
return {
|
|
275
|
+
resolveToolResult: (toolCallId, payload) => this.toolBridge.resolveResult(toolCallId, payload),
|
|
276
|
+
resolveApproval: (approvalId, payload) => this.approvalBridge.resolveResult(approvalId, payload),
|
|
277
|
+
cancelPendingCalls: (threadId) => {
|
|
278
|
+
this.toolBridge.cancelScope(threadId);
|
|
279
|
+
this.approvalBridge.cancelScope(threadId);
|
|
280
|
+
}
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
/** Abort every RPC still waiting on a provider. Idempotent. */
|
|
284
|
+
cancelRpcCalls() {
|
|
285
|
+
for (const abort of this.rpcAborts)
|
|
286
|
+
abort.abort();
|
|
287
|
+
this.rpcAborts.clear();
|
|
288
|
+
}
|
|
289
|
+
/**
|
|
290
|
+
* Put a controller in {@link rpcAborts} so {@link cancelRpcCalls} — a `stop`
|
|
291
|
+
* command or a dropped socket — reaches the call it belongs to, and hand
|
|
292
|
+
* back the deregistration the caller runs when the call settles.
|
|
293
|
+
*/
|
|
294
|
+
registerAbort(controller) {
|
|
295
|
+
this.rpcAborts.add(controller);
|
|
296
|
+
return () => {
|
|
297
|
+
this.rpcAborts.delete(controller);
|
|
298
|
+
};
|
|
299
|
+
}
|
|
300
|
+
sendDetached(message) {
|
|
301
|
+
void this.sendMessage(message).catch((err) => {
|
|
302
|
+
this.logError("detached websocket send failed", err);
|
|
303
|
+
});
|
|
304
|
+
}
|
|
305
|
+
requireUserId() {
|
|
306
|
+
if (this.userId === null) {
|
|
307
|
+
throw new Error("WebSocketClientSession has no user id: connect() has not run");
|
|
308
|
+
}
|
|
309
|
+
return this.userId;
|
|
310
|
+
}
|
|
311
|
+
constructor(options) {
|
|
312
|
+
this.userId = options.userId ?? null;
|
|
313
|
+
this.authToken = options.authToken ?? null;
|
|
314
|
+
this.appSession = options.appSession ?? null;
|
|
315
|
+
this.defaultModel = options.defaultModel ?? "gpt-oss:20b";
|
|
316
|
+
this.defaultProvider = options.defaultProvider ?? "ollama";
|
|
317
|
+
this.resolveExecutor = options.resolveExecutor;
|
|
318
|
+
this.resolveNodeType = options.resolveNodeType;
|
|
319
|
+
this.resolveProvider = options.resolveProvider;
|
|
320
|
+
this.workspaceResolver = options.workspaceResolver;
|
|
321
|
+
this.getNodeMetadata = options.getNodeMetadata;
|
|
322
|
+
this.validateNode = options.validateNode;
|
|
323
|
+
this.nodeRegistry = options.nodeRegistry;
|
|
324
|
+
this.pythonBridge = options.pythonBridge;
|
|
325
|
+
this.frontendRendererRegistry = options.frontendRendererRegistry;
|
|
326
|
+
this.getSystemStats = options.getSystemStats ?? createSystemStatsSampler();
|
|
327
|
+
this.systemStatsEnabled =
|
|
328
|
+
options.systemStatsEnabled ?? systemStatsBroadcastEnabled();
|
|
329
|
+
this.inference = new DirectInferenceHandler(this, {
|
|
330
|
+
defaults: { provider: this.defaultProvider, model: this.defaultModel },
|
|
331
|
+
currentRequestSeq: () => this.chat.currentRequestSeq,
|
|
332
|
+
registerAbort: (controller) => this.registerAbort(controller)
|
|
333
|
+
});
|
|
334
|
+
this.jobs = new JobExecutionManager(this, {
|
|
335
|
+
beforeRunJob: options.beforeRunJob,
|
|
336
|
+
getMaxConcurrentJobs: () => this.getMaxConcurrentJobs(),
|
|
337
|
+
getMaxConcurrentRunsPerWorkflow: () => this.getMaxConcurrentRunsPerWorkflow(),
|
|
338
|
+
defaultMaxConcurrentJobs: WebSocketClientSession.DEFAULT_MAX_CONCURRENT_JOBS,
|
|
339
|
+
defaultMaxConcurrentRunsPerWorkflow: WebSocketClientSession.DEFAULT_MAX_CONCURRENT_RUNS_PER_WORKFLOW,
|
|
340
|
+
sendToSocket: (message) => this.sendToSocket(message),
|
|
341
|
+
isSocketConnected: () => this.isRendererConnected(),
|
|
342
|
+
defaults: {
|
|
343
|
+
provider: this.defaultProvider,
|
|
344
|
+
model: this.defaultModel
|
|
345
|
+
}
|
|
346
|
+
});
|
|
347
|
+
this.chat = new ChatTurnHandler(this, {
|
|
348
|
+
// A chat-driven workflow run shares the connection's concurrency
|
|
349
|
+
// accounting, so it is registered and released here rather than in a
|
|
350
|
+
// map of chat's own.
|
|
351
|
+
jobs: {
|
|
352
|
+
registerJob: (jobId, active) => this.jobs.registerJob(jobId, active),
|
|
353
|
+
dropJob: (jobId) => this.jobs.dropJob(jobId),
|
|
354
|
+
releaseJob: (jobId) => this.jobs.releaseJob(jobId),
|
|
355
|
+
handleNodeProviderCost: (active, outbound) => this.jobs._handleNodeProviderCost(active, outbound),
|
|
356
|
+
runMeasuredCost: (active) => this.jobs.runMeasuredCost(active)
|
|
357
|
+
},
|
|
358
|
+
toolBridge: this.toolBridge,
|
|
359
|
+
approvalBridge: this.approvalBridge,
|
|
360
|
+
clientTools: () => this.clientToolsManifest,
|
|
361
|
+
authToken: () => this.authToken,
|
|
362
|
+
beforeRunJob: options.beforeRunJob,
|
|
363
|
+
defaults: {
|
|
364
|
+
provider: this.defaultProvider,
|
|
365
|
+
model: this.defaultModel
|
|
366
|
+
},
|
|
367
|
+
hydrateGraph: (graph) => this.jobs.hydrateGraph(graph),
|
|
368
|
+
configuredProviders: (userId) => this.configuredProvidersCache.get(userId),
|
|
369
|
+
entityRefResolver,
|
|
370
|
+
resolveEntityReferenceImages,
|
|
371
|
+
resolveSourceImageBytes: (data, mediaGeneration, userId) => this.resolveSourceImageBytes(data, mediaGeneration, userId),
|
|
372
|
+
resolveReferenceMediaBytes: (data, mediaGeneration, userId) => this.resolveReferenceMediaBytes(data, mediaGeneration, userId)
|
|
373
|
+
});
|
|
374
|
+
this.commands = new CommandRouter({
|
|
375
|
+
session: this,
|
|
376
|
+
jobs: this.jobs,
|
|
377
|
+
chat: this.chat,
|
|
378
|
+
inference: this.inference,
|
|
379
|
+
// What a command does to the connection itself: the socket, the wire
|
|
380
|
+
// mode, the RPC abort set, the tool bridges, and the chat-turn session
|
|
381
|
+
// bookkeeping the frame router reads. All host state, reached through
|
|
382
|
+
// this adapter rather than owned by the router.
|
|
383
|
+
host: {
|
|
384
|
+
sendToSocket: (message) => this.sendToSocket(message),
|
|
385
|
+
setMode: (mode) => {
|
|
386
|
+
this.mode = mode;
|
|
387
|
+
},
|
|
388
|
+
clearModels: () => this.clearModels(),
|
|
389
|
+
cancelRpcCalls: () => this.cancelRpcCalls(),
|
|
390
|
+
cancelToolScope: (scope) => {
|
|
391
|
+
this.toolBridge.cancelScope(scope);
|
|
392
|
+
this.approvalBridge.cancelScope(scope);
|
|
393
|
+
},
|
|
394
|
+
chatTurnHooks: () => this.buildChatTurnHooks(),
|
|
395
|
+
chatDeliveryTarget: this.chatDeliveryTarget,
|
|
396
|
+
getChatTurnSession: () => this.chatTurnSession,
|
|
397
|
+
setChatTurnSession: (session) => {
|
|
398
|
+
this.chatTurnSession = session;
|
|
399
|
+
},
|
|
400
|
+
adoptSession: (threadId, session) => {
|
|
401
|
+
this.adoptedSessions.set(threadId, session);
|
|
402
|
+
},
|
|
403
|
+
forgetAdoptedSession: (threadId) => {
|
|
404
|
+
this.adoptedSessions.delete(threadId);
|
|
405
|
+
},
|
|
406
|
+
closeForDrain: () => this.onDraining()
|
|
407
|
+
},
|
|
408
|
+
defaults: {
|
|
409
|
+
provider: this.defaultProvider,
|
|
410
|
+
model: this.defaultModel
|
|
411
|
+
},
|
|
412
|
+
apiOptions: options.apiOptions,
|
|
413
|
+
getPythonBridgeReady: options.getPythonBridgeReady
|
|
414
|
+
});
|
|
415
|
+
}
|
|
416
|
+
isRendererConnected() {
|
|
417
|
+
return (this.websocket !== null &&
|
|
418
|
+
this.websocket.clientState !== "disconnected" &&
|
|
419
|
+
this.websocket.applicationState !== "disconnected");
|
|
420
|
+
}
|
|
421
|
+
isRendererReady() {
|
|
422
|
+
return this.clientToolsManifestReady;
|
|
423
|
+
}
|
|
424
|
+
getRendererToolManifest() {
|
|
425
|
+
return Object.fromEntries(Object.entries(this.clientToolsManifest).map(([name, manifest]) => [
|
|
426
|
+
name,
|
|
427
|
+
{ ...manifest }
|
|
428
|
+
]));
|
|
429
|
+
}
|
|
430
|
+
/** Send a connection-level frontend tool call and await its renderer result. */
|
|
431
|
+
async executeRendererTool(rendererId, call, timeoutMs = 300_000) {
|
|
432
|
+
if (this.frontendRendererId !== rendererId || !this.isRendererConnected()) {
|
|
433
|
+
throw new Error(`Renderer "${rendererId}" is not connected`);
|
|
434
|
+
}
|
|
435
|
+
if (!this.isRendererReady()) {
|
|
436
|
+
throw new Error(`Renderer "${rendererId}" is not ready`);
|
|
437
|
+
}
|
|
438
|
+
if (!this.clientToolsManifest[call.name]) {
|
|
439
|
+
throw new Error(`Tool "${call.name}" is not available in renderer`);
|
|
440
|
+
}
|
|
441
|
+
const resultPromise = this.rendererToolBridge.createWaiter(call.tool_call_id, timeoutMs);
|
|
442
|
+
try {
|
|
443
|
+
await this.sendToSocket({
|
|
444
|
+
type: "renderer_tool_call",
|
|
445
|
+
renderer_id: rendererId,
|
|
446
|
+
tool_call_id: call.tool_call_id,
|
|
447
|
+
name: call.name,
|
|
448
|
+
args: call.args
|
|
449
|
+
});
|
|
450
|
+
if (!this.isRendererConnected()) {
|
|
451
|
+
throw new Error(`Renderer "${rendererId}" disconnected during tool call`);
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
catch (error) {
|
|
455
|
+
this.rendererToolBridge.rejectResult(call.tool_call_id, error instanceof Error ? error : new Error(String(error)));
|
|
456
|
+
}
|
|
457
|
+
const result = await resultPromise;
|
|
458
|
+
if (result.ok !== true) {
|
|
459
|
+
throw new Error(isString(result.error) ? result.error : "Renderer tool failed");
|
|
460
|
+
}
|
|
461
|
+
return {
|
|
462
|
+
renderer_id: rendererId,
|
|
463
|
+
tool_call_id: call.tool_call_id,
|
|
464
|
+
ok: true,
|
|
465
|
+
result: result.result ?? result.content
|
|
466
|
+
};
|
|
467
|
+
}
|
|
468
|
+
async connect(websocket, userId, authToken) {
|
|
469
|
+
if (userId)
|
|
470
|
+
this.userId = userId;
|
|
471
|
+
if (authToken)
|
|
472
|
+
this.authToken = authToken;
|
|
473
|
+
this.userId = this.userId ?? "1";
|
|
474
|
+
await websocket.accept();
|
|
475
|
+
this.websocket = websocket;
|
|
476
|
+
if (this.frontendRendererRegistry) {
|
|
477
|
+
this.frontendRendererId = this.frontendRendererRegistry.register(this.userId, this);
|
|
478
|
+
await this.sendToSocket({
|
|
479
|
+
type: "renderer_registered",
|
|
480
|
+
renderer_id: this.frontendRendererId
|
|
481
|
+
});
|
|
482
|
+
}
|
|
483
|
+
log.info("Client connected", { userId: this.userId });
|
|
484
|
+
this.startHeartbeat();
|
|
485
|
+
this.startStatsBroadcast();
|
|
486
|
+
this.registerObserver();
|
|
487
|
+
// A connection accepted just before the drain took effect gets the
|
|
488
|
+
// callback immediately, so it closes like any older one.
|
|
489
|
+
this.drainUnsubscribe = onDrain(() => this.onDraining());
|
|
490
|
+
}
|
|
491
|
+
async disconnect() {
|
|
492
|
+
log.info("Client disconnected");
|
|
493
|
+
this.drainUnsubscribe?.();
|
|
494
|
+
this.drainUnsubscribe = null;
|
|
495
|
+
this.stopDrainTimer();
|
|
496
|
+
this.stopHeartbeat();
|
|
497
|
+
this.stopStatsBroadcast();
|
|
498
|
+
this.unregisterObserver();
|
|
499
|
+
if (this.frontendRendererId) {
|
|
500
|
+
this.frontendRendererRegistry?.unregister(this.frontendRendererId);
|
|
501
|
+
this.frontendRendererId = null;
|
|
502
|
+
}
|
|
503
|
+
this.rendererToolBridge.cancelAll();
|
|
504
|
+
// An RPC has no session to detach into and no client left to answer, so
|
|
505
|
+
// it is always cancelled — unlike a resilient chat turn below.
|
|
506
|
+
this.cancelRpcCalls();
|
|
507
|
+
// A resilient chat turn survives the socket: detach it (frames keep
|
|
508
|
+
// buffering in the session for replay) instead of aborting. The session's
|
|
509
|
+
// execution budget bounds its work while detached. Its pending
|
|
510
|
+
// client tool calls stay alive too — replay re-delivers the `tool_call`
|
|
511
|
+
// frames, so a reconnecting client can still answer them. Everything
|
|
512
|
+
// else (a sessionless `inference` turn, other pending calls) is cancelled
|
|
513
|
+
// as before: nobody is left to receive its output.
|
|
514
|
+
const detachedThreadId = this.chatTurnSession?.status === "running"
|
|
515
|
+
? this.chatTurnSession.threadId
|
|
516
|
+
: null;
|
|
517
|
+
if (detachedThreadId) {
|
|
518
|
+
this.chatTurnSession?.detach(this.chatDeliveryTarget);
|
|
519
|
+
this.toolBridge.cancelAllExcept(detachedThreadId);
|
|
520
|
+
this.approvalBridge.cancelAllExcept(detachedThreadId);
|
|
521
|
+
}
|
|
522
|
+
else {
|
|
523
|
+
this.toolBridge.cancelAll();
|
|
524
|
+
this.approvalBridge.cancelAll();
|
|
525
|
+
this.chat.cancel();
|
|
526
|
+
}
|
|
527
|
+
for (const session of this.adoptedSessions.values()) {
|
|
528
|
+
session.detach(this.chatDeliveryTarget);
|
|
529
|
+
}
|
|
530
|
+
this.adoptedSessions.clear();
|
|
531
|
+
await this.jobs.cancelAll();
|
|
532
|
+
if (this.websocket) {
|
|
533
|
+
try {
|
|
534
|
+
await this.websocket.close();
|
|
535
|
+
}
|
|
536
|
+
catch (error) {
|
|
537
|
+
this.logError("disconnect websocket.close failed", error);
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
this.websocket = null;
|
|
541
|
+
}
|
|
542
|
+
/** A chat turn or a workflow run this connection is still driving. */
|
|
543
|
+
hasRunningWork() {
|
|
544
|
+
if (this.chatTurnSession?.status === "running")
|
|
545
|
+
return true;
|
|
546
|
+
for (const session of this.adoptedSessions.values()) {
|
|
547
|
+
if (session.status === "running")
|
|
548
|
+
return true;
|
|
549
|
+
}
|
|
550
|
+
return this.jobs.activeJobIds().length > 0;
|
|
551
|
+
}
|
|
552
|
+
/**
|
|
553
|
+
* The process is draining. A connection with nothing in flight is closed at
|
|
554
|
+
* once so the client's own reconnect lands on a machine that is staying; one
|
|
555
|
+
* driving a turn or a run keeps it and closes when that settles, because
|
|
556
|
+
* closing here would only move the work's output nowhere.
|
|
557
|
+
*/
|
|
558
|
+
onDraining() {
|
|
559
|
+
if (!this.hasRunningWork()) {
|
|
560
|
+
void this.closeForDrain();
|
|
561
|
+
return;
|
|
562
|
+
}
|
|
563
|
+
if (this.drainTimer)
|
|
564
|
+
return;
|
|
565
|
+
this.drainTimer = setInterval(() => {
|
|
566
|
+
if (this.hasRunningWork())
|
|
567
|
+
return;
|
|
568
|
+
void this.closeForDrain();
|
|
569
|
+
}, DRAIN_POLL_MS);
|
|
570
|
+
this.drainTimer.unref?.();
|
|
571
|
+
}
|
|
572
|
+
/**
|
|
573
|
+
* Close this socket with 1012. The client reconnects on its own and the
|
|
574
|
+
* proxy sends it to a machine whose health check still passes.
|
|
575
|
+
*/
|
|
576
|
+
async closeForDrain() {
|
|
577
|
+
this.stopDrainTimer();
|
|
578
|
+
const websocket = this.websocket;
|
|
579
|
+
if (!websocket)
|
|
580
|
+
return;
|
|
581
|
+
try {
|
|
582
|
+
await websocket.close(DRAIN_CLOSE_CODE, "Server draining");
|
|
583
|
+
}
|
|
584
|
+
catch (error) {
|
|
585
|
+
this.logError("drain close failed", error);
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
stopDrainTimer() {
|
|
589
|
+
if (this.drainTimer) {
|
|
590
|
+
clearInterval(this.drainTimer);
|
|
591
|
+
this.drainTimer = null;
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
serializeForJson(value) {
|
|
595
|
+
if (value instanceof Uint8Array)
|
|
596
|
+
return Array.from(value);
|
|
597
|
+
if (value instanceof Date)
|
|
598
|
+
return value.toISOString();
|
|
599
|
+
if (Array.isArray(value))
|
|
600
|
+
return value.map((v) => this.serializeForJson(v));
|
|
601
|
+
if (isObjectLike(value)) {
|
|
602
|
+
const out = {};
|
|
603
|
+
for (const [k, v] of Object.entries(value)) {
|
|
604
|
+
out[k] = this.serializeForJson(v);
|
|
605
|
+
}
|
|
606
|
+
return out;
|
|
607
|
+
}
|
|
608
|
+
// SAFETY: bytes, dates, arrays and objects are handled above; what is left
|
|
609
|
+
// is a JSON scalar.
|
|
610
|
+
return value;
|
|
611
|
+
}
|
|
612
|
+
send(message) {
|
|
613
|
+
return this.sendMessage(message);
|
|
614
|
+
}
|
|
615
|
+
async sendMessage(message) {
|
|
616
|
+
// Frames belonging to this connection's resilient chat turn go through the
|
|
617
|
+
// session: seq-stamped, buffered for replay, delivered to the attached
|
|
618
|
+
// connection (possibly a later one than this).
|
|
619
|
+
const session = this.chatTurnSession;
|
|
620
|
+
if (session &&
|
|
621
|
+
session.status === "running" &&
|
|
622
|
+
isString(message.thread_id) &&
|
|
623
|
+
message.thread_id === session.threadId) {
|
|
624
|
+
session.emit(message);
|
|
625
|
+
return;
|
|
626
|
+
}
|
|
627
|
+
// Same for a resilient run's frames — including its terminal job_update,
|
|
628
|
+
// which is the one frame a reconnecting client most needs replayed.
|
|
629
|
+
// Adopted sessions are checked too so a `cancel_job` this connection
|
|
630
|
+
// issued against a run owned by another connection still buffers its
|
|
631
|
+
// acknowledgement into that run's session rather than only this socket.
|
|
632
|
+
const jobSession = this.jobs.resolveJobSession(message.job_id);
|
|
633
|
+
if (jobSession && jobSession.status === "running") {
|
|
634
|
+
jobSession.emit(message);
|
|
635
|
+
return;
|
|
636
|
+
}
|
|
637
|
+
await this.sendToSocket(message);
|
|
638
|
+
}
|
|
639
|
+
async sendToSocket(message) {
|
|
640
|
+
if (!this.websocket)
|
|
641
|
+
return;
|
|
642
|
+
if (this.websocket.clientState === "disconnected" ||
|
|
643
|
+
this.websocket.applicationState === "disconnected") {
|
|
644
|
+
return;
|
|
645
|
+
}
|
|
646
|
+
assertValidOutboundMessage(message);
|
|
647
|
+
// Resolve storage keys in content to browser-accessible URLs before
|
|
648
|
+
// sending over the wire. This keeps DB storage URL-agnostic while
|
|
649
|
+
// delivering ready-to-use URLs to the client.
|
|
650
|
+
if (Array.isArray(message.content)) {
|
|
651
|
+
message = {
|
|
652
|
+
...message,
|
|
653
|
+
content: await resolveContentUrls(message.content, message.user_id ?? this.userId ?? undefined)
|
|
654
|
+
};
|
|
655
|
+
}
|
|
656
|
+
// In-process audio/CV chunks carry samples as a native Float32Array,
|
|
657
|
+
// which neither msgpack nor JSON represents. Encode them to base64
|
|
658
|
+
// f32le here — the one and only conversion on the path to the client.
|
|
659
|
+
message = encodeNativeAudioChunks(message);
|
|
660
|
+
// Snapshot the mode ONCE for this frame. Reading this.mode again after the
|
|
661
|
+
// send-lock await would let a set_mode that lands mid-queue transmit a
|
|
662
|
+
// payload prepared for the other mode (e.g. a binary payload with raw
|
|
663
|
+
// Uint8Arrays JSON.stringify'd into index-keyed garbage).
|
|
664
|
+
const mode = this.mode;
|
|
665
|
+
const payload = mode === "text"
|
|
666
|
+
? this.serializeForJson(message)
|
|
667
|
+
: message;
|
|
668
|
+
const prev = this.sendLock;
|
|
669
|
+
let release;
|
|
670
|
+
this.sendLock = new Promise((resolve) => {
|
|
671
|
+
release = resolve;
|
|
672
|
+
});
|
|
673
|
+
await prev;
|
|
674
|
+
try {
|
|
675
|
+
const websocket = this.websocket;
|
|
676
|
+
if (!websocket ||
|
|
677
|
+
websocket.clientState === "disconnected" ||
|
|
678
|
+
websocket.applicationState === "disconnected") {
|
|
679
|
+
return;
|
|
680
|
+
}
|
|
681
|
+
if (mode === "binary") {
|
|
682
|
+
await websocket.sendBytes(packWebSocketMessage(payload));
|
|
683
|
+
}
|
|
684
|
+
else {
|
|
685
|
+
await websocket.sendText(JSON.stringify(payload));
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
finally {
|
|
689
|
+
release();
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
async receiveMessage() {
|
|
693
|
+
if (!this.websocket) {
|
|
694
|
+
throw new Error("WebSocket is not connected");
|
|
695
|
+
}
|
|
696
|
+
const message = await this.websocket.receive();
|
|
697
|
+
if (message.type === "websocket.disconnect")
|
|
698
|
+
return null;
|
|
699
|
+
if (message.bytes) {
|
|
700
|
+
const maxBytes = getMaxWsMessageBytes();
|
|
701
|
+
if (message.bytes.length > maxBytes) {
|
|
702
|
+
throw new Error(`Incoming WebSocket message exceeds maximum size: ` +
|
|
703
|
+
`${message.bytes.length} > ${maxBytes} bytes ` +
|
|
704
|
+
`(set NODETOOL_WS_MAX_MESSAGE_BYTES to raise the limit)`);
|
|
705
|
+
}
|
|
706
|
+
return unpackWebSocketMessage(message.bytes);
|
|
707
|
+
}
|
|
708
|
+
if (message.text) {
|
|
709
|
+
const maxBytes = getMaxWsMessageBytes();
|
|
710
|
+
const textBytes = Buffer.byteLength(message.text, "utf8");
|
|
711
|
+
if (textBytes > maxBytes) {
|
|
712
|
+
throw new Error(`Incoming WebSocket message exceeds maximum size: ` +
|
|
713
|
+
`${textBytes} > ${maxBytes} bytes ` +
|
|
714
|
+
`(set NODETOOL_WS_MAX_MESSAGE_BYTES to raise the limit)`);
|
|
715
|
+
}
|
|
716
|
+
return JSON.parse(message.text);
|
|
717
|
+
}
|
|
718
|
+
return null;
|
|
719
|
+
}
|
|
720
|
+
/** Default cap when `MAX_CONCURRENT_JOBS` is unset/invalid. */
|
|
721
|
+
static DEFAULT_MAX_CONCURRENT_JOBS = 4;
|
|
722
|
+
/** Default per-workflow cap when `MAX_CONCURRENT_RUNS_PER_WORKFLOW` is unset/invalid. */
|
|
723
|
+
static DEFAULT_MAX_CONCURRENT_RUNS_PER_WORKFLOW = 4;
|
|
724
|
+
/** How long a resolved concurrency-setting value is reused before re-reading. */
|
|
725
|
+
static MAX_CONCURRENT_JOBS_TTL_MS = 5000;
|
|
726
|
+
maxConcurrentJobsCache = null;
|
|
727
|
+
maxRunsPerWorkflowCache = null;
|
|
728
|
+
/**
|
|
729
|
+
* Resolve the per-client concurrency cap from settings (>= 1), cached for a
|
|
730
|
+
* few seconds so back-to-back run_job/drainQueue calls don't hit the settings
|
|
731
|
+
* store every time. The setting changes rarely, so a short TTL is fine.
|
|
732
|
+
*/
|
|
733
|
+
async getMaxConcurrentJobs() {
|
|
734
|
+
const cached = this.maxConcurrentJobsCache;
|
|
735
|
+
const value = await this.resolvePositiveIntSetting("MAX_CONCURRENT_JOBS", WebSocketClientSession.DEFAULT_MAX_CONCURRENT_JOBS, cached);
|
|
736
|
+
this.maxConcurrentJobsCache = value;
|
|
737
|
+
return value.value;
|
|
738
|
+
}
|
|
739
|
+
/**
|
|
740
|
+
* Resolve the per-workflow concurrency cap (>= 1) for runs that opt into
|
|
741
|
+
* concurrency. When this many runs of the same workflow are already in
|
|
742
|
+
* flight, further opted-in runs queue. Cached like {@link getMaxConcurrentJobs}.
|
|
743
|
+
*/
|
|
744
|
+
async getMaxConcurrentRunsPerWorkflow() {
|
|
745
|
+
const cached = this.maxRunsPerWorkflowCache;
|
|
746
|
+
const value = await this.resolvePositiveIntSetting("MAX_CONCURRENT_RUNS_PER_WORKFLOW", WebSocketClientSession.DEFAULT_MAX_CONCURRENT_RUNS_PER_WORKFLOW, cached);
|
|
747
|
+
this.maxRunsPerWorkflowCache = value;
|
|
748
|
+
return value.value;
|
|
749
|
+
}
|
|
750
|
+
/**
|
|
751
|
+
* Read a positive-integer setting, reusing the cached value while it's still
|
|
752
|
+
* within the TTL. Falls back to `fallback` when the setting is unset/invalid
|
|
753
|
+
* or the settings store is unavailable (e.g. DB not initialized) rather than
|
|
754
|
+
* blocking the run, matching the runner's other best-effort DB access.
|
|
755
|
+
*/
|
|
756
|
+
async resolvePositiveIntSetting(key, fallback, cached) {
|
|
757
|
+
const now = Date.now();
|
|
758
|
+
if (cached &&
|
|
759
|
+
now - cached.at < WebSocketClientSession.MAX_CONCURRENT_JOBS_TTL_MS) {
|
|
760
|
+
return cached;
|
|
761
|
+
}
|
|
762
|
+
let raw = null;
|
|
763
|
+
try {
|
|
764
|
+
raw = await getSetting(key);
|
|
765
|
+
}
|
|
766
|
+
catch {
|
|
767
|
+
// Settings store unavailable — fall back to the default.
|
|
768
|
+
}
|
|
769
|
+
const parsed = raw ? Number.parseInt(raw, 10) : NaN;
|
|
770
|
+
const value = Number.isFinite(parsed) && parsed > 0 ? parsed : fallback;
|
|
771
|
+
return { value, at: now };
|
|
772
|
+
}
|
|
773
|
+
async clearModels() {
|
|
774
|
+
return {
|
|
775
|
+
message: "Model clearing is managed by provider implementations in TS runtime"
|
|
776
|
+
};
|
|
777
|
+
}
|
|
778
|
+
/**
|
|
779
|
+
* Bytes behind one media content block, whatever form the client used to
|
|
780
|
+
* name them: a stored `asset_id`, an `asset://<id>.<ext>` uri written by the
|
|
781
|
+
* `@`-mention picker, an inline `data:` uri, an http(s) url, or a bare
|
|
782
|
+
* base64 `data` field. Returns null when none of them resolves.
|
|
783
|
+
*/
|
|
784
|
+
async resolveMediaRefBytes(ref, userId) {
|
|
785
|
+
const assetId = isString(ref.asset_id) ? ref.asset_id : null;
|
|
786
|
+
if (assetId) {
|
|
787
|
+
const bytes = await this.loadAssetBytes(userId, assetId);
|
|
788
|
+
if (bytes && bytes.length > 0)
|
|
789
|
+
return bytes;
|
|
790
|
+
}
|
|
791
|
+
const uri = isString(ref.uri) ? ref.uri : null;
|
|
792
|
+
if (uri) {
|
|
793
|
+
if (uri.startsWith("asset://")) {
|
|
794
|
+
// `@`-mentioned or library-dragged asset: `asset://<id>.<ext>`.
|
|
795
|
+
const withoutScheme = uri.slice("asset://".length);
|
|
796
|
+
const dotIdx = withoutScheme.lastIndexOf(".");
|
|
797
|
+
const mentionedId = dotIdx > -1 ? withoutScheme.slice(0, dotIdx) : withoutScheme;
|
|
798
|
+
const bytes = await this.loadAssetBytes(userId, mentionedId);
|
|
799
|
+
if (bytes && bytes.length > 0)
|
|
800
|
+
return bytes;
|
|
801
|
+
}
|
|
802
|
+
else if (uri.startsWith("data:")) {
|
|
803
|
+
const commaIdx = uri.indexOf(",");
|
|
804
|
+
if (commaIdx > -1) {
|
|
805
|
+
const b64 = uri.slice(commaIdx + 1);
|
|
806
|
+
try {
|
|
807
|
+
return new Uint8Array(Buffer.from(b64, "base64"));
|
|
808
|
+
}
|
|
809
|
+
catch {
|
|
810
|
+
/* fall through to the `data` field below */
|
|
811
|
+
}
|
|
812
|
+
}
|
|
813
|
+
}
|
|
814
|
+
else if (uri.startsWith("http://") || uri.startsWith("https://")) {
|
|
815
|
+
// A chat client picked this uri, so the media-ref egress policy
|
|
816
|
+
// decides — including on every redirect hop, which the predicate
|
|
817
|
+
// this replaced never saw.
|
|
818
|
+
try {
|
|
819
|
+
const resp = await fetchExternalMedia(uri);
|
|
820
|
+
if (resp.ok) {
|
|
821
|
+
return new Uint8Array(await resp.arrayBuffer());
|
|
822
|
+
}
|
|
823
|
+
}
|
|
824
|
+
catch (err) {
|
|
825
|
+
log.warn("resolveMediaRefBytes: fetch failed", {
|
|
826
|
+
uri,
|
|
827
|
+
error: err instanceof Error ? err.message : String(err)
|
|
828
|
+
});
|
|
829
|
+
}
|
|
830
|
+
}
|
|
831
|
+
}
|
|
832
|
+
const data64 = isString(ref.data) ? ref.data : null;
|
|
833
|
+
if (data64) {
|
|
834
|
+
try {
|
|
835
|
+
return new Uint8Array(Buffer.from(data64, "base64"));
|
|
836
|
+
}
|
|
837
|
+
catch {
|
|
838
|
+
/* ignore */
|
|
839
|
+
}
|
|
840
|
+
}
|
|
841
|
+
return null;
|
|
842
|
+
}
|
|
843
|
+
/** One asset's bytes, or null when it is gone or unreadable. */
|
|
844
|
+
async loadAssetBytes(userId, assetId) {
|
|
845
|
+
if (!assetId)
|
|
846
|
+
return null;
|
|
847
|
+
try {
|
|
848
|
+
const asset = await Asset.find(userId, assetId);
|
|
849
|
+
if (!asset)
|
|
850
|
+
return null;
|
|
851
|
+
return await retrieveAssetBytes(getAssetAdapter(), userId, assetId, asset.content_type);
|
|
852
|
+
}
|
|
853
|
+
catch (err) {
|
|
854
|
+
log.warn("loadAssetBytes: asset load failed", {
|
|
855
|
+
assetId,
|
|
856
|
+
error: err instanceof Error ? err.message : String(err)
|
|
857
|
+
});
|
|
858
|
+
return null;
|
|
859
|
+
}
|
|
860
|
+
}
|
|
861
|
+
/** The inner ref record of every `image_url` / `video` block on a message. */
|
|
862
|
+
mediaRefsOnMessage(data, blockType) {
|
|
863
|
+
const content = data.content;
|
|
864
|
+
if (!Array.isArray(content))
|
|
865
|
+
return [];
|
|
866
|
+
const field = blockType === "image_url" ? "image" : "video";
|
|
867
|
+
const refs = [];
|
|
868
|
+
for (const c of content) {
|
|
869
|
+
if (!isObjectLike(c))
|
|
870
|
+
continue;
|
|
871
|
+
const block = c;
|
|
872
|
+
if (block.type !== blockType)
|
|
873
|
+
continue;
|
|
874
|
+
const ref = block[field];
|
|
875
|
+
refs.push(isObjectLike(ref) ? ref : {});
|
|
876
|
+
}
|
|
877
|
+
return refs;
|
|
878
|
+
}
|
|
879
|
+
/**
|
|
880
|
+
* Resolve the source image bytes for image-edit / image-to-video calls.
|
|
881
|
+
* Searches in priority order:
|
|
882
|
+
* 1. `media_generation.source_asset_id` → load from Asset storage
|
|
883
|
+
* 2. The first `image_url` content block on the user message
|
|
884
|
+
* (supports asset_id, http(s) uri, and inline data:base64 payloads)
|
|
885
|
+
* Returns `null` when no usable source image can be found.
|
|
886
|
+
*/
|
|
887
|
+
async resolveSourceImageBytes(data, mediaGeneration, userId) {
|
|
888
|
+
const explicitId = isString(mediaGeneration.source_asset_id)
|
|
889
|
+
? mediaGeneration.source_asset_id
|
|
890
|
+
: null;
|
|
891
|
+
if (explicitId) {
|
|
892
|
+
const fromAsset = await this.loadAssetBytes(userId, explicitId);
|
|
893
|
+
if (fromAsset && fromAsset.length > 0)
|
|
894
|
+
return fromAsset;
|
|
895
|
+
}
|
|
896
|
+
for (const ref of this.mediaRefsOnMessage(data, "image_url")) {
|
|
897
|
+
const bytes = await this.resolveMediaRefBytes(ref, userId);
|
|
898
|
+
if (bytes && bytes.length > 0)
|
|
899
|
+
return bytes;
|
|
900
|
+
}
|
|
901
|
+
return null;
|
|
902
|
+
}
|
|
903
|
+
/**
|
|
904
|
+
* Every reference the user attached, for reference-to-video: *all* the
|
|
905
|
+
* image and video blocks on the message rather than the first one, because
|
|
906
|
+
* the whole point of the mode is that several references describe one shot
|
|
907
|
+
* (a character, a garment, a location). `source_asset_id` joins the images
|
|
908
|
+
* so a surface that names one explicitly still reaches the model. A block
|
|
909
|
+
* whose bytes do not resolve drops rather than failing the turn — the
|
|
910
|
+
* caller refuses only when nothing at all resolved.
|
|
911
|
+
*/
|
|
912
|
+
async resolveReferenceMediaBytes(data, mediaGeneration, userId) {
|
|
913
|
+
const collect = async (blockType) => {
|
|
914
|
+
const out = [];
|
|
915
|
+
for (const ref of this.mediaRefsOnMessage(data, blockType)) {
|
|
916
|
+
const bytes = await this.resolveMediaRefBytes(ref, userId);
|
|
917
|
+
if (bytes && bytes.length > 0)
|
|
918
|
+
out.push(bytes);
|
|
919
|
+
}
|
|
920
|
+
return out;
|
|
921
|
+
};
|
|
922
|
+
const images = await collect("image_url");
|
|
923
|
+
const videos = await collect("video");
|
|
924
|
+
const explicitId = isString(mediaGeneration.source_asset_id)
|
|
925
|
+
? mediaGeneration.source_asset_id
|
|
926
|
+
: null;
|
|
927
|
+
if (explicitId) {
|
|
928
|
+
const bytes = await this.loadAssetBytes(userId, explicitId);
|
|
929
|
+
if (bytes && bytes.length > 0)
|
|
930
|
+
images.unshift(bytes);
|
|
931
|
+
}
|
|
932
|
+
return { images, videos };
|
|
933
|
+
}
|
|
934
|
+
async handleCommand(command) {
|
|
935
|
+
return this.commands.handle(command.command, command.data ?? {}, command.request_id);
|
|
936
|
+
}
|
|
937
|
+
startHeartbeat() {
|
|
938
|
+
this.stopHeartbeat();
|
|
939
|
+
this.heartbeatTimer = setInterval(() => {
|
|
940
|
+
this.sendMessage({ type: "ping", ts: Date.now() / 1000 }).catch((err) => {
|
|
941
|
+
log.warn("Failed to send heartbeat ping", { error: String(err) });
|
|
942
|
+
});
|
|
943
|
+
}, 25_000);
|
|
944
|
+
}
|
|
945
|
+
stopHeartbeat() {
|
|
946
|
+
if (this.heartbeatTimer) {
|
|
947
|
+
clearInterval(this.heartbeatTimer);
|
|
948
|
+
this.heartbeatTimer = null;
|
|
949
|
+
}
|
|
950
|
+
}
|
|
951
|
+
startStatsBroadcast() {
|
|
952
|
+
this.stopStatsBroadcast();
|
|
953
|
+
if (!this.systemStatsEnabled) {
|
|
954
|
+
return;
|
|
955
|
+
}
|
|
956
|
+
const send = () => {
|
|
957
|
+
this.sendMessage({
|
|
958
|
+
type: "system_stats",
|
|
959
|
+
stats: this.getSystemStats()
|
|
960
|
+
}).catch((err) => {
|
|
961
|
+
log.warn("Failed to send system stats", { error: String(err) });
|
|
962
|
+
});
|
|
963
|
+
};
|
|
964
|
+
// Fire an initial sample ~1s after connect so the sampler has a delta to
|
|
965
|
+
// report — then keep emitting on a regular cadence.
|
|
966
|
+
this.statsPrimeTimer = setTimeout(send, 1000);
|
|
967
|
+
this.statsTimer = setInterval(send, 5_000);
|
|
968
|
+
}
|
|
969
|
+
stopStatsBroadcast() {
|
|
970
|
+
if (this.statsPrimeTimer) {
|
|
971
|
+
clearTimeout(this.statsPrimeTimer);
|
|
972
|
+
this.statsPrimeTimer = null;
|
|
973
|
+
}
|
|
974
|
+
if (this.statsTimer) {
|
|
975
|
+
clearInterval(this.statsTimer);
|
|
976
|
+
this.statsTimer = null;
|
|
977
|
+
}
|
|
978
|
+
}
|
|
979
|
+
registerObserver() {
|
|
980
|
+
if (this.observerRegistered)
|
|
981
|
+
return;
|
|
982
|
+
// Both feeds are scoped by `this.userId`, which for a deployed app's
|
|
983
|
+
// visitor is the *owner* — so subscribing would stream them the ids,
|
|
984
|
+
// etags and timestamps of every row that user touches, from any tab or
|
|
985
|
+
// agent, for as long as the page is open. The public page has no cache to
|
|
986
|
+
// invalidate anyway: it renders one release and runs it.
|
|
987
|
+
if (this.appSession)
|
|
988
|
+
return;
|
|
989
|
+
ModelObserver.subscribe(this.onModelChange);
|
|
990
|
+
resourceEvents.on("change", this.onResourceEvent);
|
|
991
|
+
this.observerRegistered = true;
|
|
992
|
+
}
|
|
993
|
+
unregisterObserver() {
|
|
994
|
+
if (!this.observerRegistered)
|
|
995
|
+
return;
|
|
996
|
+
ModelObserver.unsubscribe(this.onModelChange);
|
|
997
|
+
resourceEvents.off("change", this.onResourceEvent);
|
|
998
|
+
this.observerRegistered = false;
|
|
999
|
+
}
|
|
1000
|
+
onModelChange = (instance, event, meta) => {
|
|
1001
|
+
if (!this.websocket)
|
|
1002
|
+
return;
|
|
1003
|
+
// Only forward changes for models the connected user owns. Models without
|
|
1004
|
+
// a `user_id` (runtime-internal types) are forwarded to every connection.
|
|
1005
|
+
const ownerId = instance.user_id;
|
|
1006
|
+
if (ownerId && this.userId && ownerId !== this.userId)
|
|
1007
|
+
return;
|
|
1008
|
+
const resource = {
|
|
1009
|
+
id: instance.partitionValue(),
|
|
1010
|
+
etag: instance.getEtag()
|
|
1011
|
+
};
|
|
1012
|
+
// Include scope fields for resource types whose cache is keyed on a
|
|
1013
|
+
// parent id (Message → thread_id, WorkflowVersion → workflow_id, etc.).
|
|
1014
|
+
// Frontend handlers use these to narrow invalidation. `updated_at` rides
|
|
1015
|
+
// along as the row's concurrency token: an open editor compares it against
|
|
1016
|
+
// the token it last saved with to tell its own write apart from one made
|
|
1017
|
+
// outside the browser (agent, CLI, another tab).
|
|
1018
|
+
const data = instance;
|
|
1019
|
+
for (const field of [
|
|
1020
|
+
"workflow_id",
|
|
1021
|
+
"thread_id",
|
|
1022
|
+
"parent_id",
|
|
1023
|
+
"updated_at"
|
|
1024
|
+
]) {
|
|
1025
|
+
const value = data[field];
|
|
1026
|
+
if (isNonEmptyString(value)) {
|
|
1027
|
+
resource[field] = value;
|
|
1028
|
+
}
|
|
1029
|
+
}
|
|
1030
|
+
const message = {
|
|
1031
|
+
type: "resource_change",
|
|
1032
|
+
event,
|
|
1033
|
+
resource_type: instance.constructor.name.toLowerCase(),
|
|
1034
|
+
resource
|
|
1035
|
+
};
|
|
1036
|
+
if (meta?.ops && meta.ops.length > 0) {
|
|
1037
|
+
message.ops = meta.ops;
|
|
1038
|
+
}
|
|
1039
|
+
this.sendDetached(message);
|
|
1040
|
+
};
|
|
1041
|
+
onResourceEvent = (payload) => {
|
|
1042
|
+
if (!this.websocket)
|
|
1043
|
+
return;
|
|
1044
|
+
if (payload.userId && this.userId && payload.userId !== this.userId)
|
|
1045
|
+
return;
|
|
1046
|
+
this.sendDetached({
|
|
1047
|
+
type: "resource_change",
|
|
1048
|
+
event: payload.event,
|
|
1049
|
+
resource_type: payload.resource_type,
|
|
1050
|
+
resource: payload.resource
|
|
1051
|
+
});
|
|
1052
|
+
};
|
|
1053
|
+
async run(websocket) {
|
|
1054
|
+
try {
|
|
1055
|
+
await this.connect(websocket, this.userId ?? undefined, this.authToken ?? undefined);
|
|
1056
|
+
await this.receiveMessages();
|
|
1057
|
+
}
|
|
1058
|
+
finally {
|
|
1059
|
+
await this.disconnect();
|
|
1060
|
+
}
|
|
1061
|
+
}
|
|
1062
|
+
async receiveMessages() {
|
|
1063
|
+
while (true) {
|
|
1064
|
+
let data;
|
|
1065
|
+
try {
|
|
1066
|
+
data = await this.receiveMessage();
|
|
1067
|
+
}
|
|
1068
|
+
catch (err) {
|
|
1069
|
+
// A frame that fails to even decode (truncated msgpack, an
|
|
1070
|
+
// oversized payload past NODETOOL_WS_MAX_MESSAGE_BYTES, …) must not
|
|
1071
|
+
// kill the connection or this loop — it's just one bad frame from a
|
|
1072
|
+
// client that may otherwise be mid-job. Reject it and keep reading.
|
|
1073
|
+
this.logError("Failed to receive/decode WebSocket frame", err);
|
|
1074
|
+
if (this.websocket &&
|
|
1075
|
+
this.websocket.clientState !== "disconnected" &&
|
|
1076
|
+
this.websocket.applicationState !== "disconnected") {
|
|
1077
|
+
await this.sendMessage({
|
|
1078
|
+
error: "invalid_frame",
|
|
1079
|
+
message: err instanceof Error ? err.message : String(err)
|
|
1080
|
+
}).catch((sendErr) => {
|
|
1081
|
+
this.logError("Failed to notify client of invalid frame", sendErr);
|
|
1082
|
+
});
|
|
1083
|
+
continue;
|
|
1084
|
+
}
|
|
1085
|
+
break;
|
|
1086
|
+
}
|
|
1087
|
+
if (data === null)
|
|
1088
|
+
break;
|
|
1089
|
+
const msgType = isString(data.type) ? data.type : null;
|
|
1090
|
+
if (msgType !== null && msgType in controlMessageInSchemas) {
|
|
1091
|
+
const schema = controlMessageInSchemas[msgType];
|
|
1092
|
+
const parsed = schema.safeParse(data);
|
|
1093
|
+
if (!parsed.success) {
|
|
1094
|
+
await this.sendMessage({
|
|
1095
|
+
error: "invalid_message",
|
|
1096
|
+
message: `Malformed '${msgType}' frame: ` +
|
|
1097
|
+
parsed.error.issues
|
|
1098
|
+
.map((issue) => `${issue.path.join(".") || "<root>"}: ${issue.message}`)
|
|
1099
|
+
.join("; ")
|
|
1100
|
+
});
|
|
1101
|
+
continue;
|
|
1102
|
+
}
|
|
1103
|
+
}
|
|
1104
|
+
// Heartbeats show that the connection is alive, not that the user is
|
|
1105
|
+
// working in this editor.
|
|
1106
|
+
if (this.frontendRendererId && msgType !== "ping" && msgType !== "pong") {
|
|
1107
|
+
this.frontendRendererRegistry?.touch(this.frontendRendererId);
|
|
1108
|
+
}
|
|
1109
|
+
if (msgType === "client_tools_manifest") {
|
|
1110
|
+
const tools = Array.isArray(data.tools) ? data.tools : [];
|
|
1111
|
+
this.clientToolsManifest = {};
|
|
1112
|
+
for (const tool of tools) {
|
|
1113
|
+
if (isObjectLike(tool) &&
|
|
1114
|
+
isString(tool.name)) {
|
|
1115
|
+
const name = tool.name;
|
|
1116
|
+
this.clientToolsManifest[name] = tool;
|
|
1117
|
+
}
|
|
1118
|
+
}
|
|
1119
|
+
this.clientToolsManifestReady = true;
|
|
1120
|
+
if (this.frontendRendererId) {
|
|
1121
|
+
this.frontendRendererRegistry?.markReady(this.frontendRendererId);
|
|
1122
|
+
}
|
|
1123
|
+
continue;
|
|
1124
|
+
}
|
|
1125
|
+
if (msgType === "renderer_tool_result") {
|
|
1126
|
+
const rendererId = isString(data.renderer_id) ? data.renderer_id : null;
|
|
1127
|
+
const toolCallId = isString(data.tool_call_id)
|
|
1128
|
+
? data.tool_call_id
|
|
1129
|
+
: null;
|
|
1130
|
+
if (rendererId &&
|
|
1131
|
+
toolCallId &&
|
|
1132
|
+
rendererId === this.frontendRendererId) {
|
|
1133
|
+
this.frontendRendererRegistry?.touch(rendererId);
|
|
1134
|
+
this.rendererToolBridge.resolveResult(toolCallId, data);
|
|
1135
|
+
}
|
|
1136
|
+
continue;
|
|
1137
|
+
}
|
|
1138
|
+
if (msgType === "tool_result") {
|
|
1139
|
+
const toolCallId = isString(data.tool_call_id)
|
|
1140
|
+
? data.tool_call_id
|
|
1141
|
+
: null;
|
|
1142
|
+
if (toolCallId) {
|
|
1143
|
+
this.chat.resolveToolResult(toolCallId, data);
|
|
1144
|
+
// The waiter may live on the runner executing an adopted turn.
|
|
1145
|
+
// resolveResult no-ops on unknown ids, so forwarding is safe.
|
|
1146
|
+
for (const session of this.adoptedSessions.values()) {
|
|
1147
|
+
session.hooks.resolveToolResult(toolCallId, data);
|
|
1148
|
+
}
|
|
1149
|
+
}
|
|
1150
|
+
continue;
|
|
1151
|
+
}
|
|
1152
|
+
if (msgType === "tool_approval_response") {
|
|
1153
|
+
const approvalId = isString(data.approval_id) ? data.approval_id : null;
|
|
1154
|
+
if (approvalId) {
|
|
1155
|
+
this.approvalBridge.resolveResult(approvalId, data);
|
|
1156
|
+
for (const session of this.adoptedSessions.values()) {
|
|
1157
|
+
session.hooks.resolveApproval(approvalId, data);
|
|
1158
|
+
}
|
|
1159
|
+
}
|
|
1160
|
+
continue;
|
|
1161
|
+
}
|
|
1162
|
+
if (msgType === "plan_approval_response") {
|
|
1163
|
+
const approvalId = isString(data.approval_id) ? data.approval_id : null;
|
|
1164
|
+
if (approvalId) {
|
|
1165
|
+
this.approvalBridge.resolveResult(approvalId, data);
|
|
1166
|
+
for (const session of this.adoptedSessions.values()) {
|
|
1167
|
+
session.hooks.resolveApproval(approvalId, data);
|
|
1168
|
+
}
|
|
1169
|
+
}
|
|
1170
|
+
continue;
|
|
1171
|
+
}
|
|
1172
|
+
if (msgType === "secret_request_response") {
|
|
1173
|
+
const approvalId = isString(data.approval_id) ? data.approval_id : null;
|
|
1174
|
+
if (approvalId) {
|
|
1175
|
+
this.approvalBridge.resolveResult(approvalId, data);
|
|
1176
|
+
for (const session of this.adoptedSessions.values()) {
|
|
1177
|
+
session.hooks.resolveApproval(approvalId, data);
|
|
1178
|
+
}
|
|
1179
|
+
}
|
|
1180
|
+
continue;
|
|
1181
|
+
}
|
|
1182
|
+
if (msgType === "ping") {
|
|
1183
|
+
await this.sendMessage({ type: "pong", ts: Date.now() / 1000 });
|
|
1184
|
+
continue;
|
|
1185
|
+
}
|
|
1186
|
+
if (msgType === "pong") {
|
|
1187
|
+
continue;
|
|
1188
|
+
}
|
|
1189
|
+
if (isString(data.command)) {
|
|
1190
|
+
const envelopeParsed = webSocketCommandEnvelopeSchema.safeParse(data);
|
|
1191
|
+
if (!envelopeParsed.success) {
|
|
1192
|
+
await this.sendMessage({
|
|
1193
|
+
error: "invalid_command",
|
|
1194
|
+
details: "Malformed command envelope: " +
|
|
1195
|
+
envelopeParsed.error.issues
|
|
1196
|
+
.map((issue) => `${issue.path.join(".") || "<root>"}: ${issue.message}`)
|
|
1197
|
+
.join("; ")
|
|
1198
|
+
});
|
|
1199
|
+
continue;
|
|
1200
|
+
}
|
|
1201
|
+
// Commands this build doesn't recognize fall through to
|
|
1202
|
+
// handleCommand's own `{ error: "Unknown command" }` reply below —
|
|
1203
|
+
// only known commands get their `data` payload schema-checked here.
|
|
1204
|
+
const dataSchema = commandDataSchemas[envelopeParsed.data.command];
|
|
1205
|
+
if (dataSchema) {
|
|
1206
|
+
const dataParsed = dataSchema.safeParse(envelopeParsed.data.data ?? {});
|
|
1207
|
+
if (!dataParsed.success) {
|
|
1208
|
+
await this.sendMessage({
|
|
1209
|
+
error: "invalid_command",
|
|
1210
|
+
details: `Malformed '${envelopeParsed.data.command}' data: ` +
|
|
1211
|
+
dataParsed.error.issues
|
|
1212
|
+
.map((issue) => `${issue.path.join(".") || "<root>"}: ${issue.message}`)
|
|
1213
|
+
.join("; ")
|
|
1214
|
+
});
|
|
1215
|
+
continue;
|
|
1216
|
+
}
|
|
1217
|
+
}
|
|
1218
|
+
try {
|
|
1219
|
+
// The envelope Zod-parsed above is the same frame — its schema
|
|
1220
|
+
// passes every key through, so nothing was dropped.
|
|
1221
|
+
// SAFETY: the schema types `command` as a bare string on purpose;
|
|
1222
|
+
// `handleCommand`'s switch answers `{ error: "Unknown command" }`
|
|
1223
|
+
// for anything this build does not implement.
|
|
1224
|
+
const response = await this.handleCommand({
|
|
1225
|
+
...envelopeParsed.data,
|
|
1226
|
+
command: envelopeParsed.data.command,
|
|
1227
|
+
data: envelopeParsed.data.data ?? {},
|
|
1228
|
+
// MessagePack clients encode an absent request_id as nil; the
|
|
1229
|
+
// envelope declares it optional, not nullable.
|
|
1230
|
+
request_id: envelopeParsed.data.request_id ?? undefined
|
|
1231
|
+
});
|
|
1232
|
+
// RPC commands send their `rpc_response` frame inline (in runRpc)
|
|
1233
|
+
// and return null so we don't send a stray legacy reply.
|
|
1234
|
+
if (response)
|
|
1235
|
+
await this.sendMessage(response);
|
|
1236
|
+
}
|
|
1237
|
+
catch (err) {
|
|
1238
|
+
this.logError("invalid_command handling failed", err);
|
|
1239
|
+
await this.sendMessage({
|
|
1240
|
+
error: "invalid_command",
|
|
1241
|
+
details: err instanceof Error ? err.message : String(err)
|
|
1242
|
+
});
|
|
1243
|
+
}
|
|
1244
|
+
continue;
|
|
1245
|
+
}
|
|
1246
|
+
await this.sendMessage({
|
|
1247
|
+
error: "invalid_message",
|
|
1248
|
+
message: "All messages must include a 'command' field. Use 'chat_message' command for chat."
|
|
1249
|
+
});
|
|
1250
|
+
}
|
|
1251
|
+
}
|
|
1252
|
+
}
|
|
1253
|
+
//# sourceMappingURL=websocket-client-session.js.map
|