@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
|
@@ -15,6 +15,10 @@ import type { EngineAdapter } from './session.js';
|
|
|
15
15
|
* calls `create()` on the first slot (first edit), awaiting it then — by which
|
|
16
16
|
* point init is usually already settled. The other methods receive the resolved
|
|
17
17
|
* engine from EngineSession, so they never touch the promise.
|
|
18
|
+
*
|
|
19
|
+
* `engine` may also be a thunk `() => Promise<CreativeEngine>`: the stdio
|
|
20
|
+
* transport passes a lazy, slot-gated boot so no engine initializes until the
|
|
21
|
+
* first edit calls create().
|
|
18
22
|
*/
|
|
19
|
-
export declare function cesdkAdapter(engine: CreativeEngine | Promise<CreativeEngine>): EngineAdapter<CreativeEngine>;
|
|
23
|
+
export declare function cesdkAdapter(engine: CreativeEngine | Promise<CreativeEngine> | (() => CreativeEngine | Promise<CreativeEngine>)): EngineAdapter<CreativeEngine>;
|
|
20
24
|
//# sourceMappingURL=cesdk-adapter.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cesdk-adapter.d.ts","sourceRoot":"","sources":["../../src/engine/cesdk-adapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,cAAc,MAAM,eAAe,CAAC;AAEhD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAElD
|
|
1
|
+
{"version":3,"file":"cesdk-adapter.d.ts","sourceRoot":"","sources":["../../src/engine/cesdk-adapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,cAAc,MAAM,eAAe,CAAC;AAEhD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAElD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,YAAY,CAC1B,MAAM,EACF,cAAc,GACd,OAAO,CAAC,cAAc,CAAC,GACvB,CAAC,MAAM,cAAc,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC,GACnD,aAAa,CAAC,cAAc,CAAC,CAiB/B"}
|
|
@@ -14,10 +14,17 @@ import { SCENE_ALLOWED_RESOURCE_SCHEMES } from './scene-resource-schemes.js';
|
|
|
14
14
|
* calls `create()` on the first slot (first edit), awaiting it then — by which
|
|
15
15
|
* point init is usually already settled. The other methods receive the resolved
|
|
16
16
|
* engine from EngineSession, so they never touch the promise.
|
|
17
|
+
*
|
|
18
|
+
* `engine` may also be a thunk `() => Promise<CreativeEngine>`: the stdio
|
|
19
|
+
* transport passes a lazy, slot-gated boot so no engine initializes until the
|
|
20
|
+
* first edit calls create().
|
|
17
21
|
*/
|
|
18
22
|
export function cesdkAdapter(engine) {
|
|
19
23
|
return {
|
|
20
|
-
|
|
24
|
+
// Value/promise: always the same instance. Thunk: the stdio transport passes
|
|
25
|
+
// a lazy slot-gated boot (CODE-59) so nothing initializes until the first
|
|
26
|
+
// edit; EngineSession(size:1) calls create() only once, on that first edit.
|
|
27
|
+
create: () => (typeof engine === 'function' ? engine() : engine),
|
|
21
28
|
reset: async (eng) => {
|
|
22
29
|
eng.scene.create(); // wipes the active scene; design-unit patch from tools/engine.ts re-applies
|
|
23
30
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cesdk-adapter.js","sourceRoot":"","sources":["../../src/engine/cesdk-adapter.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,8BAA8B,EAAE,MAAM,6BAA6B,CAAC;AAG7E
|
|
1
|
+
{"version":3,"file":"cesdk-adapter.js","sourceRoot":"","sources":["../../src/engine/cesdk-adapter.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,8BAA8B,EAAE,MAAM,6BAA6B,CAAC;AAG7E;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,UAAU,YAAY,CAC1B,MAGoD;IAEpD,OAAO;QACL,6EAA6E;QAC7E,0EAA0E;QAC1E,4EAA4E;QAC5E,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC,OAAO,MAAM,KAAK,UAAU,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;QAChE,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;YACnB,GAAG,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,4EAA4E;QAClG,CAAC;QACD,cAAc,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE;YACnC,MAAM,GAAG,CAAC,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;QACxC,CAAC;QACD,YAAY,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE,CAC1B,GAAG,CAAC,KAAK,CAAC,YAAY,CAAC;YACrB,sBAAsB,EAAE,8BAA8B;SACvD,CAAC;KACL,CAAC;AACJ,CAAC","sourcesContent":["import type CreativeEngine from '@cesdk/engine';\nimport { SCENE_ALLOWED_RESOURCE_SCHEMES } from './scene-resource-schemes.js';\nimport type { EngineAdapter } from './session.js';\n\n/**\n * Adapts a `@cesdk/engine` CreativeEngine instance to the EngineSession's\n * generic EngineAdapter shape. One-to-one mapping; two quirks. First, `reset`\n * (CE.SDK has no `reset()` — we wipe by creating a new scene via the same\n * patched create path `ensureHeadlessEngine` installed for the design-unit fix).\n * Second, `saveToString` passes an explicit `allowedResourceSchemes`: the\n * engine default rejects our durable `workspace://` scheme, so an edit commit\n * of a scene referencing workspace assets would fail without it (see\n * scene-resource-schemes.ts, CODE-3).\n *\n * `engine` may be a Promise: the stdio transport defers engine init off the\n * MCP-handshake path and hands the in-flight promise here. EngineSession only\n * calls `create()` on the first slot (first edit), awaiting it then — by which\n * point init is usually already settled. The other methods receive the resolved\n * engine from EngineSession, so they never touch the promise.\n *\n * `engine` may also be a thunk `() => Promise<CreativeEngine>`: the stdio\n * transport passes a lazy, slot-gated boot so no engine initializes until the\n * first edit calls create().\n */\nexport function cesdkAdapter(\n engine:\n | CreativeEngine\n | Promise<CreativeEngine>\n | (() => CreativeEngine | Promise<CreativeEngine>)\n): EngineAdapter<CreativeEngine> {\n return {\n // Value/promise: always the same instance. Thunk: the stdio transport passes\n // a lazy slot-gated boot (CODE-59) so nothing initializes until the first\n // edit; EngineSession(size:1) calls create() only once, on that first edit.\n create: () => (typeof engine === 'function' ? engine() : engine),\n reset: async (eng) => {\n eng.scene.create(); // wipes the active scene; design-unit patch from tools/engine.ts re-applies\n },\n loadFromString: async (eng, scene) => {\n await eng.scene.loadFromString(scene);\n },\n saveToString: async (eng) =>\n eng.scene.saveToString({\n allowedResourceSchemes: SCENE_ALLOWED_RESOURCE_SCHEMES\n })\n };\n}\n"]}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { CodesignMcpToolRegistration } from '../server.js';
|
|
2
|
+
/** Thrown from the slot-gated engine boot when all engine slots are held. */
|
|
3
|
+
export declare class EngineCapacityError extends Error {
|
|
4
|
+
readonly max: number;
|
|
5
|
+
constructor(max: number);
|
|
6
|
+
}
|
|
7
|
+
/** The agent-facing capacity message, templated on the live cap. */
|
|
8
|
+
export declare function capacityMessage(max: number): string;
|
|
9
|
+
/**
|
|
10
|
+
* Wrap a tool registration so a thrown EngineCapacityError becomes a clean MCP
|
|
11
|
+
* isError result (the capacity message) instead of propagating as a protocol
|
|
12
|
+
* error. Other errors pass through untouched. Applied to every tool at the stdio
|
|
13
|
+
* composition root; a no-op for tools that never touch the engine.
|
|
14
|
+
*/
|
|
15
|
+
export declare function wrapEngineCapacity(reg: CodesignMcpToolRegistration): CodesignMcpToolRegistration;
|
|
16
|
+
//# sourceMappingURL=engine-capacity.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engine-capacity.d.ts","sourceRoot":"","sources":["../../src/engine/engine-capacity.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,cAAc,CAAC;AAEhE,6EAA6E;AAC7E,qBAAa,mBAAoB,SAAQ,KAAK;IAChC,QAAQ,CAAC,GAAG,EAAE,MAAM;gBAAX,GAAG,EAAE,MAAM;CAIjC;AAED,oEAAoE;AACpE,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAYnD;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,2BAA2B,GAC/B,2BAA2B,CAiB7B"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/** Thrown from the slot-gated engine boot when all engine slots are held. */
|
|
2
|
+
export class EngineCapacityError extends Error {
|
|
3
|
+
constructor(max) {
|
|
4
|
+
super(`engine capacity reached (max=${max})`);
|
|
5
|
+
this.max = max;
|
|
6
|
+
this.name = 'EngineCapacityError';
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
/** The agent-facing capacity message, templated on the live cap. */
|
|
10
|
+
export function capacityMessage(max) {
|
|
11
|
+
return [
|
|
12
|
+
`Design engine capacity reached — ${max} of ${max} CE.SDK engines are already running on this machine.`,
|
|
13
|
+
`This is a temporary, machine-wide limit that prevents parallel design sessions from exhausting memory. Your request was valid — nothing is wrong with your code or inputs, and no design was created. A slot frees automatically as soon as another session finishes or closes.`,
|
|
14
|
+
``,
|
|
15
|
+
`What to do:`,
|
|
16
|
+
`- Retry the exact same call after a short wait — resending it unchanged will succeed once a slot is free.`,
|
|
17
|
+
`- Do not modify your design code in response to this; the code is not the problem.`,
|
|
18
|
+
`- If you are running several design tasks at once, run them one at a time instead of in parallel.`,
|
|
19
|
+
``,
|
|
20
|
+
`(The human can raise the limit by setting IMGLY_MAX_STDIO_ENGINES higher and restarting. Current limit: ${max}.)`
|
|
21
|
+
].join('\n');
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Wrap a tool registration so a thrown EngineCapacityError becomes a clean MCP
|
|
25
|
+
* isError result (the capacity message) instead of propagating as a protocol
|
|
26
|
+
* error. Other errors pass through untouched. Applied to every tool at the stdio
|
|
27
|
+
* composition root; a no-op for tools that never touch the engine.
|
|
28
|
+
*/
|
|
29
|
+
export function wrapEngineCapacity(reg) {
|
|
30
|
+
return {
|
|
31
|
+
...reg,
|
|
32
|
+
call: async (args) => {
|
|
33
|
+
try {
|
|
34
|
+
return await reg.call(args);
|
|
35
|
+
}
|
|
36
|
+
catch (err) {
|
|
37
|
+
if (err instanceof EngineCapacityError) {
|
|
38
|
+
return {
|
|
39
|
+
isError: true,
|
|
40
|
+
content: [{ type: 'text', text: capacityMessage(err.max) }]
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
throw err;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=engine-capacity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engine-capacity.js","sourceRoot":"","sources":["../../src/engine/engine-capacity.ts"],"names":[],"mappings":"AAYA,6EAA6E;AAC7E,MAAM,OAAO,mBAAoB,SAAQ,KAAK;IAC5C,YAAqB,GAAW;QAC9B,KAAK,CAAC,gCAAgC,GAAG,GAAG,CAAC,CAAC;QAD3B,QAAG,GAAH,GAAG,CAAQ;QAE9B,IAAI,CAAC,IAAI,GAAG,qBAAqB,CAAC;IACpC,CAAC;CACF;AAED,oEAAoE;AACpE,MAAM,UAAU,eAAe,CAAC,GAAW;IACzC,OAAO;QACL,oCAAoC,GAAG,OAAO,GAAG,sDAAsD;QACvG,iRAAiR;QACjR,EAAE;QACF,aAAa;QACb,2GAA2G;QAC3G,oFAAoF;QACpF,mGAAmG;QACnG,EAAE;QACF,2GAA2G,GAAG,IAAI;KACnH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,kBAAkB,CAChC,GAAgC;IAEhC,OAAO;QACL,GAAG,GAAG;QACN,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;YACnB,IAAI,CAAC;gBACH,OAAO,MAAM,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC9B,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,IAAI,GAAG,YAAY,mBAAmB,EAAE,CAAC;oBACvC,OAAO;wBACL,OAAO,EAAE,IAAI;wBACb,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,eAAe,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;qBAC5D,CAAC;gBACJ,CAAC;gBACD,MAAM,GAAG,CAAC;YACZ,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC","sourcesContent":["// packages/codesign-mcp/src/engine/engine-capacity.ts\n//\n// The machine-wide engine cap (CODE-59) fails fast: when every slot is held, the\n// triggering tool call returns an MCP isError result carrying an agent-facing\n// message — NOT a thrown protocol error. This module owns that error type, the\n// message, and the wrapper that turns the throw into the result.\n//\n// The message is a deliberate design surface: it is read by an LLM, so it (a)\n// states the request/code is fine (stops the model rewriting its design), (b)\n// says it is retryable and how, (c) tells an orchestrator to reduce parallelism.\nimport type { CodesignMcpToolRegistration } from '../server.js';\n\n/** Thrown from the slot-gated engine boot when all engine slots are held. */\nexport class EngineCapacityError extends Error {\n constructor(readonly max: number) {\n super(`engine capacity reached (max=${max})`);\n this.name = 'EngineCapacityError';\n }\n}\n\n/** The agent-facing capacity message, templated on the live cap. */\nexport function capacityMessage(max: number): string {\n return [\n `Design engine capacity reached — ${max} of ${max} CE.SDK engines are already running on this machine.`,\n `This is a temporary, machine-wide limit that prevents parallel design sessions from exhausting memory. Your request was valid — nothing is wrong with your code or inputs, and no design was created. A slot frees automatically as soon as another session finishes or closes.`,\n ``,\n `What to do:`,\n `- Retry the exact same call after a short wait — resending it unchanged will succeed once a slot is free.`,\n `- Do not modify your design code in response to this; the code is not the problem.`,\n `- If you are running several design tasks at once, run them one at a time instead of in parallel.`,\n ``,\n `(The human can raise the limit by setting IMGLY_MAX_STDIO_ENGINES higher and restarting. Current limit: ${max}.)`\n ].join('\\n');\n}\n\n/**\n * Wrap a tool registration so a thrown EngineCapacityError becomes a clean MCP\n * isError result (the capacity message) instead of propagating as a protocol\n * error. Other errors pass through untouched. Applied to every tool at the stdio\n * composition root; a no-op for tools that never touch the engine.\n */\nexport function wrapEngineCapacity(\n reg: CodesignMcpToolRegistration\n): CodesignMcpToolRegistration {\n return {\n ...reg,\n call: async (args) => {\n try {\n return await reg.call(args);\n } catch (err) {\n if (err instanceof EngineCapacityError) {\n return {\n isError: true,\n content: [{ type: 'text', text: capacityMessage(err.max) }]\n };\n }\n throw err;\n }\n }\n };\n}\n"]}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
export interface SlotHandle {
|
|
2
|
+
/** Which numbered slot (0-based) this handle owns. */
|
|
3
|
+
readonly index: number;
|
|
4
|
+
/** Release the slot (unlink its file). Idempotent; best-effort. */
|
|
5
|
+
release(): Promise<void>;
|
|
6
|
+
}
|
|
7
|
+
export interface AcquireEngineSlotOptions {
|
|
8
|
+
/** Max concurrent engines. The (max)th acquire succeeds; the (max+1)th returns null. */
|
|
9
|
+
max: number;
|
|
10
|
+
/** Slot directory. Defaults to ~/.codesign/engine-slots. Override in tests. */
|
|
11
|
+
dir?: string;
|
|
12
|
+
/** Liveness probe for a slot's owner PID. Defaults to a real kill(pid,0). Injectable for tests. */
|
|
13
|
+
isPidAlive?: (pid: number) => boolean;
|
|
14
|
+
/** This process's PID, recorded in the claimed slot. Defaults to process.pid. */
|
|
15
|
+
pid?: number;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* True if a process with `pid` is alive. `kill(pid, 0)` sends no signal; it only
|
|
19
|
+
* probes. ESRCH => no such process (dead). EPERM (exists, another user) or any
|
|
20
|
+
* other error => assume alive (conservative — never steal a slot we're unsure of).
|
|
21
|
+
*/
|
|
22
|
+
export declare function isPidAlive(pid: number): boolean;
|
|
23
|
+
/**
|
|
24
|
+
* Claim one of `max` numbered slots. Returns a handle for the first free (or
|
|
25
|
+
* reclaimable-stale) slot, or null when all `max` are held by live owners.
|
|
26
|
+
*/
|
|
27
|
+
export declare function acquireEngineSlot(opts: AcquireEngineSlotOptions): Promise<SlotHandle | null>;
|
|
28
|
+
export interface SlotGatedEngine<E> {
|
|
29
|
+
/**
|
|
30
|
+
* Boot the engine on first call, gated by a machine-wide slot. Memoized: later
|
|
31
|
+
* calls return the same engine. Throws EngineCapacityError at capacity (the
|
|
32
|
+
* memo is NOT cached, so a later retry re-attempts). A boot FAILURE is cached
|
|
33
|
+
* (a hard init error must not churn slots on retry) and its slot is released.
|
|
34
|
+
*/
|
|
35
|
+
get(): Promise<E>;
|
|
36
|
+
/** Release the held slot (for the clean-shutdown path). Idempotent. */
|
|
37
|
+
release(): Promise<void>;
|
|
38
|
+
}
|
|
39
|
+
export declare function createSlotGatedEngine<E>(opts: {
|
|
40
|
+
max: number;
|
|
41
|
+
boot: () => Promise<E>;
|
|
42
|
+
dir?: string;
|
|
43
|
+
acquire?: (o: {
|
|
44
|
+
max: number;
|
|
45
|
+
dir?: string;
|
|
46
|
+
}) => Promise<SlotHandle | null>;
|
|
47
|
+
}): SlotGatedEngine<E>;
|
|
48
|
+
//# sourceMappingURL=engine-slots.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engine-slots.d.ts","sourceRoot":"","sources":["../../src/engine/engine-slots.ts"],"names":[],"mappings":"AA4CA,MAAM,WAAW,UAAU;IACzB,sDAAsD;IACtD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,mEAAmE;IACnE,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1B;AAED,MAAM,WAAW,wBAAwB;IACvC,wFAAwF;IACxF,GAAG,EAAE,MAAM,CAAC;IACZ,+EAA+E;IAC/E,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,mGAAmG;IACnG,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC;IACtC,iFAAiF;IACjF,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAO/C;AAED;;;GAGG;AACH,wBAAsB,iBAAiB,CACrC,IAAI,EAAE,wBAAwB,GAC7B,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAU5B;AA+ED,MAAM,WAAW,eAAe,CAAC,CAAC;IAChC;;;;;OAKG;IACH,GAAG,IAAI,OAAO,CAAC,CAAC,CAAC,CAAC;IAClB,uEAAuE;IACvE,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1B;AAED,wBAAgB,qBAAqB,CAAC,CAAC,EAAE,IAAI,EAAE;IAC7C,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,CAAC;IACvB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,CAAC,CAAC,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAAC;CAC5E,GAAG,eAAe,CAAC,CAAC,CAAC,CAmCrB"}
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
// packages/codesign-mcp/src/engine/engine-slots.ts
|
|
2
|
+
//
|
|
3
|
+
// Machine-wide (per-user) semaphore bounding how many CE.SDK engines boot
|
|
4
|
+
// concurrently across ALL independent codesign-mcp stdio processes. Each engine
|
|
5
|
+
// costs ~82 MB idle / 200-300 MB active, so a handful stacked across parallel
|
|
6
|
+
// sessions can OOM the machine (CODE-59). No in-process cap can bound the total —
|
|
7
|
+
// each stdio server is its own process with its own singleton engine — so the
|
|
8
|
+
// coordination point lives on the filesystem.
|
|
9
|
+
//
|
|
10
|
+
// Mechanism: N slot files slot-0..slot-(N-1) under ~/.codesign/engine-slots. A
|
|
11
|
+
// slot is claimed by atomically creating its file with O_EXCL (open(path,'wx')).
|
|
12
|
+
// The file records the owner PID; a slot whose PID is dead (process.kill(pid,0)
|
|
13
|
+
// -> ESRCH) is reclaimed on the next acquire — the backstop for SIGKILL, where
|
|
14
|
+
// the clean release path (CODE-53 shutdown) never runs. Reclaim renames the
|
|
15
|
+
// stale file to a per-PID tombstone; rename() requires the source to exist, so
|
|
16
|
+
// only one concurrent reclaimer of the SAME stale file wins (losers get ENOENT
|
|
17
|
+
// and re-loop to see the new owner). Clean release unlinks.
|
|
18
|
+
//
|
|
19
|
+
// Scope: the slot dir is under the user's home, so the cap is really per-user —
|
|
20
|
+
// which matches the OOM scenario (one user's many parallel sessions).
|
|
21
|
+
//
|
|
22
|
+
// Known limitations — both narrow, both at worst a TRANSIENT over-provision by
|
|
23
|
+
// ~1 (never the unbounded, dozens-of-engines OOM this prevents), self-correcting
|
|
24
|
+
// on process exit. Neither is fixable with portable fs primitives: O_EXCL create
|
|
25
|
+
// is the only atomic mutual-exclusion primitive, and it cannot reclaim an
|
|
26
|
+
// already-occupied name, so every content-blind removal (unlink OR rename) has a
|
|
27
|
+
// TOCTOU. A single-process broker (the deferred "Approach C") is the real fix if
|
|
28
|
+
// hard multi-process correctness is ever required.
|
|
29
|
+
// 1. PID reuse: a dead owner's PID could be recycled by an unrelated live
|
|
30
|
+
// process, making a stale slot look alive until that PID exits.
|
|
31
|
+
// 2. Concurrent-reclaim straggler: rename() is content-blind, so if reclaimer
|
|
32
|
+
// B's rename syscall lags reclaimer A's full reclaim+recreate cycle, B's
|
|
33
|
+
// rename can steal A's already-recreated FRESH file and both end up owning
|
|
34
|
+
// the slot. rename() closes the common simultaneous case; this residual
|
|
35
|
+
// needs adversarial sub-millisecond syscall reordering across processes.
|
|
36
|
+
// (A tombstone orphaned by SIGKILL between rename and its cleanup unlink is inert
|
|
37
|
+
// litter — acquire only ever touches exact `slot-<i>` paths, never `*.dead.*`.)
|
|
38
|
+
import { mkdir, open, readFile, rename, unlink } from 'node:fs/promises';
|
|
39
|
+
import { homedir } from 'node:os';
|
|
40
|
+
import { join } from 'node:path';
|
|
41
|
+
import { EngineCapacityError } from './engine-capacity.js';
|
|
42
|
+
const DEFAULT_SLOT_DIR = join(homedir(), '.codesign', 'engine-slots');
|
|
43
|
+
/**
|
|
44
|
+
* True if a process with `pid` is alive. `kill(pid, 0)` sends no signal; it only
|
|
45
|
+
* probes. ESRCH => no such process (dead). EPERM (exists, another user) or any
|
|
46
|
+
* other error => assume alive (conservative — never steal a slot we're unsure of).
|
|
47
|
+
*/
|
|
48
|
+
export function isPidAlive(pid) {
|
|
49
|
+
try {
|
|
50
|
+
process.kill(pid, 0);
|
|
51
|
+
return true;
|
|
52
|
+
}
|
|
53
|
+
catch (err) {
|
|
54
|
+
return err.code !== 'ESRCH';
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Claim one of `max` numbered slots. Returns a handle for the first free (or
|
|
59
|
+
* reclaimable-stale) slot, or null when all `max` are held by live owners.
|
|
60
|
+
*/
|
|
61
|
+
export async function acquireEngineSlot(opts) {
|
|
62
|
+
const dir = opts.dir ?? DEFAULT_SLOT_DIR;
|
|
63
|
+
const alive = opts.isPidAlive ?? isPidAlive;
|
|
64
|
+
const pid = opts.pid ?? process.pid;
|
|
65
|
+
await mkdir(dir, { recursive: true });
|
|
66
|
+
for (let i = 0; i < opts.max; i++) {
|
|
67
|
+
const handle = await tryClaimSlot(join(dir, `slot-${i}`), i, pid, alive);
|
|
68
|
+
if (handle)
|
|
69
|
+
return handle;
|
|
70
|
+
}
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
async function tryClaimSlot(path, index, pid, alive) {
|
|
74
|
+
// Two attempts: create; if occupied-but-dead, reclaim and retry the create.
|
|
75
|
+
for (let attempt = 0; attempt < 2; attempt++) {
|
|
76
|
+
try {
|
|
77
|
+
const fh = await open(path, 'wx'); // O_CREAT | O_EXCL — atomic claim
|
|
78
|
+
try {
|
|
79
|
+
await fh.writeFile(JSON.stringify({ pid, bootedAt: Date.now() }));
|
|
80
|
+
}
|
|
81
|
+
finally {
|
|
82
|
+
await fh.close();
|
|
83
|
+
}
|
|
84
|
+
return makeHandle(path, index);
|
|
85
|
+
}
|
|
86
|
+
catch (err) {
|
|
87
|
+
if (err.code !== 'EEXIST')
|
|
88
|
+
throw err;
|
|
89
|
+
if (!(await ownerIsDead(path, alive)))
|
|
90
|
+
return null; // held by a live owner
|
|
91
|
+
// Reclaim atomically: rename the stale file aside. rename() requires the
|
|
92
|
+
// source to exist, so only ONE concurrent reclaimer of the same slot
|
|
93
|
+
// succeeds; the losers get ENOENT and re-loop to see the new owner. An
|
|
94
|
+
// unconditional unlink+recreate would instead let a second reclaimer
|
|
95
|
+
// delete the first's fresh file and double-occupy the slot.
|
|
96
|
+
const tomb = `${path}.dead.${pid}`;
|
|
97
|
+
try {
|
|
98
|
+
await rename(path, tomb);
|
|
99
|
+
}
|
|
100
|
+
catch (e) {
|
|
101
|
+
if (e.code === 'ENOENT')
|
|
102
|
+
continue; // lost the reclaim; retry the slot
|
|
103
|
+
throw e;
|
|
104
|
+
}
|
|
105
|
+
await unlink(tomb).catch(() => { }); // best-effort tombstone cleanup
|
|
106
|
+
// slot path is now free; loop retries the exclusive create
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
return null; // lost the reclaim race — treat as taken, move on
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Is the slot file's recorded owner provably dead? Only a slot with a readable,
|
|
113
|
+
* valid PID that is not alive is reclaimable. Empty/malformed/unreadable => treat
|
|
114
|
+
* as ALIVE (return false) so we never steal a slot a peer just created with
|
|
115
|
+
* O_EXCL but has not finished writing yet.
|
|
116
|
+
*/
|
|
117
|
+
async function ownerIsDead(path, alive) {
|
|
118
|
+
let raw;
|
|
119
|
+
try {
|
|
120
|
+
raw = await readFile(path, 'utf8');
|
|
121
|
+
}
|
|
122
|
+
catch {
|
|
123
|
+
return false;
|
|
124
|
+
}
|
|
125
|
+
let pid;
|
|
126
|
+
try {
|
|
127
|
+
pid = JSON.parse(raw).pid;
|
|
128
|
+
}
|
|
129
|
+
catch {
|
|
130
|
+
return false;
|
|
131
|
+
}
|
|
132
|
+
return typeof pid === 'number' && !alive(pid);
|
|
133
|
+
}
|
|
134
|
+
function makeHandle(path, index) {
|
|
135
|
+
let released = false;
|
|
136
|
+
return {
|
|
137
|
+
index,
|
|
138
|
+
release: async () => {
|
|
139
|
+
if (released)
|
|
140
|
+
return;
|
|
141
|
+
released = true;
|
|
142
|
+
await unlink(path).catch(() => { }); // ENOENT etc. — best-effort
|
|
143
|
+
}
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
export function createSlotGatedEngine(opts) {
|
|
147
|
+
const acquire = opts.acquire ?? acquireEngineSlot;
|
|
148
|
+
let engine;
|
|
149
|
+
let handle;
|
|
150
|
+
const boot = async () => {
|
|
151
|
+
const h = await acquire({
|
|
152
|
+
max: opts.max,
|
|
153
|
+
...(opts.dir !== undefined ? { dir: opts.dir } : {})
|
|
154
|
+
});
|
|
155
|
+
if (!h) {
|
|
156
|
+
engine = undefined; // capacity is retryable — don't memoize the rejection
|
|
157
|
+
throw new EngineCapacityError(opts.max);
|
|
158
|
+
}
|
|
159
|
+
handle = h;
|
|
160
|
+
try {
|
|
161
|
+
return await opts.boot();
|
|
162
|
+
}
|
|
163
|
+
catch (err) {
|
|
164
|
+
// Hard init failure: free the slot (don't hold it for a dead engine). Keep
|
|
165
|
+
// the rejected memo so retries don't churn slots on a permanent failure.
|
|
166
|
+
await h.release().catch(() => { });
|
|
167
|
+
handle = undefined;
|
|
168
|
+
throw err;
|
|
169
|
+
}
|
|
170
|
+
};
|
|
171
|
+
return {
|
|
172
|
+
get: () => (engine ??= boot()),
|
|
173
|
+
release: async () => {
|
|
174
|
+
const h = handle;
|
|
175
|
+
handle = undefined;
|
|
176
|
+
engine = undefined;
|
|
177
|
+
if (h)
|
|
178
|
+
await h.release();
|
|
179
|
+
}
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
//# sourceMappingURL=engine-slots.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engine-slots.js","sourceRoot":"","sources":["../../src/engine/engine-slots.ts"],"names":[],"mappings":"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","sourcesContent":["// packages/codesign-mcp/src/engine/engine-slots.ts\n//\n// Machine-wide (per-user) semaphore bounding how many CE.SDK engines boot\n// concurrently across ALL independent codesign-mcp stdio processes. Each engine\n// costs ~82 MB idle / 200-300 MB active, so a handful stacked across parallel\n// sessions can OOM the machine (CODE-59). No in-process cap can bound the total —\n// each stdio server is its own process with its own singleton engine — so the\n// coordination point lives on the filesystem.\n//\n// Mechanism: N slot files slot-0..slot-(N-1) under ~/.codesign/engine-slots. A\n// slot is claimed by atomically creating its file with O_EXCL (open(path,'wx')).\n// The file records the owner PID; a slot whose PID is dead (process.kill(pid,0)\n// -> ESRCH) is reclaimed on the next acquire — the backstop for SIGKILL, where\n// the clean release path (CODE-53 shutdown) never runs. Reclaim renames the\n// stale file to a per-PID tombstone; rename() requires the source to exist, so\n// only one concurrent reclaimer of the SAME stale file wins (losers get ENOENT\n// and re-loop to see the new owner). Clean release unlinks.\n//\n// Scope: the slot dir is under the user's home, so the cap is really per-user —\n// which matches the OOM scenario (one user's many parallel sessions).\n//\n// Known limitations — both narrow, both at worst a TRANSIENT over-provision by\n// ~1 (never the unbounded, dozens-of-engines OOM this prevents), self-correcting\n// on process exit. Neither is fixable with portable fs primitives: O_EXCL create\n// is the only atomic mutual-exclusion primitive, and it cannot reclaim an\n// already-occupied name, so every content-blind removal (unlink OR rename) has a\n// TOCTOU. A single-process broker (the deferred \"Approach C\") is the real fix if\n// hard multi-process correctness is ever required.\n// 1. PID reuse: a dead owner's PID could be recycled by an unrelated live\n// process, making a stale slot look alive until that PID exits.\n// 2. Concurrent-reclaim straggler: rename() is content-blind, so if reclaimer\n// B's rename syscall lags reclaimer A's full reclaim+recreate cycle, B's\n// rename can steal A's already-recreated FRESH file and both end up owning\n// the slot. rename() closes the common simultaneous case; this residual\n// needs adversarial sub-millisecond syscall reordering across processes.\n// (A tombstone orphaned by SIGKILL between rename and its cleanup unlink is inert\n// litter — acquire only ever touches exact `slot-<i>` paths, never `*.dead.*`.)\nimport { mkdir, open, readFile, rename, unlink } from 'node:fs/promises';\nimport { homedir } from 'node:os';\nimport { join } from 'node:path';\nimport { EngineCapacityError } from './engine-capacity.js';\n\nconst DEFAULT_SLOT_DIR = join(homedir(), '.codesign', 'engine-slots');\n\nexport interface SlotHandle {\n /** Which numbered slot (0-based) this handle owns. */\n readonly index: number;\n /** Release the slot (unlink its file). Idempotent; best-effort. */\n release(): Promise<void>;\n}\n\nexport interface AcquireEngineSlotOptions {\n /** Max concurrent engines. The (max)th acquire succeeds; the (max+1)th returns null. */\n max: number;\n /** Slot directory. Defaults to ~/.codesign/engine-slots. Override in tests. */\n dir?: string;\n /** Liveness probe for a slot's owner PID. Defaults to a real kill(pid,0). Injectable for tests. */\n isPidAlive?: (pid: number) => boolean;\n /** This process's PID, recorded in the claimed slot. Defaults to process.pid. */\n pid?: number;\n}\n\n/**\n * True if a process with `pid` is alive. `kill(pid, 0)` sends no signal; it only\n * probes. ESRCH => no such process (dead). EPERM (exists, another user) or any\n * other error => assume alive (conservative — never steal a slot we're unsure of).\n */\nexport function isPidAlive(pid: number): boolean {\n try {\n process.kill(pid, 0);\n return true;\n } catch (err) {\n return (err as NodeJS.ErrnoException).code !== 'ESRCH';\n }\n}\n\n/**\n * Claim one of `max` numbered slots. Returns a handle for the first free (or\n * reclaimable-stale) slot, or null when all `max` are held by live owners.\n */\nexport async function acquireEngineSlot(\n opts: AcquireEngineSlotOptions\n): Promise<SlotHandle | null> {\n const dir = opts.dir ?? DEFAULT_SLOT_DIR;\n const alive = opts.isPidAlive ?? isPidAlive;\n const pid = opts.pid ?? process.pid;\n await mkdir(dir, { recursive: true });\n for (let i = 0; i < opts.max; i++) {\n const handle = await tryClaimSlot(join(dir, `slot-${i}`), i, pid, alive);\n if (handle) return handle;\n }\n return null;\n}\n\nasync function tryClaimSlot(\n path: string,\n index: number,\n pid: number,\n alive: (pid: number) => boolean\n): Promise<SlotHandle | null> {\n // Two attempts: create; if occupied-but-dead, reclaim and retry the create.\n for (let attempt = 0; attempt < 2; attempt++) {\n try {\n const fh = await open(path, 'wx'); // O_CREAT | O_EXCL — atomic claim\n try {\n await fh.writeFile(JSON.stringify({ pid, bootedAt: Date.now() }));\n } finally {\n await fh.close();\n }\n return makeHandle(path, index);\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code !== 'EEXIST') throw err;\n if (!(await ownerIsDead(path, alive))) return null; // held by a live owner\n // Reclaim atomically: rename the stale file aside. rename() requires the\n // source to exist, so only ONE concurrent reclaimer of the same slot\n // succeeds; the losers get ENOENT and re-loop to see the new owner. An\n // unconditional unlink+recreate would instead let a second reclaimer\n // delete the first's fresh file and double-occupy the slot.\n const tomb = `${path}.dead.${pid}`;\n try {\n await rename(path, tomb);\n } catch (e) {\n if ((e as NodeJS.ErrnoException).code === 'ENOENT') continue; // lost the reclaim; retry the slot\n throw e;\n }\n await unlink(tomb).catch(() => {}); // best-effort tombstone cleanup\n // slot path is now free; loop retries the exclusive create\n }\n }\n return null; // lost the reclaim race — treat as taken, move on\n}\n\n/**\n * Is the slot file's recorded owner provably dead? Only a slot with a readable,\n * valid PID that is not alive is reclaimable. Empty/malformed/unreadable => treat\n * as ALIVE (return false) so we never steal a slot a peer just created with\n * O_EXCL but has not finished writing yet.\n */\nasync function ownerIsDead(\n path: string,\n alive: (pid: number) => boolean\n): Promise<boolean> {\n let raw: string;\n try {\n raw = await readFile(path, 'utf8');\n } catch {\n return false;\n }\n let pid: unknown;\n try {\n pid = (JSON.parse(raw) as { pid?: unknown }).pid;\n } catch {\n return false;\n }\n return typeof pid === 'number' && !alive(pid);\n}\n\nfunction makeHandle(path: string, index: number): SlotHandle {\n let released = false;\n return {\n index,\n release: async () => {\n if (released) return;\n released = true;\n await unlink(path).catch(() => {}); // ENOENT etc. — best-effort\n }\n };\n}\n\n// ── Slot-gated lazy engine ──────────────────────────────────────────────────\n\nexport interface SlotGatedEngine<E> {\n /**\n * Boot the engine on first call, gated by a machine-wide slot. Memoized: later\n * calls return the same engine. Throws EngineCapacityError at capacity (the\n * memo is NOT cached, so a later retry re-attempts). A boot FAILURE is cached\n * (a hard init error must not churn slots on retry) and its slot is released.\n */\n get(): Promise<E>;\n /** Release the held slot (for the clean-shutdown path). Idempotent. */\n release(): Promise<void>;\n}\n\nexport function createSlotGatedEngine<E>(opts: {\n max: number;\n boot: () => Promise<E>;\n dir?: string;\n acquire?: (o: { max: number; dir?: string }) => Promise<SlotHandle | null>;\n}): SlotGatedEngine<E> {\n const acquire = opts.acquire ?? acquireEngineSlot;\n let engine: Promise<E> | undefined;\n let handle: SlotHandle | undefined;\n\n const boot = async (): Promise<E> => {\n const h = await acquire({\n max: opts.max,\n ...(opts.dir !== undefined ? { dir: opts.dir } : {})\n });\n if (!h) {\n engine = undefined; // capacity is retryable — don't memoize the rejection\n throw new EngineCapacityError(opts.max);\n }\n handle = h;\n try {\n return await opts.boot();\n } catch (err) {\n // Hard init failure: free the slot (don't hold it for a dead engine). Keep\n // the rejected memo so retries don't churn slots on a permanent failure.\n await h.release().catch(() => {});\n handle = undefined;\n throw err;\n }\n };\n\n return {\n get: () => (engine ??= boot()),\n release: async () => {\n const h = handle;\n handle = undefined;\n engine = undefined;\n if (h) await h.release();\n }\n };\n}\n"]}
|
package/dist/tools/engine.d.ts
CHANGED
|
@@ -28,4 +28,17 @@ import type CreativeEngine from '@cesdk/engine';
|
|
|
28
28
|
* default to `device: 'auto'` (Metal/EGL → CPU fallback on native).
|
|
29
29
|
*/
|
|
30
30
|
export declare function ensureHeadlessEngine(license: string): Promise<CreativeEngine>;
|
|
31
|
+
/**
|
|
32
|
+
* Dispose the process-wide headless engine if one was created, and reset the
|
|
33
|
+
* cache so a subsequent `ensureHeadlessEngine` re-initializes from scratch.
|
|
34
|
+
*
|
|
35
|
+
* Idempotent and safe to call when no engine was ever initialized (a no-op that
|
|
36
|
+
* never imports `@cesdk/node`) or while an init is still in flight — it awaits
|
|
37
|
+
* the pending init first so we dispose a fully-constructed engine, never a
|
|
38
|
+
* half-built one. A rejected init produced no engine, so that case is swallowed.
|
|
39
|
+
*
|
|
40
|
+
* `CreativeEngine.dispose()` is synchronous; this wrapper is async only because
|
|
41
|
+
* it may await an in-flight `init()`.
|
|
42
|
+
*/
|
|
43
|
+
export declare function disposeHeadlessEngine(): Promise<void>;
|
|
31
44
|
//# 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;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,CAmC7E"}
|
|
1
|
+
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../src/tools/engine.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,cAAc,MAAM,eAAe,CAAC;AAIhD;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;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
|
@@ -56,4 +56,32 @@ export function ensureHeadlessEngine(license) {
|
|
|
56
56
|
}
|
|
57
57
|
return cached;
|
|
58
58
|
}
|
|
59
|
+
/**
|
|
60
|
+
* Dispose the process-wide headless engine if one was created, and reset the
|
|
61
|
+
* cache so a subsequent `ensureHeadlessEngine` re-initializes from scratch.
|
|
62
|
+
*
|
|
63
|
+
* Idempotent and safe to call when no engine was ever initialized (a no-op that
|
|
64
|
+
* never imports `@cesdk/node`) or while an init is still in flight — it awaits
|
|
65
|
+
* the pending init first so we dispose a fully-constructed engine, never a
|
|
66
|
+
* half-built one. A rejected init produced no engine, so that case is swallowed.
|
|
67
|
+
*
|
|
68
|
+
* `CreativeEngine.dispose()` is synchronous; this wrapper is async only because
|
|
69
|
+
* it may await an in-flight `init()`.
|
|
70
|
+
*/
|
|
71
|
+
export async function disposeHeadlessEngine() {
|
|
72
|
+
const pending = cached;
|
|
73
|
+
if (!pending)
|
|
74
|
+
return;
|
|
75
|
+
// Clear the cache first so no concurrent caller receives the engine we are
|
|
76
|
+
// about to dispose; a later `ensureHeadlessEngine` builds a fresh one.
|
|
77
|
+
cached = undefined;
|
|
78
|
+
let engine;
|
|
79
|
+
try {
|
|
80
|
+
engine = await pending;
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
return; // init never produced an engine — nothing to dispose
|
|
84
|
+
}
|
|
85
|
+
engine.dispose();
|
|
86
|
+
}
|
|
59
87
|
//# 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":"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;AAED;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB;IACzC,MAAM,OAAO,GAAG,MAAM,CAAC;IACvB,IAAI,CAAC,OAAO;QAAE,OAAO;IACrB,2EAA2E;IAC3E,uEAAuE;IACvE,MAAM,GAAG,SAAS,CAAC;IACnB,IAAI,MAAsB,CAAC;IAC3B,IAAI,CAAC;QACH,MAAM,GAAG,MAAM,OAAO,CAAC;IACzB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,CAAC,qDAAqD;IAC/D,CAAC;IACD,MAAM,CAAC,OAAO,EAAE,CAAC;AACnB,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\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"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@imgly/codesign-mcp",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.7",
|
|
4
4
|
"description": "Codesign MCP server: SYSTEM prompt, prompts, skills, design tools as MCP resources/prompts/tools.",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE.md",
|
|
6
6
|
"homepage": "https://github.com/imgly/imgly-codesign/tree/main/packages/codesign-mcp",
|
|
@@ -60,13 +60,13 @@
|
|
|
60
60
|
"pretest": "pnpm run refresh-assets",
|
|
61
61
|
"build": "tsc --build tsconfig.src.json && shx chmod +x dist/cli.js",
|
|
62
62
|
"prepare": "pnpm run build",
|
|
63
|
-
"pack:release": "node scripts/pack-release.mjs",
|
|
64
63
|
"publish:beta": "node scripts/publish-beta.mjs",
|
|
65
64
|
"check": "tsc --build tsconfig.src.json && tsc --build tsconfig.test.json && tsc -p tsconfig.scripts.json",
|
|
66
65
|
"test": "vitest --run",
|
|
67
66
|
"dev:claude": "bash scripts/dev-claude.sh",
|
|
68
67
|
"changelog:collate": "node --experimental-strip-types scripts/changelog-collate.ts",
|
|
69
68
|
"changelog:add": "node --experimental-strip-types scripts/changelog-add.ts",
|
|
69
|
+
"changelog:section": "node --experimental-strip-types scripts/changelog-section.ts",
|
|
70
70
|
"bump:cesdk": "node --experimental-strip-types scripts/bump-cesdk.ts"
|
|
71
71
|
},
|
|
72
72
|
"dependencies": {
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../../src/dashboard/router.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAGjC,wBAAgB,qBAAqB,IAAI,MAAM,CAQ9C"}
|
package/dist/dashboard/router.js
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
// packages/codesign-mcp/src/dashboard/router.ts
|
|
2
|
-
//
|
|
3
|
-
// Standalone performance-dashboard SPA — deliberately SEPARATE from the viewer
|
|
4
|
-
// SPA (src/viewer) and sharing no assets with it. Serves one self-contained
|
|
5
|
-
// HTML page that polls the /metrics JSON route and renders sessions, process
|
|
6
|
-
// memory, per-tool latency, and a recent-calls list. Mounted only when
|
|
7
|
-
// IMGLY_METRICS_ENABLED is on (see src/metrics/mount.ts).
|
|
8
|
-
import { Router } from 'express';
|
|
9
|
-
import { SPA_ASSETS } from './spa-assets.generated.js';
|
|
10
|
-
export function createDashboardRouter() {
|
|
11
|
-
const router = Router();
|
|
12
|
-
router.get('/', (_req, res) => {
|
|
13
|
-
res
|
|
14
|
-
.type('html')
|
|
15
|
-
.send(SPA_ASSETS['index.html'].replaceAll('{{METRICS_URL}}', '/metrics'));
|
|
16
|
-
});
|
|
17
|
-
return router;
|
|
18
|
-
}
|
|
19
|
-
//# sourceMappingURL=router.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"router.js","sourceRoot":"","sources":["../../src/dashboard/router.ts"],"names":[],"mappings":"AAAA,gDAAgD;AAChD,EAAE;AACF,+EAA+E;AAC/E,4EAA4E;AAC5E,6EAA6E;AAC7E,uEAAuE;AACvE,0DAA0D;AAC1D,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAEvD,MAAM,UAAU,qBAAqB;IACnC,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC;IACxB,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE;QAC5B,GAAG;aACA,IAAI,CAAC,MAAM,CAAC;aACZ,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC,UAAU,CAAC,iBAAiB,EAAE,UAAU,CAAC,CAAC,CAAC;IAC9E,CAAC,CAAC,CAAC;IACH,OAAO,MAAM,CAAC;AAChB,CAAC","sourcesContent":["// packages/codesign-mcp/src/dashboard/router.ts\n//\n// Standalone performance-dashboard SPA — deliberately SEPARATE from the viewer\n// SPA (src/viewer) and sharing no assets with it. Serves one self-contained\n// HTML page that polls the /metrics JSON route and renders sessions, process\n// memory, per-tool latency, and a recent-calls list. Mounted only when\n// IMGLY_METRICS_ENABLED is on (see src/metrics/mount.ts).\nimport { Router } from 'express';\nimport { SPA_ASSETS } from './spa-assets.generated.js';\n\nexport function createDashboardRouter(): Router {\n const router = Router();\n router.get('/', (_req, res) => {\n res\n .type('html')\n .send(SPA_ASSETS['index.html'].replaceAll('{{METRICS_URL}}', '/metrics'));\n });\n return router;\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"spa-assets.generated.d.ts","sourceRoot":"","sources":["../../src/dashboard/spa-assets.generated.ts"],"names":[],"mappings":"AACA,eAAO,MAAM,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAyN7C,CAAC"}
|