@vurb/core 3.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +677 -0
- package/dist/cli/args.d.ts +26 -0
- package/dist/cli/args.d.ts.map +1 -0
- package/dist/cli/args.js +117 -0
- package/dist/cli/args.js.map +1 -0
- package/dist/cli/commands/create.d.ts +11 -0
- package/dist/cli/commands/create.d.ts.map +1 -0
- package/dist/cli/commands/create.js +121 -0
- package/dist/cli/commands/create.js.map +1 -0
- package/dist/cli/commands/deploy.d.ts +3 -0
- package/dist/cli/commands/deploy.d.ts.map +1 -0
- package/dist/cli/commands/deploy.js +268 -0
- package/dist/cli/commands/deploy.js.map +1 -0
- package/dist/cli/commands/dev.d.ts +9 -0
- package/dist/cli/commands/dev.d.ts.map +1 -0
- package/dist/cli/commands/dev.js +58 -0
- package/dist/cli/commands/dev.js.map +1 -0
- package/dist/cli/commands/lock.d.ts +5 -0
- package/dist/cli/commands/lock.d.ts.map +1 -0
- package/dist/cli/commands/lock.js +94 -0
- package/dist/cli/commands/lock.js.map +1 -0
- package/dist/cli/commands/remote.d.ts +3 -0
- package/dist/cli/commands/remote.d.ts.map +1 -0
- package/dist/cli/commands/remote.js +37 -0
- package/dist/cli/commands/remote.js.map +1 -0
- package/dist/cli/constants.d.ts +18 -0
- package/dist/cli/constants.d.ts.map +1 -0
- package/dist/cli/constants.js +95 -0
- package/dist/cli/constants.js.map +1 -0
- package/dist/cli/progress.d.ts +34 -0
- package/dist/cli/progress.d.ts.map +1 -0
- package/dist/cli/progress.js +102 -0
- package/dist/cli/progress.js.map +1 -0
- package/dist/cli/rc.d.ts +11 -0
- package/dist/cli/rc.d.ts.map +1 -0
- package/dist/cli/rc.js +75 -0
- package/dist/cli/rc.js.map +1 -0
- package/dist/cli/registry.d.ts +25 -0
- package/dist/cli/registry.d.ts.map +1 -0
- package/dist/cli/registry.js +86 -0
- package/dist/cli/registry.js.map +1 -0
- package/dist/cli/scaffold.d.ts +10 -0
- package/dist/cli/scaffold.d.ts.map +1 -0
- package/dist/cli/scaffold.js +105 -0
- package/dist/cli/scaffold.js.map +1 -0
- package/dist/cli/templates/config.d.ts +14 -0
- package/dist/cli/templates/config.d.ts.map +1 -0
- package/dist/cli/templates/config.js +133 -0
- package/dist/cli/templates/config.js.map +1 -0
- package/dist/cli/templates/constants.d.ts +9 -0
- package/dist/cli/templates/constants.d.ts.map +1 -0
- package/dist/cli/templates/constants.js +9 -0
- package/dist/cli/templates/constants.js.map +1 -0
- package/dist/cli/templates/core.d.ts +14 -0
- package/dist/cli/templates/core.d.ts.map +1 -0
- package/dist/cli/templates/core.js +186 -0
- package/dist/cli/templates/core.js.map +1 -0
- package/dist/cli/templates/cursor.d.ts +8 -0
- package/dist/cli/templates/cursor.d.ts.map +1 -0
- package/dist/cli/templates/cursor.js +13 -0
- package/dist/cli/templates/cursor.js.map +1 -0
- package/dist/cli/templates/index.d.ts +17 -0
- package/dist/cli/templates/index.d.ts.map +1 -0
- package/dist/cli/templates/index.js +27 -0
- package/dist/cli/templates/index.js.map +1 -0
- package/dist/cli/templates/middleware.d.ts +7 -0
- package/dist/cli/templates/middleware.d.ts.map +1 -0
- package/dist/cli/templates/middleware.js +34 -0
- package/dist/cli/templates/middleware.js.map +1 -0
- package/dist/cli/templates/presenter.d.ts +7 -0
- package/dist/cli/templates/presenter.d.ts.map +1 -0
- package/dist/cli/templates/presenter.js +46 -0
- package/dist/cli/templates/presenter.js.map +1 -0
- package/dist/cli/templates/prompt.d.ts +7 -0
- package/dist/cli/templates/prompt.d.ts.map +1 -0
- package/dist/cli/templates/prompt.js +42 -0
- package/dist/cli/templates/prompt.js.map +1 -0
- package/dist/cli/templates/readme.d.ts +8 -0
- package/dist/cli/templates/readme.d.ts.map +1 -0
- package/dist/cli/templates/readme.js +173 -0
- package/dist/cli/templates/readme.js.map +1 -0
- package/dist/cli/templates/testing.d.ts +11 -0
- package/dist/cli/templates/testing.d.ts.map +1 -0
- package/dist/cli/templates/testing.js +101 -0
- package/dist/cli/templates/testing.js.map +1 -0
- package/dist/cli/templates/tools.d.ts +13 -0
- package/dist/cli/templates/tools.d.ts.map +1 -0
- package/dist/cli/templates/tools.js +63 -0
- package/dist/cli/templates/tools.js.map +1 -0
- package/dist/cli/templates/vectors/database.d.ts +9 -0
- package/dist/cli/templates/vectors/database.d.ts.map +1 -0
- package/dist/cli/templates/vectors/database.js +82 -0
- package/dist/cli/templates/vectors/database.js.map +1 -0
- package/dist/cli/templates/vectors/index.d.ts +9 -0
- package/dist/cli/templates/vectors/index.d.ts.map +1 -0
- package/dist/cli/templates/vectors/index.js +9 -0
- package/dist/cli/templates/vectors/index.js.map +1 -0
- package/dist/cli/templates/vectors/oauth.d.ts +10 -0
- package/dist/cli/templates/vectors/oauth.d.ts.map +1 -0
- package/dist/cli/templates/vectors/oauth.js +76 -0
- package/dist/cli/templates/vectors/oauth.js.map +1 -0
- package/dist/cli/templates/vectors/openapi.d.ts +10 -0
- package/dist/cli/templates/vectors/openapi.d.ts.map +1 -0
- package/dist/cli/templates/vectors/openapi.js +106 -0
- package/dist/cli/templates/vectors/openapi.js.map +1 -0
- package/dist/cli/templates/vectors/workflow.d.ts +7 -0
- package/dist/cli/templates/vectors/workflow.d.ts.map +1 -0
- package/dist/cli/templates/vectors/workflow.js +49 -0
- package/dist/cli/templates/vectors/workflow.js.map +1 -0
- package/dist/cli/types.d.ts +36 -0
- package/dist/cli/types.d.ts.map +1 -0
- package/dist/cli/types.js +10 -0
- package/dist/cli/types.js.map +1 -0
- package/dist/cli/utils.d.ts +27 -0
- package/dist/cli/utils.d.ts.map +1 -0
- package/dist/cli/utils.js +73 -0
- package/dist/cli/utils.js.map +1 -0
- package/dist/cli/vurb.d.ts +15 -0
- package/dist/cli/vurb.d.ts.map +1 -0
- package/dist/cli/vurb.js +87 -0
- package/dist/cli/vurb.js.map +1 -0
- package/dist/client/InferRouter.d.ts +92 -0
- package/dist/client/InferRouter.d.ts.map +1 -0
- package/dist/client/InferRouter.js +31 -0
- package/dist/client/InferRouter.js.map +1 -0
- package/dist/client/VurbClient.d.ts +282 -0
- package/dist/client/VurbClient.d.ts.map +1 -0
- package/dist/client/VurbClient.js +287 -0
- package/dist/client/VurbClient.js.map +1 -0
- package/dist/client/createTypedRegistry.d.ts +25 -0
- package/dist/client/createTypedRegistry.d.ts.map +1 -0
- package/dist/client/createTypedRegistry.js +74 -0
- package/dist/client/createTypedRegistry.js.map +1 -0
- package/dist/client/index.d.ts +6 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/index.js +4 -0
- package/dist/client/index.js.map +1 -0
- package/dist/converters/ConverterBase.d.ts +68 -0
- package/dist/converters/ConverterBase.d.ts.map +1 -0
- package/dist/converters/ConverterBase.js +62 -0
- package/dist/converters/ConverterBase.js.map +1 -0
- package/dist/converters/GroupConverter.d.ts +33 -0
- package/dist/converters/GroupConverter.d.ts.map +1 -0
- package/dist/converters/GroupConverter.js +26 -0
- package/dist/converters/GroupConverter.js.map +1 -0
- package/dist/converters/PromptConverter.d.ts +33 -0
- package/dist/converters/PromptConverter.d.ts.map +1 -0
- package/dist/converters/PromptConverter.js +26 -0
- package/dist/converters/PromptConverter.js.map +1 -0
- package/dist/converters/ResourceConverter.d.ts +35 -0
- package/dist/converters/ResourceConverter.d.ts.map +1 -0
- package/dist/converters/ResourceConverter.js +28 -0
- package/dist/converters/ResourceConverter.js.map +1 -0
- package/dist/converters/ToolAnnotationsConverter.d.ts +33 -0
- package/dist/converters/ToolAnnotationsConverter.d.ts.map +1 -0
- package/dist/converters/ToolAnnotationsConverter.js +26 -0
- package/dist/converters/ToolAnnotationsConverter.js.map +1 -0
- package/dist/converters/ToolConverter.d.ts +35 -0
- package/dist/converters/ToolConverter.d.ts.map +1 -0
- package/dist/converters/ToolConverter.js +28 -0
- package/dist/converters/ToolConverter.js.map +1 -0
- package/dist/converters/index.d.ts +7 -0
- package/dist/converters/index.d.ts.map +1 -0
- package/dist/converters/index.js +7 -0
- package/dist/converters/index.js.map +1 -0
- package/dist/core/StandardSchema.d.ts +178 -0
- package/dist/core/StandardSchema.d.ts.map +1 -0
- package/dist/core/StandardSchema.js +174 -0
- package/dist/core/StandardSchema.js.map +1 -0
- package/dist/core/builder/ActionGroupBuilder.d.ts +208 -0
- package/dist/core/builder/ActionGroupBuilder.d.ts.map +1 -0
- package/dist/core/builder/ActionGroupBuilder.js +193 -0
- package/dist/core/builder/ActionGroupBuilder.js.map +1 -0
- package/dist/core/builder/ErrorBuilder.d.ts +59 -0
- package/dist/core/builder/ErrorBuilder.d.ts.map +1 -0
- package/dist/core/builder/ErrorBuilder.js +99 -0
- package/dist/core/builder/ErrorBuilder.js.map +1 -0
- package/dist/core/builder/FluentRouter.d.ts +96 -0
- package/dist/core/builder/FluentRouter.d.ts.map +1 -0
- package/dist/core/builder/FluentRouter.js +116 -0
- package/dist/core/builder/FluentRouter.js.map +1 -0
- package/dist/core/builder/FluentSchemaHelpers.d.ts +237 -0
- package/dist/core/builder/FluentSchemaHelpers.d.ts.map +1 -0
- package/dist/core/builder/FluentSchemaHelpers.js +227 -0
- package/dist/core/builder/FluentSchemaHelpers.js.map +1 -0
- package/dist/core/builder/FluentToolBuilder.d.ts +419 -0
- package/dist/core/builder/FluentToolBuilder.d.ts.map +1 -0
- package/dist/core/builder/FluentToolBuilder.js +643 -0
- package/dist/core/builder/FluentToolBuilder.js.map +1 -0
- package/dist/core/builder/GroupedToolBuilder.d.ts +832 -0
- package/dist/core/builder/GroupedToolBuilder.d.ts.map +1 -0
- package/dist/core/builder/GroupedToolBuilder.js +1306 -0
- package/dist/core/builder/GroupedToolBuilder.js.map +1 -0
- package/dist/core/builder/ParamDescriptors.d.ts +142 -0
- package/dist/core/builder/ParamDescriptors.d.ts.map +1 -0
- package/dist/core/builder/ParamDescriptors.js +164 -0
- package/dist/core/builder/ParamDescriptors.js.map +1 -0
- package/dist/core/builder/ToolDefinitionCompiler.d.ts +37 -0
- package/dist/core/builder/ToolDefinitionCompiler.d.ts.map +1 -0
- package/dist/core/builder/ToolDefinitionCompiler.js +72 -0
- package/dist/core/builder/ToolDefinitionCompiler.js.map +1 -0
- package/dist/core/builder/defineTool.d.ts +180 -0
- package/dist/core/builder/defineTool.d.ts.map +1 -0
- package/dist/core/builder/defineTool.js +164 -0
- package/dist/core/builder/defineTool.js.map +1 -0
- package/dist/core/builder/index.d.ts +13 -0
- package/dist/core/builder/index.d.ts.map +1 -0
- package/dist/core/builder/index.js +13 -0
- package/dist/core/builder/index.js.map +1 -0
- package/dist/core/createGroup.d.ts +140 -0
- package/dist/core/createGroup.d.ts.map +1 -0
- package/dist/core/createGroup.js +144 -0
- package/dist/core/createGroup.js.map +1 -0
- package/dist/core/execution/ConcurrencyGuard.d.ts +103 -0
- package/dist/core/execution/ConcurrencyGuard.d.ts.map +1 -0
- package/dist/core/execution/ConcurrencyGuard.js +147 -0
- package/dist/core/execution/ConcurrencyGuard.js.map +1 -0
- package/dist/core/execution/EgressGuard.d.ts +72 -0
- package/dist/core/execution/EgressGuard.d.ts.map +1 -0
- package/dist/core/execution/EgressGuard.js +163 -0
- package/dist/core/execution/EgressGuard.js.map +1 -0
- package/dist/core/execution/ExecutionPipeline.d.ts +67 -0
- package/dist/core/execution/ExecutionPipeline.d.ts.map +1 -0
- package/dist/core/execution/ExecutionPipeline.js +176 -0
- package/dist/core/execution/ExecutionPipeline.js.map +1 -0
- package/dist/core/execution/MiddlewareCompiler.d.ts +35 -0
- package/dist/core/execution/MiddlewareCompiler.d.ts.map +1 -0
- package/dist/core/execution/MiddlewareCompiler.js +111 -0
- package/dist/core/execution/MiddlewareCompiler.js.map +1 -0
- package/dist/core/execution/MutationSerializer.d.ts +78 -0
- package/dist/core/execution/MutationSerializer.d.ts.map +1 -0
- package/dist/core/execution/MutationSerializer.js +106 -0
- package/dist/core/execution/MutationSerializer.js.map +1 -0
- package/dist/core/execution/PipelineHooks.d.ts +46 -0
- package/dist/core/execution/PipelineHooks.d.ts.map +1 -0
- package/dist/core/execution/PipelineHooks.js +66 -0
- package/dist/core/execution/PipelineHooks.js.map +1 -0
- package/dist/core/execution/ProgressHelper.d.ts +67 -0
- package/dist/core/execution/ProgressHelper.d.ts.map +1 -0
- package/dist/core/execution/ProgressHelper.js +59 -0
- package/dist/core/execution/ProgressHelper.js.map +1 -0
- package/dist/core/execution/ValidationErrorFormatter.d.ts +34 -0
- package/dist/core/execution/ValidationErrorFormatter.d.ts.map +1 -0
- package/dist/core/execution/ValidationErrorFormatter.js +193 -0
- package/dist/core/execution/ValidationErrorFormatter.js.map +1 -0
- package/dist/core/execution/index.d.ts +9 -0
- package/dist/core/execution/index.d.ts.map +1 -0
- package/dist/core/execution/index.js +9 -0
- package/dist/core/execution/index.js.map +1 -0
- package/dist/core/index.d.ts +34 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +29 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/initVurb.d.ts +295 -0
- package/dist/core/initVurb.d.ts.map +1 -0
- package/dist/core/initVurb.js +171 -0
- package/dist/core/initVurb.js.map +1 -0
- package/dist/core/middleware/ContextDerivation.d.ts +124 -0
- package/dist/core/middleware/ContextDerivation.d.ts.map +1 -0
- package/dist/core/middleware/ContextDerivation.js +117 -0
- package/dist/core/middleware/ContextDerivation.js.map +1 -0
- package/dist/core/middleware/index.d.ts +4 -0
- package/dist/core/middleware/index.d.ts.map +1 -0
- package/dist/core/middleware/index.js +3 -0
- package/dist/core/middleware/index.js.map +1 -0
- package/dist/core/registry/ToolFilterEngine.d.ts +27 -0
- package/dist/core/registry/ToolFilterEngine.d.ts.map +1 -0
- package/dist/core/registry/ToolFilterEngine.js +45 -0
- package/dist/core/registry/ToolFilterEngine.js.map +1 -0
- package/dist/core/registry/ToolRegistry.d.ts +259 -0
- package/dist/core/registry/ToolRegistry.d.ts.map +1 -0
- package/dist/core/registry/ToolRegistry.js +343 -0
- package/dist/core/registry/ToolRegistry.js.map +1 -0
- package/dist/core/registry/index.d.ts +4 -0
- package/dist/core/registry/index.d.ts.map +1 -0
- package/dist/core/registry/index.js +3 -0
- package/dist/core/registry/index.js.map +1 -0
- package/dist/core/response.d.ts +289 -0
- package/dist/core/response.d.ts.map +1 -0
- package/dist/core/response.js +286 -0
- package/dist/core/response.js.map +1 -0
- package/dist/core/result.d.ts +93 -0
- package/dist/core/result.d.ts.map +1 -0
- package/dist/core/result.js +66 -0
- package/dist/core/result.js.map +1 -0
- package/dist/core/schema/AnnotationAggregator.d.ts +11 -0
- package/dist/core/schema/AnnotationAggregator.d.ts.map +1 -0
- package/dist/core/schema/AnnotationAggregator.js +40 -0
- package/dist/core/schema/AnnotationAggregator.js.map +1 -0
- package/dist/core/schema/DescriptionGenerator.d.ts +12 -0
- package/dist/core/schema/DescriptionGenerator.d.ts.map +1 -0
- package/dist/core/schema/DescriptionGenerator.js +81 -0
- package/dist/core/schema/DescriptionGenerator.js.map +1 -0
- package/dist/core/schema/SchemaGenerator.d.ts +15 -0
- package/dist/core/schema/SchemaGenerator.d.ts.map +1 -0
- package/dist/core/schema/SchemaGenerator.js +192 -0
- package/dist/core/schema/SchemaGenerator.js.map +1 -0
- package/dist/core/schema/SchemaUtils.d.ts +26 -0
- package/dist/core/schema/SchemaUtils.d.ts.map +1 -0
- package/dist/core/schema/SchemaUtils.js +85 -0
- package/dist/core/schema/SchemaUtils.js.map +1 -0
- package/dist/core/schema/ToonDescriptionGenerator.d.ts +3 -0
- package/dist/core/schema/ToonDescriptionGenerator.d.ts.map +1 -0
- package/dist/core/schema/ToonDescriptionGenerator.js +65 -0
- package/dist/core/schema/ToonDescriptionGenerator.js.map +1 -0
- package/dist/core/schema/index.d.ts +7 -0
- package/dist/core/schema/index.d.ts.map +1 -0
- package/dist/core/schema/index.js +7 -0
- package/dist/core/schema/index.js.map +1 -0
- package/dist/core/serialization/JsonSerializer.d.ts +71 -0
- package/dist/core/serialization/JsonSerializer.d.ts.map +1 -0
- package/dist/core/serialization/JsonSerializer.js +192 -0
- package/dist/core/serialization/JsonSerializer.js.map +1 -0
- package/dist/core/serialization/index.d.ts +7 -0
- package/dist/core/serialization/index.d.ts.map +1 -0
- package/dist/core/serialization/index.js +7 -0
- package/dist/core/serialization/index.js.map +1 -0
- package/dist/core/types.d.ts +303 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +17 -0
- package/dist/core/types.js.map +1 -0
- package/dist/domain/Annotations.d.ts +42 -0
- package/dist/domain/Annotations.d.ts.map +1 -0
- package/dist/domain/Annotations.js +16 -0
- package/dist/domain/Annotations.js.map +1 -0
- package/dist/domain/BaseModel.d.ts +50 -0
- package/dist/domain/BaseModel.d.ts.map +1 -0
- package/dist/domain/BaseModel.js +41 -0
- package/dist/domain/BaseModel.js.map +1 -0
- package/dist/domain/Group.d.ts +99 -0
- package/dist/domain/Group.d.ts.map +1 -0
- package/dist/domain/Group.js +172 -0
- package/dist/domain/Group.js.map +1 -0
- package/dist/domain/GroupItem.d.ts +46 -0
- package/dist/domain/GroupItem.d.ts.map +1 -0
- package/dist/domain/GroupItem.js +58 -0
- package/dist/domain/GroupItem.js.map +1 -0
- package/dist/domain/Icon.d.ts +41 -0
- package/dist/domain/Icon.d.ts.map +1 -0
- package/dist/domain/Icon.js +15 -0
- package/dist/domain/Icon.js.map +1 -0
- package/dist/domain/Prompt.d.ts +49 -0
- package/dist/domain/Prompt.d.ts.map +1 -0
- package/dist/domain/Prompt.js +59 -0
- package/dist/domain/Prompt.js.map +1 -0
- package/dist/domain/PromptArgument.d.ts +23 -0
- package/dist/domain/PromptArgument.d.ts.map +1 -0
- package/dist/domain/PromptArgument.js +27 -0
- package/dist/domain/PromptArgument.js.map +1 -0
- package/dist/domain/Resource.d.ts +37 -0
- package/dist/domain/Resource.d.ts.map +1 -0
- package/dist/domain/Resource.js +39 -0
- package/dist/domain/Resource.js.map +1 -0
- package/dist/domain/Role.d.ts +23 -0
- package/dist/domain/Role.d.ts.map +1 -0
- package/dist/domain/Role.js +24 -0
- package/dist/domain/Role.js.map +1 -0
- package/dist/domain/Tool.d.ts +39 -0
- package/dist/domain/Tool.d.ts.map +1 -0
- package/dist/domain/Tool.js +41 -0
- package/dist/domain/Tool.js.map +1 -0
- package/dist/domain/ToolAnnotations.d.ts +48 -0
- package/dist/domain/ToolAnnotations.d.ts.map +1 -0
- package/dist/domain/ToolAnnotations.js +15 -0
- package/dist/domain/ToolAnnotations.js.map +1 -0
- package/dist/domain/index.d.ts +16 -0
- package/dist/domain/index.d.ts.map +1 -0
- package/dist/domain/index.js +13 -0
- package/dist/domain/index.js.map +1 -0
- package/dist/domain/utils.d.ts +6 -0
- package/dist/domain/utils.d.ts.map +1 -0
- package/dist/domain/utils.js +12 -0
- package/dist/domain/utils.js.map +1 -0
- package/dist/edge-stub.d.ts +73 -0
- package/dist/edge-stub.d.ts.map +1 -0
- package/dist/edge-stub.js +83 -0
- package/dist/edge-stub.js.map +1 -0
- package/dist/exposition/ExpositionCompiler.d.ts +66 -0
- package/dist/exposition/ExpositionCompiler.d.ts.map +1 -0
- package/dist/exposition/ExpositionCompiler.js +279 -0
- package/dist/exposition/ExpositionCompiler.js.map +1 -0
- package/dist/exposition/index.d.ts +4 -0
- package/dist/exposition/index.d.ts.map +1 -0
- package/dist/exposition/index.js +2 -0
- package/dist/exposition/index.js.map +1 -0
- package/dist/exposition/types.d.ts +58 -0
- package/dist/exposition/types.d.ts.map +1 -0
- package/dist/exposition/types.js +11 -0
- package/dist/exposition/types.js.map +1 -0
- package/dist/fsm/StateMachineGate.d.ts +294 -0
- package/dist/fsm/StateMachineGate.d.ts.map +1 -0
- package/dist/fsm/StateMachineGate.js +400 -0
- package/dist/fsm/StateMachineGate.js.map +1 -0
- package/dist/index.d.ts +148 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +112 -0
- package/dist/index.js.map +1 -0
- package/dist/introspection/BehaviorDigest.d.ts +112 -0
- package/dist/introspection/BehaviorDigest.d.ts.map +1 -0
- package/dist/introspection/BehaviorDigest.js +149 -0
- package/dist/introspection/BehaviorDigest.js.map +1 -0
- package/dist/introspection/CapabilityLockfile.d.ts +261 -0
- package/dist/introspection/CapabilityLockfile.d.ts.map +1 -0
- package/dist/introspection/CapabilityLockfile.js +395 -0
- package/dist/introspection/CapabilityLockfile.js.map +1 -0
- package/dist/introspection/ContractAwareSelfHealing.d.ts +90 -0
- package/dist/introspection/ContractAwareSelfHealing.d.ts.map +1 -0
- package/dist/introspection/ContractAwareSelfHealing.js +132 -0
- package/dist/introspection/ContractAwareSelfHealing.js.map +1 -0
- package/dist/introspection/ContractDiff.d.ts +91 -0
- package/dist/introspection/ContractDiff.d.ts.map +1 -0
- package/dist/introspection/ContractDiff.js +466 -0
- package/dist/introspection/ContractDiff.js.map +1 -0
- package/dist/introspection/CryptoAttestation.d.ts +143 -0
- package/dist/introspection/CryptoAttestation.d.ts.map +1 -0
- package/dist/introspection/CryptoAttestation.js +192 -0
- package/dist/introspection/CryptoAttestation.js.map +1 -0
- package/dist/introspection/EntitlementScanner.d.ts +177 -0
- package/dist/introspection/EntitlementScanner.d.ts.map +1 -0
- package/dist/introspection/EntitlementScanner.js +459 -0
- package/dist/introspection/EntitlementScanner.js.map +1 -0
- package/dist/introspection/GovernanceObserver.d.ts +88 -0
- package/dist/introspection/GovernanceObserver.d.ts.map +1 -0
- package/dist/introspection/GovernanceObserver.js +136 -0
- package/dist/introspection/GovernanceObserver.js.map +1 -0
- package/dist/introspection/IntrospectionResource.d.ts +20 -0
- package/dist/introspection/IntrospectionResource.d.ts.map +1 -0
- package/dist/introspection/IntrospectionResource.js +112 -0
- package/dist/introspection/IntrospectionResource.js.map +1 -0
- package/dist/introspection/ManifestCompiler.d.ts +33 -0
- package/dist/introspection/ManifestCompiler.d.ts.map +1 -0
- package/dist/introspection/ManifestCompiler.js +88 -0
- package/dist/introspection/ManifestCompiler.js.map +1 -0
- package/dist/introspection/SemanticProbe.d.ts +207 -0
- package/dist/introspection/SemanticProbe.d.ts.map +1 -0
- package/dist/introspection/SemanticProbe.js +274 -0
- package/dist/introspection/SemanticProbe.js.map +1 -0
- package/dist/introspection/TokenEconomics.d.ts +210 -0
- package/dist/introspection/TokenEconomics.d.ts.map +1 -0
- package/dist/introspection/TokenEconomics.js +292 -0
- package/dist/introspection/TokenEconomics.js.map +1 -0
- package/dist/introspection/ToolContract.d.ts +161 -0
- package/dist/introspection/ToolContract.d.ts.map +1 -0
- package/dist/introspection/ToolContract.js +218 -0
- package/dist/introspection/ToolContract.js.map +1 -0
- package/dist/introspection/canonicalize.d.ts +35 -0
- package/dist/introspection/canonicalize.d.ts.map +1 -0
- package/dist/introspection/canonicalize.js +72 -0
- package/dist/introspection/canonicalize.js.map +1 -0
- package/dist/introspection/index.d.ts +26 -0
- package/dist/introspection/index.d.ts.map +1 -0
- package/dist/introspection/index.js +24 -0
- package/dist/introspection/index.js.map +1 -0
- package/dist/introspection/types.d.ts +120 -0
- package/dist/introspection/types.d.ts.map +1 -0
- package/dist/introspection/types.js +13 -0
- package/dist/introspection/types.js.map +1 -0
- package/dist/observability/DebugObserver.d.ts +185 -0
- package/dist/observability/DebugObserver.d.ts.map +1 -0
- package/dist/observability/DebugObserver.js +102 -0
- package/dist/observability/DebugObserver.js.map +1 -0
- package/dist/observability/TelemetryBus.d.ts +88 -0
- package/dist/observability/TelemetryBus.d.ts.map +1 -0
- package/dist/observability/TelemetryBus.js +463 -0
- package/dist/observability/TelemetryBus.js.map +1 -0
- package/dist/observability/TelemetryEvent.d.ts +177 -0
- package/dist/observability/TelemetryEvent.d.ts.map +1 -0
- package/dist/observability/TelemetryEvent.js +2 -0
- package/dist/observability/TelemetryEvent.js.map +1 -0
- package/dist/observability/Tracing.d.ts +155 -0
- package/dist/observability/Tracing.d.ts.map +1 -0
- package/dist/observability/Tracing.js +67 -0
- package/dist/observability/Tracing.js.map +1 -0
- package/dist/observability/index.d.ts +13 -0
- package/dist/observability/index.d.ts.map +1 -0
- package/dist/observability/index.js +12 -0
- package/dist/observability/index.js.map +1 -0
- package/dist/presenter/PostProcessor.d.ts +52 -0
- package/dist/presenter/PostProcessor.d.ts.map +1 -0
- package/dist/presenter/PostProcessor.js +148 -0
- package/dist/presenter/PostProcessor.js.map +1 -0
- package/dist/presenter/Presenter.d.ts +575 -0
- package/dist/presenter/Presenter.d.ts.map +1 -0
- package/dist/presenter/Presenter.js +768 -0
- package/dist/presenter/Presenter.js.map +1 -0
- package/dist/presenter/PresenterValidationError.d.ts +42 -0
- package/dist/presenter/PresenterValidationError.d.ts.map +1 -0
- package/dist/presenter/PresenterValidationError.js +55 -0
- package/dist/presenter/PresenterValidationError.js.map +1 -0
- package/dist/presenter/RedactEngine.d.ts +110 -0
- package/dist/presenter/RedactEngine.d.ts.map +1 -0
- package/dist/presenter/RedactEngine.js +128 -0
- package/dist/presenter/RedactEngine.js.map +1 -0
- package/dist/presenter/ResponseBuilder.d.ts +262 -0
- package/dist/presenter/ResponseBuilder.d.ts.map +1 -0
- package/dist/presenter/ResponseBuilder.js +374 -0
- package/dist/presenter/ResponseBuilder.js.map +1 -0
- package/dist/presenter/SelectUtils.d.ts +78 -0
- package/dist/presenter/SelectUtils.d.ts.map +1 -0
- package/dist/presenter/SelectUtils.js +141 -0
- package/dist/presenter/SelectUtils.js.map +1 -0
- package/dist/presenter/ZodDescriptionExtractor.d.ts +54 -0
- package/dist/presenter/ZodDescriptionExtractor.d.ts.map +1 -0
- package/dist/presenter/ZodDescriptionExtractor.js +131 -0
- package/dist/presenter/ZodDescriptionExtractor.js.map +1 -0
- package/dist/presenter/definePresenter.d.ts +193 -0
- package/dist/presenter/definePresenter.d.ts.map +1 -0
- package/dist/presenter/definePresenter.js +99 -0
- package/dist/presenter/definePresenter.js.map +1 -0
- package/dist/presenter/index.d.ts +21 -0
- package/dist/presenter/index.d.ts.map +1 -0
- package/dist/presenter/index.js +28 -0
- package/dist/presenter/index.js.map +1 -0
- package/dist/presenter/suggest.d.ts +39 -0
- package/dist/presenter/suggest.d.ts.map +1 -0
- package/dist/presenter/suggest.js +41 -0
- package/dist/presenter/suggest.js.map +1 -0
- package/dist/presenter/typeHelpers.d.ts +147 -0
- package/dist/presenter/typeHelpers.d.ts.map +1 -0
- package/dist/presenter/typeHelpers.js +152 -0
- package/dist/presenter/typeHelpers.js.map +1 -0
- package/dist/presenter/ui.d.ts +205 -0
- package/dist/presenter/ui.d.ts.map +1 -0
- package/dist/presenter/ui.js +222 -0
- package/dist/presenter/ui.js.map +1 -0
- package/dist/prompt/CursorCodec.d.ts +43 -0
- package/dist/prompt/CursorCodec.d.ts.map +1 -0
- package/dist/prompt/CursorCodec.js +171 -0
- package/dist/prompt/CursorCodec.js.map +1 -0
- package/dist/prompt/FluentPromptBuilder.d.ts +155 -0
- package/dist/prompt/FluentPromptBuilder.d.ts.map +1 -0
- package/dist/prompt/FluentPromptBuilder.js +195 -0
- package/dist/prompt/FluentPromptBuilder.js.map +1 -0
- package/dist/prompt/HydrationSandbox.d.ts +55 -0
- package/dist/prompt/HydrationSandbox.d.ts.map +1 -0
- package/dist/prompt/HydrationSandbox.js +122 -0
- package/dist/prompt/HydrationSandbox.js.map +1 -0
- package/dist/prompt/PromptExecutionPipeline.d.ts +61 -0
- package/dist/prompt/PromptExecutionPipeline.d.ts.map +1 -0
- package/dist/prompt/PromptExecutionPipeline.js +177 -0
- package/dist/prompt/PromptExecutionPipeline.js.map +1 -0
- package/dist/prompt/PromptMessage.d.ts +133 -0
- package/dist/prompt/PromptMessage.d.ts.map +1 -0
- package/dist/prompt/PromptMessage.js +182 -0
- package/dist/prompt/PromptMessage.js.map +1 -0
- package/dist/prompt/PromptRegistry.d.ts +236 -0
- package/dist/prompt/PromptRegistry.d.ts.map +1 -0
- package/dist/prompt/PromptRegistry.js +399 -0
- package/dist/prompt/PromptRegistry.js.map +1 -0
- package/dist/prompt/definePrompt.d.ts +111 -0
- package/dist/prompt/definePrompt.d.ts.map +1 -0
- package/dist/prompt/definePrompt.js +130 -0
- package/dist/prompt/definePrompt.js.map +1 -0
- package/dist/prompt/index.d.ts +12 -0
- package/dist/prompt/index.d.ts.map +1 -0
- package/dist/prompt/index.js +13 -0
- package/dist/prompt/index.js.map +1 -0
- package/dist/prompt/types.d.ts +425 -0
- package/dist/prompt/types.d.ts.map +1 -0
- package/dist/prompt/types.js +19 -0
- package/dist/prompt/types.js.map +1 -0
- package/dist/sandbox/SandboxEngine.d.ts +225 -0
- package/dist/sandbox/SandboxEngine.d.ts.map +1 -0
- package/dist/sandbox/SandboxEngine.js +437 -0
- package/dist/sandbox/SandboxEngine.js.map +1 -0
- package/dist/sandbox/SandboxGuard.d.ts +47 -0
- package/dist/sandbox/SandboxGuard.d.ts.map +1 -0
- package/dist/sandbox/SandboxGuard.js +127 -0
- package/dist/sandbox/SandboxGuard.js.map +1 -0
- package/dist/sandbox/index.d.ts +23 -0
- package/dist/sandbox/index.d.ts.map +1 -0
- package/dist/sandbox/index.js +26 -0
- package/dist/sandbox/index.js.map +1 -0
- package/dist/server/DevServer.d.ts +120 -0
- package/dist/server/DevServer.d.ts.map +1 -0
- package/dist/server/DevServer.js +252 -0
- package/dist/server/DevServer.js.map +1 -0
- package/dist/server/ServerAttachment.d.ts +354 -0
- package/dist/server/ServerAttachment.d.ts.map +1 -0
- package/dist/server/ServerAttachment.js +709 -0
- package/dist/server/ServerAttachment.js.map +1 -0
- package/dist/server/ServerResolver.d.ts +24 -0
- package/dist/server/ServerResolver.d.ts.map +1 -0
- package/dist/server/ServerResolver.js +50 -0
- package/dist/server/ServerResolver.js.map +1 -0
- package/dist/server/autoDiscover.d.ts +75 -0
- package/dist/server/autoDiscover.d.ts.map +1 -0
- package/dist/server/autoDiscover.js +164 -0
- package/dist/server/autoDiscover.js.map +1 -0
- package/dist/server/index.d.ts +12 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +11 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/startServer.d.ts +81 -0
- package/dist/server/startServer.d.ts.map +1 -0
- package/dist/server/startServer.js +143 -0
- package/dist/server/startServer.js.map +1 -0
- package/dist/state-sync/CausalEngine.d.ts +28 -0
- package/dist/state-sync/CausalEngine.d.ts.map +1 -0
- package/dist/state-sync/CausalEngine.js +17 -0
- package/dist/state-sync/CausalEngine.js.map +1 -0
- package/dist/state-sync/DescriptionDecorator.d.ts +31 -0
- package/dist/state-sync/DescriptionDecorator.d.ts.map +1 -0
- package/dist/state-sync/DescriptionDecorator.js +38 -0
- package/dist/state-sync/DescriptionDecorator.js.map +1 -0
- package/dist/state-sync/GlobMatcher.d.ts +29 -0
- package/dist/state-sync/GlobMatcher.d.ts.map +1 -0
- package/dist/state-sync/GlobMatcher.js +79 -0
- package/dist/state-sync/GlobMatcher.js.map +1 -0
- package/dist/state-sync/PolicyEngine.d.ts +75 -0
- package/dist/state-sync/PolicyEngine.d.ts.map +1 -0
- package/dist/state-sync/PolicyEngine.js +107 -0
- package/dist/state-sync/PolicyEngine.js.map +1 -0
- package/dist/state-sync/PolicyValidator.d.ts +67 -0
- package/dist/state-sync/PolicyValidator.d.ts.map +1 -0
- package/dist/state-sync/PolicyValidator.js +122 -0
- package/dist/state-sync/PolicyValidator.js.map +1 -0
- package/dist/state-sync/ResponseDecorator.d.ts +33 -0
- package/dist/state-sync/ResponseDecorator.d.ts.map +1 -0
- package/dist/state-sync/ResponseDecorator.js +20 -0
- package/dist/state-sync/ResponseDecorator.js.map +1 -0
- package/dist/state-sync/StateSyncBuilder.d.ts +77 -0
- package/dist/state-sync/StateSyncBuilder.d.ts.map +1 -0
- package/dist/state-sync/StateSyncBuilder.js +129 -0
- package/dist/state-sync/StateSyncBuilder.js.map +1 -0
- package/dist/state-sync/StateSyncLayer.d.ts +107 -0
- package/dist/state-sync/StateSyncLayer.d.ts.map +1 -0
- package/dist/state-sync/StateSyncLayer.js +158 -0
- package/dist/state-sync/StateSyncLayer.js.map +1 -0
- package/dist/state-sync/index.d.ts +27 -0
- package/dist/state-sync/index.d.ts.map +1 -0
- package/dist/state-sync/index.js +27 -0
- package/dist/state-sync/index.js.map +1 -0
- package/dist/state-sync/types.d.ts +174 -0
- package/dist/state-sync/types.d.ts.map +1 -0
- package/dist/state-sync/types.js +17 -0
- package/dist/state-sync/types.js.map +1 -0
- package/dist/testing/MvaMetaSymbol.d.ts +45 -0
- package/dist/testing/MvaMetaSymbol.d.ts.map +1 -0
- package/dist/testing/MvaMetaSymbol.js +34 -0
- package/dist/testing/MvaMetaSymbol.js.map +1 -0
- package/package.json +153 -0
|
@@ -0,0 +1,709 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ServerAttachment — MCP Server Integration Strategy
|
|
3
|
+
*
|
|
4
|
+
* Handles attaching a ToolRegistry to an MCP Server by registering
|
|
5
|
+
* request handlers for tools/list and tools/call.
|
|
6
|
+
*
|
|
7
|
+
* Supports both Server (low-level) and McpServer (high-level) via duck-typing.
|
|
8
|
+
*
|
|
9
|
+
* Pure-function module: receives dependencies, returns detach function.
|
|
10
|
+
*/
|
|
11
|
+
import { ListToolsRequestSchema, CallToolRequestSchema, ListPromptsRequestSchema, GetPromptRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
|
|
12
|
+
import {} from '@modelcontextprotocol/sdk/types.js';
|
|
13
|
+
import { error, toolError } from '../core/response.js';
|
|
14
|
+
import {} from '../core/types.js';
|
|
15
|
+
import {} from '../core/execution/ProgressHelper.js';
|
|
16
|
+
import { resolveServer } from './ServerResolver.js';
|
|
17
|
+
import {} from '../observability/DebugObserver.js';
|
|
18
|
+
import {} from '../observability/Tracing.js';
|
|
19
|
+
import { StateSyncLayer } from '../state-sync/StateSyncLayer.js';
|
|
20
|
+
import {} from '../state-sync/types.js';
|
|
21
|
+
import {} from '../introspection/types.js';
|
|
22
|
+
import { registerIntrospectionResource } from '../introspection/IntrospectionResource.js';
|
|
23
|
+
import { AttestationError } from '../introspection/CryptoAttestation.js';
|
|
24
|
+
import { enrichValidationError } from '../introspection/ContractAwareSelfHealing.js';
|
|
25
|
+
import { compileContracts } from '../introspection/ToolContract.js';
|
|
26
|
+
import { computeServerDigest } from '../introspection/BehaviorDigest.js';
|
|
27
|
+
import {} from '../exposition/types.js';
|
|
28
|
+
import { compileExposition } from '../exposition/ExpositionCompiler.js';
|
|
29
|
+
import {} from '../prompt/PromptRegistry.js';
|
|
30
|
+
import {} from '../prompt/types.js';
|
|
31
|
+
import { StateMachineGate } from '../fsm/StateMachineGate.js';
|
|
32
|
+
// ── Observability Propagation ────────────────────────────
|
|
33
|
+
/**
|
|
34
|
+
* Propagate debug and tracing observers to all registered builders.
|
|
35
|
+
* Zero overhead when neither is configured.
|
|
36
|
+
*/
|
|
37
|
+
function propagateObservability(registry, debug, tracing, telemetry) {
|
|
38
|
+
if (debug && registry.enableDebug) {
|
|
39
|
+
registry.enableDebug(debug);
|
|
40
|
+
}
|
|
41
|
+
if (tracing && registry.enableTracing) {
|
|
42
|
+
registry.enableTracing(tracing);
|
|
43
|
+
}
|
|
44
|
+
if (telemetry && registry.enableTelemetry) {
|
|
45
|
+
registry.enableTelemetry(telemetry);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
// ── Missing Context Guard ────────────────────────────────
|
|
49
|
+
/**
|
|
50
|
+
* Proxy sentinel used when `contextFactory` is not provided.
|
|
51
|
+
*
|
|
52
|
+
* Instead of `undefined` (which causes cryptic `TypeError: Cannot read
|
|
53
|
+
* properties of undefined`), this proxy throws a clear, actionable error
|
|
54
|
+
* the moment a handler accesses any property on `ctx`.
|
|
55
|
+
*
|
|
56
|
+
* For `void` contexts where handlers never touch `ctx`, the proxy is
|
|
57
|
+
* never triggered — zero false positives.
|
|
58
|
+
*
|
|
59
|
+
* @internal — exported for reuse by `startServer.ts` edge handler.
|
|
60
|
+
*/
|
|
61
|
+
export const _missingContextProxy = new Proxy(Object.freeze({}), {
|
|
62
|
+
get(_target, prop) {
|
|
63
|
+
// Allow symbol access (e.g. Symbol.toPrimitive, Symbol.toStringTag) and
|
|
64
|
+
// JSON.stringify probing ('toJSON') to avoid breaking framework internals.
|
|
65
|
+
if (typeof prop === 'symbol')
|
|
66
|
+
return undefined;
|
|
67
|
+
throw new Error(`[vurb] Attempted to access "ctx.${String(prop)}" but no contextFactory was provided. ` +
|
|
68
|
+
`Add contextFactory to your attachToServer() options:\n\n` +
|
|
69
|
+
` registry.attachToServer(server, {\n` +
|
|
70
|
+
` contextFactory: (extra) => createAppContext(extra),\n` +
|
|
71
|
+
` });\n`);
|
|
72
|
+
},
|
|
73
|
+
});
|
|
74
|
+
// ── Handler Factories ────────────────────────────────────
|
|
75
|
+
/**
|
|
76
|
+
* Create the `tools/list` request handler.
|
|
77
|
+
*
|
|
78
|
+
* In flat mode, re-compiles exposition from the current registry state.
|
|
79
|
+
* In grouped mode, delegates to the registry's tag-filtered listing.
|
|
80
|
+
*/
|
|
81
|
+
function createToolListHandler(hCtx) {
|
|
82
|
+
return async (_request, extra) => {
|
|
83
|
+
// Per-request FSM clone for serverless isolation (Bug #3 + Bug #77 fix).
|
|
84
|
+
// Always clone the FSM so concurrent requests never share mutable state.
|
|
85
|
+
let fsm = hCtx.fsm;
|
|
86
|
+
if (fsm) {
|
|
87
|
+
fsm = fsm.clone();
|
|
88
|
+
if (hCtx.fsmStore) {
|
|
89
|
+
const sessionId = extractSessionId(extra) ?? '__default__';
|
|
90
|
+
const snap = await hCtx.fsmStore.load(sessionId);
|
|
91
|
+
if (snap)
|
|
92
|
+
fsm.restore(snap);
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
// In-memory fallback: restore from session-scoped snapshot
|
|
96
|
+
const sessionId = extractSessionId(extra) ?? '__default__';
|
|
97
|
+
const snap = hCtx.fsmMemorySnapshots?.get(sessionId);
|
|
98
|
+
if (snap)
|
|
99
|
+
fsm.restore(snap);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
let tools;
|
|
103
|
+
if (hCtx.isFlat) {
|
|
104
|
+
const exposition = hCtx.recompile();
|
|
105
|
+
tools = hCtx.filter
|
|
106
|
+
? filterFlatTools(exposition.tools, exposition.routingMap, hCtx.filter)
|
|
107
|
+
: exposition.tools;
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
tools = hCtx.filter
|
|
111
|
+
? hCtx.registry.getTools(hCtx.filter)
|
|
112
|
+
: hCtx.registry.getAllTools();
|
|
113
|
+
}
|
|
114
|
+
// FSM State Gate: remove tools not allowed in the current state
|
|
115
|
+
if (fsm && fsm.hasBindings) {
|
|
116
|
+
tools = tools.filter(tool => fsm.isToolAllowed(tool.name));
|
|
117
|
+
}
|
|
118
|
+
return { tools: hCtx.syncLayer ? hCtx.syncLayer.decorateTools(tools) : tools };
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Create the `tools/call` request handler.
|
|
123
|
+
*
|
|
124
|
+
* Handles both flat (O(1) dispatch) and grouped (registry routing) modes.
|
|
125
|
+
* Wires progress notifications when the client opts in via `_meta.progressToken`.
|
|
126
|
+
*/
|
|
127
|
+
function createToolCallHandler(hCtx) {
|
|
128
|
+
return async (request, extra) => {
|
|
129
|
+
const { name, arguments: args = {} } = request.params;
|
|
130
|
+
const ctx = hCtx.contextFactory
|
|
131
|
+
? await hCtx.contextFactory(extra)
|
|
132
|
+
: _missingContextProxy;
|
|
133
|
+
const progressSink = createProgressSink(extra);
|
|
134
|
+
const signal = extractSignal(extra);
|
|
135
|
+
const emit = hCtx.telemetry;
|
|
136
|
+
// ── Telemetry: route event ──────────────────────────
|
|
137
|
+
// Resolve group/action from the routing map instead of naive
|
|
138
|
+
// split('_') — avoids misattributing tools with underscores
|
|
139
|
+
// in their names (e.g. 'user_accounts_list' → group='user_accounts', action='list').
|
|
140
|
+
const exposition = hCtx.isFlat ? hCtx.recompile() : undefined;
|
|
141
|
+
const flatRoute = exposition?.routingMap.get(name);
|
|
142
|
+
const toolGroup = flatRoute ? flatRoute.builder.getName() : name;
|
|
143
|
+
const action = flatRoute ? flatRoute.actionKey : name;
|
|
144
|
+
emit?.({ type: 'route', tool: toolGroup, action, args, timestamp: Date.now() });
|
|
145
|
+
// Per-request FSM clone for serverless isolation (Bug #3 + Bug #77 fix).
|
|
146
|
+
let fsm = hCtx.fsm;
|
|
147
|
+
if (fsm) {
|
|
148
|
+
fsm = fsm.clone();
|
|
149
|
+
if (hCtx.fsmStore) {
|
|
150
|
+
const sessionId = extractSessionId(extra) ?? '__default__';
|
|
151
|
+
const snap = await hCtx.fsmStore.load(sessionId);
|
|
152
|
+
if (snap)
|
|
153
|
+
fsm.restore(snap);
|
|
154
|
+
}
|
|
155
|
+
else {
|
|
156
|
+
const sessionId = extractSessionId(extra) ?? '__default__';
|
|
157
|
+
const snap = hCtx.fsmMemorySnapshots?.get(sessionId);
|
|
158
|
+
if (snap)
|
|
159
|
+
fsm.restore(snap);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
// Bug #107 fix: enforce FSM gate on tools/call — not just tools/list.
|
|
163
|
+
// Without this, a client that knows a tool's name can bypass the gate.
|
|
164
|
+
if (fsm && fsm.hasBindings && !fsm.isToolAllowed(name)) {
|
|
165
|
+
return toolError('FORBIDDEN', {
|
|
166
|
+
message: `Tool "${name}" is not available in the current FSM state ("${fsm.currentState}").`,
|
|
167
|
+
suggestion: 'This tool is gated by the FSM State Gate. Call an allowed tool to advance the state first.',
|
|
168
|
+
availableActions: fsm.getVisibleToolNames([...new Set((exposition?.tools ?? hCtx.registry.getAllTools()).map(t => t.name))]),
|
|
169
|
+
severity: 'error',
|
|
170
|
+
details: { currentState: fsm.currentState, blockedTool: name },
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
let result;
|
|
174
|
+
const t0 = Date.now();
|
|
175
|
+
try {
|
|
176
|
+
if (hCtx.isFlat) {
|
|
177
|
+
// Reuse exposition compiled above for telemetry (avoid double recompile)
|
|
178
|
+
if (flatRoute) {
|
|
179
|
+
const enrichedArgs = { ...args, [flatRoute.discriminator]: flatRoute.actionKey };
|
|
180
|
+
result = await flatRoute.builder.execute(ctx, enrichedArgs, progressSink, signal);
|
|
181
|
+
result = decorateIfSync(hCtx.syncLayer, flatRoute, result);
|
|
182
|
+
}
|
|
183
|
+
else {
|
|
184
|
+
result = await hCtx.registry.routeCall(ctx, name, args, progressSink, signal);
|
|
185
|
+
result = hCtx.syncLayer ? hCtx.syncLayer.decorateResult(name, result) : result;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
else {
|
|
189
|
+
result = await hCtx.registry.routeCall(ctx, name, args, progressSink, signal);
|
|
190
|
+
result = hCtx.syncLayer ? hCtx.syncLayer.decorateResult(name, result) : result;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
catch (err) {
|
|
194
|
+
emit?.({ type: 'error', tool: toolGroup, action, error: String(err), timestamp: Date.now() });
|
|
195
|
+
throw err;
|
|
196
|
+
}
|
|
197
|
+
// ── Self-Healing: enrich validation errors with contract deltas (Bug #43 fix) ──
|
|
198
|
+
if (result.isError && hCtx.selfHealing) {
|
|
199
|
+
const text = result.content?.[0]?.type === 'text' ? result.content[0].text : '';
|
|
200
|
+
if (text) {
|
|
201
|
+
const healing = enrichValidationError(text, toolGroup, action, hCtx.selfHealing);
|
|
202
|
+
if (healing.injected) {
|
|
203
|
+
result = { ...result, content: [{ type: 'text', text: healing.enrichedError }] };
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
// ── Telemetry: execute event ─────────────────────────
|
|
208
|
+
emit?.({
|
|
209
|
+
type: 'execute', tool: toolGroup, action,
|
|
210
|
+
durationMs: Date.now() - t0,
|
|
211
|
+
isError: !!result.isError,
|
|
212
|
+
timestamp: Date.now(),
|
|
213
|
+
});
|
|
214
|
+
// FSM State Gate: auto-transition on successful execution
|
|
215
|
+
if (fsm && !result.isError) {
|
|
216
|
+
const transitionEvent = fsm.getTransitionEvent(name);
|
|
217
|
+
if (transitionEvent) {
|
|
218
|
+
const fromState = fsm.currentState;
|
|
219
|
+
const transition = await fsm.transition(transitionEvent);
|
|
220
|
+
if (transition.changed) {
|
|
221
|
+
// Emit fsm.transition telemetry event
|
|
222
|
+
if (hCtx.telemetry) {
|
|
223
|
+
hCtx.telemetry({
|
|
224
|
+
type: 'fsm.transition',
|
|
225
|
+
tool: name,
|
|
226
|
+
action: transitionEvent,
|
|
227
|
+
from: fromState,
|
|
228
|
+
to: fsm.currentState,
|
|
229
|
+
timestamp: Date.now(),
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
// Persist new state to external store (serverless/edge)
|
|
233
|
+
// Use fallback session ID for transports without sessions (e.g., stdio) (Bug #44 fix)
|
|
234
|
+
if (hCtx.fsmStore) {
|
|
235
|
+
const sessionId = extractSessionId(extra) ?? '__default__';
|
|
236
|
+
await hCtx.fsmStore.save(sessionId, fsm.snapshot());
|
|
237
|
+
}
|
|
238
|
+
else if (hCtx.fsmMemorySnapshots) {
|
|
239
|
+
// Bug #77 fix: persist to in-memory session map
|
|
240
|
+
const sessionId = extractSessionId(extra) ?? '__default__';
|
|
241
|
+
hCtx.fsmMemorySnapshots.set(sessionId, fsm.snapshot());
|
|
242
|
+
}
|
|
243
|
+
// Notify client to re-fetch tools/list
|
|
244
|
+
hCtx.notifyToolListChanged?.();
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
return result;
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* Decorate a flat-route result with state-sync metadata when applicable.
|
|
253
|
+
* Uses the canonical dot-notation key for policy matching.
|
|
254
|
+
*/
|
|
255
|
+
function decorateIfSync(syncLayer, flatRoute, result) {
|
|
256
|
+
if (!syncLayer)
|
|
257
|
+
return result;
|
|
258
|
+
const canonicalKey = `${flatRoute.builder.getName()}.${flatRoute.actionKey}`;
|
|
259
|
+
return syncLayer.decorateResult(canonicalKey, result);
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* Register `prompts/list` and `prompts/get` handlers on the server.
|
|
263
|
+
*
|
|
264
|
+
* Wires the prompt lifecycle notification sink and the internal
|
|
265
|
+
* loopback dispatcher that allows prompts to invoke tools in-memory.
|
|
266
|
+
*/
|
|
267
|
+
function registerPromptHandlers(resolved, server, prompts, registry, filter, contextFactory) {
|
|
268
|
+
// Wire lifecycle sync
|
|
269
|
+
const serverAny = server;
|
|
270
|
+
const sendFn = serverAny['sendPromptListChanged'];
|
|
271
|
+
if (typeof sendFn === 'function') {
|
|
272
|
+
prompts.setNotificationSink(() => { sendFn.call(server); });
|
|
273
|
+
}
|
|
274
|
+
// prompts/list
|
|
275
|
+
resolved.setRequestHandler(ListPromptsRequestSchema, async (request) => {
|
|
276
|
+
const params = {};
|
|
277
|
+
if (filter)
|
|
278
|
+
params.filter = filter;
|
|
279
|
+
if (request?.params?.cursor)
|
|
280
|
+
params.cursor = request.params.cursor;
|
|
281
|
+
return await prompts.listPrompts(params);
|
|
282
|
+
});
|
|
283
|
+
// prompts/get — with loopback dispatcher and signal propagation
|
|
284
|
+
resolved.setRequestHandler(GetPromptRequestSchema, async (request, extra) => {
|
|
285
|
+
const { name, arguments: args = {} } = request.params;
|
|
286
|
+
const ctx = contextFactory
|
|
287
|
+
? await contextFactory(extra)
|
|
288
|
+
: _missingContextProxy;
|
|
289
|
+
const signal = extractSignal(extra);
|
|
290
|
+
const enrichedCtx = injectLoopbackDispatcher(ctx, registry, signal);
|
|
291
|
+
return prompts.routeGet(enrichedCtx, name, args);
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* Inject `invokeTool()` into the context so prompt handlers can call
|
|
296
|
+
* tools in-memory. Runs the Tool's full pipeline with RBAC enforced.
|
|
297
|
+
* Propagates the cancellation signal from the parent request.
|
|
298
|
+
*/
|
|
299
|
+
function injectLoopbackDispatcher(ctx, registry, signal) {
|
|
300
|
+
// Protect the original context from mutation — use prototype-based proxy
|
|
301
|
+
// for object contexts (safe — no property copy). For non-object contexts
|
|
302
|
+
// (primitives or null), start with an empty wrapper.
|
|
303
|
+
let wrapped;
|
|
304
|
+
if (ctx != null && typeof ctx === 'object') {
|
|
305
|
+
wrapped = Object.create(ctx);
|
|
306
|
+
}
|
|
307
|
+
else {
|
|
308
|
+
// ctx is null, undefined, or a primitive — start fresh.
|
|
309
|
+
// No prototype pollution risk here: no properties to copy.
|
|
310
|
+
wrapped = {};
|
|
311
|
+
}
|
|
312
|
+
wrapped['invokeTool'] = async (toolName, toolArgs = {}) => {
|
|
313
|
+
const response = await registry.routeCall(wrapped, toolName, toolArgs, undefined, signal);
|
|
314
|
+
const text = response.content
|
|
315
|
+
.filter((c) => c.type === 'text')
|
|
316
|
+
.map((c) => c.text)
|
|
317
|
+
.join('\n');
|
|
318
|
+
return {
|
|
319
|
+
text,
|
|
320
|
+
isError: response.isError ?? false,
|
|
321
|
+
raw: response,
|
|
322
|
+
};
|
|
323
|
+
};
|
|
324
|
+
return wrapped;
|
|
325
|
+
}
|
|
326
|
+
/**
|
|
327
|
+
* Create the detach function that replaces all handlers with no-ops.
|
|
328
|
+
*/
|
|
329
|
+
function createDetachFn(resolved, hasPrompts) {
|
|
330
|
+
return () => {
|
|
331
|
+
resolved.setRequestHandler(ListToolsRequestSchema, () => ({ tools: [] }));
|
|
332
|
+
resolved.setRequestHandler(CallToolRequestSchema, () => error('Tool handlers have been detached'));
|
|
333
|
+
if (hasPrompts) {
|
|
334
|
+
resolved.setRequestHandler(ListPromptsRequestSchema, () => ({ prompts: [] }));
|
|
335
|
+
resolved.setRequestHandler(GetPromptRequestSchema, () => ({
|
|
336
|
+
messages: [{ role: 'user', content: { type: 'text', text: 'Prompt handlers have been detached' } }],
|
|
337
|
+
}));
|
|
338
|
+
}
|
|
339
|
+
};
|
|
340
|
+
}
|
|
341
|
+
// ── Public API ───────────────────────────────────────────
|
|
342
|
+
/**
|
|
343
|
+
* Attach a registry to an MCP Server.
|
|
344
|
+
*
|
|
345
|
+
* Resolves the server type, registers tools/list and tools/call handlers,
|
|
346
|
+
* and returns a detach function to remove the handlers.
|
|
347
|
+
*
|
|
348
|
+
* @param server - Server or McpServer instance (duck-typed)
|
|
349
|
+
* @param registry - Delegate providing tool listing and routing
|
|
350
|
+
* @param options - Filter and context factory options
|
|
351
|
+
* @returns A detach function to remove the handlers
|
|
352
|
+
*/
|
|
353
|
+
export async function attachToServer(server, registry, options = {}) {
|
|
354
|
+
const resolved = resolveServer(server);
|
|
355
|
+
const { filter, contextFactory, debug, tracing, stateSync, introspection, serverName, toolExposition = 'flat', actionSeparator = '_', prompts, zeroTrust, selfHealing, } = options;
|
|
356
|
+
// 1. Propagate observability to all registered builders
|
|
357
|
+
propagateObservability(registry, debug, tracing, options.telemetry);
|
|
358
|
+
// 2. Create State Sync layer (zero overhead when not configured)
|
|
359
|
+
// Merge manual policies with fluent hints from builders (.invalidates(), .cached())
|
|
360
|
+
const mergedSyncConfig = mergeStateSyncConfig(stateSync, registry.getBuilders());
|
|
361
|
+
const syncLayer = mergedSyncConfig ? new StateSyncLayer(mergedSyncConfig) : undefined;
|
|
362
|
+
// 3. Register introspection resource (zero overhead when disabled)
|
|
363
|
+
if (introspection?.enabled) {
|
|
364
|
+
registerIntrospectionResource(resolved, introspection, serverName ?? 'vurb-server', { values: () => registry.getBuilders() }, contextFactory);
|
|
365
|
+
}
|
|
366
|
+
// 3b. Zero-Trust: compile contracts, compute digest, verify attestation
|
|
367
|
+
// Zero overhead when not configured — no crypto operations run.
|
|
368
|
+
if (zeroTrust) {
|
|
369
|
+
const contracts = await compileContracts(registry.getBuilders());
|
|
370
|
+
const serverDigest = await computeServerDigest(contracts);
|
|
371
|
+
// Synchronous digest comparison (no signer needed for pinning)
|
|
372
|
+
if (zeroTrust.expectedDigest && serverDigest.digest !== zeroTrust.expectedDigest) {
|
|
373
|
+
if (zeroTrust.failOnMismatch ?? true) {
|
|
374
|
+
throw new AttestationError(`[Vurb] Zero-Trust attestation failed: computed digest ${serverDigest.digest} does not match expected ${zeroTrust.expectedDigest}`, {
|
|
375
|
+
valid: false,
|
|
376
|
+
computedDigest: serverDigest.digest,
|
|
377
|
+
expectedDigest: zeroTrust.expectedDigest,
|
|
378
|
+
signature: null,
|
|
379
|
+
signerName: typeof zeroTrust.signer === 'string' ? zeroTrust.signer : zeroTrust.signer.name,
|
|
380
|
+
attestedAt: new Date().toISOString(),
|
|
381
|
+
error: `Digest mismatch: ${serverDigest.digest} !== ${zeroTrust.expectedDigest}`,
|
|
382
|
+
});
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
// 4. Build handler context (shared state for all handler factories)
|
|
387
|
+
// FSM State Gate: auto-bind tool bindings from builders
|
|
388
|
+
const { fsm, fsmStore } = options;
|
|
389
|
+
if (fsm) {
|
|
390
|
+
autoBindFsmFromBuilders(fsm, registry.getBuilders(), toolExposition, actionSeparator);
|
|
391
|
+
}
|
|
392
|
+
// Wire the notification sink for list_changed (FSM transitions)
|
|
393
|
+
let notifyToolListChanged;
|
|
394
|
+
if (fsm) {
|
|
395
|
+
const serverAny = server;
|
|
396
|
+
const sendFn = serverAny['sendToolListChanged'] ?? serverAny['notification'];
|
|
397
|
+
if (typeof sendFn === 'function') {
|
|
398
|
+
notifyToolListChanged = () => {
|
|
399
|
+
try {
|
|
400
|
+
void sendFn.call(server, { method: 'notifications/tools/list_changed' });
|
|
401
|
+
}
|
|
402
|
+
catch {
|
|
403
|
+
// Connection might not be established — ignore
|
|
404
|
+
}
|
|
405
|
+
};
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
const hCtx = {
|
|
409
|
+
registry,
|
|
410
|
+
...(filter ? { filter } : {}),
|
|
411
|
+
...(contextFactory ? { contextFactory } : {}),
|
|
412
|
+
...(syncLayer ? { syncLayer } : {}),
|
|
413
|
+
toolExposition, actionSeparator,
|
|
414
|
+
isFlat: toolExposition === 'flat',
|
|
415
|
+
recompile: (() => {
|
|
416
|
+
let cachedBuilders;
|
|
417
|
+
let cachedResult;
|
|
418
|
+
return () => {
|
|
419
|
+
const builders = [...registry.getBuilders()];
|
|
420
|
+
if (cachedResult && cachedBuilders && builders.length === cachedBuilders.length && builders.every((b, i) => b === cachedBuilders[i])) {
|
|
421
|
+
return cachedResult;
|
|
422
|
+
}
|
|
423
|
+
cachedBuilders = builders;
|
|
424
|
+
// Bug #131: route diagnostic warnings through debug observer
|
|
425
|
+
const warnFn = debug
|
|
426
|
+
? (msg) => debug({ type: 'error', tool: '', action: '', error: msg, step: 'route', timestamp: Date.now() })
|
|
427
|
+
: undefined;
|
|
428
|
+
cachedResult = compileExposition(builders, toolExposition, actionSeparator, warnFn);
|
|
429
|
+
return cachedResult;
|
|
430
|
+
};
|
|
431
|
+
})(),
|
|
432
|
+
...(fsm ? { fsm } : {}),
|
|
433
|
+
...(fsmStore ? { fsmStore } : {}),
|
|
434
|
+
// Bug #77 fix: in-memory FSM snapshot store when no external fsmStore
|
|
435
|
+
// Bug #108 fix: bounded LRU eviction (max 10,000 entries) to prevent
|
|
436
|
+
// unbounded memory growth proportional to unique session count.
|
|
437
|
+
...(fsm && !fsmStore ? { fsmMemorySnapshots: createBoundedSnapshotMap(10_000) } : {}),
|
|
438
|
+
...(notifyToolListChanged ? { notifyToolListChanged } : {}),
|
|
439
|
+
...(options.telemetry ? { telemetry: options.telemetry } : {}),
|
|
440
|
+
...(selfHealing ? { selfHealing } : {}),
|
|
441
|
+
};
|
|
442
|
+
// 5. Register tool handlers
|
|
443
|
+
resolved.setRequestHandler(ListToolsRequestSchema, createToolListHandler(hCtx));
|
|
444
|
+
resolved.setRequestHandler(CallToolRequestSchema, createToolCallHandler(hCtx));
|
|
445
|
+
// 6. Register prompt handlers (zero overhead when omitted)
|
|
446
|
+
if (prompts) {
|
|
447
|
+
registerPromptHandlers(resolved, server, prompts, registry, filter, contextFactory);
|
|
448
|
+
}
|
|
449
|
+
// 7. Return detach function
|
|
450
|
+
return createDetachFn(resolved, prompts !== undefined);
|
|
451
|
+
}
|
|
452
|
+
// ── Flat Tool Filtering ──────────────────────────────────
|
|
453
|
+
/**
|
|
454
|
+
* Filter flat tools by tag criteria.
|
|
455
|
+
*
|
|
456
|
+
* Maps each flat tool back to its originating builder to check tags,
|
|
457
|
+
* then applies the standard tag filter logic.
|
|
458
|
+
*/
|
|
459
|
+
function filterFlatTools(tools, routeMap, filter) {
|
|
460
|
+
const requiredTags = filter.tags && filter.tags.length > 0 ? new Set(filter.tags) : undefined;
|
|
461
|
+
const anyTags = filter.anyTag && filter.anyTag.length > 0 ? new Set(filter.anyTag) : undefined;
|
|
462
|
+
const excludeTags = filter.exclude && filter.exclude.length > 0 ? new Set(filter.exclude) : undefined;
|
|
463
|
+
if (!requiredTags && !anyTags && !excludeTags)
|
|
464
|
+
return tools;
|
|
465
|
+
return tools.filter(tool => {
|
|
466
|
+
const route = routeMap.get(tool.name);
|
|
467
|
+
if (!route)
|
|
468
|
+
return true; // Non-flat tool, include by default
|
|
469
|
+
const builderTags = route.builder.getTags();
|
|
470
|
+
// AND logic: builder must have ALL required tags
|
|
471
|
+
if (requiredTags && !Array.from(requiredTags).every(t => builderTags.includes(t))) {
|
|
472
|
+
return false;
|
|
473
|
+
}
|
|
474
|
+
// OR logic: builder must have at least ONE of these tags
|
|
475
|
+
if (anyTags && !builderTags.some(t => anyTags.has(t))) {
|
|
476
|
+
return false;
|
|
477
|
+
}
|
|
478
|
+
// Exclude: builder must NOT have ANY of these tags
|
|
479
|
+
if (excludeTags && builderTags.some(t => excludeTags.has(t))) {
|
|
480
|
+
return false;
|
|
481
|
+
}
|
|
482
|
+
return true;
|
|
483
|
+
});
|
|
484
|
+
}
|
|
485
|
+
// ── Progress Sink Factory ────────────────────────────────
|
|
486
|
+
/**
|
|
487
|
+
* Duck-type check: the extra object from MCP SDK has _meta and sendNotification.
|
|
488
|
+
*/
|
|
489
|
+
function isMcpExtra(extra) {
|
|
490
|
+
return (typeof extra === 'object' &&
|
|
491
|
+
extra !== null &&
|
|
492
|
+
'sendNotification' in extra &&
|
|
493
|
+
typeof extra.sendNotification === 'function');
|
|
494
|
+
}
|
|
495
|
+
/**
|
|
496
|
+
* Create a ProgressSink from the MCP request `extra` object.
|
|
497
|
+
*
|
|
498
|
+
* When the client includes `_meta.progressToken` in its `tools/call` request,
|
|
499
|
+
* this factory returns a ProgressSink that maps each internal ProgressEvent
|
|
500
|
+
* to the MCP `notifications/progress` protocol wire format.
|
|
501
|
+
*
|
|
502
|
+
* When no progressToken is present (client didn't opt in),
|
|
503
|
+
* returns `undefined` — zero overhead.
|
|
504
|
+
*
|
|
505
|
+
* @param extra - The MCP request handler's extra argument (duck-typed)
|
|
506
|
+
* @returns A ProgressSink or undefined
|
|
507
|
+
*/
|
|
508
|
+
function createProgressSink(extra) {
|
|
509
|
+
if (!isMcpExtra(extra))
|
|
510
|
+
return undefined;
|
|
511
|
+
const token = extra._meta?.progressToken;
|
|
512
|
+
if (token === undefined)
|
|
513
|
+
return undefined;
|
|
514
|
+
const sendNotification = extra.sendNotification;
|
|
515
|
+
return (event) => {
|
|
516
|
+
// Fire-and-forget: progress notifications are best-effort.
|
|
517
|
+
// We intentionally do not await to avoid blocking the handler pipeline.
|
|
518
|
+
void sendNotification({
|
|
519
|
+
method: 'notifications/progress',
|
|
520
|
+
params: {
|
|
521
|
+
progressToken: token,
|
|
522
|
+
progress: event.percent,
|
|
523
|
+
total: 100,
|
|
524
|
+
message: event.message,
|
|
525
|
+
},
|
|
526
|
+
});
|
|
527
|
+
};
|
|
528
|
+
}
|
|
529
|
+
// ── Signal Extraction ────────────────────────────────────
|
|
530
|
+
/**
|
|
531
|
+
* Extract the AbortSignal from the MCP SDK `extra` object.
|
|
532
|
+
*
|
|
533
|
+
* The SDK fires this signal when the client sends `notifications/cancelled`
|
|
534
|
+
* or when the transport connection drops. By extracting and propagating it,
|
|
535
|
+
* the framework enables cooperative cancellation at every pipeline layer.
|
|
536
|
+
*
|
|
537
|
+
* Returns `undefined` when not available — zero overhead.
|
|
538
|
+
*
|
|
539
|
+
* @param extra - The MCP request handler's extra argument (duck-typed)
|
|
540
|
+
* @returns The AbortSignal or undefined
|
|
541
|
+
*/
|
|
542
|
+
function extractSignal(extra) {
|
|
543
|
+
if (!isMcpExtra(extra))
|
|
544
|
+
return undefined;
|
|
545
|
+
return extra.signal;
|
|
546
|
+
}
|
|
547
|
+
// ── State Sync Hint Collection ──────────────────────────────
|
|
548
|
+
/**
|
|
549
|
+
* Collect per-builder state sync hints and merge with manual config.
|
|
550
|
+
*
|
|
551
|
+
* Three scenarios:
|
|
552
|
+
* 1. Manual `stateSync` only — returns it unchanged
|
|
553
|
+
* 2. Fluent hints only — generates policies automatically
|
|
554
|
+
* 3. Both — fluent-generated policies are appended AFTER manual ones
|
|
555
|
+
* (first-match-wins, so manual policies take precedence)
|
|
556
|
+
*
|
|
557
|
+
* Zero overhead when neither is configured.
|
|
558
|
+
*/
|
|
559
|
+
function mergeStateSyncConfig(manual, builders) {
|
|
560
|
+
const hintPolicies = collectHintPolicies(builders);
|
|
561
|
+
if (hintPolicies.length === 0)
|
|
562
|
+
return manual;
|
|
563
|
+
if (!manual)
|
|
564
|
+
return { policies: hintPolicies };
|
|
565
|
+
// Merge: manual first (higher precedence), then auto-generated
|
|
566
|
+
return {
|
|
567
|
+
...manual,
|
|
568
|
+
policies: [...manual.policies, ...hintPolicies],
|
|
569
|
+
};
|
|
570
|
+
}
|
|
571
|
+
/**
|
|
572
|
+
* Walk all builders and convert their StateSyncHints into SyncPolicy[].
|
|
573
|
+
*
|
|
574
|
+
* For each builder with hints:
|
|
575
|
+
* - `'*'` key → tool-level policy matching `{toolName}.*`
|
|
576
|
+
* - Named action keys → action-level policy matching `{toolName}.{actionKey}`
|
|
577
|
+
*/
|
|
578
|
+
function collectHintPolicies(builders) {
|
|
579
|
+
const policies = [];
|
|
580
|
+
for (const builder of builders) {
|
|
581
|
+
if (!builder.getStateSyncHints)
|
|
582
|
+
continue;
|
|
583
|
+
const hints = builder.getStateSyncHints();
|
|
584
|
+
if (hints.size === 0)
|
|
585
|
+
continue;
|
|
586
|
+
const toolName = builder.getName();
|
|
587
|
+
for (const [key, hint] of hints) {
|
|
588
|
+
const match = key === '*' ? `${toolName}.*` : `${toolName}.${key}`;
|
|
589
|
+
policies.push({
|
|
590
|
+
match,
|
|
591
|
+
...(hint.cacheControl ? { cacheControl: hint.cacheControl } : {}),
|
|
592
|
+
...(hint.invalidates?.length ? { invalidates: [...hint.invalidates] } : {}),
|
|
593
|
+
});
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
return policies;
|
|
597
|
+
}
|
|
598
|
+
// ── Session ID Extraction ──────────────────────────────
|
|
599
|
+
/**
|
|
600
|
+
* Create a bounded Map for in-memory FSM snapshots with LRU eviction.
|
|
601
|
+
*
|
|
602
|
+
* When the map exceeds `maxSize`, the oldest entry (first inserted) is evicted.
|
|
603
|
+
* Uses native `Map` iteration order guarantee (insertion order) as the LRU proxy.
|
|
604
|
+
* On `get()`, the accessed entry is re-inserted to refresh its position.
|
|
605
|
+
*
|
|
606
|
+
* Bug #108 fix: prevents unbounded memory growth proportional to unique sessions.
|
|
607
|
+
*/
|
|
608
|
+
function createBoundedSnapshotMap(maxSize) {
|
|
609
|
+
const map = new Map();
|
|
610
|
+
const originalSet = map.set.bind(map);
|
|
611
|
+
const originalGet = map.get.bind(map);
|
|
612
|
+
const originalHas = map.has.bind(map);
|
|
613
|
+
const originalDelete = map.delete.bind(map);
|
|
614
|
+
map.get = (key) => {
|
|
615
|
+
const value = originalGet(key);
|
|
616
|
+
if (value !== undefined) {
|
|
617
|
+
// Refresh position: delete and re-insert to make it "most recently used"
|
|
618
|
+
originalDelete(key);
|
|
619
|
+
originalSet(key, value);
|
|
620
|
+
}
|
|
621
|
+
return value;
|
|
622
|
+
};
|
|
623
|
+
map.set = (key, value) => {
|
|
624
|
+
// If key already exists, delete first to refresh position
|
|
625
|
+
if (originalHas(key)) {
|
|
626
|
+
originalDelete(key);
|
|
627
|
+
}
|
|
628
|
+
originalSet(key, value);
|
|
629
|
+
// Evict oldest entry if over capacity
|
|
630
|
+
if (map.size > maxSize) {
|
|
631
|
+
const oldest = map.keys().next().value;
|
|
632
|
+
if (oldest !== undefined)
|
|
633
|
+
originalDelete(oldest);
|
|
634
|
+
}
|
|
635
|
+
return map;
|
|
636
|
+
};
|
|
637
|
+
return map;
|
|
638
|
+
}
|
|
639
|
+
/**
|
|
640
|
+
* Extract the MCP session identifier from the request `extra` object.
|
|
641
|
+
*
|
|
642
|
+
* For Streamable HTTP transport, the session ID comes from the
|
|
643
|
+
* `Mcp-Session-Id` header. For stdio/SSE transports with persistent
|
|
644
|
+
* connections, a stable session ID may be available from the SDK.
|
|
645
|
+
*
|
|
646
|
+
* Returns `undefined` when not available (stdio transport without session tracking).
|
|
647
|
+
*
|
|
648
|
+
* @param extra - The MCP request handler's extra argument (duck-typed)
|
|
649
|
+
* @returns Session ID string or undefined
|
|
650
|
+
*/
|
|
651
|
+
function extractSessionId(extra) {
|
|
652
|
+
if (typeof extra !== 'object' || extra === null)
|
|
653
|
+
return undefined;
|
|
654
|
+
const ex = extra;
|
|
655
|
+
// Standard MCP SDK session ID
|
|
656
|
+
if (typeof ex['sessionId'] === 'string')
|
|
657
|
+
return ex['sessionId'];
|
|
658
|
+
// Streamable HTTP: from request headers
|
|
659
|
+
const headers = ex['headers'];
|
|
660
|
+
if (headers && typeof headers['mcp-session-id'] === 'string') {
|
|
661
|
+
return headers['mcp-session-id'];
|
|
662
|
+
}
|
|
663
|
+
return undefined;
|
|
664
|
+
}
|
|
665
|
+
// ── FSM Auto-Binding ─────────────────────────────────
|
|
666
|
+
/**
|
|
667
|
+
* Auto-bind FSM tool bindings from all registered builders.
|
|
668
|
+
*
|
|
669
|
+
* Walks all builders, checks for `.bindState()` metadata, and registers
|
|
670
|
+
* the bindings on the `StateMachineGate`. This allows the dev to use
|
|
671
|
+
* `.bindState()` on FluentToolBuilder without manually calling
|
|
672
|
+
* `gate.bindTool()` for each tool.
|
|
673
|
+
*
|
|
674
|
+
* In flat exposition mode, tool names are `{toolName}{separator}{actionKey}`.
|
|
675
|
+
* In grouped mode, tool names are just the builder's name.
|
|
676
|
+
*/
|
|
677
|
+
function autoBindFsmFromBuilders(gate, builders, exposition, separator) {
|
|
678
|
+
for (const builder of builders) {
|
|
679
|
+
// Duck-type: check if builder has getFsmBinding
|
|
680
|
+
const getFsm = builder['getFsmBinding'];
|
|
681
|
+
if (typeof getFsm !== 'function')
|
|
682
|
+
continue;
|
|
683
|
+
const binding = getFsm.call(builder);
|
|
684
|
+
if (!binding)
|
|
685
|
+
continue;
|
|
686
|
+
const toolName = builder.getName();
|
|
687
|
+
if (exposition === 'flat') {
|
|
688
|
+
// In flat mode, each action becomes a separate tool: toolName_actionKey
|
|
689
|
+
// We need to bind each flat tool name to the FSM
|
|
690
|
+
const actions = builder['getActions'];
|
|
691
|
+
if (typeof actions === 'function') {
|
|
692
|
+
const actionList = actions.call(builder);
|
|
693
|
+
for (const action of actionList) {
|
|
694
|
+
const flatName = `${toolName}${separator}${action.key}`;
|
|
695
|
+
gate.bindTool(flatName, binding.states, binding.transition);
|
|
696
|
+
}
|
|
697
|
+
}
|
|
698
|
+
else {
|
|
699
|
+
// Fallback: bind the base tool name
|
|
700
|
+
gate.bindTool(toolName, binding.states, binding.transition);
|
|
701
|
+
}
|
|
702
|
+
}
|
|
703
|
+
else {
|
|
704
|
+
// Grouped mode: tool name is just the builder name
|
|
705
|
+
gate.bindTool(toolName, binding.states, binding.transition);
|
|
706
|
+
}
|
|
707
|
+
}
|
|
708
|
+
}
|
|
709
|
+
//# sourceMappingURL=ServerAttachment.js.map
|