@nodetool-ai/agents 0.8.1 → 0.8.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/.nodetool-build-stamp +1 -1
- package/dist/analysis/audio-dsp.d.ts +3 -2
- package/dist/analysis/audio-dsp.d.ts.map +1 -1
- package/dist/analysis/audio-dsp.js +11 -8
- package/dist/analysis/audio-dsp.js.map +1 -1
- package/dist/analysis/media-decode.d.ts +13 -0
- package/dist/analysis/media-decode.d.ts.map +1 -1
- package/dist/analysis/media-decode.js +33 -6
- package/dist/analysis/media-decode.js.map +1 -1
- package/dist/apify/assets.d.ts.map +1 -1
- package/dist/apify/assets.js +4 -0
- package/dist/apify/assets.js.map +1 -1
- package/dist/author-graph.d.ts +2 -3
- package/dist/author-graph.d.ts.map +1 -1
- package/dist/author-graph.js +3 -5
- package/dist/author-graph.js.map +1 -1
- package/dist/browser-gate.d.ts +2 -2
- package/dist/browser-gate.js +2 -2
- package/dist/capabilities/GamePublishRequest.d.ts +14 -0
- package/dist/capabilities/GamePublishRequest.d.ts.map +1 -0
- package/dist/capabilities/GamePublishRequest.js +2 -0
- package/dist/capabilities/GamePublishRequest.js.map +1 -0
- package/dist/capabilities/adapters.d.ts +4 -13
- package/dist/capabilities/adapters.d.ts.map +1 -1
- package/dist/capabilities/adapters.js +9 -14
- package/dist/capabilities/adapters.js.map +1 -1
- package/dist/capabilities/agent-activity.d.ts +27 -0
- package/dist/capabilities/agent-activity.d.ts.map +1 -0
- package/dist/capabilities/agent-activity.js +103 -0
- package/dist/capabilities/agent-activity.js.map +1 -0
- package/dist/capabilities/agentic-storyboard-finish.d.ts +67 -0
- package/dist/capabilities/agentic-storyboard-finish.d.ts.map +1 -0
- package/dist/capabilities/agentic-storyboard-finish.js +1321 -0
- package/dist/capabilities/agentic-storyboard-finish.js.map +1 -0
- package/dist/capabilities/agents.d.ts +5 -2
- package/dist/capabilities/agents.d.ts.map +1 -1
- package/dist/capabilities/agents.js +14 -4
- package/dist/capabilities/agents.js.map +1 -1
- package/dist/capabilities/agents.specs.d.ts +3 -0
- package/dist/capabilities/agents.specs.d.ts.map +1 -1
- package/dist/capabilities/agents.specs.js +71 -1
- package/dist/capabilities/agents.specs.js.map +1 -1
- package/dist/capabilities/analysis.d.ts.map +1 -1
- package/dist/capabilities/analysis.js +33 -22
- package/dist/capabilities/analysis.js.map +1 -1
- package/dist/capabilities/analysis.specs.js +2 -2
- package/dist/capabilities/analysis.specs.js.map +1 -1
- package/dist/capabilities/apps.d.ts.map +1 -1
- package/dist/capabilities/apps.js +5 -3
- package/dist/capabilities/apps.js.map +1 -1
- package/dist/capabilities/args.d.ts +2 -5
- package/dist/capabilities/args.d.ts.map +1 -1
- package/dist/capabilities/args.js +2 -5
- package/dist/capabilities/args.js.map +1 -1
- package/dist/capabilities/assets.d.ts.map +1 -1
- package/dist/capabilities/assets.js +40 -10
- package/dist/capabilities/assets.js.map +1 -1
- package/dist/capabilities/browser.d.ts +1 -1
- package/dist/capabilities/browser.js +1 -1
- package/dist/capabilities/browser.specs.d.ts +1 -1
- package/dist/capabilities/browser.specs.js +1 -1
- package/dist/capabilities/code.d.ts +5 -0
- package/dist/capabilities/code.d.ts.map +1 -1
- package/dist/capabilities/code.js +128 -89
- package/dist/capabilities/code.js.map +1 -1
- package/dist/capabilities/collections.d.ts +4 -6
- package/dist/capabilities/collections.d.ts.map +1 -1
- package/dist/capabilities/collections.js +16 -11
- package/dist/capabilities/collections.js.map +1 -1
- package/dist/capabilities/derive-shot.d.ts +45 -0
- package/dist/capabilities/derive-shot.d.ts.map +1 -0
- package/dist/capabilities/derive-shot.js +82 -0
- package/dist/capabilities/derive-shot.js.map +1 -0
- package/dist/capabilities/documents.d.ts +2 -1
- package/dist/capabilities/documents.d.ts.map +1 -1
- package/dist/capabilities/documents.js +12 -6
- package/dist/capabilities/documents.js.map +1 -1
- package/dist/capabilities/email.d.ts +2 -1
- package/dist/capabilities/email.d.ts.map +1 -1
- package/dist/capabilities/email.js +5 -3
- package/dist/capabilities/email.js.map +1 -1
- package/dist/capabilities/errors.d.ts +19 -0
- package/dist/capabilities/errors.d.ts.map +1 -0
- package/dist/capabilities/errors.js +109 -0
- package/dist/capabilities/errors.js.map +1 -0
- package/dist/capabilities/errors.specs.d.ts +11 -0
- package/dist/capabilities/errors.specs.d.ts.map +1 -0
- package/dist/capabilities/errors.specs.js +100 -0
- package/dist/capabilities/errors.specs.js.map +1 -0
- package/dist/capabilities/example-timelines.d.ts.map +1 -1
- package/dist/capabilities/example-timelines.js +52 -10
- package/dist/capabilities/example-timelines.js.map +1 -1
- package/dist/capabilities/example-timelines.specs.d.ts +1 -0
- package/dist/capabilities/example-timelines.specs.d.ts.map +1 -1
- package/dist/capabilities/example-timelines.specs.js +21 -3
- package/dist/capabilities/example-timelines.specs.js.map +1 -1
- package/dist/capabilities/finish-storyboard.d.ts +5 -0
- package/dist/capabilities/finish-storyboard.d.ts.map +1 -0
- package/dist/capabilities/finish-storyboard.js +278 -0
- package/dist/capabilities/finish-storyboard.js.map +1 -0
- package/dist/capabilities/game-asset-browser.d.ts +11 -0
- package/dist/capabilities/game-asset-browser.d.ts.map +1 -0
- package/dist/capabilities/game-asset-browser.js +152 -0
- package/dist/capabilities/game-asset-browser.js.map +1 -0
- package/dist/capabilities/game-asset-source.js +1 -1
- package/dist/capabilities/game-asset-source.js.map +1 -1
- package/dist/capabilities/game.d.ts +44 -2
- package/dist/capabilities/game.d.ts.map +1 -1
- package/dist/capabilities/game.js +408 -160
- package/dist/capabilities/game.js.map +1 -1
- package/dist/capabilities/game.specs.d.ts +4 -0
- package/dist/capabilities/game.specs.d.ts.map +1 -1
- package/dist/capabilities/game.specs.js +42 -13
- package/dist/capabilities/game.specs.js.map +1 -1
- package/dist/capabilities/game3d.d.ts +17 -0
- package/dist/capabilities/game3d.d.ts.map +1 -0
- package/dist/capabilities/game3d.js +434 -0
- package/dist/capabilities/game3d.js.map +1 -0
- package/dist/capabilities/gate-from-context.d.ts +1 -1
- package/dist/capabilities/gate-from-context.js +1 -1
- package/dist/capabilities/generations.d.ts +2 -0
- package/dist/capabilities/generations.d.ts.map +1 -1
- package/dist/capabilities/generations.js +14 -23
- package/dist/capabilities/generations.js.map +1 -1
- package/dist/capabilities/index.d.ts +2 -2
- package/dist/capabilities/index.d.ts.map +1 -1
- package/dist/capabilities/index.js +2 -2
- package/dist/capabilities/index.js.map +1 -1
- package/dist/capabilities/invoke.d.ts +14 -25
- package/dist/capabilities/invoke.d.ts.map +1 -1
- package/dist/capabilities/invoke.js +72 -35
- package/dist/capabilities/invoke.js.map +1 -1
- package/dist/capabilities/jobs.d.ts.map +1 -1
- package/dist/capabilities/jobs.js +47 -3
- package/dist/capabilities/jobs.js.map +1 -1
- package/dist/capabilities/jobs.specs.d.ts.map +1 -1
- package/dist/capabilities/jobs.specs.js +3 -1
- package/dist/capabilities/jobs.specs.js.map +1 -1
- package/dist/capabilities/js-scripts.d.ts +19 -1
- package/dist/capabilities/js-scripts.d.ts.map +1 -1
- package/dist/capabilities/js-scripts.js +109 -2
- package/dist/capabilities/js-scripts.js.map +1 -1
- package/dist/capabilities/js-scripts.specs.d.ts +2 -0
- package/dist/capabilities/js-scripts.specs.d.ts.map +1 -1
- package/dist/capabilities/js-scripts.specs.js +50 -0
- package/dist/capabilities/js-scripts.specs.js.map +1 -1
- package/dist/capabilities/lazy-tool-core.d.ts +23 -0
- package/dist/capabilities/lazy-tool-core.d.ts.map +1 -0
- package/dist/capabilities/lazy-tool-core.js +56 -0
- package/dist/capabilities/lazy-tool-core.js.map +1 -0
- package/dist/capabilities/lazy-tool.d.ts +3 -23
- package/dist/capabilities/lazy-tool.d.ts.map +1 -1
- package/dist/capabilities/lazy-tool.js +6 -64
- package/dist/capabilities/lazy-tool.js.map +1 -1
- package/dist/capabilities/legacy-tools.d.ts +15 -0
- package/dist/capabilities/legacy-tools.d.ts.map +1 -0
- package/dist/capabilities/legacy-tools.js +98 -0
- package/dist/capabilities/legacy-tools.js.map +1 -0
- package/dist/capabilities/media.d.ts +0 -9
- package/dist/capabilities/media.d.ts.map +1 -1
- package/dist/capabilities/media.js +314 -261
- package/dist/capabilities/media.js.map +1 -1
- package/dist/capabilities/media.specs.d.ts.map +1 -1
- package/dist/capabilities/media.specs.js +17 -0
- package/dist/capabilities/media.specs.js.map +1 -1
- package/dist/capabilities/metadata.d.ts +62 -0
- package/dist/capabilities/metadata.d.ts.map +1 -0
- package/dist/capabilities/metadata.js +114 -0
- package/dist/capabilities/metadata.js.map +1 -0
- package/dist/capabilities/model3d.d.ts.map +1 -1
- package/dist/capabilities/model3d.js +4 -0
- package/dist/capabilities/model3d.js.map +1 -1
- package/dist/capabilities/models.d.ts +2 -2
- package/dist/capabilities/models.d.ts.map +1 -1
- package/dist/capabilities/models.js +5 -3
- package/dist/capabilities/models.js.map +1 -1
- package/dist/capabilities/registry.d.ts +6 -19
- package/dist/capabilities/registry.d.ts.map +1 -1
- package/dist/capabilities/registry.js +72 -113
- package/dist/capabilities/registry.js.map +1 -1
- package/dist/capabilities/run-agent.d.ts +19 -0
- package/dist/capabilities/run-agent.d.ts.map +1 -0
- package/dist/capabilities/run-agent.js +183 -0
- package/dist/capabilities/run-agent.js.map +1 -0
- package/dist/capabilities/runs.d.ts +9 -0
- package/dist/capabilities/runs.d.ts.map +1 -0
- package/dist/capabilities/runs.js +46 -0
- package/dist/capabilities/runs.js.map +1 -0
- package/dist/capabilities/runs.specs.d.ts +39 -0
- package/dist/capabilities/runs.specs.d.ts.map +1 -0
- package/dist/capabilities/runs.specs.js +52 -0
- package/dist/capabilities/runs.specs.js.map +1 -0
- package/dist/capabilities/scripts.d.ts.map +1 -1
- package/dist/capabilities/scripts.js +11 -5
- package/dist/capabilities/scripts.js.map +1 -1
- package/dist/capabilities/settings.d.ts.map +1 -1
- package/dist/capabilities/settings.js +4 -2
- package/dist/capabilities/settings.js.map +1 -1
- package/dist/capabilities/sketches.d.ts.map +1 -1
- package/dist/capabilities/sketches.js +4 -2
- package/dist/capabilities/sketches.js.map +1 -1
- package/dist/capabilities/skills.d.ts.map +1 -1
- package/dist/capabilities/skills.js +22 -2
- package/dist/capabilities/skills.js.map +1 -1
- package/dist/capabilities/storyboard-layout-check.d.ts +33 -0
- package/dist/capabilities/storyboard-layout-check.d.ts.map +1 -0
- package/dist/capabilities/storyboard-layout-check.js +229 -0
- package/dist/capabilities/storyboard-layout-check.js.map +1 -0
- package/dist/capabilities/storyboard-measured-sources.d.ts +10 -0
- package/dist/capabilities/storyboard-measured-sources.d.ts.map +1 -0
- package/dist/capabilities/storyboard-measured-sources.js +67 -0
- package/dist/capabilities/storyboard-measured-sources.js.map +1 -0
- package/dist/capabilities/storyboard-review-times.d.ts +4 -0
- package/dist/capabilities/storyboard-review-times.d.ts.map +1 -0
- package/dist/capabilities/storyboard-review-times.js +39 -0
- package/dist/capabilities/storyboard-review-times.js.map +1 -0
- package/dist/capabilities/storyboards.d.ts +12 -18
- package/dist/capabilities/storyboards.d.ts.map +1 -1
- package/dist/capabilities/storyboards.js +779 -96
- package/dist/capabilities/storyboards.js.map +1 -1
- package/dist/capabilities/storyboards.specs.d.ts +9 -0
- package/dist/capabilities/storyboards.specs.d.ts.map +1 -1
- package/dist/capabilities/storyboards.specs.js +173 -5
- package/dist/capabilities/storyboards.specs.js.map +1 -1
- package/dist/capabilities/threads.js +1 -1
- package/dist/capabilities/threads.js.map +1 -1
- package/dist/capabilities/timeline-bridge.d.ts +368 -0
- package/dist/capabilities/timeline-bridge.d.ts.map +1 -0
- package/dist/capabilities/timeline-bridge.js +1008 -0
- package/dist/capabilities/timeline-bridge.js.map +1 -0
- package/dist/capabilities/timeline-clip-frames.d.ts +17 -0
- package/dist/capabilities/timeline-clip-frames.d.ts.map +1 -0
- package/dist/capabilities/timeline-clip-frames.js +84 -0
- package/dist/capabilities/timeline-clip-frames.js.map +1 -0
- package/dist/capabilities/timeline-media-edit.d.ts +8 -0
- package/dist/capabilities/timeline-media-edit.d.ts.map +1 -0
- package/dist/capabilities/timeline-media-edit.js +94 -0
- package/dist/capabilities/timeline-media-edit.js.map +1 -0
- package/dist/capabilities/timeline-native-media.d.ts.map +1 -1
- package/dist/capabilities/timeline-native-media.js +40 -0
- package/dist/capabilities/timeline-native-media.js.map +1 -1
- package/dist/capabilities/timeline-operations.d.ts +52 -0
- package/dist/capabilities/timeline-operations.d.ts.map +1 -0
- package/dist/capabilities/timeline-operations.js +413 -0
- package/dist/capabilities/timeline-operations.js.map +1 -0
- package/dist/capabilities/timelines.d.ts +28 -3
- package/dist/capabilities/timelines.d.ts.map +1 -1
- package/dist/capabilities/timelines.js +410 -294
- package/dist/capabilities/timelines.js.map +1 -1
- package/dist/capabilities/timelines.specs.d.ts +8 -0
- package/dist/capabilities/timelines.specs.d.ts.map +1 -1
- package/dist/capabilities/timelines.specs.js +178 -9
- package/dist/capabilities/timelines.specs.js.map +1 -1
- package/dist/capabilities/types.d.ts +3 -1
- package/dist/capabilities/types.d.ts.map +1 -1
- package/dist/capabilities/types.js.map +1 -1
- package/dist/capabilities/ui.d.ts.map +1 -1
- package/dist/capabilities/ui.js +24 -2
- package/dist/capabilities/ui.js.map +1 -1
- package/dist/capabilities/web.d.ts.map +1 -1
- package/dist/capabilities/web.js +4 -0
- package/dist/capabilities/web.js.map +1 -1
- package/dist/capabilities/workflows.d.ts +3 -1
- package/dist/capabilities/workflows.d.ts.map +1 -1
- package/dist/capabilities/workflows.js +244 -39
- package/dist/capabilities/workflows.js.map +1 -1
- package/dist/capabilities/workflows.specs.d.ts +2 -0
- package/dist/capabilities/workflows.specs.d.ts.map +1 -1
- package/dist/capabilities/workflows.specs.js +72 -2
- package/dist/capabilities/workflows.specs.js.map +1 -1
- package/dist/codeact/action-diagnostics.d.ts.map +1 -1
- package/dist/codeact/action-diagnostics.js +51 -1
- package/dist/codeact/action-diagnostics.js.map +1 -1
- package/dist/codeact/codeact-executor.d.ts.map +1 -1
- package/dist/codeact/codeact-executor.js +16 -8
- package/dist/codeact/codeact-executor.js.map +1 -1
- package/dist/codeact/compact-ids.d.ts.map +1 -1
- package/dist/codeact/compact-ids.js +5 -1
- package/dist/codeact/compact-ids.js.map +1 -1
- package/dist/codeact/graph-model.d.ts +1 -1
- package/dist/codeact/graph-model.d.ts.map +1 -1
- package/dist/codeact/graph-model.js +2 -3
- package/dist/codeact/graph-model.js.map +1 -1
- package/dist/codeact/nodetool-api.d.ts +1 -1
- package/dist/codeact/nodetool-api.d.ts.map +1 -1
- package/dist/codeact/nodetool-api.js +202 -284
- package/dist/codeact/nodetool-api.js.map +1 -1
- package/dist/codeact/sandbox-packages.d.ts +0 -7
- package/dist/codeact/sandbox-packages.d.ts.map +1 -1
- package/dist/codeact/sandbox-packages.js +1 -10
- package/dist/codeact/sandbox-packages.js.map +1 -1
- package/dist/codeact/tool-api.d.ts +6 -3
- package/dist/codeact/tool-api.d.ts.map +1 -1
- package/dist/codeact/tool-api.js +22 -15
- package/dist/codeact/tool-api.js.map +1 -1
- package/dist/evals/codeact-api-cases.d.ts.map +1 -1
- package/dist/evals/codeact-api-cases.js +2 -0
- package/dist/evals/codeact-api-cases.js.map +1 -1
- package/dist/evals/codeact-api-runs.d.ts +3 -0
- package/dist/evals/codeact-api-runs.d.ts.map +1 -0
- package/dist/evals/codeact-api-runs.js +33 -0
- package/dist/evals/codeact-api-runs.js.map +1 -0
- package/dist/evals/surfaces/game.d.ts +8 -2
- package/dist/evals/surfaces/game.d.ts.map +1 -1
- package/dist/evals/surfaces/game.js +460 -2
- package/dist/evals/surfaces/game.js.map +1 -1
- package/dist/evals/surfaces/sketch.d.ts +2 -0
- package/dist/evals/surfaces/sketch.d.ts.map +1 -1
- package/dist/evals/surfaces/sketch.js +11 -3
- package/dist/evals/surfaces/sketch.js.map +1 -1
- package/dist/evals/surfaces/timeline.d.ts +4 -357
- package/dist/evals/surfaces/timeline.d.ts.map +1 -1
- package/dist/evals/surfaces/timeline.js +9 -2621
- package/dist/evals/surfaces/timeline.js.map +1 -1
- package/dist/evals/tool-loop-bridge.d.ts +4 -0
- package/dist/evals/tool-loop-bridge.d.ts.map +1 -1
- package/dist/evals/tool-loop-bridge.js.map +1 -1
- package/dist/evals/tool-loop-eval.d.ts +2 -0
- package/dist/evals/tool-loop-eval.d.ts.map +1 -1
- package/dist/evals/tool-loop-eval.js +6 -1
- package/dist/evals/tool-loop-eval.js.map +1 -1
- package/dist/evals/tool-loop-permission.d.ts +1 -15
- package/dist/evals/tool-loop-permission.d.ts.map +1 -1
- package/dist/evals/tool-loop-permission.js +23 -41
- package/dist/evals/tool-loop-permission.js.map +1 -1
- package/dist/game-authoring.d.ts +9573 -0
- package/dist/game-authoring.d.ts.map +1 -0
- package/dist/game-authoring.js +146 -0
- package/dist/game-authoring.js.map +1 -0
- package/dist/game-build.d.ts +3 -0
- package/dist/game-build.d.ts.map +1 -0
- package/dist/game-build.js +3 -0
- package/dist/game-build.js.map +1 -0
- package/dist/game-code-bake.d.ts +26 -0
- package/dist/game-code-bake.d.ts.map +1 -0
- package/dist/game-code-bake.js +98 -0
- package/dist/game-code-bake.js.map +1 -0
- package/dist/game-examples.d.ts +2227 -18
- package/dist/game-examples.d.ts.map +1 -1
- package/dist/game-examples.js +5 -4
- package/dist/game-examples.js.map +1 -1
- package/dist/generation-cancel.d.ts +31 -0
- package/dist/generation-cancel.d.ts.map +1 -0
- package/dist/generation-cancel.js +28 -0
- package/dist/generation-cancel.js.map +1 -0
- package/dist/host-access-gate.d.ts +29 -0
- package/dist/host-access-gate.d.ts.map +1 -0
- package/dist/host-access-gate.js +39 -0
- package/dist/host-access-gate.js.map +1 -0
- package/dist/host-modules/dispatcher.d.ts +7 -1
- package/dist/host-modules/dispatcher.d.ts.map +1 -1
- package/dist/host-modules/dispatcher.js +13 -2
- package/dist/host-modules/dispatcher.js.map +1 -1
- package/dist/host-modules/docx.d.ts.map +1 -1
- package/dist/host-modules/docx.js +2 -2
- package/dist/host-modules/docx.js.map +1 -1
- package/dist/host-modules/epub.d.ts.map +1 -1
- package/dist/host-modules/epub.js +2 -2
- package/dist/host-modules/epub.js.map +1 -1
- package/dist/host-modules/fabric.d.ts.map +1 -1
- package/dist/host-modules/fabric.js +1 -1
- package/dist/host-modules/fabric.js.map +1 -1
- package/dist/host-modules/limits.d.ts +10 -8
- package/dist/host-modules/limits.d.ts.map +1 -1
- package/dist/host-modules/limits.js +14 -9
- package/dist/host-modules/limits.js.map +1 -1
- package/dist/host-modules/mammoth.d.ts.map +1 -1
- package/dist/host-modules/mammoth.js +2 -2
- package/dist/host-modules/mammoth.js.map +1 -1
- package/dist/host-modules/ocr.d.ts.map +1 -1
- package/dist/host-modules/ocr.js +1 -1
- package/dist/host-modules/ocr.js.map +1 -1
- package/dist/host-modules/pdf.d.ts.map +1 -1
- package/dist/host-modules/pdf.js +2 -2
- package/dist/host-modules/pdf.js.map +1 -1
- package/dist/host-modules/pdflib.d.ts.map +1 -1
- package/dist/host-modules/pdflib.js +2 -2
- package/dist/host-modules/pdflib.js.map +1 -1
- package/dist/host-modules/pptx.d.ts.map +1 -1
- package/dist/host-modules/pptx.js +2 -2
- package/dist/host-modules/pptx.js.map +1 -1
- package/dist/host-modules/pptxgen.d.ts.map +1 -1
- package/dist/host-modules/pptxgen.js +2 -2
- package/dist/host-modules/pptxgen.js.map +1 -1
- package/dist/host-modules/tfjs.d.ts.map +1 -1
- package/dist/host-modules/tfjs.js +4 -4
- package/dist/host-modules/tfjs.js.map +1 -1
- package/dist/host-modules/xlsx.d.ts.map +1 -1
- package/dist/host-modules/xlsx.js +2 -2
- package/dist/host-modules/xlsx.js.map +1 -1
- package/dist/index.d.ts +18 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +17 -3
- package/dist/index.js.map +1 -1
- package/dist/js-sandbox-worker/engine.d.ts +4 -0
- package/dist/js-sandbox-worker/engine.d.ts.map +1 -0
- package/dist/js-sandbox-worker/engine.js +45 -0
- package/dist/js-sandbox-worker/engine.js.map +1 -0
- package/dist/js-sandbox-worker/host.js +1 -1
- package/dist/js-sandbox-worker/host.js.map +1 -1
- package/dist/js-sandbox-worker/interpreter.d.ts +1 -1
- package/dist/js-sandbox-worker/interpreter.d.ts.map +1 -1
- package/dist/js-sandbox-worker/interpreter.js +94 -2
- package/dist/js-sandbox-worker/interpreter.js.map +1 -1
- package/dist/js-sandbox-worker/worker-entry.d.ts.map +1 -1
- package/dist/js-sandbox-worker/worker-entry.js +3 -2
- package/dist/js-sandbox-worker/worker-entry.js.map +1 -1
- package/dist/js-sandbox.d.ts +9 -1
- package/dist/js-sandbox.d.ts.map +1 -1
- package/dist/js-sandbox.js +76 -15
- package/dist/js-sandbox.js.map +1 -1
- package/dist/js-script-app-runner.d.ts +2 -0
- package/dist/js-script-app-runner.d.ts.map +1 -1
- package/dist/js-script-app-runner.js +8 -3
- package/dist/js-script-app-runner.js.map +1 -1
- package/dist/js-script-sandbox.d.ts +12 -18
- package/dist/js-script-sandbox.d.ts.map +1 -1
- package/dist/js-script-sandbox.js +3 -49
- package/dist/js-script-sandbox.js.map +1 -1
- package/dist/prompts/product-knowledge.d.ts +1 -1
- package/dist/prompts/product-knowledge.d.ts.map +1 -1
- package/dist/prompts/product-knowledge.js +82 -41
- package/dist/prompts/product-knowledge.js.map +1 -1
- package/dist/sandbox-pack-resolution.d.ts +21 -0
- package/dist/sandbox-pack-resolution.d.ts.map +1 -0
- package/dist/sandbox-pack-resolution.js +42 -0
- package/dist/sandbox-pack-resolution.js.map +1 -0
- package/dist/sandbox-toolbelt.d.ts +3 -1
- package/dist/sandbox-toolbelt.d.ts.map +1 -1
- package/dist/sandbox-toolbelt.js +8 -2
- package/dist/sandbox-toolbelt.js.map +1 -1
- package/dist/skill-prompt.d.ts +11 -1
- package/dist/skill-prompt.d.ts.map +1 -1
- package/dist/skill-prompt.js +17 -6
- package/dist/skill-prompt.js.map +1 -1
- package/dist/system-skills.d.ts +7 -1
- package/dist/system-skills.d.ts.map +1 -1
- package/dist/system-skills.js +2 -2
- package/dist/system-skills.js.map +1 -1
- package/dist/timeline-capture.d.ts +21 -0
- package/dist/timeline-capture.d.ts.map +1 -0
- package/dist/timeline-capture.js +564 -0
- package/dist/timeline-capture.js.map +1 -0
- package/dist/timeline-code-bake.d.ts +75 -0
- package/dist/timeline-code-bake.d.ts.map +1 -0
- package/dist/timeline-code-bake.js +327 -0
- package/dist/timeline-code-bake.js.map +1 -0
- package/dist/timeline-preview/frames.d.ts +26 -0
- package/dist/timeline-preview/frames.d.ts.map +1 -1
- package/dist/timeline-preview/frames.js +155 -70
- package/dist/timeline-preview/frames.js.map +1 -1
- package/dist/tools/base-tool.d.ts +1 -0
- package/dist/tools/base-tool.d.ts.map +1 -1
- package/dist/tools/base-tool.js +1 -1
- package/dist/tools/base-tool.js.map +1 -1
- package/dist/tools/builtin-tools.d.ts +4 -3
- package/dist/tools/builtin-tools.d.ts.map +1 -1
- package/dist/tools/builtin-tools.js +24 -3
- package/dist/tools/builtin-tools.js.map +1 -1
- package/dist/tools/external-capability-tools.d.ts +1 -1
- package/dist/tools/external-capability-tools.js +1 -1
- package/dist/tools/mcp-tool-support.d.ts +10 -9
- package/dist/tools/mcp-tool-support.d.ts.map +1 -1
- package/dist/tools/mcp-tool-support.js +14 -13
- package/dist/tools/mcp-tool-support.js.map +1 -1
- package/dist/tools/mcp-tools.d.ts +6 -4
- package/dist/tools/mcp-tools.d.ts.map +1 -1
- package/dist/tools/mcp-tools.js +65 -62
- package/dist/tools/mcp-tools.js.map +1 -1
- package/dist/tools/tool-permissions.d.ts +1 -1
- package/dist/tools/tool-permissions.js +1 -1
- package/package.json +124 -41
- package/dist/capabilities/gate-tools.d.ts +0 -18
- package/dist/capabilities/gate-tools.d.ts.map +0 -1
- package/dist/capabilities/gate-tools.js +0 -66
- package/dist/capabilities/gate-tools.js.map +0 -1
- package/dist/tsconfig.tests.tmp.tsbuildinfo +0 -1
|
@@ -1,15 +1,21 @@
|
|
|
1
1
|
import { createHash, randomUUID } from "node:crypto";
|
|
2
2
|
import { mkdtemp, readFile, readdir, rm } from "node:fs/promises";
|
|
3
3
|
import { join } from "node:path";
|
|
4
|
-
import { getManagedWorkspaceDir, managedWorkspaceKey, workspaceStorageKind } from "@nodetool-ai/config";
|
|
5
|
-
import { AmbiguousGameIdError, Asset, Game, Prediction, Project, Workspace } from "@nodetool-ai/models";
|
|
6
|
-
import { gameAssetBinding, gameDocument, gameInputFrame, shortResourceId } from "@nodetool-ai/protocol";
|
|
7
|
-
import { autoplayNativeGame, MAX_GAME_ROUTE_TICKS, createScriptedGameSession, createTopDownRoomGame,
|
|
4
|
+
import { createLogger, getManagedWorkspaceDir, managedWorkspaceKey, workspaceStorageKind } from "@nodetool-ai/config";
|
|
5
|
+
import { AmbiguousGameIdError, MissingGameDraftSourceError, Asset, Game, Prediction, Project, Workspace } from "@nodetool-ai/models";
|
|
6
|
+
import { anyGameAssetBinding as gameAssetBinding, gameAssetBinding as legacyAssetBinding, gameAssetBinding3D, anyGameDocument as gameDocument, gameInputFrame, shortResourceId } from "@nodetool-ai/protocol";
|
|
7
|
+
import { autoplayNativeGame, MAX_GAME_ROUTE_TICKS, createScriptedGameSession, createTopDownRoomGame, createNative3DGame, decodePreparedGameCollider3D, validateAnyGame, trackGameAuthoringEdits, anyGameDocumentOp as gameDocumentOp, GameOpError } from "@nodetool-ai/game-runtime";
|
|
8
8
|
import { workspaceFromRow } from "@nodetool-ai/execution/service";
|
|
9
9
|
import { assetKeyCandidates, assetObjectKey } from "@nodetool-ai/storage";
|
|
10
|
+
import { gameOutline3D, inputFrames3D, playtestGame3D, captureFrames3D, colliderBinding3D, stageModelGameAsset3D } from "./game3d.js";
|
|
10
11
|
import { gameSpecs } from "./game.specs.js";
|
|
11
12
|
import { persistOutput } from "../tools/asset-persist.js";
|
|
12
13
|
import { getExampleGameBundle, installExampleGameAssets, listExampleGames } from "../game-examples.js";
|
|
14
|
+
import { previewGameAuthoring, applyGameAuthoring } from "../game-authoring.js";
|
|
15
|
+
import { gameDocumentDigest } from "../game-code-bake.js";
|
|
16
|
+
import { previewGameAuthoringSpec, applyGameAuthoringSpec, browseGameAssetsSpec } from "./game.specs.js";
|
|
17
|
+
import { browseGameAssets } from "./game-asset-browser.js";
|
|
18
|
+
const log = createLogger("capabilities.game");
|
|
13
19
|
const MAX_PLAYTEST_TICKS = MAX_GAME_ROUTE_TICKS;
|
|
14
20
|
const MAX_CAPTURE_FRAMES = 8;
|
|
15
21
|
const MAX_BUILD_ASSETS = 128;
|
|
@@ -24,7 +30,9 @@ const MEDIA_EXTENSIONS = {
|
|
|
24
30
|
"audio/ogg": "ogg",
|
|
25
31
|
"audio/mpeg": "mp3",
|
|
26
32
|
"font/ttf": "ttf",
|
|
27
|
-
"font/otf": "otf"
|
|
33
|
+
"font/otf": "otf",
|
|
34
|
+
"model/gltf-binary": "glb",
|
|
35
|
+
"application/json": "json"
|
|
28
36
|
};
|
|
29
37
|
function userId(run) {
|
|
30
38
|
return run.context.userId ?? null;
|
|
@@ -102,6 +110,9 @@ async function readSource(workspace, game, source, revision) {
|
|
|
102
110
|
return draft?.document ?? null;
|
|
103
111
|
}
|
|
104
112
|
function outline(document) {
|
|
113
|
+
if (document.schemaVersion === 3) {
|
|
114
|
+
return gameOutline3D(document);
|
|
115
|
+
}
|
|
105
116
|
return {
|
|
106
117
|
settings: {
|
|
107
118
|
schemaVersion: document.schemaVersion,
|
|
@@ -111,7 +122,8 @@ function outline(document) {
|
|
|
111
122
|
inputActions: document.inputActions,
|
|
112
123
|
collisionLayers: document.collisionLayers,
|
|
113
124
|
renderEffects: document.renderEffects,
|
|
114
|
-
hudEffectOrder: document.hudEffectOrder
|
|
125
|
+
hudEffectOrder: document.hudEffectOrder,
|
|
126
|
+
audio: document.audio
|
|
115
127
|
},
|
|
116
128
|
scenes: document.scenes.map((scene) => ({
|
|
117
129
|
id: scene.id,
|
|
@@ -174,6 +186,8 @@ async function captureFrames(run, user, document, ticks, inputs, seed, options)
|
|
|
174
186
|
return cancelled || wallTimeLimited;
|
|
175
187
|
};
|
|
176
188
|
const { captureGameFrame } = await import("@nodetool-ai/game-renderer/node");
|
|
189
|
+
const { GameParticles2D } = await import("@nodetool-ai/game-renderer");
|
|
190
|
+
const particles = new GameParticles2D(document.tickRate);
|
|
177
191
|
const diagnostics = [];
|
|
178
192
|
const storage = run.context.assetStorage;
|
|
179
193
|
const assetCache = new Map();
|
|
@@ -211,7 +225,9 @@ async function captureFrames(run, user, document, ticks, inputs, seed, options)
|
|
|
211
225
|
if (budgetReached()) {
|
|
212
226
|
break;
|
|
213
227
|
}
|
|
214
|
-
|
|
228
|
+
const step = session.step(inputs[simulatedTicks] ?? { pressed: [], justPressed: [] });
|
|
229
|
+
particles.tick(step.frame, session.takePresentationEvents());
|
|
230
|
+
simulatedTicks = step.tick;
|
|
215
231
|
}
|
|
216
232
|
if (budgetReached()) {
|
|
217
233
|
break;
|
|
@@ -228,11 +244,11 @@ async function captureFrames(run, user, document, ticks, inputs, seed, options)
|
|
|
228
244
|
const start = diagnostics.length;
|
|
229
245
|
let png;
|
|
230
246
|
try {
|
|
231
|
-
png = await captureGameFrame(frame, { resolveAsset, scale, effects: document.renderEffects, hudEffectOrder: document.hudEffectOrder, backend: document.renderEffects?.length ? "webgpu" : "canvas2d", onDiagnostic: (message) => diagnostics.push(message) });
|
|
247
|
+
png = await captureGameFrame(frame, { resolveAsset, scale, particles, effects: document.renderEffects, hudEffectOrder: document.hudEffectOrder, backend: document.renderEffects?.length ? "webgpu" : "canvas2d", onDiagnostic: (message) => diagnostics.push(message) });
|
|
232
248
|
}
|
|
233
249
|
catch (error) {
|
|
234
250
|
diagnostics.push(`WebGPU capture failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
235
|
-
png = await captureGameFrame(frame, { resolveAsset, scale, backend: "canvas2d", onDiagnostic: (message) => diagnostics.push(message) });
|
|
251
|
+
png = await captureGameFrame(frame, { resolveAsset, scale, particles, backend: "canvas2d", onDiagnostic: (message) => diagnostics.push(message) });
|
|
236
252
|
}
|
|
237
253
|
if (budgetReached()) {
|
|
238
254
|
break;
|
|
@@ -308,8 +324,8 @@ function validateSource(source, gameId, revision) {
|
|
|
308
324
|
const parsed = gameDocument.safeParse(source);
|
|
309
325
|
if (!parsed.success)
|
|
310
326
|
return { error: parsed.error.message };
|
|
311
|
-
const result =
|
|
312
|
-
return result.document
|
|
327
|
+
const result = validateAnyGame({ ...parsed.data, id: gameId, revision });
|
|
328
|
+
return result.valid ? result.document : { error: result.diagnostics.map((issue) => `${issue.code} ${issue.path.join(".")}: ${issue.message}`).join("; ") };
|
|
313
329
|
}
|
|
314
330
|
function summary(game) {
|
|
315
331
|
return {
|
|
@@ -319,25 +335,52 @@ function summary(game) {
|
|
|
319
335
|
workspace_id: game.workspace_id
|
|
320
336
|
};
|
|
321
337
|
}
|
|
322
|
-
async function publish(user, game,
|
|
338
|
+
async function publish(user, game, request) {
|
|
339
|
+
const baseRevision = request.base_revision;
|
|
323
340
|
if (game.current_revision !== baseRevision)
|
|
324
341
|
return { error: "Game was modified concurrently", current_revision: game.current_revision };
|
|
325
342
|
const revision = randomUUID().replace(/-/g, "");
|
|
326
|
-
const document = validateSource(source, game.id, revision);
|
|
327
|
-
if ("error" in document)
|
|
328
|
-
return document;
|
|
329
343
|
const workspace = await workspaceOf(user, game);
|
|
330
344
|
if (!workspace)
|
|
331
345
|
return { error: "Game workspace is unavailable" };
|
|
332
346
|
const draft = await Game.readDraft(user, game.id, workspace);
|
|
333
347
|
if (!draft)
|
|
334
348
|
return { error: "Game draft not found" };
|
|
349
|
+
const draftToken = request.document ? request.base_updated_at : draft.game.draft_updated_at;
|
|
350
|
+
if (draftToken !== draft.game.draft_updated_at) {
|
|
351
|
+
return { error: "Game draft was modified concurrently" };
|
|
352
|
+
}
|
|
353
|
+
let document = validateSource(request.document ?? draft.document, game.id, revision);
|
|
354
|
+
if ("error" in document)
|
|
355
|
+
return document;
|
|
356
|
+
if ((document.schemaVersion === 3) !== (draft.document.schemaVersion === 3)) {
|
|
357
|
+
return { error: "A game cannot change dimension" };
|
|
358
|
+
}
|
|
359
|
+
if (gameDocumentDigest(document.authoring) !== gameDocumentDigest(draft.document.authoring)) {
|
|
360
|
+
return { error: "Retained authoring metadata must be updated through construction preview and apply" };
|
|
361
|
+
}
|
|
362
|
+
document = trackGameAuthoringEdits(draft.document, document);
|
|
363
|
+
const checked = validateAnyGame(document);
|
|
364
|
+
if (!checked.valid) {
|
|
365
|
+
return { error: "Game publication rejected", diagnostics: checked.diagnostics };
|
|
366
|
+
}
|
|
335
367
|
await workspace.write(revisionPath(game, revision), JSON.stringify(document), "application/json");
|
|
336
|
-
const updated = await Game.publish(user, game.id, baseRevision, revision,
|
|
337
|
-
if (!updated)
|
|
368
|
+
const updated = await Game.publish(user, game.id, baseRevision, revision, draftToken, workspace, request.message);
|
|
369
|
+
if (!updated) {
|
|
370
|
+
try {
|
|
371
|
+
await workspace.delete(revisionPath(game, revision));
|
|
372
|
+
}
|
|
373
|
+
catch (error) {
|
|
374
|
+
log.error("Losing game publication revision cleanup failed", { gameId: game.id, revision, error: String(error) });
|
|
375
|
+
}
|
|
338
376
|
return { error: "Game was modified concurrently" };
|
|
339
|
-
|
|
340
|
-
|
|
377
|
+
}
|
|
378
|
+
try {
|
|
379
|
+
await Game.pruneRevisionFiles(user, game.id, workspace);
|
|
380
|
+
}
|
|
381
|
+
catch (error) {
|
|
382
|
+
log.error("Game publication revision cleanup failed", { gameId: game.id, error: String(error) });
|
|
383
|
+
}
|
|
341
384
|
return { game: summary(updated), document };
|
|
342
385
|
}
|
|
343
386
|
const create = {
|
|
@@ -349,14 +392,26 @@ const create = {
|
|
|
349
392
|
if (!user || typeof projectId !== "string" || typeof name !== "string" || !name.trim()) {
|
|
350
393
|
return { error: "project_id and name are required in a user session" };
|
|
351
394
|
}
|
|
352
|
-
const
|
|
395
|
+
const dimension = args["dimension"];
|
|
396
|
+
if (dimension !== undefined && dimension !== "2d" && dimension !== "3d") {
|
|
397
|
+
return { error: "dimension must be 2d or 3d" };
|
|
398
|
+
}
|
|
399
|
+
if (args["template"] !== undefined && args["template"] !== "exploration" && args["template"] !== "topdown") {
|
|
400
|
+
return { error: "Unknown native game template" };
|
|
401
|
+
}
|
|
402
|
+
if (args["template"] !== undefined && args["template"] !== (dimension === "3d" ? "exploration" : "topdown")) {
|
|
403
|
+
return { error: "Template does not match the requested dimension" };
|
|
404
|
+
}
|
|
405
|
+
const created = await createNativeGame(user, projectId, name.trim(), undefined, dimension ?? "2d");
|
|
353
406
|
return "error" in created
|
|
354
407
|
? created
|
|
355
408
|
: { game: summary(created.game), document: created.document };
|
|
356
409
|
}
|
|
357
410
|
};
|
|
358
|
-
|
|
359
|
-
|
|
411
|
+
export async function createNativeGame(user, projectId, name, source, dimension = "2d") {
|
|
412
|
+
if (source?.authoring) {
|
|
413
|
+
return { error: "Attach retained construction through preview and apply after creating the game" };
|
|
414
|
+
}
|
|
360
415
|
const project = await Project.findOwned(user, projectId);
|
|
361
416
|
if (!project)
|
|
362
417
|
return { error: "Project not found" };
|
|
@@ -366,9 +421,12 @@ export async function createNativeGame(user, projectId, name, source) {
|
|
|
366
421
|
return { error: "Project workspace is unavailable" };
|
|
367
422
|
const id = randomUUID().replace(/-/g, "");
|
|
368
423
|
const revision = randomUUID().replace(/-/g, "");
|
|
369
|
-
const document = validateSource(source ?? { ...createTopDownRoomGame(id), schemaVersion:
|
|
424
|
+
const document = validateSource(source ?? (dimension === "3d" ? createNative3DGame(id) : { ...createTopDownRoomGame(id), schemaVersion: 4, engineVersion: "3" }), id, revision);
|
|
370
425
|
if ("error" in document)
|
|
371
426
|
return document;
|
|
427
|
+
if (source && ((document.schemaVersion === 3) !== (dimension === "3d"))) {
|
|
428
|
+
return { error: "Supplied document does not match the requested dimension" };
|
|
429
|
+
}
|
|
372
430
|
const game = new Game({
|
|
373
431
|
id,
|
|
374
432
|
user_id: user,
|
|
@@ -395,13 +453,18 @@ const get = {
|
|
|
395
453
|
const id = args["game_id"];
|
|
396
454
|
if (!user || typeof id !== "string")
|
|
397
455
|
return { error: "game_id is required in a user session" };
|
|
398
|
-
|
|
456
|
+
let game = await ownedGame(user, id);
|
|
399
457
|
if (!game)
|
|
400
458
|
return { error: "Game not found" };
|
|
401
459
|
const workspace = await workspaceOf(user, game);
|
|
402
460
|
if (!workspace)
|
|
403
461
|
return { error: "Game workspace is unavailable" };
|
|
404
|
-
const
|
|
462
|
+
const readsDraft = (args["source"] === undefined || args["source"] === "draft") && args["revision"] === undefined;
|
|
463
|
+
const draft = readsDraft ? await Game.readDraft(user, game.id, workspace) : null;
|
|
464
|
+
const document = readsDraft ? draft?.document : await readSource(workspace, game, args["source"], args["revision"]);
|
|
465
|
+
if (draft) {
|
|
466
|
+
game = draft.game;
|
|
467
|
+
}
|
|
405
468
|
if (!document)
|
|
406
469
|
return { error: "Game source not found" };
|
|
407
470
|
const view = args["view"] ?? "outline";
|
|
@@ -430,11 +493,19 @@ const save = {
|
|
|
430
493
|
const game = await ownedGame(user, id);
|
|
431
494
|
if (!game)
|
|
432
495
|
return { error: "Game not found" };
|
|
433
|
-
const
|
|
434
|
-
if (
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
496
|
+
const request = { game_id: id, base_revision: base, message: typeof args["message"] === "string" ? args["message"] : undefined };
|
|
497
|
+
if (args["document"] !== undefined) {
|
|
498
|
+
const token = args["base_updated_at"];
|
|
499
|
+
if (typeof token !== "string" || !token) {
|
|
500
|
+
return { error: "base_updated_at is required with an explicit document" };
|
|
501
|
+
}
|
|
502
|
+
const parsed = gameDocument.safeParse(args["document"]);
|
|
503
|
+
if (!parsed.success) {
|
|
504
|
+
return { error: parsed.error.message };
|
|
505
|
+
}
|
|
506
|
+
return publish(user, game, { ...request, document: parsed.data, base_updated_at: token });
|
|
507
|
+
}
|
|
508
|
+
return publish(user, game, request);
|
|
438
509
|
}
|
|
439
510
|
};
|
|
440
511
|
const edit = {
|
|
@@ -494,6 +565,9 @@ const install = {
|
|
|
494
565
|
if (parsed.data.mediaKind === "font" && !parsed.data.fontFormat) {
|
|
495
566
|
return { error: "Font binding needs a TrueType or OpenType format" };
|
|
496
567
|
}
|
|
568
|
+
if (parsed.data.mediaKind === "hdri") {
|
|
569
|
+
return { error: "HDRI candidates cannot be installed until HDRI preparation verifies their bytes and dimensions" };
|
|
570
|
+
}
|
|
497
571
|
const workspace = await workspaceOf(user, game);
|
|
498
572
|
if (!workspace)
|
|
499
573
|
return { error: "Game workspace is unavailable" };
|
|
@@ -510,11 +584,13 @@ const install = {
|
|
|
510
584
|
return { error: "Candidate workspace is unavailable" };
|
|
511
585
|
candidateWorkspace = resolved;
|
|
512
586
|
}
|
|
513
|
-
const formats = parsed.data.mediaKind === "
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
587
|
+
const formats = parsed.data.mediaKind === "model" ? [["glb", "model/gltf-binary"]]
|
|
588
|
+
: parsed.data.mediaKind === "collider" ? [["json", "application/json"]]
|
|
589
|
+
: parsed.data.mediaKind === "audio"
|
|
590
|
+
? [["wav", "audio/wav"], ["mp3", "audio/mpeg"], ["ogg", "audio/ogg"]]
|
|
591
|
+
: parsed.data.mediaKind === "font"
|
|
592
|
+
? [[parsed.data.fontFormat, `font/${parsed.data.fontFormat}`]]
|
|
593
|
+
: [["png", "image/png"], ["jpg", "image/jpeg"], ["webp", "image/webp"]];
|
|
518
594
|
let candidate = null;
|
|
519
595
|
for (const [extension, contentType] of formats) {
|
|
520
596
|
if (!extension)
|
|
@@ -536,6 +612,45 @@ const install = {
|
|
|
536
612
|
if (!draft)
|
|
537
613
|
return { error: "Game draft is missing" };
|
|
538
614
|
const expectedUpdatedAt = typeof args["base_updated_at"] === "string" ? args["base_updated_at"] : draft.game.draft_updated_at;
|
|
615
|
+
let binding = parsed.data;
|
|
616
|
+
try {
|
|
617
|
+
if (binding.mediaKind === "model") {
|
|
618
|
+
const { prepareGameModelBinding3D } = await import("@nodetool-ai/game-renderer/preparation3d");
|
|
619
|
+
const prepared = await prepareGameModelBinding3D(bytes, { assetId: binding.assetId, expectedDigest: binding.digest, signal: run.context.signal });
|
|
620
|
+
if (!prepared.ok) {
|
|
621
|
+
return { error: "Model preparation failed", diagnostics: prepared.diagnostics };
|
|
622
|
+
}
|
|
623
|
+
const sourceAsset = binding.sourceAssetId ? await Asset.find(user, binding.sourceAssetId) : null;
|
|
624
|
+
if (binding.sourceAssetId && !sourceAsset) {
|
|
625
|
+
return { error: "Model source asset is not owned" };
|
|
626
|
+
}
|
|
627
|
+
const canonical = { ...prepared.binding, required: binding.required };
|
|
628
|
+
if (binding.provenance) {
|
|
629
|
+
canonical.provenance = binding.provenance;
|
|
630
|
+
}
|
|
631
|
+
if (binding.importSettings) {
|
|
632
|
+
canonical.importSettings = binding.importSettings;
|
|
633
|
+
}
|
|
634
|
+
if (binding.sourceDigest) {
|
|
635
|
+
canonical.sourceDigest = binding.sourceDigest;
|
|
636
|
+
}
|
|
637
|
+
if (sourceAsset) {
|
|
638
|
+
canonical.sourceAssetId = sourceAsset.id;
|
|
639
|
+
}
|
|
640
|
+
binding = canonical;
|
|
641
|
+
}
|
|
642
|
+
else if (binding.mediaKind === "collider") {
|
|
643
|
+
binding = colliderBinding3D(bytes, binding);
|
|
644
|
+
await decodePreparedGameCollider3D(bytes, gameAssetBinding3D.options[1].parse(binding));
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
catch (error) {
|
|
648
|
+
return { error: error instanceof Error ? error.message : String(error) };
|
|
649
|
+
}
|
|
650
|
+
const targetBinding = draft.document.schemaVersion === 3 ? gameAssetBinding3D.safeParse(binding) : legacyAssetBinding.safeParse(binding);
|
|
651
|
+
if (!targetBinding.success) {
|
|
652
|
+
return { error: "Asset binding does not match the game dimension" };
|
|
653
|
+
}
|
|
539
654
|
const storage = run.context.assetStorage;
|
|
540
655
|
if (!storage)
|
|
541
656
|
return { error: "Asset storage is unavailable" };
|
|
@@ -558,7 +673,8 @@ const install = {
|
|
|
558
673
|
uri = await storage.store(key, bytes, contentType);
|
|
559
674
|
let result;
|
|
560
675
|
try {
|
|
561
|
-
const
|
|
676
|
+
const op = gameDocumentOp.parse({ op: "bind_asset", slot, binding: { ...targetBinding.data, assetId: installed.id } });
|
|
677
|
+
const updated = await Game.updateDraft(user, game.id, expectedUpdatedAt, [op], workspace, { actor: "agent", threadId: run.context.threadId ?? undefined, messageId: run.context.get?.("chat_message_id") ?? undefined });
|
|
562
678
|
result = updated ? { game: summary(updated.game), draft_updated_at: updated.game.draft_updated_at, document: updated.document } : { error: "Game draft was modified concurrently" };
|
|
563
679
|
}
|
|
564
680
|
catch (error) {
|
|
@@ -597,6 +713,15 @@ const playtest = {
|
|
|
597
713
|
const document = await readSource(workspace, game, args["source"], args["revision"]);
|
|
598
714
|
if (!document)
|
|
599
715
|
return { error: "Game source not found" };
|
|
716
|
+
if (document.schemaVersion === 3) {
|
|
717
|
+
try {
|
|
718
|
+
return await playtestGame3D(run, user, document, args);
|
|
719
|
+
}
|
|
720
|
+
catch (error) {
|
|
721
|
+
run.context.signal?.throwIfAborted();
|
|
722
|
+
return { error: error instanceof Error ? error.message : String(error), code: "game3d_preparation_failed" };
|
|
723
|
+
}
|
|
724
|
+
}
|
|
600
725
|
const captures = captureTicks(args["capture_ticks"], []);
|
|
601
726
|
if ("error" in captures)
|
|
602
727
|
return captures;
|
|
@@ -732,6 +857,20 @@ const capture = {
|
|
|
732
857
|
const ticks = captureTicks(args["ticks"], [0]);
|
|
733
858
|
if ("error" in ticks)
|
|
734
859
|
return ticks;
|
|
860
|
+
if (document.schemaVersion === 3) {
|
|
861
|
+
const inputs = inputFrames3D(args["inputs"], Math.max(0, ...ticks));
|
|
862
|
+
if ("error" in inputs) {
|
|
863
|
+
return inputs;
|
|
864
|
+
}
|
|
865
|
+
const seed = typeof args["seed"] === "number" && Number.isSafeInteger(args["seed"]) ? args["seed"] : 1;
|
|
866
|
+
try {
|
|
867
|
+
return await captureFrames3D(run, user, document, ticks, inputs, seed, args);
|
|
868
|
+
}
|
|
869
|
+
catch (error) {
|
|
870
|
+
run.context.signal?.throwIfAborted();
|
|
871
|
+
return { error: error instanceof Error ? error.message : String(error), code: "game3d_capture_failed" };
|
|
872
|
+
}
|
|
873
|
+
}
|
|
735
874
|
const inputs = inputFrames(args["inputs"], Math.max(0, ...ticks));
|
|
736
875
|
if ("error" in inputs)
|
|
737
876
|
return inputs;
|
|
@@ -754,7 +893,7 @@ const generateAsset = {
|
|
|
754
893
|
const kind = args["kind"];
|
|
755
894
|
const prompt = args["prompt"];
|
|
756
895
|
const inputFile = args["input_file"];
|
|
757
|
-
if (!user || typeof id !== "string" || typeof slot !== "string" || !slot || !["image", "audio", "music", "sfx", "font"].includes(String(kind))) {
|
|
896
|
+
if (!user || typeof id !== "string" || typeof slot !== "string" || !slot || !["image", "audio", "music", "sfx", "font", "model", "collider"].includes(String(kind))) {
|
|
758
897
|
return { error: "game_id, slot, and kind are required" };
|
|
759
898
|
}
|
|
760
899
|
if (inputFile !== undefined && (typeof inputFile !== "string" || !inputFile.trim())) {
|
|
@@ -772,6 +911,21 @@ const generateAsset = {
|
|
|
772
911
|
if (!draft) {
|
|
773
912
|
return { error: "Game draft not found" };
|
|
774
913
|
}
|
|
914
|
+
if (kind === "model" || kind === "collider") {
|
|
915
|
+
if (draft.document.schemaVersion !== 3) {
|
|
916
|
+
return { error: "Model and collider assets require a 3D game" };
|
|
917
|
+
}
|
|
918
|
+
try {
|
|
919
|
+
return await stageModelGameAsset3D(run, game, workspace, draft.document, args);
|
|
920
|
+
}
|
|
921
|
+
catch (error) {
|
|
922
|
+
run.context.signal?.throwIfAborted();
|
|
923
|
+
return { error: error instanceof Error ? error.message : String(error) };
|
|
924
|
+
}
|
|
925
|
+
}
|
|
926
|
+
if (draft.document.schemaVersion === 3 && kind === "image") {
|
|
927
|
+
return { error: "3D games use model assets with embedded textures" };
|
|
928
|
+
}
|
|
775
929
|
const reference = typeof args["reference_slot"] === "string" ? draft.document.assets[args["reference_slot"]] : undefined;
|
|
776
930
|
if (args["reference_slot"] !== undefined && !reference) {
|
|
777
931
|
return { error: "reference_slot is not bound" };
|
|
@@ -791,7 +945,7 @@ const generateAsset = {
|
|
|
791
945
|
let provider = args["provider"];
|
|
792
946
|
let model = args["model"];
|
|
793
947
|
let generated = {};
|
|
794
|
-
let sourceBytes
|
|
948
|
+
let sourceBytes;
|
|
795
949
|
const makeLut = settings?.success && settings.data.lut !== undefined;
|
|
796
950
|
if (makeLut && (inputFile !== undefined || reference || args["generation_id"] !== undefined)) {
|
|
797
951
|
return { error: "LUT preparation creates a color cube directly and cannot use input_file, reference_slot or generation_id" };
|
|
@@ -908,7 +1062,7 @@ const generateAsset = {
|
|
|
908
1062
|
let height = 1;
|
|
909
1063
|
const previous = draft.document.assets[slot];
|
|
910
1064
|
const binding = {
|
|
911
|
-
width, height, pivot: previous
|
|
1065
|
+
width, height, pivot: previous && "pivot" in previous ? previous.pivot : { x: 0.5, y: 0.5 }, sampling: previous && "sampling" in previous ? previous.sampling : "nearest"
|
|
912
1066
|
};
|
|
913
1067
|
let frames;
|
|
914
1068
|
let tiles;
|
|
@@ -940,7 +1094,7 @@ const generateAsset = {
|
|
|
940
1094
|
if (prepared.baseline !== undefined && frames?.[0]) {
|
|
941
1095
|
binding.pivot = { x: 0.5, y: (prepared.baseline + 1) / frames[0].height };
|
|
942
1096
|
}
|
|
943
|
-
if (draft.document.schemaVersion
|
|
1097
|
+
if (draft.document.schemaVersion !== 1) {
|
|
944
1098
|
binding.preparation = imagePreparationMetadata(settings.data);
|
|
945
1099
|
binding.originalDimensions = { width: prepared.originalWidth, height: prepared.originalHeight };
|
|
946
1100
|
if (prepared.trim) {
|
|
@@ -978,10 +1132,41 @@ const generateAsset = {
|
|
|
978
1132
|
binding.digest = digest;
|
|
979
1133
|
binding.width = width;
|
|
980
1134
|
binding.height = height;
|
|
981
|
-
if (draft.document.schemaVersion
|
|
1135
|
+
if (draft.document.schemaVersion !== 1 && draft.document.schemaVersion !== 3) {
|
|
982
1136
|
binding.provenance = typeof inputFile === "string" ? `import:${inputFile}`
|
|
983
1137
|
: makeLut ? "generated:color-cube" : kind === "sfx" ? `node:${args["node_type"]}` : `${provider}:${model}:${generated.generation_id ?? ""}`;
|
|
984
1138
|
}
|
|
1139
|
+
if (draft.document.schemaVersion === 3) {
|
|
1140
|
+
delete binding.width;
|
|
1141
|
+
delete binding.height;
|
|
1142
|
+
delete binding.pivot;
|
|
1143
|
+
delete binding.sampling;
|
|
1144
|
+
const parsedBinding = gameAssetBinding3D.safeParse(binding);
|
|
1145
|
+
if (!parsedBinding.success) {
|
|
1146
|
+
return { error: "Invalid 3D asset binding", diagnostics: parsedBinding.error.issues };
|
|
1147
|
+
}
|
|
1148
|
+
return { game_id: shortResourceId(game.id), slot, binding: parsedBinding.data, candidate_workspace_id: game.workspace_id,
|
|
1149
|
+
draft_updated_at: draft.game.draft_updated_at, installed: false, next: "Call install_native_game_asset with this binding to install the candidate." };
|
|
1150
|
+
}
|
|
1151
|
+
if (args["install"] === false) {
|
|
1152
|
+
const parsedBinding = legacyAssetBinding.safeParse(binding);
|
|
1153
|
+
if (!parsedBinding.success) {
|
|
1154
|
+
return { error: "Invalid asset binding", diagnostics: parsedBinding.error.issues };
|
|
1155
|
+
}
|
|
1156
|
+
const staged = { game_id: shortResourceId(game.id), slot, binding: parsedBinding.data, candidate_workspace_id: game.workspace_id,
|
|
1157
|
+
draft_updated_at: draft.game.draft_updated_at, installed: false, generation_id: generated.generation_id,
|
|
1158
|
+
next: "Call install_native_game_asset with this binding to install the candidate." };
|
|
1159
|
+
if (frames) {
|
|
1160
|
+
staged.frames = frames;
|
|
1161
|
+
}
|
|
1162
|
+
if (tiles) {
|
|
1163
|
+
staged.tiles = tiles;
|
|
1164
|
+
}
|
|
1165
|
+
if (lutSize) {
|
|
1166
|
+
staged.lut_size = lutSize;
|
|
1167
|
+
}
|
|
1168
|
+
return staged;
|
|
1169
|
+
}
|
|
985
1170
|
const installed = await install.impl(run, { game_id: game.id, slot, binding, base_updated_at: draft.game.draft_updated_at });
|
|
986
1171
|
if (typeof installed !== "object" || installed === null) {
|
|
987
1172
|
return { generation_id: generated.generation_id, result: installed };
|
|
@@ -1008,133 +1193,177 @@ const generateAsset = {
|
|
|
1008
1193
|
return { generation_id: generated.generation_id, ...installed, ...extras };
|
|
1009
1194
|
}
|
|
1010
1195
|
};
|
|
1011
|
-
const
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1196
|
+
const BUILD_CONTENT_TYPES = {
|
|
1197
|
+
js: "text/javascript", css: "text/css", json: "application/json", html: "text/html", png: "image/png", jpg: "image/jpeg",
|
|
1198
|
+
webp: "image/webp", wav: "audio/wav", ogg: "audio/ogg", mp3: "audio/mpeg", ttf: "font/ttf", otf: "font/otf",
|
|
1199
|
+
glb: "model/gltf-binary", wasm: "application/wasm", md: "text/markdown", toml: "text/plain", rs: "text/plain",
|
|
1200
|
+
ico: "image/vnd.microsoft.icon", icns: "image/icns"
|
|
1201
|
+
};
|
|
1202
|
+
/**
|
|
1203
|
+
* Builds an owned, published game revision into its project workspace: a static web player under
|
|
1204
|
+
* `game-builds/<game-id>/<revision>`, or a Tauri desktop project under `game-builds/<game-id>/<revision>-tauri-<settings>`.
|
|
1205
|
+
* The capability and the editor's export download share this path.
|
|
1206
|
+
*/
|
|
1207
|
+
export async function buildOwnedNativeGame(request) {
|
|
1208
|
+
const user = request.userId;
|
|
1209
|
+
const target = request.target ?? "web";
|
|
1210
|
+
const game = await ownedGame(user, request.gameId);
|
|
1211
|
+
if (!game)
|
|
1212
|
+
return { error: "Game not found" };
|
|
1213
|
+
const workspace = await workspaceOf(user, game);
|
|
1214
|
+
if (!workspace)
|
|
1215
|
+
return { error: "Game workspace is unavailable" };
|
|
1216
|
+
const revision = request.revision ?? game.current_revision;
|
|
1217
|
+
const document = await readDocument(workspace, game, revision);
|
|
1218
|
+
if (!document)
|
|
1219
|
+
return { error: "Game revision not found" };
|
|
1220
|
+
if (Object.keys(document.assets).length > MAX_BUILD_ASSETS) {
|
|
1221
|
+
return { error: `A standalone build supports at most ${MAX_BUILD_ASSETS} assets` };
|
|
1222
|
+
}
|
|
1223
|
+
const expectedDigests = new Map();
|
|
1224
|
+
for (const binding of Object.values(document.assets)) {
|
|
1225
|
+
if (binding.assetId.startsWith("builtin:"))
|
|
1226
|
+
continue;
|
|
1227
|
+
const digests = expectedDigests.get(binding.assetId) ?? new Set();
|
|
1228
|
+
digests.add(binding.digest);
|
|
1229
|
+
expectedDigests.set(binding.assetId, digests);
|
|
1230
|
+
}
|
|
1231
|
+
if ([...expectedDigests.values()].some((digests) => digests.size !== 1)) {
|
|
1232
|
+
return { error: "One source asset has conflicting digests in this revision" };
|
|
1233
|
+
}
|
|
1234
|
+
let buildPath = `game-builds/${game.id}/${revision}`;
|
|
1235
|
+
let entryPath = `${buildPath}/index.html`;
|
|
1236
|
+
let tauriApp;
|
|
1237
|
+
let metadata;
|
|
1238
|
+
if (target === "tauri") {
|
|
1239
|
+
tauriApp = { name: game.name };
|
|
1240
|
+
const { tauriAppMetadata } = await import("@nodetool-ai/game-renderer/build-tauri");
|
|
1241
|
+
try {
|
|
1242
|
+
metadata = tauriAppMetadata(document, tauriApp);
|
|
1030
1243
|
}
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
if (binding.assetId.startsWith("builtin:"))
|
|
1034
|
-
continue;
|
|
1035
|
-
const digests = expectedDigests.get(binding.assetId) ?? new Set();
|
|
1036
|
-
digests.add(binding.digest);
|
|
1037
|
-
expectedDigests.set(binding.assetId, digests);
|
|
1244
|
+
catch (error) {
|
|
1245
|
+
return { error: error instanceof Error ? error.message : String(error) };
|
|
1038
1246
|
}
|
|
1039
|
-
|
|
1040
|
-
|
|
1247
|
+
// The app name comes from the game row, which can change without a new revision.
|
|
1248
|
+
const settings = createHash("sha256").update(JSON.stringify(metadata)).digest("hex").slice(0, 12);
|
|
1249
|
+
buildPath = `game-builds/${game.id}/${revision}-tauri-${settings}`;
|
|
1250
|
+
entryPath = `${buildPath}/src-tauri/tauri.conf.json`;
|
|
1251
|
+
}
|
|
1252
|
+
const done = { game_id: game.id, revision, target, build_path: buildPath, entry_path: entryPath, workspace, app: metadata ?? null };
|
|
1253
|
+
if (await workspace.exists(entryPath)) {
|
|
1254
|
+
return { ...done, cached: true };
|
|
1255
|
+
}
|
|
1256
|
+
const storage = request.storage;
|
|
1257
|
+
const cache = new Map();
|
|
1258
|
+
let totalAssetBytes = 0;
|
|
1259
|
+
const resolveAsset = async (assetId) => {
|
|
1260
|
+
const cached = cache.get(assetId);
|
|
1261
|
+
if (cached)
|
|
1262
|
+
return cached;
|
|
1263
|
+
if (!/^[a-f0-9]{32}$/.test(assetId))
|
|
1264
|
+
return null;
|
|
1265
|
+
const asset = await Asset.find(user, assetId);
|
|
1266
|
+
if (!asset || !storage)
|
|
1267
|
+
return null;
|
|
1268
|
+
const extension = MEDIA_EXTENSIONS[asset.content_type];
|
|
1269
|
+
if (!extension || (asset.size !== null && asset.size > MAX_BUILD_ASSET_BYTES))
|
|
1270
|
+
return null;
|
|
1271
|
+
const keys = assetKeyCandidates(user, `${asset.id}.${extension}`);
|
|
1272
|
+
let bytes = null;
|
|
1273
|
+
for (const key of keys) {
|
|
1274
|
+
bytes = await storage.retrieve(storage.uriForKey(key));
|
|
1275
|
+
if (bytes)
|
|
1276
|
+
break;
|
|
1041
1277
|
}
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1278
|
+
if (!bytes || bytes.byteLength > MAX_BUILD_ASSET_BYTES)
|
|
1279
|
+
return null;
|
|
1280
|
+
const digest = createHash("sha256").update(bytes).digest("hex");
|
|
1281
|
+
if (!expectedDigests.get(assetId)?.has(digest)) {
|
|
1282
|
+
throw new Error(`Asset digest changed for ${assetId}`);
|
|
1046
1283
|
}
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
}
|
|
1069
|
-
if (!bytes || bytes.byteLength > MAX_BUILD_ASSET_BYTES)
|
|
1070
|
-
return null;
|
|
1071
|
-
const digest = createHash("sha256").update(bytes).digest("hex");
|
|
1072
|
-
if (!expectedDigests.get(assetId)?.has(digest)) {
|
|
1073
|
-
throw new Error(`Asset digest changed for ${assetId}`);
|
|
1074
|
-
}
|
|
1075
|
-
totalAssetBytes += bytes.byteLength;
|
|
1076
|
-
if (totalAssetBytes > MAX_BUILD_BYTES) {
|
|
1077
|
-
throw new Error(`A standalone build supports at most ${MAX_BUILD_BYTES} asset bytes`);
|
|
1078
|
-
}
|
|
1079
|
-
const resolved = { bytes, mimeType: asset.content_type };
|
|
1080
|
-
cache.set(assetId, resolved);
|
|
1081
|
-
return resolved;
|
|
1082
|
-
};
|
|
1083
|
-
const scratch = await workspace.scratchDir();
|
|
1084
|
-
const staging = await mkdtemp(join(scratch, ".native-game-build-"));
|
|
1085
|
-
try {
|
|
1284
|
+
totalAssetBytes += bytes.byteLength;
|
|
1285
|
+
if (totalAssetBytes > MAX_BUILD_BYTES) {
|
|
1286
|
+
throw new Error(`A standalone build supports at most ${MAX_BUILD_BYTES} asset bytes`);
|
|
1287
|
+
}
|
|
1288
|
+
const resolved = { bytes, mimeType: asset.content_type };
|
|
1289
|
+
cache.set(assetId, resolved);
|
|
1290
|
+
return resolved;
|
|
1291
|
+
};
|
|
1292
|
+
const scratch = await workspace.scratchDir();
|
|
1293
|
+
const staging = await mkdtemp(join(scratch, ".native-game-build-"));
|
|
1294
|
+
try {
|
|
1295
|
+
const output = join(staging, "player");
|
|
1296
|
+
if (tauriApp) {
|
|
1297
|
+
const { buildTauriGameProject } = await import("@nodetool-ai/game-renderer/build-tauri");
|
|
1298
|
+
await buildTauriGameProject({ document, outputDir: output, resolveAsset, app: tauriApp, signal: request.signal });
|
|
1299
|
+
}
|
|
1300
|
+
else if (document.schemaVersion === 3) {
|
|
1301
|
+
const { buildStandaloneGame3D } = await import("@nodetool-ai/game-renderer/build3d");
|
|
1302
|
+
await buildStandaloneGame3D({ document, outputDir: output, resolveAsset, signal: request.signal });
|
|
1303
|
+
}
|
|
1304
|
+
else {
|
|
1086
1305
|
const { buildStandaloneGame } = await import("@nodetool-ai/game-renderer/build");
|
|
1087
|
-
await buildStandaloneGame({ document, outputDir:
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
files.push({ path, bytes });
|
|
1306
|
+
await buildStandaloneGame({ document, outputDir: output, resolveAsset });
|
|
1307
|
+
}
|
|
1308
|
+
const files = [];
|
|
1309
|
+
const pending = [""];
|
|
1310
|
+
let totalBytes = 0;
|
|
1311
|
+
while (pending.length > 0) {
|
|
1312
|
+
const directory = pending.pop() ?? "";
|
|
1313
|
+
for (const entry of await readdir(join(output, directory), { withFileTypes: true })) {
|
|
1314
|
+
const path = directory ? `${directory}/${entry.name}` : entry.name;
|
|
1315
|
+
if (entry.isDirectory()) {
|
|
1316
|
+
pending.push(path);
|
|
1317
|
+
}
|
|
1318
|
+
else if (entry.isFile()) {
|
|
1319
|
+
const bytes = await readFile(join(output, path));
|
|
1320
|
+
totalBytes += bytes.byteLength;
|
|
1321
|
+
if (files.length >= MAX_BUILD_FILES || totalBytes > MAX_BUILD_BYTES) {
|
|
1322
|
+
throw new Error("Standalone build exceeds file or byte limits");
|
|
1105
1323
|
}
|
|
1324
|
+
files.push({ path, bytes });
|
|
1106
1325
|
}
|
|
1107
1326
|
}
|
|
1108
|
-
if (!files.some((file) => file.path === "index.html")) {
|
|
1109
|
-
throw new Error("Standalone player entry is missing");
|
|
1110
|
-
}
|
|
1111
|
-
for (const file of files.filter((item) => item.path !== "index.html")) {
|
|
1112
|
-
const contentType = file.path.endsWith(".js") ? "text/javascript"
|
|
1113
|
-
: file.path.endsWith(".css") ? "text/css"
|
|
1114
|
-
: file.path.endsWith(".json") ? "application/json"
|
|
1115
|
-
: file.path.endsWith(".png") ? "image/png"
|
|
1116
|
-
: file.path.endsWith(".jpg") ? "image/jpeg"
|
|
1117
|
-
: file.path.endsWith(".webp") ? "image/webp"
|
|
1118
|
-
: file.path.endsWith(".wav") ? "audio/wav"
|
|
1119
|
-
: file.path.endsWith(".ogg") ? "audio/ogg"
|
|
1120
|
-
: file.path.endsWith(".mp3") ? "audio/mpeg"
|
|
1121
|
-
: file.path.endsWith(".ttf") ? "font/ttf"
|
|
1122
|
-
: file.path.endsWith(".otf") ? "font/otf"
|
|
1123
|
-
: "application/octet-stream";
|
|
1124
|
-
await workspace.write(`${buildPath}/${file.path}`, file.bytes, contentType);
|
|
1125
|
-
}
|
|
1126
|
-
const index = files.find((file) => file.path === "index.html");
|
|
1127
|
-
if (!index)
|
|
1128
|
-
throw new Error("Standalone player entry is missing");
|
|
1129
|
-
await workspace.write(indexPath, index.bytes, "text/html");
|
|
1130
|
-
return { game_id: game.id, revision, build_path: buildPath, entry_path: indexPath, cached: false };
|
|
1131
1327
|
}
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1328
|
+
const entryFile = entryPath.slice(buildPath.length + 1);
|
|
1329
|
+
const entry = files.find((file) => file.path === entryFile);
|
|
1330
|
+
if (!entry)
|
|
1331
|
+
throw new Error("Standalone build entry is missing");
|
|
1332
|
+
const contentType = (path) => BUILD_CONTENT_TYPES[path.slice(path.lastIndexOf(".") + 1)] ?? "application/octet-stream";
|
|
1333
|
+
// The entry file is written last, so its presence marks a complete build for the cache check above.
|
|
1334
|
+
for (const file of files.filter((item) => item !== entry)) {
|
|
1335
|
+
await workspace.write(`${buildPath}/${file.path}`, file.bytes, contentType(file.path));
|
|
1137
1336
|
}
|
|
1337
|
+
await workspace.write(entryPath, entry.bytes, contentType(entry.path));
|
|
1338
|
+
return { ...done, cached: false };
|
|
1339
|
+
}
|
|
1340
|
+
catch (error) {
|
|
1341
|
+
return { error: error instanceof Error ? error.message : String(error) };
|
|
1342
|
+
}
|
|
1343
|
+
finally {
|
|
1344
|
+
await rm(staging, { recursive: true, force: true });
|
|
1345
|
+
}
|
|
1346
|
+
}
|
|
1347
|
+
const buildGame = {
|
|
1348
|
+
spec: gameSpecs[5],
|
|
1349
|
+
impl: async (run, args) => {
|
|
1350
|
+
const user = userId(run);
|
|
1351
|
+
const id = args["game_id"];
|
|
1352
|
+
if (!user || typeof id !== "string")
|
|
1353
|
+
return { error: "game_id is required in a user session" };
|
|
1354
|
+
const target = args["target"] ?? "web";
|
|
1355
|
+
if (target !== "web" && target !== "tauri")
|
|
1356
|
+
return { error: "target must be web or tauri" };
|
|
1357
|
+
const revision = args["revision"];
|
|
1358
|
+
const result = await buildOwnedNativeGame({ userId: user, gameId: id, revision: typeof revision === "string" ? revision : undefined,
|
|
1359
|
+
target, storage: run.context.assetStorage, signal: run.context.signal });
|
|
1360
|
+
if ("error" in result)
|
|
1361
|
+
return { error: result.error };
|
|
1362
|
+
const report = { game_id: result.game_id, revision: result.revision, target: result.target, build_path: result.build_path,
|
|
1363
|
+
entry_path: result.entry_path, cached: result.cached };
|
|
1364
|
+
return target === "tauri"
|
|
1365
|
+
? { ...report, next: "The project builds desktop installers with `npm install && npm run build` in a checkout that has Rust and the Tauri prerequisites." }
|
|
1366
|
+
: report;
|
|
1138
1367
|
}
|
|
1139
1368
|
};
|
|
1140
1369
|
const listExamples = {
|
|
@@ -1193,7 +1422,7 @@ const installExample = {
|
|
|
1193
1422
|
return { error: "Example game not found" };
|
|
1194
1423
|
const installed = await installExampleGameAssets(user, projectId, {}, slug, storage);
|
|
1195
1424
|
try {
|
|
1196
|
-
const created = await createNativeGame(user, projectId, typeof name === "string" ? name.trim() : installed.bundle.name, installed.document);
|
|
1425
|
+
const created = await createNativeGame(user, projectId, typeof name === "string" ? name.trim() : installed.bundle.name, installed.document, installed.document.schemaVersion === 3 ? "3d" : "2d");
|
|
1197
1426
|
if ("error" in created) {
|
|
1198
1427
|
await installed.rollback();
|
|
1199
1428
|
return created;
|
|
@@ -1222,6 +1451,9 @@ const autoplay = {
|
|
|
1222
1451
|
const document = await readSource(workspace, game, args["source"], args["revision"]);
|
|
1223
1452
|
if (!document)
|
|
1224
1453
|
return { error: "Game source not found" };
|
|
1454
|
+
if (document.schemaVersion === 3) {
|
|
1455
|
+
return { status: "unsupported", dimension: "3d", code: "autoplay_3d_unsupported", message: "Use playtest_native_game with a recorded 3D route" };
|
|
1456
|
+
}
|
|
1225
1457
|
const targetPrefix = args["target_prefix"];
|
|
1226
1458
|
const playerId = args["player_id"];
|
|
1227
1459
|
const win = args["win"];
|
|
@@ -1255,8 +1487,24 @@ const autoplay = {
|
|
|
1255
1487
|
return { game_id: shortResourceId(game.id), revision: document.revision, ...route, win_tick: winTick, reached_targets: reachedTargets, level_stats: levelStats, state: snapshot };
|
|
1256
1488
|
}
|
|
1257
1489
|
};
|
|
1490
|
+
function withDraftRecovery(capability) {
|
|
1491
|
+
return { ...capability, impl: async (run, args) => {
|
|
1492
|
+
try {
|
|
1493
|
+
return await capability.impl(run, args);
|
|
1494
|
+
}
|
|
1495
|
+
catch (error) {
|
|
1496
|
+
if (error instanceof MissingGameDraftSourceError) {
|
|
1497
|
+
return { error: error.message, code: "game_draft_source_unavailable" };
|
|
1498
|
+
}
|
|
1499
|
+
throw error;
|
|
1500
|
+
}
|
|
1501
|
+
} };
|
|
1502
|
+
}
|
|
1258
1503
|
export const module = {
|
|
1259
1504
|
module: "game",
|
|
1260
|
-
exports: [create, get, save, install, playtest, buildGame, edit, capture, generateAsset, listExamples, getExample, installExample, autoplay
|
|
1505
|
+
exports: [create, get, save, install, playtest, buildGame, edit, capture, generateAsset, listExamples, getExample, installExample, autoplay,
|
|
1506
|
+
{ spec: previewGameAuthoringSpec, impl: previewGameAuthoring },
|
|
1507
|
+
{ spec: applyGameAuthoringSpec, impl: applyGameAuthoring },
|
|
1508
|
+
{ spec: browseGameAssetsSpec, impl: browseGameAssets }].map(withDraftRecovery)
|
|
1261
1509
|
};
|
|
1262
1510
|
//# sourceMappingURL=game.js.map
|