@fps-games/editor 0.2.1-beta.3 → 0.2.1-beta.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/build-info.json +44 -44
- package/dist/editor-commands/capabilities/assets.d.ts +8 -0
- package/dist/editor-commands/capabilities/assets.d.ts.map +1 -0
- package/dist/{agent-bridge → editor-commands}/capabilities/assets.js +41 -41
- package/dist/editor-commands/capabilities/assets.js.map +1 -0
- package/dist/editor-commands/capabilities/editor-state.d.ts +5 -0
- package/dist/editor-commands/capabilities/editor-state.d.ts.map +1 -0
- package/dist/{agent-bridge → editor-commands}/capabilities/editor-state.js +22 -22
- package/dist/editor-commands/capabilities/editor-state.js.map +1 -0
- package/dist/editor-commands/capabilities/hierarchy.d.ts +4 -0
- package/dist/editor-commands/capabilities/hierarchy.d.ts.map +1 -0
- package/dist/{agent-bridge → editor-commands}/capabilities/hierarchy.js +5 -5
- package/dist/editor-commands/capabilities/hierarchy.js.map +1 -0
- package/dist/editor-commands/capabilities/host-lifecycle.d.ts +11 -0
- package/dist/editor-commands/capabilities/host-lifecycle.d.ts.map +1 -0
- package/dist/editor-commands/capabilities/host-lifecycle.js +149 -0
- package/dist/editor-commands/capabilities/host-lifecycle.js.map +1 -0
- package/dist/editor-commands/capabilities/prefabs.d.ts +5 -0
- package/dist/editor-commands/capabilities/prefabs.d.ts.map +1 -0
- package/dist/{agent-bridge → editor-commands}/capabilities/prefabs.js +93 -93
- package/dist/editor-commands/capabilities/prefabs.js.map +1 -0
- package/dist/editor-commands/capabilities/scene-objects.d.ts +8 -0
- package/dist/editor-commands/capabilities/scene-objects.d.ts.map +1 -0
- package/dist/editor-commands/capabilities/scene-objects.js +480 -0
- package/dist/editor-commands/capabilities/scene-objects.js.map +1 -0
- package/dist/editor-commands/capabilities/selection.d.ts +5 -0
- package/dist/editor-commands/capabilities/selection.d.ts.map +1 -0
- package/dist/editor-commands/capabilities/selection.js +60 -0
- package/dist/editor-commands/capabilities/selection.js.map +1 -0
- package/dist/editor-commands/capabilities/shadows.d.ts +5 -0
- package/dist/editor-commands/capabilities/shadows.d.ts.map +1 -0
- package/dist/{agent-bridge → editor-commands}/capabilities/shadows.js +74 -74
- package/dist/editor-commands/capabilities/shadows.js.map +1 -0
- package/dist/editor-commands/capabilities/transform.d.ts +5 -0
- package/dist/editor-commands/capabilities/transform.d.ts.map +1 -0
- package/dist/editor-commands/capabilities/transform.js +164 -0
- package/dist/editor-commands/capabilities/transform.js.map +1 -0
- package/dist/editor-commands/capabilities/ui-regions.d.ts +4 -0
- package/dist/editor-commands/capabilities/ui-regions.d.ts.map +1 -0
- package/dist/{agent-bridge → editor-commands}/capabilities/ui-regions.js +55 -57
- package/dist/editor-commands/capabilities/ui-regions.js.map +1 -0
- package/dist/editor-commands/capabilities/viewport.d.ts +5 -0
- package/dist/editor-commands/capabilities/viewport.d.ts.map +1 -0
- package/dist/{agent-bridge → editor-commands}/capabilities/viewport.js +100 -100
- package/dist/editor-commands/capabilities/viewport.js.map +1 -0
- package/dist/editor-commands/command-sources.d.ts +7 -0
- package/dist/editor-commands/command-sources.d.ts.map +1 -0
- package/dist/editor-commands/command-sources.js +34 -0
- package/dist/editor-commands/command-sources.js.map +1 -0
- package/dist/editor-commands/diagnostics.d.ts +12 -0
- package/dist/editor-commands/diagnostics.d.ts.map +1 -0
- package/dist/{agent-bridge → editor-commands}/diagnostics.js +4 -4
- package/dist/editor-commands/diagnostics.js.map +1 -0
- package/dist/{agent-bridge → editor-commands}/index.d.ts +1 -1
- package/dist/editor-commands/index.d.ts.map +1 -0
- package/dist/{agent-bridge → editor-commands}/index.js +1 -1
- package/dist/editor-commands/index.js.map +1 -0
- package/dist/editor-commands/register.d.ts +4 -0
- package/dist/editor-commands/register.d.ts.map +1 -0
- package/dist/{agent-bridge → editor-commands}/register.js +323 -286
- package/dist/editor-commands/register.js.map +1 -0
- package/dist/{agent-bridge → editor-commands}/shared.d.ts +80 -80
- package/dist/editor-commands/shared.d.ts.map +1 -0
- package/dist/{agent-bridge → editor-commands}/shared.js +29 -29
- package/dist/editor-commands/shared.js.map +1 -0
- package/dist/editor-commands/source-types.d.ts +110 -0
- package/dist/editor-commands/source-types.d.ts.map +1 -0
- package/dist/editor-commands/source-types.js.map +1 -0
- package/dist/editor-plugin-commands.d.ts +4 -0
- package/dist/editor-plugin-commands.d.ts.map +1 -0
- package/dist/editor-plugin-commands.js +18 -0
- package/dist/editor-plugin-commands.js.map +1 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/local-editor-commands.d.ts +2 -0
- package/dist/local-editor-commands.d.ts.map +1 -0
- package/dist/local-editor-commands.js +2 -0
- package/dist/local-editor-commands.js.map +1 -0
- package/dist/local-editor-harness.d.ts +35 -21
- package/dist/local-editor-harness.d.ts.map +1 -1
- package/dist/local-editor-harness.js +1721 -367
- package/dist/local-editor-harness.js.map +1 -1
- package/dist/local-editor-prefab-stage-transaction.d.ts +2 -1
- package/dist/local-editor-prefab-stage-transaction.d.ts.map +1 -1
- package/dist/local-editor-prefab-stage-transaction.js +6 -5
- package/dist/local-editor-prefab-stage-transaction.js.map +1 -1
- package/dist/local-editor-scene-view-interaction-runtime.d.ts.map +1 -1
- package/dist/local-editor-scene-view-interaction-runtime.js +2 -5
- package/dist/local-editor-scene-view-interaction-runtime.js.map +1 -1
- package/dist/playable-local-editor-entry.d.ts +10 -0
- package/dist/playable-local-editor-entry.d.ts.map +1 -1
- package/dist/playable-local-editor-entry.js +10 -2
- package/dist/playable-local-editor-entry.js.map +1 -1
- package/dist/playable-local-editor-host.d.ts +3 -32
- package/dist/playable-local-editor-host.d.ts.map +1 -1
- package/dist/playable-local-editor-host.js +6 -70
- package/dist/playable-local-editor-host.js.map +1 -1
- package/dist/playable-product-local-editor.d.ts +1 -2
- package/dist/playable-product-local-editor.d.ts.map +1 -1
- package/dist/playable-product-local-editor.js +0 -1
- package/dist/playable-product-local-editor.js.map +1 -1
- package/dist/playable-product-projection-preview.d.ts.map +1 -1
- package/dist/playable-product-projection-preview.js +1 -1
- package/dist/playable-product-projection-preview.js.map +1 -1
- package/dist/playable-product-scene-capabilities.d.ts +0 -2
- package/dist/playable-product-scene-capabilities.d.ts.map +1 -1
- package/dist/playable-product-scene-capabilities.js +33 -6
- package/dist/playable-product-scene-capabilities.js.map +1 -1
- package/dist/playable-runtime-babylon.d.ts +4 -0
- package/dist/playable-runtime-babylon.d.ts.map +1 -1
- package/dist/playable-runtime-babylon.js +4 -0
- package/dist/playable-runtime-babylon.js.map +1 -1
- package/dist/playable-sdk.d.ts +1 -1
- package/dist/playable-sdk.d.ts.map +1 -1
- package/dist/playable-sdk.js.map +1 -1
- package/dist/playable-standard-project.d.ts +0 -2
- package/dist/playable-standard-project.d.ts.map +1 -1
- package/dist/playable-standard-project.js +1 -2
- package/dist/playable-standard-project.js.map +1 -1
- package/dist/project-service-projection.d.ts +16 -0
- package/dist/project-service-projection.d.ts.map +1 -0
- package/dist/project-service-projection.js +67 -0
- package/dist/project-service-projection.js.map +1 -0
- package/node_modules/@fps-games/babylon-renderer/dist/post-process/babylon-default-pipeline.d.ts +18 -0
- package/node_modules/@fps-games/babylon-renderer/dist/post-process/babylon-default-pipeline.d.ts.map +1 -1
- package/node_modules/@fps-games/babylon-renderer/dist/post-process/babylon-default-pipeline.js +54 -18
- package/node_modules/@fps-games/babylon-renderer/dist/post-process/babylon-default-pipeline.js.map +1 -1
- package/node_modules/@fps-games/babylon-renderer/package.json +9 -9
- package/node_modules/@fps-games/editor-babylon/dist/projection.d.ts +1 -0
- package/node_modules/@fps-games/editor-babylon/dist/projection.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-babylon/dist/projection.js +1 -1
- package/node_modules/@fps-games/editor-babylon/dist/projection.js.map +1 -1
- package/node_modules/@fps-games/editor-babylon/dist/selection-presentation-controller.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-babylon/dist/selection-presentation-controller.js +127 -13
- package/node_modules/@fps-games/editor-babylon/dist/selection-presentation-controller.js.map +1 -1
- package/node_modules/@fps-games/editor-babylon/dist/transform-gizmo-controller.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-babylon/dist/transform-gizmo-controller.js +66 -1
- package/node_modules/@fps-games/editor-babylon/dist/transform-gizmo-controller.js.map +1 -1
- package/node_modules/@fps-games/editor-babylon/package.json +6 -6
- package/node_modules/@fps-games/editor-browser/dist/editor-command-service-client.d.ts +32 -0
- package/node_modules/@fps-games/editor-browser/dist/editor-command-service-client.d.ts.map +1 -0
- package/node_modules/@fps-games/editor-browser/dist/editor-command-service-client.js +254 -0
- package/node_modules/@fps-games/editor-browser/dist/editor-command-service-client.js.map +1 -0
- package/node_modules/@fps-games/editor-browser/dist/index.d.ts +3 -1
- package/node_modules/@fps-games/editor-browser/dist/index.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-browser/dist/index.js +2 -0
- package/node_modules/@fps-games/editor-browser/dist/index.js.map +1 -1
- package/node_modules/@fps-games/editor-browser/dist/local-editor-command-center.d.ts +68 -0
- package/node_modules/@fps-games/editor-browser/dist/local-editor-command-center.d.ts.map +1 -0
- package/node_modules/@fps-games/editor-browser/dist/local-editor-command-center.js +650 -0
- package/node_modules/@fps-games/editor-browser/dist/local-editor-command-center.js.map +1 -0
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-formal-surface-visibility.d.ts +1 -0
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-formal-surface-visibility.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-formal-surface-visibility.js +22 -0
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-formal-surface-visibility.js.map +1 -1
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-controller.d.ts +8 -0
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-controller.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-controller.js +117 -6
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-controller.js.map +1 -1
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-view.d.ts +14 -1
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-view.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-view.js +100 -1
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-view.js.map +1 -1
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-panels.d.ts +8 -1
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-panels.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-panels.js +75 -2
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-panels.js.map +1 -1
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-types.d.ts +37 -12
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-types.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-types.js.map +1 -1
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui.d.ts +25 -2
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui.js +332 -107
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui.js.map +1 -1
- package/node_modules/@fps-games/editor-browser/package.json +7 -7
- package/node_modules/@fps-games/editor-core/dist/editor-authoring-host.d.ts +107 -0
- package/node_modules/@fps-games/editor-core/dist/editor-authoring-host.d.ts.map +1 -0
- package/node_modules/@fps-games/editor-core/dist/editor-authoring-host.js +1211 -0
- package/node_modules/@fps-games/editor-core/dist/editor-authoring-host.js.map +1 -0
- package/node_modules/@fps-games/editor-core/dist/editor-command-capability-adapter.d.ts +34 -0
- package/node_modules/@fps-games/editor-core/dist/editor-command-capability-adapter.d.ts.map +1 -0
- package/node_modules/@fps-games/editor-core/dist/editor-command-capability-adapter.js +260 -0
- package/node_modules/@fps-games/editor-core/dist/editor-command-capability-adapter.js.map +1 -0
- package/node_modules/@fps-games/editor-core/dist/editor-command-composed-authority.d.ts +9 -0
- package/node_modules/@fps-games/editor-core/dist/editor-command-composed-authority.d.ts.map +1 -0
- package/node_modules/@fps-games/editor-core/dist/editor-command-composed-authority.js +14 -0
- package/node_modules/@fps-games/editor-core/dist/editor-command-composed-authority.js.map +1 -0
- package/node_modules/@fps-games/editor-core/dist/editor-command-observability.d.ts +18 -0
- package/node_modules/@fps-games/editor-core/dist/editor-command-observability.d.ts.map +1 -0
- package/node_modules/@fps-games/editor-core/dist/editor-command-observability.js +113 -0
- package/node_modules/@fps-games/editor-core/dist/editor-command-observability.js.map +1 -0
- package/node_modules/@fps-games/editor-core/dist/editor-command-system.d.ts +82 -0
- package/node_modules/@fps-games/editor-core/dist/editor-command-system.d.ts.map +1 -0
- package/node_modules/@fps-games/editor-core/dist/editor-command-system.js +1098 -0
- package/node_modules/@fps-games/editor-core/dist/editor-command-system.js.map +1 -0
- package/node_modules/@fps-games/editor-core/dist/editor-plugin-host.d.ts +6 -7
- package/node_modules/@fps-games/editor-core/dist/editor-plugin-host.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-core/dist/editor-plugin-host.js +62 -103
- package/node_modules/@fps-games/editor-core/dist/editor-plugin-host.js.map +1 -1
- package/node_modules/@fps-games/editor-core/dist/editor-service-gateway.d.ts +30 -0
- package/node_modules/@fps-games/editor-core/dist/editor-service-gateway.d.ts.map +1 -0
- package/node_modules/@fps-games/editor-core/dist/editor-service-gateway.js +540 -0
- package/node_modules/@fps-games/editor-core/dist/editor-service-gateway.js.map +1 -0
- package/node_modules/@fps-games/editor-core/dist/editor-session-authority.d.ts +9 -0
- package/node_modules/@fps-games/editor-core/dist/editor-session-authority.d.ts.map +1 -0
- package/node_modules/@fps-games/editor-core/dist/editor-session-authority.js +61 -0
- package/node_modules/@fps-games/editor-core/dist/editor-session-authority.js.map +1 -0
- package/node_modules/@fps-games/editor-core/dist/editor-session.d.ts +55 -0
- package/node_modules/@fps-games/editor-core/dist/editor-session.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-core/dist/editor-session.js +247 -6
- package/node_modules/@fps-games/editor-core/dist/editor-session.js.map +1 -1
- package/node_modules/@fps-games/editor-core/dist/index.d.ts +6 -2
- package/node_modules/@fps-games/editor-core/dist/index.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-core/dist/index.js +6 -2
- package/node_modules/@fps-games/editor-core/dist/index.js.map +1 -1
- package/node_modules/@fps-games/editor-core/package.json +6 -6
- package/node_modules/@fps-games/editor-forge-play/dist/index.d.ts +0 -1
- package/node_modules/@fps-games/editor-forge-play/dist/index.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-forge-play/dist/index.js +0 -1
- package/node_modules/@fps-games/editor-forge-play/dist/index.js.map +1 -1
- package/node_modules/@fps-games/editor-forge-play/package.json +2 -2
- package/node_modules/@fps-games/editor-playable-sdk/dist/bridge-command/protocol.d.ts +2 -0
- package/node_modules/@fps-games/editor-playable-sdk/dist/bridge-command/protocol.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/document/helpers.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/document/helpers.js +41 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/document/helpers.js.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/local-harness/forge-play-types.d.ts +27 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/local-harness/forge-play-types.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/local-harness/forge-play-types.js.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/local-harness/forge-play.d.ts +2 -0
- package/node_modules/@fps-games/editor-playable-sdk/dist/local-harness/forge-play.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/local-harness/forge-play.js +214 -7
- package/node_modules/@fps-games/editor-playable-sdk/dist/local-harness/forge-play.js.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/local-harness/host-controller.d.ts +1 -0
- package/node_modules/@fps-games/editor-playable-sdk/dist/local-harness/host-controller.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/local-harness/host-controller.js +11 -3
- package/node_modules/@fps-games/editor-playable-sdk/dist/local-harness/host-controller.js.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/local-harness/index.d.ts +2 -4
- package/node_modules/@fps-games/editor-playable-sdk/dist/local-harness/index.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/local-harness/index.js +0 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/local-harness/index.js.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/local-harness/lifecycle.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/local-harness/lifecycle.js +77 -31
- package/node_modules/@fps-games/editor-playable-sdk/dist/local-harness/lifecycle.js.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/local-harness/types.d.ts +8 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/local-harness/types.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/local-harness/types.js.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/material-binding/asset-fields.d.ts +21 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/material-binding/asset-fields.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/material-binding/asset-fields.js +90 -4
- package/node_modules/@fps-games/editor-playable-sdk/dist/material-binding/asset-fields.js.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/material-binding/binding.d.ts +27 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/material-binding/binding.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/material-binding/binding.js +161 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/material-binding/binding.js.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/material-binding/inspector.d.ts +2 -2
- package/node_modules/@fps-games/editor-playable-sdk/dist/material-binding/inspector.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/material-binding/inspector.js +5 -92
- package/node_modules/@fps-games/editor-playable-sdk/dist/material-binding/inspector.js.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/material-binding/scene-inspector.d.ts +7 -0
- package/node_modules/@fps-games/editor-playable-sdk/dist/material-binding/scene-inspector.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/material-binding/scene-inspector.js +26 -9
- package/node_modules/@fps-games/editor-playable-sdk/dist/material-binding/scene-inspector.js.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/material-binding/slot-inspector.d.ts +9 -0
- package/node_modules/@fps-games/editor-playable-sdk/dist/material-binding/slot-inspector.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/material-binding/slot-inspector.js +19 -8
- package/node_modules/@fps-games/editor-playable-sdk/dist/material-binding/slot-inspector.js.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/prefab-stage/material-override-inspector.d.ts +5 -0
- package/node_modules/@fps-games/editor-playable-sdk/dist/prefab-stage/material-override-inspector.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/prefab-stage/material-override-inspector.js +16 -4
- package/node_modules/@fps-games/editor-playable-sdk/dist/prefab-stage/material-override-inspector.js.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/prefab-stage/stage-inspector.d.ts +9 -0
- package/node_modules/@fps-games/editor-playable-sdk/dist/prefab-stage/stage-inspector.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/prefab-stage/stage-inspector.js +12 -2
- package/node_modules/@fps-games/editor-playable-sdk/dist/prefab-stage/stage-inspector.js.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/product/ground-decal.d.ts +2 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/product/ground-decal.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/product/ground-decal.js +10 -5
- package/node_modules/@fps-games/editor-playable-sdk/dist/product/ground-decal.js.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/product/index.d.ts +1 -0
- package/node_modules/@fps-games/editor-playable-sdk/dist/product/index.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/product/index.js +1 -0
- package/node_modules/@fps-games/editor-playable-sdk/dist/product/index.js.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/product/project-host-services.d.ts +17 -82
- package/node_modules/@fps-games/editor-playable-sdk/dist/product/project-host-services.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/product/project-host-services.js +53 -57
- package/node_modules/@fps-games/editor-playable-sdk/dist/product/project-host-services.js.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/product/scene-session.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/product/scene-session.js +3 -2
- package/node_modules/@fps-games/editor-playable-sdk/dist/product/scene-session.js.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/product/standard-authoring-commands.d.ts +10 -0
- package/node_modules/@fps-games/editor-playable-sdk/dist/product/standard-authoring-commands.d.ts.map +1 -0
- package/node_modules/@fps-games/editor-playable-sdk/dist/product/standard-authoring-commands.js +256 -0
- package/node_modules/@fps-games/editor-playable-sdk/dist/product/standard-authoring-commands.js.map +1 -0
- package/node_modules/@fps-games/editor-playable-sdk/dist/product/standard-scene-assembly.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/product/standard-scene-assembly.js +7 -5
- package/node_modules/@fps-games/editor-playable-sdk/dist/product/standard-scene-assembly.js.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/scene-source/client.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/scene-source/client.js +8 -0
- package/node_modules/@fps-games/editor-playable-sdk/dist/scene-source/client.js.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/scene-source/types.d.ts +1 -0
- package/node_modules/@fps-games/editor-playable-sdk/dist/scene-source/types.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/scene-source/types.js.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/upgrade-doctor/inspectors.js +134 -12
- package/node_modules/@fps-games/editor-playable-sdk/dist/upgrade-doctor/inspectors.js.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/vite/editor-scene-workflow.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/vite/editor-scene-workflow.js +47 -0
- package/node_modules/@fps-games/editor-playable-sdk/dist/vite/editor-scene-workflow.js.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/vite/editor-service-vite.d.ts +27 -0
- package/node_modules/@fps-games/editor-playable-sdk/dist/vite/editor-service-vite.d.ts.map +1 -0
- package/node_modules/@fps-games/editor-playable-sdk/dist/vite/editor-service-vite.js +592 -0
- package/node_modules/@fps-games/editor-playable-sdk/dist/vite/editor-service-vite.js.map +1 -0
- package/node_modules/@fps-games/editor-playable-sdk/dist/vite/index.d.ts +3 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/vite/index.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/vite/index.js +2 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/vite/index.js.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/vite/plugin.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/vite/plugin.js +61 -6
- package/node_modules/@fps-games/editor-playable-sdk/dist/vite/plugin.js.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/vite/product-adapter.d.ts +0 -2
- package/node_modules/@fps-games/editor-playable-sdk/dist/vite/product-adapter.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/vite/product-adapter.js +1 -10
- package/node_modules/@fps-games/editor-playable-sdk/dist/vite/product-adapter.js.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/vite/product-authoring-api.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/vite/product-authoring-api.js +21 -0
- package/node_modules/@fps-games/editor-playable-sdk/dist/vite/product-authoring-api.js.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/vite/project-authoring-backend.d.ts +13 -0
- package/node_modules/@fps-games/editor-playable-sdk/dist/vite/project-authoring-backend.d.ts.map +1 -0
- package/node_modules/@fps-games/editor-playable-sdk/dist/vite/project-authoring-backend.js +18 -0
- package/node_modules/@fps-games/editor-playable-sdk/dist/vite/project-authoring-backend.js.map +1 -0
- package/node_modules/@fps-games/editor-playable-sdk/dist/vite/project-editor-service.d.ts +28 -0
- package/node_modules/@fps-games/editor-playable-sdk/dist/vite/project-editor-service.d.ts.map +1 -0
- package/node_modules/@fps-games/editor-playable-sdk/dist/vite/project-editor-service.js +863 -0
- package/node_modules/@fps-games/editor-playable-sdk/dist/vite/project-editor-service.js.map +1 -0
- package/node_modules/@fps-games/editor-playable-sdk/dist/vite/types.d.ts +2 -0
- package/node_modules/@fps-games/editor-playable-sdk/dist/vite/types.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/vite/types.js.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/package.json +6 -6
- package/node_modules/@fps-games/editor-protocol/dist/editor-command-capabilities.d.ts +1626 -0
- package/node_modules/@fps-games/editor-protocol/dist/editor-command-capabilities.d.ts.map +1 -0
- package/node_modules/@fps-games/editor-protocol/dist/{agent-bridge.js → editor-command-capabilities.js} +766 -620
- package/node_modules/@fps-games/editor-protocol/dist/editor-command-capabilities.js.map +1 -0
- package/node_modules/@fps-games/editor-protocol/dist/editor-command-trace.d.ts +69 -0
- package/node_modules/@fps-games/editor-protocol/dist/editor-command-trace.d.ts.map +1 -0
- package/node_modules/@fps-games/editor-protocol/dist/editor-command-trace.js +22 -0
- package/node_modules/@fps-games/editor-protocol/dist/editor-command-trace.js.map +1 -0
- package/node_modules/@fps-games/editor-protocol/dist/editor-command.d.ts +136 -0
- package/node_modules/@fps-games/editor-protocol/dist/editor-command.d.ts.map +1 -0
- package/node_modules/@fps-games/editor-protocol/dist/editor-command.js +2 -0
- package/node_modules/@fps-games/editor-protocol/dist/editor-command.js.map +1 -0
- package/node_modules/@fps-games/editor-protocol/dist/editor-service.d.ts +225 -0
- package/node_modules/@fps-games/editor-protocol/dist/editor-service.d.ts.map +1 -0
- package/node_modules/@fps-games/editor-protocol/dist/editor-service.js +4 -0
- package/node_modules/@fps-games/editor-protocol/dist/editor-service.js.map +1 -0
- package/node_modules/@fps-games/editor-protocol/dist/index.d.ts +6 -3
- package/node_modules/@fps-games/editor-protocol/dist/index.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-protocol/dist/index.js +6 -3
- package/node_modules/@fps-games/editor-protocol/dist/index.js.map +1 -1
- package/node_modules/@fps-games/editor-protocol/package.json +2 -2
- package/node_modules/@fps-games/editor-tooling/package.json +3 -3
- package/node_modules/@fps-games/editor-ui/package.json +1 -1
- package/node_modules/@fps-games/playable-assets/package.json +1 -1
- package/node_modules/@fps-games/playable-contracts/package.json +1 -1
- package/node_modules/@fps-games/playable-rendering/package.json +2 -2
- package/node_modules/@fps-games/playable-runtime/package.json +12 -12
- package/node_modules/@fps-games/playable-runtime-data/package.json +4 -4
- package/node_modules/@fps-games/playable-scene/package.json +2 -2
- package/node_modules/@fps-games/plugin-api/package.json +1 -1
- package/node_modules/@fps-games/plugin-assets/dist/version.d.ts +1 -1
- package/node_modules/@fps-games/plugin-assets/dist/version.js +1 -1
- package/node_modules/@fps-games/plugin-assets/dist/version.js.map +1 -1
- package/node_modules/@fps-games/plugin-assets/package.json +6 -6
- package/node_modules/@fps-games/plugin-hierarchy/dist/kernel.d.ts +1 -0
- package/node_modules/@fps-games/plugin-hierarchy/dist/kernel.d.ts.map +1 -1
- package/node_modules/@fps-games/plugin-hierarchy/dist/kernel.js +78 -4
- package/node_modules/@fps-games/plugin-hierarchy/dist/kernel.js.map +1 -1
- package/node_modules/@fps-games/plugin-hierarchy/dist/version.d.ts +1 -1
- package/node_modules/@fps-games/plugin-hierarchy/dist/version.js +1 -1
- package/node_modules/@fps-games/plugin-hierarchy/dist/version.js.map +1 -1
- package/node_modules/@fps-games/plugin-hierarchy/package.json +5 -5
- package/node_modules/@fps-games/plugin-host/package.json +2 -2
- package/node_modules/@fps-games/plugin-markers/dist/version.d.ts +1 -1
- package/node_modules/@fps-games/plugin-markers/dist/version.js +1 -1
- package/node_modules/@fps-games/plugin-markers/dist/version.js.map +1 -1
- package/node_modules/@fps-games/plugin-markers/package.json +5 -5
- package/node_modules/@fps-games/plugin-materials/dist/version.d.ts +1 -1
- package/node_modules/@fps-games/plugin-materials/dist/version.js +1 -1
- package/node_modules/@fps-games/plugin-materials/dist/version.js.map +1 -1
- package/node_modules/@fps-games/plugin-materials/package.json +5 -5
- package/node_modules/@fps-games/plugin-rendering/dist/version.d.ts +1 -1
- package/node_modules/@fps-games/plugin-rendering/dist/version.js +1 -1
- package/node_modules/@fps-games/plugin-rendering/dist/version.js.map +1 -1
- package/node_modules/@fps-games/plugin-rendering/package.json +5 -5
- package/node_modules/@fps-games/plugin-scene/dist/version.d.ts +1 -1
- package/node_modules/@fps-games/plugin-scene/dist/version.js +1 -1
- package/node_modules/@fps-games/plugin-scene/dist/version.js.map +1 -1
- package/node_modules/@fps-games/plugin-scene/package.json +5 -5
- package/node_modules/@fps-games/plugin-shadow-map-experiment/dist/version.d.ts +1 -1
- package/node_modules/@fps-games/plugin-shadow-map-experiment/dist/version.js +1 -1
- package/node_modules/@fps-games/plugin-shadow-map-experiment/dist/version.js.map +1 -1
- package/node_modules/@fps-games/plugin-shadow-map-experiment/package.json +5 -5
- package/node_modules/@fps-games/plugin-shadows/dist/version.d.ts +1 -1
- package/node_modules/@fps-games/plugin-shadows/dist/version.js +1 -1
- package/node_modules/@fps-games/plugin-shadows/dist/version.js.map +1 -1
- package/node_modules/@fps-games/plugin-shadows/package.json +7 -7
- package/package.json +23 -23
- package/dist/agent-bridge/capabilities/assets.d.ts +0 -8
- package/dist/agent-bridge/capabilities/assets.d.ts.map +0 -1
- package/dist/agent-bridge/capabilities/assets.js.map +0 -1
- package/dist/agent-bridge/capabilities/editor-state.d.ts +0 -5
- package/dist/agent-bridge/capabilities/editor-state.d.ts.map +0 -1
- package/dist/agent-bridge/capabilities/editor-state.js.map +0 -1
- package/dist/agent-bridge/capabilities/hierarchy.d.ts +0 -4
- package/dist/agent-bridge/capabilities/hierarchy.d.ts.map +0 -1
- package/dist/agent-bridge/capabilities/hierarchy.js.map +0 -1
- package/dist/agent-bridge/capabilities/host-lifecycle.d.ts +0 -11
- package/dist/agent-bridge/capabilities/host-lifecycle.d.ts.map +0 -1
- package/dist/agent-bridge/capabilities/host-lifecycle.js +0 -149
- package/dist/agent-bridge/capabilities/host-lifecycle.js.map +0 -1
- package/dist/agent-bridge/capabilities/prefabs.d.ts +0 -5
- package/dist/agent-bridge/capabilities/prefabs.d.ts.map +0 -1
- package/dist/agent-bridge/capabilities/prefabs.js.map +0 -1
- package/dist/agent-bridge/capabilities/scene-objects.d.ts +0 -8
- package/dist/agent-bridge/capabilities/scene-objects.d.ts.map +0 -1
- package/dist/agent-bridge/capabilities/scene-objects.js +0 -480
- package/dist/agent-bridge/capabilities/scene-objects.js.map +0 -1
- package/dist/agent-bridge/capabilities/selection.d.ts +0 -5
- package/dist/agent-bridge/capabilities/selection.d.ts.map +0 -1
- package/dist/agent-bridge/capabilities/selection.js +0 -60
- package/dist/agent-bridge/capabilities/selection.js.map +0 -1
- package/dist/agent-bridge/capabilities/shadows.d.ts +0 -5
- package/dist/agent-bridge/capabilities/shadows.d.ts.map +0 -1
- package/dist/agent-bridge/capabilities/shadows.js.map +0 -1
- package/dist/agent-bridge/capabilities/transform.d.ts +0 -5
- package/dist/agent-bridge/capabilities/transform.d.ts.map +0 -1
- package/dist/agent-bridge/capabilities/transform.js +0 -164
- package/dist/agent-bridge/capabilities/transform.js.map +0 -1
- package/dist/agent-bridge/capabilities/ui-regions.d.ts +0 -4
- package/dist/agent-bridge/capabilities/ui-regions.d.ts.map +0 -1
- package/dist/agent-bridge/capabilities/ui-regions.js.map +0 -1
- package/dist/agent-bridge/capabilities/viewport.d.ts +0 -5
- package/dist/agent-bridge/capabilities/viewport.d.ts.map +0 -1
- package/dist/agent-bridge/capabilities/viewport.js.map +0 -1
- package/dist/agent-bridge/capability-sources.d.ts +0 -7
- package/dist/agent-bridge/capability-sources.d.ts.map +0 -1
- package/dist/agent-bridge/capability-sources.js +0 -34
- package/dist/agent-bridge/capability-sources.js.map +0 -1
- package/dist/agent-bridge/diagnostics.d.ts +0 -12
- package/dist/agent-bridge/diagnostics.d.ts.map +0 -1
- package/dist/agent-bridge/diagnostics.js.map +0 -1
- package/dist/agent-bridge/index.d.ts.map +0 -1
- package/dist/agent-bridge/index.js.map +0 -1
- package/dist/agent-bridge/register.d.ts +0 -4
- package/dist/agent-bridge/register.d.ts.map +0 -1
- package/dist/agent-bridge/register.js.map +0 -1
- package/dist/agent-bridge/shared.d.ts.map +0 -1
- package/dist/agent-bridge/shared.js.map +0 -1
- package/dist/agent-bridge/source-types.d.ts +0 -110
- package/dist/agent-bridge/source-types.d.ts.map +0 -1
- package/dist/agent-bridge/source-types.js.map +0 -1
- package/dist/editor-plugin-agent-capabilities.d.ts +0 -4
- package/dist/editor-plugin-agent-capabilities.d.ts.map +0 -1
- package/dist/editor-plugin-agent-capabilities.js +0 -64
- package/dist/editor-plugin-agent-capabilities.js.map +0 -1
- package/dist/local-editor-agent-actions.d.ts +0 -43
- package/dist/local-editor-agent-actions.d.ts.map +0 -1
- package/dist/local-editor-agent-actions.js +0 -321
- package/dist/local-editor-agent-actions.js.map +0 -1
- package/dist/local-editor-agent-bridge-transport.d.ts +0 -129
- package/dist/local-editor-agent-bridge-transport.d.ts.map +0 -1
- package/dist/local-editor-agent-bridge-transport.js +0 -403
- package/dist/local-editor-agent-bridge-transport.js.map +0 -1
- package/dist/local-editor-agent-bridge.d.ts +0 -2
- package/dist/local-editor-agent-bridge.d.ts.map +0 -1
- package/dist/local-editor-agent-bridge.js +0 -2
- package/dist/local-editor-agent-bridge.js.map +0 -1
- package/dist/local-editor-agent-context.d.ts +0 -68
- package/dist/local-editor-agent-context.d.ts.map +0 -1
- package/dist/local-editor-agent-context.js +0 -716
- package/dist/local-editor-agent-context.js.map +0 -1
- package/node_modules/@fps-games/editor-core/dist/agent-bridge.d.ts +0 -22
- package/node_modules/@fps-games/editor-core/dist/agent-bridge.d.ts.map +0 -1
- package/node_modules/@fps-games/editor-core/dist/agent-bridge.js +0 -106
- package/node_modules/@fps-games/editor-core/dist/agent-bridge.js.map +0 -1
- package/node_modules/@fps-games/editor-core/dist/agent-interaction.d.ts +0 -17
- package/node_modules/@fps-games/editor-core/dist/agent-interaction.d.ts.map +0 -1
- package/node_modules/@fps-games/editor-core/dist/agent-interaction.js +0 -14
- package/node_modules/@fps-games/editor-core/dist/agent-interaction.js.map +0 -1
- package/node_modules/@fps-games/editor-forge-play/dist/agent-transport.d.ts +0 -23
- package/node_modules/@fps-games/editor-forge-play/dist/agent-transport.d.ts.map +0 -1
- package/node_modules/@fps-games/editor-forge-play/dist/agent-transport.js +0 -47
- package/node_modules/@fps-games/editor-forge-play/dist/agent-transport.js.map +0 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/local-harness/agent-descriptions.d.ts +0 -112
- package/node_modules/@fps-games/editor-playable-sdk/dist/local-harness/agent-descriptions.d.ts.map +0 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/local-harness/agent-descriptions.js +0 -159
- package/node_modules/@fps-games/editor-playable-sdk/dist/local-harness/agent-descriptions.js.map +0 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/vite/session-metadata.d.ts +0 -15
- package/node_modules/@fps-games/editor-playable-sdk/dist/vite/session-metadata.d.ts.map +0 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/vite/session-metadata.js +0 -76
- package/node_modules/@fps-games/editor-playable-sdk/dist/vite/session-metadata.js.map +0 -1
- package/node_modules/@fps-games/editor-protocol/dist/agent-bridge.d.ts +0 -1622
- package/node_modules/@fps-games/editor-protocol/dist/agent-bridge.d.ts.map +0 -1
- package/node_modules/@fps-games/editor-protocol/dist/agent-bridge.js.map +0 -1
- package/node_modules/@fps-games/editor-protocol/dist/agent-trace.d.ts +0 -68
- package/node_modules/@fps-games/editor-protocol/dist/agent-trace.d.ts.map +0 -1
- package/node_modules/@fps-games/editor-protocol/dist/agent-trace.js +0 -23
- package/node_modules/@fps-games/editor-protocol/dist/agent-trace.js.map +0 -1
- package/node_modules/@fps-games/editor-protocol/dist/agent.d.ts +0 -187
- package/node_modules/@fps-games/editor-protocol/dist/agent.d.ts.map +0 -1
- package/node_modules/@fps-games/editor-protocol/dist/agent.js +0 -5
- package/node_modules/@fps-games/editor-protocol/dist/agent.js.map +0 -1
- /package/dist/{agent-bridge → editor-commands}/source-types.js +0 -0
|
@@ -0,0 +1,1098 @@
|
|
|
1
|
+
import { EDITOR_COMMAND_SCHEMA_VERSION, } from '@fps-games/editor-protocol';
|
|
2
|
+
import { isAuthorizedCommandComposedRegistration } from './editor-command-composed-authority.js';
|
|
3
|
+
const DEFAULT_MAX_RETAINED_OPERATIONS = 200;
|
|
4
|
+
const DEFAULT_MAX_RESULT_BYTES = 128 * 1024;
|
|
5
|
+
const MAX_SCHEMA_DIAGNOSTICS = 20;
|
|
6
|
+
export function createEditorCommandSystem(options = {}) {
|
|
7
|
+
const registrations = new Map();
|
|
8
|
+
const operations = new Map();
|
|
9
|
+
const idempotency = new Map();
|
|
10
|
+
const now = options.now ?? Date.now;
|
|
11
|
+
const createOperationId = options.createOperationId ?? createDefaultOperationIdFactory();
|
|
12
|
+
const maxRetainedOperations = normalizePositiveInteger(options.maxRetainedOperations, DEFAULT_MAX_RETAINED_OPERATIONS);
|
|
13
|
+
const maxResultBytes = normalizePositiveInteger(options.maxResultBytes, DEFAULT_MAX_RESULT_BYTES);
|
|
14
|
+
let catalogRevision = 0;
|
|
15
|
+
let disposed = false;
|
|
16
|
+
let executionInterceptor;
|
|
17
|
+
let executionAuthorityScopeId = '';
|
|
18
|
+
const readTimestamp = (fallback) => {
|
|
19
|
+
try {
|
|
20
|
+
const value = now();
|
|
21
|
+
return typeof value === 'number' && Number.isFinite(value) ? value : fallback;
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
// Operation timestamps are observability metadata. A broken clock must
|
|
25
|
+
// never turn an already-committed command into a failed operation.
|
|
26
|
+
return fallback;
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
const system = {
|
|
30
|
+
get catalogRevision() { return catalogRevision; },
|
|
31
|
+
get executionAuthorityInstalled() { return executionInterceptor !== undefined; },
|
|
32
|
+
registerCommand(registration) {
|
|
33
|
+
assertActive();
|
|
34
|
+
const normalized = snapshotRegistration(registration);
|
|
35
|
+
const commandId = normalized.manifest.id;
|
|
36
|
+
if (registrations.has(commandId)) {
|
|
37
|
+
throw new Error(`Editor command is already registered: ${commandId}`);
|
|
38
|
+
}
|
|
39
|
+
registrations.set(commandId, normalized);
|
|
40
|
+
catalogRevision += 1;
|
|
41
|
+
let active = true;
|
|
42
|
+
return () => {
|
|
43
|
+
if (!active)
|
|
44
|
+
return;
|
|
45
|
+
active = false;
|
|
46
|
+
if (registrations.get(commandId) === normalized) {
|
|
47
|
+
registrations.delete(commandId);
|
|
48
|
+
for (const [scope, record] of idempotency) {
|
|
49
|
+
if (record.registration === normalized)
|
|
50
|
+
idempotency.delete(scope);
|
|
51
|
+
}
|
|
52
|
+
catalogRevision += 1;
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
},
|
|
56
|
+
installExecutionInterceptor(interceptor, interceptorOptions = {}) {
|
|
57
|
+
assertActive();
|
|
58
|
+
if (typeof interceptor !== 'function')
|
|
59
|
+
throw new Error('Editor command execution interceptor is required.');
|
|
60
|
+
if (executionInterceptor)
|
|
61
|
+
throw new Error('Editor command execution authority is already installed.');
|
|
62
|
+
executionInterceptor = interceptor;
|
|
63
|
+
executionAuthorityScopeId = interceptorOptions.scopeId?.trim() ?? '';
|
|
64
|
+
let active = true;
|
|
65
|
+
return () => {
|
|
66
|
+
if (!active)
|
|
67
|
+
return;
|
|
68
|
+
active = false;
|
|
69
|
+
if (executionInterceptor === interceptor) {
|
|
70
|
+
executionInterceptor = undefined;
|
|
71
|
+
executionAuthorityScopeId = '';
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
},
|
|
75
|
+
listManifests() {
|
|
76
|
+
assertActive();
|
|
77
|
+
return [...registrations.values()]
|
|
78
|
+
.map(registration => cloneManifest(registration.manifest));
|
|
79
|
+
},
|
|
80
|
+
async getCatalog(query = {}) {
|
|
81
|
+
assertActive();
|
|
82
|
+
const normalizedQuery = normalizeCatalogQuery(query);
|
|
83
|
+
const candidates = [...registrations.values()]
|
|
84
|
+
.filter(registration => !normalizedQuery.target || registration.manifest.target === normalizedQuery.target)
|
|
85
|
+
.filter(registration => !normalizedQuery.access || registration.manifest.access === normalizedQuery.access)
|
|
86
|
+
.map(registration => ({
|
|
87
|
+
registration,
|
|
88
|
+
score: scoreManifest(registration.manifest, normalizedQuery.text),
|
|
89
|
+
}))
|
|
90
|
+
.filter(candidate => candidate.score >= 0)
|
|
91
|
+
.sort((left, right) => right.score - left.score
|
|
92
|
+
|| left.registration.manifest.id.localeCompare(right.registration.manifest.id))
|
|
93
|
+
.slice(0, normalizedQuery.limit);
|
|
94
|
+
const commands = await Promise.all(candidates.map(async ({ registration }) => ({
|
|
95
|
+
manifest: cloneManifest(registration.manifest),
|
|
96
|
+
availability: await resolveAvailability(registration),
|
|
97
|
+
})));
|
|
98
|
+
return { catalogRevision, commands };
|
|
99
|
+
},
|
|
100
|
+
async describeCommand(commandId) {
|
|
101
|
+
assertActive();
|
|
102
|
+
const normalizedId = normalizeCommandId(commandId);
|
|
103
|
+
const registration = registrations.get(normalizedId);
|
|
104
|
+
if (!registration)
|
|
105
|
+
return null;
|
|
106
|
+
return {
|
|
107
|
+
manifest: cloneManifest(registration.manifest),
|
|
108
|
+
availability: await resolveAvailability(registration),
|
|
109
|
+
};
|
|
110
|
+
},
|
|
111
|
+
invoke(rawInvocation) {
|
|
112
|
+
assertActive();
|
|
113
|
+
const commandId = normalizeCommandId(rawInvocation?.commandId);
|
|
114
|
+
const registration = registrations.get(commandId);
|
|
115
|
+
const invocation = snapshotInvocation(rawInvocation, registration?.validateInput === false);
|
|
116
|
+
const fingerprint = stableStringify({
|
|
117
|
+
intentCommandId: invocation.intentCommandId ?? null,
|
|
118
|
+
input: invocation.input === undefined
|
|
119
|
+
? { presence: 'omitted' }
|
|
120
|
+
: { presence: 'provided', value: invocation.input },
|
|
121
|
+
expectedRevision: invocation.expectedRevision ?? null,
|
|
122
|
+
});
|
|
123
|
+
const idempotencyScope = invocation.idempotencyKey
|
|
124
|
+
? createIdempotencyScope(invocation, executionAuthorityScopeId)
|
|
125
|
+
: undefined;
|
|
126
|
+
if (idempotencyScope) {
|
|
127
|
+
const existing = idempotency.get(idempotencyScope);
|
|
128
|
+
if (existing) {
|
|
129
|
+
if (existing.fingerprint === fingerprint) {
|
|
130
|
+
return createHandle(existing, true);
|
|
131
|
+
}
|
|
132
|
+
const conflict = createOperationRecord(invocation, registration, fingerprint);
|
|
133
|
+
operations.set(conflict.snapshot.operationId, conflict);
|
|
134
|
+
conflict.completion = observeCompletion(conflict, Promise.resolve(finalizeFailure(conflict, [{
|
|
135
|
+
severity: 'error',
|
|
136
|
+
source: 'command-system',
|
|
137
|
+
code: 'command.idempotencyConflict',
|
|
138
|
+
message: `Idempotency key was reused with different input: ${invocation.idempotencyKey}`,
|
|
139
|
+
}])));
|
|
140
|
+
pruneOperations();
|
|
141
|
+
return createHandle(conflict, false);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
const record = createOperationRecord(invocation, registration, fingerprint, idempotencyScope);
|
|
145
|
+
operations.set(record.snapshot.operationId, record);
|
|
146
|
+
if (idempotencyScope)
|
|
147
|
+
idempotency.set(idempotencyScope, record);
|
|
148
|
+
record.completion = observeCompletion(record, runOperation(record));
|
|
149
|
+
return createHandle(record, false);
|
|
150
|
+
},
|
|
151
|
+
execute(invocation) {
|
|
152
|
+
return system.invoke(invocation).completion;
|
|
153
|
+
},
|
|
154
|
+
getOperation(operationId) {
|
|
155
|
+
const record = operations.get(operationId);
|
|
156
|
+
return record ? cloneOperationSnapshot(record.snapshot) : null;
|
|
157
|
+
},
|
|
158
|
+
cancelOperation(operationId) {
|
|
159
|
+
const record = operations.get(operationId);
|
|
160
|
+
if (!record || record.snapshot.status !== 'accepted')
|
|
161
|
+
return false;
|
|
162
|
+
record.controller.abort();
|
|
163
|
+
return true;
|
|
164
|
+
},
|
|
165
|
+
dispose() {
|
|
166
|
+
if (disposed)
|
|
167
|
+
return;
|
|
168
|
+
disposed = true;
|
|
169
|
+
registrations.clear();
|
|
170
|
+
executionInterceptor = undefined;
|
|
171
|
+
catalogRevision += 1;
|
|
172
|
+
for (const record of operations.values()) {
|
|
173
|
+
if (record.snapshot.status === 'accepted')
|
|
174
|
+
record.controller.abort();
|
|
175
|
+
}
|
|
176
|
+
idempotency.clear();
|
|
177
|
+
},
|
|
178
|
+
};
|
|
179
|
+
return system;
|
|
180
|
+
function assertActive() {
|
|
181
|
+
if (disposed)
|
|
182
|
+
throw new Error('Editor Command System is disposed.');
|
|
183
|
+
}
|
|
184
|
+
function createOperationRecord(invocation, registration, fingerprint, idempotencyScope) {
|
|
185
|
+
const operationId = normalizeOpaqueId(createOperationId(), 'operationId');
|
|
186
|
+
const snapshot = {
|
|
187
|
+
operationId,
|
|
188
|
+
requestId: invocation.requestId,
|
|
189
|
+
commandId: invocation.commandId,
|
|
190
|
+
...(invocation.intentCommandId ? { intentCommandId: invocation.intentCommandId } : {}),
|
|
191
|
+
status: 'accepted',
|
|
192
|
+
source: invocation.source,
|
|
193
|
+
principal: { ...invocation.principal },
|
|
194
|
+
createdAt: readTimestamp(0),
|
|
195
|
+
...(invocation.traceId ? { traceId: invocation.traceId } : {}),
|
|
196
|
+
...(invocation.traceStepId ? { traceStepId: invocation.traceStepId } : {}),
|
|
197
|
+
...(invocation.transactionId ? { transactionId: invocation.transactionId } : {}),
|
|
198
|
+
};
|
|
199
|
+
const record = {
|
|
200
|
+
controller: new AbortController(),
|
|
201
|
+
fingerprint,
|
|
202
|
+
...(idempotencyScope ? { idempotencyScope } : {}),
|
|
203
|
+
...(registration ? { registration } : {}),
|
|
204
|
+
invocation,
|
|
205
|
+
snapshot,
|
|
206
|
+
completion: Promise.resolve(undefined),
|
|
207
|
+
};
|
|
208
|
+
return record;
|
|
209
|
+
}
|
|
210
|
+
async function runOperation(record) {
|
|
211
|
+
if (record.controller.signal.aborted)
|
|
212
|
+
return finalizeCancelled(record);
|
|
213
|
+
const registration = record.registration;
|
|
214
|
+
if (!registration) {
|
|
215
|
+
return finalizeFailure(record, [{
|
|
216
|
+
severity: 'error',
|
|
217
|
+
source: 'command-system',
|
|
218
|
+
code: 'command.notFound',
|
|
219
|
+
message: `Editor command is not registered: ${record.invocation.commandId}`,
|
|
220
|
+
}]);
|
|
221
|
+
}
|
|
222
|
+
if (registration.manifest.target === 'authoring'
|
|
223
|
+
&& registration.manifest.access === 'write'
|
|
224
|
+
&& !executionInterceptor) {
|
|
225
|
+
return finalizeFailure(record, [{
|
|
226
|
+
severity: 'error',
|
|
227
|
+
source: 'command-system',
|
|
228
|
+
code: 'command.authorityUnavailable',
|
|
229
|
+
message: 'Editor authoring authority is unavailable.',
|
|
230
|
+
}]);
|
|
231
|
+
}
|
|
232
|
+
try {
|
|
233
|
+
const context = {
|
|
234
|
+
...record.invocation,
|
|
235
|
+
operationId: record.snapshot.operationId,
|
|
236
|
+
manifest: cloneManifest(registration.manifest),
|
|
237
|
+
signal: record.controller.signal,
|
|
238
|
+
...(registration.authorityTransaction
|
|
239
|
+
? { authorityTransaction: registration.authorityTransaction }
|
|
240
|
+
: {}),
|
|
241
|
+
};
|
|
242
|
+
const execute = async (authorityContext) => {
|
|
243
|
+
const availability = await resolveAvailability(registration, record.controller.signal);
|
|
244
|
+
if (record.controller.signal.aborted)
|
|
245
|
+
return cancelledOutcome(record.invocation.commandId);
|
|
246
|
+
if (!availability.available)
|
|
247
|
+
return { ok: false, diagnostics: availability.reasons };
|
|
248
|
+
const input = record.invocation.input !== undefined
|
|
249
|
+
? record.invocation.input
|
|
250
|
+
: registration.manifest.presentation?.inputMode === 'none' ? {} : null;
|
|
251
|
+
if (registration.validateInput !== false) {
|
|
252
|
+
const diagnostics = validateJsonSchema(input, registration.manifest.inputSchema, '$', 'command.inputInvalid');
|
|
253
|
+
if (diagnostics.length)
|
|
254
|
+
return { ok: false, diagnostics };
|
|
255
|
+
}
|
|
256
|
+
if (record.controller.signal.aborted)
|
|
257
|
+
return cancelledOutcome(record.invocation.commandId);
|
|
258
|
+
record.snapshot = {
|
|
259
|
+
...record.snapshot,
|
|
260
|
+
status: 'running',
|
|
261
|
+
startedAt: readTimestamp(record.snapshot.createdAt),
|
|
262
|
+
};
|
|
263
|
+
const handlerContext = authorityContext === undefined
|
|
264
|
+
? context
|
|
265
|
+
: { ...context, authorityContext };
|
|
266
|
+
const handlerPromise = Promise.resolve(registration.handler(input, handlerContext));
|
|
267
|
+
const outcome = registration.authorityTransaction === 'composed'
|
|
268
|
+
? await handlerPromise
|
|
269
|
+
: await awaitAbortable(handlerPromise, record.controller.signal);
|
|
270
|
+
if (outcome === ABORTED)
|
|
271
|
+
return cancelledOutcome(record.invocation.commandId);
|
|
272
|
+
if (!outcome.ok)
|
|
273
|
+
return { ok: false, diagnostics: normalizeDiagnostics(outcome.diagnostics) };
|
|
274
|
+
if (registration.validateOutput !== false) {
|
|
275
|
+
const diagnostics = validateJsonSchema(outcome.output, registration.manifest.outputSchema, '$', 'command.outputInvalid');
|
|
276
|
+
if (diagnostics.length)
|
|
277
|
+
return { ok: false, diagnostics };
|
|
278
|
+
}
|
|
279
|
+
const diagnostics = outcome.diagnostics?.length
|
|
280
|
+
? normalizeDiagnostics(outcome.diagnostics)
|
|
281
|
+
: undefined;
|
|
282
|
+
return {
|
|
283
|
+
ok: true,
|
|
284
|
+
output: cloneBoundedResult(outcome.output, maxResultBytes),
|
|
285
|
+
...(diagnostics ? { diagnostics } : {}),
|
|
286
|
+
};
|
|
287
|
+
};
|
|
288
|
+
const outcome = executionInterceptor
|
|
289
|
+
? await executionInterceptor(context, execute)
|
|
290
|
+
: await execute();
|
|
291
|
+
if (!outcome.ok) {
|
|
292
|
+
const diagnostics = normalizeDiagnostics(outcome.diagnostics);
|
|
293
|
+
return diagnostics.some(diagnostic => diagnostic.code === 'command.cancelled')
|
|
294
|
+
? finalizeFailure(record, diagnostics, 'cancelled')
|
|
295
|
+
: finalizeFailure(record, diagnostics);
|
|
296
|
+
}
|
|
297
|
+
record.snapshot = {
|
|
298
|
+
...record.snapshot,
|
|
299
|
+
status: 'completed',
|
|
300
|
+
completedAt: readTimestamp(record.snapshot.startedAt ?? record.snapshot.createdAt),
|
|
301
|
+
output: outcome.output,
|
|
302
|
+
...(outcome.diagnostics?.length
|
|
303
|
+
? { diagnostics: [...outcome.diagnostics] }
|
|
304
|
+
: {}),
|
|
305
|
+
};
|
|
306
|
+
pruneOperations();
|
|
307
|
+
return cloneOperationSnapshot(record.snapshot);
|
|
308
|
+
}
|
|
309
|
+
catch (error) {
|
|
310
|
+
if (record.controller.signal.aborted)
|
|
311
|
+
return finalizeCancelled(record);
|
|
312
|
+
return finalizeFailure(record, [{
|
|
313
|
+
severity: 'error',
|
|
314
|
+
source: 'command-system',
|
|
315
|
+
code: error instanceof EditorCommandResultTooLargeError
|
|
316
|
+
? 'command.resultTooLarge'
|
|
317
|
+
: 'command.exception',
|
|
318
|
+
message: error instanceof Error ? error.message : String(error),
|
|
319
|
+
}]);
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
function finalizeCancelled(record) {
|
|
323
|
+
return finalizeFailure(record, [{
|
|
324
|
+
severity: 'warning',
|
|
325
|
+
source: 'command-system',
|
|
326
|
+
code: 'command.cancelled',
|
|
327
|
+
message: `Editor command was cancelled: ${record.invocation.commandId}`,
|
|
328
|
+
}], 'cancelled');
|
|
329
|
+
}
|
|
330
|
+
function finalizeFailure(record, diagnostics, status = 'failed') {
|
|
331
|
+
record.snapshot = {
|
|
332
|
+
...record.snapshot,
|
|
333
|
+
status,
|
|
334
|
+
completedAt: readTimestamp(record.snapshot.startedAt ?? record.snapshot.createdAt),
|
|
335
|
+
diagnostics: normalizeDiagnostics(diagnostics),
|
|
336
|
+
};
|
|
337
|
+
pruneOperations();
|
|
338
|
+
return cloneOperationSnapshot(record.snapshot);
|
|
339
|
+
}
|
|
340
|
+
async function observeCompletion(record, completion) {
|
|
341
|
+
const operation = await completion;
|
|
342
|
+
try {
|
|
343
|
+
options.onOperationSettled?.({
|
|
344
|
+
invocation: snapshotInvocation(record.invocation, record.registration?.validateInput === false),
|
|
345
|
+
...(record.registration ? { manifest: cloneManifest(record.registration.manifest) } : {}),
|
|
346
|
+
operation: structuredClone(operation),
|
|
347
|
+
});
|
|
348
|
+
}
|
|
349
|
+
catch {
|
|
350
|
+
// Observability is bounded best-effort metadata and never changes command semantics.
|
|
351
|
+
}
|
|
352
|
+
return operation;
|
|
353
|
+
}
|
|
354
|
+
function pruneOperations() {
|
|
355
|
+
if (operations.size <= maxRetainedOperations)
|
|
356
|
+
return;
|
|
357
|
+
for (const [operationId, record] of operations) {
|
|
358
|
+
if (!isTerminalStatus(record.snapshot.status))
|
|
359
|
+
continue;
|
|
360
|
+
operations.delete(operationId);
|
|
361
|
+
// Operation query retention is bounded, but idempotency lives for the
|
|
362
|
+
// service instance. A late retry must not execute again merely because
|
|
363
|
+
// its operation snapshot aged out of the query window.
|
|
364
|
+
if (operations.size <= maxRetainedOperations)
|
|
365
|
+
break;
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
function snapshotRegistration(registration) {
|
|
370
|
+
if (!registration || typeof registration !== 'object') {
|
|
371
|
+
throw new Error('Editor command registration must be an object.');
|
|
372
|
+
}
|
|
373
|
+
if (typeof registration.handler !== 'function') {
|
|
374
|
+
throw new Error('Editor command handler is required.');
|
|
375
|
+
}
|
|
376
|
+
if (registration.available !== undefined && typeof registration.available !== 'function') {
|
|
377
|
+
throw new Error('Editor command availability must be a function.');
|
|
378
|
+
}
|
|
379
|
+
if (registration.authorityTransaction !== undefined
|
|
380
|
+
&& registration.authorityTransaction !== 'isolated'
|
|
381
|
+
&& registration.authorityTransaction !== 'composed') {
|
|
382
|
+
throw new Error('Editor command authority transaction mode is invalid.');
|
|
383
|
+
}
|
|
384
|
+
if (registration.authorityTransaction === 'composed'
|
|
385
|
+
&& !isAuthorizedCommandComposedRegistration(registration)) {
|
|
386
|
+
throw new Error('Composed Editor command authority is reserved for the owning Authoring Host.');
|
|
387
|
+
}
|
|
388
|
+
return {
|
|
389
|
+
manifest: snapshotEditorCommandManifest(registration.manifest),
|
|
390
|
+
...(registration.available ? { available: registration.available } : {}),
|
|
391
|
+
handler: registration.handler,
|
|
392
|
+
...(registration.validateInput === false ? { validateInput: false } : {}),
|
|
393
|
+
...(registration.validateOutput === false ? { validateOutput: false } : {}),
|
|
394
|
+
...(registration.authorityTransaction ? { authorityTransaction: registration.authorityTransaction } : {}),
|
|
395
|
+
};
|
|
396
|
+
}
|
|
397
|
+
export function snapshotEditorCommandManifest(manifest) {
|
|
398
|
+
if (!manifest || typeof manifest !== 'object')
|
|
399
|
+
throw new Error('Editor command manifest is required.');
|
|
400
|
+
if (manifest.schemaVersion !== EDITOR_COMMAND_SCHEMA_VERSION) {
|
|
401
|
+
throw new Error(`Unsupported Editor command schema version: ${String(manifest.schemaVersion)}`);
|
|
402
|
+
}
|
|
403
|
+
const id = normalizeCommandId(manifest.id);
|
|
404
|
+
if (!Number.isInteger(manifest.version) || manifest.version <= 0) {
|
|
405
|
+
throw new Error(`Editor command version must be a positive integer: ${id}`);
|
|
406
|
+
}
|
|
407
|
+
const title = normalizeRequiredText(manifest.title, `Editor command title is required: ${id}`);
|
|
408
|
+
const targets = new Set(['workspace-service', 'tooling', 'authoring', 'view', 'renderer']);
|
|
409
|
+
if (!targets.has(manifest.target))
|
|
410
|
+
throw new Error(`Editor command target is invalid: ${id}`);
|
|
411
|
+
if (manifest.access !== 'read' && manifest.access !== 'write') {
|
|
412
|
+
throw new Error(`Editor command access is invalid: ${id}`);
|
|
413
|
+
}
|
|
414
|
+
const stabilities = new Set(['experimental', 'stable', 'deprecated']);
|
|
415
|
+
if (!stabilities.has(manifest.stability))
|
|
416
|
+
throw new Error(`Editor command stability is invalid: ${id}`);
|
|
417
|
+
if (!manifest.effects || typeof manifest.effects !== 'object') {
|
|
418
|
+
throw new Error(`Editor command effects are required: ${id}`);
|
|
419
|
+
}
|
|
420
|
+
const persistence = new Set(['none', 'view', 'authoring', 'filesystem']);
|
|
421
|
+
if (!persistence.has(manifest.effects.persistence)) {
|
|
422
|
+
throw new Error(`Editor command persistence is invalid: ${id}`);
|
|
423
|
+
}
|
|
424
|
+
if (typeof manifest.effects.undoable !== 'boolean' || typeof manifest.effects.idempotent !== 'boolean') {
|
|
425
|
+
throw new Error(`Editor command effects flags are invalid: ${id}`);
|
|
426
|
+
}
|
|
427
|
+
const description = normalizeOptionalText(manifest.description);
|
|
428
|
+
const snapshot = {
|
|
429
|
+
schemaVersion: EDITOR_COMMAND_SCHEMA_VERSION,
|
|
430
|
+
id,
|
|
431
|
+
version: manifest.version,
|
|
432
|
+
title,
|
|
433
|
+
...(description ? { description } : {}),
|
|
434
|
+
target: manifest.target,
|
|
435
|
+
access: manifest.access,
|
|
436
|
+
stability: manifest.stability,
|
|
437
|
+
inputSchema: snapshotJsonSchema(manifest.inputSchema, `${id}.inputSchema`),
|
|
438
|
+
outputSchema: snapshotJsonSchema(manifest.outputSchema, `${id}.outputSchema`),
|
|
439
|
+
...(manifest.requires ? { requires: snapshotRequirements(manifest.requires, id) } : {}),
|
|
440
|
+
effects: Object.freeze({ ...manifest.effects }),
|
|
441
|
+
...(manifest.presentation ? { presentation: snapshotPresentation(manifest.presentation, id, manifest.inputSchema) } : {}),
|
|
442
|
+
};
|
|
443
|
+
return Object.freeze(snapshot);
|
|
444
|
+
}
|
|
445
|
+
function snapshotRequirements(value, commandId) {
|
|
446
|
+
for (const key of ['editorReady', 'viewAttached', 'rendererAttached']) {
|
|
447
|
+
if (value[key] !== undefined && typeof value[key] !== 'boolean') {
|
|
448
|
+
throw new Error(`Editor command requirement ${key} is invalid: ${commandId}`);
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
return Object.freeze({
|
|
452
|
+
...(value.editorReady !== undefined ? { editorReady: value.editorReady } : {}),
|
|
453
|
+
...(value.viewAttached !== undefined ? { viewAttached: value.viewAttached } : {}),
|
|
454
|
+
...(value.rendererAttached !== undefined ? { rendererAttached: value.rendererAttached } : {}),
|
|
455
|
+
...(value.activeScope ? { activeScope: Object.freeze(snapshotStringList(value.activeScope, commandId)) } : {}),
|
|
456
|
+
...(value.permissions ? { permissions: Object.freeze(snapshotStringList(value.permissions, commandId)) } : {}),
|
|
457
|
+
});
|
|
458
|
+
}
|
|
459
|
+
function snapshotPresentation(value, commandId, inputSchema) {
|
|
460
|
+
const category = normalizeOptionalText(value.category);
|
|
461
|
+
const shortcut = normalizeOptionalText(value.shortcut);
|
|
462
|
+
const inputModes = new Set(['none', 'inline-json', 'schema-form']);
|
|
463
|
+
if (value.inputMode !== undefined && !inputModes.has(value.inputMode)) {
|
|
464
|
+
throw new Error(`Editor command presentation input mode is invalid: ${commandId}`);
|
|
465
|
+
}
|
|
466
|
+
const menu = value.menu
|
|
467
|
+
? Object.freeze({
|
|
468
|
+
path: Object.freeze(snapshotStringList(value.menu.path, commandId)),
|
|
469
|
+
...(normalizeOptionalText(value.menu.group) ? { group: value.menu.group.trim() } : {}),
|
|
470
|
+
...(value.menu.order !== undefined ? { order: normalizeFiniteNumber(value.menu.order, `${commandId}.menu.order`) } : {}),
|
|
471
|
+
})
|
|
472
|
+
: undefined;
|
|
473
|
+
const selectionBinding = value.selectionBinding
|
|
474
|
+
? snapshotSelectionBinding(value.selectionBinding, commandId, inputSchema)
|
|
475
|
+
: undefined;
|
|
476
|
+
return Object.freeze({
|
|
477
|
+
...(category ? { category } : {}),
|
|
478
|
+
...(value.aliases ? { aliases: Object.freeze(snapshotStringList(value.aliases, commandId)) } : {}),
|
|
479
|
+
...(value.keywords ? { keywords: Object.freeze(snapshotStringList(value.keywords, commandId)) } : {}),
|
|
480
|
+
...(value.examples ? { examples: Object.freeze(snapshotStringList(value.examples, commandId)) } : {}),
|
|
481
|
+
...(shortcut ? { shortcut } : {}),
|
|
482
|
+
...(menu ? { menu } : {}),
|
|
483
|
+
...(value.inputMode ? { inputMode: value.inputMode } : {}),
|
|
484
|
+
...(selectionBinding ? { selectionBinding } : {}),
|
|
485
|
+
});
|
|
486
|
+
}
|
|
487
|
+
function snapshotSelectionBinding(value, commandId, inputSchema) {
|
|
488
|
+
const activeId = normalizeOptionalText(value.activeId);
|
|
489
|
+
const selectedIds = normalizeOptionalText(value.selectedIds);
|
|
490
|
+
if (!activeId && !selectedIds)
|
|
491
|
+
throw new Error(`Editor command selection binding is empty: ${commandId}`);
|
|
492
|
+
const properties = inputSchema.properties && typeof inputSchema.properties === 'object'
|
|
493
|
+
? inputSchema.properties
|
|
494
|
+
: {};
|
|
495
|
+
if (activeId && properties[activeId]?.type !== 'string') {
|
|
496
|
+
throw new Error(`Editor command active selection binding must target a string property: ${commandId}.${activeId}`);
|
|
497
|
+
}
|
|
498
|
+
if (selectedIds && (properties[selectedIds]?.type !== 'array' || properties[selectedIds]?.items?.type !== 'string')) {
|
|
499
|
+
throw new Error(`Editor command multi-selection binding must target a string array property: ${commandId}.${selectedIds}`);
|
|
500
|
+
}
|
|
501
|
+
return Object.freeze({ ...(activeId ? { activeId } : {}), ...(selectedIds ? { selectedIds } : {}) });
|
|
502
|
+
}
|
|
503
|
+
function snapshotInvocation(invocation, allowUnvalidatedInput = false) {
|
|
504
|
+
if (!invocation || typeof invocation !== 'object')
|
|
505
|
+
throw new Error('Editor command invocation is required.');
|
|
506
|
+
const commandId = normalizeCommandId(invocation.commandId);
|
|
507
|
+
const intentCommandId = invocation.intentCommandId === undefined
|
|
508
|
+
? undefined
|
|
509
|
+
: normalizeCommandId(invocation.intentCommandId);
|
|
510
|
+
const requestId = normalizeOpaqueId(invocation.requestId, 'requestId');
|
|
511
|
+
if (!invocation.principal || typeof invocation.principal !== 'object') {
|
|
512
|
+
throw new Error('Editor command principal is required.');
|
|
513
|
+
}
|
|
514
|
+
const principalType = normalizeRequiredText(invocation.principal.type, 'Editor command principal type is required.');
|
|
515
|
+
const source = normalizeRequiredText(invocation.source, 'Editor command source is required.');
|
|
516
|
+
const principalId = normalizeOptionalText(invocation.principal.id);
|
|
517
|
+
const idempotencyKey = normalizeOptionalText(invocation.idempotencyKey);
|
|
518
|
+
const traceId = normalizeOptionalText(invocation.traceId);
|
|
519
|
+
const traceStepId = normalizeOptionalText(invocation.traceStepId);
|
|
520
|
+
const transactionId = normalizeOptionalText(invocation.transactionId);
|
|
521
|
+
const clientId = normalizeOptionalText(invocation.clientId);
|
|
522
|
+
return Object.freeze({
|
|
523
|
+
commandId,
|
|
524
|
+
...(intentCommandId ? { intentCommandId } : {}),
|
|
525
|
+
...(invocation.input !== undefined ? {
|
|
526
|
+
input: (allowUnvalidatedInput
|
|
527
|
+
? cloneUnvalidatedInput(invocation.input, '$input')
|
|
528
|
+
: cloneJsonValue(invocation.input, '$input')),
|
|
529
|
+
} : {}),
|
|
530
|
+
requestId,
|
|
531
|
+
...(idempotencyKey ? { idempotencyKey } : {}),
|
|
532
|
+
principal: Object.freeze({ type: principalType, ...(principalId ? { id: principalId } : {}) }),
|
|
533
|
+
source,
|
|
534
|
+
...(invocation.expectedRevision ? {
|
|
535
|
+
expectedRevision: Object.freeze(snapshotExpectedRevision(invocation.expectedRevision)),
|
|
536
|
+
} : {}),
|
|
537
|
+
...(traceId ? { traceId } : {}),
|
|
538
|
+
...(traceStepId ? { traceStepId } : {}),
|
|
539
|
+
...(transactionId ? { transactionId } : {}),
|
|
540
|
+
...(clientId ? { clientId } : {}),
|
|
541
|
+
});
|
|
542
|
+
}
|
|
543
|
+
function snapshotExpectedRevision(value) {
|
|
544
|
+
const result = {};
|
|
545
|
+
if (value.serviceInstanceId !== undefined) {
|
|
546
|
+
const serviceInstanceId = normalizeRequiredText(value.serviceInstanceId, 'expectedRevision.serviceInstanceId');
|
|
547
|
+
result.serviceInstanceId = serviceInstanceId;
|
|
548
|
+
}
|
|
549
|
+
for (const key of ['document', 'scope', 'catalog']) {
|
|
550
|
+
const revision = value[key];
|
|
551
|
+
if (revision === undefined)
|
|
552
|
+
continue;
|
|
553
|
+
if (!Number.isSafeInteger(revision) || revision < 0) {
|
|
554
|
+
throw new Error(`Editor command expected revision is invalid: ${key}`);
|
|
555
|
+
}
|
|
556
|
+
result[key] = revision;
|
|
557
|
+
}
|
|
558
|
+
return result;
|
|
559
|
+
}
|
|
560
|
+
const ABORTED = Symbol('editor-command-aborted');
|
|
561
|
+
async function awaitAbortable(promise, signal) {
|
|
562
|
+
if (signal.aborted)
|
|
563
|
+
return ABORTED;
|
|
564
|
+
return new Promise((resolve, reject) => {
|
|
565
|
+
const onAbort = () => resolve(ABORTED);
|
|
566
|
+
signal.addEventListener('abort', onAbort, { once: true });
|
|
567
|
+
promise.then(value => {
|
|
568
|
+
signal.removeEventListener('abort', onAbort);
|
|
569
|
+
resolve(value);
|
|
570
|
+
}, error => {
|
|
571
|
+
signal.removeEventListener('abort', onAbort);
|
|
572
|
+
reject(error);
|
|
573
|
+
});
|
|
574
|
+
});
|
|
575
|
+
}
|
|
576
|
+
function cancelledOutcome(commandId) {
|
|
577
|
+
return {
|
|
578
|
+
ok: false,
|
|
579
|
+
diagnostics: [{
|
|
580
|
+
severity: 'warning',
|
|
581
|
+
source: 'command-system',
|
|
582
|
+
code: 'command.cancelled',
|
|
583
|
+
message: `Editor command was cancelled: ${commandId}`,
|
|
584
|
+
}],
|
|
585
|
+
};
|
|
586
|
+
}
|
|
587
|
+
async function resolveAvailability(registration, signal) {
|
|
588
|
+
if (!registration.available)
|
|
589
|
+
return { available: true, reasons: [] };
|
|
590
|
+
try {
|
|
591
|
+
const pending = Promise.resolve(registration.available());
|
|
592
|
+
const value = signal ? await awaitAbortable(pending, signal) : await pending;
|
|
593
|
+
if (value === ABORTED)
|
|
594
|
+
return unavailable('Editor command was cancelled.', 'command.cancelled');
|
|
595
|
+
if (value === true)
|
|
596
|
+
return { available: true, reasons: [] };
|
|
597
|
+
if (value === false)
|
|
598
|
+
return unavailable('Editor command is unavailable.');
|
|
599
|
+
if (typeof value === 'string')
|
|
600
|
+
return unavailable(value.trim() || 'Editor command is unavailable.');
|
|
601
|
+
if (!value || typeof value !== 'object' || typeof value.available !== 'boolean') {
|
|
602
|
+
return unavailable('Editor command availability returned an invalid result.', 'command.availabilityInvalid');
|
|
603
|
+
}
|
|
604
|
+
return {
|
|
605
|
+
available: value.available,
|
|
606
|
+
reasons: value.available || value.reasons?.length
|
|
607
|
+
? normalizeDiagnostics(value.reasons ?? [])
|
|
608
|
+
: unavailable('Editor command is unavailable.').reasons,
|
|
609
|
+
};
|
|
610
|
+
}
|
|
611
|
+
catch (error) {
|
|
612
|
+
return unavailable(error instanceof Error ? error.message : String(error), 'command.availabilityException');
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
function unavailable(message, code = 'command.unavailable') {
|
|
616
|
+
return {
|
|
617
|
+
available: false,
|
|
618
|
+
reasons: [{ severity: 'error', source: 'command-system', code, message }],
|
|
619
|
+
};
|
|
620
|
+
}
|
|
621
|
+
function validateJsonSchema(value, schema, path, code) {
|
|
622
|
+
const issues = [];
|
|
623
|
+
validateSchemaNode(value, schema, path, issues);
|
|
624
|
+
return issues.slice(0, MAX_SCHEMA_DIAGNOSTICS).map(message => ({
|
|
625
|
+
severity: 'error',
|
|
626
|
+
source: 'command-system',
|
|
627
|
+
code,
|
|
628
|
+
message,
|
|
629
|
+
path: message.split(':', 1)[0],
|
|
630
|
+
}));
|
|
631
|
+
}
|
|
632
|
+
function snapshotJsonSchema(value, path) {
|
|
633
|
+
const schema = cloneJsonObject(value, path);
|
|
634
|
+
assertJsonSchemaDefinition(schema, path);
|
|
635
|
+
return schema;
|
|
636
|
+
}
|
|
637
|
+
function assertJsonSchemaDefinition(rawSchema, path) {
|
|
638
|
+
if (typeof rawSchema === 'boolean')
|
|
639
|
+
return;
|
|
640
|
+
if (!isPlainObject(rawSchema))
|
|
641
|
+
throw new Error(`Editor command JSON Schema is invalid at ${path}.`);
|
|
642
|
+
const schema = rawSchema;
|
|
643
|
+
const jsonTypes = new Set(['null', 'object', 'array', 'string', 'number', 'integer', 'boolean']);
|
|
644
|
+
if ('type' in schema) {
|
|
645
|
+
const types = typeof schema.type === 'string' ? [schema.type] : schema.type;
|
|
646
|
+
if (!Array.isArray(types) || types.length === 0
|
|
647
|
+
|| types.some(type => typeof type !== 'string' || !jsonTypes.has(type))
|
|
648
|
+
|| new Set(types).size !== types.length) {
|
|
649
|
+
throw new Error(`Editor command JSON Schema type is invalid at ${path}.type.`);
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
if ('required' in schema) {
|
|
653
|
+
if (!Array.isArray(schema.required)
|
|
654
|
+
|| schema.required.some(key => typeof key !== 'string' || key.length === 0)
|
|
655
|
+
|| new Set(schema.required).size !== schema.required.length) {
|
|
656
|
+
throw new Error(`Editor command JSON Schema required is invalid at ${path}.required.`);
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
if ('properties' in schema) {
|
|
660
|
+
if (!isPlainObject(schema.properties)) {
|
|
661
|
+
throw new Error(`Editor command JSON Schema properties is invalid at ${path}.properties.`);
|
|
662
|
+
}
|
|
663
|
+
for (const [key, child] of Object.entries(schema.properties)) {
|
|
664
|
+
assertJsonSchemaDefinition(child, `${path}.properties.${key}`);
|
|
665
|
+
}
|
|
666
|
+
}
|
|
667
|
+
if ('additionalProperties' in schema
|
|
668
|
+
&& typeof schema.additionalProperties !== 'boolean'
|
|
669
|
+
&& !isPlainObject(schema.additionalProperties)) {
|
|
670
|
+
throw new Error(`Editor command JSON Schema additionalProperties is invalid at ${path}.additionalProperties.`);
|
|
671
|
+
}
|
|
672
|
+
if (isPlainObject(schema.additionalProperties)) {
|
|
673
|
+
assertJsonSchemaDefinition(schema.additionalProperties, `${path}.additionalProperties`);
|
|
674
|
+
}
|
|
675
|
+
if ('items' in schema)
|
|
676
|
+
assertJsonSchemaDefinition(schema.items, `${path}.items`);
|
|
677
|
+
for (const keyword of ['allOf', 'anyOf', 'oneOf']) {
|
|
678
|
+
if (!(keyword in schema))
|
|
679
|
+
continue;
|
|
680
|
+
const children = schema[keyword];
|
|
681
|
+
if (!Array.isArray(children) || children.length === 0) {
|
|
682
|
+
throw new Error(`Editor command JSON Schema ${keyword} is invalid at ${path}.${keyword}.`);
|
|
683
|
+
}
|
|
684
|
+
children.forEach((child, index) => assertJsonSchemaDefinition(child, `${path}.${keyword}[${index}]`));
|
|
685
|
+
}
|
|
686
|
+
if ('not' in schema)
|
|
687
|
+
assertJsonSchemaDefinition(schema.not, `${path}.not`);
|
|
688
|
+
if ('enum' in schema && (!Array.isArray(schema.enum) || schema.enum.length === 0)) {
|
|
689
|
+
throw new Error(`Editor command JSON Schema enum is invalid at ${path}.enum.`);
|
|
690
|
+
}
|
|
691
|
+
for (const keyword of ['minLength', 'maxLength', 'minItems', 'maxItems', 'minProperties', 'maxProperties']) {
|
|
692
|
+
if (keyword in schema && (!Number.isSafeInteger(schema[keyword]) || schema[keyword] < 0)) {
|
|
693
|
+
throw new Error(`Editor command JSON Schema ${keyword} is invalid at ${path}.${keyword}.`);
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
for (const keyword of ['minimum', 'maximum', 'exclusiveMinimum', 'exclusiveMaximum']) {
|
|
697
|
+
if (keyword in schema && (typeof schema[keyword] !== 'number' || !Number.isFinite(schema[keyword]))) {
|
|
698
|
+
throw new Error(`Editor command JSON Schema ${keyword} is invalid at ${path}.${keyword}.`);
|
|
699
|
+
}
|
|
700
|
+
}
|
|
701
|
+
if ('multipleOf' in schema
|
|
702
|
+
&& (typeof schema.multipleOf !== 'number' || !Number.isFinite(schema.multipleOf) || schema.multipleOf <= 0)) {
|
|
703
|
+
throw new Error(`Editor command JSON Schema multipleOf is invalid at ${path}.multipleOf.`);
|
|
704
|
+
}
|
|
705
|
+
if ('uniqueItems' in schema && typeof schema.uniqueItems !== 'boolean') {
|
|
706
|
+
throw new Error(`Editor command JSON Schema uniqueItems is invalid at ${path}.uniqueItems.`);
|
|
707
|
+
}
|
|
708
|
+
if ('pattern' in schema) {
|
|
709
|
+
if (typeof schema.pattern !== 'string') {
|
|
710
|
+
throw new Error(`Editor command JSON Schema pattern is invalid at ${path}.pattern.`);
|
|
711
|
+
}
|
|
712
|
+
try {
|
|
713
|
+
new RegExp(schema.pattern);
|
|
714
|
+
}
|
|
715
|
+
catch {
|
|
716
|
+
throw new Error(`Editor command JSON Schema pattern is invalid at ${path}.pattern.`);
|
|
717
|
+
}
|
|
718
|
+
}
|
|
719
|
+
}
|
|
720
|
+
function validateSchemaNode(value, rawSchema, path, issues) {
|
|
721
|
+
if (issues.length >= MAX_SCHEMA_DIAGNOSTICS)
|
|
722
|
+
return;
|
|
723
|
+
if (rawSchema === true || rawSchema === undefined)
|
|
724
|
+
return;
|
|
725
|
+
if (rawSchema === false) {
|
|
726
|
+
issues.push(`${path}: value is not allowed`);
|
|
727
|
+
return;
|
|
728
|
+
}
|
|
729
|
+
if (!rawSchema || typeof rawSchema !== 'object' || Array.isArray(rawSchema)) {
|
|
730
|
+
issues.push(`${path}: schema is invalid`);
|
|
731
|
+
return;
|
|
732
|
+
}
|
|
733
|
+
const schema = rawSchema;
|
|
734
|
+
if (Array.isArray(schema.allOf)) {
|
|
735
|
+
for (const child of schema.allOf)
|
|
736
|
+
validateSchemaNode(value, child, path, issues);
|
|
737
|
+
}
|
|
738
|
+
if (Array.isArray(schema.anyOf)) {
|
|
739
|
+
const matched = schema.anyOf.some(child => {
|
|
740
|
+
const childIssues = [];
|
|
741
|
+
validateSchemaNode(value, child, path, childIssues);
|
|
742
|
+
return childIssues.length === 0;
|
|
743
|
+
});
|
|
744
|
+
if (!matched)
|
|
745
|
+
issues.push(`${path}: value does not match any allowed schema`);
|
|
746
|
+
}
|
|
747
|
+
if (Array.isArray(schema.oneOf)) {
|
|
748
|
+
const matches = schema.oneOf.filter(child => {
|
|
749
|
+
const childIssues = [];
|
|
750
|
+
validateSchemaNode(value, child, path, childIssues);
|
|
751
|
+
return childIssues.length === 0;
|
|
752
|
+
}).length;
|
|
753
|
+
if (matches !== 1)
|
|
754
|
+
issues.push(`${path}: value must match exactly one allowed schema`);
|
|
755
|
+
}
|
|
756
|
+
if (schema.not !== undefined) {
|
|
757
|
+
const childIssues = [];
|
|
758
|
+
validateSchemaNode(value, schema.not, path, childIssues);
|
|
759
|
+
if (childIssues.length === 0)
|
|
760
|
+
issues.push(`${path}: value matches a disallowed schema`);
|
|
761
|
+
}
|
|
762
|
+
if (Array.isArray(schema.enum) && !schema.enum.some(entry => deepJsonEqual(entry, value))) {
|
|
763
|
+
issues.push(`${path}: value is not in the allowed enum`);
|
|
764
|
+
return;
|
|
765
|
+
}
|
|
766
|
+
if ('const' in schema && !deepJsonEqual(schema.const, value)) {
|
|
767
|
+
issues.push(`${path}: value does not match the required constant`);
|
|
768
|
+
return;
|
|
769
|
+
}
|
|
770
|
+
const allowedTypes = typeof schema.type === 'string'
|
|
771
|
+
? [schema.type]
|
|
772
|
+
: Array.isArray(schema.type)
|
|
773
|
+
? schema.type.filter(type => typeof type === 'string')
|
|
774
|
+
: [];
|
|
775
|
+
if (allowedTypes.length && !allowedTypes.some(type => matchesJsonType(value, type))) {
|
|
776
|
+
issues.push(`${path}: expected ${allowedTypes.join(' or ')}`);
|
|
777
|
+
return;
|
|
778
|
+
}
|
|
779
|
+
if (typeof value === 'string') {
|
|
780
|
+
if (typeof schema.minLength === 'number' && value.length < schema.minLength) {
|
|
781
|
+
issues.push(`${path}: string is shorter than ${schema.minLength}`);
|
|
782
|
+
}
|
|
783
|
+
if (typeof schema.maxLength === 'number' && value.length > schema.maxLength) {
|
|
784
|
+
issues.push(`${path}: string is longer than ${schema.maxLength}`);
|
|
785
|
+
}
|
|
786
|
+
if (typeof schema.pattern === 'string') {
|
|
787
|
+
try {
|
|
788
|
+
if (!new RegExp(schema.pattern).test(value))
|
|
789
|
+
issues.push(`${path}: string does not match pattern`);
|
|
790
|
+
}
|
|
791
|
+
catch {
|
|
792
|
+
issues.push(`${path}: schema pattern is invalid`);
|
|
793
|
+
}
|
|
794
|
+
}
|
|
795
|
+
}
|
|
796
|
+
if (typeof value === 'number') {
|
|
797
|
+
if (typeof schema.minimum === 'number' && value < schema.minimum)
|
|
798
|
+
issues.push(`${path}: number is below minimum`);
|
|
799
|
+
if (typeof schema.maximum === 'number' && value > schema.maximum)
|
|
800
|
+
issues.push(`${path}: number is above maximum`);
|
|
801
|
+
if (typeof schema.exclusiveMinimum === 'number' && value <= schema.exclusiveMinimum)
|
|
802
|
+
issues.push(`${path}: number is not above exclusive minimum`);
|
|
803
|
+
if (typeof schema.exclusiveMaximum === 'number' && value >= schema.exclusiveMaximum)
|
|
804
|
+
issues.push(`${path}: number is not below exclusive maximum`);
|
|
805
|
+
if (typeof schema.multipleOf === 'number' && !isJsonNumberMultipleOf(value, schema.multipleOf)) {
|
|
806
|
+
issues.push(`${path}: number is not a multiple of ${schema.multipleOf}`);
|
|
807
|
+
}
|
|
808
|
+
}
|
|
809
|
+
if (Array.isArray(value)) {
|
|
810
|
+
if (typeof schema.minItems === 'number' && value.length < schema.minItems)
|
|
811
|
+
issues.push(`${path}: array has too few items`);
|
|
812
|
+
if (typeof schema.maxItems === 'number' && value.length > schema.maxItems)
|
|
813
|
+
issues.push(`${path}: array has too many items`);
|
|
814
|
+
if (schema.uniqueItems === true && value.some((entry, index) => value.slice(0, index).some(previous => deepJsonEqual(previous, entry)))) {
|
|
815
|
+
issues.push(`${path}: array items are not unique`);
|
|
816
|
+
}
|
|
817
|
+
if (schema.items !== undefined) {
|
|
818
|
+
value.forEach((entry, index) => validateSchemaNode(entry, schema.items, `${path}[${index}]`, issues));
|
|
819
|
+
}
|
|
820
|
+
}
|
|
821
|
+
if (isPlainObject(value)) {
|
|
822
|
+
const properties = isPlainObject(schema.properties) ? schema.properties : {};
|
|
823
|
+
const required = Array.isArray(schema.required)
|
|
824
|
+
? schema.required.filter(key => typeof key === 'string')
|
|
825
|
+
: [];
|
|
826
|
+
if (typeof schema.minProperties === 'number' && Object.keys(value).length < schema.minProperties) {
|
|
827
|
+
issues.push(`${path}: object has too few properties`);
|
|
828
|
+
}
|
|
829
|
+
if (typeof schema.maxProperties === 'number' && Object.keys(value).length > schema.maxProperties) {
|
|
830
|
+
issues.push(`${path}: object has too many properties`);
|
|
831
|
+
}
|
|
832
|
+
for (const key of required) {
|
|
833
|
+
if (!hasOwn(value, key))
|
|
834
|
+
issues.push(`${path}.${key}: required property is missing`);
|
|
835
|
+
}
|
|
836
|
+
for (const [key, child] of Object.entries(value)) {
|
|
837
|
+
if (hasOwn(properties, key)) {
|
|
838
|
+
validateSchemaNode(child, properties[key], `${path}.${key}`, issues);
|
|
839
|
+
}
|
|
840
|
+
else if (schema.additionalProperties === false) {
|
|
841
|
+
issues.push(`${path}.${key}: additional property is not allowed`);
|
|
842
|
+
}
|
|
843
|
+
else if (isPlainObject(schema.additionalProperties)) {
|
|
844
|
+
validateSchemaNode(child, schema.additionalProperties, `${path}.${key}`, issues);
|
|
845
|
+
}
|
|
846
|
+
}
|
|
847
|
+
}
|
|
848
|
+
}
|
|
849
|
+
function matchesJsonType(value, type) {
|
|
850
|
+
switch (type) {
|
|
851
|
+
case 'null': return value === null;
|
|
852
|
+
case 'object': return isPlainObject(value);
|
|
853
|
+
case 'array': return Array.isArray(value);
|
|
854
|
+
case 'string': return typeof value === 'string';
|
|
855
|
+
case 'number': return typeof value === 'number' && Number.isFinite(value);
|
|
856
|
+
case 'integer': return typeof value === 'number' && Number.isSafeInteger(value);
|
|
857
|
+
case 'boolean': return typeof value === 'boolean';
|
|
858
|
+
default: return false;
|
|
859
|
+
}
|
|
860
|
+
}
|
|
861
|
+
function hasOwn(value, key) {
|
|
862
|
+
return Object.prototype.hasOwnProperty.call(value, key);
|
|
863
|
+
}
|
|
864
|
+
function isJsonNumberMultipleOf(value, multiple) {
|
|
865
|
+
const left = toDecimalInteger(value);
|
|
866
|
+
const right = toDecimalInteger(multiple);
|
|
867
|
+
const numerator = left.coefficient * (10n ** BigInt(right.scale));
|
|
868
|
+
const denominator = right.coefficient * (10n ** BigInt(left.scale));
|
|
869
|
+
return denominator !== 0n && numerator % denominator === 0n;
|
|
870
|
+
}
|
|
871
|
+
function toDecimalInteger(value) {
|
|
872
|
+
const text = value.toString().toLowerCase();
|
|
873
|
+
const [mantissa, exponentText] = text.split('e');
|
|
874
|
+
const exponent = exponentText === undefined ? 0 : Number(exponentText);
|
|
875
|
+
const negative = mantissa.startsWith('-');
|
|
876
|
+
const unsigned = negative ? mantissa.slice(1) : mantissa;
|
|
877
|
+
const [integerPart, fractionalPart = ''] = unsigned.split('.');
|
|
878
|
+
const digits = `${integerPart}${fractionalPart}`.replace(/^0+(?=\d)/, '') || '0';
|
|
879
|
+
let coefficient = BigInt(digits);
|
|
880
|
+
if (negative)
|
|
881
|
+
coefficient = -coefficient;
|
|
882
|
+
const scale = fractionalPart.length - exponent;
|
|
883
|
+
if (scale >= 0)
|
|
884
|
+
return { coefficient, scale };
|
|
885
|
+
return { coefficient: coefficient * (10n ** BigInt(-scale)), scale: 0 };
|
|
886
|
+
}
|
|
887
|
+
function normalizeDiagnostics(diagnostics) {
|
|
888
|
+
if (!Array.isArray(diagnostics))
|
|
889
|
+
return unavailable('Command diagnostics are invalid.').reasons;
|
|
890
|
+
return diagnostics.slice(0, MAX_SCHEMA_DIAGNOSTICS).map((diagnostic, index) => {
|
|
891
|
+
if (!diagnostic || typeof diagnostic !== 'object') {
|
|
892
|
+
return {
|
|
893
|
+
severity: 'error', source: 'command-system', code: 'command.diagnosticInvalid',
|
|
894
|
+
message: `Command diagnostic is invalid at index ${index}.`,
|
|
895
|
+
};
|
|
896
|
+
}
|
|
897
|
+
return {
|
|
898
|
+
severity: diagnostic.severity === 'info' || diagnostic.severity === 'warning'
|
|
899
|
+
? diagnostic.severity
|
|
900
|
+
: 'error',
|
|
901
|
+
source: normalizeOptionalText(diagnostic.source) ?? 'command',
|
|
902
|
+
code: normalizeOptionalText(diagnostic.code) ?? 'command.failed',
|
|
903
|
+
message: normalizeOptionalText(diagnostic.message) ?? 'Editor command failed.',
|
|
904
|
+
...(normalizeOptionalText(diagnostic.path) ? { path: diagnostic.path.trim() } : {}),
|
|
905
|
+
...(normalizeOptionalText(diagnostic.objectId) ? { objectId: diagnostic.objectId.trim() } : {}),
|
|
906
|
+
...(diagnostic.details ? { details: cloneJsonObject(diagnostic.details, '$diagnostic.details') } : {}),
|
|
907
|
+
};
|
|
908
|
+
});
|
|
909
|
+
}
|
|
910
|
+
function normalizeCatalogQuery(query) {
|
|
911
|
+
const text = normalizeOptionalText(query.text)?.toLocaleLowerCase();
|
|
912
|
+
const limit = query.limit === undefined ? 200 : query.limit;
|
|
913
|
+
if (!Number.isInteger(limit) || limit < 1 || limit > 1000) {
|
|
914
|
+
throw new Error('Editor command catalog limit must be an integer between 1 and 1000.');
|
|
915
|
+
}
|
|
916
|
+
return { ...query, ...(text ? { text } : {}), limit };
|
|
917
|
+
}
|
|
918
|
+
function scoreManifest(manifest, query) {
|
|
919
|
+
if (!query)
|
|
920
|
+
return 0;
|
|
921
|
+
const id = manifest.id.toLocaleLowerCase();
|
|
922
|
+
const title = manifest.title.toLocaleLowerCase();
|
|
923
|
+
const aliases = manifest.presentation?.aliases?.map(value => value.toLocaleLowerCase()) ?? [];
|
|
924
|
+
const keywords = manifest.presentation?.keywords?.map(value => value.toLocaleLowerCase()) ?? [];
|
|
925
|
+
if (id === query)
|
|
926
|
+
return 100;
|
|
927
|
+
if (aliases.includes(query))
|
|
928
|
+
return 90;
|
|
929
|
+
if (id.startsWith(query))
|
|
930
|
+
return 80;
|
|
931
|
+
if (title.startsWith(query))
|
|
932
|
+
return 70;
|
|
933
|
+
if (id.includes(query))
|
|
934
|
+
return 60;
|
|
935
|
+
if (title.includes(query))
|
|
936
|
+
return 50;
|
|
937
|
+
if (aliases.some(value => value.includes(query)))
|
|
938
|
+
return 40;
|
|
939
|
+
if (keywords.some(value => value.includes(query)))
|
|
940
|
+
return 30;
|
|
941
|
+
return manifest.description?.toLocaleLowerCase().includes(query) ? 10 : -1;
|
|
942
|
+
}
|
|
943
|
+
function createHandle(record, reused) {
|
|
944
|
+
return {
|
|
945
|
+
operationId: record.snapshot.operationId,
|
|
946
|
+
requestId: record.snapshot.requestId,
|
|
947
|
+
reused,
|
|
948
|
+
completion: record.completion,
|
|
949
|
+
};
|
|
950
|
+
}
|
|
951
|
+
function createIdempotencyScope(invocation, authorityScopeId) {
|
|
952
|
+
return stableStringify([
|
|
953
|
+
authorityScopeId,
|
|
954
|
+
invocation.principal.type,
|
|
955
|
+
invocation.principal.id ?? '',
|
|
956
|
+
invocation.source,
|
|
957
|
+
invocation.commandId,
|
|
958
|
+
invocation.idempotencyKey ?? '',
|
|
959
|
+
]);
|
|
960
|
+
}
|
|
961
|
+
function cloneManifest(manifest) {
|
|
962
|
+
return cloneJsonValue(manifest, '$manifest');
|
|
963
|
+
}
|
|
964
|
+
function cloneOperationSnapshot(snapshot) {
|
|
965
|
+
return cloneJsonValue(snapshot, '$operation');
|
|
966
|
+
}
|
|
967
|
+
function cloneBoundedResult(value, maxBytes) {
|
|
968
|
+
if (value === undefined)
|
|
969
|
+
throw new Error('Editor command result is not JSON-serializable: undefined.');
|
|
970
|
+
let json;
|
|
971
|
+
try {
|
|
972
|
+
json = JSON.stringify(value);
|
|
973
|
+
}
|
|
974
|
+
catch (error) {
|
|
975
|
+
throw new Error(`Editor command result is not serializable: ${error instanceof Error ? error.message : String(error)}`);
|
|
976
|
+
}
|
|
977
|
+
if (json === undefined)
|
|
978
|
+
throw new Error('Editor command result is not serializable.');
|
|
979
|
+
const byteLength = new TextEncoder().encode(json).byteLength;
|
|
980
|
+
if (byteLength > maxBytes) {
|
|
981
|
+
throw new EditorCommandResultTooLargeError(`Editor command result exceeds the ${maxBytes} byte limit (${byteLength} bytes).`);
|
|
982
|
+
}
|
|
983
|
+
return JSON.parse(json);
|
|
984
|
+
}
|
|
985
|
+
class EditorCommandResultTooLargeError extends Error {
|
|
986
|
+
}
|
|
987
|
+
function cloneJsonObject(value, path) {
|
|
988
|
+
const cloned = cloneJsonValue(value, path);
|
|
989
|
+
if (!isPlainObject(cloned))
|
|
990
|
+
throw new Error(`Editor command JSON object is required at ${path}.`);
|
|
991
|
+
return Object.freeze(cloned);
|
|
992
|
+
}
|
|
993
|
+
function cloneJsonValue(value, path) {
|
|
994
|
+
if (value === null || typeof value === 'string' || typeof value === 'boolean')
|
|
995
|
+
return value;
|
|
996
|
+
if (typeof value === 'number' && Number.isFinite(value))
|
|
997
|
+
return value;
|
|
998
|
+
if (Array.isArray(value))
|
|
999
|
+
return Object.freeze(value.map((entry, index) => cloneJsonValue(entry, `${path}[${index}]`)));
|
|
1000
|
+
if (!isPlainObject(value))
|
|
1001
|
+
throw new Error(`Editor command value must be JSON-compatible at ${path}.`);
|
|
1002
|
+
const result = Object.create(null);
|
|
1003
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
1004
|
+
if (entry === undefined)
|
|
1005
|
+
continue;
|
|
1006
|
+
result[key] = cloneJsonValue(entry, `${path}.${key}`);
|
|
1007
|
+
}
|
|
1008
|
+
return Object.freeze(result);
|
|
1009
|
+
}
|
|
1010
|
+
function cloneUnvalidatedInput(value, path) {
|
|
1011
|
+
if (value === null || typeof value === 'string' || typeof value === 'boolean')
|
|
1012
|
+
return value;
|
|
1013
|
+
if (typeof value === 'number')
|
|
1014
|
+
return value;
|
|
1015
|
+
if (Array.isArray(value))
|
|
1016
|
+
return Object.freeze(value.map((entry, index) => cloneUnvalidatedInput(entry, `${path}[${index}]`)));
|
|
1017
|
+
if (!isPlainObject(value))
|
|
1018
|
+
throw new Error(`Unvalidated Editor command input must contain plain values at ${path}.`);
|
|
1019
|
+
const result = Object.create(null);
|
|
1020
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
1021
|
+
if (entry === undefined)
|
|
1022
|
+
continue;
|
|
1023
|
+
result[key] = cloneUnvalidatedInput(entry, `${path}.${key}`);
|
|
1024
|
+
}
|
|
1025
|
+
return Object.freeze(result);
|
|
1026
|
+
}
|
|
1027
|
+
function isPlainObject(value) {
|
|
1028
|
+
if (!value || typeof value !== 'object' || Array.isArray(value))
|
|
1029
|
+
return false;
|
|
1030
|
+
const prototype = Object.getPrototypeOf(value);
|
|
1031
|
+
return prototype === Object.prototype || prototype === null;
|
|
1032
|
+
}
|
|
1033
|
+
function deepJsonEqual(left, right) {
|
|
1034
|
+
try {
|
|
1035
|
+
return stableStringify(left) === stableStringify(right);
|
|
1036
|
+
}
|
|
1037
|
+
catch {
|
|
1038
|
+
return false;
|
|
1039
|
+
}
|
|
1040
|
+
}
|
|
1041
|
+
function stableStringify(value) {
|
|
1042
|
+
if (value === null || typeof value === 'string' || typeof value === 'boolean')
|
|
1043
|
+
return JSON.stringify(value);
|
|
1044
|
+
if (typeof value === 'number') {
|
|
1045
|
+
if (Number.isFinite(value))
|
|
1046
|
+
return JSON.stringify(value);
|
|
1047
|
+
if (Number.isNaN(value))
|
|
1048
|
+
return '"__non_json_finite_nan__"';
|
|
1049
|
+
return value > 0 ? '"__non_json_finite_infinity__"' : '"__non_json_finite_negative_infinity__"';
|
|
1050
|
+
}
|
|
1051
|
+
if (Array.isArray(value))
|
|
1052
|
+
return `[${value.map(stableStringify).join(',')}]`;
|
|
1053
|
+
if (!isPlainObject(value))
|
|
1054
|
+
throw new Error('Editor command idempotency input must be JSON-compatible.');
|
|
1055
|
+
return `{${Object.keys(value).sort().filter(key => value[key] !== undefined).map(key => (`${JSON.stringify(key)}:${stableStringify(value[key])}`)).join(',')}}`;
|
|
1056
|
+
}
|
|
1057
|
+
function snapshotStringList(value, commandId) {
|
|
1058
|
+
if (!Array.isArray(value))
|
|
1059
|
+
throw new Error(`Editor command string list is invalid: ${commandId}`);
|
|
1060
|
+
return [...new Set(value.map(entry => normalizeRequiredText(entry, `Editor command string list contains an empty value: ${commandId}`)))];
|
|
1061
|
+
}
|
|
1062
|
+
function normalizeCommandId(value) {
|
|
1063
|
+
const id = normalizeRequiredText(value, 'Editor command id is required.');
|
|
1064
|
+
if (id.length > 160 || /\s/.test(id))
|
|
1065
|
+
throw new Error(`Editor command id is invalid: ${id}`);
|
|
1066
|
+
return id;
|
|
1067
|
+
}
|
|
1068
|
+
function normalizeOpaqueId(value, label) {
|
|
1069
|
+
const id = normalizeRequiredText(value, `Editor command ${label} is required.`);
|
|
1070
|
+
if (id.length > 256)
|
|
1071
|
+
throw new Error(`Editor command ${label} is too long.`);
|
|
1072
|
+
return id;
|
|
1073
|
+
}
|
|
1074
|
+
function normalizeRequiredText(value, message) {
|
|
1075
|
+
if (typeof value !== 'string' || !value.trim())
|
|
1076
|
+
throw new Error(message);
|
|
1077
|
+
return value.trim();
|
|
1078
|
+
}
|
|
1079
|
+
function normalizeOptionalText(value) {
|
|
1080
|
+
return typeof value === 'string' && value.trim() ? value.trim() : undefined;
|
|
1081
|
+
}
|
|
1082
|
+
function normalizeFiniteNumber(value, path) {
|
|
1083
|
+
if (typeof value !== 'number' || !Number.isFinite(value)) {
|
|
1084
|
+
throw new Error(`Editor command number is invalid: ${path}`);
|
|
1085
|
+
}
|
|
1086
|
+
return value;
|
|
1087
|
+
}
|
|
1088
|
+
function normalizePositiveInteger(value, fallback) {
|
|
1089
|
+
return Number.isInteger(value) && value > 0 ? value : fallback;
|
|
1090
|
+
}
|
|
1091
|
+
function isTerminalStatus(status) {
|
|
1092
|
+
return status === 'completed' || status === 'failed' || status === 'cancelled';
|
|
1093
|
+
}
|
|
1094
|
+
function createDefaultOperationIdFactory() {
|
|
1095
|
+
let sequence = 0;
|
|
1096
|
+
return () => `editor-command-${Date.now().toString(36)}-${(++sequence).toString(36)}`;
|
|
1097
|
+
}
|
|
1098
|
+
//# sourceMappingURL=editor-command-system.js.map
|