@imgly/codesign-mcp 0.1.6 → 0.1.7
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/dist/cli/http.d.ts.map +1 -1
- package/dist/cli/http.js +12 -2
- package/dist/cli/http.js.map +1 -1
- package/dist/cli/stdio.d.ts.map +1 -1
- package/dist/cli/stdio.js +103 -35
- package/dist/cli/stdio.js.map +1 -1
- package/dist/config.d.ts +11 -2
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +12 -1
- package/dist/config.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/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/tools/engine.d.ts +13 -0
- package/dist/tools/engine.d.ts.map +1 -1
- package/dist/tools/engine.js +28 -0
- package/dist/tools/engine.js.map +1 -1
- package/package.json +2 -2
- 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 +0 -2
- 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
|
@@ -1,174 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it, vi } from 'vitest';
|
|
2
|
-
import { Mutex } from '../../src/engine/mutex.js';
|
|
3
|
-
import { EngineSession } from '../../src/engine/session.js';
|
|
4
|
-
import { RevisionStore } from '../../src/revisions/store.js';
|
|
5
|
-
import { createExportTool } from '../../src/tools/export.js';
|
|
6
|
-
import { LocalViewerUrlBuilder } from '../../src/viewer/url-builder.js';
|
|
7
|
-
import { InMemoryWorkspaceFS } from '../../src/workspace/in-memory.js';
|
|
8
|
-
const engineLock = new Mutex();
|
|
9
|
-
const urlBuilder = new LocalViewerUrlBuilder({ base: 'http://127.0.0.1:9000' });
|
|
10
|
-
function makeDeps() {
|
|
11
|
-
const fs = new InMemoryWorkspaceFS();
|
|
12
|
-
const store = new RevisionStore(fs);
|
|
13
|
-
const fakeEngine = {
|
|
14
|
-
_scene: '',
|
|
15
|
-
block: {
|
|
16
|
-
export: vi.fn(async () => new Blob([new Uint8Array([0xff, 0xd8, 0xff, 0xe0])]))
|
|
17
|
-
},
|
|
18
|
-
scene: { saveToString: vi.fn(async () => '<scene-serialized/>') }
|
|
19
|
-
};
|
|
20
|
-
const adapter = {
|
|
21
|
-
create: () => fakeEngine,
|
|
22
|
-
reset: async (e) => {
|
|
23
|
-
e._scene = 'EMPTY';
|
|
24
|
-
},
|
|
25
|
-
loadFromString: async (e, s) => {
|
|
26
|
-
e._scene = s;
|
|
27
|
-
},
|
|
28
|
-
saveToString: async (e) => e._scene
|
|
29
|
-
};
|
|
30
|
-
const session = new EngineSession({ size: 1, adapter });
|
|
31
|
-
return { fs, store, session, fakeEngine };
|
|
32
|
-
}
|
|
33
|
-
describe('export tool', () => {
|
|
34
|
-
it('export target=image renders the block and writes the file deterministically', async () => {
|
|
35
|
-
const { fs, store, session } = makeDeps();
|
|
36
|
-
const root = await store.write({ scene: 'S', parent: null, title: 'T' });
|
|
37
|
-
const tool = createExportTool({
|
|
38
|
-
fs,
|
|
39
|
-
store,
|
|
40
|
-
session,
|
|
41
|
-
engineLock,
|
|
42
|
-
urlBuilder
|
|
43
|
-
});
|
|
44
|
-
const result = await tool.call({
|
|
45
|
-
target: 'image',
|
|
46
|
-
format: 'png',
|
|
47
|
-
revision: root.id,
|
|
48
|
-
blockId: 5
|
|
49
|
-
});
|
|
50
|
-
const body = JSON.parse(result.content[0].text);
|
|
51
|
-
const shard = root.id.slice(0, 2);
|
|
52
|
-
const rest = root.id.slice(2);
|
|
53
|
-
expect(body.uri).toBe(`workspace://exports/${shard}/${rest}/image.png`);
|
|
54
|
-
expect(await fs.exists(`exports/${shard}/${rest}/image.png`)).toBe(true);
|
|
55
|
-
});
|
|
56
|
-
it("export target=pdf renders via block.export('application/pdf')", async () => {
|
|
57
|
-
const { fs, store, session, fakeEngine } = makeDeps();
|
|
58
|
-
const root = await store.write({ scene: 'S', parent: null, title: 'T' });
|
|
59
|
-
const tool = createExportTool({
|
|
60
|
-
fs,
|
|
61
|
-
store,
|
|
62
|
-
session,
|
|
63
|
-
engineLock,
|
|
64
|
-
urlBuilder
|
|
65
|
-
});
|
|
66
|
-
await tool.call({
|
|
67
|
-
target: 'pdf',
|
|
68
|
-
format: 'pdf',
|
|
69
|
-
revision: root.id,
|
|
70
|
-
blockId: 5
|
|
71
|
-
});
|
|
72
|
-
expect(fakeEngine.block.export).toHaveBeenCalledWith(5, 'application/pdf', expect.any(Object));
|
|
73
|
-
});
|
|
74
|
-
it('returns isError when target=video (deferred to Phase 4)', async () => {
|
|
75
|
-
const { fs, store, session } = makeDeps();
|
|
76
|
-
const root = await store.write({ scene: 'S', parent: null, title: 'T' });
|
|
77
|
-
const tool = createExportTool({
|
|
78
|
-
fs,
|
|
79
|
-
store,
|
|
80
|
-
session,
|
|
81
|
-
engineLock,
|
|
82
|
-
urlBuilder
|
|
83
|
-
});
|
|
84
|
-
const result = await tool.call({
|
|
85
|
-
target: 'video',
|
|
86
|
-
format: 'mp4',
|
|
87
|
-
revision: root.id
|
|
88
|
-
});
|
|
89
|
-
expect(result.isError).toBe(true);
|
|
90
|
-
expect(result.content[0].text).toMatch(/phase 4/i);
|
|
91
|
-
});
|
|
92
|
-
it('respects local `outPath` escape hatch — returns path, not httpUrl', async () => {
|
|
93
|
-
const { fs, store, session } = makeDeps();
|
|
94
|
-
const root = await store.write({
|
|
95
|
-
scene: 'SCENE_X',
|
|
96
|
-
parent: null,
|
|
97
|
-
title: 'T'
|
|
98
|
-
});
|
|
99
|
-
const { mkdtemp, rm } = await import('node:fs/promises');
|
|
100
|
-
const { tmpdir } = await import('node:os');
|
|
101
|
-
const { join } = await import('node:path');
|
|
102
|
-
const dir = await mkdtemp(join(tmpdir(), 'export-out-'));
|
|
103
|
-
const outPath = join(dir, 'x.png');
|
|
104
|
-
const tool = createExportTool({
|
|
105
|
-
fs,
|
|
106
|
-
store,
|
|
107
|
-
session,
|
|
108
|
-
engineLock,
|
|
109
|
-
urlBuilder,
|
|
110
|
-
allowOutPath: true
|
|
111
|
-
});
|
|
112
|
-
const result = await tool.call({
|
|
113
|
-
target: 'image',
|
|
114
|
-
format: 'png',
|
|
115
|
-
revision: root.id,
|
|
116
|
-
blockId: 5,
|
|
117
|
-
outPath
|
|
118
|
-
});
|
|
119
|
-
const body = JSON.parse(result.content[0].text);
|
|
120
|
-
expect(body.path).toBe(outPath);
|
|
121
|
-
expect(body.httpUrl).toBeUndefined();
|
|
122
|
-
await rm(dir, { recursive: true });
|
|
123
|
-
});
|
|
124
|
-
it('rejects `outPath` when not allowed (Hosted/sandbox)', async () => {
|
|
125
|
-
const { fs, store, session } = makeDeps();
|
|
126
|
-
const root = await store.write({ scene: 'S', parent: null, title: 'T' });
|
|
127
|
-
const tool = createExportTool({
|
|
128
|
-
fs,
|
|
129
|
-
store,
|
|
130
|
-
session,
|
|
131
|
-
engineLock,
|
|
132
|
-
urlBuilder,
|
|
133
|
-
allowOutPath: false
|
|
134
|
-
});
|
|
135
|
-
const result = await tool.call({
|
|
136
|
-
target: 'image',
|
|
137
|
-
format: 'png',
|
|
138
|
-
revision: root.id,
|
|
139
|
-
blockId: 5,
|
|
140
|
-
outPath: '/tmp/x'
|
|
141
|
-
});
|
|
142
|
-
expect(result.isError).toBe(true);
|
|
143
|
-
expect(result.content[0].text).toMatch(/outPath.*not.*supported/i);
|
|
144
|
-
});
|
|
145
|
-
it('omits `outPath` from the schema when not allowed (Hosted), advertises it when allowed (Local)', () => {
|
|
146
|
-
const { fs, store, session } = makeDeps();
|
|
147
|
-
const base = { fs, store, session, engineLock, urlBuilder };
|
|
148
|
-
const hosted = createExportTool({ ...base, allowOutPath: false });
|
|
149
|
-
const local = createExportTool({ ...base, allowOutPath: true });
|
|
150
|
-
const props = (s) => s.properties;
|
|
151
|
-
expect(props(hosted.inputSchema)).not.toHaveProperty('outPath');
|
|
152
|
-
expect(props(local.inputSchema)).toHaveProperty('outPath');
|
|
153
|
-
});
|
|
154
|
-
it('rejects target=scene (moved to the save tool)', async () => {
|
|
155
|
-
const { fs, store, session } = makeDeps();
|
|
156
|
-
const root = await store.write({ scene: 'S', parent: null, title: 'T' });
|
|
157
|
-
const tool = createExportTool({
|
|
158
|
-
fs,
|
|
159
|
-
store,
|
|
160
|
-
session,
|
|
161
|
-
engineLock,
|
|
162
|
-
urlBuilder
|
|
163
|
-
});
|
|
164
|
-
const result = await tool.call({
|
|
165
|
-
target: 'scene',
|
|
166
|
-
format: 'scene',
|
|
167
|
-
revision: root.id,
|
|
168
|
-
blockId: 5
|
|
169
|
-
});
|
|
170
|
-
expect(result.isError).toBe(true);
|
|
171
|
-
expect(result.content[0].text).toMatch(/invalid format/i);
|
|
172
|
-
});
|
|
173
|
-
});
|
|
174
|
-
//# sourceMappingURL=export.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"export.test.js","sourceRoot":"","sources":["../../../../test/tools/export.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { describe, expect, it, vi } from 'vitest';\nimport { Mutex } from '../../src/engine/mutex.js';\nimport { type EngineAdapter, EngineSession } from '../../src/engine/session.js';\nimport { RevisionStore } from '../../src/revisions/store.js';\nimport { createExportTool } from '../../src/tools/export.js';\nimport { LocalViewerUrlBuilder } from '../../src/viewer/url-builder.js';\nimport { InMemoryWorkspaceFS } from '../../src/workspace/in-memory.js';\n\nconst engineLock = new Mutex();\n\ninterface FakeEngine {\n _scene: string;\n block: { export: ReturnType<typeof vi.fn> };\n scene: { saveToString: ReturnType<typeof vi.fn> };\n}\n\nconst urlBuilder = new LocalViewerUrlBuilder({ base: 'http://127.0.0.1:9000' });\n\nfunction makeDeps() {\n const fs = new InMemoryWorkspaceFS();\n const store = new RevisionStore(fs);\n const fakeEngine: FakeEngine = {\n _scene: '',\n block: {\n export: vi.fn(\n async () => new Blob([new Uint8Array([0xff, 0xd8, 0xff, 0xe0])])\n )\n },\n scene: { saveToString: vi.fn(async () => '<scene-serialized/>') }\n };\n const adapter: EngineAdapter<FakeEngine> = {\n create: () => fakeEngine,\n reset: async (e) => {\n e._scene = 'EMPTY';\n },\n loadFromString: async (e, s) => {\n e._scene = s;\n },\n saveToString: async (e) => e._scene\n };\n const session = new EngineSession<FakeEngine>({ size: 1, adapter });\n return { fs, store, session, fakeEngine };\n}\n\ndescribe('export tool', () => {\n it('export target=image renders the block and writes the file deterministically', async () => {\n const { fs, store, session } = makeDeps();\n const root = await store.write({ scene: 'S', parent: null, title: 'T' });\n const tool = createExportTool({\n fs,\n store,\n session,\n engineLock,\n urlBuilder\n });\n const result = await tool.call({\n target: 'image',\n format: 'png',\n revision: root.id,\n blockId: 5\n });\n const body = JSON.parse((result.content[0] as { text: string }).text) as {\n uri: string;\n };\n const shard = root.id.slice(0, 2);\n const rest = root.id.slice(2);\n expect(body.uri).toBe(`workspace://exports/${shard}/${rest}/image.png`);\n expect(await fs.exists(`exports/${shard}/${rest}/image.png`)).toBe(true);\n });\n\n it(\"export target=pdf renders via block.export('application/pdf')\", async () => {\n const { fs, store, session, fakeEngine } = makeDeps();\n const root = await store.write({ scene: 'S', parent: null, title: 'T' });\n const tool = createExportTool({\n fs,\n store,\n session,\n engineLock,\n urlBuilder\n });\n await tool.call({\n target: 'pdf',\n format: 'pdf',\n revision: root.id,\n blockId: 5\n });\n expect(fakeEngine.block.export).toHaveBeenCalledWith(\n 5,\n 'application/pdf',\n expect.any(Object)\n );\n });\n\n it('returns isError when target=video (deferred to Phase 4)', async () => {\n const { fs, store, session } = makeDeps();\n const root = await store.write({ scene: 'S', parent: null, title: 'T' });\n const tool = createExportTool({\n fs,\n store,\n session,\n engineLock,\n urlBuilder\n });\n const result = await tool.call({\n target: 'video',\n format: 'mp4',\n revision: root.id\n });\n expect(result.isError).toBe(true);\n expect((result.content[0] as { text: string }).text).toMatch(/phase 4/i);\n });\n\n it('respects local `outPath` escape hatch — returns path, not httpUrl', async () => {\n const { fs, store, session } = makeDeps();\n const root = await store.write({\n scene: 'SCENE_X',\n parent: null,\n title: 'T'\n });\n const { mkdtemp, rm } = await import('node:fs/promises');\n const { tmpdir } = await import('node:os');\n const { join } = await import('node:path');\n const dir = await mkdtemp(join(tmpdir(), 'export-out-'));\n const outPath = join(dir, 'x.png');\n const tool = createExportTool({\n fs,\n store,\n session,\n engineLock,\n urlBuilder,\n allowOutPath: true\n });\n const result = await tool.call({\n target: 'image',\n format: 'png',\n revision: root.id,\n blockId: 5,\n outPath\n });\n const body = JSON.parse((result.content[0] as { text: string }).text) as {\n path?: string;\n httpUrl?: string;\n };\n expect(body.path).toBe(outPath);\n expect(body.httpUrl).toBeUndefined();\n await rm(dir, { recursive: true });\n });\n\n it('rejects `outPath` when not allowed (Hosted/sandbox)', async () => {\n const { fs, store, session } = makeDeps();\n const root = await store.write({ scene: 'S', parent: null, title: 'T' });\n const tool = createExportTool({\n fs,\n store,\n session,\n engineLock,\n urlBuilder,\n allowOutPath: false\n });\n const result = await tool.call({\n target: 'image',\n format: 'png',\n revision: root.id,\n blockId: 5,\n outPath: '/tmp/x'\n });\n expect(result.isError).toBe(true);\n expect((result.content[0] as { text: string }).text).toMatch(\n /outPath.*not.*supported/i\n );\n });\n\n it('omits `outPath` from the schema when not allowed (Hosted), advertises it when allowed (Local)', () => {\n const { fs, store, session } = makeDeps();\n const base = { fs, store, session, engineLock, urlBuilder };\n const hosted = createExportTool({ ...base, allowOutPath: false });\n const local = createExportTool({ ...base, allowOutPath: true });\n const props = (s: unknown) =>\n (s as { properties: Record<string, unknown> }).properties;\n expect(props(hosted.inputSchema)).not.toHaveProperty('outPath');\n expect(props(local.inputSchema)).toHaveProperty('outPath');\n });\n\n it('rejects target=scene (moved to the save tool)', async () => {\n const { fs, store, session } = makeDeps();\n const root = await store.write({ scene: 'S', parent: null, title: 'T' });\n const tool = createExportTool({\n fs,\n store,\n session,\n engineLock,\n urlBuilder\n });\n const result = await tool.call({\n target: 'scene',\n format: 'scene',\n revision: root.id,\n blockId: 5\n });\n expect(result.isError).toBe(true);\n expect((result.content[0] as { text: string }).text).toMatch(\n /invalid format/i\n );\n });\n});\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"history.test.d.ts","sourceRoot":"","sources":["../../../../test/tools/history.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest';
|
|
2
|
-
import { RevisionStore } from '../../src/revisions/store.js';
|
|
3
|
-
import { createHistoryTool } from '../../src/tools/history.js';
|
|
4
|
-
import { InMemoryWorkspaceFS } from '../../src/workspace/in-memory.js';
|
|
5
|
-
describe('history tool', () => {
|
|
6
|
-
it('returns the chain from root to revision', async () => {
|
|
7
|
-
const store = new RevisionStore(new InMemoryWorkspaceFS());
|
|
8
|
-
const r1 = await store.write({
|
|
9
|
-
scene: 'a',
|
|
10
|
-
parent: null,
|
|
11
|
-
title: 'T',
|
|
12
|
-
note: 'init'
|
|
13
|
-
});
|
|
14
|
-
const r2 = await store.write({ scene: 'b', parent: r1.id, note: 'tweak' });
|
|
15
|
-
const r3 = await store.write({ scene: 'c', parent: r2.id, note: 'final' });
|
|
16
|
-
const tool = createHistoryTool({ store });
|
|
17
|
-
const result = await tool.call({ revision: r3.id });
|
|
18
|
-
const chain = JSON.parse(result.content[0].text);
|
|
19
|
-
expect(chain.map((r) => r.revision)).toEqual([r1.id, r2.id, r3.id]);
|
|
20
|
-
expect(chain.map((r) => r.note)).toEqual(['init', 'tweak', 'final']);
|
|
21
|
-
});
|
|
22
|
-
it('returns isError when revision is missing', async () => {
|
|
23
|
-
const store = new RevisionStore(new InMemoryWorkspaceFS());
|
|
24
|
-
const tool = createHistoryTool({ store });
|
|
25
|
-
const result = await tool.call({ revision: 'deadbeefdead' });
|
|
26
|
-
expect(result.isError).toBe(true);
|
|
27
|
-
});
|
|
28
|
-
});
|
|
29
|
-
//# sourceMappingURL=history.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"history.test.js","sourceRoot":"","sources":["../../../../test/tools/history.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAC/D,OAAO,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AAEvE,QAAQ,CAAC,cAAc,EAAE,GAAG,EAAE;IAC5B,EAAE,CAAC,yCAAyC,EAAE,KAAK,IAAI,EAAE;QACvD,MAAM,KAAK,GAAG,IAAI,aAAa,CAAC,IAAI,mBAAmB,EAAE,CAAC,CAAC;QAC3D,MAAM,EAAE,GAAG,MAAM,KAAK,CAAC,KAAK,CAAC;YAC3B,KAAK,EAAE,GAAG;YACV,MAAM,EAAE,IAAI;YACZ,KAAK,EAAE,GAAG;YACV,IAAI,EAAE,MAAM;SACb,CAAC,CAAC;QACH,MAAM,EAAE,GAAG,MAAM,KAAK,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;QAC3E,MAAM,EAAE,GAAG,MAAM,KAAK,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;QAC3E,MAAM,IAAI,GAAG,iBAAiB,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;QAC1C,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;QACpD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CACrB,MAAM,CAAC,OAAO,CAAC,CAAC,CAAsB,CAAC,IAAI,CAK5C,CAAC;QACH,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QACpE,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;IACvE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0CAA0C,EAAE,KAAK,IAAI,EAAE;QACxD,MAAM,KAAK,GAAG,IAAI,aAAa,CAAC,IAAI,mBAAmB,EAAE,CAAC,CAAC;QAC3D,MAAM,IAAI,GAAG,iBAAiB,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;QAC1C,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,cAAc,EAAE,CAAC,CAAC;QAC7D,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACpC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["import { describe, expect, it } from 'vitest';\nimport { RevisionStore } from '../../src/revisions/store.js';\nimport { createHistoryTool } from '../../src/tools/history.js';\nimport { InMemoryWorkspaceFS } from '../../src/workspace/in-memory.js';\n\ndescribe('history tool', () => {\n it('returns the chain from root to revision', async () => {\n const store = new RevisionStore(new InMemoryWorkspaceFS());\n const r1 = await store.write({\n scene: 'a',\n parent: null,\n title: 'T',\n note: 'init'\n });\n const r2 = await store.write({ scene: 'b', parent: r1.id, note: 'tweak' });\n const r3 = await store.write({ scene: 'c', parent: r2.id, note: 'final' });\n const tool = createHistoryTool({ store });\n const result = await tool.call({ revision: r3.id });\n const chain = JSON.parse(\n (result.content[0] as { text: string }).text\n ) as Array<{\n revision: string;\n parent: string | null;\n note?: string;\n }>;\n expect(chain.map((r) => r.revision)).toEqual([r1.id, r2.id, r3.id]);\n expect(chain.map((r) => r.note)).toEqual(['init', 'tweak', 'final']);\n });\n\n it('returns isError when revision is missing', async () => {\n const store = new RevisionStore(new InMemoryWorkspaceFS());\n const tool = createHistoryTool({ store });\n const result = await tool.call({ revision: 'deadbeefdead' });\n expect(result.isError).toBe(true);\n });\n});\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"import.test.d.ts","sourceRoot":"","sources":["../../../../test/tools/import.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,122 +0,0 @@
|
|
|
1
|
-
import { mkdtemp, rm, writeFile } from 'node:fs/promises';
|
|
2
|
-
import { tmpdir } from 'node:os';
|
|
3
|
-
import { join } from 'node:path';
|
|
4
|
-
import { afterAll, beforeAll, describe, expect, it } from 'vitest';
|
|
5
|
-
import { createImportTool } from '../../src/tools/import.js';
|
|
6
|
-
import { LocalViewerUrlBuilder } from '../../src/viewer/url-builder.js';
|
|
7
|
-
import { InMemoryWorkspaceFS } from '../../src/workspace/in-memory.js';
|
|
8
|
-
const urlBuilder = new LocalViewerUrlBuilder({ base: 'http://127.0.0.1:9000' });
|
|
9
|
-
let dir;
|
|
10
|
-
beforeAll(async () => {
|
|
11
|
-
dir = await mkdtemp(join(tmpdir(), 'import-in-'));
|
|
12
|
-
});
|
|
13
|
-
afterAll(async () => {
|
|
14
|
-
await rm(dir, { recursive: true, force: true });
|
|
15
|
-
});
|
|
16
|
-
async function tempFile(name, bytes) {
|
|
17
|
-
const p = join(dir, name);
|
|
18
|
-
await writeFile(p, bytes);
|
|
19
|
-
return p;
|
|
20
|
-
}
|
|
21
|
-
const textOf = (r) => r.content[0].text;
|
|
22
|
-
const parse = (r) => JSON.parse(textOf(r));
|
|
23
|
-
describe('import tool', () => {
|
|
24
|
-
it('imports a local JPG and persists it under assets/<sha>.jpg', async () => {
|
|
25
|
-
const fs = new InMemoryWorkspaceFS();
|
|
26
|
-
const tool = createImportTool({ fs, urlBuilder, allowLocalPath: true });
|
|
27
|
-
const path = await tempFile('beach.jpg', new Uint8Array([1, 2, 3, 4, 5]));
|
|
28
|
-
const result = await tool.call({ source: { path } });
|
|
29
|
-
expect(result.isError).toBeFalsy();
|
|
30
|
-
const body = parse(result);
|
|
31
|
-
expect(body.uri).toMatch(/^workspace:\/\/assets\/[0-9a-f]{12}\.jpg$/);
|
|
32
|
-
expect(body.mimeType).toBe('image/jpeg');
|
|
33
|
-
expect(body.kind).toBe('image');
|
|
34
|
-
expect(body.bytes).toBe(5);
|
|
35
|
-
const relPath = body.uri.replace('workspace://', '');
|
|
36
|
-
expect(Array.from(await fs.readFile(relPath))).toEqual([1, 2, 3, 4, 5]);
|
|
37
|
-
expect(body.httpUrl).toBe(`http://127.0.0.1:9000/r/${relPath}`);
|
|
38
|
-
});
|
|
39
|
-
it('classifies video (.mp4) and audio (.mp3) by extension', async () => {
|
|
40
|
-
const fs = new InMemoryWorkspaceFS();
|
|
41
|
-
const tool = createImportTool({ fs, urlBuilder, allowLocalPath: true });
|
|
42
|
-
const vid = await tool.call({
|
|
43
|
-
source: { path: await tempFile('clip.mp4', new Uint8Array([9])) }
|
|
44
|
-
});
|
|
45
|
-
const aud = await tool.call({
|
|
46
|
-
source: { path: await tempFile('song.mp3', new Uint8Array([8])) }
|
|
47
|
-
});
|
|
48
|
-
expect(parse(vid)).toMatchObject({ kind: 'video', mimeType: 'video/mp4' });
|
|
49
|
-
expect(parse(aud)).toMatchObject({ kind: 'audio', mimeType: 'audio/mpeg' });
|
|
50
|
-
});
|
|
51
|
-
it('canonicalizes extension + is case-insensitive (Photo.JPEG → assets/<sha>.jpg)', async () => {
|
|
52
|
-
const fs = new InMemoryWorkspaceFS();
|
|
53
|
-
const tool = createImportTool({ fs, urlBuilder, allowLocalPath: true });
|
|
54
|
-
const path = await tempFile('Photo.JPEG', new Uint8Array([1, 2, 3]));
|
|
55
|
-
const body = parse(await tool.call({ source: { path } }));
|
|
56
|
-
expect(body.mimeType).toBe('image/jpeg');
|
|
57
|
-
expect(body.kind).toBe('image');
|
|
58
|
-
expect(body.uri).toMatch(/^workspace:\/\/assets\/[0-9a-f]{12}\.jpg$/);
|
|
59
|
-
});
|
|
60
|
-
it('returns isError when source has no path (local, source: {})', async () => {
|
|
61
|
-
const fs = new InMemoryWorkspaceFS();
|
|
62
|
-
const tool = createImportTool({ fs, urlBuilder, allowLocalPath: true });
|
|
63
|
-
const result = await tool.call({ source: {} });
|
|
64
|
-
expect(result.isError).toBe(true);
|
|
65
|
-
expect(textOf(result)).toMatch(/source\.path/);
|
|
66
|
-
});
|
|
67
|
-
it('is content-addressed — same bytes import to the same uri (idempotent)', async () => {
|
|
68
|
-
const fs = new InMemoryWorkspaceFS();
|
|
69
|
-
const tool = createImportTool({ fs, urlBuilder, allowLocalPath: true });
|
|
70
|
-
const path = await tempFile('again.png', new Uint8Array([7, 7, 7]));
|
|
71
|
-
const a = parse(await tool.call({ source: { path } }));
|
|
72
|
-
const b = parse(await tool.call({ source: { path } }));
|
|
73
|
-
expect(a.uri).toBe(b.uri);
|
|
74
|
-
expect(await fs.readdir('assets')).toHaveLength(1);
|
|
75
|
-
});
|
|
76
|
-
it('rejects a relative source.path (must be absolute)', async () => {
|
|
77
|
-
const fs = new InMemoryWorkspaceFS();
|
|
78
|
-
const tool = createImportTool({ fs, urlBuilder, allowLocalPath: true });
|
|
79
|
-
const result = await tool.call({ source: { path: 'beach.jpg' } });
|
|
80
|
-
expect(result.isError).toBe(true);
|
|
81
|
-
expect(textOf(result)).toMatch(/absolute/i);
|
|
82
|
-
});
|
|
83
|
-
it('returns isError when the file does not exist (ENOENT)', async () => {
|
|
84
|
-
const fs = new InMemoryWorkspaceFS();
|
|
85
|
-
const tool = createImportTool({ fs, urlBuilder, allowLocalPath: true });
|
|
86
|
-
const missing = join(dir, 'nope.jpg');
|
|
87
|
-
const result = await tool.call({ source: { path: missing } });
|
|
88
|
-
expect(result.isError).toBe(true);
|
|
89
|
-
expect(textOf(result)).toContain(missing);
|
|
90
|
-
});
|
|
91
|
-
it('returns isError for an unsupported type', async () => {
|
|
92
|
-
const fs = new InMemoryWorkspaceFS();
|
|
93
|
-
const tool = createImportTool({ fs, urlBuilder, allowLocalPath: true });
|
|
94
|
-
const path = await tempFile('data.xyz', new Uint8Array([0]));
|
|
95
|
-
const result = await tool.call({ source: { path } });
|
|
96
|
-
expect(result.isError).toBe(true);
|
|
97
|
-
expect(textOf(result)).toMatch(/supported/i);
|
|
98
|
-
});
|
|
99
|
-
it('rejects `source.path` on a hosted backend (allowLocalPath false)', async () => {
|
|
100
|
-
const fs = new InMemoryWorkspaceFS();
|
|
101
|
-
const tool = createImportTool({ fs, urlBuilder, allowLocalPath: false });
|
|
102
|
-
const result = await tool.call({ source: { path: '/tmp/x.jpg' } });
|
|
103
|
-
expect(result.isError).toBe(true);
|
|
104
|
-
expect(textOf(result)).toMatch(/hosted|not supported/i);
|
|
105
|
-
});
|
|
106
|
-
it('advertises source.path only when allowLocalPath is true', () => {
|
|
107
|
-
const local = createImportTool({
|
|
108
|
-
fs: new InMemoryWorkspaceFS(),
|
|
109
|
-
urlBuilder,
|
|
110
|
-
allowLocalPath: true
|
|
111
|
-
});
|
|
112
|
-
const hosted = createImportTool({
|
|
113
|
-
fs: new InMemoryWorkspaceFS(),
|
|
114
|
-
urlBuilder,
|
|
115
|
-
allowLocalPath: false
|
|
116
|
-
});
|
|
117
|
-
const sourceProps = (t) => t.inputSchema.properties.source.properties;
|
|
118
|
-
expect(sourceProps(local)).toHaveProperty('path');
|
|
119
|
-
expect(sourceProps(hosted)).not.toHaveProperty('path');
|
|
120
|
-
});
|
|
121
|
-
});
|
|
122
|
-
//# sourceMappingURL=import.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"import.test.js","sourceRoot":"","sources":["../../../../test/tools/import.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { mkdtemp, rm, writeFile } from 'node:fs/promises';\nimport { tmpdir } from 'node:os';\nimport { join } from 'node:path';\nimport { afterAll, beforeAll, describe, expect, it } from 'vitest';\nimport { createImportTool } from '../../src/tools/import.js';\nimport { LocalViewerUrlBuilder } from '../../src/viewer/url-builder.js';\nimport { InMemoryWorkspaceFS } from '../../src/workspace/in-memory.js';\n\nconst urlBuilder = new LocalViewerUrlBuilder({ base: 'http://127.0.0.1:9000' });\n\nlet dir: string;\nbeforeAll(async () => {\n dir = await mkdtemp(join(tmpdir(), 'import-in-'));\n});\nafterAll(async () => {\n await rm(dir, { recursive: true, force: true });\n});\n\nasync function tempFile(name: string, bytes: Uint8Array): Promise<string> {\n const p = join(dir, name);\n await writeFile(p, bytes);\n return p;\n}\n\nconst textOf = (r: { content: Array<unknown> }) =>\n (r.content[0] as { text: string }).text;\nconst parse = (r: { content: Array<unknown> }) => JSON.parse(textOf(r));\n\ndescribe('import tool', () => {\n it('imports a local JPG and persists it under assets/<sha>.jpg', async () => {\n const fs = new InMemoryWorkspaceFS();\n const tool = createImportTool({ fs, urlBuilder, allowLocalPath: true });\n const path = await tempFile('beach.jpg', new Uint8Array([1, 2, 3, 4, 5]));\n const result = await tool.call({ source: { path } });\n expect(result.isError).toBeFalsy();\n const body = parse(result);\n expect(body.uri).toMatch(/^workspace:\\/\\/assets\\/[0-9a-f]{12}\\.jpg$/);\n expect(body.mimeType).toBe('image/jpeg');\n expect(body.kind).toBe('image');\n expect(body.bytes).toBe(5);\n const relPath = body.uri.replace('workspace://', '');\n expect(Array.from(await fs.readFile(relPath))).toEqual([1, 2, 3, 4, 5]);\n expect(body.httpUrl).toBe(`http://127.0.0.1:9000/r/${relPath}`);\n });\n\n it('classifies video (.mp4) and audio (.mp3) by extension', async () => {\n const fs = new InMemoryWorkspaceFS();\n const tool = createImportTool({ fs, urlBuilder, allowLocalPath: true });\n const vid = await tool.call({\n source: { path: await tempFile('clip.mp4', new Uint8Array([9])) }\n });\n const aud = await tool.call({\n source: { path: await tempFile('song.mp3', new Uint8Array([8])) }\n });\n expect(parse(vid)).toMatchObject({ kind: 'video', mimeType: 'video/mp4' });\n expect(parse(aud)).toMatchObject({ kind: 'audio', mimeType: 'audio/mpeg' });\n });\n\n it('canonicalizes extension + is case-insensitive (Photo.JPEG → assets/<sha>.jpg)', async () => {\n const fs = new InMemoryWorkspaceFS();\n const tool = createImportTool({ fs, urlBuilder, allowLocalPath: true });\n const path = await tempFile('Photo.JPEG', new Uint8Array([1, 2, 3]));\n const body = parse(await tool.call({ source: { path } }));\n expect(body.mimeType).toBe('image/jpeg');\n expect(body.kind).toBe('image');\n expect(body.uri).toMatch(/^workspace:\\/\\/assets\\/[0-9a-f]{12}\\.jpg$/);\n });\n\n it('returns isError when source has no path (local, source: {})', async () => {\n const fs = new InMemoryWorkspaceFS();\n const tool = createImportTool({ fs, urlBuilder, allowLocalPath: true });\n const result = await tool.call({ source: {} });\n expect(result.isError).toBe(true);\n expect(textOf(result)).toMatch(/source\\.path/);\n });\n\n it('is content-addressed — same bytes import to the same uri (idempotent)', async () => {\n const fs = new InMemoryWorkspaceFS();\n const tool = createImportTool({ fs, urlBuilder, allowLocalPath: true });\n const path = await tempFile('again.png', new Uint8Array([7, 7, 7]));\n const a = parse(await tool.call({ source: { path } }));\n const b = parse(await tool.call({ source: { path } }));\n expect(a.uri).toBe(b.uri);\n expect(await fs.readdir('assets')).toHaveLength(1);\n });\n\n it('rejects a relative source.path (must be absolute)', async () => {\n const fs = new InMemoryWorkspaceFS();\n const tool = createImportTool({ fs, urlBuilder, allowLocalPath: true });\n const result = await tool.call({ source: { path: 'beach.jpg' } });\n expect(result.isError).toBe(true);\n expect(textOf(result)).toMatch(/absolute/i);\n });\n\n it('returns isError when the file does not exist (ENOENT)', async () => {\n const fs = new InMemoryWorkspaceFS();\n const tool = createImportTool({ fs, urlBuilder, allowLocalPath: true });\n const missing = join(dir, 'nope.jpg');\n const result = await tool.call({ source: { path: missing } });\n expect(result.isError).toBe(true);\n expect(textOf(result)).toContain(missing);\n });\n\n it('returns isError for an unsupported type', async () => {\n const fs = new InMemoryWorkspaceFS();\n const tool = createImportTool({ fs, urlBuilder, allowLocalPath: true });\n const path = await tempFile('data.xyz', new Uint8Array([0]));\n const result = await tool.call({ source: { path } });\n expect(result.isError).toBe(true);\n expect(textOf(result)).toMatch(/supported/i);\n });\n\n it('rejects `source.path` on a hosted backend (allowLocalPath false)', async () => {\n const fs = new InMemoryWorkspaceFS();\n const tool = createImportTool({ fs, urlBuilder, allowLocalPath: false });\n const result = await tool.call({ source: { path: '/tmp/x.jpg' } });\n expect(result.isError).toBe(true);\n expect(textOf(result)).toMatch(/hosted|not supported/i);\n });\n\n it('advertises source.path only when allowLocalPath is true', () => {\n const local = createImportTool({\n fs: new InMemoryWorkspaceFS(),\n urlBuilder,\n allowLocalPath: true\n });\n const hosted = createImportTool({\n fs: new InMemoryWorkspaceFS(),\n urlBuilder,\n allowLocalPath: false\n });\n const sourceProps = (t: { inputSchema: unknown }) =>\n (\n t.inputSchema as {\n properties: { source: { properties: Record<string, unknown> } };\n }\n ).properties.source.properties;\n expect(sourceProps(local)).toHaveProperty('path');\n expect(sourceProps(hosted)).not.toHaveProperty('path');\n });\n});\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.test.d.ts","sourceRoot":"","sources":["../../../../test/tools/index.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest';
|
|
2
|
-
import { buildDesignToolRegistrations } from '../../src/tools/index.js';
|
|
3
|
-
// The tool factories only close over their deps (they touch them on `call`,
|
|
4
|
-
// not at construction), so stub primitives are enough to assert which tools
|
|
5
|
-
// get registered.
|
|
6
|
-
const stub = {};
|
|
7
|
-
function gateway(available) {
|
|
8
|
-
return {
|
|
9
|
-
available,
|
|
10
|
-
generateImage: async () => ({
|
|
11
|
-
bytes: new Uint8Array(),
|
|
12
|
-
mimeType: 'image/png'
|
|
13
|
-
})
|
|
14
|
-
};
|
|
15
|
-
}
|
|
16
|
-
function baseBuildOpts() {
|
|
17
|
-
return {
|
|
18
|
-
fs: stub,
|
|
19
|
-
store: stub,
|
|
20
|
-
session: stub,
|
|
21
|
-
engineLock: stub,
|
|
22
|
-
gateway: gateway(false),
|
|
23
|
-
urlBuilder: stub,
|
|
24
|
-
allowOutPath: true
|
|
25
|
-
};
|
|
26
|
-
}
|
|
27
|
-
function toolNames(available, allowOutPath = true) {
|
|
28
|
-
return buildDesignToolRegistrations({
|
|
29
|
-
...baseBuildOpts(),
|
|
30
|
-
gateway: gateway(available),
|
|
31
|
-
allowOutPath
|
|
32
|
-
}).map((t) => t.name);
|
|
33
|
-
}
|
|
34
|
-
// Tools present on every backend. asset_generate (beta-hidden) and import
|
|
35
|
-
// (Local-only) are deployment-gated and asserted separately below.
|
|
36
|
-
const alwaysOn = [
|
|
37
|
-
'edit',
|
|
38
|
-
'preview',
|
|
39
|
-
'export',
|
|
40
|
-
'save',
|
|
41
|
-
'load',
|
|
42
|
-
'list',
|
|
43
|
-
'history',
|
|
44
|
-
'inspect',
|
|
45
|
-
'rename',
|
|
46
|
-
'open_editor',
|
|
47
|
-
'asset_search'
|
|
48
|
-
];
|
|
49
|
-
// asset_generate is hidden for the beta via the ASSET_GENERATE_ENABLED
|
|
50
|
-
// kill-switch in src/tools/index.ts, so it is omitted regardless of gateway
|
|
51
|
-
// availability. When the feature ships and the flag flips back to true, the
|
|
52
|
-
// "available" case should assert it IS registered again.
|
|
53
|
-
describe('buildDesignToolRegistrations — asset_generate gating (beta: hidden)', () => {
|
|
54
|
-
it('omits asset_generate when the gateway is unavailable (no API_KEY)', () => {
|
|
55
|
-
const names = toolNames(false);
|
|
56
|
-
expect(names).not.toContain('asset_generate');
|
|
57
|
-
expect(names).toEqual([...alwaysOn, 'import']); // Local backend
|
|
58
|
-
});
|
|
59
|
-
it('stays hidden even when the gateway is available (beta kill-switch)', () => {
|
|
60
|
-
const names = toolNames(true);
|
|
61
|
-
expect(names).not.toContain('asset_generate');
|
|
62
|
-
expect(names).toEqual([...alwaysOn, 'import']); // Local backend
|
|
63
|
-
});
|
|
64
|
-
});
|
|
65
|
-
// `import` is Local-only until hosted byte transports land (CODE-42): it is
|
|
66
|
-
// registered when the backend shares the caller's disk (allowOutPath=true) and
|
|
67
|
-
// hidden otherwise, so the model never sees a tool whose every hosted call fails.
|
|
68
|
-
describe('buildDesignToolRegistrations — import gating (Local-only)', () => {
|
|
69
|
-
it('registers import on Local (allowOutPath=true)', () => {
|
|
70
|
-
expect(toolNames(false, true)).toContain('import');
|
|
71
|
-
});
|
|
72
|
-
it('hides import on Hosted (allowOutPath=false) until CODE-42', () => {
|
|
73
|
-
const names = toolNames(false, false);
|
|
74
|
-
expect(names).not.toContain('import');
|
|
75
|
-
expect(names).toEqual(alwaysOn);
|
|
76
|
-
});
|
|
77
|
-
});
|
|
78
|
-
describe('buildDesignToolRegistrations — telemetry threading', () => {
|
|
79
|
-
it('threads telemetry into the engine tools', async () => {
|
|
80
|
-
const reports = [];
|
|
81
|
-
const regs = buildDesignToolRegistrations({
|
|
82
|
-
...baseBuildOpts(),
|
|
83
|
-
telemetry: { record: (r) => reports.push(r) }
|
|
84
|
-
});
|
|
85
|
-
const preview = regs.find((r) => r.name === 'preview');
|
|
86
|
-
await preview.call({}); // missing blockId -> isError, but still recorded
|
|
87
|
-
expect(reports.some((r) => r.tool === 'preview')).toBe(true);
|
|
88
|
-
});
|
|
89
|
-
it('wraps non-engine tools so every call is recorded (with empty spans)', async () => {
|
|
90
|
-
const reports = [];
|
|
91
|
-
const regs = buildDesignToolRegistrations({
|
|
92
|
-
...baseBuildOpts(),
|
|
93
|
-
telemetry: { record: (r) => reports.push(r) }
|
|
94
|
-
});
|
|
95
|
-
// `list` has no internal telemetry; the wrapper must still record it. The
|
|
96
|
-
// stub store makes the call throw, but the wrapper records in its finally.
|
|
97
|
-
const list = regs.find((r) => r.name === 'list');
|
|
98
|
-
await list.call({}).catch(() => { });
|
|
99
|
-
const rec = reports.find((r) => r.tool === 'list');
|
|
100
|
-
expect(rec).toBeDefined();
|
|
101
|
-
expect(rec.spans).toEqual([]);
|
|
102
|
-
expect(rec.args).toEqual({});
|
|
103
|
-
});
|
|
104
|
-
it('captures the tool result in the report', async () => {
|
|
105
|
-
const reports = [];
|
|
106
|
-
const regs = buildDesignToolRegistrations({
|
|
107
|
-
...baseBuildOpts(),
|
|
108
|
-
telemetry: { record: (r) => reports.push(r) }
|
|
109
|
-
});
|
|
110
|
-
const preview = regs.find((r) => r.name === 'preview');
|
|
111
|
-
await preview.call({}); // missing blockId -> isError result (not a throw)
|
|
112
|
-
const rec = reports.find((r) => r.tool === 'preview');
|
|
113
|
-
expect(rec.result).toBeDefined();
|
|
114
|
-
expect(JSON.stringify(rec.result)).toContain('blockId');
|
|
115
|
-
});
|
|
116
|
-
});
|
|
117
|
-
//# sourceMappingURL=index.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.test.js","sourceRoot":"","sources":["../../../../test/tools/index.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { describe, expect, it } from 'vitest';\nimport type { GatewayClient } from '../../src/gateway/types.js';\nimport {\n buildDesignToolRegistrations,\n type BuildDesignToolRegistrationsOptions\n} from '../../src/tools/index.js';\nimport type { ToolCallReport } from '../../src/tools/spans.js';\n\n// The tool factories only close over their deps (they touch them on `call`,\n// not at construction), so stub primitives are enough to assert which tools\n// get registered.\nconst stub = {} as never;\n\nfunction gateway(available: boolean): GatewayClient {\n return {\n available,\n generateImage: async () => ({\n bytes: new Uint8Array(),\n mimeType: 'image/png'\n })\n };\n}\n\nfunction baseBuildOpts(): BuildDesignToolRegistrationsOptions {\n return {\n fs: stub,\n store: stub,\n session: stub,\n engineLock: stub,\n gateway: gateway(false),\n urlBuilder: stub,\n allowOutPath: true\n };\n}\n\nfunction toolNames(available: boolean, allowOutPath = true): string[] {\n return buildDesignToolRegistrations({\n ...baseBuildOpts(),\n gateway: gateway(available),\n allowOutPath\n }).map((t) => t.name);\n}\n\n// Tools present on every backend. asset_generate (beta-hidden) and import\n// (Local-only) are deployment-gated and asserted separately below.\nconst alwaysOn = [\n 'edit',\n 'preview',\n 'export',\n 'save',\n 'load',\n 'list',\n 'history',\n 'inspect',\n 'rename',\n 'open_editor',\n 'asset_search'\n];\n\n// asset_generate is hidden for the beta via the ASSET_GENERATE_ENABLED\n// kill-switch in src/tools/index.ts, so it is omitted regardless of gateway\n// availability. When the feature ships and the flag flips back to true, the\n// \"available\" case should assert it IS registered again.\ndescribe('buildDesignToolRegistrations — asset_generate gating (beta: hidden)', () => {\n it('omits asset_generate when the gateway is unavailable (no API_KEY)', () => {\n const names = toolNames(false);\n expect(names).not.toContain('asset_generate');\n expect(names).toEqual([...alwaysOn, 'import']); // Local backend\n });\n\n it('stays hidden even when the gateway is available (beta kill-switch)', () => {\n const names = toolNames(true);\n expect(names).not.toContain('asset_generate');\n expect(names).toEqual([...alwaysOn, 'import']); // Local backend\n });\n});\n\n// `import` is Local-only until hosted byte transports land (CODE-42): it is\n// registered when the backend shares the caller's disk (allowOutPath=true) and\n// hidden otherwise, so the model never sees a tool whose every hosted call fails.\ndescribe('buildDesignToolRegistrations — import gating (Local-only)', () => {\n it('registers import on Local (allowOutPath=true)', () => {\n expect(toolNames(false, true)).toContain('import');\n });\n\n it('hides import on Hosted (allowOutPath=false) until CODE-42', () => {\n const names = toolNames(false, false);\n expect(names).not.toContain('import');\n expect(names).toEqual(alwaysOn);\n });\n});\n\ndescribe('buildDesignToolRegistrations — telemetry threading', () => {\n it('threads telemetry into the engine tools', async () => {\n const reports: ToolCallReport[] = [];\n const regs = buildDesignToolRegistrations({\n ...baseBuildOpts(),\n telemetry: { record: (r) => reports.push(r) }\n });\n const preview = regs.find((r) => r.name === 'preview')!;\n await preview.call({}); // missing blockId -> isError, but still recorded\n expect(reports.some((r) => r.tool === 'preview')).toBe(true);\n });\n\n it('wraps non-engine tools so every call is recorded (with empty spans)', async () => {\n const reports: ToolCallReport[] = [];\n const regs = buildDesignToolRegistrations({\n ...baseBuildOpts(),\n telemetry: { record: (r) => reports.push(r) }\n });\n // `list` has no internal telemetry; the wrapper must still record it. The\n // stub store makes the call throw, but the wrapper records in its finally.\n const list = regs.find((r) => r.name === 'list')!;\n await list.call({}).catch(() => {});\n const rec = reports.find((r) => r.tool === 'list');\n expect(rec).toBeDefined();\n expect(rec!.spans).toEqual([]);\n expect(rec!.args).toEqual({});\n });\n\n it('captures the tool result in the report', async () => {\n const reports: ToolCallReport[] = [];\n const regs = buildDesignToolRegistrations({\n ...baseBuildOpts(),\n telemetry: { record: (r) => reports.push(r) }\n });\n const preview = regs.find((r) => r.name === 'preview')!;\n await preview.call({}); // missing blockId -> isError result (not a throw)\n const rec = reports.find((r) => r.tool === 'preview')!;\n expect(rec.result).toBeDefined();\n expect(JSON.stringify(rec.result)).toContain('blockId');\n });\n});\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"inspect.test.d.ts","sourceRoot":"","sources":["../../../../test/tools/inspect.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest';
|
|
2
|
-
import { RevisionStore } from '../../src/revisions/store.js';
|
|
3
|
-
import { createInspectTool } from '../../src/tools/inspect.js';
|
|
4
|
-
import { InMemoryWorkspaceFS } from '../../src/workspace/in-memory.js';
|
|
5
|
-
describe('inspect tool', () => {
|
|
6
|
-
it('returns revision meta plus the persisted code', async () => {
|
|
7
|
-
const store = new RevisionStore(new InMemoryWorkspaceFS());
|
|
8
|
-
const written = await store.write({
|
|
9
|
-
scene: 'scene-bytes',
|
|
10
|
-
parent: null,
|
|
11
|
-
title: 'Holiday Card',
|
|
12
|
-
note: 'blank A6 portrait',
|
|
13
|
-
code: 'const page = engine.scene.create();'
|
|
14
|
-
});
|
|
15
|
-
const tool = createInspectTool({ store });
|
|
16
|
-
const result = await tool.call({ revision: written.id });
|
|
17
|
-
const body = JSON.parse(result.content[0].text);
|
|
18
|
-
expect(body.revision).toBe(written.id);
|
|
19
|
-
expect(body.parent).toBeNull();
|
|
20
|
-
expect(body.title).toBe('Holiday Card');
|
|
21
|
-
expect(body.note).toBe('blank A6 portrait');
|
|
22
|
-
expect(body.code).toBe('const page = engine.scene.create();');
|
|
23
|
-
expect(typeof body.createdAt).toBe('number');
|
|
24
|
-
});
|
|
25
|
-
it('omits code when the revision has none', async () => {
|
|
26
|
-
const store = new RevisionStore(new InMemoryWorkspaceFS());
|
|
27
|
-
const written = await store.write({ scene: 's', parent: null, title: 'T' });
|
|
28
|
-
const tool = createInspectTool({ store });
|
|
29
|
-
const result = await tool.call({ revision: written.id });
|
|
30
|
-
const body = JSON.parse(result.content[0].text);
|
|
31
|
-
expect(body.code).toBeUndefined();
|
|
32
|
-
});
|
|
33
|
-
it('omits title for non-root revisions', async () => {
|
|
34
|
-
const store = new RevisionStore(new InMemoryWorkspaceFS());
|
|
35
|
-
const root = await store.write({ scene: 'v1', parent: null, title: 'T' });
|
|
36
|
-
const child = await store.write({
|
|
37
|
-
scene: 'v2',
|
|
38
|
-
parent: root.id,
|
|
39
|
-
note: 'tweak',
|
|
40
|
-
code: '// child'
|
|
41
|
-
});
|
|
42
|
-
const tool = createInspectTool({ store });
|
|
43
|
-
const result = await tool.call({ revision: child.id });
|
|
44
|
-
const body = JSON.parse(result.content[0].text);
|
|
45
|
-
expect(body.title).toBeUndefined();
|
|
46
|
-
expect(body.parent).toBe(root.id);
|
|
47
|
-
});
|
|
48
|
-
it('returns isError for an unknown revision', async () => {
|
|
49
|
-
const store = new RevisionStore(new InMemoryWorkspaceFS());
|
|
50
|
-
const tool = createInspectTool({ store });
|
|
51
|
-
const result = await tool.call({ revision: 'deadbeefdead' });
|
|
52
|
-
expect(result.isError).toBe(true);
|
|
53
|
-
expect(result.content[0].text).toMatch(/unknown revision/i);
|
|
54
|
-
});
|
|
55
|
-
it('returns isError when revision argument is missing', async () => {
|
|
56
|
-
const store = new RevisionStore(new InMemoryWorkspaceFS());
|
|
57
|
-
const tool = createInspectTool({ store });
|
|
58
|
-
const result = await tool.call({});
|
|
59
|
-
expect(result.isError).toBe(true);
|
|
60
|
-
});
|
|
61
|
-
});
|
|
62
|
-
//# sourceMappingURL=inspect.test.js.map
|