@syrin/cli 1.3.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/LICENSE +15 -0
- package/README.md +302 -0
- package/dist/cli/commands/analyse.d.ts +16 -0
- package/dist/cli/commands/analyse.js +61 -0
- package/dist/cli/commands/dev.d.ts +23 -0
- package/dist/cli/commands/dev.js +419 -0
- package/dist/cli/commands/doctor.d.ts +10 -0
- package/dist/cli/commands/doctor.js +195 -0
- package/dist/cli/commands/index.d.ts +12 -0
- package/dist/cli/commands/index.js +12 -0
- package/dist/cli/commands/init.d.ts +16 -0
- package/dist/cli/commands/init.js +90 -0
- package/dist/cli/commands/list.d.ts +15 -0
- package/dist/cli/commands/list.js +50 -0
- package/dist/cli/commands/rollback.d.ts +12 -0
- package/dist/cli/commands/rollback.js +101 -0
- package/dist/cli/commands/test.d.ts +31 -0
- package/dist/cli/commands/test.js +88 -0
- package/dist/cli/commands/update.d.ts +9 -0
- package/dist/cli/commands/update.js +76 -0
- package/dist/cli/index.d.ts +13 -0
- package/dist/cli/index.js +342 -0
- package/dist/cli/prompts/index.d.ts +5 -0
- package/dist/cli/prompts/index.js +5 -0
- package/dist/cli/prompts/init-prompt.d.ts +17 -0
- package/dist/cli/prompts/init-prompt.js +263 -0
- package/dist/cli/utils/command-error-handler.d.ts +14 -0
- package/dist/cli/utils/command-error-handler.js +35 -0
- package/dist/cli/utils/common-types.d.ts +24 -0
- package/dist/cli/utils/common-types.js +6 -0
- package/dist/cli/utils/connection-handler.d.ts +37 -0
- package/dist/cli/utils/connection-handler.js +90 -0
- package/dist/cli/utils/index.d.ts +11 -0
- package/dist/cli/utils/index.js +11 -0
- package/dist/cli/utils/option-parsers.d.ts +41 -0
- package/dist/cli/utils/option-parsers.js +92 -0
- package/dist/cli/utils/output-utils.d.ts +12 -0
- package/dist/cli/utils/output-utils.js +21 -0
- package/dist/cli/utils/transport-resolver.d.ts +33 -0
- package/dist/cli/utils/transport-resolver.js +82 -0
- package/dist/cli/utils/version-banner.d.ts +10 -0
- package/dist/cli/utils/version-banner.js +26 -0
- package/dist/config/env-checker.d.ts +37 -0
- package/dist/config/env-checker.js +136 -0
- package/dist/config/generator.d.ts +19 -0
- package/dist/config/generator.js +196 -0
- package/dist/config/index.d.ts +9 -0
- package/dist/config/index.js +9 -0
- package/dist/config/loader.d.ts +19 -0
- package/dist/config/loader.js +57 -0
- package/dist/config/schema.d.ts +42 -0
- package/dist/config/schema.js +181 -0
- package/dist/config/syrin.template.yaml +127 -0
- package/dist/config/types.d.ts +87 -0
- package/dist/config/types.js +6 -0
- package/dist/constants/app.d.ts +9 -0
- package/dist/constants/app.js +9 -0
- package/dist/constants/commands.d.ts +43 -0
- package/dist/constants/commands.js +43 -0
- package/dist/constants/defaults.d.ts +18 -0
- package/dist/constants/defaults.js +18 -0
- package/dist/constants/env-vars.d.ts +11 -0
- package/dist/constants/env-vars.js +11 -0
- package/dist/constants/icons.d.ts +23 -0
- package/dist/constants/icons.js +23 -0
- package/dist/constants/index.d.ts +17 -0
- package/dist/constants/index.js +17 -0
- package/dist/constants/labels.d.ts +38 -0
- package/dist/constants/labels.js +42 -0
- package/dist/constants/links.d.ts +10 -0
- package/dist/constants/links.js +11 -0
- package/dist/constants/list.d.ts +10 -0
- package/dist/constants/list.js +9 -0
- package/dist/constants/llm.d.ts +26 -0
- package/dist/constants/llm.js +25 -0
- package/dist/constants/messages.d.ts +107 -0
- package/dist/constants/messages.js +138 -0
- package/dist/constants/paths.d.ts +29 -0
- package/dist/constants/paths.js +29 -0
- package/dist/constants/transport.d.ts +9 -0
- package/dist/constants/transport.js +8 -0
- package/dist/events/emitter.d.ts +64 -0
- package/dist/events/emitter.js +142 -0
- package/dist/events/event-type.d.ts +66 -0
- package/dist/events/event-type.js +81 -0
- package/dist/events/payloads/diagnostics.d.ts +24 -0
- package/dist/events/payloads/diagnostics.js +5 -0
- package/dist/events/payloads/index.d.ts +15 -0
- package/dist/events/payloads/index.js +6 -0
- package/dist/events/payloads/llm.d.ts +58 -0
- package/dist/events/payloads/llm.js +6 -0
- package/dist/events/payloads/registry.d.ts +28 -0
- package/dist/events/payloads/registry.js +5 -0
- package/dist/events/payloads/session.d.ts +32 -0
- package/dist/events/payloads/session.js +5 -0
- package/dist/events/payloads/testing.d.ts +17 -0
- package/dist/events/payloads/testing.js +5 -0
- package/dist/events/payloads/tool.d.ts +29 -0
- package/dist/events/payloads/tool.js +5 -0
- package/dist/events/payloads/transport.d.ts +30 -0
- package/dist/events/payloads/transport.js +5 -0
- package/dist/events/payloads/validation.d.ts +37 -0
- package/dist/events/payloads/validation.js +5 -0
- package/dist/events/payloads/workflow.d.ts +45 -0
- package/dist/events/payloads/workflow.js +5 -0
- package/dist/events/store/file-store.d.ts +37 -0
- package/dist/events/store/file-store.js +113 -0
- package/dist/events/store/index.d.ts +7 -0
- package/dist/events/store/index.js +6 -0
- package/dist/events/store/memory-store.d.ts +26 -0
- package/dist/events/store/memory-store.js +39 -0
- package/dist/events/store.d.ts +11 -0
- package/dist/events/store.js +2 -0
- package/dist/events/types.d.ts +14 -0
- package/dist/events/types.js +2 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +30 -0
- package/dist/presentation/analysis-ui.d.ts +24 -0
- package/dist/presentation/analysis-ui.js +158 -0
- package/dist/presentation/dev/chat-ui-types.d.ts +68 -0
- package/dist/presentation/dev/chat-ui-types.js +5 -0
- package/dist/presentation/dev/chat-ui.d.ts +61 -0
- package/dist/presentation/dev/chat-ui.js +714 -0
- package/dist/presentation/dev/components/assistant-message.d.ts +19 -0
- package/dist/presentation/dev/components/assistant-message.js +36 -0
- package/dist/presentation/dev/components/header.d.ts +16 -0
- package/dist/presentation/dev/components/header.js +22 -0
- package/dist/presentation/dev/components/index.d.ts +13 -0
- package/dist/presentation/dev/components/index.js +13 -0
- package/dist/presentation/dev/components/input-panel.d.ts +22 -0
- package/dist/presentation/dev/components/input-panel.js +43 -0
- package/dist/presentation/dev/components/message-component.d.ts +16 -0
- package/dist/presentation/dev/components/message-component.js +51 -0
- package/dist/presentation/dev/components/messages-list.d.ts +24 -0
- package/dist/presentation/dev/components/messages-list.js +48 -0
- package/dist/presentation/dev/components/system-message.d.ts +16 -0
- package/dist/presentation/dev/components/system-message.js +26 -0
- package/dist/presentation/dev/components/user-message.d.ts +21 -0
- package/dist/presentation/dev/components/user-message.js +35 -0
- package/dist/presentation/dev/components/welcome-banner.d.ts +24 -0
- package/dist/presentation/dev/components/welcome-banner.js +146 -0
- package/dist/presentation/dev/goodbye-messages.d.ts +31 -0
- package/dist/presentation/dev/goodbye-messages.js +100 -0
- package/dist/presentation/dev/index.d.ts +5 -0
- package/dist/presentation/dev/index.js +5 -0
- package/dist/presentation/dev/text-wrapper.d.ts +30 -0
- package/dist/presentation/dev/text-wrapper.js +74 -0
- package/dist/presentation/dev-ui.d.ts +33 -0
- package/dist/presentation/dev-ui.js +246 -0
- package/dist/presentation/doctor-ui.d.ts +40 -0
- package/dist/presentation/doctor-ui.js +157 -0
- package/dist/presentation/init-ui.d.ts +14 -0
- package/dist/presentation/init-ui.js +41 -0
- package/dist/presentation/list-ui.d.ts +44 -0
- package/dist/presentation/list-ui.js +139 -0
- package/dist/presentation/test-ui.d.ts +49 -0
- package/dist/presentation/test-ui.js +358 -0
- package/dist/runtime/analysis/analyser.d.ts +14 -0
- package/dist/runtime/analysis/analyser.js +88 -0
- package/dist/runtime/analysis/dependencies.d.ts +10 -0
- package/dist/runtime/analysis/dependencies.js +140 -0
- package/dist/runtime/analysis/index.d.ts +10 -0
- package/dist/runtime/analysis/index.js +10 -0
- package/dist/runtime/analysis/indexer.d.ts +10 -0
- package/dist/runtime/analysis/indexer.js +62 -0
- package/dist/runtime/analysis/loader.d.ts +15 -0
- package/dist/runtime/analysis/loader.js +47 -0
- package/dist/runtime/analysis/normalizer.d.ts +14 -0
- package/dist/runtime/analysis/normalizer.js +184 -0
- package/dist/runtime/analysis/rules/__test-helpers__.d.ts +18 -0
- package/dist/runtime/analysis/rules/__test-helpers__.js +40 -0
- package/dist/runtime/analysis/rules/base.d.ts +38 -0
- package/dist/runtime/analysis/rules/base.js +23 -0
- package/dist/runtime/analysis/rules/error-codes.d.ts +64 -0
- package/dist/runtime/analysis/rules/error-codes.js +73 -0
- package/dist/runtime/analysis/rules/errors/e000-tool-not-found.d.ts +35 -0
- package/dist/runtime/analysis/rules/errors/e000-tool-not-found.js +32 -0
- package/dist/runtime/analysis/rules/errors/e001-missing-output-schema.d.ts +22 -0
- package/dist/runtime/analysis/rules/errors/e001-missing-output-schema.js +30 -0
- package/dist/runtime/analysis/rules/errors/e002-underspecified-input.d.ts +24 -0
- package/dist/runtime/analysis/rules/errors/e002-underspecified-input.js +52 -0
- package/dist/runtime/analysis/rules/errors/e003-type-mismatch.d.ts +23 -0
- package/dist/runtime/analysis/rules/errors/e003-type-mismatch.js +73 -0
- package/dist/runtime/analysis/rules/errors/e004-free-text-propagation.d.ts +23 -0
- package/dist/runtime/analysis/rules/errors/e004-free-text-propagation.js +47 -0
- package/dist/runtime/analysis/rules/errors/e005-tool-ambiguity.d.ts +25 -0
- package/dist/runtime/analysis/rules/errors/e005-tool-ambiguity.js +73 -0
- package/dist/runtime/analysis/rules/errors/e006-param-not-in-description.d.ts +22 -0
- package/dist/runtime/analysis/rules/errors/e006-param-not-in-description.js +57 -0
- package/dist/runtime/analysis/rules/errors/e007-output-not-guaranteed.d.ts +23 -0
- package/dist/runtime/analysis/rules/errors/e007-output-not-guaranteed.js +56 -0
- package/dist/runtime/analysis/rules/errors/e008-circular-dependency.d.ts +22 -0
- package/dist/runtime/analysis/rules/errors/e008-circular-dependency.js +84 -0
- package/dist/runtime/analysis/rules/errors/e009-implicit-user-input.d.ts +23 -0
- package/dist/runtime/analysis/rules/errors/e009-implicit-user-input.js +89 -0
- package/dist/runtime/analysis/rules/errors/e010-non-serializable.d.ts +25 -0
- package/dist/runtime/analysis/rules/errors/e010-non-serializable.js +46 -0
- package/dist/runtime/analysis/rules/errors/e011-missing-tool-description.d.ts +24 -0
- package/dist/runtime/analysis/rules/errors/e011-missing-tool-description.js +33 -0
- package/dist/runtime/analysis/rules/errors/e012-side-effect-detected.d.ts +39 -0
- package/dist/runtime/analysis/rules/errors/e012-side-effect-detected.js +40 -0
- package/dist/runtime/analysis/rules/errors/e013-non-deterministic-output.d.ts +37 -0
- package/dist/runtime/analysis/rules/errors/e013-non-deterministic-output.js +34 -0
- package/dist/runtime/analysis/rules/errors/e013-output-explosion.d.ts +39 -0
- package/dist/runtime/analysis/rules/errors/e013-output-explosion.js +36 -0
- package/dist/runtime/analysis/rules/errors/e014-hidden-dependency.d.ts +42 -0
- package/dist/runtime/analysis/rules/errors/e014-hidden-dependency.js +46 -0
- package/dist/runtime/analysis/rules/errors/e014-output-explosion.d.ts +39 -0
- package/dist/runtime/analysis/rules/errors/e014-output-explosion.js +36 -0
- package/dist/runtime/analysis/rules/errors/e015-hidden-dependency.d.ts +42 -0
- package/dist/runtime/analysis/rules/errors/e015-hidden-dependency.js +46 -0
- package/dist/runtime/analysis/rules/errors/e015-unbounded-execution.d.ts +44 -0
- package/dist/runtime/analysis/rules/errors/e015-unbounded-execution.js +66 -0
- package/dist/runtime/analysis/rules/errors/e016-output-validation-failed.d.ts +43 -0
- package/dist/runtime/analysis/rules/errors/e016-output-validation-failed.js +42 -0
- package/dist/runtime/analysis/rules/errors/e016-unbounded-execution.d.ts +44 -0
- package/dist/runtime/analysis/rules/errors/e016-unbounded-execution.js +66 -0
- package/dist/runtime/analysis/rules/errors/e017-input-validation-failed.d.ts +57 -0
- package/dist/runtime/analysis/rules/errors/e017-input-validation-failed.js +80 -0
- package/dist/runtime/analysis/rules/errors/e017-output-validation-failed.d.ts +43 -0
- package/dist/runtime/analysis/rules/errors/e017-output-validation-failed.js +42 -0
- package/dist/runtime/analysis/rules/errors/e018-input-validation-failed.d.ts +57 -0
- package/dist/runtime/analysis/rules/errors/e018-input-validation-failed.js +80 -0
- package/dist/runtime/analysis/rules/errors/e018-tool-execution-failed.d.ts +38 -0
- package/dist/runtime/analysis/rules/errors/e018-tool-execution-failed.js +37 -0
- package/dist/runtime/analysis/rules/errors/e019-tool-execution-failed.d.ts +38 -0
- package/dist/runtime/analysis/rules/errors/e019-tool-execution-failed.js +37 -0
- package/dist/runtime/analysis/rules/errors/e019-unexpected-test-result.d.ts +65 -0
- package/dist/runtime/analysis/rules/errors/e019-unexpected-test-result.js +109 -0
- package/dist/runtime/analysis/rules/errors/e020-unexpected-test-result.d.ts +65 -0
- package/dist/runtime/analysis/rules/errors/e020-unexpected-test-result.js +109 -0
- package/dist/runtime/analysis/rules/errors/e100-missing-output-schema.d.ts +22 -0
- package/dist/runtime/analysis/rules/errors/e100-missing-output-schema.js +30 -0
- package/dist/runtime/analysis/rules/errors/e101-missing-tool-description.d.ts +24 -0
- package/dist/runtime/analysis/rules/errors/e101-missing-tool-description.js +33 -0
- package/dist/runtime/analysis/rules/errors/e102-underspecified-input.d.ts +24 -0
- package/dist/runtime/analysis/rules/errors/e102-underspecified-input.js +52 -0
- package/dist/runtime/analysis/rules/errors/e103-type-mismatch.d.ts +23 -0
- package/dist/runtime/analysis/rules/errors/e103-type-mismatch.js +72 -0
- package/dist/runtime/analysis/rules/errors/e104-param-not-in-description.d.ts +22 -0
- package/dist/runtime/analysis/rules/errors/e104-param-not-in-description.js +57 -0
- package/dist/runtime/analysis/rules/errors/e105-free-text-propagation.d.ts +23 -0
- package/dist/runtime/analysis/rules/errors/e105-free-text-propagation.js +47 -0
- package/dist/runtime/analysis/rules/errors/e106-output-not-guaranteed.d.ts +23 -0
- package/dist/runtime/analysis/rules/errors/e106-output-not-guaranteed.js +58 -0
- package/dist/runtime/analysis/rules/errors/e107-circular-dependency.d.ts +22 -0
- package/dist/runtime/analysis/rules/errors/e107-circular-dependency.js +84 -0
- package/dist/runtime/analysis/rules/errors/e108-implicit-user-input.d.ts +23 -0
- package/dist/runtime/analysis/rules/errors/e108-implicit-user-input.js +94 -0
- package/dist/runtime/analysis/rules/errors/e109-non-serializable.d.ts +25 -0
- package/dist/runtime/analysis/rules/errors/e109-non-serializable.js +44 -0
- package/dist/runtime/analysis/rules/errors/e110-tool-ambiguity.d.ts +25 -0
- package/dist/runtime/analysis/rules/errors/e110-tool-ambiguity.js +73 -0
- package/dist/runtime/analysis/rules/errors/e200-input-validation-failed.d.ts +57 -0
- package/dist/runtime/analysis/rules/errors/e200-input-validation-failed.js +71 -0
- package/dist/runtime/analysis/rules/errors/e300-output-validation-failed.d.ts +43 -0
- package/dist/runtime/analysis/rules/errors/e300-output-validation-failed.js +44 -0
- package/dist/runtime/analysis/rules/errors/e301-output-explosion.d.ts +39 -0
- package/dist/runtime/analysis/rules/errors/e301-output-explosion.js +36 -0
- package/dist/runtime/analysis/rules/errors/e400-tool-execution-failed.d.ts +38 -0
- package/dist/runtime/analysis/rules/errors/e400-tool-execution-failed.js +37 -0
- package/dist/runtime/analysis/rules/errors/e403-unbounded-execution.d.ts +44 -0
- package/dist/runtime/analysis/rules/errors/e403-unbounded-execution.js +66 -0
- package/dist/runtime/analysis/rules/errors/e500-side-effect-detected.d.ts +39 -0
- package/dist/runtime/analysis/rules/errors/e500-side-effect-detected.js +40 -0
- package/dist/runtime/analysis/rules/errors/e501-hidden-dependency.d.ts +47 -0
- package/dist/runtime/analysis/rules/errors/e501-hidden-dependency.js +46 -0
- package/dist/runtime/analysis/rules/errors/e600-unexpected-test-result.d.ts +65 -0
- package/dist/runtime/analysis/rules/errors/e600-unexpected-test-result.js +109 -0
- package/dist/runtime/analysis/rules/index.d.ts +18 -0
- package/dist/runtime/analysis/rules/index.js +94 -0
- package/dist/runtime/analysis/rules/warnings/w001-implicit-dependency.d.ts +22 -0
- package/dist/runtime/analysis/rules/warnings/w001-implicit-dependency.js +39 -0
- package/dist/runtime/analysis/rules/warnings/w002-free-text-without-normalization.d.ts +24 -0
- package/dist/runtime/analysis/rules/warnings/w002-free-text-without-normalization.js +40 -0
- package/dist/runtime/analysis/rules/warnings/w003-missing-examples.d.ts +22 -0
- package/dist/runtime/analysis/rules/warnings/w003-missing-examples.js +84 -0
- package/dist/runtime/analysis/rules/warnings/w004-overloaded-responsibility.d.ts +23 -0
- package/dist/runtime/analysis/rules/warnings/w004-overloaded-responsibility.js +96 -0
- package/dist/runtime/analysis/rules/warnings/w005-generic-description.d.ts +53 -0
- package/dist/runtime/analysis/rules/warnings/w005-generic-description.js +108 -0
- package/dist/runtime/analysis/rules/warnings/w006-optional-as-required.d.ts +22 -0
- package/dist/runtime/analysis/rules/warnings/w006-optional-as-required.js +44 -0
- package/dist/runtime/analysis/rules/warnings/w007-broad-output-schema.d.ts +23 -0
- package/dist/runtime/analysis/rules/warnings/w007-broad-output-schema.js +37 -0
- package/dist/runtime/analysis/rules/warnings/w008-multiple-entry-points.d.ts +22 -0
- package/dist/runtime/analysis/rules/warnings/w008-multiple-entry-points.js +97 -0
- package/dist/runtime/analysis/rules/warnings/w009-hidden-side-effects.d.ts +23 -0
- package/dist/runtime/analysis/rules/warnings/w009-hidden-side-effects.js +88 -0
- package/dist/runtime/analysis/rules/warnings/w010-output-not-reusable.d.ts +22 -0
- package/dist/runtime/analysis/rules/warnings/w010-output-not-reusable.js +81 -0
- package/dist/runtime/analysis/rules/warnings/w021-weak-schema.d.ts +40 -0
- package/dist/runtime/analysis/rules/warnings/w021-weak-schema.js +32 -0
- package/dist/runtime/analysis/rules/warnings/w022-high-entropy-output.d.ts +39 -0
- package/dist/runtime/analysis/rules/warnings/w022-high-entropy-output.js +36 -0
- package/dist/runtime/analysis/rules/warnings/w023-unstable-defaults.d.ts +38 -0
- package/dist/runtime/analysis/rules/warnings/w023-unstable-defaults.js +36 -0
- package/dist/runtime/analysis/rules/warnings/w100-implicit-dependency.d.ts +22 -0
- package/dist/runtime/analysis/rules/warnings/w100-implicit-dependency.js +89 -0
- package/dist/runtime/analysis/rules/warnings/w101-free-text-without-normalization.d.ts +24 -0
- package/dist/runtime/analysis/rules/warnings/w101-free-text-without-normalization.js +40 -0
- package/dist/runtime/analysis/rules/warnings/w102-missing-examples.d.ts +22 -0
- package/dist/runtime/analysis/rules/warnings/w102-missing-examples.js +76 -0
- package/dist/runtime/analysis/rules/warnings/w103-overloaded-responsibility.d.ts +23 -0
- package/dist/runtime/analysis/rules/warnings/w103-overloaded-responsibility.js +91 -0
- package/dist/runtime/analysis/rules/warnings/w104-generic-description.d.ts +53 -0
- package/dist/runtime/analysis/rules/warnings/w104-generic-description.js +108 -0
- package/dist/runtime/analysis/rules/warnings/w105-optional-as-required.d.ts +22 -0
- package/dist/runtime/analysis/rules/warnings/w105-optional-as-required.js +45 -0
- package/dist/runtime/analysis/rules/warnings/w106-broad-output-schema.d.ts +23 -0
- package/dist/runtime/analysis/rules/warnings/w106-broad-output-schema.js +37 -0
- package/dist/runtime/analysis/rules/warnings/w107-multiple-entry-points.d.ts +22 -0
- package/dist/runtime/analysis/rules/warnings/w107-multiple-entry-points.js +97 -0
- package/dist/runtime/analysis/rules/warnings/w108-hidden-side-effects.d.ts +23 -0
- package/dist/runtime/analysis/rules/warnings/w108-hidden-side-effects.js +94 -0
- package/dist/runtime/analysis/rules/warnings/w109-output-not-reusable.d.ts +22 -0
- package/dist/runtime/analysis/rules/warnings/w109-output-not-reusable.js +63 -0
- package/dist/runtime/analysis/rules/warnings/w110-weak-schema.d.ts +40 -0
- package/dist/runtime/analysis/rules/warnings/w110-weak-schema.js +32 -0
- package/dist/runtime/analysis/rules/warnings/w300-high-entropy-output.d.ts +39 -0
- package/dist/runtime/analysis/rules/warnings/w300-high-entropy-output.js +47 -0
- package/dist/runtime/analysis/rules/warnings/w301-unstable-defaults.d.ts +38 -0
- package/dist/runtime/analysis/rules/warnings/w301-unstable-defaults.js +36 -0
- package/dist/runtime/analysis/strict-mode.d.ts +21 -0
- package/dist/runtime/analysis/strict-mode.js +44 -0
- package/dist/runtime/analysis/types.d.ts +133 -0
- package/dist/runtime/analysis/types.js +6 -0
- package/dist/runtime/analysis/utils.d.ts +19 -0
- package/dist/runtime/analysis/utils.js +21 -0
- package/dist/runtime/dev/data-manager.d.ts +55 -0
- package/dist/runtime/dev/data-manager.js +87 -0
- package/dist/runtime/dev/event-mapper.d.ts +100 -0
- package/dist/runtime/dev/event-mapper.js +400 -0
- package/dist/runtime/dev/formatter.d.ts +94 -0
- package/dist/runtime/dev/formatter.js +236 -0
- package/dist/runtime/dev/index.d.ts +9 -0
- package/dist/runtime/dev/index.js +9 -0
- package/dist/runtime/dev/repl.d.ts +114 -0
- package/dist/runtime/dev/repl.js +310 -0
- package/dist/runtime/dev/session.d.ts +86 -0
- package/dist/runtime/dev/session.js +447 -0
- package/dist/runtime/dev/stack-trace.d.ts +77 -0
- package/dist/runtime/dev/stack-trace.js +286 -0
- package/dist/runtime/dev/types.d.ts +54 -0
- package/dist/runtime/dev/types.js +5 -0
- package/dist/runtime/llm/claude.d.ts +27 -0
- package/dist/runtime/llm/claude.js +150 -0
- package/dist/runtime/llm/factory.d.ts +30 -0
- package/dist/runtime/llm/factory.js +78 -0
- package/dist/runtime/llm/index.d.ts +10 -0
- package/dist/runtime/llm/index.js +10 -0
- package/dist/runtime/llm/ollama.d.ts +45 -0
- package/dist/runtime/llm/ollama.js +449 -0
- package/dist/runtime/llm/openai.d.ts +27 -0
- package/dist/runtime/llm/openai.js +170 -0
- package/dist/runtime/llm/provider.d.ts +32 -0
- package/dist/runtime/llm/provider.js +6 -0
- package/dist/runtime/llm/types.d.ts +55 -0
- package/dist/runtime/llm/types.js +6 -0
- package/dist/runtime/mcp/client/base.d.ts +40 -0
- package/dist/runtime/mcp/client/base.js +157 -0
- package/dist/runtime/mcp/client/manager.d.ts +91 -0
- package/dist/runtime/mcp/client/manager.js +248 -0
- package/dist/runtime/mcp/client/process.d.ts +31 -0
- package/dist/runtime/mcp/client/process.js +82 -0
- package/dist/runtime/mcp/connection.d.ts +63 -0
- package/dist/runtime/mcp/connection.js +449 -0
- package/dist/runtime/mcp/index.d.ts +9 -0
- package/dist/runtime/mcp/index.js +9 -0
- package/dist/runtime/mcp/list.d.ts +50 -0
- package/dist/runtime/mcp/list.js +65 -0
- package/dist/runtime/mcp/stdio-transport.d.ts +23 -0
- package/dist/runtime/mcp/stdio-transport.js +71 -0
- package/dist/runtime/mcp/types.d.ts +85 -0
- package/dist/runtime/mcp/types.js +6 -0
- package/dist/runtime/sandbox/executor.d.ts +102 -0
- package/dist/runtime/sandbox/executor.js +537 -0
- package/dist/runtime/sandbox/index.d.ts +9 -0
- package/dist/runtime/sandbox/index.js +9 -0
- package/dist/runtime/sandbox/io-monitor.d.ts +78 -0
- package/dist/runtime/sandbox/io-monitor.js +98 -0
- package/dist/runtime/sandbox/time-parser.d.ts +19 -0
- package/dist/runtime/sandbox/time-parser.js +67 -0
- package/dist/runtime/sandbox/types.d.ts +58 -0
- package/dist/runtime/sandbox/types.js +23 -0
- package/dist/runtime/test/behavior-observer.d.ts +61 -0
- package/dist/runtime/test/behavior-observer.js +140 -0
- package/dist/runtime/test/contract-loader.d.ts +41 -0
- package/dist/runtime/test/contract-loader.js +158 -0
- package/dist/runtime/test/contract-schema.d.ts +46 -0
- package/dist/runtime/test/contract-schema.js +107 -0
- package/dist/runtime/test/contract-types.d.ts +106 -0
- package/dist/runtime/test/contract-types.js +6 -0
- package/dist/runtime/test/dependency-tracker.d.ts +66 -0
- package/dist/runtime/test/dependency-tracker.js +80 -0
- package/dist/runtime/test/formatters.d.ts +18 -0
- package/dist/runtime/test/formatters.js +172 -0
- package/dist/runtime/test/index.d.ts +12 -0
- package/dist/runtime/test/index.js +13 -0
- package/dist/runtime/test/input-generator.d.ts +33 -0
- package/dist/runtime/test/input-generator.js +498 -0
- package/dist/runtime/test/mcp-root-detector.d.ts +31 -0
- package/dist/runtime/test/mcp-root-detector.js +105 -0
- package/dist/runtime/test/orchestrator.d.ts +131 -0
- package/dist/runtime/test/orchestrator.js +738 -0
- package/dist/runtime/test/output-validator.d.ts +44 -0
- package/dist/runtime/test/output-validator.js +262 -0
- package/dist/runtime/test/retry-tester.d.ts +44 -0
- package/dist/runtime/test/retry-tester.js +103 -0
- package/dist/runtime/test/runner.d.ts +28 -0
- package/dist/runtime/test/runner.js +55 -0
- package/dist/runtime/test/synthetic-input-generator.d.ts +11 -0
- package/dist/runtime/test/synthetic-input-generator.js +154 -0
- package/dist/runtime/test/test-runner.d.ts +28 -0
- package/dist/runtime/test/test-runner.js +55 -0
- package/dist/types/factories.d.ts +16 -0
- package/dist/types/factories.js +43 -0
- package/dist/types/ids.d.ts +16 -0
- package/dist/types/ids.js +2 -0
- package/dist/types/opaque.d.ts +4 -0
- package/dist/types/opaque.js +2 -0
- package/dist/utils/errors.d.ts +92 -0
- package/dist/utils/errors.js +97 -0
- package/dist/utils/gitignore.d.ts +11 -0
- package/dist/utils/gitignore.js +59 -0
- package/dist/utils/json-file-saver.d.ts +17 -0
- package/dist/utils/json-file-saver.js +81 -0
- package/dist/utils/json-formatter.d.ts +63 -0
- package/dist/utils/json-formatter.js +344 -0
- package/dist/utils/logger.d.ts +184 -0
- package/dist/utils/logger.js +330 -0
- package/dist/utils/package-manager.d.ts +30 -0
- package/dist/utils/package-manager.js +157 -0
- package/dist/utils/version-checker.d.ts +47 -0
- package/dist/utils/version-checker.js +167 -0
- package/dist/utils/version-display.d.ts +10 -0
- package/dist/utils/version-display.js +20 -0
- package/package.json +106 -0
|
@@ -0,0 +1,738 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test orchestrator.
|
|
3
|
+
* Coordinates contract loading, sandboxed execution, and rule evaluation.
|
|
4
|
+
*/
|
|
5
|
+
import * as path from 'path';
|
|
6
|
+
import * as fs from 'fs';
|
|
7
|
+
import { loadConfig } from '../../config/loader.js';
|
|
8
|
+
import { loadAllContracts } from './contract-loader.js';
|
|
9
|
+
import { SandboxExecutor, ToolExecutionErrorType } from '../../runtime/sandbox/index.js';
|
|
10
|
+
import { IOMonitor } from '../../runtime/sandbox/index.js';
|
|
11
|
+
import { BehaviorObserver } from './behavior-observer.js';
|
|
12
|
+
import { runContractTests } from './runner.js';
|
|
13
|
+
import { validateOutputStructure } from './output-validator.js';
|
|
14
|
+
import { parseTimeString } from '../../runtime/sandbox/index.js';
|
|
15
|
+
// Error rule imports - these provide diagnostic generation methods
|
|
16
|
+
// Note: Error codes are centralized in ERROR_CODES/ERROR_TYPE_TO_CODE below
|
|
17
|
+
// to maintain a single source of truth. Individual error classes provide
|
|
18
|
+
// rule-specific diagnostic creation via checkWithBehavioralContext methods.
|
|
19
|
+
import { E000ToolNotFound } from '../../runtime/analysis/rules/errors/e000-tool-not-found.js';
|
|
20
|
+
import { E500SideEffectDetected } from '../../runtime/analysis/rules/errors/e500-side-effect-detected.js';
|
|
21
|
+
import { E301OutputExplosion } from '../../runtime/analysis/rules/errors/e301-output-explosion.js';
|
|
22
|
+
import { E403UnboundedExecution } from '../../runtime/analysis/rules/errors/e403-unbounded-execution.js';
|
|
23
|
+
import { E300OutputValidationFailed } from '../../runtime/analysis/rules/errors/e300-output-validation-failed.js';
|
|
24
|
+
import { E200InputValidationFailed } from '../../runtime/analysis/rules/errors/e200-input-validation-failed.js';
|
|
25
|
+
import { E400ToolExecutionFailed } from '../../runtime/analysis/rules/errors/e400-tool-execution-failed.js';
|
|
26
|
+
import { E600UnexpectedTestResult } from '../../runtime/analysis/rules/errors/e600-unexpected-test-result.js';
|
|
27
|
+
// Centralized error code constants - single source of truth for error codes
|
|
28
|
+
import { ERROR_CODES, ERROR_TYPE_TO_CODE, } from '../../runtime/analysis/rules/error-codes.js';
|
|
29
|
+
import { applyStrictMode, computeVerdict, } from '../../runtime/analysis/strict-mode.js';
|
|
30
|
+
import { logger } from '../../utils/logger.js';
|
|
31
|
+
import { ConfigurationError } from '../../utils/errors.js';
|
|
32
|
+
/**
|
|
33
|
+
* Test orchestrator for tool validation.
|
|
34
|
+
*/
|
|
35
|
+
export class TestOrchestrator {
|
|
36
|
+
options;
|
|
37
|
+
constructor(options) {
|
|
38
|
+
this.options = options;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Extract expectedOutputSchema from TestExecutionResult.
|
|
42
|
+
* @param result - Test execution result
|
|
43
|
+
* @returns Expected output schema name, or undefined if not present
|
|
44
|
+
*/
|
|
45
|
+
getExpectedOutputSchema(result) {
|
|
46
|
+
return result.expectedOutputSchema;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Run tool validation tests.
|
|
50
|
+
*/
|
|
51
|
+
async run() {
|
|
52
|
+
const { projectRoot, toolsDir, toolName, strictMode } = this.options;
|
|
53
|
+
// Load configuration
|
|
54
|
+
const config = loadConfig(projectRoot);
|
|
55
|
+
// Determine tools directory (relative to project root)
|
|
56
|
+
const finalToolsDir = toolsDir || config.check?.tools_dir || 'tools';
|
|
57
|
+
const toolsDirPath = path.resolve(projectRoot, finalToolsDir);
|
|
58
|
+
// Determine target directory for loading contracts
|
|
59
|
+
let targetContractsDir = toolsDirPath;
|
|
60
|
+
if (this.options.toolPath) {
|
|
61
|
+
const pathFilter = this.options.toolPath.replace(/^\/+|\/+$/g, ''); // Remove leading/trailing slashes
|
|
62
|
+
const targetPath = path.resolve(toolsDirPath, pathFilter);
|
|
63
|
+
// Verify the path exists
|
|
64
|
+
if (!fs.existsSync(targetPath)) {
|
|
65
|
+
throw new ConfigurationError(`Tool path not found: ${this.options.toolPath} (resolved to: ${targetPath})`);
|
|
66
|
+
}
|
|
67
|
+
if (!fs.statSync(targetPath).isDirectory()) {
|
|
68
|
+
throw new ConfigurationError(`Tool path is not a directory: ${this.options.toolPath} (resolved to: ${targetPath})`);
|
|
69
|
+
}
|
|
70
|
+
// Only load contracts from the specified path
|
|
71
|
+
targetContractsDir = targetPath;
|
|
72
|
+
}
|
|
73
|
+
// Load contracts from target directory (only the specified path if toolPath is provided)
|
|
74
|
+
const parsedContracts = loadAllContracts(targetContractsDir);
|
|
75
|
+
const contracts = parsedContracts;
|
|
76
|
+
// Filter by tool name if specified
|
|
77
|
+
const contractsToTest = toolName
|
|
78
|
+
? contracts.filter(c => c.tool === toolName)
|
|
79
|
+
: contracts;
|
|
80
|
+
if (contractsToTest.length === 0) {
|
|
81
|
+
if (toolName) {
|
|
82
|
+
throw new ConfigurationError(`No contract found for tool: ${toolName}`);
|
|
83
|
+
}
|
|
84
|
+
throw new ConfigurationError(`No tool contracts found in ${toolsDirPath}. Create contract files (e.g., tools/<tool-name>.yaml).`);
|
|
85
|
+
}
|
|
86
|
+
// Get MCP command from config or options
|
|
87
|
+
// For tool testing, we need to spawn the server regardless of transport type
|
|
88
|
+
// (sandboxed execution requires spawning the process)
|
|
89
|
+
const mcpCommand = this.options.mcpCommand || config.script;
|
|
90
|
+
if (!mcpCommand) {
|
|
91
|
+
throw new ConfigurationError('MCP command is required for tool testing. Set script in syrin.yaml or use --mcp-command option.');
|
|
92
|
+
}
|
|
93
|
+
// Initialize sandbox executor first (this starts the MCP server process)
|
|
94
|
+
// Suppress stderr by default, unless user explicitly requests to see errors
|
|
95
|
+
const suppressStderr = this.options.showErrors !== true;
|
|
96
|
+
const sandboxExecutor = new SandboxExecutor({
|
|
97
|
+
timeout: this.options.timeout || config.check?.timeout_ms || 30000,
|
|
98
|
+
memoryLimitMB: this.options.memoryLimitMB || config.check?.memory_limit_mb,
|
|
99
|
+
mcpCommand,
|
|
100
|
+
env: this.options.env,
|
|
101
|
+
projectRoot,
|
|
102
|
+
suppressStderr,
|
|
103
|
+
});
|
|
104
|
+
try {
|
|
105
|
+
// Initialize sandbox (start MCP server process once)
|
|
106
|
+
await sandboxExecutor.initialize();
|
|
107
|
+
// Get available tools from the sandbox executor's client
|
|
108
|
+
// (reuse the same connection instead of creating a new one)
|
|
109
|
+
const client = sandboxExecutor.getClient();
|
|
110
|
+
if (!client) {
|
|
111
|
+
throw new ConfigurationError('Failed to get MCP client from sandbox executor');
|
|
112
|
+
}
|
|
113
|
+
const availableTools = await client.listTools();
|
|
114
|
+
// Create tool schema map
|
|
115
|
+
const toolSchemaMap = new Map(availableTools.tools.map(tool => [
|
|
116
|
+
tool.name,
|
|
117
|
+
{
|
|
118
|
+
inputSchema: tool.inputSchema,
|
|
119
|
+
outputSchema: tool.outputSchema,
|
|
120
|
+
},
|
|
121
|
+
]));
|
|
122
|
+
const toolResults = [];
|
|
123
|
+
const allDiagnostics = [];
|
|
124
|
+
// Test each contract
|
|
125
|
+
for (const contract of contractsToTest) {
|
|
126
|
+
const toolResult = await this.testTool(contract, toolSchemaMap, sandboxExecutor, projectRoot, config);
|
|
127
|
+
toolResults.push(toolResult);
|
|
128
|
+
allDiagnostics.push(...toolResult.diagnostics);
|
|
129
|
+
}
|
|
130
|
+
// Apply strict mode
|
|
131
|
+
const processedDiagnostics = applyStrictMode(allDiagnostics, strictMode || config.check?.strict_mode || false);
|
|
132
|
+
// Compute verdict
|
|
133
|
+
const verdict = computeVerdict(processedDiagnostics, strictMode || config.check?.strict_mode || false);
|
|
134
|
+
const toolsPassed = toolResults.filter(r => r.passed).length;
|
|
135
|
+
const toolsFailed = toolResults.filter(r => !r.passed).length;
|
|
136
|
+
return {
|
|
137
|
+
verdict,
|
|
138
|
+
diagnostics: processedDiagnostics,
|
|
139
|
+
toolResults,
|
|
140
|
+
toolsTested: toolResults.length,
|
|
141
|
+
toolsPassed,
|
|
142
|
+
toolsFailed,
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
finally {
|
|
146
|
+
// Cleanup sandbox (this also closes the MCP connection)
|
|
147
|
+
await sandboxExecutor.cleanup();
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Test a single tool.
|
|
152
|
+
*/
|
|
153
|
+
async testTool(contract, toolSchemaMap, sandboxExecutor, projectRoot, config) {
|
|
154
|
+
const toolName = contract.tool;
|
|
155
|
+
const toolSchema = toolSchemaMap.get(toolName);
|
|
156
|
+
if (!toolSchema) {
|
|
157
|
+
// Get the MCP command being used (from options or config)
|
|
158
|
+
const mcpCommand = this.options.mcpCommand || config.script;
|
|
159
|
+
const scriptName = mcpCommand ? String(mcpCommand) : 'unknown';
|
|
160
|
+
if (!this.options.ci) {
|
|
161
|
+
logger.warn(`Tool "${toolName}" not found in MCP server. Running: ${scriptName}`);
|
|
162
|
+
}
|
|
163
|
+
// Create a diagnostic error for missing tool using E000 rule
|
|
164
|
+
const diagnostics = E000ToolNotFound.checkWithRuntimeContext({
|
|
165
|
+
toolName,
|
|
166
|
+
scriptName,
|
|
167
|
+
});
|
|
168
|
+
const diagnostic = diagnostics[0];
|
|
169
|
+
return {
|
|
170
|
+
toolName,
|
|
171
|
+
contract,
|
|
172
|
+
diagnostics: [diagnostic],
|
|
173
|
+
passed: false,
|
|
174
|
+
summary: {
|
|
175
|
+
totalExecutions: 0,
|
|
176
|
+
successfulExecutions: 0,
|
|
177
|
+
failedExecutions: 0,
|
|
178
|
+
timedOutExecutions: 0,
|
|
179
|
+
},
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
// Create I/O monitor
|
|
183
|
+
const tempDir = sandboxExecutor.getTempDir() || '';
|
|
184
|
+
const ioMonitor = new IOMonitor(tempDir, projectRoot);
|
|
185
|
+
// Create behavior observer
|
|
186
|
+
const behaviorObserver = new BehaviorObserver();
|
|
187
|
+
// Parse per-tool timeout if declared, otherwise use global default
|
|
188
|
+
let toolTimeoutMs;
|
|
189
|
+
if (contract.guarantees?.max_execution_time) {
|
|
190
|
+
try {
|
|
191
|
+
toolTimeoutMs = parseTimeString(contract.guarantees.max_execution_time);
|
|
192
|
+
if (!this.options.ci) {
|
|
193
|
+
logger.info(`Tool "${toolName}" declared max_execution_time: ${contract.guarantees.max_execution_time} (${toolTimeoutMs}ms)`);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
catch (_error) {
|
|
197
|
+
if (!this.options.ci) {
|
|
198
|
+
logger.warn(`Invalid max_execution_time for tool "${toolName}": ${contract.guarantees.max_execution_time}. Using global default.`);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
// Run contract-defined tests
|
|
203
|
+
const contractTestResults = await runContractTests(sandboxExecutor, contract, toolTimeoutMs);
|
|
204
|
+
// All results are from contract tests
|
|
205
|
+
const allResults = contractTestResults;
|
|
206
|
+
// Run behavioral observations
|
|
207
|
+
const sideEffectResult = behaviorObserver.detectSideEffects(ioMonitor, contract);
|
|
208
|
+
const outputSizeResults = behaviorObserver.checkOutputSize(allResults, contract, this.options.maxOutputSizeKB || 50);
|
|
209
|
+
const unboundedResult = behaviorObserver.detectUnboundedExecution(allResults);
|
|
210
|
+
const executionErrorResult = behaviorObserver.detectExecutionErrors(allResults);
|
|
211
|
+
// Run behavioral rules
|
|
212
|
+
const diagnostics = [];
|
|
213
|
+
const testResults = [];
|
|
214
|
+
// Match expectations against actual results
|
|
215
|
+
for (const result of allResults) {
|
|
216
|
+
const expectation = result.expectation;
|
|
217
|
+
// Use discriminated union to check result state
|
|
218
|
+
const hasError = !result.success;
|
|
219
|
+
const hasTimeout = !result.success && result.timedOut === true;
|
|
220
|
+
// Determine actual outcome
|
|
221
|
+
let actualOutcome;
|
|
222
|
+
let actualErrorCode;
|
|
223
|
+
let actualErrorType;
|
|
224
|
+
if (hasTimeout) {
|
|
225
|
+
actualOutcome = 'timeout';
|
|
226
|
+
actualErrorCode = ERROR_CODES.E403;
|
|
227
|
+
actualErrorType = 'timeout';
|
|
228
|
+
}
|
|
229
|
+
else if (hasError && !result.success) {
|
|
230
|
+
actualOutcome = 'error';
|
|
231
|
+
actualErrorCode =
|
|
232
|
+
result.error.errorType === ToolExecutionErrorType.INPUT_VALIDATION
|
|
233
|
+
? ERROR_CODES.E200
|
|
234
|
+
: result.error.errorType ===
|
|
235
|
+
ToolExecutionErrorType.OUTPUT_VALIDATION
|
|
236
|
+
? ERROR_CODES.E300
|
|
237
|
+
: ERROR_CODES.E600;
|
|
238
|
+
// Normalize enum value to expected string format (e.g., 'EXECUTION_ERROR' -> 'execution_error')
|
|
239
|
+
actualErrorType = result.error.errorType.toLowerCase();
|
|
240
|
+
}
|
|
241
|
+
else {
|
|
242
|
+
actualOutcome = 'success';
|
|
243
|
+
}
|
|
244
|
+
// Fix TypeScript: error is guaranteed to exist when actualOutcome is 'error'
|
|
245
|
+
// Determine expected outcome
|
|
246
|
+
// Some behavioral errors are tool-level (side_effect, output_explosion)
|
|
247
|
+
// Others are test-level (unbounded_execution, execution_error)
|
|
248
|
+
const toolLevelBehavioralErrors = ['side_effect', 'output_explosion'];
|
|
249
|
+
const testLevelBehavioralErrors = [
|
|
250
|
+
'unbounded_execution',
|
|
251
|
+
'execution_error',
|
|
252
|
+
];
|
|
253
|
+
const expectedErrorType = expectation?.error?.type;
|
|
254
|
+
const isToolLevelBehavioralError = expectedErrorType &&
|
|
255
|
+
toolLevelBehavioralErrors.includes(expectedErrorType);
|
|
256
|
+
const isTestLevelBehavioralError = expectedErrorType &&
|
|
257
|
+
testLevelBehavioralErrors.includes(expectedErrorType);
|
|
258
|
+
let expectedOutcome;
|
|
259
|
+
if (isToolLevelBehavioralError) {
|
|
260
|
+
// For tool-level behavioral errors (side_effect, output_explosion),
|
|
261
|
+
// the test execution itself should succeed - the error is detected separately at tool level
|
|
262
|
+
expectedOutcome = 'success';
|
|
263
|
+
}
|
|
264
|
+
else if (isTestLevelBehavioralError) {
|
|
265
|
+
// For test-level behavioral errors (unbounded_execution, execution_error),
|
|
266
|
+
// the test execution itself should fail/timeout - that's how the error is detected
|
|
267
|
+
expectedOutcome = 'error';
|
|
268
|
+
}
|
|
269
|
+
else if (expectation?.error) {
|
|
270
|
+
expectedOutcome = 'error';
|
|
271
|
+
}
|
|
272
|
+
else if (expectation?.success === false) {
|
|
273
|
+
expectedOutcome = 'error';
|
|
274
|
+
}
|
|
275
|
+
else {
|
|
276
|
+
expectedOutcome = 'success'; // Default to success if no expectation or success=true
|
|
277
|
+
}
|
|
278
|
+
// Match expectation against actual result
|
|
279
|
+
// For tool-level behavioral errors, test execution should succeed
|
|
280
|
+
// For test-level behavioral errors, test execution should match the error type
|
|
281
|
+
let expectationMatched;
|
|
282
|
+
if (isToolLevelBehavioralError) {
|
|
283
|
+
expectationMatched = actualOutcome === 'success';
|
|
284
|
+
}
|
|
285
|
+
else if (isTestLevelBehavioralError) {
|
|
286
|
+
// For unbounded_execution, expect timeout; for execution_error, expect error
|
|
287
|
+
if (expectedErrorType === 'unbounded_execution') {
|
|
288
|
+
expectationMatched = actualOutcome === 'timeout';
|
|
289
|
+
}
|
|
290
|
+
else if (expectedErrorType === 'execution_error') {
|
|
291
|
+
expectationMatched =
|
|
292
|
+
actualOutcome === 'error' && actualErrorType === 'execution_error';
|
|
293
|
+
}
|
|
294
|
+
else {
|
|
295
|
+
expectationMatched = false;
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
else {
|
|
299
|
+
expectationMatched = this.matchExpectation(expectation, actualOutcome, actualErrorCode, actualErrorType, !result.success ? result.error : undefined);
|
|
300
|
+
}
|
|
301
|
+
// Check if this is a synthetic input (no explicit expectation)
|
|
302
|
+
const isSyntheticInput = result.testName?.startsWith('synthetic_input_') && !expectation;
|
|
303
|
+
testResults.push({
|
|
304
|
+
testName: result.testName,
|
|
305
|
+
passed: expectationMatched,
|
|
306
|
+
expected: expectedOutcome,
|
|
307
|
+
actual: actualOutcome,
|
|
308
|
+
errorCode: actualErrorCode,
|
|
309
|
+
errorType: actualErrorType,
|
|
310
|
+
message: !result.success ? result.error.message : undefined,
|
|
311
|
+
});
|
|
312
|
+
// Only add diagnostics if expectation doesn't match
|
|
313
|
+
// For synthetic inputs without expectations, skip error reporting (they're exploratory)
|
|
314
|
+
if (!expectationMatched && !isSyntheticInput) {
|
|
315
|
+
if (expectedOutcome === 'error' && actualOutcome === 'success') {
|
|
316
|
+
// Expected error but got success
|
|
317
|
+
diagnostics.push(...E600UnexpectedTestResult.checkWithBehavioralContext({
|
|
318
|
+
toolName,
|
|
319
|
+
testName: result.testName || 'unknown',
|
|
320
|
+
testInput: result.testInput,
|
|
321
|
+
expectedOutcome: 'error',
|
|
322
|
+
actualOutcome: 'success',
|
|
323
|
+
expectedErrorType: expectation?.error?.type,
|
|
324
|
+
expectedErrorCode: expectation?.error?.code,
|
|
325
|
+
expectedError: expectation?.error,
|
|
326
|
+
}));
|
|
327
|
+
}
|
|
328
|
+
else if (expectedOutcome === 'success' && actualOutcome === 'error') {
|
|
329
|
+
// Expected success but got error
|
|
330
|
+
if (!result.success) {
|
|
331
|
+
const errorMessage = result.error.message;
|
|
332
|
+
const parsedError = this.parseValidationError(errorMessage);
|
|
333
|
+
// Use appropriate rule based on error type
|
|
334
|
+
if (result.error.errorType === ToolExecutionErrorType.INPUT_VALIDATION) {
|
|
335
|
+
diagnostics.push(...E200InputValidationFailed.checkWithBehavioralContext({
|
|
336
|
+
toolName,
|
|
337
|
+
testName: result.testName,
|
|
338
|
+
testInput: result.testInput,
|
|
339
|
+
error: errorMessage,
|
|
340
|
+
parsedError: parsedError,
|
|
341
|
+
details: {
|
|
342
|
+
expectedOutputSchema: this.getExpectedOutputSchema(result),
|
|
343
|
+
actualError: {
|
|
344
|
+
code: actualErrorCode,
|
|
345
|
+
type: actualErrorType,
|
|
346
|
+
message: errorMessage,
|
|
347
|
+
},
|
|
348
|
+
errorType: result.error.errorType,
|
|
349
|
+
...result.error.context,
|
|
350
|
+
},
|
|
351
|
+
}));
|
|
352
|
+
}
|
|
353
|
+
else if (result.error.errorType ===
|
|
354
|
+
ToolExecutionErrorType.OUTPUT_VALIDATION) {
|
|
355
|
+
diagnostics.push(...E300OutputValidationFailed.checkWithBehavioralContext({
|
|
356
|
+
toolName,
|
|
357
|
+
testName: result.testName,
|
|
358
|
+
testInput: result.testInput,
|
|
359
|
+
expectedOutputSchema: this.getExpectedOutputSchema(result),
|
|
360
|
+
error: errorMessage,
|
|
361
|
+
details: {
|
|
362
|
+
actualError: {
|
|
363
|
+
code: actualErrorCode,
|
|
364
|
+
type: actualErrorType,
|
|
365
|
+
message: errorMessage,
|
|
366
|
+
},
|
|
367
|
+
...result.error.context,
|
|
368
|
+
},
|
|
369
|
+
}));
|
|
370
|
+
}
|
|
371
|
+
else {
|
|
372
|
+
// For other errors, use E019 (execution errors are handled separately in the E019 rule section)
|
|
373
|
+
// This case should rarely happen as E019 is handled separately
|
|
374
|
+
const readableMessage = parsedError.summary || errorMessage;
|
|
375
|
+
diagnostics.push({
|
|
376
|
+
code: ERROR_CODES.E600,
|
|
377
|
+
severity: 'error',
|
|
378
|
+
message: parsedError.field
|
|
379
|
+
? `${parsedError.field}: ${parsedError.message || readableMessage}`
|
|
380
|
+
: readableMessage,
|
|
381
|
+
tool: toolName,
|
|
382
|
+
context: {
|
|
383
|
+
testName: result.testName,
|
|
384
|
+
testInput: result.testInput,
|
|
385
|
+
expectedOutputSchema: this.getExpectedOutputSchema(result),
|
|
386
|
+
expectedResult: 'success',
|
|
387
|
+
actualError: {
|
|
388
|
+
code: actualErrorCode,
|
|
389
|
+
type: actualErrorType,
|
|
390
|
+
message: errorMessage,
|
|
391
|
+
},
|
|
392
|
+
errorType: result.error.errorType,
|
|
393
|
+
...result.error.context,
|
|
394
|
+
},
|
|
395
|
+
});
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
else if (expectedOutcome === 'error' &&
|
|
400
|
+
actualOutcome === 'error' &&
|
|
401
|
+
!result.success) {
|
|
402
|
+
// Expected error but got different error
|
|
403
|
+
const expectedCode = expectation?.error?.code;
|
|
404
|
+
const expectedType = expectation?.error?.type;
|
|
405
|
+
// Check if error type matches (if specified)
|
|
406
|
+
let typeMatches = true;
|
|
407
|
+
if (expectedType && actualErrorType) {
|
|
408
|
+
const expectedTypeLower = String(expectedType).toLowerCase();
|
|
409
|
+
const actualTypeLower = String(actualErrorType).toLowerCase();
|
|
410
|
+
typeMatches =
|
|
411
|
+
actualTypeLower.includes(expectedTypeLower) ||
|
|
412
|
+
expectedTypeLower === actualTypeLower;
|
|
413
|
+
}
|
|
414
|
+
// Check if error code matches (if specified)
|
|
415
|
+
const codeMatches = !expectedCode || actualErrorCode === expectedCode;
|
|
416
|
+
// Check detailed error matching (if specified)
|
|
417
|
+
const detailsMatch = !expectation?.error?.details ||
|
|
418
|
+
this.matchExpectationDetails(expectation.error.details, result.error);
|
|
419
|
+
// If any part doesn't match, report E020
|
|
420
|
+
if (!typeMatches || !codeMatches || !detailsMatch) {
|
|
421
|
+
diagnostics.push(...E600UnexpectedTestResult.checkWithBehavioralContext({
|
|
422
|
+
toolName,
|
|
423
|
+
testName: result.testName || 'unknown',
|
|
424
|
+
testInput: result.testInput,
|
|
425
|
+
expectedOutcome: 'error',
|
|
426
|
+
actualOutcome: 'error',
|
|
427
|
+
expectedErrorType: expectedType,
|
|
428
|
+
expectedErrorCode: expectedCode,
|
|
429
|
+
actualErrorType: actualErrorType,
|
|
430
|
+
actualErrorCode: actualErrorCode,
|
|
431
|
+
expectedError: expectation?.error,
|
|
432
|
+
actualError: {
|
|
433
|
+
code: actualErrorCode,
|
|
434
|
+
type: actualErrorType,
|
|
435
|
+
message: result.error.message,
|
|
436
|
+
},
|
|
437
|
+
}));
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
// E012: Side Effect Detected
|
|
443
|
+
if (sideEffectResult.detected) {
|
|
444
|
+
diagnostics.push(...E500SideEffectDetected.checkWithBehavioralContext({
|
|
445
|
+
toolName,
|
|
446
|
+
sideEffects: sideEffectResult.sideEffects,
|
|
447
|
+
}));
|
|
448
|
+
}
|
|
449
|
+
// E301: Output Explosion
|
|
450
|
+
for (const sizeResult of outputSizeResults) {
|
|
451
|
+
if (sizeResult.exceedsLimit) {
|
|
452
|
+
diagnostics.push(...E301OutputExplosion.checkWithBehavioralContext({
|
|
453
|
+
toolName,
|
|
454
|
+
actualSize: sizeResult.actualSize,
|
|
455
|
+
maxSize: sizeResult.maxSize,
|
|
456
|
+
limitString: sizeResult.limitString,
|
|
457
|
+
}));
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
// E403: Unbounded Execution (timeouts and connection errors only)
|
|
461
|
+
if (unboundedResult.detected) {
|
|
462
|
+
diagnostics.push(...E403UnboundedExecution.checkWithBehavioralContext({
|
|
463
|
+
toolName,
|
|
464
|
+
timedOut: unboundedResult.timedOut,
|
|
465
|
+
declaredTimeout: contract.guarantees?.max_execution_time,
|
|
466
|
+
actualTimeoutMs: toolTimeoutMs,
|
|
467
|
+
errors: unboundedResult.errors.map(e => ({
|
|
468
|
+
message: e.message,
|
|
469
|
+
code: e.name,
|
|
470
|
+
})),
|
|
471
|
+
}));
|
|
472
|
+
}
|
|
473
|
+
// E400: Tool Execution Failed (execution errors, separate from E016)
|
|
474
|
+
if (executionErrorResult.detected) {
|
|
475
|
+
diagnostics.push(...E400ToolExecutionFailed.checkWithBehavioralContext({
|
|
476
|
+
toolName,
|
|
477
|
+
errors: executionErrorResult.errors.map(e => ({
|
|
478
|
+
message: e.message,
|
|
479
|
+
code: e.name,
|
|
480
|
+
})),
|
|
481
|
+
}));
|
|
482
|
+
}
|
|
483
|
+
// Validate output structure (if schema available and test expects success)
|
|
484
|
+
if (toolSchema.outputSchema) {
|
|
485
|
+
for (const result of allResults) {
|
|
486
|
+
if (!result)
|
|
487
|
+
continue;
|
|
488
|
+
// Only validate output if test expects success
|
|
489
|
+
const expectation = result.expectation;
|
|
490
|
+
const expectsSuccess = !expectation?.error && expectation?.success !== false;
|
|
491
|
+
if (result.success && expectsSuccess) {
|
|
492
|
+
// Use test-specific output schema or fall back to contract schema
|
|
493
|
+
const expectedOutputSchema = this.getExpectedOutputSchema(result);
|
|
494
|
+
const outputSchema = expectation?.output_schema
|
|
495
|
+
? this.resolveSchemaByName(expectation.output_schema, toolSchema.outputSchema)
|
|
496
|
+
: expectedOutputSchema
|
|
497
|
+
? this.resolveSchemaByName(expectedOutputSchema, toolSchema.outputSchema)
|
|
498
|
+
: toolSchema.outputSchema;
|
|
499
|
+
const validationResult = validateOutputStructure(result.output, outputSchema || toolSchema.outputSchema);
|
|
500
|
+
if (!validationResult.valid) {
|
|
501
|
+
// Check if this test result already failed expectation matching
|
|
502
|
+
const testResult = testResults.find(tr => tr.testName === result.testName);
|
|
503
|
+
if (!testResult || !testResult.passed) {
|
|
504
|
+
// Output validation failed - this is unexpected for success expectation
|
|
505
|
+
diagnostics.push(...E300OutputValidationFailed.checkWithBehavioralContext({
|
|
506
|
+
toolName,
|
|
507
|
+
testName: result.testName,
|
|
508
|
+
testInput: result.testInput,
|
|
509
|
+
expectedOutputSchema: this.getExpectedOutputSchema(result),
|
|
510
|
+
error: validationResult.error || 'Unknown error',
|
|
511
|
+
details: validationResult.details,
|
|
512
|
+
}));
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
// Compute summary based on test expectations
|
|
519
|
+
const totalExecutions = allResults.length;
|
|
520
|
+
const totalContractTests = testResults.length;
|
|
521
|
+
const passedTests = testResults.filter(tr => tr.passed).length;
|
|
522
|
+
const failedTests = testResults.filter(tr => !tr.passed).length;
|
|
523
|
+
const successfulExecutions = allResults.filter(r => r.success).length;
|
|
524
|
+
const failedExecutions = allResults.filter(r => !r.success).length;
|
|
525
|
+
const timedOutExecutions = allResults.filter(r => !r.success && r.timedOut === true).length;
|
|
526
|
+
// Determine if test passed based on expectations (no unmatched diagnostics)
|
|
527
|
+
// Filter out expected behavioral errors - check if any test expects them
|
|
528
|
+
// Use error type to code mapping from constants
|
|
529
|
+
const errorTypeToCode = ERROR_TYPE_TO_CODE;
|
|
530
|
+
// Collect expected behavioral errors from all test expectations
|
|
531
|
+
const expectedBehavioralErrors = new Set();
|
|
532
|
+
if (contract.tests) {
|
|
533
|
+
for (const test of contract.tests) {
|
|
534
|
+
if (test.expect?.error?.type) {
|
|
535
|
+
const errorType = test.expect.error.type;
|
|
536
|
+
const errorCode = errorTypeToCode[errorType];
|
|
537
|
+
if (errorCode) {
|
|
538
|
+
expectedBehavioralErrors.add(errorCode);
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
// Filter out expected behavioral errors from diagnostics
|
|
544
|
+
// This prevents them from being displayed and counted in the summary
|
|
545
|
+
const filteredDiagnostics = diagnostics.filter(d => !expectedBehavioralErrors.has(d.code || ''));
|
|
546
|
+
const errors = filteredDiagnostics.filter(d => d.severity === 'error');
|
|
547
|
+
const passed = errors.length === 0;
|
|
548
|
+
return {
|
|
549
|
+
toolName,
|
|
550
|
+
contract,
|
|
551
|
+
diagnostics: filteredDiagnostics, // Use filtered diagnostics to exclude expected errors
|
|
552
|
+
passed,
|
|
553
|
+
summary: {
|
|
554
|
+
totalExecutions,
|
|
555
|
+
successfulExecutions,
|
|
556
|
+
failedExecutions,
|
|
557
|
+
timedOutExecutions,
|
|
558
|
+
testsPassed: totalContractTests > 0 ? passedTests : undefined,
|
|
559
|
+
testsFailed: totalContractTests > 0 ? failedTests : undefined,
|
|
560
|
+
},
|
|
561
|
+
};
|
|
562
|
+
}
|
|
563
|
+
/**
|
|
564
|
+
* Parse Pydantic validation error message to extract key information.
|
|
565
|
+
*/
|
|
566
|
+
parseValidationError(errorMessage) {
|
|
567
|
+
const parsed = {};
|
|
568
|
+
// Extract field name (usually on its own line)
|
|
569
|
+
const fieldMatch = errorMessage.match(/^(\w+)\s*$/m);
|
|
570
|
+
if (fieldMatch && fieldMatch[1]) {
|
|
571
|
+
parsed.field = fieldMatch[1];
|
|
572
|
+
}
|
|
573
|
+
// Extract error type and message
|
|
574
|
+
const typeMatch = errorMessage.match(/\[type=([^,]+)/);
|
|
575
|
+
if (typeMatch && typeMatch[1]) {
|
|
576
|
+
parsed.errorType = typeMatch[1];
|
|
577
|
+
}
|
|
578
|
+
// Extract input value and type
|
|
579
|
+
const inputValueMatch = errorMessage.match(/input_value=([^,]+)/);
|
|
580
|
+
if (inputValueMatch && inputValueMatch[1]) {
|
|
581
|
+
parsed.inputValue = inputValueMatch[1].trim();
|
|
582
|
+
}
|
|
583
|
+
const inputTypeMatch = errorMessage.match(/input_type=(\w+)/);
|
|
584
|
+
if (inputTypeMatch && inputTypeMatch[1]) {
|
|
585
|
+
parsed.inputType = inputTypeMatch[1];
|
|
586
|
+
}
|
|
587
|
+
// Build summary based on error type
|
|
588
|
+
if (parsed.errorType === 'missing_argument') {
|
|
589
|
+
parsed.summary = `Missing required field: ${parsed.field || 'unknown'}`;
|
|
590
|
+
parsed.message = `Field "${parsed.field || 'unknown'}" is required but was not provided`;
|
|
591
|
+
}
|
|
592
|
+
else if (parsed.errorType === 'string_type') {
|
|
593
|
+
parsed.summary = `Invalid type for ${parsed.field || 'field'}: expected string, got ${parsed.inputType || 'unknown'}`;
|
|
594
|
+
parsed.message = `Expected string but received ${parsed.inputType || 'unknown type'}`;
|
|
595
|
+
}
|
|
596
|
+
else if (parsed.errorType === 'unexpected_keyword_argument') {
|
|
597
|
+
parsed.summary = `Unexpected field: ${parsed.field || 'unknown'}`;
|
|
598
|
+
parsed.message = `Field "${parsed.field || 'unknown'}" is not allowed in the input schema`;
|
|
599
|
+
}
|
|
600
|
+
else {
|
|
601
|
+
// Generic error
|
|
602
|
+
const firstLine = errorMessage.split('\n')[0];
|
|
603
|
+
parsed.summary = firstLine || errorMessage;
|
|
604
|
+
parsed.message = errorMessage;
|
|
605
|
+
}
|
|
606
|
+
return parsed;
|
|
607
|
+
}
|
|
608
|
+
/**
|
|
609
|
+
* Match actual result against test expectation.
|
|
610
|
+
*/
|
|
611
|
+
matchExpectation(expectation, actualOutcome, actualErrorCode, actualErrorType, error) {
|
|
612
|
+
// No expectation means expect success by default
|
|
613
|
+
if (!expectation) {
|
|
614
|
+
return actualOutcome === 'success';
|
|
615
|
+
}
|
|
616
|
+
// If error expectation is specified
|
|
617
|
+
if (expectation.error) {
|
|
618
|
+
// Must have an error
|
|
619
|
+
if (actualOutcome !== 'error') {
|
|
620
|
+
return false;
|
|
621
|
+
}
|
|
622
|
+
// Match by type first (most important for developer-friendly matching)
|
|
623
|
+
if (expectation.error.type && actualErrorType) {
|
|
624
|
+
const expectedType = String(expectation.error.type).toLowerCase();
|
|
625
|
+
const actualType = String(actualErrorType).toLowerCase();
|
|
626
|
+
// Normalize type names for matching
|
|
627
|
+
const typeMapping = {
|
|
628
|
+
input_validation: ['input_validation'],
|
|
629
|
+
output_validation: ['output_validation'],
|
|
630
|
+
execution_error: ['execution_error', 'unknown'],
|
|
631
|
+
side_effect: ['side_effect'],
|
|
632
|
+
output_explosion: ['output_explosion'],
|
|
633
|
+
unbounded_execution: ['unbounded_execution', 'timeout'],
|
|
634
|
+
};
|
|
635
|
+
const expectedTypes = typeMapping[expectedType] || [expectedType];
|
|
636
|
+
const typeMatches = expectedTypes.some(et => actualType.includes(et) || et === actualType);
|
|
637
|
+
if (!typeMatches) {
|
|
638
|
+
return false;
|
|
639
|
+
}
|
|
640
|
+
}
|
|
641
|
+
// Match error code if specified (optional - for backward compatibility)
|
|
642
|
+
if (expectation.error.code && actualErrorCode) {
|
|
643
|
+
const expectedCode = String(expectation.error.code)
|
|
644
|
+
.trim()
|
|
645
|
+
.toUpperCase();
|
|
646
|
+
const actualCode = String(actualErrorCode).trim().toUpperCase();
|
|
647
|
+
if (expectedCode !== actualCode) {
|
|
648
|
+
return false;
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
// Match error details if specified (most specific matching)
|
|
652
|
+
if (expectation.error.details && error) {
|
|
653
|
+
const detailsMatch = this.matchExpectationDetails(expectation.error.details, error);
|
|
654
|
+
if (!detailsMatch) {
|
|
655
|
+
return false;
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
// If we have type or details, that's sufficient for matching
|
|
659
|
+
// If only code was specified, we already checked it above
|
|
660
|
+
return true;
|
|
661
|
+
}
|
|
662
|
+
// If success is explicitly false, expect error
|
|
663
|
+
if (expectation.success === false) {
|
|
664
|
+
return actualOutcome === 'error';
|
|
665
|
+
}
|
|
666
|
+
// Default: expect success
|
|
667
|
+
return actualOutcome === 'success';
|
|
668
|
+
}
|
|
669
|
+
/**
|
|
670
|
+
* Match expectation details against actual error.
|
|
671
|
+
*/
|
|
672
|
+
matchExpectationDetails(expectedDetails, error) {
|
|
673
|
+
if (!expectedDetails) {
|
|
674
|
+
return true; // No details to match
|
|
675
|
+
}
|
|
676
|
+
const parsedError = this.parseValidationError(error.message);
|
|
677
|
+
// Match error_type if specified
|
|
678
|
+
if (expectedDetails.error_type &&
|
|
679
|
+
expectedDetails.error_type !== parsedError.errorType) {
|
|
680
|
+
return false;
|
|
681
|
+
}
|
|
682
|
+
// Match field if specified
|
|
683
|
+
if (expectedDetails.field && expectedDetails.field !== parsedError.field) {
|
|
684
|
+
return false;
|
|
685
|
+
}
|
|
686
|
+
// Match expected type if specified (pattern match)
|
|
687
|
+
if (expectedDetails.expected) {
|
|
688
|
+
const expectedStr = String(expectedDetails.expected).toLowerCase();
|
|
689
|
+
if (!error.message.toLowerCase().includes(expectedStr)) {
|
|
690
|
+
return false;
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
// Match received type if specified
|
|
694
|
+
if (expectedDetails.received &&
|
|
695
|
+
expectedDetails.received !== parsedError.inputType) {
|
|
696
|
+
return false;
|
|
697
|
+
}
|
|
698
|
+
return true;
|
|
699
|
+
}
|
|
700
|
+
/**
|
|
701
|
+
* Resolve schema by name from JSON Schema $defs.
|
|
702
|
+
*
|
|
703
|
+
* Schema names in contracts are string references to named schemas defined in the
|
|
704
|
+
* tool's schema $defs section (e.g., "Username", "UserResponse").
|
|
705
|
+
*
|
|
706
|
+
* This function looks up the named schema from the root schema's $defs dictionary.
|
|
707
|
+
* If the schema name is not found in $defs, it falls back to the defaultSchema.
|
|
708
|
+
*
|
|
709
|
+
* @param schemaName - Schema name to resolve (e.g., "Username")
|
|
710
|
+
* @param defaultSchema - The root schema containing $defs (e.g., tool outputSchema)
|
|
711
|
+
* @returns The resolved schema from $defs, or defaultSchema if not found
|
|
712
|
+
*/
|
|
713
|
+
resolveSchemaByName(schemaName, defaultSchema) {
|
|
714
|
+
// Check if defaultSchema is an object with $defs
|
|
715
|
+
if (defaultSchema &&
|
|
716
|
+
typeof defaultSchema === 'object' &&
|
|
717
|
+
!Array.isArray(defaultSchema)) {
|
|
718
|
+
const schema = defaultSchema;
|
|
719
|
+
// Look for $defs (JSON Schema 2020-12) or definitions (JSON Schema draft-07)
|
|
720
|
+
const defs = ('$defs' in schema ? schema.$defs : undefined) ||
|
|
721
|
+
('definitions' in schema ? schema.definitions : undefined);
|
|
722
|
+
if (defs && typeof defs === 'object' && !Array.isArray(defs)) {
|
|
723
|
+
const defsDict = defs;
|
|
724
|
+
// Look up the schema by name in $defs
|
|
725
|
+
if (schemaName in defsDict) {
|
|
726
|
+
const resolvedSchema = defsDict[schemaName];
|
|
727
|
+
// Return the resolved schema, merging with any base schema context if needed
|
|
728
|
+
return resolvedSchema;
|
|
729
|
+
}
|
|
730
|
+
}
|
|
731
|
+
}
|
|
732
|
+
// Fallback to defaultSchema if schema name not found in $defs
|
|
733
|
+
// This handles cases where schemaName refers to the root schema itself
|
|
734
|
+
// or when $defs doesn't exist
|
|
735
|
+
return defaultSchema;
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
//# sourceMappingURL=orchestrator.js.map
|