@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,768 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Presenter — MVA View Layer for AI Agents
|
|
3
|
+
*
|
|
4
|
+
* Domain-level "lens" that defines how data is presented to an LLM.
|
|
5
|
+
* A Presenter validates data through a Zod schema, attaches JIT system
|
|
6
|
+
* rules, and renders deterministic UI blocks — all at Node.js speed.
|
|
7
|
+
*
|
|
8
|
+
* The Presenter is **domain-level**, not tool-level. The same Presenter
|
|
9
|
+
* (e.g. `InvoicePresenter`) can be reused across any tool that returns
|
|
10
|
+
* invoices, guaranteeing consistent AI perception of the domain.
|
|
11
|
+
*
|
|
12
|
+
* ## Advanced Features
|
|
13
|
+
*
|
|
14
|
+
* - **Context-Aware**: Callbacks receive `TContext` for RBAC, DLP, locale
|
|
15
|
+
* - **Cognitive Guardrails**: `.agentLimit()` truncates large arrays
|
|
16
|
+
* - **Agentic Affordances**: `.suggestActions()` for HATEOAS-style hints
|
|
17
|
+
* - **Composition**: `.embed()` nests child Presenters (DRY relational data)
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```typescript
|
|
21
|
+
* import { createPresenter, ui } from 'vurb';
|
|
22
|
+
* import { z } from 'zod';
|
|
23
|
+
*
|
|
24
|
+
* export const InvoicePresenter = createPresenter('Invoice')
|
|
25
|
+
* .schema(z.object({
|
|
26
|
+
* id: z.string(),
|
|
27
|
+
* amount_cents: z.number(),
|
|
28
|
+
* status: z.enum(['paid', 'pending']),
|
|
29
|
+
* }))
|
|
30
|
+
* .systemRules((invoice, ctx) => [
|
|
31
|
+
* 'CRITICAL: amount_cents is in CENTS. Divide by 100.',
|
|
32
|
+
* ctx?.user?.role !== 'admin' ? 'Mask sensitive financial data.' : null,
|
|
33
|
+
* ])
|
|
34
|
+
* .uiBlocks((invoice) => [
|
|
35
|
+
* ui.echarts({
|
|
36
|
+
* series: [{ type: 'gauge', data: [{ value: invoice.amount_cents / 100 }] }],
|
|
37
|
+
* }),
|
|
38
|
+
* ])
|
|
39
|
+
* .agentLimit(50, (omitted) =>
|
|
40
|
+
* ui.summary(`⚠️ Dataset truncated. 50 shown, ${omitted} hidden.`)
|
|
41
|
+
* )
|
|
42
|
+
* .suggestActions((invoice) => {
|
|
43
|
+
* if (invoice.status === 'pending') {
|
|
44
|
+
* return [{ tool: 'billing.pay', reason: 'Offer immediate payment' }];
|
|
45
|
+
* }
|
|
46
|
+
* return [];
|
|
47
|
+
* });
|
|
48
|
+
* ```
|
|
49
|
+
*
|
|
50
|
+
* @see {@link createPresenter} for the factory function
|
|
51
|
+
* @see {@link ResponseBuilder} for manual response composition
|
|
52
|
+
*
|
|
53
|
+
* @module
|
|
54
|
+
*/
|
|
55
|
+
import { z, ZodType, ZodError } from 'zod';
|
|
56
|
+
import { ResponseBuilder } from './ResponseBuilder.js';
|
|
57
|
+
import {} from './ui.js';
|
|
58
|
+
import { PresenterValidationError } from './PresenterValidationError.js';
|
|
59
|
+
import { applySelectFilter, extractZodKeys } from './SelectUtils.js';
|
|
60
|
+
import { defaultSerializer } from '../core/serialization/JsonSerializer.js';
|
|
61
|
+
import { compileRedactor } from './RedactEngine.js';
|
|
62
|
+
// ── Brand ────────────────────────────────────────────────
|
|
63
|
+
const PRESENTER_BRAND = 'VurbPresenter';
|
|
64
|
+
/**
|
|
65
|
+
* Check if a value is a {@link Presenter} instance.
|
|
66
|
+
*
|
|
67
|
+
* Used by the execution pipeline to detect Presenters declared
|
|
68
|
+
* via the `returns` field in action configuration.
|
|
69
|
+
*
|
|
70
|
+
* @param value - Any value
|
|
71
|
+
* @returns `true` if the value is a Presenter
|
|
72
|
+
*/
|
|
73
|
+
export function isPresenter(value) {
|
|
74
|
+
return (typeof value === 'object' &&
|
|
75
|
+
value !== null &&
|
|
76
|
+
'__brand' in value &&
|
|
77
|
+
value.__brand === PRESENTER_BRAND);
|
|
78
|
+
}
|
|
79
|
+
// ── Presenter ────────────────────────────────────────────
|
|
80
|
+
/**
|
|
81
|
+
* Domain-level Presenter — the "View" in MVA (Model-View-Agent).
|
|
82
|
+
*
|
|
83
|
+
* Encapsulates:
|
|
84
|
+
* - **Schema** (Zod): Validates and filters data before it reaches the LLM
|
|
85
|
+
* - **System Rules**: JIT context directives that travel with the data
|
|
86
|
+
* - **UI Blocks**: SSR-rendered visual blocks (charts, diagrams, tables)
|
|
87
|
+
* - **Agent Limit**: Smart truncation for large collections
|
|
88
|
+
* - **Action Suggestions**: HATEOAS-style next-action hints
|
|
89
|
+
* - **Embeds**: Relational Presenter composition (DRY)
|
|
90
|
+
*
|
|
91
|
+
* @typeParam T - The validated output type (inferred from the Zod schema)
|
|
92
|
+
*
|
|
93
|
+
* @see {@link createPresenter} for the factory function
|
|
94
|
+
*/
|
|
95
|
+
export class Presenter {
|
|
96
|
+
/** @internal Brand for type detection in the pipeline */
|
|
97
|
+
__brand = PRESENTER_BRAND;
|
|
98
|
+
/** @internal Human-readable domain name (for debugging) */
|
|
99
|
+
name;
|
|
100
|
+
_schema;
|
|
101
|
+
_rules = [];
|
|
102
|
+
_itemUiBlocks;
|
|
103
|
+
_collectionUiBlocks;
|
|
104
|
+
_suggestActions;
|
|
105
|
+
_agentLimit;
|
|
106
|
+
_embeds = [];
|
|
107
|
+
_sealed = false;
|
|
108
|
+
_compiledStringify;
|
|
109
|
+
_compiledRedactor;
|
|
110
|
+
_redactConfig;
|
|
111
|
+
_redactPaths = [];
|
|
112
|
+
/** @internal Use {@link createPresenter} factory instead */
|
|
113
|
+
constructor(name) {
|
|
114
|
+
this.name = name;
|
|
115
|
+
}
|
|
116
|
+
// ── Configuration Guards ─────────────────────────────
|
|
117
|
+
/**
|
|
118
|
+
* Ensure the Presenter is not sealed.
|
|
119
|
+
* Throws a clear error if `.make()` has already been called.
|
|
120
|
+
* @internal
|
|
121
|
+
*/
|
|
122
|
+
_assertNotSealed() {
|
|
123
|
+
if (this._sealed) {
|
|
124
|
+
throw new Error(`Presenter "${this.name}" is sealed after first .make() call. ` +
|
|
125
|
+
`Configuration must be done before .make() is called.`);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
// Implementation — accepts both ZodType and plain object shapes
|
|
129
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
130
|
+
schema(schemaOrShape) {
|
|
131
|
+
this._assertNotSealed();
|
|
132
|
+
const narrowed = this;
|
|
133
|
+
// Detect if it's an already-constructed ZodType (has _def property)
|
|
134
|
+
if (schemaOrShape instanceof ZodType) {
|
|
135
|
+
narrowed._schema = schemaOrShape;
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
// Plain object shape → wrap in z.object()
|
|
139
|
+
narrowed._schema = z.object(schemaOrShape);
|
|
140
|
+
}
|
|
141
|
+
// AOT: Lazy-compile a fast stringify function for this schema.
|
|
142
|
+
// Falls back to JSON.stringify if fast-json-stringify is unavailable.
|
|
143
|
+
narrowed._compiledStringify = defaultSerializer.compile(narrowed._schema);
|
|
144
|
+
return narrowed;
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Set JIT system rules that travel with the data.
|
|
148
|
+
*
|
|
149
|
+
* Rules are **Context Tree-Shaking**: they only appear in the LLM's
|
|
150
|
+
* context when this specific domain's data is returned.
|
|
151
|
+
*
|
|
152
|
+
* Accepts either a **static array** or a **dynamic function** that
|
|
153
|
+
* receives the data and request context for RBAC/DLP/locale rules.
|
|
154
|
+
* Return `null` from dynamic rules to conditionally exclude them.
|
|
155
|
+
*
|
|
156
|
+
* @param rules - Array of rule strings, or a function `(data, ctx?) => (string | null)[]`
|
|
157
|
+
* @returns `this` for chaining
|
|
158
|
+
*
|
|
159
|
+
* @example
|
|
160
|
+
* ```typescript
|
|
161
|
+
* // Static rules
|
|
162
|
+
* .systemRules(['CRITICAL: amounts in CENTS.'])
|
|
163
|
+
*
|
|
164
|
+
* // Dynamic context-aware rules (RBAC)
|
|
165
|
+
* .systemRules((user, ctx) => [
|
|
166
|
+
* ctx?.user?.role !== 'admin' ? 'Mask email and phone.' : null,
|
|
167
|
+
* `Format dates using ${ctx?.tenant?.locale ?? 'en-US'}`
|
|
168
|
+
* ])
|
|
169
|
+
* ```
|
|
170
|
+
*/
|
|
171
|
+
systemRules(rules) {
|
|
172
|
+
this._assertNotSealed();
|
|
173
|
+
this._rules = rules;
|
|
174
|
+
return this;
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Define UI blocks generated for a **single data item**.
|
|
178
|
+
*
|
|
179
|
+
* The callback receives the validated data item and optionally the
|
|
180
|
+
* request context. Return `null` for conditional blocks (filtered
|
|
181
|
+
* automatically).
|
|
182
|
+
*
|
|
183
|
+
* @param fn - `(item, ctx?) => (UiBlock | null)[]`
|
|
184
|
+
* @returns `this` for chaining
|
|
185
|
+
*
|
|
186
|
+
* @example
|
|
187
|
+
* ```typescript
|
|
188
|
+
* .uiBlocks((invoice, ctx) => [
|
|
189
|
+
* ui.echarts({ series: [...] }),
|
|
190
|
+
* ctx?.user?.department === 'finance' ? ui.echarts(advancedChart) : null,
|
|
191
|
+
* ])
|
|
192
|
+
* ```
|
|
193
|
+
*/
|
|
194
|
+
uiBlocks(fn) {
|
|
195
|
+
this._assertNotSealed();
|
|
196
|
+
this._itemUiBlocks = fn;
|
|
197
|
+
return this;
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Define aggregated UI blocks for a **collection** (array) of items.
|
|
201
|
+
*
|
|
202
|
+
* When the handler returns an array, this callback is called **once**
|
|
203
|
+
* with the entire validated array. Prevents N individual charts
|
|
204
|
+
* from flooding the LLM's context.
|
|
205
|
+
*
|
|
206
|
+
* @param fn - `(items[], ctx?) => (UiBlock | null)[]`
|
|
207
|
+
* @returns `this` for chaining
|
|
208
|
+
*
|
|
209
|
+
* @example
|
|
210
|
+
* ```typescript
|
|
211
|
+
* .collectionUiBlocks((invoices) => [
|
|
212
|
+
* ui.echarts({ xAxis: { data: invoices.map(i => i.id) } }),
|
|
213
|
+
* ui.summary(`${invoices.length} invoices found.`),
|
|
214
|
+
* ])
|
|
215
|
+
* ```
|
|
216
|
+
*/
|
|
217
|
+
collectionUiBlocks(fn) {
|
|
218
|
+
this._assertNotSealed();
|
|
219
|
+
this._collectionUiBlocks = fn;
|
|
220
|
+
return this;
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Set a cognitive guardrail that truncates large collections.
|
|
224
|
+
*
|
|
225
|
+
* Protects against context DDoS: if a tool returns thousands of
|
|
226
|
+
* records, the Presenter automatically truncates the data array
|
|
227
|
+
* and injects a summary block teaching the AI to use filters.
|
|
228
|
+
*
|
|
229
|
+
* @param max - Maximum items to keep in the data array
|
|
230
|
+
* @param onTruncate - Callback that generates a warning UI block.
|
|
231
|
+
* Receives the count of omitted items.
|
|
232
|
+
* @returns `this` for chaining
|
|
233
|
+
*
|
|
234
|
+
* @example
|
|
235
|
+
* ```typescript
|
|
236
|
+
* .agentLimit(50, (omitted) =>
|
|
237
|
+
* ui.summary(`⚠️ Truncated. 50 shown, ${omitted} hidden. Use filters.`)
|
|
238
|
+
* )
|
|
239
|
+
* ```
|
|
240
|
+
*/
|
|
241
|
+
agentLimit(max, onTruncate) {
|
|
242
|
+
this._assertNotSealed();
|
|
243
|
+
this._agentLimit = { max, onTruncate };
|
|
244
|
+
return this;
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* Define HATEOAS-style action suggestions based on data state.
|
|
248
|
+
*
|
|
249
|
+
* The callback inspects the data and returns suggested next tools,
|
|
250
|
+
* guiding the AI through the business state machine. Eliminates
|
|
251
|
+
* routing hallucinations by providing explicit next-step hints.
|
|
252
|
+
*
|
|
253
|
+
* @param fn - `(data, ctx?) => ActionSuggestion[]`
|
|
254
|
+
* @returns `this` for chaining
|
|
255
|
+
*
|
|
256
|
+
* @example
|
|
257
|
+
* ```typescript
|
|
258
|
+
* .suggestActions((invoice, ctx) => {
|
|
259
|
+
* if (invoice.status === 'pending') {
|
|
260
|
+
* return [
|
|
261
|
+
* { tool: 'billing.pay', reason: 'Offer immediate payment' },
|
|
262
|
+
* { tool: 'billing.send_reminder', reason: 'Send reminder email' },
|
|
263
|
+
* ];
|
|
264
|
+
* }
|
|
265
|
+
* return [];
|
|
266
|
+
* })
|
|
267
|
+
* ```
|
|
268
|
+
*/
|
|
269
|
+
suggestActions(fn) {
|
|
270
|
+
this._assertNotSealed();
|
|
271
|
+
this._suggestActions = fn;
|
|
272
|
+
return this;
|
|
273
|
+
}
|
|
274
|
+
// ── Fluent Aliases ───────────────────────────────────
|
|
275
|
+
/**
|
|
276
|
+
* Alias for `.suggestActions()` — fluent shorthand.
|
|
277
|
+
*
|
|
278
|
+
* Define HATEOAS-style action suggestions based on data state.
|
|
279
|
+
* Use with the `suggest()` helper for maximum fluency.
|
|
280
|
+
*
|
|
281
|
+
* @param fn - `(data, ctx?) => (ActionSuggestion | null)[]`
|
|
282
|
+
* @returns `this` for chaining
|
|
283
|
+
*
|
|
284
|
+
* @example
|
|
285
|
+
* ```typescript
|
|
286
|
+
* import { suggest } from 'vurb';
|
|
287
|
+
*
|
|
288
|
+
* .suggest((inv) => [
|
|
289
|
+
* suggest('invoices.get', 'View details'),
|
|
290
|
+
* inv.status === 'overdue'
|
|
291
|
+
* ? suggest('billing.remind', 'Send reminder')
|
|
292
|
+
* : null,
|
|
293
|
+
* ])
|
|
294
|
+
* ```
|
|
295
|
+
*/
|
|
296
|
+
suggest(fn) {
|
|
297
|
+
return this.suggestActions(fn);
|
|
298
|
+
}
|
|
299
|
+
/**
|
|
300
|
+
* Alias for `.systemRules()` — fluent shorthand.
|
|
301
|
+
*
|
|
302
|
+
* @param rules - Static rules array or dynamic `(data, ctx?) => (string | null)[]`
|
|
303
|
+
* @returns `this` for chaining
|
|
304
|
+
*
|
|
305
|
+
* @example
|
|
306
|
+
* ```typescript
|
|
307
|
+
* .rules(['CRITICAL: amounts in CENTS.'])
|
|
308
|
+
* .rules((inv) => [
|
|
309
|
+
* inv.status === 'overdue' ? '⚠️ OVERDUE' : null,
|
|
310
|
+
* ])
|
|
311
|
+
* ```
|
|
312
|
+
*/
|
|
313
|
+
rules(rules) {
|
|
314
|
+
return this.systemRules(rules);
|
|
315
|
+
}
|
|
316
|
+
/**
|
|
317
|
+
* Alias for `.uiBlocks()` — fluent shorthand.
|
|
318
|
+
*
|
|
319
|
+
* @param fn - `(item, ctx?) => (UiBlock | null)[]`
|
|
320
|
+
* @returns `this` for chaining
|
|
321
|
+
*
|
|
322
|
+
* @example
|
|
323
|
+
* ```typescript
|
|
324
|
+
* .ui((inv) => [
|
|
325
|
+
* ui.echarts({ series: [{ type: 'gauge', data: [{ value: inv.amount / 100 }] }] }),
|
|
326
|
+
* ])
|
|
327
|
+
* ```
|
|
328
|
+
*/
|
|
329
|
+
ui(fn) {
|
|
330
|
+
return this.uiBlocks(fn);
|
|
331
|
+
}
|
|
332
|
+
/**
|
|
333
|
+
* Cognitive guardrail shorthand with auto-generated message.
|
|
334
|
+
*
|
|
335
|
+
* Truncates large collections and injects a smart summary block.
|
|
336
|
+
* For custom truncation messages, use `.agentLimit(max, onTruncate)` instead.
|
|
337
|
+
*
|
|
338
|
+
* @param max - Maximum items to keep in the data array
|
|
339
|
+
* @returns `this` for chaining
|
|
340
|
+
*
|
|
341
|
+
* @example
|
|
342
|
+
* ```typescript
|
|
343
|
+
* // Auto-generated message:
|
|
344
|
+
* .limit(50)
|
|
345
|
+
* // → "⚠️ Dataset truncated. 50 shown, {omitted} hidden. Use filters to narrow results."
|
|
346
|
+
*
|
|
347
|
+
* // For custom message, use agentLimit():
|
|
348
|
+
* .agentLimit(50, (omitted) => ui.summary(`Custom: ${omitted} hidden`))
|
|
349
|
+
* ```
|
|
350
|
+
*/
|
|
351
|
+
limit(max) {
|
|
352
|
+
return this.agentLimit(max, (omitted) => ({
|
|
353
|
+
type: 'summary',
|
|
354
|
+
content: `📊 **Summary**: ⚠️ Dataset truncated. ${max} shown, ${omitted} hidden. Use filters to narrow results.`,
|
|
355
|
+
}));
|
|
356
|
+
}
|
|
357
|
+
/**
|
|
358
|
+
* Compose a child Presenter for a nested relation.
|
|
359
|
+
*
|
|
360
|
+
* When `data[key]` exists, the child Presenter's rules and UI blocks
|
|
361
|
+
* are merged into the parent response. This is the DRY solution for
|
|
362
|
+
* relational data: define `ClientPresenter` once, embed it everywhere.
|
|
363
|
+
*
|
|
364
|
+
* @param key - The property key containing the nested data
|
|
365
|
+
* @param childPresenter - The Presenter to apply to `data[key]`
|
|
366
|
+
* @returns `this` for chaining
|
|
367
|
+
*
|
|
368
|
+
* @example
|
|
369
|
+
* ```typescript
|
|
370
|
+
* import { ClientPresenter } from './ClientPresenter';
|
|
371
|
+
*
|
|
372
|
+
* export const InvoicePresenter = createPresenter('Invoice')
|
|
373
|
+
* .schema(invoiceSchema)
|
|
374
|
+
* .embed('client', ClientPresenter);
|
|
375
|
+
* ```
|
|
376
|
+
*/
|
|
377
|
+
embed(key, childPresenter) {
|
|
378
|
+
this._assertNotSealed();
|
|
379
|
+
this._embeds.push({ key, presenter: childPresenter });
|
|
380
|
+
return this;
|
|
381
|
+
}
|
|
382
|
+
// ── DLP Compliance (PII Redaction) ────────────────────
|
|
383
|
+
/**
|
|
384
|
+
* Declare PII fields to redact before data leaves the framework.
|
|
385
|
+
*
|
|
386
|
+
* Uses `fast-redact` (Pino's V8-optimized serialization engine) to
|
|
387
|
+
* compile object paths into hyper-fast masking functions at config
|
|
388
|
+
* time — zero overhead on the hot path.
|
|
389
|
+
*
|
|
390
|
+
* The redaction is applied **structurally** on the wire-facing data
|
|
391
|
+
* (after `_select` filter, before `ResponseBuilder`). UI blocks and
|
|
392
|
+
* system rules still see the **full unmasked data** (Late Guillotine
|
|
393
|
+
* pattern preserved).
|
|
394
|
+
*
|
|
395
|
+
* Requires `fast-redact` as an optional peer dependency.
|
|
396
|
+
* If not installed, passes data through unmodified (defensive fallback).
|
|
397
|
+
*
|
|
398
|
+
* @param paths - Object paths to redact. Supports dot notation,
|
|
399
|
+
* bracket notation, wildcards (`'*'`), and array indices.
|
|
400
|
+
* @param censor - Replacement value. Default: `'[REDACTED]'`.
|
|
401
|
+
* Can be a function `(originalValue) => maskedValue`.
|
|
402
|
+
* @returns `this` for chaining
|
|
403
|
+
*
|
|
404
|
+
* @example
|
|
405
|
+
* ```typescript
|
|
406
|
+
* // Basic PII masking
|
|
407
|
+
* createPresenter('Patient')
|
|
408
|
+
* .schema({ name: t.string, ssn: t.string, diagnosis: t.string })
|
|
409
|
+
* .redactPII(['ssn', 'diagnosis'])
|
|
410
|
+
*
|
|
411
|
+
* // Wildcard — redact all nested SSN fields
|
|
412
|
+
* createPresenter('Users')
|
|
413
|
+
* .redactPII(['*.ssn', '*.password', 'credit_card.number'])
|
|
414
|
+
*
|
|
415
|
+
* // Array wildcard — redact diagnosis in all patients
|
|
416
|
+
* createPresenter('Hospital')
|
|
417
|
+
* .redactPII(['patients[*].diagnosis', 'patients[*].ssn'])
|
|
418
|
+
*
|
|
419
|
+
* // Custom censor — last 4 digits visible
|
|
420
|
+
* createPresenter('Payment')
|
|
421
|
+
* .redactPII(['credit_card.number'], (v) => '****-****-****-' + String(v).slice(-4))
|
|
422
|
+
* ```
|
|
423
|
+
*
|
|
424
|
+
* @see {@link https://github.com/davidmarkclements/fast-redact | fast-redact}
|
|
425
|
+
*/
|
|
426
|
+
redactPII(paths, censor) {
|
|
427
|
+
this._assertNotSealed();
|
|
428
|
+
const config = {
|
|
429
|
+
paths,
|
|
430
|
+
...(censor !== undefined ? { censor } : {}),
|
|
431
|
+
};
|
|
432
|
+
this._redactConfig = config;
|
|
433
|
+
this._compiledRedactor = compileRedactor(config);
|
|
434
|
+
this._redactPaths = paths;
|
|
435
|
+
return this;
|
|
436
|
+
}
|
|
437
|
+
/**
|
|
438
|
+
* Alias for `.redactPII()` — fluent shorthand.
|
|
439
|
+
*
|
|
440
|
+
* @param paths - Object paths to redact
|
|
441
|
+
* @param censor - Replacement value or function
|
|
442
|
+
* @returns `this` for chaining
|
|
443
|
+
*
|
|
444
|
+
* @example
|
|
445
|
+
* ```typescript
|
|
446
|
+
* createPresenter('User')
|
|
447
|
+
* .schema({ name: t.string, ssn: t.string })
|
|
448
|
+
* .redact(['ssn'])
|
|
449
|
+
* ```
|
|
450
|
+
*/
|
|
451
|
+
redact(paths, censor) {
|
|
452
|
+
return this.redactPII(paths, censor);
|
|
453
|
+
}
|
|
454
|
+
// ── Introspection (read-only metadata accessors) ─────
|
|
455
|
+
/**
|
|
456
|
+
* Get the Zod schema's top-level keys.
|
|
457
|
+
*
|
|
458
|
+
* Returns the field names declared in the Presenter's schema.
|
|
459
|
+
* Safe to call at any time — does NOT seal the Presenter.
|
|
460
|
+
*
|
|
461
|
+
* @returns Array of key names, or empty array if no schema is set
|
|
462
|
+
*/
|
|
463
|
+
getSchemaKeys() {
|
|
464
|
+
if (!this._schema)
|
|
465
|
+
return [];
|
|
466
|
+
return extractZodKeys(this._schema);
|
|
467
|
+
}
|
|
468
|
+
/**
|
|
469
|
+
* Get the DLP redaction paths configured on this Presenter.
|
|
470
|
+
*
|
|
471
|
+
* Returns the paths passed to `.redactPII()` / `.redact()`.
|
|
472
|
+
* Empty array if no redaction is configured.
|
|
473
|
+
*
|
|
474
|
+
* @internal Used by PostProcessor for `dlp.redact` telemetry
|
|
475
|
+
*/
|
|
476
|
+
getRedactPaths() {
|
|
477
|
+
return this._redactPaths;
|
|
478
|
+
}
|
|
479
|
+
/**
|
|
480
|
+
* Get the agent limit config (if set via `.agentLimit()` or `.limit()`).
|
|
481
|
+
*
|
|
482
|
+
* @internal Used by PostProcessor for guardrail telemetry
|
|
483
|
+
* @returns The max limit, or `undefined` if no limit is configured
|
|
484
|
+
*/
|
|
485
|
+
getAgentLimitMax() {
|
|
486
|
+
return this._agentLimit?.max;
|
|
487
|
+
}
|
|
488
|
+
/**
|
|
489
|
+
* Get which UI block factory methods were configured.
|
|
490
|
+
*
|
|
491
|
+
* Inspects the configuration callbacks to determine supported
|
|
492
|
+
* UI block types. Does NOT execute any callbacks.
|
|
493
|
+
*
|
|
494
|
+
* @returns Array of UI block type labels
|
|
495
|
+
*/
|
|
496
|
+
getUiBlockTypes() {
|
|
497
|
+
const types = [];
|
|
498
|
+
if (this._itemUiBlocks)
|
|
499
|
+
types.push('item');
|
|
500
|
+
if (this._collectionUiBlocks)
|
|
501
|
+
types.push('collection');
|
|
502
|
+
// Note: specific types (echarts, mermaid, etc.) are only known at
|
|
503
|
+
// runtime when callbacks execute. We report callback presence here.
|
|
504
|
+
return types;
|
|
505
|
+
}
|
|
506
|
+
/**
|
|
507
|
+
* Whether the Presenter uses dynamic (context-aware) system rules.
|
|
508
|
+
*
|
|
509
|
+
* Static rules (string arrays) are NOT contextual.
|
|
510
|
+
* Functions `(data, ctx?) => ...` ARE contextual.
|
|
511
|
+
*
|
|
512
|
+
* @returns `true` if rules are a function
|
|
513
|
+
*/
|
|
514
|
+
hasContextualRules() {
|
|
515
|
+
return typeof this._rules === 'function';
|
|
516
|
+
}
|
|
517
|
+
/**
|
|
518
|
+
* Return static rule strings for introspection hashing.
|
|
519
|
+
*
|
|
520
|
+
* If rules are dynamic (function), returns an empty array because
|
|
521
|
+
* the actual rule content depends on runtime data/context.
|
|
522
|
+
*
|
|
523
|
+
* @returns Static rule strings, or empty array if rules are contextual
|
|
524
|
+
*/
|
|
525
|
+
getStaticRuleStrings() {
|
|
526
|
+
if (typeof this._rules === 'function')
|
|
527
|
+
return [];
|
|
528
|
+
return this._rules;
|
|
529
|
+
}
|
|
530
|
+
// ── Execution ────────────────────────────────────────
|
|
531
|
+
/**
|
|
532
|
+
* Compose a {@link ResponseBuilder} from raw data.
|
|
533
|
+
*
|
|
534
|
+
* Orchestrates: truncate → validate → embed → render UI → attach rules
|
|
535
|
+
* → suggest actions → **Late Guillotine** (`_select` filter).
|
|
536
|
+
*
|
|
537
|
+
* **Late Guillotine pattern**: UI blocks, system rules, and action
|
|
538
|
+
* suggestions are computed using the **full** validated data, ensuring
|
|
539
|
+
* charts and rules never see `undefined` for pruned fields. Only the
|
|
540
|
+
* wire-facing data block in the ResponseBuilder is filtered by `_select`
|
|
541
|
+
* — the UI consumes full data in RAM, the AI consumes pruned data on
|
|
542
|
+
* the wire.
|
|
543
|
+
*
|
|
544
|
+
* After the first call, the Presenter is sealed (immutable).
|
|
545
|
+
*
|
|
546
|
+
* **Auto-detection**: If `data` is an array, items are validated
|
|
547
|
+
* individually and `collectionUiBlocks` is called (if defined).
|
|
548
|
+
* Otherwise, `uiBlocks` is called for the single item.
|
|
549
|
+
*
|
|
550
|
+
* @param data - Raw data from the handler (object or array)
|
|
551
|
+
* @param ctx - Optional request context (for RBAC, locale, etc.)
|
|
552
|
+
* @param selectFields - Optional top-level field names to keep in the
|
|
553
|
+
* data block. When provided, only these keys survive in the JSON
|
|
554
|
+
* payload sent to the AI. Nested objects are kept whole (shallow).
|
|
555
|
+
* @returns A {@link ResponseBuilder} ready for chaining or `.build()`
|
|
556
|
+
* @throws If Zod validation fails
|
|
557
|
+
*
|
|
558
|
+
* @example
|
|
559
|
+
* ```typescript
|
|
560
|
+
* // Full data (default)
|
|
561
|
+
* return InvoicePresenter.make(rawInvoice).build();
|
|
562
|
+
*
|
|
563
|
+
* // With _select filtering — only 'status' reaches the AI
|
|
564
|
+
* return InvoicePresenter.make(rawInvoice, ctx, ['status']).build();
|
|
565
|
+
* ```
|
|
566
|
+
*/
|
|
567
|
+
make(data, ctx, selectFields) {
|
|
568
|
+
// Seal on first use — configuration is frozen from here
|
|
569
|
+
this._sealed = true;
|
|
570
|
+
const isArray = Array.isArray(data);
|
|
571
|
+
// Step 0: Cognitive Guardrails — truncate if needed
|
|
572
|
+
let truncationBlock;
|
|
573
|
+
if (isArray && this._agentLimit && data.length > this._agentLimit.max) {
|
|
574
|
+
const fullLength = data.length;
|
|
575
|
+
const omitted = fullLength - this._agentLimit.max;
|
|
576
|
+
data = data.slice(0, this._agentLimit.max);
|
|
577
|
+
truncationBlock = this._agentLimit.onTruncate(omitted);
|
|
578
|
+
}
|
|
579
|
+
// Step 1: Process embedded child Presenters (on RAW data, before validation)
|
|
580
|
+
// Embeds access relational keys (e.g. `client`) that the parent schema
|
|
581
|
+
// may not include — so they must run on pre-validation data.
|
|
582
|
+
const rawForEmbeds = data;
|
|
583
|
+
// Step 2: Validate — produces the FULL validated data
|
|
584
|
+
const validated = this._validate(data, isArray);
|
|
585
|
+
// ── Late Guillotine ──────────────────────────────────
|
|
586
|
+
// Steps 3-6 use the FULL validated data so that UI blocks,
|
|
587
|
+
// system rules, and action suggestions never see undefined
|
|
588
|
+
// for pruned fields (e.g. a chart using 'revenue' won't break
|
|
589
|
+
// if the AI only selected 'status').
|
|
590
|
+
//
|
|
591
|
+
// The _select filter is applied ONLY to the wire-facing data
|
|
592
|
+
// block in the ResponseBuilder — the last step before serialization.
|
|
593
|
+
// Step 3: Determine wire-facing data (filtered or full)
|
|
594
|
+
const wireData = (selectFields && selectFields.length > 0)
|
|
595
|
+
? applySelectFilter(validated, selectFields, isArray)
|
|
596
|
+
: validated;
|
|
597
|
+
// Step 3.1: DLP Redaction — mask PII on the wire-facing data
|
|
598
|
+
// Uses structuredClone so UI blocks/rules still see full data.
|
|
599
|
+
const safeWireData = this._applyRedaction(wireData, isArray);
|
|
600
|
+
const builder = new ResponseBuilder(safeWireData, this._compiledStringify);
|
|
601
|
+
// Step 3.5: Truncation warning (first UI block, before all others)
|
|
602
|
+
if (truncationBlock) {
|
|
603
|
+
builder.uiBlock(truncationBlock);
|
|
604
|
+
}
|
|
605
|
+
// Step 4: Merge embedded child Presenter blocks (using FULL data)
|
|
606
|
+
this._processEmbeds(builder, rawForEmbeds, isArray, ctx);
|
|
607
|
+
// Step 5: Attach UI blocks (using FULL validated data)
|
|
608
|
+
this._attachUiBlocks(builder, validated, isArray, ctx);
|
|
609
|
+
// Step 6: Attach rules (using FULL validated data)
|
|
610
|
+
this._attachRules(builder, validated, isArray, ctx);
|
|
611
|
+
// Step 7: Attach action suggestions (using FULL validated data)
|
|
612
|
+
this._attachSuggestions(builder, validated, isArray, ctx);
|
|
613
|
+
return builder;
|
|
614
|
+
}
|
|
615
|
+
// ── Private Decomposed Steps ─────────────────────────
|
|
616
|
+
/**
|
|
617
|
+
* Apply PII redaction to wire-facing data.
|
|
618
|
+
* Creates a deep clone to preserve original data for UI/rules.
|
|
619
|
+
* @internal
|
|
620
|
+
*/
|
|
621
|
+
_applyRedaction(data, isArray) {
|
|
622
|
+
// Lazy recompilation: if redactPII was called before fast-redact loaded
|
|
623
|
+
// (e.g., top-level Presenter declared before initVurb()), retry now.
|
|
624
|
+
if (!this._compiledRedactor && this._redactConfig) {
|
|
625
|
+
this._compiledRedactor = compileRedactor(this._redactConfig);
|
|
626
|
+
if (!this._compiledRedactor) {
|
|
627
|
+
console.warn(`[vurb] Presenter "${this.name}": PII redaction configured but fast-redact is not available. ` +
|
|
628
|
+
`Data will pass through WITHOUT redaction. Ensure initVurb() completes before .make() is called, ` +
|
|
629
|
+
`or install fast-redact as a dependency.`);
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
if (!this._compiledRedactor)
|
|
633
|
+
return data;
|
|
634
|
+
if (isArray) {
|
|
635
|
+
return data.map(item => this._compiledRedactor(item));
|
|
636
|
+
}
|
|
637
|
+
return this._compiledRedactor(data);
|
|
638
|
+
}
|
|
639
|
+
/**
|
|
640
|
+
* Validate data through the Zod schema (if configured).
|
|
641
|
+
* For arrays, each item is validated independently.
|
|
642
|
+
* @internal
|
|
643
|
+
*/
|
|
644
|
+
_validate(data, isArray) {
|
|
645
|
+
if (!this._schema)
|
|
646
|
+
return data;
|
|
647
|
+
try {
|
|
648
|
+
if (isArray) {
|
|
649
|
+
return data.map(item => this._schema.parse(item));
|
|
650
|
+
}
|
|
651
|
+
return this._schema.parse(data);
|
|
652
|
+
}
|
|
653
|
+
catch (err) {
|
|
654
|
+
if (err instanceof ZodError) {
|
|
655
|
+
throw new PresenterValidationError(this.name, err);
|
|
656
|
+
}
|
|
657
|
+
throw err;
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
/**
|
|
661
|
+
* Generate and attach UI blocks to the response builder.
|
|
662
|
+
* Auto-detects single vs collection. Filters `null` blocks.
|
|
663
|
+
* @internal
|
|
664
|
+
*/
|
|
665
|
+
_attachUiBlocks(builder, data, isArray, ctx) {
|
|
666
|
+
if (isArray && this._collectionUiBlocks) {
|
|
667
|
+
const blocks = this._collectionUiBlocks(data, ctx).filter(Boolean);
|
|
668
|
+
if (blocks.length > 0)
|
|
669
|
+
builder.uiBlocks(blocks);
|
|
670
|
+
}
|
|
671
|
+
else if (!isArray && this._itemUiBlocks) {
|
|
672
|
+
const blocks = this._itemUiBlocks(data, ctx).filter(Boolean);
|
|
673
|
+
if (blocks.length > 0)
|
|
674
|
+
builder.uiBlocks(blocks);
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
/**
|
|
678
|
+
* Resolve and attach domain rules to the response builder.
|
|
679
|
+
* Supports both static arrays and dynamic context-aware functions.
|
|
680
|
+
* Filters `null` rules automatically.
|
|
681
|
+
* @internal
|
|
682
|
+
*/
|
|
683
|
+
_attachRules(builder, data, isArray, ctx) {
|
|
684
|
+
if (typeof this._rules === 'function') {
|
|
685
|
+
// Dynamic rules — resolve with data and context
|
|
686
|
+
const singleData = isArray ? data[0] : data;
|
|
687
|
+
if (singleData !== undefined) {
|
|
688
|
+
const resolved = this._rules(singleData, ctx)
|
|
689
|
+
.filter((r) => r !== null);
|
|
690
|
+
if (resolved.length > 0)
|
|
691
|
+
builder.systemRules(resolved);
|
|
692
|
+
}
|
|
693
|
+
}
|
|
694
|
+
else if (this._rules.length > 0) {
|
|
695
|
+
// Static rules — pass directly
|
|
696
|
+
builder.systemRules(this._rules);
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
/**
|
|
700
|
+
* Evaluate and attach action suggestions to the response.
|
|
701
|
+
* Generates a `[SYSTEM HINT]` block with recommended next tools.
|
|
702
|
+
* @internal
|
|
703
|
+
*/
|
|
704
|
+
_attachSuggestions(builder, data, isArray, ctx) {
|
|
705
|
+
if (!this._suggestActions)
|
|
706
|
+
return;
|
|
707
|
+
// For collections, evaluate suggestions on the first item (or skip)
|
|
708
|
+
const singleData = isArray ? data[0] : data;
|
|
709
|
+
if (singleData === undefined)
|
|
710
|
+
return;
|
|
711
|
+
const suggestions = this._suggestActions(singleData, ctx);
|
|
712
|
+
if (suggestions.length > 0) {
|
|
713
|
+
builder.systemHint(suggestions);
|
|
714
|
+
}
|
|
715
|
+
}
|
|
716
|
+
/**
|
|
717
|
+
* Process embedded child Presenters for nested relational data.
|
|
718
|
+
* Merges child UI blocks and rules into the parent builder.
|
|
719
|
+
* @internal
|
|
720
|
+
*/
|
|
721
|
+
_processEmbeds(builder, data, isArray, ctx) {
|
|
722
|
+
if (this._embeds.length === 0)
|
|
723
|
+
return;
|
|
724
|
+
const singleData = isArray ? data[0] : data;
|
|
725
|
+
if (singleData === undefined || typeof singleData !== 'object')
|
|
726
|
+
return;
|
|
727
|
+
for (const embed of this._embeds) {
|
|
728
|
+
const nestedData = singleData[embed.key];
|
|
729
|
+
if (nestedData === undefined || nestedData === null)
|
|
730
|
+
continue;
|
|
731
|
+
// Run the child Presenter and extract its blocks
|
|
732
|
+
const childBuilder = embed.presenter.make(nestedData, ctx);
|
|
733
|
+
const childResponse = childBuilder.build();
|
|
734
|
+
// Skip the first block (data) — parent already has it
|
|
735
|
+
// Merge remaining blocks (UI, rules, hints) into the parent
|
|
736
|
+
for (let i = 1; i < childResponse.content.length; i++) {
|
|
737
|
+
builder.rawBlock(childResponse.content[i].text);
|
|
738
|
+
}
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
// ── Factory ──────────────────────────────────────────────
|
|
743
|
+
/**
|
|
744
|
+
* Create a new domain-level Presenter.
|
|
745
|
+
*
|
|
746
|
+
* The Presenter defines how a specific domain model (Invoice, Task,
|
|
747
|
+
* Project) is presented to AI agents. It is **reusable** across any
|
|
748
|
+
* tool that returns that model.
|
|
749
|
+
*
|
|
750
|
+
* @param name - Human-readable domain name (for debugging/logging)
|
|
751
|
+
* @returns A new {@link Presenter} ready for configuration
|
|
752
|
+
*
|
|
753
|
+
* @example
|
|
754
|
+
* ```typescript
|
|
755
|
+
* import { createPresenter, ui } from 'vurb';
|
|
756
|
+
*
|
|
757
|
+
* export const TaskPresenter = createPresenter('Task')
|
|
758
|
+
* .schema(taskSchema)
|
|
759
|
+
* .systemRules(['Use emojis: 🔄 In Progress, ✅ Done'])
|
|
760
|
+
* .uiBlocks((task) => [ui.markdown(`**${task.title}**: ${task.status}`)]);
|
|
761
|
+
* ```
|
|
762
|
+
*
|
|
763
|
+
* @see {@link Presenter} for the full API
|
|
764
|
+
*/
|
|
765
|
+
export function createPresenter(name) {
|
|
766
|
+
return new Presenter(name);
|
|
767
|
+
}
|
|
768
|
+
//# sourceMappingURL=Presenter.js.map
|