@imgly/codesign-mcp 0.1.6 → 0.1.8
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 +5 -10
- package/assets/docs/api/index.d.ts +9 -3
- package/assets/docs/guide/SKILL.md +2 -2
- package/assets/docs/guide/api/node/classes/creativeengine.md +13 -13
- package/assets/docs/guide/edit-image/transform/scale.md +1 -3
- package/assets/docs/guide/filters-and-effects/duotone.md +1 -1
- package/assets/docs/guide/get-started/bun.md +0 -2
- package/assets/docs/guide/get-started/deno.md +0 -1
- package/assets/docs/guide/get-started/vanilla.md +0 -2
- package/assets/docs/guide/import-media/default-assets.md +20 -24
- package/assets/docs/guide/plugins/print-ready-pdf.md +0 -2
- package/assets/docs/guide/serve-assets.md +80 -23
- package/assets/docs/handbook/SKILL.md +6 -7
- package/dist/assets/inline.generated.js +12 -12
- package/dist/assets/inline.generated.js.map +1 -1
- package/dist/cli/http.d.ts.map +1 -1
- package/dist/cli/http.js +29 -5
- package/dist/cli/http.js.map +1 -1
- package/dist/cli/stdio.d.ts.map +1 -1
- package/dist/cli/stdio.js +145 -48
- package/dist/cli/stdio.js.map +1 -1
- package/dist/cli/trial-license.generated.d.ts +1 -1
- package/dist/cli/trial-license.generated.js +1 -1
- package/dist/cli/trial-license.generated.js.map +1 -1
- package/dist/config.d.ts +17 -2
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +20 -1
- package/dist/config.js.map +1 -1
- package/dist/diagnostics/bundle.d.ts +3 -0
- package/dist/diagnostics/bundle.d.ts.map +1 -1
- package/dist/diagnostics/bundle.js +25 -22
- package/dist/diagnostics/bundle.js.map +1 -1
- package/dist/diagnostics/events.d.ts +6 -0
- package/dist/diagnostics/events.d.ts.map +1 -1
- package/dist/diagnostics/events.js.map +1 -1
- package/dist/diagnostics/prompt.d.ts +3 -0
- package/dist/diagnostics/prompt.d.ts.map +1 -0
- package/dist/diagnostics/prompt.js +21 -0
- package/dist/diagnostics/prompt.js.map +1 -0
- package/dist/diagnostics/router.d.ts +12 -0
- package/dist/diagnostics/router.d.ts.map +1 -0
- package/dist/diagnostics/router.js +64 -0
- package/dist/diagnostics/router.js.map +1 -0
- package/dist/diagnostics/spa-assets.generated.d.ts.map +1 -0
- package/dist/diagnostics/spa-assets.generated.js +1231 -0
- package/dist/diagnostics/spa-assets.generated.js.map +1 -0
- package/dist/diagnostics/status.d.ts +38 -0
- package/dist/diagnostics/status.d.ts.map +1 -0
- package/dist/diagnostics/status.js +53 -0
- package/dist/diagnostics/status.js.map +1 -0
- package/dist/diagnostics/summary.d.ts +48 -0
- package/dist/diagnostics/summary.d.ts.map +1 -0
- package/dist/diagnostics/summary.js +116 -0
- package/dist/diagnostics/summary.js.map +1 -0
- package/dist/diagnostics/tool.d.ts +16 -0
- package/dist/diagnostics/tool.d.ts.map +1 -0
- package/dist/diagnostics/tool.js +90 -0
- package/dist/diagnostics/tool.js.map +1 -0
- package/dist/engine/asset-sources.d.ts +8 -0
- package/dist/engine/asset-sources.d.ts.map +1 -1
- package/dist/engine/asset-sources.js +9 -2
- package/dist/engine/asset-sources.js.map +1 -1
- package/dist/engine/cesdk-adapter.d.ts +5 -1
- package/dist/engine/cesdk-adapter.d.ts.map +1 -1
- package/dist/engine/cesdk-adapter.js +8 -1
- package/dist/engine/cesdk-adapter.js.map +1 -1
- package/dist/engine/engine-capacity.d.ts +16 -0
- package/dist/engine/engine-capacity.d.ts.map +1 -0
- package/dist/engine/engine-capacity.js +48 -0
- package/dist/engine/engine-capacity.js.map +1 -0
- package/dist/engine/engine-slots.d.ts +48 -0
- package/dist/engine/engine-slots.d.ts.map +1 -0
- package/dist/engine/engine-slots.js +182 -0
- package/dist/engine/engine-slots.js.map +1 -0
- package/dist/engine/uri-resolver.js.map +1 -1
- package/dist/server.d.ts +25 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +24 -4
- package/dist/server.js.map +1 -1
- package/dist/tools/engine.d.ts +92 -14
- package/dist/tools/engine.d.ts.map +1 -1
- package/dist/tools/engine.js +147 -20
- package/dist/tools/engine.js.map +1 -1
- package/dist/tools/export.d.ts.map +1 -1
- package/dist/tools/export.js +34 -4
- package/dist/tools/export.js.map +1 -1
- package/dist/tools/index.js +2 -2
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/load.d.ts.map +1 -1
- package/dist/tools/load.js +26 -19
- package/dist/tools/load.js.map +1 -1
- package/dist/tools/preview.d.ts.map +1 -1
- package/dist/tools/preview.js +60 -40
- package/dist/tools/preview.js.map +1 -1
- package/dist/tools/{open-editor.d.ts → view.d.ts} +3 -3
- package/dist/tools/view.d.ts.map +1 -0
- package/dist/tools/{open-editor.js → view.js} +20 -18
- package/dist/tools/view.js.map +1 -0
- package/dist/viewer/listener.d.ts +2 -0
- package/dist/viewer/listener.d.ts.map +1 -1
- package/dist/viewer/listener.js +2 -0
- package/dist/viewer/listener.js.map +1 -1
- package/dist/viewer/presigned-r2-url-builder.d.ts +1 -1
- package/dist/viewer/presigned-r2-url-builder.js +1 -1
- package/dist/viewer/presigned-r2-url-builder.js.map +1 -1
- package/dist/viewer/router.d.ts.map +1 -1
- package/dist/viewer/router.js +8 -17
- package/dist/viewer/router.js.map +1 -1
- package/dist/viewer/session-mount.js.map +1 -1
- package/dist/viewer/spa-assets.generated.d.ts.map +1 -1
- package/dist/viewer/spa-assets.generated.js +750 -869
- package/dist/viewer/spa-assets.generated.js.map +1 -1
- package/dist/viewer/url-builder.d.ts +4 -3
- package/dist/viewer/url-builder.d.ts.map +1 -1
- package/dist/viewer/url-builder.js +4 -4
- package/dist/viewer/url-builder.js.map +1 -1
- package/package.json +7 -6
- package/dist/dashboard/router.d.ts +0 -3
- package/dist/dashboard/router.d.ts.map +0 -1
- package/dist/dashboard/router.js +0 -19
- package/dist/dashboard/router.js.map +0 -1
- package/dist/dashboard/spa-assets.generated.d.ts.map +0 -1
- package/dist/dashboard/spa-assets.generated.js +0 -220
- package/dist/dashboard/spa-assets.generated.js.map +0 -1
- package/dist/metrics/mount.d.ts +0 -11
- package/dist/metrics/mount.d.ts.map +0 -1
- package/dist/metrics/mount.js +0 -13
- package/dist/metrics/mount.js.map +0 -1
- package/dist/metrics/recorder.d.ts +0 -55
- package/dist/metrics/recorder.d.ts.map +0 -1
- package/dist/metrics/recorder.js +0 -97
- package/dist/metrics/recorder.js.map +0 -1
- package/dist/test/scripts/changelog-add.d.ts +0 -8
- package/dist/test/scripts/changelog-add.d.ts.map +0 -1
- package/dist/test/scripts/changelog-add.js +0 -50
- package/dist/test/scripts/changelog-add.js.map +0 -1
- package/dist/test/scripts/changelog-collate.d.ts +0 -38
- package/dist/test/scripts/changelog-collate.d.ts.map +0 -1
- package/dist/test/scripts/changelog-collate.js +0 -171
- package/dist/test/scripts/changelog-collate.js.map +0 -1
- package/dist/test/test/changelog.test.d.ts +0 -2
- package/dist/test/test/changelog.test.d.ts.map +0 -1
- package/dist/test/test/changelog.test.js +0 -293
- package/dist/test/test/changelog.test.js.map +0 -1
- package/dist/test/test/cli/dispatcher.test.d.ts +0 -2
- package/dist/test/test/cli/dispatcher.test.d.ts.map +0 -1
- package/dist/test/test/cli/dispatcher.test.js +0 -54
- package/dist/test/test/cli/dispatcher.test.js.map +0 -1
- package/dist/test/test/cli/redirect-console.test.d.ts +0 -2
- package/dist/test/test/cli/redirect-console.test.d.ts.map +0 -1
- package/dist/test/test/cli/redirect-console.test.js +0 -78
- package/dist/test/test/cli/redirect-console.test.js.map +0 -1
- package/dist/test/test/cli/resolve-license.test.d.ts +0 -2
- package/dist/test/test/cli/resolve-license.test.d.ts.map +0 -1
- package/dist/test/test/cli/resolve-license.test.js +0 -29
- package/dist/test/test/cli/resolve-license.test.js.map +0 -1
- package/dist/test/test/cli/stdio-diagnostics.test.d.ts +0 -2
- package/dist/test/test/cli/stdio-diagnostics.test.d.ts.map +0 -1
- package/dist/test/test/cli/stdio-diagnostics.test.js +0 -31
- package/dist/test/test/cli/stdio-diagnostics.test.js.map +0 -1
- package/dist/test/test/cli/stdio-license.test.d.ts +0 -2
- package/dist/test/test/cli/stdio-license.test.d.ts.map +0 -1
- package/dist/test/test/cli/stdio-license.test.js +0 -19
- package/dist/test/test/cli/stdio-license.test.js.map +0 -1
- package/dist/test/test/config.test.d.ts +0 -2
- package/dist/test/test/config.test.d.ts.map +0 -1
- package/dist/test/test/config.test.js +0 -95
- package/dist/test/test/config.test.js.map +0 -1
- package/dist/test/test/cross-ref.test.d.ts +0 -2
- package/dist/test/test/cross-ref.test.d.ts.map +0 -1
- package/dist/test/test/cross-ref.test.js +0 -39
- package/dist/test/test/cross-ref.test.js.map +0 -1
- package/dist/test/test/diagnostics/bundle.test.d.ts +0 -2
- package/dist/test/test/diagnostics/bundle.test.d.ts.map +0 -1
- package/dist/test/test/diagnostics/bundle.test.js +0 -53
- package/dist/test/test/diagnostics/bundle.test.js.map +0 -1
- package/dist/test/test/diagnostics/compose.test.d.ts +0 -2
- package/dist/test/test/diagnostics/compose.test.d.ts.map +0 -1
- package/dist/test/test/diagnostics/compose.test.js +0 -31
- package/dist/test/test/diagnostics/compose.test.js.map +0 -1
- package/dist/test/test/diagnostics/file-sink.test.d.ts +0 -2
- package/dist/test/test/diagnostics/file-sink.test.d.ts.map +0 -1
- package/dist/test/test/diagnostics/file-sink.test.js +0 -113
- package/dist/test/test/diagnostics/file-sink.test.js.map +0 -1
- package/dist/test/test/diagnostics/redact.test.d.ts +0 -2
- package/dist/test/test/diagnostics/redact.test.d.ts.map +0 -1
- package/dist/test/test/diagnostics/redact.test.js +0 -59
- package/dist/test/test/diagnostics/redact.test.js.map +0 -1
- package/dist/test/test/diagnostics/tool-call-adapter.test.d.ts +0 -2
- package/dist/test/test/diagnostics/tool-call-adapter.test.d.ts.map +0 -1
- package/dist/test/test/diagnostics/tool-call-adapter.test.js +0 -34
- package/dist/test/test/diagnostics/tool-call-adapter.test.js.map +0 -1
- package/dist/test/test/engine/asset-sources.test.d.ts +0 -2
- package/dist/test/test/engine/asset-sources.test.d.ts.map +0 -1
- package/dist/test/test/engine/asset-sources.test.js +0 -100
- package/dist/test/test/engine/asset-sources.test.js.map +0 -1
- package/dist/test/test/engine/cesdk-adapter.test.d.ts +0 -2
- package/dist/test/test/engine/cesdk-adapter.test.d.ts.map +0 -1
- package/dist/test/test/engine/cesdk-adapter.test.js +0 -32
- package/dist/test/test/engine/cesdk-adapter.test.js.map +0 -1
- package/dist/test/test/engine/mutex.test.d.ts +0 -2
- package/dist/test/test/engine/mutex.test.d.ts.map +0 -1
- package/dist/test/test/engine/mutex.test.js +0 -63
- package/dist/test/test/engine/mutex.test.js.map +0 -1
- package/dist/test/test/engine/session.test.d.ts +0 -2
- package/dist/test/test/engine/session.test.d.ts.map +0 -1
- package/dist/test/test/engine/session.test.js +0 -159
- package/dist/test/test/engine/session.test.js.map +0 -1
- package/dist/test/test/engine/unsplash-source.test.d.ts +0 -2
- package/dist/test/test/engine/unsplash-source.test.d.ts.map +0 -1
- package/dist/test/test/engine/unsplash-source.test.js +0 -129
- package/dist/test/test/engine/unsplash-source.test.js.map +0 -1
- package/dist/test/test/engine/uri-resolver.test.d.ts +0 -2
- package/dist/test/test/engine/uri-resolver.test.d.ts.map +0 -1
- package/dist/test/test/engine/uri-resolver.test.js +0 -38
- package/dist/test/test/engine/uri-resolver.test.js.map +0 -1
- package/dist/test/test/gateway/hosted-stub.test.d.ts +0 -2
- package/dist/test/test/gateway/hosted-stub.test.d.ts.map +0 -1
- package/dist/test/test/gateway/hosted-stub.test.js +0 -11
- package/dist/test/test/gateway/hosted-stub.test.js.map +0 -1
- package/dist/test/test/gateway/local.test.d.ts +0 -2
- package/dist/test/test/gateway/local.test.d.ts.map +0 -1
- package/dist/test/test/gateway/local.test.js +0 -29
- package/dist/test/test/gateway/local.test.js.map +0 -1
- package/dist/test/test/handbook-contract.test.d.ts +0 -2
- package/dist/test/test/handbook-contract.test.d.ts.map +0 -1
- package/dist/test/test/handbook-contract.test.js +0 -79
- package/dist/test/test/handbook-contract.test.js.map +0 -1
- package/dist/test/test/http/server.test.d.ts +0 -2
- package/dist/test/test/http/server.test.d.ts.map +0 -1
- package/dist/test/test/http/server.test.js +0 -338
- package/dist/test/test/http/server.test.js.map +0 -1
- package/dist/test/test/http/session-id-header.test.d.ts +0 -2
- package/dist/test/test/http/session-id-header.test.d.ts.map +0 -1
- package/dist/test/test/http/session-id-header.test.js +0 -76
- package/dist/test/test/http/session-id-header.test.js.map +0 -1
- package/dist/test/test/http/session-manager.test.d.ts +0 -2
- package/dist/test/test/http/session-manager.test.d.ts.map +0 -1
- package/dist/test/test/http/session-manager.test.js +0 -97
- package/dist/test/test/http/session-manager.test.js.map +0 -1
- package/dist/test/test/http/workspace-auth.test.d.ts +0 -2
- package/dist/test/test/http/workspace-auth.test.d.ts.map +0 -1
- package/dist/test/test/http/workspace-auth.test.js +0 -40
- package/dist/test/test/http/workspace-auth.test.js.map +0 -1
- package/dist/test/test/metrics/mount.test.d.ts +0 -2
- package/dist/test/test/metrics/mount.test.d.ts.map +0 -1
- package/dist/test/test/metrics/mount.test.js +0 -59
- package/dist/test/test/metrics/mount.test.js.map +0 -1
- package/dist/test/test/metrics/recorder.test.d.ts +0 -2
- package/dist/test/test/metrics/recorder.test.d.ts.map +0 -1
- package/dist/test/test/metrics/recorder.test.js +0 -118
- package/dist/test/test/metrics/recorder.test.js.map +0 -1
- package/dist/test/test/revisions/hash.test.d.ts +0 -2
- package/dist/test/test/revisions/hash.test.d.ts.map +0 -1
- package/dist/test/test/revisions/hash.test.js +0 -33
- package/dist/test/test/revisions/hash.test.js.map +0 -1
- package/dist/test/test/revisions/store.test.d.ts +0 -2
- package/dist/test/test/revisions/store.test.d.ts.map +0 -1
- package/dist/test/test/revisions/store.test.js +0 -315
- package/dist/test/test/revisions/store.test.js.map +0 -1
- package/dist/test/test/server.metrics.test.d.ts +0 -2
- package/dist/test/test/server.metrics.test.d.ts.map +0 -1
- package/dist/test/test/server.metrics.test.js +0 -87
- package/dist/test/test/server.metrics.test.js.map +0 -1
- package/dist/test/test/server.test.d.ts +0 -2
- package/dist/test/test/server.test.d.ts.map +0 -1
- package/dist/test/test/server.test.js +0 -146
- package/dist/test/test/server.test.js.map +0 -1
- package/dist/test/test/skill-tools.test.d.ts +0 -2
- package/dist/test/test/skill-tools.test.d.ts.map +0 -1
- package/dist/test/test/skill-tools.test.js +0 -84
- package/dist/test/test/skill-tools.test.js.map +0 -1
- package/dist/test/test/smoke.test.d.ts +0 -2
- package/dist/test/test/smoke.test.d.ts.map +0 -1
- package/dist/test/test/smoke.test.js +0 -8
- package/dist/test/test/smoke.test.js.map +0 -1
- package/dist/test/test/tools/asset-generate.test.d.ts +0 -2
- package/dist/test/test/tools/asset-generate.test.d.ts.map +0 -1
- package/dist/test/test/tools/asset-generate.test.js +0 -66
- package/dist/test/test/tools/asset-generate.test.js.map +0 -1
- package/dist/test/test/tools/asset-search.test.d.ts +0 -2
- package/dist/test/test/tools/asset-search.test.d.ts.map +0 -1
- package/dist/test/test/tools/asset-search.test.js +0 -121
- package/dist/test/test/tools/asset-search.test.js.map +0 -1
- package/dist/test/test/tools/edit-harness.d.ts +0 -14
- package/dist/test/test/tools/edit-harness.d.ts.map +0 -1
- package/dist/test/test/tools/edit-harness.js +0 -30
- package/dist/test/test/tools/edit-harness.js.map +0 -1
- package/dist/test/test/tools/edit.telemetry.test.d.ts +0 -2
- package/dist/test/test/tools/edit.telemetry.test.d.ts.map +0 -1
- package/dist/test/test/tools/edit.telemetry.test.js +0 -46
- package/dist/test/test/tools/edit.telemetry.test.js.map +0 -1
- package/dist/test/test/tools/edit.test.d.ts +0 -2
- package/dist/test/test/tools/edit.test.d.ts.map +0 -1
- package/dist/test/test/tools/edit.test.js +0 -267
- package/dist/test/test/tools/edit.test.js.map +0 -1
- package/dist/test/test/tools/export-harness.d.ts +0 -13
- package/dist/test/test/tools/export-harness.d.ts.map +0 -1
- package/dist/test/test/tools/export-harness.js +0 -27
- package/dist/test/test/tools/export-harness.js.map +0 -1
- package/dist/test/test/tools/export.telemetry.test.d.ts +0 -2
- package/dist/test/test/tools/export.telemetry.test.d.ts.map +0 -1
- package/dist/test/test/tools/export.telemetry.test.js +0 -65
- package/dist/test/test/tools/export.telemetry.test.js.map +0 -1
- package/dist/test/test/tools/export.test.d.ts +0 -2
- package/dist/test/test/tools/export.test.d.ts.map +0 -1
- package/dist/test/test/tools/export.test.js +0 -174
- package/dist/test/test/tools/export.test.js.map +0 -1
- package/dist/test/test/tools/history.test.d.ts +0 -2
- package/dist/test/test/tools/history.test.d.ts.map +0 -1
- package/dist/test/test/tools/history.test.js +0 -29
- package/dist/test/test/tools/history.test.js.map +0 -1
- package/dist/test/test/tools/import.test.d.ts +0 -2
- package/dist/test/test/tools/import.test.d.ts.map +0 -1
- package/dist/test/test/tools/import.test.js +0 -122
- package/dist/test/test/tools/import.test.js.map +0 -1
- package/dist/test/test/tools/index.test.d.ts +0 -2
- package/dist/test/test/tools/index.test.d.ts.map +0 -1
- package/dist/test/test/tools/index.test.js +0 -117
- package/dist/test/test/tools/index.test.js.map +0 -1
- package/dist/test/test/tools/inspect.test.d.ts +0 -2
- package/dist/test/test/tools/inspect.test.d.ts.map +0 -1
- package/dist/test/test/tools/inspect.test.js +0 -62
- package/dist/test/test/tools/inspect.test.js.map +0 -1
- package/dist/test/test/tools/list.test.d.ts +0 -2
- package/dist/test/test/tools/list.test.d.ts.map +0 -1
- package/dist/test/test/tools/list.test.js +0 -23
- package/dist/test/test/tools/list.test.js.map +0 -1
- package/dist/test/test/tools/load.integration.test.d.ts +0 -2
- package/dist/test/test/tools/load.integration.test.d.ts.map +0 -1
- package/dist/test/test/tools/load.integration.test.js +0 -165
- package/dist/test/test/tools/load.integration.test.js.map +0 -1
- package/dist/test/test/tools/load.test.d.ts +0 -2
- package/dist/test/test/tools/load.test.d.ts.map +0 -1
- package/dist/test/test/tools/load.test.js +0 -387
- package/dist/test/test/tools/load.test.js.map +0 -1
- package/dist/test/test/tools/metrics.test.d.ts +0 -2
- package/dist/test/test/tools/metrics.test.d.ts.map +0 -1
- package/dist/test/test/tools/metrics.test.js +0 -29
- package/dist/test/test/tools/metrics.test.js.map +0 -1
- package/dist/test/test/tools/open-editor.test.d.ts +0 -2
- package/dist/test/test/tools/open-editor.test.d.ts.map +0 -1
- package/dist/test/test/tools/open-editor.test.js +0 -53
- package/dist/test/test/tools/open-editor.test.js.map +0 -1
- package/dist/test/test/tools/preview-harness.d.ts +0 -9
- package/dist/test/test/tools/preview-harness.d.ts.map +0 -1
- package/dist/test/test/tools/preview-harness.js +0 -23
- package/dist/test/test/tools/preview-harness.js.map +0 -1
- package/dist/test/test/tools/preview.telemetry.test.d.ts +0 -2
- package/dist/test/test/tools/preview.telemetry.test.d.ts.map +0 -1
- package/dist/test/test/tools/preview.telemetry.test.js +0 -36
- package/dist/test/test/tools/preview.telemetry.test.js.map +0 -1
- package/dist/test/test/tools/preview.test.d.ts +0 -2
- package/dist/test/test/tools/preview.test.d.ts.map +0 -1
- package/dist/test/test/tools/preview.test.js +0 -75
- package/dist/test/test/tools/preview.test.js.map +0 -1
- package/dist/test/test/tools/rename.test.d.ts +0 -2
- package/dist/test/test/tools/rename.test.d.ts.map +0 -1
- package/dist/test/test/tools/rename.test.js +0 -16
- package/dist/test/test/tools/rename.test.js.map +0 -1
- package/dist/test/test/tools/save.test.d.ts +0 -2
- package/dist/test/test/tools/save.test.d.ts.map +0 -1
- package/dist/test/test/tools/save.test.js +0 -137
- package/dist/test/test/tools/save.test.js.map +0 -1
- package/dist/test/test/tools/schema-best-practices.d.ts +0 -13
- package/dist/test/test/tools/schema-best-practices.d.ts.map +0 -1
- package/dist/test/test/tools/schema-best-practices.js +0 -169
- package/dist/test/test/tools/schema-best-practices.js.map +0 -1
- package/dist/test/test/tools/schema-best-practices.test.d.ts +0 -3
- package/dist/test/test/tools/schema-best-practices.test.d.ts.map +0 -1
- package/dist/test/test/tools/schema-best-practices.test.js +0 -194
- package/dist/test/test/tools/schema-best-practices.test.js.map +0 -1
- package/dist/test/test/tools/spans.test.d.ts +0 -2
- package/dist/test/test/tools/spans.test.d.ts.map +0 -1
- package/dist/test/test/tools/spans.test.js +0 -84
- package/dist/test/test/tools/spans.test.js.map +0 -1
- package/dist/test/test/viewer/broadcaster.test.d.ts +0 -2
- package/dist/test/test/viewer/broadcaster.test.d.ts.map +0 -1
- package/dist/test/test/viewer/broadcaster.test.js +0 -53
- package/dist/test/test/viewer/broadcaster.test.js.map +0 -1
- package/dist/test/test/viewer/cesdk-cdn.test.d.ts +0 -2
- package/dist/test/test/viewer/cesdk-cdn.test.d.ts.map +0 -1
- package/dist/test/test/viewer/cesdk-cdn.test.js +0 -19
- package/dist/test/test/viewer/cesdk-cdn.test.js.map +0 -1
- package/dist/test/test/viewer/config-route.test.d.ts +0 -2
- package/dist/test/test/viewer/config-route.test.d.ts.map +0 -1
- package/dist/test/test/viewer/config-route.test.js +0 -28
- package/dist/test/test/viewer/config-route.test.js.map +0 -1
- package/dist/test/test/viewer/resource-route.test.d.ts +0 -2
- package/dist/test/test/viewer/resource-route.test.d.ts.map +0 -1
- package/dist/test/test/viewer/resource-route.test.js +0 -70
- package/dist/test/test/viewer/resource-route.test.js.map +0 -1
- package/dist/test/test/viewer/router.test.d.ts +0 -2
- package/dist/test/test/viewer/router.test.d.ts.map +0 -1
- package/dist/test/test/viewer/router.test.js +0 -227
- package/dist/test/test/viewer/router.test.js.map +0 -1
- package/dist/test/test/viewer/session-mount.test.d.ts +0 -2
- package/dist/test/test/viewer/session-mount.test.d.ts.map +0 -1
- package/dist/test/test/viewer/session-mount.test.js +0 -52
- package/dist/test/test/viewer/session-mount.test.js.map +0 -1
- package/dist/test/test/viewer/spa-version.test.d.ts +0 -2
- package/dist/test/test/viewer/spa-version.test.d.ts.map +0 -1
- package/dist/test/test/viewer/spa-version.test.js +0 -14
- package/dist/test/test/viewer/spa-version.test.js.map +0 -1
- package/dist/test/test/viewer/url-builder.test.d.ts +0 -2
- package/dist/test/test/viewer/url-builder.test.d.ts.map +0 -1
- package/dist/test/test/viewer/url-builder.test.js +0 -98
- package/dist/test/test/viewer/url-builder.test.js.map +0 -1
- package/dist/test/test/workspace/content-hash.test.d.ts +0 -2
- package/dist/test/test/workspace/content-hash.test.d.ts.map +0 -1
- package/dist/test/test/workspace/content-hash.test.js +0 -17
- package/dist/test/test/workspace/content-hash.test.js.map +0 -1
- package/dist/test/test/workspace/hosted-stub.test.d.ts +0 -2
- package/dist/test/test/workspace/hosted-stub.test.d.ts.map +0 -1
- package/dist/test/test/workspace/hosted-stub.test.js +0 -30
- package/dist/test/test/workspace/hosted-stub.test.js.map +0 -1
- package/dist/test/test/workspace/in-memory.test.d.ts +0 -2
- package/dist/test/test/workspace/in-memory.test.d.ts.map +0 -1
- package/dist/test/test/workspace/in-memory.test.js +0 -4
- package/dist/test/test/workspace/in-memory.test.js.map +0 -1
- package/dist/test/test/workspace/node-fs.test.d.ts +0 -2
- package/dist/test/test/workspace/node-fs.test.d.ts.map +0 -1
- package/dist/test/test/workspace/node-fs.test.js +0 -20
- package/dist/test/test/workspace/node-fs.test.js.map +0 -1
- package/dist/test/test/workspace/s3.test.d.ts +0 -2
- package/dist/test/test/workspace/s3.test.d.ts.map +0 -1
- package/dist/test/test/workspace/s3.test.js +0 -153
- package/dist/test/test/workspace/s3.test.js.map +0 -1
- package/dist/test/test/workspace/scoped.test.d.ts +0 -2
- package/dist/test/test/workspace/scoped.test.d.ts.map +0 -1
- package/dist/test/test/workspace/scoped.test.js +0 -59
- package/dist/test/test/workspace/scoped.test.js.map +0 -1
- package/dist/test/test/workspace/shared-contract.d.ts +0 -3
- package/dist/test/test/workspace/shared-contract.d.ts.map +0 -1
- package/dist/test/test/workspace/shared-contract.js +0 -92
- package/dist/test/test/workspace/shared-contract.js.map +0 -1
- package/dist/test/tsconfig.test.tsbuildinfo +0 -1
- package/dist/test/vitest.config.d.ts +0 -3
- package/dist/test/vitest.config.d.ts.map +0 -1
- package/dist/test/vitest.config.js +0 -8
- package/dist/test/vitest.config.js.map +0 -1
- package/dist/tools/metrics.d.ts +0 -11
- package/dist/tools/metrics.d.ts.map +0 -1
- package/dist/tools/metrics.js +0 -28
- package/dist/tools/metrics.js.map +0 -1
- package/dist/tools/open-editor.d.ts.map +0 -1
- package/dist/tools/open-editor.js.map +0 -1
- /package/dist/{dashboard → diagnostics}/spa-assets.generated.d.ts +0 -0
package/dist/tools/engine.d.ts
CHANGED
|
@@ -1,12 +1,83 @@
|
|
|
1
1
|
import type CreativeEngine from '@cesdk/engine';
|
|
2
|
+
/**
|
|
3
|
+
* The shape both engine packages expose: `module.exports` is the CreativeEngine
|
|
4
|
+
* class itself, with `.default` aliased to the same class.
|
|
5
|
+
*/
|
|
6
|
+
type EngineModule = {
|
|
7
|
+
default?: typeof CreativeEngine;
|
|
8
|
+
};
|
|
9
|
+
/** A CJS-style `require`, injected so the selection logic is unit-testable. */
|
|
10
|
+
type Loader = (pkg: string) => unknown;
|
|
11
|
+
/** Which engine package actually loaded, and via what path. */
|
|
12
|
+
export type EngineFlavor = 'native' | 'wasm' | 'wasm-fallback';
|
|
13
|
+
/**
|
|
14
|
+
* Which engine flavor actually loaded on the first `ensureHeadlessEngine`
|
|
15
|
+
* call — `undefined` until the engine has booted at least once. Surfaced by
|
|
16
|
+
* the `diagnostics` tool (`status.config.engineResolved`) so a user can tell
|
|
17
|
+
* whether they're getting native GPU rasterization or the WASM fallback.
|
|
18
|
+
*/
|
|
19
|
+
export declare function resolvedEngineFlavor(): EngineFlavor | undefined;
|
|
20
|
+
/**
|
|
21
|
+
* Choose and load the engine package per `IMGLY_CESDK_ENGINE`, with
|
|
22
|
+
* context-aware fallback:
|
|
23
|
+
*
|
|
24
|
+
* - unset / "" (default) → WASM (TEMPORARY — native is NOT the default because
|
|
25
|
+
* registering a URI resolver breaks all resource
|
|
26
|
+
* loading on @cesdk/node-native, and the MCP server
|
|
27
|
+
* always registers one). Remove `isDefault ||` in the
|
|
28
|
+
* body to restore the native default (CODE-7) once the
|
|
29
|
+
* engine fixes the resolver; the native-load and
|
|
30
|
+
* WASM-fallback paths below stay in place, dormant.
|
|
31
|
+
* - "native" (explicit) → native; if it fails to load, throw — a deliberate
|
|
32
|
+
* request must not silently degrade to slow WASM.
|
|
33
|
+
* - "wasm" (explicit) → WASM; native is never attempted.
|
|
34
|
+
* - any other value → throw (guards typos like "natve").
|
|
35
|
+
*
|
|
36
|
+
* Native ships prebuilt binaries for darwin-arm64/darwin-x64/linux-x64 only.
|
|
37
|
+
*
|
|
38
|
+
* `load` is injected (the real `createRequire(...)` in production, a stub in
|
|
39
|
+
* tests). `warn` defaults to `console.warn`, which is stderr-safe: in stdio mode
|
|
40
|
+
* `redirectConsoleToStderr()` remaps it to stderr so it never corrupts the
|
|
41
|
+
* JSON-RPC channel; in http mode Node's console.warn already writes to stderr.
|
|
42
|
+
*/
|
|
43
|
+
export declare function resolveEngineModule(env: string | undefined, load: Loader, warn?: (msg: string) => void): {
|
|
44
|
+
module: EngineModule;
|
|
45
|
+
flavor: EngineFlavor;
|
|
46
|
+
};
|
|
47
|
+
/**
|
|
48
|
+
* Resolve the engine module, then initialize it — adding init-time fallback on
|
|
49
|
+
* top of `resolveEngineModule`'s load-time fallback.
|
|
50
|
+
*
|
|
51
|
+
* The native addon (`@cesdk/node-native`) dlopens its GStreamer/GL dependencies
|
|
52
|
+
* LAZILY, inside `init()` — not at `require()` time. So a native module can
|
|
53
|
+
* resolve successfully (flavor 'native') and still fail to boot, e.g. on a
|
|
54
|
+
* Linux host missing system libraries. `resolveEngineModule` alone can't catch
|
|
55
|
+
* that; this function does, applying the same context-aware policy:
|
|
56
|
+
*
|
|
57
|
+
* - default (env unset/'') + native resolved but init rejects → warn, load
|
|
58
|
+
* and init WASM instead, flavor 'wasm-fallback'. If WASM init ALSO
|
|
59
|
+
* rejects, that rejection propagates as-is (no further fallback).
|
|
60
|
+
* - explicit "native" + init rejects → rejects with a clearer wrapped
|
|
61
|
+
* message + `{ cause }`, mirroring `resolveEngineModule`'s load-time throw.
|
|
62
|
+
* - explicit "wasm", or already-fallback WASM (flavor !== 'native') + init
|
|
63
|
+
* rejects → propagates unchanged.
|
|
64
|
+
*
|
|
65
|
+
* `load` and `initEngine` are injected so this stays unit-testable without a
|
|
66
|
+
* real engine binary; `ensureHeadlessEngine` supplies the real `createRequire`
|
|
67
|
+
* loader and a real `Ctor.init({ license })` call.
|
|
68
|
+
*/
|
|
69
|
+
export declare function initEngineModule(env: string | undefined, load: Loader, initEngine: (mod: EngineModule) => Promise<CreativeEngine>, warn?: (msg: string) => void): Promise<{
|
|
70
|
+
engine: CreativeEngine;
|
|
71
|
+
flavor: EngineFlavor;
|
|
72
|
+
}>;
|
|
2
73
|
/**
|
|
3
74
|
* Initialize a headless CreativeEngine once and share it across calls.
|
|
4
75
|
*
|
|
5
76
|
* Only ever called on node — the browser surface passes `cesdk.engine` directly
|
|
6
77
|
* to the design tools, so this code path is dead in the browser bundle. To keep
|
|
7
|
-
* it that way,
|
|
8
|
-
*
|
|
9
|
-
*
|
|
78
|
+
* it that way, `node:module` is loaded via async dynamic import inside the
|
|
79
|
+
* function — Vite leaves dynamic imports of node builtins as runtime errors only
|
|
80
|
+
* if executed, not at module init.
|
|
10
81
|
*
|
|
11
82
|
* Both `@cesdk/node` (WASM) and `@cesdk/node-native` (N-API) are loaded through
|
|
12
83
|
* `createRequire` (CJS-shaped) rather than ESM dynamic import. `@cesdk/node`'s
|
|
@@ -15,17 +86,24 @@ import type CreativeEngine from '@cesdk/engine';
|
|
|
15
86
|
* `ReferenceError: Worker is not defined`. The native package is also CJS-shaped
|
|
16
87
|
* so the same load strategy works for both.
|
|
17
88
|
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
* - Both packages export `CreativeEngine` as `module.exports` (the class
|
|
23
|
-
* itself) with `module.exports.default` aliased to the same class.
|
|
24
|
-
* - Both expose `static init(config?: Partial<Configuration>): Promise<Engine>`
|
|
25
|
-
* and accept `{ license }` as config.
|
|
26
|
-
* - The native `Configuration` adds an optional `device: 'auto'|'cpu'|'gpu'`
|
|
27
|
-
* field (ignored by WASM). We pass only `{ license }` here so both paths
|
|
28
|
-
* default to `device: 'auto'` (Metal/EGL → CPU fallback on native).
|
|
89
|
+
* Both packages expose `static init(config?): Promise<Engine>` and accept
|
|
90
|
+
* `{ license }`. The native `Configuration` adds an optional
|
|
91
|
+
* `device: 'auto'|'cpu'|'gpu'` field (ignored by WASM); we pass only `{ license }`
|
|
92
|
+
* so both default to `device: 'auto'` (Metal/EGL → CPU fallback on native).
|
|
29
93
|
*/
|
|
30
94
|
export declare function ensureHeadlessEngine(license: string): Promise<CreativeEngine>;
|
|
95
|
+
/**
|
|
96
|
+
* Dispose the process-wide headless engine if one was created, and reset the
|
|
97
|
+
* cache so a subsequent `ensureHeadlessEngine` re-initializes from scratch.
|
|
98
|
+
*
|
|
99
|
+
* Idempotent and safe to call when no engine was ever initialized (a no-op that
|
|
100
|
+
* never imports `@cesdk/node`) or while an init is still in flight — it awaits
|
|
101
|
+
* the pending init first so we dispose a fully-constructed engine, never a
|
|
102
|
+
* half-built one. A rejected init produced no engine, so that case is swallowed.
|
|
103
|
+
*
|
|
104
|
+
* `CreativeEngine.dispose()` is synchronous; this wrapper is async only because
|
|
105
|
+
* it may await an in-flight `init()`.
|
|
106
|
+
*/
|
|
107
|
+
export declare function disposeHeadlessEngine(): Promise<void>;
|
|
108
|
+
export {};
|
|
31
109
|
//# sourceMappingURL=engine.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../src/tools/engine.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,cAAc,MAAM,eAAe,CAAC;AAIhD
|
|
1
|
+
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../src/tools/engine.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,cAAc,MAAM,eAAe,CAAC;AAIhD;;;GAGG;AACH,KAAK,YAAY,GAAG;IAClB,OAAO,CAAC,EAAE,OAAO,cAAc,CAAC;CACjC,CAAC;AAEF,+EAA+E;AAC/E,KAAK,MAAM,GAAG,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC;AAEvC,+DAA+D;AAC/D,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,MAAM,GAAG,eAAe,CAAC;AAO/D;;;;;GAKG;AACH,wBAAgB,oBAAoB,IAAI,YAAY,GAAG,SAAS,CAE/D;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,mBAAmB,CACjC,GAAG,EAAE,MAAM,GAAG,SAAS,EACvB,IAAI,EAAE,MAAM,EACZ,IAAI,GAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAmB,GACzC;IAAE,MAAM,EAAE,YAAY,CAAC;IAAC,MAAM,EAAE,YAAY,CAAA;CAAE,CAkChD;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAsB,gBAAgB,CACpC,GAAG,EAAE,MAAM,GAAG,SAAS,EACvB,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,CAAC,GAAG,EAAE,YAAY,KAAK,OAAO,CAAC,cAAc,CAAC,EAC1D,IAAI,GAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAmB,GACzC,OAAO,CAAC;IAAE,MAAM,EAAE,cAAc,CAAC;IAAC,MAAM,EAAE,YAAY,CAAA;CAAE,CAAC,CA2B3D;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,CAmC7E;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,qBAAqB,IAAI,OAAO,CAAC,IAAI,CAAC,CAa3D"}
|
package/dist/tools/engine.js
CHANGED
|
@@ -1,12 +1,118 @@
|
|
|
1
1
|
let cached;
|
|
2
|
+
const NATIVE_PKG = '@cesdk/node-native';
|
|
3
|
+
const WASM_PKG = '@cesdk/node';
|
|
4
|
+
let resolvedFlavor;
|
|
5
|
+
/**
|
|
6
|
+
* Which engine flavor actually loaded on the first `ensureHeadlessEngine`
|
|
7
|
+
* call — `undefined` until the engine has booted at least once. Surfaced by
|
|
8
|
+
* the `diagnostics` tool (`status.config.engineResolved`) so a user can tell
|
|
9
|
+
* whether they're getting native GPU rasterization or the WASM fallback.
|
|
10
|
+
*/
|
|
11
|
+
export function resolvedEngineFlavor() {
|
|
12
|
+
return resolvedFlavor;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Choose and load the engine package per `IMGLY_CESDK_ENGINE`, with
|
|
16
|
+
* context-aware fallback:
|
|
17
|
+
*
|
|
18
|
+
* - unset / "" (default) → WASM (TEMPORARY — native is NOT the default because
|
|
19
|
+
* registering a URI resolver breaks all resource
|
|
20
|
+
* loading on @cesdk/node-native, and the MCP server
|
|
21
|
+
* always registers one). Remove `isDefault ||` in the
|
|
22
|
+
* body to restore the native default (CODE-7) once the
|
|
23
|
+
* engine fixes the resolver; the native-load and
|
|
24
|
+
* WASM-fallback paths below stay in place, dormant.
|
|
25
|
+
* - "native" (explicit) → native; if it fails to load, throw — a deliberate
|
|
26
|
+
* request must not silently degrade to slow WASM.
|
|
27
|
+
* - "wasm" (explicit) → WASM; native is never attempted.
|
|
28
|
+
* - any other value → throw (guards typos like "natve").
|
|
29
|
+
*
|
|
30
|
+
* Native ships prebuilt binaries for darwin-arm64/darwin-x64/linux-x64 only.
|
|
31
|
+
*
|
|
32
|
+
* `load` is injected (the real `createRequire(...)` in production, a stub in
|
|
33
|
+
* tests). `warn` defaults to `console.warn`, which is stderr-safe: in stdio mode
|
|
34
|
+
* `redirectConsoleToStderr()` remaps it to stderr so it never corrupts the
|
|
35
|
+
* JSON-RPC channel; in http mode Node's console.warn already writes to stderr.
|
|
36
|
+
*/
|
|
37
|
+
export function resolveEngineModule(env, load, warn = console.warn) {
|
|
38
|
+
const isDefault = env === undefined || env === '';
|
|
39
|
+
if (!isDefault && env !== 'native' && env !== 'wasm') {
|
|
40
|
+
throw new Error(`Invalid IMGLY_CESDK_ENGINE "${env}": expected "native" or "wasm"`);
|
|
41
|
+
}
|
|
42
|
+
// Default (unset/empty) or explicit "wasm": load WASM. The `isDefault ||` is a
|
|
43
|
+
// temporary revert of the native default — native breaks all resource loading
|
|
44
|
+
// under a URI resolver (see the doc comment). Remove it to make native the
|
|
45
|
+
// default again (CODE-7) once the engine fixes the resolver.
|
|
46
|
+
if (isDefault || env === 'wasm') {
|
|
47
|
+
return { module: load(WASM_PKG), flavor: 'wasm' };
|
|
48
|
+
}
|
|
49
|
+
// Explicit "native" only (the default no longer reaches here): try native.
|
|
50
|
+
const explicitNative = env === 'native';
|
|
51
|
+
try {
|
|
52
|
+
return { module: load(NATIVE_PKG), flavor: 'native' };
|
|
53
|
+
}
|
|
54
|
+
catch (err) {
|
|
55
|
+
const detail = err instanceof Error ? err.message : String(err);
|
|
56
|
+
if (explicitNative) {
|
|
57
|
+
throw new Error(`IMGLY_CESDK_ENGINE=native but the native engine failed to load: ${detail}`, { cause: err });
|
|
58
|
+
}
|
|
59
|
+
warn(`native engine (${NATIVE_PKG}) unavailable on this platform; ` +
|
|
60
|
+
`falling back to WASM (${WASM_PKG}): ${detail}`);
|
|
61
|
+
return { module: load(WASM_PKG), flavor: 'wasm-fallback' };
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Resolve the engine module, then initialize it — adding init-time fallback on
|
|
66
|
+
* top of `resolveEngineModule`'s load-time fallback.
|
|
67
|
+
*
|
|
68
|
+
* The native addon (`@cesdk/node-native`) dlopens its GStreamer/GL dependencies
|
|
69
|
+
* LAZILY, inside `init()` — not at `require()` time. So a native module can
|
|
70
|
+
* resolve successfully (flavor 'native') and still fail to boot, e.g. on a
|
|
71
|
+
* Linux host missing system libraries. `resolveEngineModule` alone can't catch
|
|
72
|
+
* that; this function does, applying the same context-aware policy:
|
|
73
|
+
*
|
|
74
|
+
* - default (env unset/'') + native resolved but init rejects → warn, load
|
|
75
|
+
* and init WASM instead, flavor 'wasm-fallback'. If WASM init ALSO
|
|
76
|
+
* rejects, that rejection propagates as-is (no further fallback).
|
|
77
|
+
* - explicit "native" + init rejects → rejects with a clearer wrapped
|
|
78
|
+
* message + `{ cause }`, mirroring `resolveEngineModule`'s load-time throw.
|
|
79
|
+
* - explicit "wasm", or already-fallback WASM (flavor !== 'native') + init
|
|
80
|
+
* rejects → propagates unchanged.
|
|
81
|
+
*
|
|
82
|
+
* `load` and `initEngine` are injected so this stays unit-testable without a
|
|
83
|
+
* real engine binary; `ensureHeadlessEngine` supplies the real `createRequire`
|
|
84
|
+
* loader and a real `Ctor.init({ license })` call.
|
|
85
|
+
*/
|
|
86
|
+
export async function initEngineModule(env, load, initEngine, warn = console.warn) {
|
|
87
|
+
const { module: mod, flavor } = resolveEngineModule(env, load, warn);
|
|
88
|
+
try {
|
|
89
|
+
return { engine: await initEngine(mod), flavor };
|
|
90
|
+
}
|
|
91
|
+
catch (err) {
|
|
92
|
+
const detail = err instanceof Error ? err.message : String(err);
|
|
93
|
+
const isDefault = env === undefined || env === '';
|
|
94
|
+
if (flavor === 'native' && !isDefault) {
|
|
95
|
+
throw new Error(`IMGLY_CESDK_ENGINE=native but the native engine failed to initialize: ${detail}`, { cause: err });
|
|
96
|
+
}
|
|
97
|
+
if (flavor !== 'native') {
|
|
98
|
+
throw err; // explicit wasm, or already-fallback wasm: no further fallback
|
|
99
|
+
}
|
|
100
|
+
// Default mode, native resolved but failed to INIT: fall back to WASM,
|
|
101
|
+
// same breadcrumb-and-degrade policy as a native load-time failure.
|
|
102
|
+
warn(`native engine loaded but failed to initialize; falling back to WASM (${WASM_PKG}): ${detail}` +
|
|
103
|
+
` — if this is Linux, the native engine needs system libraries (see @cesdk/node-native README, 'Linux runtime dependencies')`);
|
|
104
|
+
const wasmMod = load(WASM_PKG);
|
|
105
|
+
return { engine: await initEngine(wasmMod), flavor: 'wasm-fallback' };
|
|
106
|
+
}
|
|
107
|
+
}
|
|
2
108
|
/**
|
|
3
109
|
* Initialize a headless CreativeEngine once and share it across calls.
|
|
4
110
|
*
|
|
5
111
|
* Only ever called on node — the browser surface passes `cesdk.engine` directly
|
|
6
112
|
* to the design tools, so this code path is dead in the browser bundle. To keep
|
|
7
|
-
* it that way,
|
|
8
|
-
*
|
|
9
|
-
*
|
|
113
|
+
* it that way, `node:module` is loaded via async dynamic import inside the
|
|
114
|
+
* function — Vite leaves dynamic imports of node builtins as runtime errors only
|
|
115
|
+
* if executed, not at module init.
|
|
10
116
|
*
|
|
11
117
|
* Both `@cesdk/node` (WASM) and `@cesdk/node-native` (N-API) are loaded through
|
|
12
118
|
* `createRequire` (CJS-shaped) rather than ESM dynamic import. `@cesdk/node`'s
|
|
@@ -15,29 +121,22 @@ let cached;
|
|
|
15
121
|
* `ReferenceError: Worker is not defined`. The native package is also CJS-shaped
|
|
16
122
|
* so the same load strategy works for both.
|
|
17
123
|
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
* - Both packages export `CreativeEngine` as `module.exports` (the class
|
|
23
|
-
* itself) with `module.exports.default` aliased to the same class.
|
|
24
|
-
* - Both expose `static init(config?: Partial<Configuration>): Promise<Engine>`
|
|
25
|
-
* and accept `{ license }` as config.
|
|
26
|
-
* - The native `Configuration` adds an optional `device: 'auto'|'cpu'|'gpu'`
|
|
27
|
-
* field (ignored by WASM). We pass only `{ license }` here so both paths
|
|
28
|
-
* default to `device: 'auto'` (Metal/EGL → CPU fallback on native).
|
|
124
|
+
* Both packages expose `static init(config?): Promise<Engine>` and accept
|
|
125
|
+
* `{ license }`. The native `Configuration` adds an optional
|
|
126
|
+
* `device: 'auto'|'cpu'|'gpu'` field (ignored by WASM); we pass only `{ license }`
|
|
127
|
+
* so both default to `device: 'auto'` (Metal/EGL → CPU fallback on native).
|
|
29
128
|
*/
|
|
30
129
|
export function ensureHeadlessEngine(license) {
|
|
31
130
|
if (!cached) {
|
|
32
131
|
cached = (async () => {
|
|
33
132
|
const { createRequire } = await import('node:module');
|
|
34
133
|
const require = createRequire(import.meta.url);
|
|
35
|
-
const
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
const
|
|
40
|
-
|
|
134
|
+
const initEngine = (mod) => {
|
|
135
|
+
const Ctor = mod.default ?? mod;
|
|
136
|
+
return Ctor.init({ license });
|
|
137
|
+
};
|
|
138
|
+
const { engine, flavor } = await initEngineModule(process.env.IMGLY_CESDK_ENGINE, require, initEngine);
|
|
139
|
+
resolvedFlavor = flavor;
|
|
41
140
|
// CE.SDK's default design unit is "Inch", which makes setTextFontSize
|
|
42
141
|
// + setWidth/Height with numeric pixel-looking values render at ~2.5×
|
|
43
142
|
// the agent's expected size. Patch scene.create so every new scene
|
|
@@ -56,4 +155,32 @@ export function ensureHeadlessEngine(license) {
|
|
|
56
155
|
}
|
|
57
156
|
return cached;
|
|
58
157
|
}
|
|
158
|
+
/**
|
|
159
|
+
* Dispose the process-wide headless engine if one was created, and reset the
|
|
160
|
+
* cache so a subsequent `ensureHeadlessEngine` re-initializes from scratch.
|
|
161
|
+
*
|
|
162
|
+
* Idempotent and safe to call when no engine was ever initialized (a no-op that
|
|
163
|
+
* never imports `@cesdk/node`) or while an init is still in flight — it awaits
|
|
164
|
+
* the pending init first so we dispose a fully-constructed engine, never a
|
|
165
|
+
* half-built one. A rejected init produced no engine, so that case is swallowed.
|
|
166
|
+
*
|
|
167
|
+
* `CreativeEngine.dispose()` is synchronous; this wrapper is async only because
|
|
168
|
+
* it may await an in-flight `init()`.
|
|
169
|
+
*/
|
|
170
|
+
export async function disposeHeadlessEngine() {
|
|
171
|
+
const pending = cached;
|
|
172
|
+
if (!pending)
|
|
173
|
+
return;
|
|
174
|
+
// Clear the cache first so no concurrent caller receives the engine we are
|
|
175
|
+
// about to dispose; a later `ensureHeadlessEngine` builds a fresh one.
|
|
176
|
+
cached = undefined;
|
|
177
|
+
let engine;
|
|
178
|
+
try {
|
|
179
|
+
engine = await pending;
|
|
180
|
+
}
|
|
181
|
+
catch {
|
|
182
|
+
return; // init never produced an engine — nothing to dispose
|
|
183
|
+
}
|
|
184
|
+
engine.dispose();
|
|
185
|
+
}
|
|
59
186
|
//# sourceMappingURL=engine.js.map
|
package/dist/tools/engine.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"engine.js","sourceRoot":"","sources":["../../src/tools/engine.ts"],"names":[],"mappings":"AAEA,IAAI,MAA2C,CAAC;AAEhD;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,MAAM,UAAU,oBAAoB,CAAC,OAAe;IAClD,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,GAAG,CAAC,KAAK,IAAI,EAAE;YACnB,MAAM,EAAE,aAAa,EAAE,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,CAAC;YACtD,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAC/C,MAAM,GAAG,GACP,OAAO,CAAC,GAAG,CAAC,kBAAkB,KAAK,QAAQ;gBACzC,CAAC,CAAC,oBAAoB;gBACtB,CAAC,CAAC,aAAa,CAAC;YACpB,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAGtB,CAAC;YACF,MAAM,IAAI,GACR,GAAG,CAAC,OAAO,IAAK,GAAwC,CAAC;YAC3D,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC;YAC5C,sEAAsE;YACtE,sEAAsE;YACtE,mEAAmE;YACnE,qDAAqD;YACrD,MAAM,UAAU,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACzD,MAAM,CAAC,KAAyD,CAAC,MAAM;gBACtE,CAAC,CAAC,MAAgB,EAAE,EAAE;oBACpB,MAAM,OAAO,GAAG,UAAU,CACxB,MAA0C,CAC3C,CAAC;oBACF,gEAAgE;oBAChE,8DAA8D;oBAC9D,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;oBACpC,OAAO,OAAO,CAAC;gBACjB,CAAC,CAA+B,CAAC;YACnC,OAAO,MAAM,CAAC;QAChB,CAAC,CAAC,EAAE,CAAC;IACP,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC","sourcesContent":["import type CreativeEngine from '@cesdk/engine';\n\nlet cached: Promise<CreativeEngine> | undefined;\n\n/**\n * Initialize a headless CreativeEngine once and share it across calls.\n *\n * Only ever called on node — the browser surface passes `cesdk.engine` directly\n * to the design tools, so this code path is dead in the browser bundle. To keep\n * it that way, both `node:module` and `@cesdk/node` are loaded via async\n * dynamic import inside the function — Vite leaves dynamic imports of node\n * builtins as runtime errors only if executed, not at module init.\n *\n * Both `@cesdk/node` (WASM) and `@cesdk/node-native` (N-API) are loaded through\n * `createRequire` (CJS-shaped) rather than ESM dynamic import. `@cesdk/node`'s\n * emscripten/wasm runtime spawns Workers that resolve relative to the package's\n * `__dirname`; ESM dynamic import + vitest pre-bundling break that path with\n * `ReferenceError: Worker is not defined`. The native package is also CJS-shaped\n * so the same load strategy works for both.\n *\n * Set `IMGLY_CESDK_ENGINE=native` to select the N-API native engine\n * (`@cesdk/node-native`). The default is the WASM engine (`@cesdk/node`).\n *\n * Native vs WASM init API:\n * - Both packages export `CreativeEngine` as `module.exports` (the class\n * itself) with `module.exports.default` aliased to the same class.\n * - Both expose `static init(config?: Partial<Configuration>): Promise<Engine>`\n * and accept `{ license }` as config.\n * - The native `Configuration` adds an optional `device: 'auto'|'cpu'|'gpu'`\n * field (ignored by WASM). We pass only `{ license }` here so both paths\n * default to `device: 'auto'` (Metal/EGL → CPU fallback on native).\n */\nexport function ensureHeadlessEngine(license: string): Promise<CreativeEngine> {\n if (!cached) {\n cached = (async () => {\n const { createRequire } = await import('node:module');\n const require = createRequire(import.meta.url);\n const pkg =\n process.env.IMGLY_CESDK_ENGINE === 'native'\n ? '@cesdk/node-native'\n : '@cesdk/node';\n const mod = require(pkg) as {\n default?: typeof CreativeEngine;\n init?: typeof CreativeEngine.init;\n };\n const Ctor: typeof CreativeEngine =\n mod.default ?? (mod as unknown as typeof CreativeEngine);\n const engine = await Ctor.init({ license });\n // CE.SDK's default design unit is \"Inch\", which makes setTextFontSize\n // + setWidth/Height with numeric pixel-looking values render at ~2.5×\n // the agent's expected size. Patch scene.create so every new scene\n // starts in Pixel — the agent never has to remember.\n const origCreate = engine.scene.create.bind(engine.scene);\n (engine.scene as unknown as { create(layout?: unknown): number }).create =\n ((layout?: unknown) => {\n const sceneId = origCreate(\n layout as Parameters<typeof origCreate>[0]\n );\n // @cesdk/node setDesignUnit takes only the unit; it operates on\n // the current scene, which is the one create() just returned.\n engine.scene.setDesignUnit('Pixel');\n return sceneId;\n }) as typeof engine.scene.create;\n return engine;\n })();\n }\n return cached;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"engine.js","sourceRoot":"","sources":["../../src/tools/engine.ts"],"names":[],"mappings":"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","sourcesContent":["import type CreativeEngine from '@cesdk/engine';\n\nlet cached: Promise<CreativeEngine> | undefined;\n\n/**\n * The shape both engine packages expose: `module.exports` is the CreativeEngine\n * class itself, with `.default` aliased to the same class.\n */\ntype EngineModule = {\n default?: typeof CreativeEngine;\n};\n\n/** A CJS-style `require`, injected so the selection logic is unit-testable. */\ntype Loader = (pkg: string) => unknown;\n\n/** Which engine package actually loaded, and via what path. */\nexport type EngineFlavor = 'native' | 'wasm' | 'wasm-fallback';\n\nconst NATIVE_PKG = '@cesdk/node-native';\nconst WASM_PKG = '@cesdk/node';\n\nlet resolvedFlavor: EngineFlavor | undefined;\n\n/**\n * Which engine flavor actually loaded on the first `ensureHeadlessEngine`\n * call — `undefined` until the engine has booted at least once. Surfaced by\n * the `diagnostics` tool (`status.config.engineResolved`) so a user can tell\n * whether they're getting native GPU rasterization or the WASM fallback.\n */\nexport function resolvedEngineFlavor(): EngineFlavor | undefined {\n return resolvedFlavor;\n}\n\n/**\n * Choose and load the engine package per `IMGLY_CESDK_ENGINE`, with\n * context-aware fallback:\n *\n * - unset / \"\" (default) → WASM (TEMPORARY — native is NOT the default because\n * registering a URI resolver breaks all resource\n * loading on @cesdk/node-native, and the MCP server\n * always registers one). Remove `isDefault ||` in the\n * body to restore the native default (CODE-7) once the\n * engine fixes the resolver; the native-load and\n * WASM-fallback paths below stay in place, dormant.\n * - \"native\" (explicit) → native; if it fails to load, throw — a deliberate\n * request must not silently degrade to slow WASM.\n * - \"wasm\" (explicit) → WASM; native is never attempted.\n * - any other value → throw (guards typos like \"natve\").\n *\n * Native ships prebuilt binaries for darwin-arm64/darwin-x64/linux-x64 only.\n *\n * `load` is injected (the real `createRequire(...)` in production, a stub in\n * tests). `warn` defaults to `console.warn`, which is stderr-safe: in stdio mode\n * `redirectConsoleToStderr()` remaps it to stderr so it never corrupts the\n * JSON-RPC channel; in http mode Node's console.warn already writes to stderr.\n */\nexport function resolveEngineModule(\n env: string | undefined,\n load: Loader,\n warn: (msg: string) => void = console.warn\n): { module: EngineModule; flavor: EngineFlavor } {\n const isDefault = env === undefined || env === '';\n if (!isDefault && env !== 'native' && env !== 'wasm') {\n throw new Error(\n `Invalid IMGLY_CESDK_ENGINE \"${env}\": expected \"native\" or \"wasm\"`\n );\n }\n\n // Default (unset/empty) or explicit \"wasm\": load WASM. The `isDefault ||` is a\n // temporary revert of the native default — native breaks all resource loading\n // under a URI resolver (see the doc comment). Remove it to make native the\n // default again (CODE-7) once the engine fixes the resolver.\n if (isDefault || env === 'wasm') {\n return { module: load(WASM_PKG) as EngineModule, flavor: 'wasm' };\n }\n\n // Explicit \"native\" only (the default no longer reaches here): try native.\n const explicitNative = env === 'native';\n try {\n return { module: load(NATIVE_PKG) as EngineModule, flavor: 'native' };\n } catch (err) {\n const detail = err instanceof Error ? err.message : String(err);\n if (explicitNative) {\n throw new Error(\n `IMGLY_CESDK_ENGINE=native but the native engine failed to load: ${detail}`,\n { cause: err }\n );\n }\n warn(\n `native engine (${NATIVE_PKG}) unavailable on this platform; ` +\n `falling back to WASM (${WASM_PKG}): ${detail}`\n );\n return { module: load(WASM_PKG) as EngineModule, flavor: 'wasm-fallback' };\n }\n}\n\n/**\n * Resolve the engine module, then initialize it — adding init-time fallback on\n * top of `resolveEngineModule`'s load-time fallback.\n *\n * The native addon (`@cesdk/node-native`) dlopens its GStreamer/GL dependencies\n * LAZILY, inside `init()` — not at `require()` time. So a native module can\n * resolve successfully (flavor 'native') and still fail to boot, e.g. on a\n * Linux host missing system libraries. `resolveEngineModule` alone can't catch\n * that; this function does, applying the same context-aware policy:\n *\n * - default (env unset/'') + native resolved but init rejects → warn, load\n * and init WASM instead, flavor 'wasm-fallback'. If WASM init ALSO\n * rejects, that rejection propagates as-is (no further fallback).\n * - explicit \"native\" + init rejects → rejects with a clearer wrapped\n * message + `{ cause }`, mirroring `resolveEngineModule`'s load-time throw.\n * - explicit \"wasm\", or already-fallback WASM (flavor !== 'native') + init\n * rejects → propagates unchanged.\n *\n * `load` and `initEngine` are injected so this stays unit-testable without a\n * real engine binary; `ensureHeadlessEngine` supplies the real `createRequire`\n * loader and a real `Ctor.init({ license })` call.\n */\nexport async function initEngineModule(\n env: string | undefined,\n load: Loader,\n initEngine: (mod: EngineModule) => Promise<CreativeEngine>,\n warn: (msg: string) => void = console.warn\n): Promise<{ engine: CreativeEngine; flavor: EngineFlavor }> {\n const { module: mod, flavor } = resolveEngineModule(env, load, warn);\n try {\n return { engine: await initEngine(mod), flavor };\n } catch (err) {\n const detail = err instanceof Error ? err.message : String(err);\n const isDefault = env === undefined || env === '';\n\n if (flavor === 'native' && !isDefault) {\n throw new Error(\n `IMGLY_CESDK_ENGINE=native but the native engine failed to initialize: ${detail}`,\n { cause: err }\n );\n }\n if (flavor !== 'native') {\n throw err; // explicit wasm, or already-fallback wasm: no further fallback\n }\n\n // Default mode, native resolved but failed to INIT: fall back to WASM,\n // same breadcrumb-and-degrade policy as a native load-time failure.\n warn(\n `native engine loaded but failed to initialize; falling back to WASM (${WASM_PKG}): ${detail}` +\n ` — if this is Linux, the native engine needs system libraries (see @cesdk/node-native README, 'Linux runtime dependencies')`\n );\n const wasmMod = load(WASM_PKG) as EngineModule;\n return { engine: await initEngine(wasmMod), flavor: 'wasm-fallback' };\n }\n}\n\n/**\n * Initialize a headless CreativeEngine once and share it across calls.\n *\n * Only ever called on node — the browser surface passes `cesdk.engine` directly\n * to the design tools, so this code path is dead in the browser bundle. To keep\n * it that way, `node:module` is loaded via async dynamic import inside the\n * function — Vite leaves dynamic imports of node builtins as runtime errors only\n * if executed, not at module init.\n *\n * Both `@cesdk/node` (WASM) and `@cesdk/node-native` (N-API) are loaded through\n * `createRequire` (CJS-shaped) rather than ESM dynamic import. `@cesdk/node`'s\n * emscripten/wasm runtime spawns Workers that resolve relative to the package's\n * `__dirname`; ESM dynamic import + vitest pre-bundling break that path with\n * `ReferenceError: Worker is not defined`. The native package is also CJS-shaped\n * so the same load strategy works for both.\n *\n * Both packages expose `static init(config?): Promise<Engine>` and accept\n * `{ license }`. The native `Configuration` adds an optional\n * `device: 'auto'|'cpu'|'gpu'` field (ignored by WASM); we pass only `{ license }`\n * so both default to `device: 'auto'` (Metal/EGL → CPU fallback on native).\n */\nexport function ensureHeadlessEngine(license: string): Promise<CreativeEngine> {\n if (!cached) {\n cached = (async () => {\n const { createRequire } = await import('node:module');\n const require = createRequire(import.meta.url);\n const initEngine = (mod: EngineModule): Promise<CreativeEngine> => {\n const Ctor: typeof CreativeEngine =\n mod.default ?? (mod as unknown as typeof CreativeEngine);\n return Ctor.init({ license });\n };\n const { engine, flavor } = await initEngineModule(\n process.env.IMGLY_CESDK_ENGINE,\n require,\n initEngine\n );\n resolvedFlavor = flavor;\n // CE.SDK's default design unit is \"Inch\", which makes setTextFontSize\n // + setWidth/Height with numeric pixel-looking values render at ~2.5×\n // the agent's expected size. Patch scene.create so every new scene\n // starts in Pixel — the agent never has to remember.\n const origCreate = engine.scene.create.bind(engine.scene);\n (engine.scene as unknown as { create(layout?: unknown): number }).create =\n ((layout?: unknown) => {\n const sceneId = origCreate(\n layout as Parameters<typeof origCreate>[0]\n );\n // @cesdk/node setDesignUnit takes only the unit; it operates on\n // the current scene, which is the one create() just returned.\n engine.scene.setDesignUnit('Pixel');\n return sceneId;\n }) as typeof engine.scene.create;\n return engine;\n })();\n }\n return cached;\n}\n\n/**\n * Dispose the process-wide headless engine if one was created, and reset the\n * cache so a subsequent `ensureHeadlessEngine` re-initializes from scratch.\n *\n * Idempotent and safe to call when no engine was ever initialized (a no-op that\n * never imports `@cesdk/node`) or while an init is still in flight — it awaits\n * the pending init first so we dispose a fully-constructed engine, never a\n * half-built one. A rejected init produced no engine, so that case is swallowed.\n *\n * `CreativeEngine.dispose()` is synchronous; this wrapper is async only because\n * it may await an in-flight `init()`.\n */\nexport async function disposeHeadlessEngine(): Promise<void> {\n const pending = cached;\n if (!pending) return;\n // Clear the cache first so no concurrent caller receives the engine we are\n // about to dispose; a later `ensureHeadlessEngine` builds a fresh one.\n cached = undefined;\n let engine: CreativeEngine;\n try {\n engine = await pending;\n } catch {\n return; // init never produced an engine — nothing to dispose\n }\n engine.dispose();\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"export.d.ts","sourceRoot":"","sources":["../../src/tools/export.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,cAAc,CAAC;AAChE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAKL,KAAK,aAAa,EACnB,MAAM,YAAY,CAAC;AAoEpB,MAAM,WAAW,uBAAuB,CAAC,CAAC,GAAG,OAAO;IAClD,EAAE,EAAE,WAAW,CAAC;IAChB,KAAK,EAAE,aAAa,CAAC;IACrB,OAAO,EAAE,aAAa,CAAC,CAAC,CAAC,CAAC;IAC1B,8EAA8E;IAC9E,UAAU,EAAE,gBAAgB,CAAC;IAC7B,gFAAgF;IAChF,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,yHAAyH;IACzH,UAAU,EAAE,KAAK,CAAC;IAClB,2FAA2F;IAC3F,SAAS,CAAC,EAAE,aAAa,CAAC;CAC3B;AAED,wBAAgB,gBAAgB,CAAC,CAAC,GAAG,OAAO,EAC1C,IAAI,EAAE,uBAAuB,CAAC,CAAC,CAAC,GAC/B,2BAA2B,
|
|
1
|
+
{"version":3,"file":"export.d.ts","sourceRoot":"","sources":["../../src/tools/export.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,cAAc,CAAC;AAChE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAKL,KAAK,aAAa,EACnB,MAAM,YAAY,CAAC;AAoEpB,MAAM,WAAW,uBAAuB,CAAC,CAAC,GAAG,OAAO;IAClD,EAAE,EAAE,WAAW,CAAC;IAChB,KAAK,EAAE,aAAa,CAAC;IACrB,OAAO,EAAE,aAAa,CAAC,CAAC,CAAC,CAAC;IAC1B,8EAA8E;IAC9E,UAAU,EAAE,gBAAgB,CAAC;IAC7B,gFAAgF;IAChF,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,yHAAyH;IACzH,UAAU,EAAE,KAAK,CAAC;IAClB,2FAA2F;IAC3F,SAAS,CAAC,EAAE,aAAa,CAAC;CAC3B;AAED,wBAAgB,gBAAgB,CAAC,CAAC,GAAG,OAAO,EAC1C,IAAI,EAAE,uBAAuB,CAAC,CAAC,CAAC,GAC/B,2BAA2B,CA0M7B"}
|
package/dist/tools/export.js
CHANGED
|
@@ -70,6 +70,7 @@ export function createExportTool(opts) {
|
|
|
70
70
|
let result;
|
|
71
71
|
let threw;
|
|
72
72
|
let revision;
|
|
73
|
+
let exportError;
|
|
73
74
|
try {
|
|
74
75
|
result = await (async () => {
|
|
75
76
|
const args = (rawArgs ?? {});
|
|
@@ -141,16 +142,41 @@ export function createExportTool(opts) {
|
|
|
141
142
|
// load-into-engine then export reads the shared engine across awaits —
|
|
142
143
|
// serialize against any concurrent engine-touching tool call.
|
|
143
144
|
const beforeLock = performance.now();
|
|
144
|
-
const
|
|
145
|
+
const rendered = await engineLock.runExclusive(async () => {
|
|
145
146
|
rec.add('lock_wait', performance.now() - beforeLock);
|
|
146
147
|
const slot = await rec.time('engine_scene_load', async () => {
|
|
147
148
|
await session.populate(revId, sceneBytes);
|
|
148
149
|
return session.acquire(revId);
|
|
149
150
|
});
|
|
150
151
|
const eng = slot.engine;
|
|
151
|
-
|
|
152
|
-
|
|
152
|
+
// We loaded `revId` under the lock just above, so the correct scene
|
|
153
|
+
// is current. If the render throws, `blockId` genuinely isn't in
|
|
154
|
+
// this revision's scene (a wrong or removed id) — return a legible
|
|
155
|
+
// tool error the model can act on (mirroring `edit`'s dirty-on-throw
|
|
156
|
+
// path) instead of rethrowing into an opaque MCP -32603.
|
|
157
|
+
try {
|
|
158
|
+
const blob = await rec.time('engine_execute', () => eng.block.export(blockId, mime, {}));
|
|
159
|
+
return { bytes: new Uint8Array(await blob.arrayBuffer()) };
|
|
160
|
+
}
|
|
161
|
+
catch (err) {
|
|
162
|
+
return { error: err };
|
|
163
|
+
}
|
|
153
164
|
});
|
|
165
|
+
if ('error' in rendered) {
|
|
166
|
+
exportError = rendered.error;
|
|
167
|
+
return {
|
|
168
|
+
isError: true,
|
|
169
|
+
content: [
|
|
170
|
+
{
|
|
171
|
+
type: 'text',
|
|
172
|
+
text: `export: could not render block ${blockId} in revision ${revId}. That block id isn't in this revision's scene — double-check the id (use \`inspect\` to see the revision's structure), or it may have been removed in this revision. ${rendered.error instanceof Error
|
|
173
|
+
? (rendered.error.stack ?? rendered.error.message)
|
|
174
|
+
: String(rendered.error)}`
|
|
175
|
+
}
|
|
176
|
+
]
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
const bytes = rendered.bytes;
|
|
154
180
|
const shard = args.revision.slice(0, 2);
|
|
155
181
|
const rest = args.revision.slice(2);
|
|
156
182
|
const ext = FORMAT_EXT[args.format];
|
|
@@ -208,7 +234,11 @@ export function createExportTool(opts) {
|
|
|
208
234
|
args: rawArgs,
|
|
209
235
|
...(result !== undefined ? { result: summarizeResult(result) } : {}),
|
|
210
236
|
...(revision ? { revision } : {}),
|
|
211
|
-
...(threw
|
|
237
|
+
...(threw
|
|
238
|
+
? { error: toErrorShape(threw) }
|
|
239
|
+
: exportError
|
|
240
|
+
? { error: toErrorShape(exportError) }
|
|
241
|
+
: {})
|
|
212
242
|
});
|
|
213
243
|
}
|
|
214
244
|
}
|
package/dist/tools/export.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"export.js","sourceRoot":"","sources":["../../src/tools/export.ts"],"names":[],"mappings":"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","sourcesContent":["// packages/codesign-mcp/src/tools/export.ts\n//\n// `export` — spec §6.2. Writes a revision-pinned artifact into\n// `exports/<shard>/<rev>/<format>.<ext>` and returns a workspace URI envelope:\n// `uri` (the durable `workspace://` handle) plus `httpUrl` (the `/r/` fetch\n// link). `path` (an absolute disk path) is returned ONLY when the caller\n// passes an explicit `outPath` — a normal workspace export never discloses\n// the workspace's on-disk location.\n//\n// `target=video` is deferred to Phase 4.\nimport { promises as nodeFs } from 'node:fs';\nimport { dirname } from 'node:path';\nimport { performance } from 'node:perf_hooks';\nimport type { Mutex } from '../engine/mutex.js';\nimport type { EngineSession } from '../engine/session.js';\nimport type { RevisionStore } from '../revisions/store.js';\nimport type { CodesignMcpToolRegistration } from '../server.js';\nimport type { ViewerUrlBuilder } from '../viewer/url-builder.js';\nimport type { WorkspaceFS } from '../workspace/types.js';\nimport {\n NOOP_TELEMETRY_SINK,\n SpanRecorder,\n summarizeResult,\n toErrorShape,\n type TelemetrySink\n} from './spans.js';\n\ntype Target = 'pdf' | 'image' | 'video';\ntype Format = 'pdf' | 'png' | 'jpeg' | 'webp' | 'mp4';\n\ninterface MinimalEngine {\n block: {\n export(blockId: number, mimeType: string, options?: unknown): Promise<Blob>;\n };\n}\n\ninterface ExportArgs {\n target: Target;\n format: Format;\n revision: string;\n blockId?: number;\n outPath?: string;\n}\n\nconst TARGET_MIME: Record<'pdf' | 'image', Record<string, string>> = {\n pdf: { pdf: 'application/pdf' },\n image: { png: 'image/png', jpeg: 'image/jpeg', webp: 'image/webp' }\n};\n\nconst FORMAT_EXT: Record<Format, string> = {\n pdf: 'pdf',\n png: 'png',\n jpeg: 'jpg',\n webp: 'webp',\n mp4: 'mp4'\n};\n\nconst DESCRIPTION = [\n 'Export a revision to pdf/image. Renders `blockId` and writes the result into the workspace under `exports/<shard>/<rev>/<target>.<ext>` (revision-pinned, deterministic).',\n '',\n 'Returns JSON: `{ uri, httpUrl?, path?, bytes, format, revision }`. `uri` (a `workspace://` URI) is the durable handle. `httpUrl` is a fetch link for opening the artifact now — present for workspace exports, tied to this process. `path` (absolute disk path) is returned ONLY when you passed `outPath`.',\n '',\n '`target=video` is deferred to Phase 4.'\n].join('\\n');\n\n// The schema is built per-backend: `outPath` is advertised ONLY when the\n// backend honours it (Local). On Hosted the property is omitted entirely, so\n// an agent never sees an affordance it can't use — it can't try a local path\n// and hit a runtime rejection. The runtime guard in `call` stays as a backstop.\nfunction buildExportInputSchema(allowOutPath: boolean) {\n const properties: Record<string, unknown> = {\n target: { enum: ['pdf', 'image', 'video'] },\n format: { enum: ['pdf', 'png', 'jpeg', 'webp', 'mp4'] },\n revision: { type: 'string' as const },\n blockId: {\n type: 'integer' as const,\n description: 'Required for pdf and image targets.'\n }\n };\n if (allowOutPath) {\n properties.outPath = {\n type: 'string' as const,\n description: 'Local-only escape hatch; absolute path.'\n };\n }\n return {\n type: 'object' as const,\n properties,\n required: ['target', 'format', 'revision'],\n additionalProperties: false\n };\n}\n\nexport interface CreateExportToolOptions<E = unknown> {\n fs: WorkspaceFS;\n store: RevisionStore;\n session: EngineSession<E>;\n /** Builds the `httpUrl` for workspace-written artifacts (the `/r/` route). */\n urlBuilder: ViewerUrlBuilder;\n /** Whether to honour an `outPath` argument (Local: yes; Hosted/sandbox: no). */\n allowOutPath?: boolean;\n /** Guards the shared engine — load-then-export must not interleave with another session's edit (see engine/mutex.ts). */\n engineLock: Mutex;\n /** Diagnostics telemetry port. Absent → no-op (no timing overhead beyond a few clocks). */\n telemetry?: TelemetrySink;\n}\n\nexport function createExportTool<E = unknown>(\n opts: CreateExportToolOptions<E>\n): CodesignMcpToolRegistration {\n const {\n fs,\n store,\n session,\n urlBuilder,\n allowOutPath = false,\n engineLock\n } = opts;\n const telemetry = opts.telemetry ?? NOOP_TELEMETRY_SINK;\n return {\n name: 'export',\n description: DESCRIPTION,\n inputSchema: buildExportInputSchema(allowOutPath),\n call: async (rawArgs) => {\n const rec = new SpanRecorder();\n const startedAt = performance.now();\n type CallResult = Awaited<\n ReturnType<CodesignMcpToolRegistration['call']>\n >;\n let result: CallResult | undefined;\n let threw: unknown;\n let revision: string | undefined;\n try {\n result = await (async (): Promise<CallResult> => {\n const args = (rawArgs ?? {}) as Partial<ExportArgs>;\n if (\n typeof args.target !== 'string' ||\n typeof args.format !== 'string' ||\n typeof args.revision !== 'string'\n ) {\n return {\n isError: true,\n content: [\n {\n type: 'text' as const,\n text: 'export: target, format, and revision are required.'\n }\n ]\n };\n }\n if (args.target === 'video') {\n return {\n isError: true,\n content: [\n {\n type: 'text' as const,\n text: 'export: target=video is deferred to Phase 4.'\n }\n ]\n };\n }\n if (args.outPath !== undefined && !allowOutPath) {\n return {\n isError: true,\n content: [\n {\n type: 'text' as const,\n text: 'export: `outPath` is not supported on this (hosted) backend. Omit it — the artifact is written to the workspace and returned as `httpUrl`; fetch that URL to download the bytes to disk.'\n }\n ]\n };\n }\n const rev = await rec.time('workspace_read', () =>\n store.read(args.revision as string)\n );\n if (typeof args.blockId !== 'number') {\n return {\n isError: true,\n content: [\n {\n type: 'text' as const,\n text: `export: target=${args.target} requires \\`blockId\\`.`\n }\n ]\n };\n }\n const mimeMap = TARGET_MIME[args.target as 'pdf' | 'image'];\n const mime = mimeMap?.[args.format];\n if (!mime) {\n return {\n isError: true,\n content: [\n {\n type: 'text' as const,\n text: `export: invalid format=${args.format} for target=${args.target}.`\n }\n ]\n };\n }\n // Capture validated args into locals so the locked closure keeps the\n // type narrowing the top-level guards established.\n const revId = args.revision;\n const blockId = args.blockId;\n const sceneBytes = rev.scene;\n // load-into-engine then export reads the shared engine across awaits —\n // serialize against any concurrent engine-touching tool call.\n const beforeLock = performance.now();\n const bytes = await engineLock.runExclusive(async () => {\n rec.add('lock_wait', performance.now() - beforeLock);\n const slot = await rec.time('engine_scene_load', async () => {\n await session.populate(revId, sceneBytes);\n return session.acquire(revId);\n });\n const eng = slot.engine as MinimalEngine;\n const blob = await rec.time('engine_execute', () =>\n eng.block.export(blockId, mime, {})\n );\n return new Uint8Array(await blob.arrayBuffer());\n });\n const shard = args.revision.slice(0, 2);\n const rest = args.revision.slice(2);\n const ext = FORMAT_EXT[args.format];\n const relPath = `exports/${shard}/${rest}/${args.target}.${ext}`;\n let absPath: string | undefined;\n let httpUrl: string | undefined;\n if (args.outPath !== undefined) {\n // Local-only escape hatch: write through real disk fs, NOT through\n // the workspace abstraction. The caller chose this path explicitly,\n // so echoing it back is a confirmation, not a workspace-path leak.\n await nodeFs.mkdir(dirname(args.outPath), { recursive: true });\n await rec.time('workspace_write', async () => {\n await nodeFs.writeFile(args.outPath as string, bytes);\n });\n absPath = args.outPath;\n } else {\n // Workspace write — goes through the WorkspaceFS abstraction. The\n // artifact is reachable over HTTP via the `/r/` route; the absolute\n // disk path is deliberately NOT disclosed.\n await rec.time('workspace_write', async () => {\n await fs.writeFile(relPath, bytes);\n });\n httpUrl = await urlBuilder.forDownload(relPath);\n }\n revision = args.revision;\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify({\n uri: `workspace://${relPath}`,\n ...(httpUrl ? { httpUrl } : {}),\n ...(absPath ? { path: absPath } : {}),\n bytes: bytes.byteLength,\n format: args.format,\n revision: args.revision\n })\n }\n ]\n };\n })();\n return result;\n } catch (err) {\n threw = err;\n throw err;\n } finally {\n telemetry.record({\n tool: 'export',\n succeeded: threw === undefined && result?.isError !== true,\n totalMs: performance.now() - startedAt,\n spans: rec.list(),\n args: rawArgs,\n ...(result !== undefined ? { result: summarizeResult(result) } : {}),\n ...(revision ? { revision } : {}),\n ...(threw ? { error: toErrorShape(threw) } : {})\n });\n }\n }\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"export.js","sourceRoot":"","sources":["../../src/tools/export.ts"],"names":[],"mappings":"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","sourcesContent":["// packages/codesign-mcp/src/tools/export.ts\n//\n// `export` — spec §6.2. Writes a revision-pinned artifact into\n// `exports/<shard>/<rev>/<format>.<ext>` and returns a workspace URI envelope:\n// `uri` (the durable `workspace://` handle) plus `httpUrl` (the `/r/` fetch\n// link). `path` (an absolute disk path) is returned ONLY when the caller\n// passes an explicit `outPath` — a normal workspace export never discloses\n// the workspace's on-disk location.\n//\n// `target=video` is deferred to Phase 4.\nimport { promises as nodeFs } from 'node:fs';\nimport { dirname } from 'node:path';\nimport { performance } from 'node:perf_hooks';\nimport type { Mutex } from '../engine/mutex.js';\nimport type { EngineSession } from '../engine/session.js';\nimport type { RevisionStore } from '../revisions/store.js';\nimport type { CodesignMcpToolRegistration } from '../server.js';\nimport type { ViewerUrlBuilder } from '../viewer/url-builder.js';\nimport type { WorkspaceFS } from '../workspace/types.js';\nimport {\n NOOP_TELEMETRY_SINK,\n SpanRecorder,\n summarizeResult,\n toErrorShape,\n type TelemetrySink\n} from './spans.js';\n\ntype Target = 'pdf' | 'image' | 'video';\ntype Format = 'pdf' | 'png' | 'jpeg' | 'webp' | 'mp4';\n\ninterface MinimalEngine {\n block: {\n export(blockId: number, mimeType: string, options?: unknown): Promise<Blob>;\n };\n}\n\ninterface ExportArgs {\n target: Target;\n format: Format;\n revision: string;\n blockId?: number;\n outPath?: string;\n}\n\nconst TARGET_MIME: Record<'pdf' | 'image', Record<string, string>> = {\n pdf: { pdf: 'application/pdf' },\n image: { png: 'image/png', jpeg: 'image/jpeg', webp: 'image/webp' }\n};\n\nconst FORMAT_EXT: Record<Format, string> = {\n pdf: 'pdf',\n png: 'png',\n jpeg: 'jpg',\n webp: 'webp',\n mp4: 'mp4'\n};\n\nconst DESCRIPTION = [\n 'Export a revision to pdf/image. Renders `blockId` and writes the result into the workspace under `exports/<shard>/<rev>/<target>.<ext>` (revision-pinned, deterministic).',\n '',\n 'Returns JSON: `{ uri, httpUrl?, path?, bytes, format, revision }`. `uri` (a `workspace://` URI) is the durable handle. `httpUrl` is a fetch link for opening the artifact now — present for workspace exports, tied to this process. `path` (absolute disk path) is returned ONLY when you passed `outPath`.',\n '',\n '`target=video` is deferred to Phase 4.'\n].join('\\n');\n\n// The schema is built per-backend: `outPath` is advertised ONLY when the\n// backend honours it (Local). On Hosted the property is omitted entirely, so\n// an agent never sees an affordance it can't use — it can't try a local path\n// and hit a runtime rejection. The runtime guard in `call` stays as a backstop.\nfunction buildExportInputSchema(allowOutPath: boolean) {\n const properties: Record<string, unknown> = {\n target: { enum: ['pdf', 'image', 'video'] },\n format: { enum: ['pdf', 'png', 'jpeg', 'webp', 'mp4'] },\n revision: { type: 'string' as const },\n blockId: {\n type: 'integer' as const,\n description: 'Required for pdf and image targets.'\n }\n };\n if (allowOutPath) {\n properties.outPath = {\n type: 'string' as const,\n description: 'Local-only escape hatch; absolute path.'\n };\n }\n return {\n type: 'object' as const,\n properties,\n required: ['target', 'format', 'revision'],\n additionalProperties: false\n };\n}\n\nexport interface CreateExportToolOptions<E = unknown> {\n fs: WorkspaceFS;\n store: RevisionStore;\n session: EngineSession<E>;\n /** Builds the `httpUrl` for workspace-written artifacts (the `/r/` route). */\n urlBuilder: ViewerUrlBuilder;\n /** Whether to honour an `outPath` argument (Local: yes; Hosted/sandbox: no). */\n allowOutPath?: boolean;\n /** Guards the shared engine — load-then-export must not interleave with another session's edit (see engine/mutex.ts). */\n engineLock: Mutex;\n /** Diagnostics telemetry port. Absent → no-op (no timing overhead beyond a few clocks). */\n telemetry?: TelemetrySink;\n}\n\nexport function createExportTool<E = unknown>(\n opts: CreateExportToolOptions<E>\n): CodesignMcpToolRegistration {\n const {\n fs,\n store,\n session,\n urlBuilder,\n allowOutPath = false,\n engineLock\n } = opts;\n const telemetry = opts.telemetry ?? NOOP_TELEMETRY_SINK;\n return {\n name: 'export',\n description: DESCRIPTION,\n inputSchema: buildExportInputSchema(allowOutPath),\n call: async (rawArgs) => {\n const rec = new SpanRecorder();\n const startedAt = performance.now();\n type CallResult = Awaited<\n ReturnType<CodesignMcpToolRegistration['call']>\n >;\n let result: CallResult | undefined;\n let threw: unknown;\n let revision: string | undefined;\n let exportError: unknown;\n try {\n result = await (async (): Promise<CallResult> => {\n const args = (rawArgs ?? {}) as Partial<ExportArgs>;\n if (\n typeof args.target !== 'string' ||\n typeof args.format !== 'string' ||\n typeof args.revision !== 'string'\n ) {\n return {\n isError: true,\n content: [\n {\n type: 'text' as const,\n text: 'export: target, format, and revision are required.'\n }\n ]\n };\n }\n if (args.target === 'video') {\n return {\n isError: true,\n content: [\n {\n type: 'text' as const,\n text: 'export: target=video is deferred to Phase 4.'\n }\n ]\n };\n }\n if (args.outPath !== undefined && !allowOutPath) {\n return {\n isError: true,\n content: [\n {\n type: 'text' as const,\n text: 'export: `outPath` is not supported on this (hosted) backend. Omit it — the artifact is written to the workspace and returned as `httpUrl`; fetch that URL to download the bytes to disk.'\n }\n ]\n };\n }\n const rev = await rec.time('workspace_read', () =>\n store.read(args.revision as string)\n );\n if (typeof args.blockId !== 'number') {\n return {\n isError: true,\n content: [\n {\n type: 'text' as const,\n text: `export: target=${args.target} requires \\`blockId\\`.`\n }\n ]\n };\n }\n const mimeMap = TARGET_MIME[args.target as 'pdf' | 'image'];\n const mime = mimeMap?.[args.format];\n if (!mime) {\n return {\n isError: true,\n content: [\n {\n type: 'text' as const,\n text: `export: invalid format=${args.format} for target=${args.target}.`\n }\n ]\n };\n }\n // Capture validated args into locals so the locked closure keeps the\n // type narrowing the top-level guards established.\n const revId = args.revision;\n const blockId = args.blockId;\n const sceneBytes = rev.scene;\n // load-into-engine then export reads the shared engine across awaits —\n // serialize against any concurrent engine-touching tool call.\n const beforeLock = performance.now();\n const rendered = await engineLock.runExclusive(\n async (): Promise<{ bytes: Uint8Array } | { error: unknown }> => {\n rec.add('lock_wait', performance.now() - beforeLock);\n const slot = await rec.time('engine_scene_load', async () => {\n await session.populate(revId, sceneBytes);\n return session.acquire(revId);\n });\n const eng = slot.engine as MinimalEngine;\n // We loaded `revId` under the lock just above, so the correct scene\n // is current. If the render throws, `blockId` genuinely isn't in\n // this revision's scene (a wrong or removed id) — return a legible\n // tool error the model can act on (mirroring `edit`'s dirty-on-throw\n // path) instead of rethrowing into an opaque MCP -32603.\n try {\n const blob = await rec.time('engine_execute', () =>\n eng.block.export(blockId, mime, {})\n );\n return { bytes: new Uint8Array(await blob.arrayBuffer()) };\n } catch (err) {\n return { error: err };\n }\n }\n );\n if ('error' in rendered) {\n exportError = rendered.error;\n return {\n isError: true,\n content: [\n {\n type: 'text' as const,\n text: `export: could not render block ${blockId} in revision ${revId}. That block id isn't in this revision's scene — double-check the id (use \\`inspect\\` to see the revision's structure), or it may have been removed in this revision. ${\n rendered.error instanceof Error\n ? (rendered.error.stack ?? rendered.error.message)\n : String(rendered.error)\n }`\n }\n ]\n };\n }\n const bytes = rendered.bytes;\n const shard = args.revision.slice(0, 2);\n const rest = args.revision.slice(2);\n const ext = FORMAT_EXT[args.format];\n const relPath = `exports/${shard}/${rest}/${args.target}.${ext}`;\n let absPath: string | undefined;\n let httpUrl: string | undefined;\n if (args.outPath !== undefined) {\n // Local-only escape hatch: write through real disk fs, NOT through\n // the workspace abstraction. The caller chose this path explicitly,\n // so echoing it back is a confirmation, not a workspace-path leak.\n await nodeFs.mkdir(dirname(args.outPath), { recursive: true });\n await rec.time('workspace_write', async () => {\n await nodeFs.writeFile(args.outPath as string, bytes);\n });\n absPath = args.outPath;\n } else {\n // Workspace write — goes through the WorkspaceFS abstraction. The\n // artifact is reachable over HTTP via the `/r/` route; the absolute\n // disk path is deliberately NOT disclosed.\n await rec.time('workspace_write', async () => {\n await fs.writeFile(relPath, bytes);\n });\n httpUrl = await urlBuilder.forDownload(relPath);\n }\n revision = args.revision;\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify({\n uri: `workspace://${relPath}`,\n ...(httpUrl ? { httpUrl } : {}),\n ...(absPath ? { path: absPath } : {}),\n bytes: bytes.byteLength,\n format: args.format,\n revision: args.revision\n })\n }\n ]\n };\n })();\n return result;\n } catch (err) {\n threw = err;\n throw err;\n } finally {\n telemetry.record({\n tool: 'export',\n succeeded: threw === undefined && result?.isError !== true,\n totalMs: performance.now() - startedAt,\n spans: rec.list(),\n args: rawArgs,\n ...(result !== undefined ? { result: summarizeResult(result) } : {}),\n ...(revision ? { revision } : {}),\n ...(threw\n ? { error: toErrorShape(threw) }\n : exportError\n ? { error: toErrorShape(exportError) }\n : {})\n });\n }\n }\n };\n}\n"]}
|
package/dist/tools/index.js
CHANGED
|
@@ -18,11 +18,11 @@ import { createImportTool } from './import.js';
|
|
|
18
18
|
import { createInspectTool } from './inspect.js';
|
|
19
19
|
import { createListTool } from './list.js';
|
|
20
20
|
import { createLoadTool } from './load.js';
|
|
21
|
-
import { createOpenEditorTool } from './open-editor.js';
|
|
22
21
|
import { createPreviewTool } from './preview.js';
|
|
23
22
|
import { createRenameTool } from './rename.js';
|
|
24
23
|
import { createSaveTool } from './save.js';
|
|
25
24
|
import { wrapWithTelemetry } from './telemetry-wrapper.js';
|
|
25
|
+
import { createViewTool } from './view.js';
|
|
26
26
|
// Beta kill-switch for asset_generate. Off for the beta (the feature isn't
|
|
27
27
|
// supported yet); set to true to re-expose the tool once it ships.
|
|
28
28
|
const ASSET_GENERATE_ENABLED = false;
|
|
@@ -75,7 +75,7 @@ export function buildDesignToolRegistrations(opts) {
|
|
|
75
75
|
createHistoryTool({ store: opts.store }),
|
|
76
76
|
createInspectTool({ store: opts.store }),
|
|
77
77
|
createRenameTool({ store: opts.store }),
|
|
78
|
-
|
|
78
|
+
createViewTool({ urlBuilder: opts.urlBuilder, store: opts.store }),
|
|
79
79
|
createAssetSearchTool({
|
|
80
80
|
session: opts.session,
|
|
81
81
|
engineLock: opts.engineLock
|
package/dist/tools/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"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","sourcesContent":["// packages/codesign-mcp/src/tools/index.ts\n//\n// Builds the design + workspace tool registrations from a fully-DI'd set of\n// primitives: the always-on design + workspace tools, plus `asset_generate`\n// — currently hidden for the beta (see ASSET_GENERATE_ENABLED below), and\n// otherwise gated on a usable gateway (Local: API_KEY set). A hidden tool\n// never shows up in tools/list, so the model won't attempt a call that can\n// only fail.\n// Each variant's CLI bootstrap (cli/stdio.ts, cli/http.ts)\n// constructs these primitives once and passes them in; this file owns no\n// engine bootstrap, no FS bootstrap, no gateway selection.\n\nimport type { Mutex } from '../engine/mutex.js';\nimport type { EngineSession } from '../engine/session.js';\nimport type { GatewayClient } from '../gateway/types.js';\nimport type { RevisionStore } from '../revisions/store.js';\nimport type { CodesignMcpToolRegistration } from '../server.js';\nimport type { ViewerUrlBuilder } from '../viewer/url-builder.js';\nimport type { WorkspaceFS } from '../workspace/types.js';\nimport type { TelemetrySink } from './spans.js';\nimport { createAssetGenerateTool } from './asset-generate.js';\nimport { createAssetSearchTool } from './asset-search.js';\nimport { createEditTool } from './edit.js';\nimport { createExportTool } from './export.js';\nimport { createHistoryTool } from './history.js';\nimport { createImportTool } from './import.js';\nimport { createInspectTool } from './inspect.js';\nimport { createListTool } from './list.js';\nimport { createLoadTool } from './load.js';\nimport { createOpenEditorTool } from './open-editor.js';\nimport { createPreviewTool } from './preview.js';\nimport { createRenameTool } from './rename.js';\nimport { createSaveTool } from './save.js';\nimport { wrapWithTelemetry } from './telemetry-wrapper.js';\n\n// Beta kill-switch for asset_generate. Off for the beta (the feature isn't\n// supported yet); set to true to re-expose the tool once it ships.\nconst ASSET_GENERATE_ENABLED = false;\n\nexport interface BuildDesignToolRegistrationsOptions<E = unknown> {\n fs: WorkspaceFS;\n store: RevisionStore;\n session: EngineSession<E>;\n /**\n * Serializes access to the shared CE.SDK engine across the edit/preview/\n * export tools. One engine today (process singleton) ⇒ one lock shared by\n * every session. See engine/mutex.ts and the bootstrap (cli/http.ts,\n * cli/stdio.ts) for where it is created.\n */\n engineLock: Mutex;\n gateway: GatewayClient;\n urlBuilder: ViewerUrlBuilder;\n /** True on Local (the `outPath?` escape hatch is allowed); false on Hosted/sandbox. */\n allowOutPath: boolean;\n /** Called when `edit` writes a new leaf revision (viewer SSE hook). */\n onLeafWritten?: (event: {\n revision: string;\n rootRevision: string;\n }) => void | Promise<void>;\n /** Render a thumbnail for a newly committed revision. Optional; best-effort. */\n renderThumbnail?: (event: {\n revision: string;\n engine: E;\n }) => Promise<Uint8Array>;\n /** Diagnostics telemetry port, threaded into the engine tools (edit/preview/export). */\n telemetry?: TelemetrySink;\n}\n\nexport function buildDesignToolRegistrations<E = unknown>(\n opts: BuildDesignToolRegistrationsOptions<E>\n): CodesignMcpToolRegistration[] {\n const registrations: CodesignMcpToolRegistration[] = [\n createEditTool({\n store: opts.store,\n session: opts.session,\n engineLock: opts.engineLock,\n onLeafWritten: opts.onLeafWritten,\n renderThumbnail: opts.renderThumbnail,\n fs: opts.fs,\n telemetry: opts.telemetry\n }),\n createPreviewTool({\n store: opts.store,\n session: opts.session,\n engineLock: opts.engineLock,\n telemetry: opts.telemetry\n }),\n createExportTool({\n fs: opts.fs,\n store: opts.store,\n session: opts.session,\n engineLock: opts.engineLock,\n urlBuilder: opts.urlBuilder,\n allowOutPath: opts.allowOutPath,\n telemetry: opts.telemetry\n }),\n createSaveTool({\n fs: opts.fs,\n store: opts.store,\n session: opts.session,\n engineLock: opts.engineLock,\n urlBuilder: opts.urlBuilder,\n allowOutPath: opts.allowOutPath\n }),\n createLoadTool({\n fs: opts.fs,\n store: opts.store,\n session: opts.session,\n engineLock: opts.engineLock,\n // Same Local-only disk gate as save/export's outPath: a `{ path }`\n // source only makes sense where the process shares a disk with the user.\n allowPath: opts.allowOutPath,\n onLeafWritten: opts.onLeafWritten,\n renderThumbnail: opts.renderThumbnail\n }),\n createListTool({ store: opts.store }),\n createHistoryTool({ store: opts.store }),\n createInspectTool({ store: opts.store }),\n createRenameTool({ store: opts.store }),\n createOpenEditorTool({ urlBuilder: opts.urlBuilder, store: opts.store }),\n createAssetSearchTool({\n session: opts.session,\n engineLock: opts.engineLock\n })\n ];\n\n // `import` is Local-only for now: its sole source arm (`{ path }`) needs a\n // server that shares the caller's disk. On Hosted there is no byte transport\n // until CODE-42, so we HIDE the tool there rather than show the model a tool\n // whose every call would fail. `allowOutPath` is the same Local(true)/\n // Hosted(false) signal export/save already use.\n if (opts.allowOutPath) {\n registrations.push(\n createImportTool({\n fs: opts.fs,\n urlBuilder: opts.urlBuilder,\n allowLocalPath: true\n })\n );\n }\n\n // BETA: asset_generate is hidden for the beta — not supported yet, and we\n // don't want the model to see a tool it can't use. The implementation\n // (asset-generate.ts, gateway plumbing) is intentionally kept intact; flip\n // ASSET_GENERATE_ENABLED back to true to re-expose it. Hiding the tool also\n // drops the handbook/instructions hint, which keys off tool presence.\n // Opt-in: only expose asset_generate when the gateway can fulfil a request.\n if (ASSET_GENERATE_ENABLED && opts.gateway.available) {\n registrations.push(\n createAssetGenerateTool({\n gateway: opts.gateway,\n fs: opts.fs,\n urlBuilder: opts.urlBuilder\n })\n );\n }\n\n // Diagnostics coverage. The engine tools (edit/preview/export) self-report a\n // rich ToolCallReport with phase spans (they were passed `telemetry` above).\n // Wrap EVERY other tool so its calls are recorded too — args, result, timing,\n // success — just with empty spans. Without a telemetry sink, nothing is\n // wrapped (zero overhead, byte-equivalent to before).\n if (!opts.telemetry) return registrations;\n const telemetry = opts.telemetry;\n const selfReporting = new Set(['edit', 'preview', 'export']);\n return registrations.map((registration) =>\n selfReporting.has(registration.name)\n ? registration\n : wrapWithTelemetry(registration, telemetry)\n );\n}\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"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","sourcesContent":["// packages/codesign-mcp/src/tools/index.ts\n//\n// Builds the design + workspace tool registrations from a fully-DI'd set of\n// primitives: the always-on design + workspace tools, plus `asset_generate`\n// — currently hidden for the beta (see ASSET_GENERATE_ENABLED below), and\n// otherwise gated on a usable gateway (Local: API_KEY set). A hidden tool\n// never shows up in tools/list, so the model won't attempt a call that can\n// only fail.\n// Each variant's CLI bootstrap (cli/stdio.ts, cli/http.ts)\n// constructs these primitives once and passes them in; this file owns no\n// engine bootstrap, no FS bootstrap, no gateway selection.\n\nimport type { Mutex } from '../engine/mutex.js';\nimport type { EngineSession } from '../engine/session.js';\nimport type { GatewayClient } from '../gateway/types.js';\nimport type { RevisionStore } from '../revisions/store.js';\nimport type { CodesignMcpToolRegistration } from '../server.js';\nimport type { ViewerUrlBuilder } from '../viewer/url-builder.js';\nimport type { WorkspaceFS } from '../workspace/types.js';\nimport type { TelemetrySink } from './spans.js';\nimport { createAssetGenerateTool } from './asset-generate.js';\nimport { createAssetSearchTool } from './asset-search.js';\nimport { createEditTool } from './edit.js';\nimport { createExportTool } from './export.js';\nimport { createHistoryTool } from './history.js';\nimport { createImportTool } from './import.js';\nimport { createInspectTool } from './inspect.js';\nimport { createListTool } from './list.js';\nimport { createLoadTool } from './load.js';\nimport { createPreviewTool } from './preview.js';\nimport { createRenameTool } from './rename.js';\nimport { createSaveTool } from './save.js';\nimport { wrapWithTelemetry } from './telemetry-wrapper.js';\nimport { createViewTool } from './view.js';\n\n// Beta kill-switch for asset_generate. Off for the beta (the feature isn't\n// supported yet); set to true to re-expose the tool once it ships.\nconst ASSET_GENERATE_ENABLED = false;\n\nexport interface BuildDesignToolRegistrationsOptions<E = unknown> {\n fs: WorkspaceFS;\n store: RevisionStore;\n session: EngineSession<E>;\n /**\n * Serializes access to the shared CE.SDK engine across the edit/preview/\n * export tools. One engine today (process singleton) ⇒ one lock shared by\n * every session. See engine/mutex.ts and the bootstrap (cli/http.ts,\n * cli/stdio.ts) for where it is created.\n */\n engineLock: Mutex;\n gateway: GatewayClient;\n urlBuilder: ViewerUrlBuilder;\n /** True on Local (the `outPath?` escape hatch is allowed); false on Hosted/sandbox. */\n allowOutPath: boolean;\n /** Called when `edit` writes a new leaf revision (viewer SSE hook). */\n onLeafWritten?: (event: {\n revision: string;\n rootRevision: string;\n }) => void | Promise<void>;\n /** Render a thumbnail for a newly committed revision. Optional; best-effort. */\n renderThumbnail?: (event: {\n revision: string;\n engine: E;\n }) => Promise<Uint8Array>;\n /** Diagnostics telemetry port, threaded into the engine tools (edit/preview/export). */\n telemetry?: TelemetrySink;\n}\n\nexport function buildDesignToolRegistrations<E = unknown>(\n opts: BuildDesignToolRegistrationsOptions<E>\n): CodesignMcpToolRegistration[] {\n const registrations: CodesignMcpToolRegistration[] = [\n createEditTool({\n store: opts.store,\n session: opts.session,\n engineLock: opts.engineLock,\n onLeafWritten: opts.onLeafWritten,\n renderThumbnail: opts.renderThumbnail,\n fs: opts.fs,\n telemetry: opts.telemetry\n }),\n createPreviewTool({\n store: opts.store,\n session: opts.session,\n engineLock: opts.engineLock,\n telemetry: opts.telemetry\n }),\n createExportTool({\n fs: opts.fs,\n store: opts.store,\n session: opts.session,\n engineLock: opts.engineLock,\n urlBuilder: opts.urlBuilder,\n allowOutPath: opts.allowOutPath,\n telemetry: opts.telemetry\n }),\n createSaveTool({\n fs: opts.fs,\n store: opts.store,\n session: opts.session,\n engineLock: opts.engineLock,\n urlBuilder: opts.urlBuilder,\n allowOutPath: opts.allowOutPath\n }),\n createLoadTool({\n fs: opts.fs,\n store: opts.store,\n session: opts.session,\n engineLock: opts.engineLock,\n // Same Local-only disk gate as save/export's outPath: a `{ path }`\n // source only makes sense where the process shares a disk with the user.\n allowPath: opts.allowOutPath,\n onLeafWritten: opts.onLeafWritten,\n renderThumbnail: opts.renderThumbnail\n }),\n createListTool({ store: opts.store }),\n createHistoryTool({ store: opts.store }),\n createInspectTool({ store: opts.store }),\n createRenameTool({ store: opts.store }),\n createViewTool({ urlBuilder: opts.urlBuilder, store: opts.store }),\n createAssetSearchTool({\n session: opts.session,\n engineLock: opts.engineLock\n })\n ];\n\n // `import` is Local-only for now: its sole source arm (`{ path }`) needs a\n // server that shares the caller's disk. On Hosted there is no byte transport\n // until CODE-42, so we HIDE the tool there rather than show the model a tool\n // whose every call would fail. `allowOutPath` is the same Local(true)/\n // Hosted(false) signal export/save already use.\n if (opts.allowOutPath) {\n registrations.push(\n createImportTool({\n fs: opts.fs,\n urlBuilder: opts.urlBuilder,\n allowLocalPath: true\n })\n );\n }\n\n // BETA: asset_generate is hidden for the beta — not supported yet, and we\n // don't want the model to see a tool it can't use. The implementation\n // (asset-generate.ts, gateway plumbing) is intentionally kept intact; flip\n // ASSET_GENERATE_ENABLED back to true to re-expose it. Hiding the tool also\n // drops the handbook/instructions hint, which keys off tool presence.\n // Opt-in: only expose asset_generate when the gateway can fulfil a request.\n if (ASSET_GENERATE_ENABLED && opts.gateway.available) {\n registrations.push(\n createAssetGenerateTool({\n gateway: opts.gateway,\n fs: opts.fs,\n urlBuilder: opts.urlBuilder\n })\n );\n }\n\n // Diagnostics coverage. The engine tools (edit/preview/export) self-report a\n // rich ToolCallReport with phase spans (they were passed `telemetry` above).\n // Wrap EVERY other tool so its calls are recorded too — args, result, timing,\n // success — just with empty spans. Without a telemetry sink, nothing is\n // wrapped (zero overhead, byte-equivalent to before).\n if (!opts.telemetry) return registrations;\n const telemetry = opts.telemetry;\n const selfReporting = new Set(['edit', 'preview', 'export']);\n return registrations.map((registration) =>\n selfReporting.has(registration.name)\n ? registration\n : wrapWithTelemetry(registration, telemetry)\n );\n}\n"]}
|
package/dist/tools/load.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"load.d.ts","sourceRoot":"","sources":["../../src/tools/load.ts"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAEhD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,cAAc,CAAC;AAEhE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"load.d.ts","sourceRoot":"","sources":["../../src/tools/load.ts"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAEhD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,cAAc,CAAC;AAEhE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAyUzD,MAAM,WAAW,qBAAqB,CAAC,CAAC,GAAG,OAAO;IAChD,EAAE,EAAE,WAAW,CAAC;IAChB,KAAK,EAAE,aAAa,CAAC;IACrB,OAAO,EAAE,aAAa,CAAC,CAAC,CAAC,CAAC;IAC1B,0GAA0G;IAC1G,UAAU,EAAE,KAAK,CAAC;IAClB,8EAA8E;IAC9E,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,uEAAuE;IACvE,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE;QACtB,QAAQ,EAAE,MAAM,CAAC;QACjB,YAAY,EAAE,MAAM,CAAC;KACtB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3B,oFAAoF;IACpF,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE;QACxB,QAAQ,EAAE,MAAM,CAAC;QACjB,MAAM,EAAE,CAAC,CAAC;KACX,KAAK,OAAO,CAAC,UAAU,CAAC,CAAC;CAC3B;AAED,wBAAgB,cAAc,CAAC,CAAC,GAAG,OAAO,EACxC,IAAI,EAAE,qBAAqB,CAAC,CAAC,CAAC,GAC7B,2BAA2B,CAmK7B"}
|