@nodetool-ai/websocket 0.8.1 → 0.8.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/.nodetool-build-stamp +1 -1
- package/dist/chat-turn-registry.d.ts +2 -1
- package/dist/chat-turn-registry.d.ts.map +1 -1
- package/dist/chat-turn-registry.js +8 -1
- package/dist/chat-turn-registry.js.map +1 -1
- package/dist/collection-api.d.ts.map +1 -1
- package/dist/collection-api.js +41 -6
- package/dist/collection-api.js.map +1 -1
- package/dist/custom-providers.d.ts.map +1 -1
- package/dist/custom-providers.js +6 -1
- package/dist/custom-providers.js.map +1 -1
- package/dist/error-traces.d.ts +56 -0
- package/dist/error-traces.d.ts.map +1 -0
- package/dist/error-traces.js +179 -0
- package/dist/error-traces.js.map +1 -0
- package/dist/example-workflows.d.ts.map +1 -1
- package/dist/example-workflows.js +6 -0
- package/dist/example-workflows.js.map +1 -1
- package/dist/fake-runtime.d.ts +41 -6
- package/dist/fake-runtime.d.ts.map +1 -1
- package/dist/fake-runtime.js +247 -16
- package/dist/fake-runtime.js.map +1 -1
- package/dist/file-api.d.ts.map +1 -1
- package/dist/file-api.js +6 -8
- package/dist/file-api.js.map +1 -1
- package/dist/generation-recovery.d.ts.map +1 -1
- package/dist/generation-recovery.js +32 -7
- package/dist/generation-recovery.js.map +1 -1
- package/dist/headless-job-runner.d.ts.map +1 -1
- package/dist/headless-job-runner.js +5 -1
- package/dist/headless-job-runner.js.map +1 -1
- package/dist/http-api.d.ts +3 -1
- package/dist/http-api.d.ts.map +1 -1
- package/dist/http-api.js +66 -9
- package/dist/http-api.js.map +1 -1
- package/dist/http-body-schemas.d.ts +2 -0
- package/dist/http-body-schemas.d.ts.map +1 -1
- package/dist/http-body-schemas.js +8 -1
- package/dist/http-body-schemas.js.map +1 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -1
- package/dist/index.js.map +1 -1
- package/dist/interrupted-jobs.d.ts +14 -0
- package/dist/interrupted-jobs.d.ts.map +1 -0
- package/dist/interrupted-jobs.js +28 -0
- package/dist/interrupted-jobs.js.map +1 -0
- package/dist/lib/admin.d.ts +7 -0
- package/dist/lib/admin.d.ts.map +1 -0
- package/dist/lib/admin.js +20 -0
- package/dist/lib/admin.js.map +1 -0
- package/dist/lib/app-debug-service.js +1 -1
- package/dist/lib/app-debug-service.js.map +1 -1
- package/dist/lib/app-instances-service.d.ts +1319 -0
- package/dist/lib/app-instances-service.d.ts.map +1 -0
- package/dist/lib/app-instances-service.js +377 -0
- package/dist/lib/app-instances-service.js.map +1 -0
- package/dist/lib/app-project-export.d.ts +12 -0
- package/dist/lib/app-project-export.d.ts.map +1 -0
- package/dist/lib/app-project-export.js +42 -0
- package/dist/lib/app-project-export.js.map +1 -0
- package/dist/lib/app-run-cancellation.d.ts +4 -0
- package/dist/lib/app-run-cancellation.d.ts.map +1 -0
- package/dist/lib/app-run-cancellation.js +28 -0
- package/dist/lib/app-run-cancellation.js.map +1 -0
- package/dist/lib/applications-service.d.ts +182 -1
- package/dist/lib/applications-service.d.ts.map +1 -1
- package/dist/lib/applications-service.js +27 -6
- package/dist/lib/applications-service.js.map +1 -1
- package/dist/lib/asset-export.d.ts +6 -2
- package/dist/lib/asset-export.d.ts.map +1 -1
- package/dist/lib/asset-export.js +15 -7
- package/dist/lib/asset-export.js.map +1 -1
- package/dist/lib/asset-paths.d.ts +7 -11
- package/dist/lib/asset-paths.d.ts.map +1 -1
- package/dist/lib/asset-paths.js +8 -56
- package/dist/lib/asset-paths.js.map +1 -1
- package/dist/lib/asset-response.d.ts.map +1 -1
- package/dist/lib/asset-response.js +3 -1
- package/dist/lib/asset-response.js.map +1 -1
- package/dist/lib/audio-peaks.d.ts.map +1 -1
- package/dist/lib/audio-peaks.js +5 -1
- package/dist/lib/audio-peaks.js.map +1 -1
- package/dist/lib/bridge.d.ts.map +1 -1
- package/dist/lib/bridge.js.map +1 -1
- package/dist/lib/cloud-profile.d.ts +10 -0
- package/dist/lib/cloud-profile.d.ts.map +1 -0
- package/dist/lib/cloud-profile.js +13 -0
- package/dist/lib/cloud-profile.js.map +1 -0
- package/dist/lib/document-model-interfaces.d.ts.map +1 -1
- package/dist/lib/document-model-interfaces.js +9 -8
- package/dist/lib/document-model-interfaces.js.map +1 -1
- package/dist/lib/example-apps.d.ts +9 -0
- package/dist/lib/example-apps.d.ts.map +1 -1
- package/dist/lib/example-apps.js +61 -14
- package/dist/lib/example-apps.js.map +1 -1
- package/dist/lib/http-tracing.d.ts +12 -0
- package/dist/lib/http-tracing.d.ts.map +1 -0
- package/dist/lib/http-tracing.js +81 -0
- package/dist/lib/http-tracing.js.map +1 -0
- package/dist/lib/http-user-id.d.ts +2 -0
- package/dist/lib/http-user-id.d.ts.map +1 -0
- package/dist/lib/http-user-id.js +4 -0
- package/dist/lib/http-user-id.js.map +1 -0
- package/dist/lib/json-body.d.ts +11 -0
- package/dist/lib/json-body.d.ts.map +1 -0
- package/dist/lib/json-body.js +13 -0
- package/dist/lib/json-body.js.map +1 -0
- package/dist/lib/media.d.ts +1 -6
- package/dist/lib/media.d.ts.map +1 -1
- package/dist/lib/media.js +8 -44
- package/dist/lib/media.js.map +1 -1
- package/dist/lib/public-routes.d.ts +22 -0
- package/dist/lib/public-routes.d.ts.map +1 -1
- package/dist/lib/public-routes.js +41 -0
- package/dist/lib/public-routes.js.map +1 -1
- package/dist/lib/public-workflow-share.d.ts +31 -0
- package/dist/lib/public-workflow-share.d.ts.map +1 -0
- package/dist/lib/public-workflow-share.js +88 -0
- package/dist/lib/public-workflow-share.js.map +1 -0
- package/dist/lib/python-metadata-roots.d.ts +27 -0
- package/dist/lib/python-metadata-roots.d.ts.map +1 -0
- package/dist/lib/python-metadata-roots.js +92 -0
- package/dist/lib/python-metadata-roots.js.map +1 -0
- package/dist/lib/run-trace-live-delivery.d.ts +25 -0
- package/dist/lib/run-trace-live-delivery.d.ts.map +1 -0
- package/dist/lib/run-trace-live-delivery.js +91 -0
- package/dist/lib/run-trace-live-delivery.js.map +1 -0
- package/dist/lib/runtime-detection.d.ts +1 -1
- package/dist/lib/runtime-detection.d.ts.map +1 -1
- package/dist/lib/runtime-detection.js +2 -1
- package/dist/lib/runtime-detection.js.map +1 -1
- package/dist/lib/server-auth-token.d.ts +18 -0
- package/dist/lib/server-auth-token.d.ts.map +1 -0
- package/dist/lib/server-auth-token.js +28 -0
- package/dist/lib/server-auth-token.js.map +1 -0
- package/dist/lib/test-ui-run-routes.d.ts +8 -0
- package/dist/lib/test-ui-run-routes.d.ts.map +1 -0
- package/dist/lib/test-ui-run-routes.js +42 -0
- package/dist/lib/test-ui-run-routes.js.map +1 -0
- package/dist/lib/thumbnail.d.ts.map +1 -1
- package/dist/lib/thumbnail.js +12 -9
- package/dist/lib/thumbnail.js.map +1 -1
- package/dist/lib/timeline-bundle.d.ts +159 -16
- package/dist/lib/timeline-bundle.d.ts.map +1 -1
- package/dist/lib/timeline-bundle.js +34 -6
- package/dist/lib/timeline-bundle.js.map +1 -1
- package/dist/lib/timeline-media-export.d.ts +18 -0
- package/dist/lib/timeline-media-export.d.ts.map +1 -0
- package/dist/lib/timeline-media-export.js +66 -0
- package/dist/lib/timeline-media-export.js.map +1 -0
- package/dist/lib/timeline-premiere-import.d.ts +24 -0
- package/dist/lib/timeline-premiere-import.d.ts.map +1 -0
- package/dist/lib/timeline-premiere-import.js +102 -0
- package/dist/lib/timeline-premiere-import.js.map +1 -0
- package/dist/lib/timeline-premiere.d.ts +38 -0
- package/dist/lib/timeline-premiere.d.ts.map +1 -0
- package/dist/lib/timeline-premiere.js +87 -0
- package/dist/lib/timeline-premiere.js.map +1 -0
- package/dist/lib/video-proxy.d.ts.map +1 -1
- package/dist/lib/video-proxy.js +3 -2
- package/dist/lib/video-proxy.js.map +1 -1
- package/dist/lib/workflow-service.d.ts.map +1 -1
- package/dist/lib/workflow-service.js +4 -1
- package/dist/lib/workflow-service.js.map +1 -1
- package/dist/mcp-agent-tools.d.ts.map +1 -1
- package/dist/mcp-agent-tools.js +95 -162
- package/dist/mcp-agent-tools.js.map +1 -1
- package/dist/mcp-client-config.d.ts +64 -0
- package/dist/mcp-client-config.d.ts.map +1 -0
- package/dist/mcp-client-config.js +353 -0
- package/dist/mcp-client-config.js.map +1 -0
- package/dist/mcp-server.d.ts +7 -0
- package/dist/mcp-server.d.ts.map +1 -1
- package/dist/mcp-server.js +163 -16
- package/dist/mcp-server.js.map +1 -1
- package/dist/mcp-skill-prompts.d.ts +23 -0
- package/dist/mcp-skill-prompts.d.ts.map +1 -0
- package/dist/mcp-skill-prompts.js +91 -0
- package/dist/mcp-skill-prompts.js.map +1 -0
- package/dist/mcp-tool-deps.d.ts.map +1 -1
- package/dist/mcp-tool-deps.js +8 -1
- package/dist/mcp-tool-deps.js.map +1 -1
- package/dist/models-api.d.ts +10 -0
- package/dist/models-api.d.ts.map +1 -1
- package/dist/models-api.js +29 -2
- package/dist/models-api.js.map +1 -1
- package/dist/node-registry-setup.d.ts +1 -1
- package/dist/node-registry-setup.d.ts.map +1 -1
- package/dist/node-registry-setup.js +21 -114
- package/dist/node-registry-setup.js.map +1 -1
- package/dist/oauth-api.d.ts.map +1 -1
- package/dist/oauth-api.js +45 -23
- package/dist/oauth-api.js.map +1 -1
- package/dist/openai-api.d.ts.map +1 -1
- package/dist/openai-api.js +10 -2
- package/dist/openai-api.js.map +1 -1
- package/dist/plugins/websocket.d.ts.map +1 -1
- package/dist/plugins/websocket.js +27 -59
- package/dist/plugins/websocket.js.map +1 -1
- package/dist/python-bridge-gate.d.ts +28 -0
- package/dist/python-bridge-gate.d.ts.map +1 -0
- package/dist/python-bridge-gate.js +36 -0
- package/dist/python-bridge-gate.js.map +1 -0
- package/dist/routes/app-runs.d.ts +4 -0
- package/dist/routes/app-runs.d.ts.map +1 -0
- package/dist/routes/app-runs.js +173 -0
- package/dist/routes/app-runs.js.map +1 -0
- package/dist/routes/applications.d.ts +1 -0
- package/dist/routes/applications.d.ts.map +1 -1
- package/dist/routes/applications.js +24 -0
- package/dist/routes/applications.js.map +1 -1
- package/dist/routes/assets.d.ts.map +1 -1
- package/dist/routes/assets.js +31 -41
- package/dist/routes/assets.js.map +1 -1
- package/dist/routes/config.d.ts.map +1 -1
- package/dist/routes/config.js +6 -0
- package/dist/routes/config.js.map +1 -1
- package/dist/routes/documents.d.ts.map +1 -1
- package/dist/routes/documents.js +24 -0
- package/dist/routes/documents.js.map +1 -1
- package/dist/routes/fal-pricing-estimate.d.ts.map +1 -1
- package/dist/routes/fal-pricing-estimate.js +2 -0
- package/dist/routes/fal-pricing-estimate.js.map +1 -1
- package/dist/routes/files.d.ts.map +1 -1
- package/dist/routes/files.js +2 -0
- package/dist/routes/files.js.map +1 -1
- package/dist/routes/games.d.ts +38 -0
- package/dist/routes/games.d.ts.map +1 -0
- package/dist/routes/games.js +158 -0
- package/dist/routes/games.js.map +1 -0
- package/dist/routes/integrations.d.ts.map +1 -1
- package/dist/routes/integrations.js +22 -26
- package/dist/routes/integrations.js.map +1 -1
- package/dist/routes/js-scripts.d.ts +10 -4
- package/dist/routes/js-scripts.d.ts.map +1 -1
- package/dist/routes/js-scripts.js +451 -69
- package/dist/routes/js-scripts.js.map +1 -1
- package/dist/routes/nodes.d.ts.map +1 -1
- package/dist/routes/nodes.js +34 -1
- package/dist/routes/nodes.js.map +1 -1
- package/dist/routes/public-shared-workflows.d.ts +16 -0
- package/dist/routes/public-shared-workflows.d.ts.map +1 -0
- package/dist/routes/public-shared-workflows.js +55 -0
- package/dist/routes/public-shared-workflows.js.map +1 -0
- package/dist/routes/run-spans.d.ts +4 -0
- package/dist/routes/run-spans.d.ts.map +1 -0
- package/dist/routes/run-spans.js +53 -0
- package/dist/routes/run-spans.js.map +1 -0
- package/dist/routes/storage.d.ts.map +1 -1
- package/dist/routes/storage.js +2 -0
- package/dist/routes/storage.js.map +1 -1
- package/dist/routes/storyboards.d.ts.map +1 -1
- package/dist/routes/storyboards.js +6 -3
- package/dist/routes/storyboards.js.map +1 -1
- package/dist/routes/timeline-fonts.d.ts +22 -0
- package/dist/routes/timeline-fonts.d.ts.map +1 -1
- package/dist/routes/timeline-fonts.js +138 -7
- package/dist/routes/timeline-fonts.js.map +1 -1
- package/dist/routes/timelines.d.ts +8 -4
- package/dist/routes/timelines.d.ts.map +1 -1
- package/dist/routes/timelines.js +209 -16
- package/dist/routes/timelines.js.map +1 -1
- package/dist/screenshot-docs-seed.d.ts +24 -0
- package/dist/screenshot-docs-seed.d.ts.map +1 -0
- package/dist/screenshot-docs-seed.js +414 -0
- package/dist/screenshot-docs-seed.js.map +1 -0
- package/dist/screenshot-projects.d.ts.map +1 -1
- package/dist/screenshot-projects.js +9 -9
- package/dist/screenshot-projects.js.map +1 -1
- package/dist/screenshot-server.js +114 -20
- package/dist/screenshot-server.js.map +1 -1
- package/dist/sdk/sdk-model-download-service.d.ts.map +1 -1
- package/dist/sdk/sdk-model-download-service.js +5 -2
- package/dist/sdk/sdk-model-download-service.js.map +1 -1
- package/dist/server.js +173 -109
- package/dist/server.js.map +1 -1
- package/dist/session/app-run-fold.d.ts +7 -0
- package/dist/session/app-run-fold.d.ts.map +1 -0
- package/dist/session/app-run-fold.js +45 -0
- package/dist/session/app-run-fold.js.map +1 -0
- package/dist/session/chat-prompt.d.ts.map +1 -1
- package/dist/session/chat-prompt.js +37 -15
- package/dist/session/chat-prompt.js.map +1 -1
- package/dist/session/chat-turn.d.ts +11 -0
- package/dist/session/chat-turn.d.ts.map +1 -1
- package/dist/session/chat-turn.js +270 -116
- package/dist/session/chat-turn.js.map +1 -1
- package/dist/session/commands.d.ts +14 -0
- package/dist/session/commands.d.ts.map +1 -1
- package/dist/session/commands.js +119 -14
- package/dist/session/commands.js.map +1 -1
- package/dist/session/inference.d.ts +30 -2
- package/dist/session/inference.d.ts.map +1 -1
- package/dist/session/inference.js +165 -16
- package/dist/session/inference.js.map +1 -1
- package/dist/session/job-execution.d.ts +7 -1
- package/dist/session/job-execution.d.ts.map +1 -1
- package/dist/session/job-execution.js +329 -42
- package/dist/session/job-execution.js.map +1 -1
- package/dist/session/model-interfaces.d.ts +2 -1
- package/dist/session/model-interfaces.d.ts.map +1 -1
- package/dist/session/model-interfaces.js +1 -0
- package/dist/session/model-interfaces.js.map +1 -1
- package/dist/storage-api.d.ts +0 -4
- package/dist/storage-api.d.ts.map +1 -1
- package/dist/storage-api.js +3 -26
- package/dist/storage-api.js.map +1 -1
- package/dist/storage-retention.d.ts +5 -0
- package/dist/storage-retention.d.ts.map +1 -1
- package/dist/storage-retention.js +22 -1
- package/dist/storage-retention.js.map +1 -1
- package/dist/test-ui-server.d.ts +11 -0
- package/dist/test-ui-server.d.ts.map +1 -1
- package/dist/test-ui-server.js +84 -6
- package/dist/test-ui-server.js.map +1 -1
- package/dist/timeline-generation-recovery.d.ts +4 -0
- package/dist/timeline-generation-recovery.d.ts.map +1 -0
- package/dist/timeline-generation-recovery.js +72 -0
- package/dist/timeline-generation-recovery.js.map +1 -0
- package/dist/triggers/dispatcher.d.ts.map +1 -1
- package/dist/triggers/dispatcher.js +26 -6
- package/dist/triggers/dispatcher.js.map +1 -1
- package/dist/triggers/file-watch.d.ts.map +1 -1
- package/dist/triggers/file-watch.js +35 -19
- package/dist/triggers/file-watch.js.map +1 -1
- package/dist/triggers/scheduler.d.ts.map +1 -1
- package/dist/triggers/scheduler.js +7 -5
- package/dist/triggers/scheduler.js.map +1 -1
- package/dist/triggers/stores.js +8 -8
- package/dist/triggers/stores.js.map +1 -1
- package/dist/triggers/webhook-route.js +2 -2
- package/dist/triggers/webhook-route.js.map +1 -1
- package/dist/trpc/error-formatter.d.ts.map +1 -1
- package/dist/trpc/error-formatter.js +2 -1
- package/dist/trpc/error-formatter.js.map +1 -1
- package/dist/trpc/error-logging.d.ts +10 -0
- package/dist/trpc/error-logging.d.ts.map +1 -1
- package/dist/trpc/error-logging.js +21 -0
- package/dist/trpc/error-logging.js.map +1 -1
- package/dist/trpc/router.d.ts +100 -31028
- package/dist/trpc/router.d.ts.map +1 -1
- package/dist/trpc/router.js +12 -3
- package/dist/trpc/router.js.map +1 -1
- package/dist/trpc/routers/app-instances.d.ts +2332 -0
- package/dist/trpc/routers/app-instances.d.ts.map +1 -0
- package/dist/trpc/routers/app-instances.js +52 -0
- package/dist/trpc/routers/app-instances.js.map +1 -0
- package/dist/trpc/routers/app-runs.d.ts +1120 -0
- package/dist/trpc/routers/app-runs.d.ts.map +1 -0
- package/dist/trpc/routers/app-runs.js +28 -0
- package/dist/trpc/routers/app-runs.js.map +1 -0
- package/dist/trpc/routers/applications.d.ts +1102 -0
- package/dist/trpc/routers/applications.d.ts.map +1 -1
- package/dist/trpc/routers/applications.js +5 -2
- package/dist/trpc/routers/applications.js.map +1 -1
- package/dist/trpc/routers/assets.d.ts +18 -0
- package/dist/trpc/routers/assets.d.ts.map +1 -1
- package/dist/trpc/routers/assets.js +20 -5
- package/dist/trpc/routers/assets.js.map +1 -1
- package/dist/trpc/routers/bug-reports.d.ts +33 -0
- package/dist/trpc/routers/bug-reports.d.ts.map +1 -0
- package/dist/trpc/routers/bug-reports.js +69 -0
- package/dist/trpc/routers/bug-reports.js.map +1 -0
- package/dist/trpc/routers/collections.d.ts.map +1 -1
- package/dist/trpc/routers/collections.js +16 -10
- package/dist/trpc/routers/collections.js.map +1 -1
- package/dist/trpc/routers/credits.d.ts.map +1 -1
- package/dist/trpc/routers/credits.js +11 -1
- package/dist/trpc/routers/credits.js.map +1 -1
- package/dist/trpc/routers/documents.d.ts.map +1 -1
- package/dist/trpc/routers/documents.js +8 -2
- package/dist/trpc/routers/documents.js.map +1 -1
- package/dist/trpc/routers/error-traces.d.ts +132 -0
- package/dist/trpc/routers/error-traces.d.ts.map +1 -0
- package/dist/trpc/routers/error-traces.js +118 -0
- package/dist/trpc/routers/error-traces.js.map +1 -0
- package/dist/trpc/routers/extension.d.ts +3 -3
- package/dist/trpc/routers/extension.d.ts.map +1 -1
- package/dist/trpc/routers/extension.js +13 -9
- package/dist/trpc/routers/extension.js.map +1 -1
- package/dist/trpc/routers/gameDraftHistory.d.ts +7 -0
- package/dist/trpc/routers/gameDraftHistory.d.ts.map +1 -0
- package/dist/trpc/routers/gameDraftHistory.js +40 -0
- package/dist/trpc/routers/gameDraftHistory.js.map +1 -0
- package/dist/trpc/routers/games.d.ts +59974 -5414
- package/dist/trpc/routers/games.d.ts.map +1 -1
- package/dist/trpc/routers/games.js +531 -136
- package/dist/trpc/routers/games.js.map +1 -1
- package/dist/trpc/routers/jobs.d.ts +42 -0
- package/dist/trpc/routers/jobs.d.ts.map +1 -1
- package/dist/trpc/routers/jobs.js +89 -4
- package/dist/trpc/routers/jobs.js.map +1 -1
- package/dist/trpc/routers/js-scripts.d.ts.map +1 -1
- package/dist/trpc/routers/js-scripts.js +18 -2
- package/dist/trpc/routers/js-scripts.js.map +1 -1
- package/dist/trpc/routers/mcp-config.d.ts +3 -1
- package/dist/trpc/routers/mcp-config.d.ts.map +1 -1
- package/dist/trpc/routers/mcp-config.js +46 -208
- package/dist/trpc/routers/mcp-config.js.map +1 -1
- package/dist/trpc/routers/messages.d.ts +10 -0
- package/dist/trpc/routers/messages.d.ts.map +1 -1
- package/dist/trpc/routers/messages.js +16 -2
- package/dist/trpc/routers/messages.js.map +1 -1
- package/dist/trpc/routers/models.d.ts +130 -0
- package/dist/trpc/routers/models.d.ts.map +1 -1
- package/dist/trpc/routers/models.js +119 -61
- package/dist/trpc/routers/models.js.map +1 -1
- package/dist/trpc/routers/packs.d.ts.map +1 -1
- package/dist/trpc/routers/packs.js +18 -4
- package/dist/trpc/routers/packs.js.map +1 -1
- package/dist/trpc/routers/projects.d.ts +66 -2
- package/dist/trpc/routers/projects.d.ts.map +1 -1
- package/dist/trpc/routers/projects.js +19 -2
- package/dist/trpc/routers/projects.js.map +1 -1
- package/dist/trpc/routers/runs.d.ts +472 -0
- package/dist/trpc/routers/runs.d.ts.map +1 -0
- package/dist/trpc/routers/runs.js +40 -0
- package/dist/trpc/routers/runs.js.map +1 -0
- package/dist/trpc/routers/settings.d.ts +3 -0
- package/dist/trpc/routers/settings.d.ts.map +1 -1
- package/dist/trpc/routers/settings.js +32 -5
- package/dist/trpc/routers/settings.js.map +1 -1
- package/dist/trpc/routers/sketch.d.ts +44 -0
- package/dist/trpc/routers/sketch.d.ts.map +1 -1
- package/dist/trpc/routers/sketch.js +2 -2
- package/dist/trpc/routers/sketch.js.map +1 -1
- package/dist/trpc/routers/storyboards.d.ts +903 -1
- package/dist/trpc/routers/storyboards.d.ts.map +1 -1
- package/dist/trpc/routers/storyboards.js +8 -5
- package/dist/trpc/routers/storyboards.js.map +1 -1
- package/dist/trpc/routers/threads.d.ts.map +1 -1
- package/dist/trpc/routers/threads.js +8 -2
- package/dist/trpc/routers/threads.js.map +1 -1
- package/dist/trpc/routers/timeline.d.ts +647 -63
- package/dist/trpc/routers/timeline.d.ts.map +1 -1
- package/dist/trpc/routers/timeline.js +193 -4
- package/dist/trpc/routers/timeline.js.map +1 -1
- package/dist/trpc/routers/triggers.d.ts.map +1 -1
- package/dist/trpc/routers/triggers.js +18 -3
- package/dist/trpc/routers/triggers.js.map +1 -1
- package/dist/trpc/routers/users.d.ts +3 -2
- package/dist/trpc/routers/users.d.ts.map +1 -1
- package/dist/trpc/routers/users.js +25 -27
- package/dist/trpc/routers/users.js.map +1 -1
- package/dist/trpc/routers/worker.d.ts +10 -9
- package/dist/trpc/routers/worker.d.ts.map +1 -1
- package/dist/trpc/routers/worker.js +40 -16
- package/dist/trpc/routers/worker.js.map +1 -1
- package/dist/trpc/routers/workflows.d.ts +202 -3
- package/dist/trpc/routers/workflows.d.ts.map +1 -1
- package/dist/trpc/routers/workflows.js +72 -12
- package/dist/trpc/routers/workflows.js.map +1 -1
- package/dist/trpc/sandbox-coverage.d.ts.map +1 -1
- package/dist/trpc/sandbox-coverage.js +119 -0
- package/dist/trpc/sandbox-coverage.js.map +1 -1
- package/dist/websocket-client-session.d.ts +4 -2
- package/dist/websocket-client-session.d.ts.map +1 -1
- package/dist/websocket-client-session.js +23 -3
- package/dist/websocket-client-session.js.map +1 -1
- package/dist/worker-settings-env.d.ts +23 -0
- package/dist/worker-settings-env.d.ts.map +1 -0
- package/dist/worker-settings-env.js +47 -0
- package/dist/worker-settings-env.js.map +1 -0
- package/dist/workflow-interface-service.d.ts +7 -0
- package/dist/workflow-interface-service.d.ts.map +1 -1
- package/package.json +58 -41
- package/dist/extension-cdp-bridge.d.ts +0 -85
- package/dist/extension-cdp-bridge.d.ts.map +0 -1
- package/dist/extension-cdp-bridge.js +0 -163
- package/dist/extension-cdp-bridge.js.map +0 -1
package/dist/server.js
CHANGED
|
@@ -6,21 +6,23 @@
|
|
|
6
6
|
* An HTTP→HTTPS redirect server starts on port 80 when TLS is active.
|
|
7
7
|
* Connect the CLI with: npm run chat -- --url ws://localhost:7777/ws
|
|
8
8
|
*/
|
|
9
|
-
import { startGenerationReconcileWorker, sweepInterruptedGenerations } from "@nodetool-ai/execution";
|
|
9
|
+
import { ensureRunTraceTelemetry, startGenerationReconcileWorker, sweepInterruptedGenerations } from "@nodetool-ai/execution";
|
|
10
10
|
import { join, resolve, dirname } from "node:path";
|
|
11
11
|
import { fileURLToPath } from "node:url";
|
|
12
12
|
import { existsSync, mkdirSync, readFileSync, readdirSync } from "node:fs";
|
|
13
|
-
import { spawnSync } from "node:child_process";
|
|
14
13
|
import { createServer as createHttpServer } from "node:http";
|
|
14
|
+
import { flushCompileCache } from "node:module";
|
|
15
15
|
import crypto from "node:crypto";
|
|
16
16
|
import { createLogger, configureLogging, getDefaultDbPath, getPostgresDatabaseUrl, loadEnvironment } from "@nodetool-ai/config";
|
|
17
17
|
import { registerTransformersJsProvider } from "@nodetool-ai/transformers-js-provider";
|
|
18
|
+
import { registerWhisperCppProviders } from "@nodetool-ai/whisper-cpp";
|
|
18
19
|
import { setCodeNodeAgentsModule } from "@nodetool-ai/base-nodes";
|
|
19
20
|
import * as agentsModule from "@nodetool-ai/agents";
|
|
20
21
|
import { bootstrapNodeRegistry, mergePythonBridgeMetadata } from "./node-registry-setup.js";
|
|
21
22
|
import { corsOriginDelegate } from "./cors.js";
|
|
22
23
|
import { zipExtensionDist } from "./lib/extension-dist.js";
|
|
23
|
-
import { isPublicAuthExemptRoute } from "./lib/public-routes.js";
|
|
24
|
+
import { isPublicAuthExemptRoute, isStaticAppRequest, routedPathname } from "./lib/public-routes.js";
|
|
25
|
+
import { matchesServerAuthToken, resolveServerAuthToken } from "./lib/server-auth-token.js";
|
|
24
26
|
import { isWebSocketUpgrade, denyUnauthorized, denyDraining } from "./lib/ws-upgrade.js";
|
|
25
27
|
import { isDraining, startDrain } from "./drain.js";
|
|
26
28
|
import { chatTurnRegistry } from "./chat-turn-registry.js";
|
|
@@ -28,18 +30,22 @@ import { jobRunRegistry } from "./job-run-registry.js";
|
|
|
28
30
|
import { replayUpgradeToOwner } from "./lib/fly-replay.js";
|
|
29
31
|
import { startJobCancelPoller } from "./job-control.js";
|
|
30
32
|
import { resolveTrustLocalhost, isLoopbackAddress, parseTrustedProxies, parseTrustedLocalNetworks, isTrustedLocalAddress } from "./lib/localhost-trust.js";
|
|
31
|
-
import {
|
|
33
|
+
import { registerHttpTracing } from "./lib/http-tracing.js";
|
|
34
|
+
import { shutdownTelemetry, createPythonBridge, WebsocketPythonBridge, SwappableBridge, logPythonWorkerStderr } from "@nodetool-ai/runtime";
|
|
32
35
|
import { deriveKey, getMasterKey, initMasterKey } from "@nodetool-ai/security";
|
|
33
36
|
import { setDefaultModelInterfaces } from "@nodetool-ai/runtime";
|
|
34
37
|
import { serverModelInterfaces } from "./websocket-client-session.js";
|
|
35
38
|
import { WorkerManager, attachWorkerActivityHeartbeat, startReaper } from "@nodetool-ai/compute";
|
|
36
|
-
import { getSecret, AccessToken, getWorkerProfile, initDb, initPostgresDb, isAccessToken, McpOauthClient, MCP_OAUTH_ACCESS_TOKEN_PREFIX, migrateSqliteDb, runSeeds } from "@nodetool-ai/models";
|
|
39
|
+
import { getSecret, getRegisteredRunTrace, AccessToken, getWorkerProfile, initDb, initPostgresDb, isAccessToken, McpOauthClient, MCP_OAUTH_ACCESS_TOKEN_PREFIX, migrateSqliteDb, runSeeds } from "@nodetool-ai/models";
|
|
40
|
+
import { applyTransformersJsCacheSetting, resolveWorkerSettingsEnv } from "./worker-settings-env.js";
|
|
37
41
|
import { isMcpHttpEnabled, MCP_ENABLE_FLAG } from "./lib/mcp-mount.js";
|
|
38
42
|
import { authenticateMcpAccessToken, mcpBearerChallenge } from "./oauth/gate.js";
|
|
39
43
|
import { registerPythonProviders, relayWorkerDownload } from "./models-api.js";
|
|
44
|
+
import { createProviderRegistrar } from "./python-bridge-gate.js";
|
|
40
45
|
import { syncCustomProviderRegistry } from "./custom-providers.js";
|
|
41
|
-
import {
|
|
46
|
+
import { runScheduledStorageCleanup } from "./storage-retention.js";
|
|
42
47
|
import { createGenerationRecoveryWorker } from "./generation-recovery.js";
|
|
48
|
+
import { sweepInterruptedJobs } from "./interrupted-jobs.js";
|
|
43
49
|
/** User id the auth middleware assigns in local (no-account) mode. */
|
|
44
50
|
const LOCAL_USER_ID = "1";
|
|
45
51
|
/** How long an MCP OAuth client nobody ever approved is kept before the
|
|
@@ -53,7 +59,7 @@ import fastifyCors from "@fastify/cors";
|
|
|
53
59
|
import fastifyRateLimit from "@fastify/rate-limit";
|
|
54
60
|
import fastifyStatic from "@fastify/static";
|
|
55
61
|
import { packWebSocketMessage } from "./messagepack.js";
|
|
56
|
-
import { SupabaseAuthProvider, LocalAuthProvider, DelegatedTokenProvider, isDelegatedToken, AppSessionTokenProvider, isAppSessionToken } from "@nodetool-ai/auth";
|
|
62
|
+
import { SupabaseAuthProvider, LocalAuthProvider, DelegatedTokenProvider, isDelegatedToken, AppSessionTokenProvider, isAppSessionToken, FileUserManager } from "@nodetool-ai/auth";
|
|
57
63
|
import { fastifyTRPCPlugin } from "@trpc/server/adapters/fastify";
|
|
58
64
|
import { appRouter } from "./trpc/router.js";
|
|
59
65
|
import { createContextFactory } from "./trpc/context.js";
|
|
@@ -89,7 +95,10 @@ import { initWorkspaceChangeEvents, initWorkspaceStorage } from "./lib/workflow-
|
|
|
89
95
|
import filesRoutes from "./routes/files.js";
|
|
90
96
|
import collectionsRoutes from "./routes/collections.js";
|
|
91
97
|
import applicationsRoutes from "./routes/applications.js";
|
|
98
|
+
import appRunsRoutes from "./routes/app-runs.js";
|
|
99
|
+
import runSpansRoutes from "./routes/run-spans.js";
|
|
92
100
|
import publicAppRoutes from "./routes/public-apps.js";
|
|
101
|
+
import publicSharedWorkflowRoutes from "./routes/public-shared-workflows.js";
|
|
93
102
|
import { appDeploymentsEnabled } from "./lib/app-deployment-service.js";
|
|
94
103
|
import accountRoutes from "./routes/account.js";
|
|
95
104
|
import jsScriptsRoutes from "./routes/js-scripts.js";
|
|
@@ -98,6 +107,7 @@ import timelineAudioBakeRoutes from "./routes/timeline-audio-bake.js";
|
|
|
98
107
|
import timelineIsolateSubjectRoutes from "./routes/timeline-isolate-subject.js";
|
|
99
108
|
import timelineTrackObjectRoutes from "./routes/timeline-track-object.js";
|
|
100
109
|
import storyboardsRoutes from "./routes/storyboards.js";
|
|
110
|
+
import gamesRoutes from "./routes/games.js";
|
|
101
111
|
import timelinesRoutes from "./routes/timelines.js";
|
|
102
112
|
import documentsRoutes from "./routes/documents.js";
|
|
103
113
|
import sandboxModulesRoutes from "./routes/sandbox-modules.js";
|
|
@@ -110,8 +120,11 @@ import kieWebhookRoute from "./routes/kie-webhook.js";
|
|
|
110
120
|
import falWebhookRoute from "./routes/fal-webhook.js";
|
|
111
121
|
import atlasCloudWebhookRoute from "./routes/atlascloud-webhook.js";
|
|
112
122
|
import { createIntegrationRoutes } from "./routes/integrations.js";
|
|
113
|
-
import {
|
|
114
|
-
import { logTrpcRequestError } from "./trpc/error-logging.js";
|
|
123
|
+
import { isString } from "./lib/wire-values.js";
|
|
124
|
+
import { logTrpcRequestError, traceTrpcRequestError } from "./trpc/error-logging.js";
|
|
125
|
+
import { captureError, startErrorTraceMaintenance } from "./error-traces.js";
|
|
126
|
+
import { detectPipMetadataRoots } from "./lib/python-metadata-roots.js";
|
|
127
|
+
import { getSetting } from "./settings-registry.js";
|
|
115
128
|
// @llamaindex/liteparse bundles a webpack pdf.js whose `isNodeJS` heuristic
|
|
116
129
|
// resolves to false inside Electron utilityProcess (process.type === "utility"),
|
|
117
130
|
// causing it to take browser-only code paths that reference the global `document`
|
|
@@ -145,15 +158,19 @@ const log = createLogger("nodetool.websocket.server");
|
|
|
145
158
|
// initialises eagerly, but an explicit call here picks up any env mutations
|
|
146
159
|
// made by the process launcher before this point).
|
|
147
160
|
configureLogging();
|
|
148
|
-
|
|
161
|
+
// The Python interpreter scan runs while telemetry starts and the database
|
|
162
|
+
// opens and migrates. The node registry below is the first reader.
|
|
163
|
+
const pipMetadataRoots = detectPipMetadataRoots();
|
|
164
|
+
await ensureRunTraceTelemetry();
|
|
149
165
|
const startupT0 = performance.now();
|
|
150
166
|
/**
|
|
151
|
-
* When this process started. A generation row still
|
|
152
|
-
* this moment belongs to a process that is gone, and the
|
|
153
|
-
* (docs/media-generation-tracking-design.md § 6.3).
|
|
167
|
+
* When this process started. A generation or job row still in flight from
|
|
168
|
+
* before this moment belongs to a process that is gone, and the startup sweeps
|
|
169
|
+
* close it (docs/media-generation-tracking-design.md § 6.3).
|
|
154
170
|
*/
|
|
155
171
|
const PROCESS_STARTED_AT = new Date().toISOString();
|
|
156
172
|
let stopGenerationReconcileWorker = null;
|
|
173
|
+
let stopErrorTraceMaintenance = null;
|
|
157
174
|
function startupMs() {
|
|
158
175
|
return `${(performance.now() - startupT0).toFixed(0)}ms`;
|
|
159
176
|
}
|
|
@@ -174,10 +191,7 @@ async function notifyPythonBridgeResourceChanges(app, pythonBridge) {
|
|
|
174
191
|
resource_type: "metadata",
|
|
175
192
|
resource: { id: "nodes", etag: String(Date.now()) }
|
|
176
193
|
});
|
|
177
|
-
const registered = await
|
|
178
|
-
if (registered.length > 0) {
|
|
179
|
-
log.info(`Registered Python providers: ${registered.join(", ")}`);
|
|
180
|
-
}
|
|
194
|
+
const registered = await registerPythonProvidersOnce();
|
|
181
195
|
const discoveredProviders = await pythonBridge.listProviders();
|
|
182
196
|
const registeredProviders = new Set(registered);
|
|
183
197
|
for (const provider of discoveredProviders) {
|
|
@@ -243,7 +257,33 @@ try {
|
|
|
243
257
|
// that need provider credentials bind their own `(key) => getSecret(key,
|
|
244
258
|
// userId)` closure when invoking provider APIs — there is no shared
|
|
245
259
|
// global resolver.
|
|
246
|
-
|
|
260
|
+
//
|
|
261
|
+
// A machine with no keychain (a container, CI, a server without a D-Bus
|
|
262
|
+
// session) cannot unlock the store. The server still starts, the way the
|
|
263
|
+
// CLI commands do: provider keys from the environment keep working, and
|
|
264
|
+
// only reading or writing a stored secret fails. Exiting here made
|
|
265
|
+
// `npx @nodetool-ai/cli serve` unusable on every headless machine.
|
|
266
|
+
try {
|
|
267
|
+
await initMasterKey();
|
|
268
|
+
}
|
|
269
|
+
catch (err) {
|
|
270
|
+
log.warn("Secret store is locked: stored secrets are unavailable, and provider " +
|
|
271
|
+
"keys are read from the environment. Set SECRETS_MASTER_KEY to a " +
|
|
272
|
+
"base64-encoded 32-byte key to enable the store.", { error: err instanceof Error ? err.message : String(err) });
|
|
273
|
+
}
|
|
274
|
+
// Transformers.js fixes its cache directory on first import, which happens
|
|
275
|
+
// after this point, so a directory saved in Settings must be applied now.
|
|
276
|
+
try {
|
|
277
|
+
const tjsCacheDir = await applyTransformersJsCacheSetting(LOCAL_USER_ID);
|
|
278
|
+
if (tjsCacheDir) {
|
|
279
|
+
log.info("Transformers.js cache directory from Settings", { path: tjsCacheDir });
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
catch (err) {
|
|
283
|
+
log.warn("Could not read TRANSFORMERS_JS_CACHE_DIR from Settings", {
|
|
284
|
+
error: err instanceof Error ? err.message : String(err)
|
|
285
|
+
});
|
|
286
|
+
}
|
|
247
287
|
// Bookkeeping for media generations: close the rows a restart orphaned, and
|
|
248
288
|
// keep refining estimates into billed amounts while the server runs.
|
|
249
289
|
void sweepInterruptedGenerations(PROCESS_STARTED_AT).catch((err) => {
|
|
@@ -251,11 +291,19 @@ try {
|
|
|
251
291
|
error: err instanceof Error ? err.message : String(err)
|
|
252
292
|
});
|
|
253
293
|
});
|
|
294
|
+
void sweepInterruptedJobs(PROCESS_STARTED_AT, {
|
|
295
|
+
sharedDatabase: Boolean(postgresDatabaseUrl)
|
|
296
|
+
}).catch((err) => {
|
|
297
|
+
log.warn("Interrupted-job sweep failed", {
|
|
298
|
+
error: err instanceof Error ? err.message : String(err)
|
|
299
|
+
});
|
|
300
|
+
});
|
|
254
301
|
stopGenerationReconcileWorker = startGenerationReconcileWorker({
|
|
255
302
|
resolveSecret: (key, userId) => getSecret(key, userId)
|
|
256
303
|
});
|
|
304
|
+
stopErrorTraceMaintenance = startErrorTraceMaintenance();
|
|
257
305
|
const runHistoryCleanup = () => {
|
|
258
|
-
void
|
|
306
|
+
void runScheduledStorageCleanup(LOCAL_USER_ID)
|
|
259
307
|
.then((result) => {
|
|
260
308
|
if (result && result.total > 0) {
|
|
261
309
|
log.info("Cleaned retained workflow and run history", result);
|
|
@@ -310,73 +358,7 @@ try {
|
|
|
310
358
|
catch (err) {
|
|
311
359
|
log.warn("Custom provider sync failed (non-fatal)", err instanceof Error ? err : new Error(String(err)));
|
|
312
360
|
}
|
|
313
|
-
|
|
314
|
-
// Python pip metadata root detection
|
|
315
|
-
// ---------------------------------------------------------------------------
|
|
316
|
-
function detectPipMetadataRoots() {
|
|
317
|
-
const script = `
|
|
318
|
-
import json, pathlib, subprocess, sys
|
|
319
|
-
roots = set()
|
|
320
|
-
try:
|
|
321
|
-
# Discover all nodetool-* packages
|
|
322
|
-
list_proc = subprocess.run(
|
|
323
|
-
[sys.executable, "-m", "pip", "list", "--format=json"],
|
|
324
|
-
capture_output=True, text=True, check=False,
|
|
325
|
-
)
|
|
326
|
-
pkg_names = [
|
|
327
|
-
p["name"] for p in json.loads(list_proc.stdout or "[]")
|
|
328
|
-
if p["name"].startswith("nodetool-")
|
|
329
|
-
] or ["nodetool-core", "nodetool-base"]
|
|
330
|
-
proc = subprocess.run(
|
|
331
|
-
[sys.executable, "-m", "pip", "show", "-f"] + pkg_names,
|
|
332
|
-
capture_output=True, text=True, check=False,
|
|
333
|
-
)
|
|
334
|
-
output = proc.stdout or ""
|
|
335
|
-
except Exception:
|
|
336
|
-
output = ""
|
|
337
|
-
location = None
|
|
338
|
-
in_files = False
|
|
339
|
-
for raw in output.splitlines():
|
|
340
|
-
line = raw.rstrip("\\n")
|
|
341
|
-
if line.startswith("Name: "):
|
|
342
|
-
location = None; in_files = False; continue
|
|
343
|
-
if line.startswith("Location: "):
|
|
344
|
-
location = line.split(":", 1)[1].strip(); continue
|
|
345
|
-
if line.startswith("Editable project location: "):
|
|
346
|
-
editable = line.split(":", 1)[1].strip()
|
|
347
|
-
if editable: roots.add(editable)
|
|
348
|
-
continue
|
|
349
|
-
if line.startswith("Files:"): in_files = True; continue
|
|
350
|
-
if line.startswith("---"):
|
|
351
|
-
location = None; in_files = False; continue
|
|
352
|
-
if not in_files or not location or not line.startswith(" "): continue
|
|
353
|
-
rel = line.strip().replace("\\\\", "/")
|
|
354
|
-
if "package_metadata" not in rel: continue
|
|
355
|
-
abs_path = (pathlib.Path(location) / rel).resolve()
|
|
356
|
-
metadata_dir = abs_path if abs_path.is_dir() else abs_path.parent
|
|
357
|
-
roots.add(str(metadata_dir))
|
|
358
|
-
print(json.dumps(sorted(roots)))
|
|
359
|
-
`;
|
|
360
|
-
for (const python of ["python3", "python"]) {
|
|
361
|
-
const proc = spawnSync(python, ["-c", script], {
|
|
362
|
-
encoding: "utf8",
|
|
363
|
-
stdio: ["ignore", "pipe", "ignore"]
|
|
364
|
-
});
|
|
365
|
-
if (proc.status !== 0 || !proc.stdout)
|
|
366
|
-
continue;
|
|
367
|
-
try {
|
|
368
|
-
const roots = JSON.parse(proc.stdout.trim());
|
|
369
|
-
if (Array.isArray(roots)) {
|
|
370
|
-
return roots.filter((p) => isNonEmptyString(p) && existsSync(p));
|
|
371
|
-
}
|
|
372
|
-
}
|
|
373
|
-
catch {
|
|
374
|
-
// try next python executable
|
|
375
|
-
}
|
|
376
|
-
}
|
|
377
|
-
return [];
|
|
378
|
-
}
|
|
379
|
-
const metadataRoots = detectPipMetadataRoots();
|
|
361
|
+
const metadataRoots = await pipMetadataRoots;
|
|
380
362
|
// Also scan local TS node packages that have nodetool/package_metadata
|
|
381
363
|
const localPackagesDir = resolve(dirname(fileURLToPath(import.meta.url)), "../../");
|
|
382
364
|
if (existsSync(localPackagesDir)) {
|
|
@@ -419,6 +401,7 @@ log.info(`Node registry ready [${startupMs()}]`);
|
|
|
419
401
|
setCodeNodeAgentsModule(agentsModule);
|
|
420
402
|
if (process.env["NODETOOL_ENV"] !== "production") {
|
|
421
403
|
registerTransformersJsProvider();
|
|
404
|
+
registerWhisperCppProviders();
|
|
422
405
|
}
|
|
423
406
|
// ---------------------------------------------------------------------------
|
|
424
407
|
// Python bridge
|
|
@@ -426,7 +409,8 @@ if (process.env["NODETOOL_ENV"] !== "production") {
|
|
|
426
409
|
const localBridge = createPythonBridge({
|
|
427
410
|
workerArgs: process.env["NODETOOL_WORKER_NAMESPACES"]
|
|
428
411
|
? ["--namespaces", process.env["NODETOOL_WORKER_NAMESPACES"]]
|
|
429
|
-
: []
|
|
412
|
+
: [],
|
|
413
|
+
workerEnv: () => resolveWorkerSettingsEnv(LOCAL_USER_ID)
|
|
430
414
|
});
|
|
431
415
|
// The ONE stable bridge reference handed to every consumer. It delegates to the
|
|
432
416
|
// local bridge by default; attaching a worker swaps in a dedicated WebSocket
|
|
@@ -435,6 +419,19 @@ const localBridge = createPythonBridge({
|
|
|
435
419
|
// stable and re-emits its target's events, consumers never re-read it and
|
|
436
420
|
// listeners are wired exactly once.
|
|
437
421
|
const pythonBridge = new SwappableBridge(localBridge);
|
|
422
|
+
/**
|
|
423
|
+
* Python-only providers (`huggingface-local`) exist only once the worker has
|
|
424
|
+
* listed them. A run that selects one must wait for this, not just for the
|
|
425
|
+
* connection: registration follows the connect, and a run that arrives in
|
|
426
|
+
* between is refused for an unknown provider.
|
|
427
|
+
*/
|
|
428
|
+
const registerPythonProvidersOnce = createProviderRegistrar(async () => {
|
|
429
|
+
const registered = await registerPythonProviders(pythonBridge);
|
|
430
|
+
if (registered.length > 0) {
|
|
431
|
+
log.info(`Registered Python providers: ${registered.join(", ")}`);
|
|
432
|
+
}
|
|
433
|
+
return registered;
|
|
434
|
+
});
|
|
438
435
|
let pythonBridgeReady = false;
|
|
439
436
|
// Worker bridge bookkeeping so it can be closed after swapping away. Only the
|
|
440
437
|
// remote WebSocket bridge is tracked here; the local stdio bridge is owned by
|
|
@@ -642,12 +639,30 @@ const serverOptions = {
|
|
|
642
639
|
}
|
|
643
640
|
};
|
|
644
641
|
const app = Fastify(httpsOptions ? { https: httpsOptions, ...serverOptions } : serverOptions);
|
|
642
|
+
// First hook, so every later hook and handler runs inside the request span.
|
|
645
643
|
// ---------------------------------------------------------------------------
|
|
646
644
|
// Request ID correlation
|
|
647
645
|
// ---------------------------------------------------------------------------
|
|
648
646
|
app.addHook("onRequest", async (request) => {
|
|
649
647
|
request.log.info({ reqId: request.id, method: request.method, url: request.url }, "incoming request");
|
|
650
648
|
});
|
|
649
|
+
// A REST handler that throws a 5xx leaves a redacted trace. 4xx errors are
|
|
650
|
+
// the caller's mistake and are not traced.
|
|
651
|
+
app.addHook("onError", async (request, _reply, error) => {
|
|
652
|
+
const status = error.statusCode ?? 500;
|
|
653
|
+
if (status < 500)
|
|
654
|
+
return;
|
|
655
|
+
captureError(error, {
|
|
656
|
+
source: "http",
|
|
657
|
+
userId: request.userId ?? null,
|
|
658
|
+
context: {
|
|
659
|
+
route: request.routeOptions.url ?? request.url.split("?")[0],
|
|
660
|
+
method: request.method,
|
|
661
|
+
http_status: status,
|
|
662
|
+
request_id: request.id
|
|
663
|
+
}
|
|
664
|
+
});
|
|
665
|
+
});
|
|
651
666
|
app.addHook("onSend", async (request, reply) => {
|
|
652
667
|
reply.header("X-Request-Id", request.id);
|
|
653
668
|
// Baseline security response headers. The web app's CSP lives in a `<meta>`
|
|
@@ -739,6 +754,18 @@ if (enforceAuth && trustLocalhost) {
|
|
|
739
754
|
const trustLocalNetworks = enforceAuth
|
|
740
755
|
? []
|
|
741
756
|
: parseTrustedLocalNetworks(process.env["NODETOOL_TRUST_LOCAL_NETWORKS"]);
|
|
757
|
+
// The bearer token `nodetool deploy` starts a container with. Local mode only,
|
|
758
|
+
// like the trusted networks above: Supabase mode needs a real login.
|
|
759
|
+
const serverAuthToken = enforceAuth
|
|
760
|
+
? null
|
|
761
|
+
: resolveServerAuthToken(process.env["SERVER_AUTH_TOKEN"]);
|
|
762
|
+
// API users created with `nodetool deploy users-add` (the tRPC users router)
|
|
763
|
+
// live in USERS_FILE. Local mode only, for the same reason as the token above.
|
|
764
|
+
const apiUsers = enforceAuth ? null : new FileUserManager();
|
|
765
|
+
if (enforceAuth && process.env["SERVER_AUTH_TOKEN"]) {
|
|
766
|
+
log.warn("SERVER_AUTH_TOKEN is set while auth is enforced (Supabase mode); it is " +
|
|
767
|
+
"ignored. Clients must sign in.");
|
|
768
|
+
}
|
|
742
769
|
if (enforceAuth && process.env["NODETOOL_TRUST_LOCAL_NETWORKS"]) {
|
|
743
770
|
log.warn("NODETOOL_TRUST_LOCAL_NETWORKS is set while auth is enforced (Supabase " +
|
|
744
771
|
"mode); it is ignored so every request must present a valid token.");
|
|
@@ -790,22 +817,16 @@ app.addHook("onRequest", async (req, reply) => {
|
|
|
790
817
|
if (req.method === "OPTIONS")
|
|
791
818
|
return;
|
|
792
819
|
// Public routes — no auth required (still rate-limited globally above).
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
820
|
+
// Match the decoded path the router uses, or `/%61pi/...` skips auth.
|
|
821
|
+
const pathname = routedPathname(req.url);
|
|
822
|
+
if (pathname !== null &&
|
|
823
|
+
(isPublicAuthExemptRoute(pathname, req.method) ||
|
|
824
|
+
(isSdkV1DiscoveryRequest(pathname, req.method) &&
|
|
825
|
+
!isSdkV1AuthenticationRequired(process.env, enforceAuth)))) {
|
|
797
826
|
return;
|
|
798
827
|
}
|
|
799
|
-
// Static frontend assets don't require auth (served by fastifyStatic)
|
|
800
|
-
|
|
801
|
-
// auth so the mount can bind the session's user.
|
|
802
|
-
if (hasStaticApp &&
|
|
803
|
-
req.method === "GET" &&
|
|
804
|
-
!pathname.startsWith("/api") &&
|
|
805
|
-
!pathname.startsWith("/ws") &&
|
|
806
|
-
!pathname.startsWith("/v1") &&
|
|
807
|
-
!pathname.startsWith("/trpc") &&
|
|
808
|
-
!pathname.startsWith("/mcp")) {
|
|
828
|
+
// Static frontend assets don't require auth (served by fastifyStatic).
|
|
829
|
+
if (hasStaticApp && isStaticAppRequest(pathname, req.method)) {
|
|
809
830
|
return;
|
|
810
831
|
}
|
|
811
832
|
// req.ip reflects X-Forwarded-For only when the request arrived through a
|
|
@@ -871,9 +892,8 @@ app.addHook("onRequest", async (req, reply) => {
|
|
|
871
892
|
// application it may act on, and its whole point is that it reaches nothing
|
|
872
893
|
// else — so the confinement is applied right here, at the door, rather than
|
|
873
894
|
// trusted to every handler downstream. `/ws` is the only path it opens: the
|
|
874
|
-
// run transport, and exactly that path — `/ws/download`
|
|
875
|
-
//
|
|
876
|
-
// visitor to somebody's app has any business opening. The public app routes
|
|
895
|
+
// run transport, and exactly that path — `/ws/download` is model downloads,
|
|
896
|
+
// which a visitor to somebody's app has no business opening. The public app routes
|
|
877
897
|
// need no token at all (they are auth-exempt above), and every other path —
|
|
878
898
|
// tRPC, the REST library, assets, settings — is refused, because the
|
|
879
899
|
// owner's account is not what the visitor was given a link to.
|
|
@@ -915,7 +935,7 @@ app.addHook("onRequest", async (req, reply) => {
|
|
|
915
935
|
// /mcp gets a WWW-Authenticate challenge on every unauthenticated/invalid
|
|
916
936
|
// denial below it — but only when the OAuth flow can actually complete
|
|
917
937
|
// (see mcpBearerChallenge). Every other path is unaffected.
|
|
918
|
-
const challenge = pathname
|
|
938
|
+
const challenge = pathname?.startsWith("/mcp")
|
|
919
939
|
? mcpBearerChallenge()
|
|
920
940
|
: undefined;
|
|
921
941
|
if (supabaseMode) {
|
|
@@ -932,8 +952,27 @@ app.addHook("onRequest", async (req, reply) => {
|
|
|
932
952
|
req.authToken = token;
|
|
933
953
|
return;
|
|
934
954
|
}
|
|
955
|
+
if (matchesServerAuthToken(token, serverAuthToken)) {
|
|
956
|
+
req.userId = "1";
|
|
957
|
+
req.authToken = token;
|
|
958
|
+
return;
|
|
959
|
+
}
|
|
960
|
+
const apiUser = token && apiUsers ? await apiUsers.verifyToken(token) : null;
|
|
961
|
+
if (apiUser) {
|
|
962
|
+
req.userId = apiUser.id;
|
|
963
|
+
req.authToken = token;
|
|
964
|
+
return;
|
|
965
|
+
}
|
|
935
966
|
denyUnauthorized(req, reply, { error: "Remote access requires authentication" }, challenge);
|
|
936
967
|
});
|
|
968
|
+
registerHttpTracing(app, {
|
|
969
|
+
async authorizeTraceParent(request, parent) {
|
|
970
|
+
if (!request.userId || request.appSession) {
|
|
971
|
+
return false;
|
|
972
|
+
}
|
|
973
|
+
return Boolean(await getRegisteredRunTrace(request.userId, parent.traceId));
|
|
974
|
+
}
|
|
975
|
+
});
|
|
937
976
|
// Multi-instance only: a handshake asking to resume a run that another machine
|
|
938
977
|
// owns is answered with a fly-replay instruction instead of being accepted
|
|
939
978
|
// here, so the client reconnects onto the process holding the run's session.
|
|
@@ -1176,12 +1215,18 @@ await app.register(fastifyTRPCPlugin, {
|
|
|
1176
1215
|
// flag the server rejects POST-to-query with 405, leaving panels empty.
|
|
1177
1216
|
allowMethodOverride: true,
|
|
1178
1217
|
maxBatchSize: TRPC_MAX_BATCH_SIZE,
|
|
1179
|
-
onError({ path, error, req }) {
|
|
1218
|
+
onError({ path, error, req, ctx }) {
|
|
1180
1219
|
logTrpcRequestError(log, {
|
|
1181
1220
|
path,
|
|
1182
1221
|
error,
|
|
1183
1222
|
requestId: req.id
|
|
1184
1223
|
});
|
|
1224
|
+
traceTrpcRequestError({
|
|
1225
|
+
path,
|
|
1226
|
+
error,
|
|
1227
|
+
requestId: req.id,
|
|
1228
|
+
userId: ctx?.userId
|
|
1229
|
+
});
|
|
1185
1230
|
}
|
|
1186
1231
|
}
|
|
1187
1232
|
});
|
|
@@ -1194,8 +1239,10 @@ await app.register(websocketPlugin, {
|
|
|
1194
1239
|
workerManager,
|
|
1195
1240
|
getPythonBridgeReady,
|
|
1196
1241
|
ensurePythonBridge: async () => {
|
|
1197
|
-
if (getPythonBridgeReady())
|
|
1242
|
+
if (getPythonBridgeReady()) {
|
|
1243
|
+
await registerPythonProvidersOnce();
|
|
1198
1244
|
return;
|
|
1245
|
+
}
|
|
1199
1246
|
log.info(`Lazily starting Python bridge [${startupMs()}]`);
|
|
1200
1247
|
try {
|
|
1201
1248
|
await pythonBridge.ensureConnected();
|
|
@@ -1233,6 +1280,8 @@ await app.register(websocketPlugin, {
|
|
|
1233
1280
|
log.warn(`Failed to fetch Python bridge status [${startupMs()}]`, err instanceof Error ? err : new Error(String(err)));
|
|
1234
1281
|
});
|
|
1235
1282
|
logPythonBridgeDiagnostics("connected");
|
|
1283
|
+
// The run that asked for the bridge may select a Python-only provider.
|
|
1284
|
+
await registerPythonProvidersOnce();
|
|
1236
1285
|
notifyPythonBridgeResourceChanges(app, pythonBridge).catch((err) => {
|
|
1237
1286
|
log.warn("Failed to notify Python bridge resource changes", err instanceof Error ? err : new Error(String(err)));
|
|
1238
1287
|
});
|
|
@@ -1269,14 +1318,18 @@ initWorkspaceStorage();
|
|
|
1269
1318
|
initWorkspaceChangeEvents();
|
|
1270
1319
|
await app.register(filesRoutes, routeOpts);
|
|
1271
1320
|
await app.register(collectionsRoutes, routeOpts);
|
|
1321
|
+
await app.register(appRunsRoutes);
|
|
1322
|
+
await app.register(runSpansRoutes);
|
|
1272
1323
|
await app.register(applicationsRoutes, routeOpts);
|
|
1273
1324
|
await app.register(publicAppRoutes, { appSessionSigningKey });
|
|
1325
|
+
await app.register(publicSharedWorkflowRoutes);
|
|
1274
1326
|
await app.register(jsScriptsRoutes, routeOpts);
|
|
1275
1327
|
await app.register(timelineAnimationRoutes, routeOpts);
|
|
1276
1328
|
await app.register(timelineAudioBakeRoutes, routeOpts);
|
|
1277
1329
|
await app.register(timelineIsolateSubjectRoutes, routeOpts);
|
|
1278
1330
|
await app.register(timelineTrackObjectRoutes, routeOpts);
|
|
1279
1331
|
await app.register(storyboardsRoutes, routeOpts);
|
|
1332
|
+
await app.register(gamesRoutes, routeOpts);
|
|
1280
1333
|
await app.register(timelinesRoutes, routeOpts);
|
|
1281
1334
|
// PDF/DOCX text extraction for script and screenplay imports. Stores
|
|
1282
1335
|
// nothing and needs no apiOptions.
|
|
@@ -1463,6 +1516,10 @@ app.listen({ port, host }, (err) => {
|
|
|
1463
1516
|
}
|
|
1464
1517
|
log.info(`Server listening on ${proto}://${host}:${port} [${startupMs()}]`);
|
|
1465
1518
|
log.info(`WebSocket endpoint: ${tlsEnabled ? "wss" : "ws"}://${host}:${port}/ws`);
|
|
1519
|
+
// When the launcher sets NODE_COMPILE_CACHE, Node writes the V8 code cache
|
|
1520
|
+
// only on a clean exit. Writing it once startup has compiled the server keeps
|
|
1521
|
+
// it for the next start even when this process is killed. No-op otherwise.
|
|
1522
|
+
flushCompileCache();
|
|
1466
1523
|
});
|
|
1467
1524
|
// ---------------------------------------------------------------------------
|
|
1468
1525
|
// Triggers — durable wakeup service, dispatcher, and ingestion adapters
|
|
@@ -1562,6 +1619,7 @@ async function shutdown(signal) {
|
|
|
1562
1619
|
clearInterval(generationRecoveryTimer);
|
|
1563
1620
|
stopJobCancelPoller();
|
|
1564
1621
|
stopGenerationReconcileWorker?.();
|
|
1622
|
+
stopErrorTraceMaintenance?.();
|
|
1565
1623
|
try {
|
|
1566
1624
|
await triggerServices.stop();
|
|
1567
1625
|
}
|
|
@@ -1592,8 +1650,14 @@ process.on("SIGUSR2", () => {
|
|
|
1592
1650
|
if (process.platform === "win32") {
|
|
1593
1651
|
process.on("SIGBREAK", () => void shutdown("SIGBREAK"));
|
|
1594
1652
|
}
|
|
1595
|
-
// Start Python bridge eagerly if a worker is available
|
|
1596
|
-
|
|
1653
|
+
// Start the Python bridge eagerly if a worker is available, unless the user
|
|
1654
|
+
// chose to start it on first use. Runs that need it start it through
|
|
1655
|
+
// `ensurePythonBridge` either way.
|
|
1656
|
+
const pythonOnDemand = (await getSetting("NODETOOL_PYTHON_ON_DEMAND")) === "true";
|
|
1657
|
+
if (pythonBridge.isAvailable() && pythonOnDemand) {
|
|
1658
|
+
log.info("Python bridge starts on first use (NODETOOL_PYTHON_ON_DEMAND=true)");
|
|
1659
|
+
}
|
|
1660
|
+
else if (pythonBridge.isAvailable()) {
|
|
1597
1661
|
log.info(`Starting Python bridge eagerly [${startupMs()}]`);
|
|
1598
1662
|
pythonBridge
|
|
1599
1663
|
.ensureConnected()
|