@nodetool-ai/websocket 0.7.0-rc.22 → 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,1216 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bridges the canonical agent tools (`@nodetool-ai/agents`) onto the MCP server
|
|
3
|
+
* so external agents (Claude Code, ChatGPT, …) get the same surface the in-app
|
|
4
|
+
* chat agent runs on.
|
|
5
|
+
*
|
|
6
|
+
* That surface is CodeAct, not a flat catalog. `execute_code` is built by the
|
|
7
|
+
* same {@link createChatCodeActSession} the chat runner uses. `view_image` and
|
|
8
|
+
* asset transfer stay direct because pixels and file bytes need MCP channels.
|
|
9
|
+
* Every other capability lives inside the sandbox as `tools.<name>()` and the
|
|
10
|
+
* `nodetool.*` object model, found with `nodetool.searchTools()` and catalogued
|
|
11
|
+
* on `nodetool://capabilities` and `nodetool://sandbox`.
|
|
12
|
+
*
|
|
13
|
+
* The bridged set is *derived*, not hand-listed: `getBuiltinTools()` plus
|
|
14
|
+
* `getAllMcpTools()` plus the Google Workspace tools are exactly what
|
|
15
|
+
* `websocket-client-session` assembles for a chat turn, so a tool added to
|
|
16
|
+
* either catalog reaches the sandbox belt with no edit here. Only tools whose
|
|
17
|
+
* constructor needs something the catalogs can't supply (a timeline loader, the
|
|
18
|
+
* lazily probed provider map) are named
|
|
19
|
+
* individually below.
|
|
20
|
+
*/
|
|
21
|
+
import { z } from "zod";
|
|
22
|
+
import { DIRECT_TOOL_NAMES, ProcessingContext as ProcessingContextImpl, SDK_NATIVE_TOOL_REPLACEMENTS, detectImageMime, isSvgBytes, loadMediaRefBytes, zodToJsonSchema } from "@nodetool-ai/runtime";
|
|
23
|
+
import { Tool, CODEACT_RESIDENT_TOOL_NAMES, createChatCodeActSession, getBuiltinTools, getAllMcpTools, getGoogleWorkspaceTools, getApifyTools, getSerpApiTools, capabilityCategoryFor, toolForCapabilityName, UNGATED, createCapabilityRun, contextSecretAvailability, gateTools, headlessGate, EXECUTE_CODE_TOOL_NAME, NODETOOL_API_NAMESPACE_TOOLS, MCP_GUEST_CONTRACT, MCP_SANDBOX_RESOURCE_URI, MCP_SANDBOX_PROMPTS, buildMcpSandboxCatalog, extractInjectableImages, stripImagePayload } from "@nodetool-ai/agents";
|
|
24
|
+
import { FileStorageAdapter } from "@nodetool-ai/storage";
|
|
25
|
+
import { uiToolSchemas } from "@nodetool-ai/protocol";
|
|
26
|
+
import { loadConfiguredProviders } from "./configured-providers.js";
|
|
27
|
+
import { mcpToolHostDeps } from "./mcp-tool-deps.js";
|
|
28
|
+
import { getSecret, Asset, ImageDocument, TimelineSequence } from "@nodetool-ai/models";
|
|
29
|
+
import { WORKFLOW_DOCUMENT_TOOL_NAMES } from "@nodetool-ai/node-sdk";
|
|
30
|
+
import { createLogger, getNodetoolDataDir, isGoogleWorkspaceEnabled } from "@nodetool-ai/config";
|
|
31
|
+
import { basename, dirname, isAbsolute, join } from "node:path";
|
|
32
|
+
import { mkdtemp, readFile, rm, stat, writeFile } from "node:fs/promises";
|
|
33
|
+
import { tmpdir } from "node:os";
|
|
34
|
+
import { execFile as execFileCallback } from "node:child_process";
|
|
35
|
+
import { promisify } from "node:util";
|
|
36
|
+
import { fileURLToPath } from "node:url";
|
|
37
|
+
import sharp from "sharp";
|
|
38
|
+
import { getAssetAdapter } from "./lib/storage.js";
|
|
39
|
+
import { normalizeAssetContentType } from "./lib/asset-paths.js";
|
|
40
|
+
import { createAssetModelInterface, updateAssetBytesModelInterface } from "./lib/asset-model-interface.js";
|
|
41
|
+
import { isRecord, isString } from "./lib/wire-values.js";
|
|
42
|
+
const log = createLogger("nodetool.websocket.mcp-agent-tools");
|
|
43
|
+
const execFile = promisify(execFileCallback);
|
|
44
|
+
/**
|
|
45
|
+
* These capabilities answer readiness questions from the configured-provider
|
|
46
|
+
* map. Populate that map before dispatch so a first workflow call cannot
|
|
47
|
+
* mistake lazy loading for a missing provider.
|
|
48
|
+
*/
|
|
49
|
+
const WORKFLOW_READINESS_TOOL_NAMES = new Set([
|
|
50
|
+
"plan_workflow",
|
|
51
|
+
"update_workflow_plan_step",
|
|
52
|
+
"build_workflow_from_plan"
|
|
53
|
+
]);
|
|
54
|
+
/**
|
|
55
|
+
* Per-user workspace directory the bridged file tools (read_file, write_file,
|
|
56
|
+
* glob, grep, …) are rooted at. Kept under the NodeTool data dir rather than a
|
|
57
|
+
* temp dir because an MCP session is long-lived and spans many calls — a file
|
|
58
|
+
* written on one call has to still be there on the next. One directory per
|
|
59
|
+
* user, so a multi-user mount cannot let one caller read another's files.
|
|
60
|
+
*/
|
|
61
|
+
function mcpWorkspaceDir(userId) {
|
|
62
|
+
// A user id reaches the filesystem as a path segment here, so allow only
|
|
63
|
+
// characters that cannot traverse out of the parent directory.
|
|
64
|
+
const safeUserId = userId.replace(/[^A-Za-z0-9_-]/g, "_") || "default";
|
|
65
|
+
return join(getNodetoolDataDir(), "mcp-workspaces", safeUserId);
|
|
66
|
+
}
|
|
67
|
+
/** Test-only: expose the workspace path rule for isolation assertions. */
|
|
68
|
+
export const __mcpWorkspaceDirForTests = mcpWorkspaceDir;
|
|
69
|
+
/**
|
|
70
|
+
* Build the shared ProcessingContext the bridged tools run against. REST-backed
|
|
71
|
+
* tools (create_workflow, list_models, …) read `NODETOOL_API_URL` from the
|
|
72
|
+
* inherited environment; media tools resolve providers via the secret resolver;
|
|
73
|
+
* save/media tools persist artifacts through `createAsset`; file tools read and
|
|
74
|
+
* write under the session's workspace directory.
|
|
75
|
+
*/
|
|
76
|
+
function buildAgentToolContext(userId) {
|
|
77
|
+
const storage = getAssetAdapter();
|
|
78
|
+
const workspaceDir = mcpWorkspaceDir(userId);
|
|
79
|
+
const context = new ProcessingContextImpl({
|
|
80
|
+
jobId: "mcp-agent-tools",
|
|
81
|
+
userId,
|
|
82
|
+
// Bind secret lookups to the scoped user — never a global default.
|
|
83
|
+
secretResolver: (key) => getSecret(key, userId),
|
|
84
|
+
storage,
|
|
85
|
+
workspaceDir,
|
|
86
|
+
workspaceStorage: new FileStorageAdapter(workspaceDir)
|
|
87
|
+
});
|
|
88
|
+
context.setModelInterfaces({
|
|
89
|
+
createAsset: createAssetModelInterface,
|
|
90
|
+
updateAssetBytes: updateAssetBytesModelInterface,
|
|
91
|
+
getAssetInfo: async ({ userId, assetId }) => {
|
|
92
|
+
const asset = await Asset.find(userId, assetId);
|
|
93
|
+
if (!asset)
|
|
94
|
+
return null;
|
|
95
|
+
return {
|
|
96
|
+
id: asset.id,
|
|
97
|
+
content_type: asset.content_type,
|
|
98
|
+
name: asset.name,
|
|
99
|
+
metadata: asset.metadata ?? null
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
return context;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Read a `timeline_sequences` row for `validate_timeline`. There is no REST
|
|
107
|
+
* route for timelines (the API is tRPC-only), so the tool takes this loader
|
|
108
|
+
* instead of fetching. Ownership is checked the same way the tRPC router's
|
|
109
|
+
* `loadOwned` does — a row belonging to another user reads as not found.
|
|
110
|
+
*/
|
|
111
|
+
const loadTimelineForUser = async (context, id) => {
|
|
112
|
+
const row = await TimelineSequence.findById(id);
|
|
113
|
+
if (!row || row.user_id !== context.userId)
|
|
114
|
+
return null;
|
|
115
|
+
return {
|
|
116
|
+
document: row.document,
|
|
117
|
+
fps: row.fps,
|
|
118
|
+
width: row.width,
|
|
119
|
+
height: row.height,
|
|
120
|
+
name: row.name
|
|
121
|
+
};
|
|
122
|
+
};
|
|
123
|
+
/**
|
|
124
|
+
* Read an `image_documents` row for `validate_sketch`. There is no REST route
|
|
125
|
+
* for sketches (the API is tRPC-only), so the tool takes this loader instead of
|
|
126
|
+
* fetching. Ownership is checked the same way the tRPC router's `loadOwned`
|
|
127
|
+
* does — a row belonging to another user reads as not found.
|
|
128
|
+
*/
|
|
129
|
+
const loadSketchForUser = async (context, id) => {
|
|
130
|
+
const row = await ImageDocument.findById(id);
|
|
131
|
+
if (!row || row.user_id !== context.userId)
|
|
132
|
+
return null;
|
|
133
|
+
return {
|
|
134
|
+
document: row.document,
|
|
135
|
+
width: row.width,
|
|
136
|
+
height: row.height,
|
|
137
|
+
backgroundColor: row.background_color,
|
|
138
|
+
name: row.name
|
|
139
|
+
};
|
|
140
|
+
};
|
|
141
|
+
/** Test-only: expose the per-user context construction for scope assertions. */
|
|
142
|
+
export const __buildAgentToolContextForTests = (userId) => buildAgentToolContext(userId);
|
|
143
|
+
// ── JSON Schema → Zod shape ─────────────────────────────────────────
|
|
144
|
+
//
|
|
145
|
+
// The agent tools declare plain JSON-Schema; the MCP SDK's `server.tool`
|
|
146
|
+
// wants a Zod raw shape. These converters cover the property kinds the tools
|
|
147
|
+
// actually use (string/number/boolean/array/object, enums, defaults).
|
|
148
|
+
function jsonSchemaPropToZod(prop) {
|
|
149
|
+
const type = prop["type"];
|
|
150
|
+
switch (type) {
|
|
151
|
+
case "string": {
|
|
152
|
+
const values = prop["enum"];
|
|
153
|
+
if (Array.isArray(values) &&
|
|
154
|
+
values.every((v) => isString(v)) &&
|
|
155
|
+
values.length > 0) {
|
|
156
|
+
return z.enum(values);
|
|
157
|
+
}
|
|
158
|
+
return z.string();
|
|
159
|
+
}
|
|
160
|
+
case "number":
|
|
161
|
+
case "integer":
|
|
162
|
+
return z.number();
|
|
163
|
+
case "boolean":
|
|
164
|
+
return z.boolean();
|
|
165
|
+
case "array": {
|
|
166
|
+
const items = prop["items"];
|
|
167
|
+
return z.array(items ? jsonSchemaPropToZod(items) : z.unknown());
|
|
168
|
+
}
|
|
169
|
+
case "object":
|
|
170
|
+
return z.record(z.string(), z.unknown());
|
|
171
|
+
default:
|
|
172
|
+
return z.unknown();
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
function jsonSchemaToZodShape(schema) {
|
|
176
|
+
const shape = {};
|
|
177
|
+
const s = schema;
|
|
178
|
+
if (!s || s["type"] !== "object")
|
|
179
|
+
return shape;
|
|
180
|
+
const properties = s["properties"];
|
|
181
|
+
if (!properties)
|
|
182
|
+
return shape;
|
|
183
|
+
const required = new Set(Array.isArray(s["required"]) ? s["required"] : []);
|
|
184
|
+
for (const [key, prop] of Object.entries(properties)) {
|
|
185
|
+
let zt = jsonSchemaPropToZod(prop);
|
|
186
|
+
if (isString(prop["description"])) {
|
|
187
|
+
zt = zt.describe(prop["description"]);
|
|
188
|
+
}
|
|
189
|
+
if ("default" in prop) {
|
|
190
|
+
zt = zt.default(prop["default"]);
|
|
191
|
+
}
|
|
192
|
+
else if (!required.has(key)) {
|
|
193
|
+
zt = zt.optional();
|
|
194
|
+
}
|
|
195
|
+
shape[key] = zt;
|
|
196
|
+
}
|
|
197
|
+
return shape;
|
|
198
|
+
}
|
|
199
|
+
// ── MCP response helpers ────────────────────────────────────────────
|
|
200
|
+
function isErrorResult(result) {
|
|
201
|
+
if (!isRecord(result))
|
|
202
|
+
return false;
|
|
203
|
+
const r = result;
|
|
204
|
+
return Boolean(r["error"]) || r["success"] === false;
|
|
205
|
+
}
|
|
206
|
+
function toToolResponse(result) {
|
|
207
|
+
const isObject = isRecord(result);
|
|
208
|
+
const isError = isErrorResult(result);
|
|
209
|
+
const base = {
|
|
210
|
+
content: [{ type: "text", text: JSON.stringify(result ?? null) }]
|
|
211
|
+
};
|
|
212
|
+
const withError = isError ? { ...base, isError: true } : base;
|
|
213
|
+
return isObject && !isError
|
|
214
|
+
? { ...withError, structuredContent: result }
|
|
215
|
+
: withError;
|
|
216
|
+
}
|
|
217
|
+
async function toImageToolResponse(result, context) {
|
|
218
|
+
const extracted = extractInjectableImages(result);
|
|
219
|
+
if (!extracted || isErrorResult(result)) {
|
|
220
|
+
return toToolResponse(result);
|
|
221
|
+
}
|
|
222
|
+
const response = toToolResponse(stripImagePayload(result));
|
|
223
|
+
const images = await Promise.all(extracted.images.map(async ({ image }) => {
|
|
224
|
+
const bytes = await loadMediaRefBytes(image, context);
|
|
225
|
+
if (!bytes?.length) {
|
|
226
|
+
throw new Error("Could not load image bytes for the MCP response.");
|
|
227
|
+
}
|
|
228
|
+
return {
|
|
229
|
+
type: "image",
|
|
230
|
+
data: Buffer.from(bytes).toString("base64"),
|
|
231
|
+
mimeType: detectImageMime(bytes)
|
|
232
|
+
};
|
|
233
|
+
}));
|
|
234
|
+
return { ...response, content: [...response.content, ...images] };
|
|
235
|
+
}
|
|
236
|
+
function errorResponse(err) {
|
|
237
|
+
return {
|
|
238
|
+
content: [
|
|
239
|
+
{
|
|
240
|
+
type: "text",
|
|
241
|
+
text: JSON.stringify({
|
|
242
|
+
error: err instanceof Error ? err.message : String(err)
|
|
243
|
+
})
|
|
244
|
+
}
|
|
245
|
+
],
|
|
246
|
+
isError: true
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Every agent tool the bridge offers, in registration order. Derived from the
|
|
251
|
+
* same catalogs `websocket-client-session` assembles a chat toolbelt from, so
|
|
252
|
+
* the two surfaces cannot drift.
|
|
253
|
+
*
|
|
254
|
+
* `providers` is the map `find_model` and `list_models` read at call time — it
|
|
255
|
+
* is passed by reference and filled in lazily, so it is empty here.
|
|
256
|
+
*/
|
|
257
|
+
function collectBridgedTools(options, providers) {
|
|
258
|
+
return [
|
|
259
|
+
// The chat agent's built-ins: files, search, browser, PDF, vision,
|
|
260
|
+
// critique, memory, asset library, todo.
|
|
261
|
+
...getBuiltinTools(),
|
|
262
|
+
// Workflow / node / job / asset / app tools. The read tools among them
|
|
263
|
+
// (list_workflows, get_asset, …)
|
|
264
|
+
// collide with the native registrations and are skipped by the caller.
|
|
265
|
+
// Thread this mount's own configuration into the host deps — a server
|
|
266
|
+
// configured with a non-default examples dir or metadata roots must not
|
|
267
|
+
// silently fall back to the defaults.
|
|
268
|
+
...getAllMcpTools({
|
|
269
|
+
registry: options?.registry,
|
|
270
|
+
...mcpToolHostDeps({
|
|
271
|
+
registry: options?.registry,
|
|
272
|
+
metadataRoots: options?.metadataRoots,
|
|
273
|
+
metadataMaxDepth: options?.metadataMaxDepth,
|
|
274
|
+
examplesDir: options?.examplesDir
|
|
275
|
+
})
|
|
276
|
+
}),
|
|
277
|
+
// Google Workspace runs on the token from the user's Google sign-in, so it
|
|
278
|
+
// only exists on deployments that have a login — same gate the runner uses.
|
|
279
|
+
...(isGoogleWorkspaceEnabled() ? getGoogleWorkspaceTools() : []),
|
|
280
|
+
// Apify and SerpAPI: same belt the chat runner offers. The gate is not
|
|
281
|
+
// set here: `registerAgentMcpTools` wraps the whole belt in `gateTools`,
|
|
282
|
+
// so these run past the same ladder as everything else.
|
|
283
|
+
...getApifyTools(),
|
|
284
|
+
...getSerpApiTools(),
|
|
285
|
+
// Timelines have no REST route (the API is tRPC-only), so this capability
|
|
286
|
+
// reads a loader off the run instead of fetching, and `getAllMcpTools`
|
|
287
|
+
// cannot build it.
|
|
288
|
+
// `UNGATED` on the inner run, because the belt-level `gateTools` wrapper
|
|
289
|
+
// is what carries this mount's gate — a second ladder here would decide
|
|
290
|
+
// the same call twice. The run exists for the loader, not for permissions.
|
|
291
|
+
toolForCapabilityName("validate_timeline", (context) => createCapabilityRun({
|
|
292
|
+
context,
|
|
293
|
+
gate: UNGATED,
|
|
294
|
+
availableSecrets: contextSecretAvailability(context),
|
|
295
|
+
loaders: { timeline: loadTimelineForUser }
|
|
296
|
+
})),
|
|
297
|
+
// Sketches are tRPC-only too, so this one reads a loader for the same
|
|
298
|
+
// reason and `getAllMcpTools` cannot build it either.
|
|
299
|
+
toolForCapabilityName("validate_sketch", (context) => createCapabilityRun({
|
|
300
|
+
context,
|
|
301
|
+
gate: UNGATED,
|
|
302
|
+
availableSecrets: contextSecretAvailability(context),
|
|
303
|
+
loaders: { sketch: loadSketchForUser }
|
|
304
|
+
})),
|
|
305
|
+
// `getAllMcpTools` only offers the media tools when handed a populated
|
|
306
|
+
// provider map. Here they resolve providers from the scoped user's secrets
|
|
307
|
+
// at call time, so offer them unconditionally rather than probing every
|
|
308
|
+
// provider during server construction.
|
|
309
|
+
...[
|
|
310
|
+
"generate_image",
|
|
311
|
+
"edit_image",
|
|
312
|
+
"generate_video",
|
|
313
|
+
"animate_image",
|
|
314
|
+
"generate_speech",
|
|
315
|
+
"transcribe_audio",
|
|
316
|
+
"embed_text"
|
|
317
|
+
].map((name) => toolForCapabilityName(name)),
|
|
318
|
+
...["find_model", "list_models"].map((name) => toolForCapabilityName(name, (context) => createCapabilityRun({
|
|
319
|
+
context,
|
|
320
|
+
gate: UNGATED,
|
|
321
|
+
availableSecrets: contextSecretAvailability(context),
|
|
322
|
+
providers
|
|
323
|
+
})))
|
|
324
|
+
];
|
|
325
|
+
}
|
|
326
|
+
/**
|
|
327
|
+
* The gate an MCP session runs under: `auto`, denying every escalation the
|
|
328
|
+
* ladder raises, with one standing approval.
|
|
329
|
+
*
|
|
330
|
+
* `auto` is D4 — a client's user connected this agent deliberately, and the
|
|
331
|
+
* session has no approval UI of its own, so a gate that could ask would only
|
|
332
|
+
* deadlock. The approver therefore denies: resolving `"allow"` would grant
|
|
333
|
+
* exactly what an escalation exists to withhold, and never resolving would
|
|
334
|
+
* hang the run (invariant I-4).
|
|
335
|
+
*
|
|
336
|
+
* The exception is `execute_code` itself, seeded into `sessionAllow`. Every
|
|
337
|
+
* action arrives as an MCP tool call the *client* put in front of its user —
|
|
338
|
+
* with the code in it — before sending it, and `sessionAllow` is the ladder's
|
|
339
|
+
* own channel for "the user already said yes". Without the seed,
|
|
340
|
+
* `admitCodeAction` would refuse every action that does not declare
|
|
341
|
+
* `risk: "low"` (an omitted declaration reads as `high`), which is most of
|
|
342
|
+
* them: the mount would answer and never act. Escalations raised *inside* a
|
|
343
|
+
* run — an Apify actor this install has not allowlisted, a security-monitor
|
|
344
|
+
* consult — are a different matter and still deny, because nothing here can
|
|
345
|
+
* put those in front of that user.
|
|
346
|
+
*/
|
|
347
|
+
function mcpSessionGate() {
|
|
348
|
+
const gate = headlessGate("MCP");
|
|
349
|
+
gate.sessionAllow.add(EXECUTE_CODE_TOOL_NAME);
|
|
350
|
+
return gate;
|
|
351
|
+
}
|
|
352
|
+
/** URI of the structured capability catalog this mount publishes. */
|
|
353
|
+
export const MCP_CAPABILITIES_RESOURCE_URI = "nodetool://capabilities";
|
|
354
|
+
/** URI of the guest-JS surface this mount publishes. Re-exported for callers. */
|
|
355
|
+
export { MCP_SANDBOX_RESOURCE_URI };
|
|
356
|
+
const RENDERER_ID_PROPERTY = {
|
|
357
|
+
type: "string",
|
|
358
|
+
description: "Target a specific connected NodeTool editor. Omit to use the " +
|
|
359
|
+
"most-recently-active one. List ids with list_renderers()."
|
|
360
|
+
};
|
|
361
|
+
function recordValue(value) {
|
|
362
|
+
return isRecord(value) ? value : {};
|
|
363
|
+
}
|
|
364
|
+
async function executeFrontendTool(options, userId, name, args) {
|
|
365
|
+
const registry = options.frontendRendererRegistry;
|
|
366
|
+
if (!registry)
|
|
367
|
+
return { handled: false };
|
|
368
|
+
const { renderer_id, ...toolArgs } = args;
|
|
369
|
+
return registry.execute({
|
|
370
|
+
userId,
|
|
371
|
+
rendererId: isString(renderer_id) ? renderer_id : undefined,
|
|
372
|
+
toolName: name,
|
|
373
|
+
args: toolArgs
|
|
374
|
+
});
|
|
375
|
+
}
|
|
376
|
+
/** Import a local file or a URL into the current user's asset library. */
|
|
377
|
+
class ImportAssetTool extends Tool {
|
|
378
|
+
localFilePathsAllowed;
|
|
379
|
+
name = "import_asset";
|
|
380
|
+
description = "Import a local file on a local MCP connection or an http(s) URL as a NodeTool asset. Returns its asset URI, size and media duration.";
|
|
381
|
+
jsonSchema = {
|
|
382
|
+
type: "object",
|
|
383
|
+
properties: {
|
|
384
|
+
path: {
|
|
385
|
+
type: "string",
|
|
386
|
+
description: "Absolute server-local path; local connections only."
|
|
387
|
+
},
|
|
388
|
+
url: { type: "string", description: "HTTP or HTTPS URL to fetch." },
|
|
389
|
+
name: { type: "string", description: "Optional asset name." },
|
|
390
|
+
content_type: { type: "string", description: "Optional MIME type." }
|
|
391
|
+
},
|
|
392
|
+
required: []
|
|
393
|
+
};
|
|
394
|
+
constructor(localFilePathsAllowed) {
|
|
395
|
+
super();
|
|
396
|
+
this.localFilePathsAllowed = localFilePathsAllowed;
|
|
397
|
+
}
|
|
398
|
+
async process(context, params) {
|
|
399
|
+
const path = params["path"];
|
|
400
|
+
const url = params["url"];
|
|
401
|
+
if (isString(path) === isString(url)) {
|
|
402
|
+
throw new Error("Provide exactly one of path or url.");
|
|
403
|
+
}
|
|
404
|
+
if (isString(path) && (!this.localFilePathsAllowed || !isAbsolute(path))) {
|
|
405
|
+
throw new Error("path requires an absolute path on a local MCP connection.");
|
|
406
|
+
}
|
|
407
|
+
if (isString(url) && !/^https?:\/\//.test(url)) {
|
|
408
|
+
throw new Error("url must be an HTTP or HTTPS URL.");
|
|
409
|
+
}
|
|
410
|
+
const sourceName = isString(path)
|
|
411
|
+
? basename(path)
|
|
412
|
+
: basename(new URL(url).pathname) || "download";
|
|
413
|
+
const name = isString(params["name"]) && params["name"].trim()
|
|
414
|
+
? params["name"].trim()
|
|
415
|
+
: sourceName;
|
|
416
|
+
let result;
|
|
417
|
+
if (isString(path)) {
|
|
418
|
+
const bytes = await readFile(path);
|
|
419
|
+
const asset = await createAssetModelInterface({
|
|
420
|
+
userId: context.userId,
|
|
421
|
+
name,
|
|
422
|
+
contentType: isString(params["content_type"])
|
|
423
|
+
? params["content_type"]
|
|
424
|
+
: "",
|
|
425
|
+
content: bytes
|
|
426
|
+
});
|
|
427
|
+
result = {
|
|
428
|
+
asset_id: asset.id,
|
|
429
|
+
asset_uri: `asset://${asset.id}`,
|
|
430
|
+
size: bytes.length
|
|
431
|
+
};
|
|
432
|
+
}
|
|
433
|
+
else {
|
|
434
|
+
const saveParams = {
|
|
435
|
+
name,
|
|
436
|
+
source: url
|
|
437
|
+
};
|
|
438
|
+
if (isString(params["content_type"])) {
|
|
439
|
+
saveParams["content_type"] = params["content_type"];
|
|
440
|
+
}
|
|
441
|
+
result = await toolForCapabilityName("save_asset").process(context, saveParams);
|
|
442
|
+
}
|
|
443
|
+
if (!isRecord(result) || !isString(result["asset_id"]))
|
|
444
|
+
return result;
|
|
445
|
+
const asset = await Asset.find(context.userId, result["asset_id"]);
|
|
446
|
+
if (!asset)
|
|
447
|
+
return result;
|
|
448
|
+
return {
|
|
449
|
+
...result,
|
|
450
|
+
asset_uri: `asset://${asset.id}`,
|
|
451
|
+
content_type: normalizeAssetContentType(asset.content_type, asset.name),
|
|
452
|
+
size: asset.size,
|
|
453
|
+
duration: asset.duration
|
|
454
|
+
};
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
class RenderDemoSurfaceTool extends Tool {
|
|
458
|
+
name = "render_demo_surface";
|
|
459
|
+
description = "Render a NodeTool product surface as a silent video asset. Cast IDs: chat hero-brief or chat-agent-qa; storyboard hero-storyboard or storyboard-assistant; script script-assistant; sketch sketch-assistant; timeline hero-timeline or promo-timeline; graph promo-trailer. A range plays at recorded speed unless duration_ms compresses it. For exact frame matching at 30 fps, duration_ms may be a multiple of 1000/30; sample_span_frames selects the cast range's interpolation span independently of output length. Available from a NodeTool source checkout with the demo renderer installed.";
|
|
460
|
+
jsonSchema = {
|
|
461
|
+
type: "object",
|
|
462
|
+
properties: {
|
|
463
|
+
surface: {
|
|
464
|
+
type: "string",
|
|
465
|
+
enum: ["chat", "storyboard", "script", "sketch", "timeline", "graph", "3d"]
|
|
466
|
+
},
|
|
467
|
+
cast_id: {
|
|
468
|
+
type: "string",
|
|
469
|
+
description: "Cast ID for the selected surface. See the tool description for valid IDs."
|
|
470
|
+
},
|
|
471
|
+
from_ms: {
|
|
472
|
+
type: "number",
|
|
473
|
+
description: "Source range start in milliseconds; provide with to_ms."
|
|
474
|
+
},
|
|
475
|
+
to_ms: {
|
|
476
|
+
type: "number",
|
|
477
|
+
description: "Source range end in milliseconds; provide with from_ms."
|
|
478
|
+
},
|
|
479
|
+
duration_ms: { type: "number", description: "Output duration in milliseconds for a ranged cast; compresses or expands the selected range." },
|
|
480
|
+
sample_span_frames: { type: "number", description: "Frame span from source range start to end. Defaults to output frame count minus one. Use 79 for the sizzle montage's cast clock." },
|
|
481
|
+
logical_width: { type: "number", description: "CSS layout width of the product surface before scaling to the output width." },
|
|
482
|
+
output_width: { type: "number", description: "Even output video width in pixels." },
|
|
483
|
+
output_height: { type: "number", description: "Even output video height in pixels." },
|
|
484
|
+
viewport: { type: "object", description: "Graph viewport {x, y, zoom} in logical surface pixels.", properties: { x: { type: "number" }, y: { type: "number" }, zoom: { type: "number" } }, required: ["x", "y", "zoom"] },
|
|
485
|
+
tracks_height_px: { type: "number", description: "Timeline track area height in logical CSS pixels." },
|
|
486
|
+
chrome: { type: "boolean", description: "Show timeline editor chrome; defaults to false." },
|
|
487
|
+
label: {
|
|
488
|
+
type: "boolean",
|
|
489
|
+
description: "Show the corner label; defaults to false."
|
|
490
|
+
}
|
|
491
|
+
},
|
|
492
|
+
required: ["surface"]
|
|
493
|
+
};
|
|
494
|
+
async process(context, params) {
|
|
495
|
+
const surface = params["surface"];
|
|
496
|
+
if (!isString(surface) ||
|
|
497
|
+
!["chat", "storyboard", "script", "sketch", "timeline", "graph", "3d"].includes(surface)) {
|
|
498
|
+
throw new Error("surface must be chat, storyboard, script, sketch, timeline, graph or 3d.");
|
|
499
|
+
}
|
|
500
|
+
const fromMs = params["from_ms"];
|
|
501
|
+
const toMs = params["to_ms"];
|
|
502
|
+
if (fromMs !== undefined &&
|
|
503
|
+
(typeof fromMs !== "number" || !Number.isFinite(fromMs) || fromMs < 0)) {
|
|
504
|
+
throw new Error("from_ms must be a nonnegative number.");
|
|
505
|
+
}
|
|
506
|
+
if (toMs !== undefined &&
|
|
507
|
+
(typeof toMs !== "number" || !Number.isFinite(toMs) || toMs <= 0)) {
|
|
508
|
+
throw new Error("to_ms must be a positive number.");
|
|
509
|
+
}
|
|
510
|
+
if (typeof fromMs === "number" &&
|
|
511
|
+
typeof toMs === "number" &&
|
|
512
|
+
toMs <= fromMs) {
|
|
513
|
+
throw new Error("to_ms must exceed from_ms.");
|
|
514
|
+
}
|
|
515
|
+
if ((fromMs === undefined) !== (toMs === undefined)) {
|
|
516
|
+
throw new Error("from_ms and to_ms must be supplied together.");
|
|
517
|
+
}
|
|
518
|
+
if (surface === "3d" && typeof toMs === "number" && toMs > 6000) {
|
|
519
|
+
throw new Error("The 3d surface range must end by 6000 ms.");
|
|
520
|
+
}
|
|
521
|
+
const casts = {
|
|
522
|
+
chat: ["hero-brief", "chat-agent-qa"],
|
|
523
|
+
storyboard: ["hero-storyboard", "storyboard-assistant"],
|
|
524
|
+
script: ["script-assistant"],
|
|
525
|
+
sketch: ["sketch-assistant"],
|
|
526
|
+
timeline: ["hero-timeline", "promo-timeline"],
|
|
527
|
+
graph: ["promo-trailer"],
|
|
528
|
+
"3d": []
|
|
529
|
+
};
|
|
530
|
+
const castId = params["cast_id"];
|
|
531
|
+
if (castId !== undefined && (!isString(castId) || !casts[surface]?.includes(castId))) {
|
|
532
|
+
throw new Error(`cast_id for ${surface} must be one of: ${casts[surface]?.join(", ") || "none"}.`);
|
|
533
|
+
}
|
|
534
|
+
const durationMs = params["duration_ms"];
|
|
535
|
+
if (durationMs !== undefined &&
|
|
536
|
+
(typeof durationMs !== "number" || !Number.isFinite(durationMs) || durationMs <= 0 || typeof fromMs !== "number")) {
|
|
537
|
+
throw new Error("duration_ms requires a source range and must be positive.");
|
|
538
|
+
}
|
|
539
|
+
const sampleSpanFrames = params["sample_span_frames"];
|
|
540
|
+
if (sampleSpanFrames !== undefined &&
|
|
541
|
+
(typeof sampleSpanFrames !== "number" || !Number.isInteger(sampleSpanFrames) || sampleSpanFrames <= 0 || typeof fromMs !== "number")) {
|
|
542
|
+
throw new Error("sample_span_frames requires a source range and must be a positive integer.");
|
|
543
|
+
}
|
|
544
|
+
for (const key of ["logical_width", "tracks_height_px"]) {
|
|
545
|
+
const value = params[key];
|
|
546
|
+
if (value !== undefined && (typeof value !== "number" || !Number.isFinite(value) || value <= 0)) {
|
|
547
|
+
throw new Error(`${key} must be a positive number.`);
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
for (const key of ["output_width", "output_height"]) {
|
|
551
|
+
const value = params[key];
|
|
552
|
+
if (value !== undefined && (typeof value !== "number" || !Number.isInteger(value) || value <= 0 || value % 2 !== 0)) {
|
|
553
|
+
throw new Error(`${key} must be a positive even integer.`);
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
const viewport = params["viewport"];
|
|
557
|
+
if (viewport !== undefined &&
|
|
558
|
+
(surface !== "graph" || !isRecord(viewport) ||
|
|
559
|
+
["x", "y", "zoom"].some((key) => typeof viewport[key] !== "number" || !Number.isFinite(viewport[key])) ||
|
|
560
|
+
typeof viewport["zoom"] !== "number" || viewport["zoom"] <= 0)) {
|
|
561
|
+
throw new Error("viewport requires graph and finite x, y and positive zoom.");
|
|
562
|
+
}
|
|
563
|
+
if (params["tracks_height_px"] !== undefined && surface !== "timeline") {
|
|
564
|
+
throw new Error("tracks_height_px requires the timeline surface.");
|
|
565
|
+
}
|
|
566
|
+
const demoDir = join(dirname(fileURLToPath(import.meta.url)), "../../../demo");
|
|
567
|
+
const renderer = join(demoDir, "../node_modules/.bin/remotion");
|
|
568
|
+
try {
|
|
569
|
+
await stat(renderer);
|
|
570
|
+
await stat(join(demoDir, "src/index.ts"));
|
|
571
|
+
}
|
|
572
|
+
catch {
|
|
573
|
+
throw new Error("The demo renderer is unavailable on this NodeTool server.");
|
|
574
|
+
}
|
|
575
|
+
const props = {};
|
|
576
|
+
if (isString(castId))
|
|
577
|
+
props["castId"] = castId;
|
|
578
|
+
if (typeof fromMs === "number")
|
|
579
|
+
props["fromMs"] = fromMs;
|
|
580
|
+
if (typeof toMs === "number")
|
|
581
|
+
props["toMs"] = toMs;
|
|
582
|
+
if (typeof durationMs === "number") {
|
|
583
|
+
props["durationMs"] = durationMs;
|
|
584
|
+
props["realtime"] = false;
|
|
585
|
+
}
|
|
586
|
+
if (typeof sampleSpanFrames === "number")
|
|
587
|
+
props["sampleSpanFrames"] = sampleSpanFrames;
|
|
588
|
+
if (typeof params["logical_width"] === "number")
|
|
589
|
+
props["logicalWidth"] = params["logical_width"];
|
|
590
|
+
if (typeof params["output_width"] === "number")
|
|
591
|
+
props["outputWidth"] = params["output_width"];
|
|
592
|
+
if (typeof params["output_height"] === "number")
|
|
593
|
+
props["outputHeight"] = params["output_height"];
|
|
594
|
+
if (viewport !== undefined)
|
|
595
|
+
props["viewport"] = viewport;
|
|
596
|
+
if (typeof params["tracks_height_px"] === "number")
|
|
597
|
+
props["tracksHeightPx"] = params["tracks_height_px"];
|
|
598
|
+
if (typeof params["chrome"] === "boolean")
|
|
599
|
+
props["chrome"] = params["chrome"];
|
|
600
|
+
const ranged = typeof fromMs === "number";
|
|
601
|
+
if (ranged)
|
|
602
|
+
props["labelVisible"] = params["label"] === true;
|
|
603
|
+
const composition = `Surface-${surface}${ranged ? "-Harness" : params["label"] === true ? "" : "-Clean"}`;
|
|
604
|
+
const directory = await mkdtemp(join(tmpdir(), "nodetool-surface-"));
|
|
605
|
+
const output = join(directory, `${surface}.mp4`);
|
|
606
|
+
try {
|
|
607
|
+
await execFile(renderer, [
|
|
608
|
+
"render",
|
|
609
|
+
"src/index.ts",
|
|
610
|
+
composition,
|
|
611
|
+
output,
|
|
612
|
+
"--props",
|
|
613
|
+
JSON.stringify(props),
|
|
614
|
+
...(surface === "3d" ? ["--gl=angle"] : [])
|
|
615
|
+
], {
|
|
616
|
+
cwd: demoDir,
|
|
617
|
+
timeout: 300_000,
|
|
618
|
+
maxBuffer: 2 * 1024 * 1024
|
|
619
|
+
});
|
|
620
|
+
const bytes = await readFile(output);
|
|
621
|
+
const asset = await createAssetModelInterface({
|
|
622
|
+
userId: context.userId,
|
|
623
|
+
name: `${surface}-surface.mp4`,
|
|
624
|
+
contentType: "video/mp4",
|
|
625
|
+
content: bytes
|
|
626
|
+
});
|
|
627
|
+
return {
|
|
628
|
+
asset_id: asset.id,
|
|
629
|
+
asset_uri: `asset://${asset.id}`,
|
|
630
|
+
duration: asset.duration,
|
|
631
|
+
size: asset.size,
|
|
632
|
+
content_type: asset.content_type
|
|
633
|
+
};
|
|
634
|
+
}
|
|
635
|
+
finally {
|
|
636
|
+
await rm(directory, { recursive: true, force: true });
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
}
|
|
640
|
+
/** A `ui_*` request that must be handled by a connected editor. */
|
|
641
|
+
class FrontendUiTool extends Tool {
|
|
642
|
+
options;
|
|
643
|
+
userId;
|
|
644
|
+
name;
|
|
645
|
+
description;
|
|
646
|
+
jsonSchema;
|
|
647
|
+
constructor(name, description, jsonSchema, options, userId) {
|
|
648
|
+
super();
|
|
649
|
+
this.options = options;
|
|
650
|
+
this.userId = userId;
|
|
651
|
+
this.name = name;
|
|
652
|
+
this.description = description;
|
|
653
|
+
this.jsonSchema = jsonSchema;
|
|
654
|
+
}
|
|
655
|
+
// HOLDOUT (anti-slop/no-unknown-returns): a bridged tool's result is
|
|
656
|
+
// whatever the editor or capability answered — the open tool-result domain
|
|
657
|
+
// the base `Tool.process` contract in `@nodetool-ai/agents` declares.
|
|
658
|
+
async process(_context, params) {
|
|
659
|
+
const outcome = await executeFrontendTool(this.options, this.userId, this.name, params);
|
|
660
|
+
if (!outcome.handled) {
|
|
661
|
+
const rendererId = params["renderer_id"];
|
|
662
|
+
throw new Error(isString(rendererId)
|
|
663
|
+
? `No connected NodeTool renderer with id "${rendererId}".`
|
|
664
|
+
: `${this.name} needs a connected NodeTool editor; none is open.`);
|
|
665
|
+
}
|
|
666
|
+
return outcome.result;
|
|
667
|
+
}
|
|
668
|
+
}
|
|
669
|
+
/** Adds the optional renderer selector to a workflow document tool schema. */
|
|
670
|
+
class RendererAwareDocumentTool extends Tool {
|
|
671
|
+
delegate;
|
|
672
|
+
name;
|
|
673
|
+
description;
|
|
674
|
+
jsonSchema;
|
|
675
|
+
constructor(delegate) {
|
|
676
|
+
super();
|
|
677
|
+
this.delegate = delegate;
|
|
678
|
+
this.name = delegate.name;
|
|
679
|
+
this.description = delegate.description;
|
|
680
|
+
const schema = delegate.inputSchema;
|
|
681
|
+
this.jsonSchema = {
|
|
682
|
+
...schema,
|
|
683
|
+
type: "object",
|
|
684
|
+
properties: {
|
|
685
|
+
...recordValue(schema["properties"]),
|
|
686
|
+
renderer_id: RENDERER_ID_PROPERTY
|
|
687
|
+
}
|
|
688
|
+
};
|
|
689
|
+
}
|
|
690
|
+
// HOLDOUT (anti-slop/no-unknown-returns): the result is the delegate's, and
|
|
691
|
+
// `Tool.process` in `@nodetool-ai/agents` declares `Promise<unknown>`.
|
|
692
|
+
async process(context, params) {
|
|
693
|
+
const { renderer_id: _rendererId, ...serverArgs } = params;
|
|
694
|
+
return this.delegate.process(context, serverArgs);
|
|
695
|
+
}
|
|
696
|
+
}
|
|
697
|
+
/** `list_renderers` as a belt tool: which editors a `ui_*` call could target. */
|
|
698
|
+
class ListRenderersTool extends Tool {
|
|
699
|
+
options;
|
|
700
|
+
userId;
|
|
701
|
+
name = "list_renderers";
|
|
702
|
+
description = "List connected NodeTool editor renderers that can run ui_* tools. Pass a " +
|
|
703
|
+
"returned renderer_id to a ui_* tool to target that editor; omit it to use " +
|
|
704
|
+
"the active one.";
|
|
705
|
+
jsonSchema = {
|
|
706
|
+
type: "object",
|
|
707
|
+
properties: {}
|
|
708
|
+
};
|
|
709
|
+
constructor(options, userId) {
|
|
710
|
+
super();
|
|
711
|
+
this.options = options;
|
|
712
|
+
this.userId = userId;
|
|
713
|
+
}
|
|
714
|
+
async process() {
|
|
715
|
+
const renderers = this.options.frontendRendererRegistry
|
|
716
|
+
? this.options.frontendRendererRegistry
|
|
717
|
+
.list(this.userId)
|
|
718
|
+
.map((renderer, index) => ({
|
|
719
|
+
renderer_id: renderer.renderer_id,
|
|
720
|
+
active: index === 0
|
|
721
|
+
}))
|
|
722
|
+
: [];
|
|
723
|
+
return { renderers };
|
|
724
|
+
}
|
|
725
|
+
}
|
|
726
|
+
/**
|
|
727
|
+
* The `ui_*` schemas that steer a connected editor rather than edit a
|
|
728
|
+
* persisted workflow document, plus `list_renderers`.
|
|
729
|
+
*/
|
|
730
|
+
function editorSteeringTools(options, userId) {
|
|
731
|
+
const documentToolNames = new Set(WORKFLOW_DOCUMENT_TOOL_NAMES);
|
|
732
|
+
const tools = [new ListRenderersTool(options, userId)];
|
|
733
|
+
for (const [name, schema] of Object.entries(uiToolSchemas)) {
|
|
734
|
+
if (documentToolNames.has(name))
|
|
735
|
+
continue;
|
|
736
|
+
const params = zodToJsonSchema(z.object(schema.parameters));
|
|
737
|
+
const properties = {
|
|
738
|
+
...recordValue(params["properties"]),
|
|
739
|
+
renderer_id: RENDERER_ID_PROPERTY
|
|
740
|
+
};
|
|
741
|
+
tools.push(new FrontendUiTool(name, schema.description, { ...params, type: "object", properties }, options, userId));
|
|
742
|
+
}
|
|
743
|
+
return tools;
|
|
744
|
+
}
|
|
745
|
+
/** First sentence of a tool description, for the capabilities catalog. */
|
|
746
|
+
function oneLine(description) {
|
|
747
|
+
const flat = description.replace(/\s+/g, " ").trim();
|
|
748
|
+
const stop = flat.indexOf(". ");
|
|
749
|
+
const line = stop > 0 ? flat.slice(0, stop + 1) : flat;
|
|
750
|
+
return line.length > 200 ? `${line.slice(0, 197)}…` : line;
|
|
751
|
+
}
|
|
752
|
+
/**
|
|
753
|
+
* The machine-readable form of what this session can do, served as the
|
|
754
|
+
* `nodetool://capabilities` resource. A client that lists two tools learns the
|
|
755
|
+
* contract from the `execute_code` description, which is right for a model and
|
|
756
|
+
* poor for tooling; this is the same catalog with structure, and costs nothing
|
|
757
|
+
* at list time.
|
|
758
|
+
*/
|
|
759
|
+
function buildCapabilityCatalog(belt, directToolNames) {
|
|
760
|
+
const available = new Set(belt.map((tool) => tool.name));
|
|
761
|
+
const modules = Object.entries(NODETOOL_API_NAMESPACE_TOOLS)
|
|
762
|
+
.map(([namespace, names]) => ({
|
|
763
|
+
namespace,
|
|
764
|
+
import: `nodetool.${namespace}`,
|
|
765
|
+
exports: names.filter((name) => available.has(name))
|
|
766
|
+
}))
|
|
767
|
+
.filter((entry) => entry.exports.length > 0);
|
|
768
|
+
return {
|
|
769
|
+
server: "nodetool",
|
|
770
|
+
direct_tools: directToolNames,
|
|
771
|
+
modules,
|
|
772
|
+
tools: belt
|
|
773
|
+
.map((tool) => ({
|
|
774
|
+
name: tool.name,
|
|
775
|
+
description: oneLine(tool.description),
|
|
776
|
+
permission_category: capabilityCategoryFor(tool.name)
|
|
777
|
+
}))
|
|
778
|
+
.sort((a, b) => a.name.localeCompare(b.name))
|
|
779
|
+
};
|
|
780
|
+
}
|
|
781
|
+
/**
|
|
782
|
+
* Register the agent surface on `server`: CodeAct, image viewing, asset
|
|
783
|
+
* transfer, and the promoted direct tools.
|
|
784
|
+
*
|
|
785
|
+
* `gate` defaults to {@link mcpSessionGate} — `auto` with an approver that
|
|
786
|
+
* denies, because an MCP session has no user of its own to ask. A host that
|
|
787
|
+
* does have an approval channel passes its own gate instead.
|
|
788
|
+
*
|
|
789
|
+
* Everything else the catalogs offer becomes the sandbox belt instead of an MCP
|
|
790
|
+
* tool. It stays fully reachable — `tools.<name>()`, the `nodetool.*` object
|
|
791
|
+
* model, `await nodetool.searchTools("query")` — and the `execute_code` description
|
|
792
|
+
* carries the same contract and catalog the chat runner puts in its system
|
|
793
|
+
* prompt, because MCP has no system prompt to put it in.
|
|
794
|
+
*/
|
|
795
|
+
export function registerAgentMcpTools(server, options, gate = mcpSessionGate()) {
|
|
796
|
+
// Every bridged tool runs against one user's secrets and assets, so a session
|
|
797
|
+
// without an explicit user binding has no surface at all — a default user
|
|
798
|
+
// here would cross the tenant boundary on any mount serving more than one
|
|
799
|
+
// caller. `createMcpServer` refuses such a session before reaching here.
|
|
800
|
+
const scope = options.agentToolsScope;
|
|
801
|
+
if (!scope) {
|
|
802
|
+
throw new Error("registerAgentMcpTools requires options.agentToolsScope: an MCP session " +
|
|
803
|
+
"must be bound to a user id.");
|
|
804
|
+
}
|
|
805
|
+
const localFilePathsAllowed = scope.source === "stdio-local" || options.allowLocalFilePaths === true;
|
|
806
|
+
const context = buildAgentToolContext(scope.userId);
|
|
807
|
+
// Populated lazily on first `find_model` call — provider probing hits the
|
|
808
|
+
// secret store and network, so it's deferred out of server construction.
|
|
809
|
+
const sharedProviders = {};
|
|
810
|
+
let providersPromise = null;
|
|
811
|
+
const ensureProviders = () => {
|
|
812
|
+
if (!providersPromise) {
|
|
813
|
+
providersPromise = loadConfiguredProviders(scope.userId).then((loaded) => {
|
|
814
|
+
Object.assign(sharedProviders, loaded);
|
|
815
|
+
});
|
|
816
|
+
}
|
|
817
|
+
return providersPromise;
|
|
818
|
+
};
|
|
819
|
+
// The gate: `auto` with the headless deny, `mcpSessionGate` above. What
|
|
820
|
+
// bounds this surface is the session's user binding, not a per-call
|
|
821
|
+
// question the mount has nobody to ask.
|
|
822
|
+
//
|
|
823
|
+
// The codeact session mounts this run, so an action can import
|
|
824
|
+
// `@nodetool-ai/sandbox-nodetool/<namespace>` and land on `run.invoke`; the
|
|
825
|
+
// belt is wrapped in `gateTools` below, so `tools.<name>()` and the direct
|
|
826
|
+
// MCP registrations reach the same ladder (invariant I-1).
|
|
827
|
+
const capabilityRun = createCapabilityRun({
|
|
828
|
+
context,
|
|
829
|
+
gate,
|
|
830
|
+
availableSecrets: contextSecretAvailability(context),
|
|
831
|
+
nodeRegistry: options.registry,
|
|
832
|
+
...mcpToolHostDeps({
|
|
833
|
+
registry: options.registry,
|
|
834
|
+
metadataRoots: options.metadataRoots,
|
|
835
|
+
metadataMaxDepth: options.metadataMaxDepth,
|
|
836
|
+
examplesDir: options.examplesDir
|
|
837
|
+
}),
|
|
838
|
+
providers: sharedProviders,
|
|
839
|
+
loaders: { timeline: loadTimelineForUser, sketch: loadSketchForUser }
|
|
840
|
+
});
|
|
841
|
+
const workflowDocumentToolNames = new Set(WORKFLOW_DOCUMENT_TOOL_NAMES);
|
|
842
|
+
/**
|
|
843
|
+
* Run one bridged tool. The single execution path for both surfaces — a
|
|
844
|
+
* direct MCP call and a `tools.<name>()` call inside an action — so a
|
|
845
|
+
* capability cannot behave differently depending on how it was reached.
|
|
846
|
+
*/
|
|
847
|
+
// HOLDOUT (anti-slop/no-unknown-returns): one path for every bridged tool,
|
|
848
|
+
// so the result is the open tool-result domain `Tool.process` declares.
|
|
849
|
+
const runBridgedTool = async (tool, args) => {
|
|
850
|
+
// Model search and workflow readiness read the configured-providers map at
|
|
851
|
+
// call time, so populate it before either handler runs. Without the
|
|
852
|
+
// workflow entries, the first plan/build call sees the lazy map while it
|
|
853
|
+
// is still empty and reports a false missing-provider blocker.
|
|
854
|
+
if (tool.name === "find_model" ||
|
|
855
|
+
tool.name === "list_models" ||
|
|
856
|
+
WORKFLOW_READINESS_TOOL_NAMES.has(tool.name)) {
|
|
857
|
+
await ensureProviders();
|
|
858
|
+
}
|
|
859
|
+
const isWorkflowDocumentTool = workflowDocumentToolNames.has(tool.name);
|
|
860
|
+
const isFrontendTool = tool.name.startsWith("ui_");
|
|
861
|
+
if (isWorkflowDocumentTool || isFrontendTool) {
|
|
862
|
+
const live = await executeFrontendTool(options, scope.userId, tool.name, args);
|
|
863
|
+
if (live.handled)
|
|
864
|
+
return live.result;
|
|
865
|
+
const rendererId = args["renderer_id"];
|
|
866
|
+
if (isString(rendererId)) {
|
|
867
|
+
throw new Error(`No connected NodeTool renderer with id "${rendererId}".`);
|
|
868
|
+
}
|
|
869
|
+
// Workflow document tools have a server-side implementation and use the
|
|
870
|
+
// live editor when one is available. Other editor tools only exist in a
|
|
871
|
+
// connected renderer, so report the missing target clearly.
|
|
872
|
+
if (isFrontendTool && !isWorkflowDocumentTool) {
|
|
873
|
+
throw new Error(`${tool.name} needs a connected NodeTool editor; none is open.`);
|
|
874
|
+
}
|
|
875
|
+
}
|
|
876
|
+
const { renderer_id: _rendererId, ...serverArgs } = args;
|
|
877
|
+
return tool.process(context, serverArgs);
|
|
878
|
+
};
|
|
879
|
+
const register = (tool) => {
|
|
880
|
+
const isImageTool = tool.name === "view_image";
|
|
881
|
+
const schema = { ...jsonSchemaToZodShape(tool.inputSchema) };
|
|
882
|
+
if (isImageTool) {
|
|
883
|
+
schema["image_id"] = z
|
|
884
|
+
.string()
|
|
885
|
+
.describe("An asset id, asset:// URI, public https:// URL, or data: URI. " +
|
|
886
|
+
"Local MCP connections also accept an absolute disk image path or file:// URI.");
|
|
887
|
+
}
|
|
888
|
+
server.tool(tool.name, tool.description +
|
|
889
|
+
(isImageTool
|
|
890
|
+
? " Returns MCP image content so you can see the pixels. On local MCP connections, image_id also accepts an absolute disk path or file:// URI."
|
|
891
|
+
: ""), schema, async (args) => {
|
|
892
|
+
try {
|
|
893
|
+
const input = { ...args };
|
|
894
|
+
const imageId = isImageTool && isString(input["image_id"])
|
|
895
|
+
? input["image_id"].trim()
|
|
896
|
+
: undefined;
|
|
897
|
+
const isDiskImage = imageId &&
|
|
898
|
+
!imageId.startsWith("/api/storage/") &&
|
|
899
|
+
(isAbsolute(imageId) || imageId.startsWith("file://"));
|
|
900
|
+
if (isDiskImage) {
|
|
901
|
+
if (!localFilePathsAllowed) {
|
|
902
|
+
throw new Error("Disk image paths require a local MCP connection. Use an asset id on remote sessions.");
|
|
903
|
+
}
|
|
904
|
+
const path = imageId.startsWith("file://")
|
|
905
|
+
? fileURLToPath(imageId)
|
|
906
|
+
: imageId;
|
|
907
|
+
const bytes = await readFile(path);
|
|
908
|
+
await sharp(bytes).metadata();
|
|
909
|
+
const mime = isSvgBytes(bytes)
|
|
910
|
+
? "image/svg+xml"
|
|
911
|
+
: detectImageMime(bytes);
|
|
912
|
+
input["image_id"] =
|
|
913
|
+
`data:${mime};base64,${bytes.toString("base64")}`;
|
|
914
|
+
if (!isString(input["question"]) || !input["question"].trim()) {
|
|
915
|
+
input["question"] = `Image ${imageId}:`;
|
|
916
|
+
}
|
|
917
|
+
}
|
|
918
|
+
else if (imageId?.startsWith("data:")) {
|
|
919
|
+
if (!isString(input["question"]) || !input["question"].trim()) {
|
|
920
|
+
input["question"] = "Inline image:";
|
|
921
|
+
}
|
|
922
|
+
}
|
|
923
|
+
const result = await runBridgedTool(tool, input);
|
|
924
|
+
if (!isImageTool) {
|
|
925
|
+
return toToolResponse(result);
|
|
926
|
+
}
|
|
927
|
+
if (isRecord(result) && imageId && !isErrorResult(result)) {
|
|
928
|
+
result["image_id"] = imageId.startsWith("data:")
|
|
929
|
+
? "inline image"
|
|
930
|
+
: imageId;
|
|
931
|
+
}
|
|
932
|
+
return await toImageToolResponse(result, context);
|
|
933
|
+
}
|
|
934
|
+
catch (err) {
|
|
935
|
+
return errorResponse(err);
|
|
936
|
+
}
|
|
937
|
+
});
|
|
938
|
+
};
|
|
939
|
+
// The belt the sandbox sees. Deduped by name, because the two catalogs
|
|
940
|
+
// overlap and a session must not offer one tool under two instances.
|
|
941
|
+
const rawBelt = [];
|
|
942
|
+
const beltNames = new Set();
|
|
943
|
+
for (const originalTool of [
|
|
944
|
+
new ImportAssetTool(localFilePathsAllowed),
|
|
945
|
+
new RenderDemoSurfaceTool(),
|
|
946
|
+
...collectBridgedTools(options, sharedProviders),
|
|
947
|
+
...editorSteeringTools(options, scope.userId)
|
|
948
|
+
]) {
|
|
949
|
+
const tool = workflowDocumentToolNames.has(originalTool.name)
|
|
950
|
+
? new RendererAwareDocumentTool(originalTool)
|
|
951
|
+
: originalTool;
|
|
952
|
+
if (beltNames.has(tool.name))
|
|
953
|
+
continue;
|
|
954
|
+
beltNames.add(tool.name);
|
|
955
|
+
rawBelt.push(tool);
|
|
956
|
+
}
|
|
957
|
+
// Every belt tool goes through the one ladder. `runBridgedTool` ends in
|
|
958
|
+
// `tool.process`, so wrapping here covers both entrances — the direct MCP
|
|
959
|
+
// registrations below and `tools.<name>()` inside a code action — with no
|
|
960
|
+
// second gate of their own. The wrapper is transparent otherwise (identity,
|
|
961
|
+
// schema, message template are the inner tool's), so the catalog and the
|
|
962
|
+
// sandbox belt are unchanged.
|
|
963
|
+
const belt = gateTools(rawBelt, gate);
|
|
964
|
+
const byName = new Map(belt.map((tool) => [tool.name, tool]));
|
|
965
|
+
// `view_image` is the one channel that puts pixels into a caller's context,
|
|
966
|
+
// and pixels cannot ride the sandbox's JSON observation envelope — so it is a
|
|
967
|
+
// direct tool and is kept off the belt, exactly as the chat runner does.
|
|
968
|
+
const beltForSandbox = belt.filter((tool) => tool.name !== "view_image");
|
|
969
|
+
// The direct set, derived the way the CLI turn and the websocket runner
|
|
970
|
+
// derive theirs — minus the tools an MCP *client* already serves natively.
|
|
971
|
+
//
|
|
972
|
+
// `DIRECT_TOOL_NAMES` goes top level everywhere else because those are the
|
|
973
|
+
// shapes models are trained on, so a sandbox round trip whose only job is to
|
|
974
|
+
// forward one buys nothing. That argument holds here too. What does not hold
|
|
975
|
+
// is the file/search half: `SDK_NATIVE_TOOL_REPLACEMENTS` already names the
|
|
976
|
+
// tools a host agent covers with its own — and an MCP client (Claude Code,
|
|
977
|
+
// ChatGPT) is that host. Offering NodeTool's workspace-scoped `read_file`
|
|
978
|
+
// beside the client's own would put two tools of one name and two different
|
|
979
|
+
// roots in front of the same model.
|
|
980
|
+
//
|
|
981
|
+
// What is left has no host equivalent: discovery (which providers, models
|
|
982
|
+
// and node types this install has — a guess there is a hallucinated id that
|
|
983
|
+
// fails at generation time, after the run was paid for), the server-side
|
|
984
|
+
// reach that runs behind NodeTool's own SSRF guard and secrets, and
|
|
985
|
+
// `run_subtask`, whose child gets the NodeTool belt rather than the client's.
|
|
986
|
+
//
|
|
987
|
+
// Derived from both tables rather than hand-listed, so a tool added to
|
|
988
|
+
// either reaches this mount with no edit here.
|
|
989
|
+
const promotedDirect = belt.filter((tool) => DIRECT_TOOL_NAMES.has(tool.name) &&
|
|
990
|
+
!SDK_NATIVE_TOOL_REPLACEMENTS.has(tool.name));
|
|
991
|
+
// They stay on the belt: an action still calls them from code. Listing them
|
|
992
|
+
// as direct only moves where the prompt documents them.
|
|
993
|
+
const directToolNames = [
|
|
994
|
+
"view_image",
|
|
995
|
+
...promotedDirect.map((tool) => tool.name)
|
|
996
|
+
];
|
|
997
|
+
const session = createChatCodeActSession({
|
|
998
|
+
tools: beltForSandbox.map((tool) => ({
|
|
999
|
+
name: tool.name,
|
|
1000
|
+
description: tool.description,
|
|
1001
|
+
inputSchema: tool.inputSchema
|
|
1002
|
+
})),
|
|
1003
|
+
directToolNames,
|
|
1004
|
+
residentToolNames: CODEACT_RESIDENT_TOOL_NAMES,
|
|
1005
|
+
executeTool: async (call) => {
|
|
1006
|
+
const tool = byName.get(call.name);
|
|
1007
|
+
if (!tool)
|
|
1008
|
+
throw new Error(`Unknown tool: ${call.name}`);
|
|
1009
|
+
return runBridgedTool(tool, call.args);
|
|
1010
|
+
},
|
|
1011
|
+
capabilityRun
|
|
1012
|
+
});
|
|
1013
|
+
// The action tool. MCP has no system prompt, so the guest contract, the
|
|
1014
|
+
// catalog and the sandbox summary ride in the description — the only field
|
|
1015
|
+
// every MCP client is guaranteed to show the model. The short contract
|
|
1016
|
+
// leads: many clients truncate a long description.
|
|
1017
|
+
// `title` is a display label for NodeTool's own chat UI, and the action path
|
|
1018
|
+
// never reads it — `executeAction` takes `code` and discards the rest. On the
|
|
1019
|
+
// provider tool it is required because a system prompt teaches the contract
|
|
1020
|
+
// and the label is what the user watches. MCP has neither: a client whose
|
|
1021
|
+
// model skipped a field this server does not use had its whole action
|
|
1022
|
+
// rejected on validation. It stays in the schema — described, and the
|
|
1023
|
+
// contract in the description still asks for one — but is optional here.
|
|
1024
|
+
//
|
|
1025
|
+
// `risk` is optional here for the same reason, and it still decides
|
|
1026
|
+
// nothing: `admitCodeAction` reads the standing `execute_code` approval in
|
|
1027
|
+
// this session's gate (see `mcpSessionGate`) before it looks at the declared
|
|
1028
|
+
// risk, because the client already asked its user about this very call.
|
|
1029
|
+
//
|
|
1030
|
+
// `description` follows `risk`: it is the text an approval dialog asks the
|
|
1031
|
+
// user about, and this surface never opens one.
|
|
1032
|
+
const optionalOnMcp = new Set(["title", "risk", "description"]);
|
|
1033
|
+
const actionSchema = session.providerTool.inputSchema;
|
|
1034
|
+
const actionShape = jsonSchemaToZodShape({
|
|
1035
|
+
...actionSchema,
|
|
1036
|
+
required: (Array.isArray(actionSchema["required"])
|
|
1037
|
+
? actionSchema["required"]
|
|
1038
|
+
: []).filter((name) => !optionalOnMcp.has(name))
|
|
1039
|
+
});
|
|
1040
|
+
server.tool(session.providerTool.name, `${MCP_GUEST_CONTRACT}\n\n${session.providerTool.description}\n\n${session.systemPromptSection}`, actionShape, async (args) => {
|
|
1041
|
+
try {
|
|
1042
|
+
// The session already returns the observation envelope as JSON text.
|
|
1043
|
+
// Passing it through `toToolResponse` would encode it a second time
|
|
1044
|
+
// and hand the caller a quoted string instead of an object.
|
|
1045
|
+
const observation = await session.executeAction(args ?? {});
|
|
1046
|
+
return {
|
|
1047
|
+
content: [{ type: "text", text: observation }]
|
|
1048
|
+
};
|
|
1049
|
+
}
|
|
1050
|
+
catch (err) {
|
|
1051
|
+
return errorResponse(err);
|
|
1052
|
+
}
|
|
1053
|
+
});
|
|
1054
|
+
// `view_image` carries image content, which an action's observation envelope
|
|
1055
|
+
// cannot, so it is direct for a reason no other tool shares.
|
|
1056
|
+
const viewImage = byName.get("view_image");
|
|
1057
|
+
if (viewImage)
|
|
1058
|
+
register(viewImage);
|
|
1059
|
+
// The rest of the direct set, for parity with every other entrance.
|
|
1060
|
+
for (const tool of promotedDirect)
|
|
1061
|
+
register(tool);
|
|
1062
|
+
server.tool("upload_asset", "Upload bytes to this user's NodeTool asset library. Pass content_base64 " +
|
|
1063
|
+
"from any MCP client, or an absolute file_path on a local connection. " +
|
|
1064
|
+
"The path is on the NodeTool server, not on a remote MCP client's machine.", {
|
|
1065
|
+
name: z
|
|
1066
|
+
.string()
|
|
1067
|
+
.optional()
|
|
1068
|
+
.describe("Asset name; defaults to the file name for file_path."),
|
|
1069
|
+
content_base64: z
|
|
1070
|
+
.string()
|
|
1071
|
+
.optional()
|
|
1072
|
+
.describe("File bytes encoded as base64."),
|
|
1073
|
+
file_path: z
|
|
1074
|
+
.string()
|
|
1075
|
+
.optional()
|
|
1076
|
+
.describe("Absolute server-local file path; local connections only."),
|
|
1077
|
+
content_type: z
|
|
1078
|
+
.string()
|
|
1079
|
+
.optional()
|
|
1080
|
+
.describe("MIME type; inferred from file_path or name when omitted.")
|
|
1081
|
+
}, async ({ name, content_base64, file_path, content_type }) => {
|
|
1082
|
+
try {
|
|
1083
|
+
if (Boolean(content_base64) === Boolean(file_path)) {
|
|
1084
|
+
throw new Error("Provide exactly one of content_base64 or file_path.");
|
|
1085
|
+
}
|
|
1086
|
+
if (file_path && (!localFilePathsAllowed || !isAbsolute(file_path))) {
|
|
1087
|
+
throw new Error("file_path requires an absolute path on a local MCP connection.");
|
|
1088
|
+
}
|
|
1089
|
+
const assetName = name?.trim() || (file_path ? basename(file_path) : "");
|
|
1090
|
+
if (!assetName)
|
|
1091
|
+
throw new Error("name is required for a base64 upload.");
|
|
1092
|
+
if (content_base64 &&
|
|
1093
|
+
!/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/.test(content_base64)) {
|
|
1094
|
+
throw new Error("content_base64 must be valid base64.");
|
|
1095
|
+
}
|
|
1096
|
+
const bytes = file_path
|
|
1097
|
+
? await readFile(file_path)
|
|
1098
|
+
: Buffer.from(content_base64 ?? "", "base64");
|
|
1099
|
+
const asset = await createAssetModelInterface({
|
|
1100
|
+
userId: scope.userId,
|
|
1101
|
+
name: assetName,
|
|
1102
|
+
contentType: normalizeAssetContentType(content_type ?? "", file_path ?? assetName),
|
|
1103
|
+
content: bytes
|
|
1104
|
+
});
|
|
1105
|
+
return toToolResponse({
|
|
1106
|
+
asset_id: asset.id,
|
|
1107
|
+
asset_uri: `asset://${asset.id}`,
|
|
1108
|
+
name: asset.name,
|
|
1109
|
+
content_type: asset.content_type,
|
|
1110
|
+
size: bytes.length
|
|
1111
|
+
});
|
|
1112
|
+
}
|
|
1113
|
+
catch (err) {
|
|
1114
|
+
return errorResponse(err);
|
|
1115
|
+
}
|
|
1116
|
+
});
|
|
1117
|
+
server.tool("download_asset", "Download an asset owned by this user. Returns content_base64, or writes " +
|
|
1118
|
+
"to an absolute output_path on a local connection. The path is on the " +
|
|
1119
|
+
"NodeTool server, not on a remote MCP client's machine.", {
|
|
1120
|
+
asset_id: z
|
|
1121
|
+
.string()
|
|
1122
|
+
.describe("Asset ID returned by upload_asset or list_assets."),
|
|
1123
|
+
output_path: z
|
|
1124
|
+
.string()
|
|
1125
|
+
.optional()
|
|
1126
|
+
.describe("Absolute server-local output path; local connections only.")
|
|
1127
|
+
}, async ({ asset_id, output_path }) => {
|
|
1128
|
+
try {
|
|
1129
|
+
if (output_path &&
|
|
1130
|
+
(!localFilePathsAllowed || !isAbsolute(output_path))) {
|
|
1131
|
+
throw new Error("output_path requires an absolute path on a local MCP connection.");
|
|
1132
|
+
}
|
|
1133
|
+
const asset = await Asset.find(scope.userId, asset_id);
|
|
1134
|
+
if (!asset || asset.isFolder)
|
|
1135
|
+
throw new Error("Asset not found.");
|
|
1136
|
+
const bytes = await loadMediaRefBytes({ asset_id: asset.id }, context);
|
|
1137
|
+
if (!bytes)
|
|
1138
|
+
throw new Error("Asset bytes not found.");
|
|
1139
|
+
if (output_path)
|
|
1140
|
+
await writeFile(output_path, bytes);
|
|
1141
|
+
return toToolResponse({
|
|
1142
|
+
asset_id: asset.id,
|
|
1143
|
+
name: asset.name,
|
|
1144
|
+
content_type: asset.content_type,
|
|
1145
|
+
size: bytes.length,
|
|
1146
|
+
...(output_path
|
|
1147
|
+
? { output_path }
|
|
1148
|
+
: { content_base64: Buffer.from(bytes).toString("base64") })
|
|
1149
|
+
});
|
|
1150
|
+
}
|
|
1151
|
+
catch (err) {
|
|
1152
|
+
return errorResponse(err);
|
|
1153
|
+
}
|
|
1154
|
+
});
|
|
1155
|
+
// The structured catalog, for clients that want more than a description.
|
|
1156
|
+
const catalog = buildCapabilityCatalog(belt, [
|
|
1157
|
+
session.providerTool.name,
|
|
1158
|
+
...directToolNames,
|
|
1159
|
+
"upload_asset",
|
|
1160
|
+
"download_asset"
|
|
1161
|
+
]);
|
|
1162
|
+
server.registerResource("NodeTool Capabilities", MCP_CAPABILITIES_RESOURCE_URI, {
|
|
1163
|
+
description: "What this NodeTool session can do: the nodetool.* modules mounted for " +
|
|
1164
|
+
"it, every tool an execute_code action can call, and each tool's " +
|
|
1165
|
+
"permission category.",
|
|
1166
|
+
mimeType: "application/json"
|
|
1167
|
+
}, async (uri) => ({
|
|
1168
|
+
contents: [
|
|
1169
|
+
{
|
|
1170
|
+
uri: uri.href,
|
|
1171
|
+
mimeType: "application/json",
|
|
1172
|
+
text: JSON.stringify(catalog, null, 2)
|
|
1173
|
+
}
|
|
1174
|
+
]
|
|
1175
|
+
}));
|
|
1176
|
+
const sandbox = buildMcpSandboxCatalog();
|
|
1177
|
+
server.registerResource("NodeTool Sandbox", MCP_SANDBOX_RESOURCE_URI, {
|
|
1178
|
+
description: "How to write execute_code: the guest contract, blocked globals, " +
|
|
1179
|
+
"bridges this chat session cannot use, and two worked examples.",
|
|
1180
|
+
mimeType: "application/json"
|
|
1181
|
+
}, async (uri) => ({
|
|
1182
|
+
contents: [
|
|
1183
|
+
{
|
|
1184
|
+
uri: uri.href,
|
|
1185
|
+
mimeType: "application/json",
|
|
1186
|
+
text: JSON.stringify(sandbox, null, 2)
|
|
1187
|
+
}
|
|
1188
|
+
]
|
|
1189
|
+
}));
|
|
1190
|
+
for (const prompt of MCP_SANDBOX_PROMPTS) {
|
|
1191
|
+
server.registerPrompt(prompt.name, {
|
|
1192
|
+
title: prompt.title,
|
|
1193
|
+
description: prompt.description
|
|
1194
|
+
}, async () => ({
|
|
1195
|
+
messages: [
|
|
1196
|
+
{
|
|
1197
|
+
role: "user",
|
|
1198
|
+
content: { type: "text", text: prompt.snippet }
|
|
1199
|
+
}
|
|
1200
|
+
]
|
|
1201
|
+
}));
|
|
1202
|
+
}
|
|
1203
|
+
log.info("Registered agent MCP tools", {
|
|
1204
|
+
userId: scope.userId,
|
|
1205
|
+
source: scope.source,
|
|
1206
|
+
registered: [
|
|
1207
|
+
session.providerTool.name,
|
|
1208
|
+
...(viewImage ? ["view_image"] : []),
|
|
1209
|
+
"upload_asset",
|
|
1210
|
+
"download_asset"
|
|
1211
|
+
],
|
|
1212
|
+
beltSize: belt.length
|
|
1213
|
+
});
|
|
1214
|
+
return capabilityRun;
|
|
1215
|
+
}
|
|
1216
|
+
//# sourceMappingURL=mcp-agent-tools.js.map
|