@copilotkit/aimock 1.11.0 → 1.13.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/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/README.md +24 -4
- package/dist/_virtual/_rolldown/runtime.cjs +2 -0
- package/dist/_virtual/_rolldown/runtime.js +29 -0
- package/dist/agui-types.d.cts.map +1 -1
- package/dist/aimock-cli.cjs +16 -0
- package/dist/aimock-cli.cjs.map +1 -1
- package/dist/aimock-cli.d.cts +2 -0
- package/dist/aimock-cli.d.cts.map +1 -1
- package/dist/aimock-cli.d.ts +2 -0
- package/dist/aimock-cli.d.ts.map +1 -1
- package/dist/aimock-cli.js +16 -0
- package/dist/aimock-cli.js.map +1 -1
- package/dist/bedrock-converse.cjs +2 -0
- package/dist/bedrock-converse.cjs.map +1 -1
- package/dist/bedrock-converse.d.cts.map +1 -1
- package/dist/bedrock-converse.d.ts.map +1 -1
- package/dist/bedrock-converse.js +2 -0
- package/dist/bedrock-converse.js.map +1 -1
- package/dist/bedrock.cjs +2 -0
- package/dist/bedrock.cjs.map +1 -1
- package/dist/bedrock.d.cts.map +1 -1
- package/dist/bedrock.d.ts.map +1 -1
- package/dist/bedrock.js +2 -0
- package/dist/bedrock.js.map +1 -1
- package/dist/cohere.cjs +1 -0
- package/dist/cohere.cjs.map +1 -1
- package/dist/cohere.js +1 -0
- package/dist/cohere.js.map +1 -1
- package/dist/config-loader.d.cts.map +1 -1
- package/dist/convert-mockllm.cjs +232 -0
- package/dist/convert-mockllm.cjs.map +1 -0
- package/dist/convert-mockllm.js +230 -0
- package/dist/convert-mockllm.js.map +1 -0
- package/dist/convert-vidaimock.cjs +110 -0
- package/dist/convert-vidaimock.cjs.map +1 -0
- package/dist/convert-vidaimock.js +108 -0
- package/dist/convert-vidaimock.js.map +1 -0
- package/dist/convert.cjs +158 -0
- package/dist/convert.cjs.map +1 -0
- package/dist/convert.d.cts +16 -0
- package/dist/convert.d.cts.map +1 -0
- package/dist/convert.d.ts +16 -0
- package/dist/convert.d.ts.map +1 -0
- package/dist/convert.js +157 -0
- package/dist/convert.js.map +1 -0
- package/dist/embeddings.cjs +2 -1
- package/dist/embeddings.cjs.map +1 -1
- package/dist/embeddings.js +2 -1
- package/dist/embeddings.js.map +1 -1
- package/dist/gemini.cjs +1 -0
- package/dist/gemini.cjs.map +1 -1
- package/dist/gemini.js +1 -0
- package/dist/gemini.js.map +1 -1
- package/dist/helpers.cjs +16 -0
- package/dist/helpers.cjs.map +1 -1
- package/dist/helpers.d.cts +6 -2
- package/dist/helpers.d.cts.map +1 -1
- package/dist/helpers.d.ts +6 -2
- package/dist/helpers.d.ts.map +1 -1
- package/dist/helpers.js +13 -1
- package/dist/helpers.js.map +1 -1
- package/dist/images.cjs +166 -0
- package/dist/images.cjs.map +1 -0
- package/dist/images.d.cts +11 -0
- package/dist/images.d.cts.map +1 -0
- package/dist/images.d.ts +11 -0
- package/dist/images.d.ts.map +1 -0
- package/dist/images.js +166 -0
- package/dist/images.js.map +1 -0
- package/dist/index.cjs +13 -0
- package/dist/index.d.cts +7 -3
- package/dist/index.d.ts +7 -3
- package/dist/index.js +6 -2
- package/dist/jest.cjs +70 -0
- package/dist/jest.cjs.map +1 -0
- package/dist/jest.d.cts +33 -0
- package/dist/jest.d.cts.map +1 -0
- package/dist/jest.d.ts +33 -0
- package/dist/jest.d.ts.map +1 -0
- package/dist/jest.js +67 -0
- package/dist/jest.js.map +1 -0
- package/dist/llmock.cjs +37 -1
- package/dist/llmock.cjs.map +1 -1
- package/dist/llmock.d.cts +5 -1
- package/dist/llmock.d.cts.map +1 -1
- package/dist/llmock.d.ts +5 -1
- package/dist/llmock.d.ts.map +1 -1
- package/dist/llmock.js +37 -1
- package/dist/llmock.js.map +1 -1
- package/dist/messages.cjs +1 -0
- package/dist/messages.cjs.map +1 -1
- package/dist/messages.js +1 -0
- package/dist/messages.js.map +1 -1
- package/dist/node_modules/.pnpm/@vitest_pretty-format@3.2.4/node_modules/@vitest/pretty-format/dist/index.cjs +934 -0
- package/dist/node_modules/.pnpm/@vitest_pretty-format@3.2.4/node_modules/@vitest/pretty-format/dist/index.cjs.map +1 -0
- package/dist/node_modules/.pnpm/@vitest_pretty-format@3.2.4/node_modules/@vitest/pretty-format/dist/index.js +934 -0
- package/dist/node_modules/.pnpm/@vitest_pretty-format@3.2.4/node_modules/@vitest/pretty-format/dist/index.js.map +1 -0
- package/dist/node_modules/.pnpm/@vitest_runner@3.2.4/node_modules/@vitest/runner/dist/chunk-hooks.cjs +1051 -0
- package/dist/node_modules/.pnpm/@vitest_runner@3.2.4/node_modules/@vitest/runner/dist/chunk-hooks.cjs.map +1 -0
- package/dist/node_modules/.pnpm/@vitest_runner@3.2.4/node_modules/@vitest/runner/dist/chunk-hooks.js +1042 -0
- package/dist/node_modules/.pnpm/@vitest_runner@3.2.4/node_modules/@vitest/runner/dist/chunk-hooks.js.map +1 -0
- package/dist/node_modules/.pnpm/@vitest_runner@3.2.4/node_modules/@vitest/runner/dist/index.cjs +1 -0
- package/dist/node_modules/.pnpm/@vitest_runner@3.2.4/node_modules/@vitest/runner/dist/index.js +3 -0
- package/dist/node_modules/.pnpm/@vitest_utils@3.2.4/node_modules/@vitest/utils/dist/chunk-_commonjsHelpers.cjs +96 -0
- package/dist/node_modules/.pnpm/@vitest_utils@3.2.4/node_modules/@vitest/utils/dist/chunk-_commonjsHelpers.cjs.map +1 -0
- package/dist/node_modules/.pnpm/@vitest_utils@3.2.4/node_modules/@vitest/utils/dist/chunk-_commonjsHelpers.js +93 -0
- package/dist/node_modules/.pnpm/@vitest_utils@3.2.4/node_modules/@vitest/utils/dist/chunk-_commonjsHelpers.js.map +1 -0
- package/dist/node_modules/.pnpm/@vitest_utils@3.2.4/node_modules/@vitest/utils/dist/helpers.cjs +49 -0
- package/dist/node_modules/.pnpm/@vitest_utils@3.2.4/node_modules/@vitest/utils/dist/helpers.cjs.map +1 -0
- package/dist/node_modules/.pnpm/@vitest_utils@3.2.4/node_modules/@vitest/utils/dist/helpers.js +43 -0
- package/dist/node_modules/.pnpm/@vitest_utils@3.2.4/node_modules/@vitest/utils/dist/helpers.js.map +1 -0
- package/dist/node_modules/.pnpm/@vitest_utils@3.2.4/node_modules/@vitest/utils/dist/index.cjs +456 -0
- package/dist/node_modules/.pnpm/@vitest_utils@3.2.4/node_modules/@vitest/utils/dist/index.cjs.map +1 -0
- package/dist/node_modules/.pnpm/@vitest_utils@3.2.4/node_modules/@vitest/utils/dist/index.js +456 -0
- package/dist/node_modules/.pnpm/@vitest_utils@3.2.4/node_modules/@vitest/utils/dist/index.js.map +1 -0
- package/dist/node_modules/.pnpm/@vitest_utils@3.2.4/node_modules/@vitest/utils/dist/source-map.cjs +170 -0
- package/dist/node_modules/.pnpm/@vitest_utils@3.2.4/node_modules/@vitest/utils/dist/source-map.cjs.map +1 -0
- package/dist/node_modules/.pnpm/@vitest_utils@3.2.4/node_modules/@vitest/utils/dist/source-map.js +169 -0
- package/dist/node_modules/.pnpm/@vitest_utils@3.2.4/node_modules/@vitest/utils/dist/source-map.js.map +1 -0
- package/dist/node_modules/.pnpm/js-tokens@9.0.1/node_modules/js-tokens/index.cjs +388 -0
- package/dist/node_modules/.pnpm/js-tokens@9.0.1/node_modules/js-tokens/index.cjs.map +1 -0
- package/dist/node_modules/.pnpm/js-tokens@9.0.1/node_modules/js-tokens/index.js +385 -0
- package/dist/node_modules/.pnpm/js-tokens@9.0.1/node_modules/js-tokens/index.js.map +1 -0
- package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/arguments.cjs +12 -0
- package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/arguments.cjs.map +1 -0
- package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/arguments.js +12 -0
- package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/arguments.js.map +1 -0
- package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/array.cjs +17 -0
- package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/array.cjs.map +1 -0
- package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/array.js +17 -0
- package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/array.js.map +1 -0
- package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/bigint.cjs +12 -0
- package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/bigint.cjs.map +1 -0
- package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/bigint.js +12 -0
- package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/bigint.js.map +1 -0
- package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/class.cjs +16 -0
- package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/class.cjs.map +1 -0
- package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/class.js +16 -0
- package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/class.js.map +1 -0
- package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/date.cjs +14 -0
- package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/date.cjs.map +1 -0
- package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/date.js +14 -0
- package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/date.js.map +1 -0
- package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/error.cjs +35 -0
- package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/error.cjs.map +1 -0
- package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/error.js +35 -0
- package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/error.js.map +1 -0
- package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/function.cjs +13 -0
- package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/function.cjs.map +1 -0
- package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/function.js +13 -0
- package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/function.js.map +1 -0
- package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/helpers.cjs +128 -0
- package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/helpers.cjs.map +1 -0
- package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/helpers.js +123 -0
- package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/helpers.js.map +1 -0
- package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/html.cjs +41 -0
- package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/html.cjs.map +1 -0
- package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/html.js +40 -0
- package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/html.js.map +1 -0
- package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/index.cjs +100 -0
- package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/index.cjs.map +1 -0
- package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/index.js +100 -0
- package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/index.js.map +1 -0
- package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/map.cjs +26 -0
- package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/map.cjs.map +1 -0
- package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/map.js +26 -0
- package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/map.js.map +1 -0
- package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/number.cjs +15 -0
- package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/number.cjs.map +1 -0
- package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/number.js +15 -0
- package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/number.js.map +1 -0
- package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/object.cjs +22 -0
- package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/object.cjs.map +1 -0
- package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/object.js +22 -0
- package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/object.js.map +1 -0
- package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/promise.cjs +7 -0
- package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/promise.cjs.map +1 -0
- package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/promise.js +6 -0
- package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/promise.js.map +1 -0
- package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/regexp.cjs +13 -0
- package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/regexp.cjs.map +1 -0
- package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/regexp.js +13 -0
- package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/regexp.js.map +1 -0
- package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/set.cjs +19 -0
- package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/set.cjs.map +1 -0
- package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/set.js +19 -0
- package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/set.js.map +1 -0
- package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/string.cjs +26 -0
- package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/string.cjs.map +1 -0
- package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/string.js +26 -0
- package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/string.js.map +1 -0
- package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/symbol.cjs +10 -0
- package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/symbol.cjs.map +1 -0
- package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/symbol.js +9 -0
- package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/symbol.js.map +1 -0
- package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/typedarray.cjs +31 -0
- package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/typedarray.cjs.map +1 -0
- package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/typedarray.js +31 -0
- package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/typedarray.js.map +1 -0
- package/dist/node_modules/.pnpm/strip-literal@3.1.0/node_modules/strip-literal/dist/index.cjs +52 -0
- package/dist/node_modules/.pnpm/strip-literal@3.1.0/node_modules/strip-literal/dist/index.cjs.map +1 -0
- package/dist/node_modules/.pnpm/strip-literal@3.1.0/node_modules/strip-literal/dist/index.js +52 -0
- package/dist/node_modules/.pnpm/strip-literal@3.1.0/node_modules/strip-literal/dist/index.js.map +1 -0
- package/dist/node_modules/.pnpm/tinyrainbow@2.0.0/node_modules/tinyrainbow/dist/chunk-BVHSVHOK.cjs +83 -0
- package/dist/node_modules/.pnpm/tinyrainbow@2.0.0/node_modules/tinyrainbow/dist/chunk-BVHSVHOK.cjs.map +1 -0
- package/dist/node_modules/.pnpm/tinyrainbow@2.0.0/node_modules/tinyrainbow/dist/chunk-BVHSVHOK.js +82 -0
- package/dist/node_modules/.pnpm/tinyrainbow@2.0.0/node_modules/tinyrainbow/dist/chunk-BVHSVHOK.js.map +1 -0
- package/dist/node_modules/.pnpm/tinyrainbow@2.0.0/node_modules/tinyrainbow/dist/node.cjs +10 -0
- package/dist/node_modules/.pnpm/tinyrainbow@2.0.0/node_modules/tinyrainbow/dist/node.cjs.map +1 -0
- package/dist/node_modules/.pnpm/tinyrainbow@2.0.0/node_modules/tinyrainbow/dist/node.js +10 -0
- package/dist/node_modules/.pnpm/tinyrainbow@2.0.0/node_modules/tinyrainbow/dist/node.js.map +1 -0
- package/dist/ollama.cjs +2 -0
- package/dist/ollama.cjs.map +1 -1
- package/dist/ollama.d.cts.map +1 -1
- package/dist/ollama.d.ts.map +1 -1
- package/dist/ollama.js +2 -0
- package/dist/ollama.js.map +1 -1
- package/dist/recorder.cjs +50 -7
- package/dist/recorder.cjs.map +1 -1
- package/dist/recorder.js +50 -7
- package/dist/recorder.js.map +1 -1
- package/dist/responses.cjs +1 -0
- package/dist/responses.cjs.map +1 -1
- package/dist/responses.js +1 -0
- package/dist/responses.js.map +1 -1
- package/dist/router.cjs +8 -0
- package/dist/router.cjs.map +1 -1
- package/dist/router.d.cts.map +1 -1
- package/dist/router.d.ts.map +1 -1
- package/dist/router.js +9 -0
- package/dist/router.js.map +1 -1
- package/dist/server.cjs +80 -3
- package/dist/server.cjs.map +1 -1
- package/dist/server.d.cts +2 -0
- package/dist/server.d.cts.map +1 -1
- package/dist/server.d.ts +2 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +80 -3
- package/dist/server.js.map +1 -1
- package/dist/speech.cjs +144 -0
- package/dist/speech.cjs.map +1 -0
- package/dist/speech.d.cts +11 -0
- package/dist/speech.d.cts.map +1 -0
- package/dist/speech.d.ts +11 -0
- package/dist/speech.d.ts.map +1 -0
- package/dist/speech.js +144 -0
- package/dist/speech.js.map +1 -0
- package/dist/transcription.cjs +134 -0
- package/dist/transcription.cjs.map +1 -0
- package/dist/transcription.d.cts +11 -0
- package/dist/transcription.d.cts.map +1 -0
- package/dist/transcription.d.ts +11 -0
- package/dist/transcription.d.ts.map +1 -0
- package/dist/transcription.js +134 -0
- package/dist/transcription.js.map +1 -0
- package/dist/types.d.cts +44 -2
- package/dist/types.d.cts.map +1 -1
- package/dist/types.d.ts +44 -2
- package/dist/types.d.ts.map +1 -1
- package/dist/video.cjs +196 -0
- package/dist/video.cjs.map +1 -0
- package/dist/video.d.cts +14 -0
- package/dist/video.d.cts.map +1 -0
- package/dist/video.d.ts +14 -0
- package/dist/video.d.ts.map +1 -0
- package/dist/video.js +195 -0
- package/dist/video.js.map +1 -0
- package/dist/vitest.cjs +80 -0
- package/dist/vitest.cjs.map +1 -0
- package/dist/vitest.d.cts +30 -0
- package/dist/vitest.d.cts.map +1 -0
- package/dist/vitest.d.ts +30 -0
- package/dist/vitest.d.ts.map +1 -0
- package/dist/vitest.js +77 -0
- package/dist/vitest.js.map +1 -0
- package/fixtures/examples/a2a/a2a-config.json +42 -0
- package/fixtures/examples/agui/agui-text-response.json +35 -0
- package/fixtures/examples/chaos/chaos-config.json +10 -0
- package/fixtures/examples/full-suite.json +116 -0
- package/fixtures/examples/llm/embeddings.json +10 -0
- package/fixtures/examples/llm/error-injection.json +15 -0
- package/fixtures/examples/llm/sequential-responses.json +20 -0
- package/fixtures/examples/llm/streaming-physics.json +15 -0
- package/fixtures/examples/mcp/mcp-config.json +26 -0
- package/fixtures/examples/record-replay/record-config.json +11 -0
- package/fixtures/examples/vector/vector-config.json +34 -0
- package/package.json +60 -2
package/dist/convert.cjs
ADDED
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
const require_runtime = require('./_virtual/_rolldown/runtime.cjs');
|
|
2
|
+
const require_convert_vidaimock = require('./convert-vidaimock.cjs');
|
|
3
|
+
const require_convert_mockllm = require('./convert-mockllm.cjs');
|
|
4
|
+
let node_path = require("node:path");
|
|
5
|
+
let node_fs = require("node:fs");
|
|
6
|
+
|
|
7
|
+
//#region src/convert.ts
|
|
8
|
+
/**
|
|
9
|
+
* CLI dispatcher for `aimock convert` subcommands.
|
|
10
|
+
*
|
|
11
|
+
* Delegates to the converter modules in src/convert-vidaimock.ts and
|
|
12
|
+
* src/convert-mockllm.ts.
|
|
13
|
+
*/
|
|
14
|
+
const CONVERT_HELP = `
|
|
15
|
+
Usage: aimock convert <format> <input> [output]
|
|
16
|
+
|
|
17
|
+
Formats:
|
|
18
|
+
vidaimock Convert VidaiMock Tera templates to aimock JSON
|
|
19
|
+
mockllm Convert mock-llm YAML config to aimock JSON
|
|
20
|
+
|
|
21
|
+
Examples:
|
|
22
|
+
aimock convert vidaimock ./templates/ ./fixtures/
|
|
23
|
+
aimock convert mockllm ./config.yaml ./fixtures/converted.json
|
|
24
|
+
`.trim();
|
|
25
|
+
function runConvertCli(deps) {
|
|
26
|
+
const { argv, log, logError, exit } = deps;
|
|
27
|
+
if (argv.length === 0 || argv[0] === "--help" || argv[0] === "-h") {
|
|
28
|
+
if (argv.length === 0) {
|
|
29
|
+
logError(CONVERT_HELP);
|
|
30
|
+
exit(1);
|
|
31
|
+
} else {
|
|
32
|
+
log(CONVERT_HELP);
|
|
33
|
+
exit(0);
|
|
34
|
+
}
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
const format = argv[0];
|
|
38
|
+
const inputArg = argv[1];
|
|
39
|
+
const outputArg = argv[2];
|
|
40
|
+
if (!inputArg) {
|
|
41
|
+
logError(`Error: missing <input> argument.\n\n${CONVERT_HELP}`);
|
|
42
|
+
exit(1);
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
switch (format) {
|
|
46
|
+
case "vidaimock":
|
|
47
|
+
runVidaimockConvert(inputArg, outputArg, {
|
|
48
|
+
log,
|
|
49
|
+
logError,
|
|
50
|
+
exit
|
|
51
|
+
});
|
|
52
|
+
break;
|
|
53
|
+
case "mockllm":
|
|
54
|
+
runMockllmConvert(inputArg, outputArg, {
|
|
55
|
+
log,
|
|
56
|
+
logError,
|
|
57
|
+
exit
|
|
58
|
+
});
|
|
59
|
+
break;
|
|
60
|
+
default:
|
|
61
|
+
logError(`Error: unknown format "${format}".\n\n${CONVERT_HELP}`);
|
|
62
|
+
exit(1);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
function runVidaimockConvert(inputArg, outputArg, io) {
|
|
66
|
+
const inputPath = (0, node_path.resolve)(inputArg);
|
|
67
|
+
const outputPath = outputArg ? (0, node_path.resolve)(outputArg) : null;
|
|
68
|
+
let fixtures;
|
|
69
|
+
try {
|
|
70
|
+
if ((0, node_fs.statSync)(inputPath).isDirectory()) fixtures = require_convert_vidaimock.convertDirectory(inputPath);
|
|
71
|
+
else {
|
|
72
|
+
const single = require_convert_vidaimock.convertFile(inputPath);
|
|
73
|
+
fixtures = single ? [single] : [];
|
|
74
|
+
}
|
|
75
|
+
} catch (err) {
|
|
76
|
+
io.logError(`Error reading input path: ${inputPath}`);
|
|
77
|
+
io.logError(err instanceof Error ? err.message : String(err));
|
|
78
|
+
io.exit(1);
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
if (fixtures.length === 0) {
|
|
82
|
+
io.logError("No fixtures produced — check that the input contains valid VidaiMock templates.");
|
|
83
|
+
io.exit(1);
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
const output = { fixtures };
|
|
87
|
+
const json = JSON.stringify(output, null, 2) + "\n";
|
|
88
|
+
if (outputPath) {
|
|
89
|
+
try {
|
|
90
|
+
(0, node_fs.writeFileSync)(outputPath, json, "utf-8");
|
|
91
|
+
} catch (err) {
|
|
92
|
+
io.logError(`Error writing output: ${err.message}`);
|
|
93
|
+
io.exit(1);
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
io.log(`Wrote ${fixtures.length} fixture(s) to ${outputPath}`);
|
|
97
|
+
} else io.log(json.trimEnd());
|
|
98
|
+
}
|
|
99
|
+
function runMockllmConvert(inputArg, outputArg, io) {
|
|
100
|
+
const inputPath = (0, node_path.resolve)(inputArg);
|
|
101
|
+
const outputPath = outputArg ? (0, node_path.resolve)(outputArg) : null;
|
|
102
|
+
let yamlContent;
|
|
103
|
+
try {
|
|
104
|
+
yamlContent = (0, node_fs.readFileSync)(inputPath, "utf-8");
|
|
105
|
+
} catch (err) {
|
|
106
|
+
io.logError(`Error reading input file: ${err.message}`);
|
|
107
|
+
io.exit(1);
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
const parsed = require_convert_mockllm.parseSimpleYaml(yamlContent);
|
|
111
|
+
if (!parsed || typeof parsed !== "object") {
|
|
112
|
+
io.logError("Error: could not parse YAML config");
|
|
113
|
+
io.exit(1);
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
const result = require_convert_mockllm.convertConfig(parsed);
|
|
117
|
+
const fixtureJson = JSON.stringify({ fixtures: result.fixtures }, null, 2);
|
|
118
|
+
if (outputPath) {
|
|
119
|
+
try {
|
|
120
|
+
(0, node_fs.writeFileSync)(outputPath, fixtureJson + "\n", "utf-8");
|
|
121
|
+
} catch (err) {
|
|
122
|
+
io.logError(`Error writing output: ${err.message}`);
|
|
123
|
+
io.exit(1);
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
io.log(`Wrote fixtures to ${outputPath}`);
|
|
127
|
+
if (result.mcpTools) {
|
|
128
|
+
const configPath = outputPath.endsWith(".json") ? outputPath.replace(/\.json$/, ".aimock.json") : outputPath + ".aimock.json";
|
|
129
|
+
const aimockConfig = {
|
|
130
|
+
llm: { fixtures: outputPath },
|
|
131
|
+
mcp: { tools: result.mcpTools.map((t) => ({
|
|
132
|
+
name: t.name,
|
|
133
|
+
description: t.description ?? "",
|
|
134
|
+
inputSchema: t.inputSchema ?? {},
|
|
135
|
+
result: `Mock result for ${t.name}`
|
|
136
|
+
})) }
|
|
137
|
+
};
|
|
138
|
+
try {
|
|
139
|
+
(0, node_fs.writeFileSync)(configPath, JSON.stringify(aimockConfig, null, 2) + "\n", "utf-8");
|
|
140
|
+
} catch (err) {
|
|
141
|
+
io.logError(`Error writing config: ${err.message}`);
|
|
142
|
+
io.exit(1);
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
io.log(`Wrote aimock config with MCP tools to ${configPath}`);
|
|
146
|
+
}
|
|
147
|
+
} else {
|
|
148
|
+
io.log(fixtureJson);
|
|
149
|
+
if (result.mcpTools) {
|
|
150
|
+
io.log("\n--- MCP Tools (aimock config format) ---");
|
|
151
|
+
io.log(JSON.stringify({ mcp: { tools: result.mcpTools } }, null, 2));
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
//#endregion
|
|
157
|
+
exports.runConvertCli = runConvertCli;
|
|
158
|
+
//# sourceMappingURL=convert.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"convert.cjs","names":["convertDirectory","convertFile","parseSimpleYaml","convertConfig"],"sources":["../src/convert.ts"],"sourcesContent":["/**\n * CLI dispatcher for `aimock convert` subcommands.\n *\n * Delegates to the converter modules in src/convert-vidaimock.ts and\n * src/convert-mockllm.ts.\n */\n\nimport { readFileSync, writeFileSync, statSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport { convertFile, convertDirectory, type AimockFixtureFile } from \"./convert-vidaimock.js\";\nimport { parseSimpleYaml, convertConfig, type MockLLMConfig } from \"./convert-mockllm.js\";\n\nconst CONVERT_HELP = `\nUsage: aimock convert <format> <input> [output]\n\nFormats:\n vidaimock Convert VidaiMock Tera templates to aimock JSON\n mockllm Convert mock-llm YAML config to aimock JSON\n\nExamples:\n aimock convert vidaimock ./templates/ ./fixtures/\n aimock convert mockllm ./config.yaml ./fixtures/converted.json\n`.trim();\n\nexport interface ConvertCliDeps {\n argv: string[];\n log: (msg: string) => void;\n logError: (msg: string) => void;\n exit: (code: number) => void;\n}\n\nexport function runConvertCli(deps: ConvertCliDeps): void {\n const { argv, log, logError, exit } = deps;\n\n if (argv.length === 0 || argv[0] === \"--help\" || argv[0] === \"-h\") {\n if (argv.length === 0) {\n logError(CONVERT_HELP);\n exit(1);\n } else {\n log(CONVERT_HELP);\n exit(0);\n }\n return;\n }\n\n const format = argv[0];\n const inputArg = argv[1];\n const outputArg = argv[2];\n\n if (!inputArg) {\n logError(`Error: missing <input> argument.\\n\\n${CONVERT_HELP}`);\n exit(1);\n return;\n }\n\n switch (format) {\n case \"vidaimock\":\n runVidaimockConvert(inputArg, outputArg, { log, logError, exit });\n break;\n case \"mockllm\":\n runMockllmConvert(inputArg, outputArg, { log, logError, exit });\n break;\n default:\n logError(`Error: unknown format \"${format}\".\\n\\n${CONVERT_HELP}`);\n exit(1);\n }\n}\n\n// ---------------------------------------------------------------------------\n// VidaiMock converter\n// ---------------------------------------------------------------------------\n\nfunction runVidaimockConvert(\n inputArg: string,\n outputArg: string | undefined,\n io: { log: (msg: string) => void; logError: (msg: string) => void; exit: (code: number) => void },\n): void {\n const inputPath = resolve(inputArg);\n const outputPath = outputArg ? resolve(outputArg) : null;\n\n let fixtures: AimockFixtureFile[\"fixtures\"];\n\n try {\n const stat = statSync(inputPath);\n if (stat.isDirectory()) {\n fixtures = convertDirectory(inputPath);\n } else {\n const single = convertFile(inputPath);\n fixtures = single ? [single] : [];\n }\n } catch (err) {\n io.logError(`Error reading input path: ${inputPath}`);\n io.logError(err instanceof Error ? err.message : String(err));\n io.exit(1);\n return;\n }\n\n if (fixtures.length === 0) {\n io.logError(\"No fixtures produced — check that the input contains valid VidaiMock templates.\");\n io.exit(1);\n return;\n }\n\n const output: AimockFixtureFile = { fixtures };\n const json = JSON.stringify(output, null, 2) + \"\\n\";\n\n if (outputPath) {\n try {\n writeFileSync(outputPath, json, \"utf-8\");\n } catch (err) {\n io.logError(`Error writing output: ${(err as Error).message}`);\n io.exit(1);\n return;\n }\n io.log(`Wrote ${fixtures.length} fixture(s) to ${outputPath}`);\n } else {\n io.log(json.trimEnd());\n }\n}\n\n// ---------------------------------------------------------------------------\n// mock-llm converter\n// ---------------------------------------------------------------------------\n\nfunction runMockllmConvert(\n inputArg: string,\n outputArg: string | undefined,\n io: { log: (msg: string) => void; logError: (msg: string) => void; exit: (code: number) => void },\n): void {\n const inputPath = resolve(inputArg);\n const outputPath = outputArg ? resolve(outputArg) : null;\n\n let yamlContent: string;\n try {\n yamlContent = readFileSync(inputPath, \"utf-8\");\n } catch (err) {\n io.logError(`Error reading input file: ${(err as Error).message}`);\n io.exit(1);\n return;\n }\n\n const parsed = parseSimpleYaml(yamlContent) as MockLLMConfig | null;\n if (!parsed || typeof parsed !== \"object\") {\n io.logError(\"Error: could not parse YAML config\");\n io.exit(1);\n return;\n }\n\n const result = convertConfig(parsed);\n const fixtureJson = JSON.stringify({ fixtures: result.fixtures }, null, 2);\n\n if (outputPath) {\n try {\n writeFileSync(outputPath, fixtureJson + \"\\n\", \"utf-8\");\n } catch (err) {\n io.logError(`Error writing output: ${(err as Error).message}`);\n io.exit(1);\n return;\n }\n io.log(`Wrote fixtures to ${outputPath}`);\n\n if (result.mcpTools) {\n const configPath = outputPath.endsWith(\".json\")\n ? outputPath.replace(/\\.json$/, \".aimock.json\")\n : outputPath + \".aimock.json\";\n const aimockConfig = {\n llm: { fixtures: outputPath },\n mcp: {\n tools: result.mcpTools.map((t) => ({\n name: t.name,\n description: t.description ?? \"\",\n inputSchema: t.inputSchema ?? {},\n result: `Mock result for ${t.name}`,\n })),\n },\n };\n try {\n writeFileSync(configPath, JSON.stringify(aimockConfig, null, 2) + \"\\n\", \"utf-8\");\n } catch (err) {\n io.logError(`Error writing config: ${(err as Error).message}`);\n io.exit(1);\n return;\n }\n io.log(`Wrote aimock config with MCP tools to ${configPath}`);\n }\n } else {\n io.log(fixtureJson);\n\n if (result.mcpTools) {\n io.log(\"\\n--- MCP Tools (aimock config format) ---\");\n io.log(JSON.stringify({ mcp: { tools: result.mcpTools } }, null, 2));\n }\n }\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
//#region src/convert.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* CLI dispatcher for `aimock convert` subcommands.
|
|
4
|
+
*
|
|
5
|
+
* Delegates to the converter modules in src/convert-vidaimock.ts and
|
|
6
|
+
* src/convert-mockllm.ts.
|
|
7
|
+
*/
|
|
8
|
+
interface ConvertCliDeps {
|
|
9
|
+
argv: string[];
|
|
10
|
+
log: (msg: string) => void;
|
|
11
|
+
logError: (msg: string) => void;
|
|
12
|
+
exit: (code: number) => void;
|
|
13
|
+
}
|
|
14
|
+
//#endregion
|
|
15
|
+
export { ConvertCliDeps };
|
|
16
|
+
//# sourceMappingURL=convert.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"convert.d.cts","names":[],"sources":["../src/convert.ts"],"sourcesContent":[],"mappings":";;AAwBA;;;;;UAAiB,cAAA"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
//#region src/convert.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* CLI dispatcher for `aimock convert` subcommands.
|
|
4
|
+
*
|
|
5
|
+
* Delegates to the converter modules in src/convert-vidaimock.ts and
|
|
6
|
+
* src/convert-mockllm.ts.
|
|
7
|
+
*/
|
|
8
|
+
interface ConvertCliDeps {
|
|
9
|
+
argv: string[];
|
|
10
|
+
log: (msg: string) => void;
|
|
11
|
+
logError: (msg: string) => void;
|
|
12
|
+
exit: (code: number) => void;
|
|
13
|
+
}
|
|
14
|
+
//#endregion
|
|
15
|
+
export { ConvertCliDeps };
|
|
16
|
+
//# sourceMappingURL=convert.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"convert.d.ts","names":[],"sources":["../src/convert.ts"],"sourcesContent":[],"mappings":";;AAwBA;;;;;UAAiB,cAAA"}
|
package/dist/convert.js
ADDED
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import { convertDirectory, convertFile } from "./convert-vidaimock.js";
|
|
2
|
+
import { convertConfig, parseSimpleYaml } from "./convert-mockllm.js";
|
|
3
|
+
import { resolve } from "node:path";
|
|
4
|
+
import { readFileSync, statSync, writeFileSync } from "node:fs";
|
|
5
|
+
|
|
6
|
+
//#region src/convert.ts
|
|
7
|
+
/**
|
|
8
|
+
* CLI dispatcher for `aimock convert` subcommands.
|
|
9
|
+
*
|
|
10
|
+
* Delegates to the converter modules in src/convert-vidaimock.ts and
|
|
11
|
+
* src/convert-mockllm.ts.
|
|
12
|
+
*/
|
|
13
|
+
const CONVERT_HELP = `
|
|
14
|
+
Usage: aimock convert <format> <input> [output]
|
|
15
|
+
|
|
16
|
+
Formats:
|
|
17
|
+
vidaimock Convert VidaiMock Tera templates to aimock JSON
|
|
18
|
+
mockllm Convert mock-llm YAML config to aimock JSON
|
|
19
|
+
|
|
20
|
+
Examples:
|
|
21
|
+
aimock convert vidaimock ./templates/ ./fixtures/
|
|
22
|
+
aimock convert mockllm ./config.yaml ./fixtures/converted.json
|
|
23
|
+
`.trim();
|
|
24
|
+
function runConvertCli(deps) {
|
|
25
|
+
const { argv, log, logError, exit } = deps;
|
|
26
|
+
if (argv.length === 0 || argv[0] === "--help" || argv[0] === "-h") {
|
|
27
|
+
if (argv.length === 0) {
|
|
28
|
+
logError(CONVERT_HELP);
|
|
29
|
+
exit(1);
|
|
30
|
+
} else {
|
|
31
|
+
log(CONVERT_HELP);
|
|
32
|
+
exit(0);
|
|
33
|
+
}
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
const format = argv[0];
|
|
37
|
+
const inputArg = argv[1];
|
|
38
|
+
const outputArg = argv[2];
|
|
39
|
+
if (!inputArg) {
|
|
40
|
+
logError(`Error: missing <input> argument.\n\n${CONVERT_HELP}`);
|
|
41
|
+
exit(1);
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
switch (format) {
|
|
45
|
+
case "vidaimock":
|
|
46
|
+
runVidaimockConvert(inputArg, outputArg, {
|
|
47
|
+
log,
|
|
48
|
+
logError,
|
|
49
|
+
exit
|
|
50
|
+
});
|
|
51
|
+
break;
|
|
52
|
+
case "mockllm":
|
|
53
|
+
runMockllmConvert(inputArg, outputArg, {
|
|
54
|
+
log,
|
|
55
|
+
logError,
|
|
56
|
+
exit
|
|
57
|
+
});
|
|
58
|
+
break;
|
|
59
|
+
default:
|
|
60
|
+
logError(`Error: unknown format "${format}".\n\n${CONVERT_HELP}`);
|
|
61
|
+
exit(1);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
function runVidaimockConvert(inputArg, outputArg, io) {
|
|
65
|
+
const inputPath = resolve(inputArg);
|
|
66
|
+
const outputPath = outputArg ? resolve(outputArg) : null;
|
|
67
|
+
let fixtures;
|
|
68
|
+
try {
|
|
69
|
+
if (statSync(inputPath).isDirectory()) fixtures = convertDirectory(inputPath);
|
|
70
|
+
else {
|
|
71
|
+
const single = convertFile(inputPath);
|
|
72
|
+
fixtures = single ? [single] : [];
|
|
73
|
+
}
|
|
74
|
+
} catch (err) {
|
|
75
|
+
io.logError(`Error reading input path: ${inputPath}`);
|
|
76
|
+
io.logError(err instanceof Error ? err.message : String(err));
|
|
77
|
+
io.exit(1);
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
if (fixtures.length === 0) {
|
|
81
|
+
io.logError("No fixtures produced — check that the input contains valid VidaiMock templates.");
|
|
82
|
+
io.exit(1);
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
const output = { fixtures };
|
|
86
|
+
const json = JSON.stringify(output, null, 2) + "\n";
|
|
87
|
+
if (outputPath) {
|
|
88
|
+
try {
|
|
89
|
+
writeFileSync(outputPath, json, "utf-8");
|
|
90
|
+
} catch (err) {
|
|
91
|
+
io.logError(`Error writing output: ${err.message}`);
|
|
92
|
+
io.exit(1);
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
io.log(`Wrote ${fixtures.length} fixture(s) to ${outputPath}`);
|
|
96
|
+
} else io.log(json.trimEnd());
|
|
97
|
+
}
|
|
98
|
+
function runMockllmConvert(inputArg, outputArg, io) {
|
|
99
|
+
const inputPath = resolve(inputArg);
|
|
100
|
+
const outputPath = outputArg ? resolve(outputArg) : null;
|
|
101
|
+
let yamlContent;
|
|
102
|
+
try {
|
|
103
|
+
yamlContent = readFileSync(inputPath, "utf-8");
|
|
104
|
+
} catch (err) {
|
|
105
|
+
io.logError(`Error reading input file: ${err.message}`);
|
|
106
|
+
io.exit(1);
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
const parsed = parseSimpleYaml(yamlContent);
|
|
110
|
+
if (!parsed || typeof parsed !== "object") {
|
|
111
|
+
io.logError("Error: could not parse YAML config");
|
|
112
|
+
io.exit(1);
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
const result = convertConfig(parsed);
|
|
116
|
+
const fixtureJson = JSON.stringify({ fixtures: result.fixtures }, null, 2);
|
|
117
|
+
if (outputPath) {
|
|
118
|
+
try {
|
|
119
|
+
writeFileSync(outputPath, fixtureJson + "\n", "utf-8");
|
|
120
|
+
} catch (err) {
|
|
121
|
+
io.logError(`Error writing output: ${err.message}`);
|
|
122
|
+
io.exit(1);
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
io.log(`Wrote fixtures to ${outputPath}`);
|
|
126
|
+
if (result.mcpTools) {
|
|
127
|
+
const configPath = outputPath.endsWith(".json") ? outputPath.replace(/\.json$/, ".aimock.json") : outputPath + ".aimock.json";
|
|
128
|
+
const aimockConfig = {
|
|
129
|
+
llm: { fixtures: outputPath },
|
|
130
|
+
mcp: { tools: result.mcpTools.map((t) => ({
|
|
131
|
+
name: t.name,
|
|
132
|
+
description: t.description ?? "",
|
|
133
|
+
inputSchema: t.inputSchema ?? {},
|
|
134
|
+
result: `Mock result for ${t.name}`
|
|
135
|
+
})) }
|
|
136
|
+
};
|
|
137
|
+
try {
|
|
138
|
+
writeFileSync(configPath, JSON.stringify(aimockConfig, null, 2) + "\n", "utf-8");
|
|
139
|
+
} catch (err) {
|
|
140
|
+
io.logError(`Error writing config: ${err.message}`);
|
|
141
|
+
io.exit(1);
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
io.log(`Wrote aimock config with MCP tools to ${configPath}`);
|
|
145
|
+
}
|
|
146
|
+
} else {
|
|
147
|
+
io.log(fixtureJson);
|
|
148
|
+
if (result.mcpTools) {
|
|
149
|
+
io.log("\n--- MCP Tools (aimock config format) ---");
|
|
150
|
+
io.log(JSON.stringify({ mcp: { tools: result.mcpTools } }, null, 2));
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
//#endregion
|
|
156
|
+
export { runConvertCli };
|
|
157
|
+
//# sourceMappingURL=convert.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"convert.js","names":[],"sources":["../src/convert.ts"],"sourcesContent":["/**\n * CLI dispatcher for `aimock convert` subcommands.\n *\n * Delegates to the converter modules in src/convert-vidaimock.ts and\n * src/convert-mockllm.ts.\n */\n\nimport { readFileSync, writeFileSync, statSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport { convertFile, convertDirectory, type AimockFixtureFile } from \"./convert-vidaimock.js\";\nimport { parseSimpleYaml, convertConfig, type MockLLMConfig } from \"./convert-mockllm.js\";\n\nconst CONVERT_HELP = `\nUsage: aimock convert <format> <input> [output]\n\nFormats:\n vidaimock Convert VidaiMock Tera templates to aimock JSON\n mockllm Convert mock-llm YAML config to aimock JSON\n\nExamples:\n aimock convert vidaimock ./templates/ ./fixtures/\n aimock convert mockllm ./config.yaml ./fixtures/converted.json\n`.trim();\n\nexport interface ConvertCliDeps {\n argv: string[];\n log: (msg: string) => void;\n logError: (msg: string) => void;\n exit: (code: number) => void;\n}\n\nexport function runConvertCli(deps: ConvertCliDeps): void {\n const { argv, log, logError, exit } = deps;\n\n if (argv.length === 0 || argv[0] === \"--help\" || argv[0] === \"-h\") {\n if (argv.length === 0) {\n logError(CONVERT_HELP);\n exit(1);\n } else {\n log(CONVERT_HELP);\n exit(0);\n }\n return;\n }\n\n const format = argv[0];\n const inputArg = argv[1];\n const outputArg = argv[2];\n\n if (!inputArg) {\n logError(`Error: missing <input> argument.\\n\\n${CONVERT_HELP}`);\n exit(1);\n return;\n }\n\n switch (format) {\n case \"vidaimock\":\n runVidaimockConvert(inputArg, outputArg, { log, logError, exit });\n break;\n case \"mockllm\":\n runMockllmConvert(inputArg, outputArg, { log, logError, exit });\n break;\n default:\n logError(`Error: unknown format \"${format}\".\\n\\n${CONVERT_HELP}`);\n exit(1);\n }\n}\n\n// ---------------------------------------------------------------------------\n// VidaiMock converter\n// ---------------------------------------------------------------------------\n\nfunction runVidaimockConvert(\n inputArg: string,\n outputArg: string | undefined,\n io: { log: (msg: string) => void; logError: (msg: string) => void; exit: (code: number) => void },\n): void {\n const inputPath = resolve(inputArg);\n const outputPath = outputArg ? resolve(outputArg) : null;\n\n let fixtures: AimockFixtureFile[\"fixtures\"];\n\n try {\n const stat = statSync(inputPath);\n if (stat.isDirectory()) {\n fixtures = convertDirectory(inputPath);\n } else {\n const single = convertFile(inputPath);\n fixtures = single ? [single] : [];\n }\n } catch (err) {\n io.logError(`Error reading input path: ${inputPath}`);\n io.logError(err instanceof Error ? err.message : String(err));\n io.exit(1);\n return;\n }\n\n if (fixtures.length === 0) {\n io.logError(\"No fixtures produced — check that the input contains valid VidaiMock templates.\");\n io.exit(1);\n return;\n }\n\n const output: AimockFixtureFile = { fixtures };\n const json = JSON.stringify(output, null, 2) + \"\\n\";\n\n if (outputPath) {\n try {\n writeFileSync(outputPath, json, \"utf-8\");\n } catch (err) {\n io.logError(`Error writing output: ${(err as Error).message}`);\n io.exit(1);\n return;\n }\n io.log(`Wrote ${fixtures.length} fixture(s) to ${outputPath}`);\n } else {\n io.log(json.trimEnd());\n }\n}\n\n// ---------------------------------------------------------------------------\n// mock-llm converter\n// ---------------------------------------------------------------------------\n\nfunction runMockllmConvert(\n inputArg: string,\n outputArg: string | undefined,\n io: { log: (msg: string) => void; logError: (msg: string) => void; exit: (code: number) => void },\n): void {\n const inputPath = resolve(inputArg);\n const outputPath = outputArg ? resolve(outputArg) : null;\n\n let yamlContent: string;\n try {\n yamlContent = readFileSync(inputPath, \"utf-8\");\n } catch (err) {\n io.logError(`Error reading input file: ${(err as Error).message}`);\n io.exit(1);\n return;\n }\n\n const parsed = parseSimpleYaml(yamlContent) as MockLLMConfig | null;\n if (!parsed || typeof parsed !== \"object\") {\n io.logError(\"Error: could not parse YAML config\");\n io.exit(1);\n return;\n }\n\n const result = convertConfig(parsed);\n const fixtureJson = JSON.stringify({ fixtures: result.fixtures }, null, 2);\n\n if (outputPath) {\n try {\n writeFileSync(outputPath, fixtureJson + \"\\n\", \"utf-8\");\n } catch (err) {\n io.logError(`Error writing output: ${(err as Error).message}`);\n io.exit(1);\n return;\n }\n io.log(`Wrote fixtures to ${outputPath}`);\n\n if (result.mcpTools) {\n const configPath = outputPath.endsWith(\".json\")\n ? outputPath.replace(/\\.json$/, \".aimock.json\")\n : outputPath + \".aimock.json\";\n const aimockConfig = {\n llm: { fixtures: outputPath },\n mcp: {\n tools: result.mcpTools.map((t) => ({\n name: t.name,\n description: t.description ?? \"\",\n inputSchema: t.inputSchema ?? {},\n result: `Mock result for ${t.name}`,\n })),\n },\n };\n try {\n writeFileSync(configPath, JSON.stringify(aimockConfig, null, 2) + \"\\n\", \"utf-8\");\n } catch (err) {\n io.logError(`Error writing config: ${(err as Error).message}`);\n io.exit(1);\n return;\n }\n io.log(`Wrote aimock config with MCP tools to ${configPath}`);\n }\n } else {\n io.log(fixtureJson);\n\n if (result.mcpTools) {\n io.log(\"\\n--- MCP Tools (aimock config format) ---\");\n io.log(JSON.stringify({ mcp: { tools: result.mcpTools } }, null, 2));\n }\n }\n}\n"],"mappings":"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"}
|
package/dist/embeddings.cjs
CHANGED
|
@@ -34,7 +34,8 @@ async function handleEmbeddings(req, res, raw, fixtures, journal, defaults, setC
|
|
|
34
34
|
const syntheticReq = {
|
|
35
35
|
model: embeddingReq.model,
|
|
36
36
|
messages: [],
|
|
37
|
-
embeddingInput: combinedInput
|
|
37
|
+
embeddingInput: combinedInput,
|
|
38
|
+
_endpointType: "embedding"
|
|
38
39
|
};
|
|
39
40
|
const testId = require_helpers.getTestId(req);
|
|
40
41
|
const fixture = require_router.matchFixture(fixtures, syntheticReq, journal.getFixtureMatchCountsForTest(testId), defaults.requestTransform);
|
package/dist/embeddings.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"embeddings.cjs","names":["flattenHeaders","getTestId","matchFixture","applyChaos","isErrorResponse","isEmbeddingResponse","buildEmbeddingResponse","proxyAndRecord","generateDeterministicEmbedding"],"sources":["../src/embeddings.ts"],"sourcesContent":["/**\n * OpenAI Embeddings API support for LLMock.\n *\n * Handles POST /v1/embeddings requests. Matches fixtures using the `inputText`\n * field, and falls back to generating a deterministic embedding from the input\n * text hash when no fixture matches.\n */\n\nimport type * as http from \"node:http\";\nimport type { ChatCompletionRequest, Fixture, HandlerDefaults } from \"./types.js\";\nimport {\n isEmbeddingResponse,\n isErrorResponse,\n generateDeterministicEmbedding,\n buildEmbeddingResponse,\n flattenHeaders,\n getTestId,\n} from \"./helpers.js\";\nimport { matchFixture } from \"./router.js\";\nimport { writeErrorResponse } from \"./sse-writer.js\";\nimport type { Journal } from \"./journal.js\";\nimport { applyChaos } from \"./chaos.js\";\nimport { proxyAndRecord } from \"./recorder.js\";\n\n// ─── Embeddings API request types ──────────────────────────────────────────\n\ninterface EmbeddingRequest {\n input: string | string[];\n model: string;\n encoding_format?: \"float\" | \"base64\";\n dimensions?: number;\n [key: string]: unknown;\n}\n\n// ─── Request handler ───────────────────────────────────────────────────────\n\nexport async function handleEmbeddings(\n req: http.IncomingMessage,\n res: http.ServerResponse,\n raw: string,\n fixtures: Fixture[],\n journal: Journal,\n defaults: HandlerDefaults,\n setCorsHeaders: (res: http.ServerResponse) => void,\n): Promise<void> {\n const { logger } = defaults;\n setCorsHeaders(res);\n\n let embeddingReq: EmbeddingRequest;\n try {\n embeddingReq = JSON.parse(raw) as EmbeddingRequest;\n } catch {\n journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v1/embeddings\",\n headers: flattenHeaders(req.headers),\n body: null,\n response: { status: 400, fixture: null },\n });\n writeErrorResponse(\n res,\n 400,\n JSON.stringify({\n error: {\n message: \"Malformed JSON\",\n type: \"invalid_request_error\",\n code: \"invalid_json\",\n },\n }),\n );\n return;\n }\n\n // Normalize input to array of strings\n const inputs: string[] = Array.isArray(embeddingReq.input)\n ? embeddingReq.input\n : [embeddingReq.input];\n\n // Concatenate all inputs for matching purposes\n const combinedInput = inputs.join(\" \");\n\n // Build a synthetic ChatCompletionRequest for the fixture router.\n // We attach `embeddingInput` so the router's inputText matching can use it.\n const syntheticReq: ChatCompletionRequest = {\n model: embeddingReq.model,\n messages: [],\n embeddingInput: combinedInput,\n };\n\n const testId = getTestId(req);\n const fixture = matchFixture(\n fixtures,\n syntheticReq,\n journal.getFixtureMatchCountsForTest(testId),\n defaults.requestTransform,\n );\n\n if (fixture) {\n journal.incrementFixtureMatchCount(fixture, fixtures, testId);\n }\n\n if (\n applyChaos(\n res,\n fixture,\n defaults.chaos,\n req.headers,\n journal,\n {\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v1/embeddings\",\n headers: flattenHeaders(req.headers),\n body: syntheticReq,\n },\n defaults.registry,\n defaults.logger,\n )\n )\n return;\n\n if (fixture) {\n const response = fixture.response;\n\n // Error response\n if (isErrorResponse(response)) {\n const status = response.status ?? 500;\n journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v1/embeddings\",\n headers: flattenHeaders(req.headers),\n body: syntheticReq,\n response: { status, fixture },\n });\n writeErrorResponse(res, status, JSON.stringify(response));\n return;\n }\n\n // Embedding response — use the fixture's embedding for each input\n if (isEmbeddingResponse(response)) {\n journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v1/embeddings\",\n headers: flattenHeaders(req.headers),\n body: syntheticReq,\n response: { status: 200, fixture },\n });\n const embeddings = inputs.map(() => [...response.embedding]);\n const body = buildEmbeddingResponse(embeddings, embeddingReq.model);\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify(body));\n return;\n }\n\n // Fixture matched but response type is not compatible with embeddings\n journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v1/embeddings\",\n headers: flattenHeaders(req.headers),\n body: syntheticReq,\n response: { status: 500, fixture },\n });\n writeErrorResponse(\n res,\n 500,\n JSON.stringify({\n error: {\n message:\n \"Fixture response did not match any known embedding type (must have embedding or error)\",\n type: \"server_error\",\n },\n }),\n );\n return;\n }\n\n // No fixture match — try record-and-replay proxy if configured\n if (defaults.record) {\n const proxied = await proxyAndRecord(\n req,\n res,\n syntheticReq,\n \"openai\",\n req.url ?? \"/v1/embeddings\",\n fixtures,\n defaults,\n raw,\n );\n if (proxied) {\n journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v1/embeddings\",\n headers: flattenHeaders(req.headers),\n body: syntheticReq,\n response: { status: res.statusCode ?? 200, fixture: null },\n });\n return;\n }\n }\n\n if (defaults.strict) {\n logger.error(\n `STRICT: No fixture matched for ${req.method ?? \"POST\"} ${req.url ?? \"/v1/embeddings\"}`,\n );\n journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v1/embeddings\",\n headers: flattenHeaders(req.headers),\n body: syntheticReq,\n response: { status: 503, fixture: null },\n });\n writeErrorResponse(\n res,\n 503,\n JSON.stringify({\n error: {\n message: \"Strict mode: no fixture matched\",\n type: \"invalid_request_error\",\n code: \"no_fixture_match\",\n },\n }),\n );\n return;\n }\n\n // No fixture match — generate deterministic embeddings from input text\n logger.warn(\n `No embedding fixture matched for \"${combinedInput.slice(0, 80)}\" — returning deterministic fallback`,\n );\n const dimensions = embeddingReq.dimensions ?? 1536;\n const embeddings = inputs.map((input) => generateDeterministicEmbedding(input, dimensions));\n\n journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v1/embeddings\",\n headers: flattenHeaders(req.headers),\n body: syntheticReq,\n response: { status: 200, fixture: null },\n });\n\n const body = buildEmbeddingResponse(embeddings, embeddingReq.model);\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify(body));\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"embeddings.cjs","names":["flattenHeaders","getTestId","matchFixture","applyChaos","isErrorResponse","isEmbeddingResponse","buildEmbeddingResponse","proxyAndRecord","generateDeterministicEmbedding"],"sources":["../src/embeddings.ts"],"sourcesContent":["/**\n * OpenAI Embeddings API support for LLMock.\n *\n * Handles POST /v1/embeddings requests. Matches fixtures using the `inputText`\n * field, and falls back to generating a deterministic embedding from the input\n * text hash when no fixture matches.\n */\n\nimport type * as http from \"node:http\";\nimport type { ChatCompletionRequest, Fixture, HandlerDefaults } from \"./types.js\";\nimport {\n isEmbeddingResponse,\n isErrorResponse,\n generateDeterministicEmbedding,\n buildEmbeddingResponse,\n flattenHeaders,\n getTestId,\n} from \"./helpers.js\";\nimport { matchFixture } from \"./router.js\";\nimport { writeErrorResponse } from \"./sse-writer.js\";\nimport type { Journal } from \"./journal.js\";\nimport { applyChaos } from \"./chaos.js\";\nimport { proxyAndRecord } from \"./recorder.js\";\n\n// ─── Embeddings API request types ──────────────────────────────────────────\n\ninterface EmbeddingRequest {\n input: string | string[];\n model: string;\n encoding_format?: \"float\" | \"base64\";\n dimensions?: number;\n [key: string]: unknown;\n}\n\n// ─── Request handler ───────────────────────────────────────────────────────\n\nexport async function handleEmbeddings(\n req: http.IncomingMessage,\n res: http.ServerResponse,\n raw: string,\n fixtures: Fixture[],\n journal: Journal,\n defaults: HandlerDefaults,\n setCorsHeaders: (res: http.ServerResponse) => void,\n): Promise<void> {\n const { logger } = defaults;\n setCorsHeaders(res);\n\n let embeddingReq: EmbeddingRequest;\n try {\n embeddingReq = JSON.parse(raw) as EmbeddingRequest;\n } catch {\n journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v1/embeddings\",\n headers: flattenHeaders(req.headers),\n body: null,\n response: { status: 400, fixture: null },\n });\n writeErrorResponse(\n res,\n 400,\n JSON.stringify({\n error: {\n message: \"Malformed JSON\",\n type: \"invalid_request_error\",\n code: \"invalid_json\",\n },\n }),\n );\n return;\n }\n\n // Normalize input to array of strings\n const inputs: string[] = Array.isArray(embeddingReq.input)\n ? embeddingReq.input\n : [embeddingReq.input];\n\n // Concatenate all inputs for matching purposes\n const combinedInput = inputs.join(\" \");\n\n // Build a synthetic ChatCompletionRequest for the fixture router.\n // We attach `embeddingInput` so the router's inputText matching can use it.\n const syntheticReq: ChatCompletionRequest = {\n model: embeddingReq.model,\n messages: [],\n embeddingInput: combinedInput,\n _endpointType: \"embedding\",\n };\n\n const testId = getTestId(req);\n const fixture = matchFixture(\n fixtures,\n syntheticReq,\n journal.getFixtureMatchCountsForTest(testId),\n defaults.requestTransform,\n );\n\n if (fixture) {\n journal.incrementFixtureMatchCount(fixture, fixtures, testId);\n }\n\n if (\n applyChaos(\n res,\n fixture,\n defaults.chaos,\n req.headers,\n journal,\n {\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v1/embeddings\",\n headers: flattenHeaders(req.headers),\n body: syntheticReq,\n },\n defaults.registry,\n defaults.logger,\n )\n )\n return;\n\n if (fixture) {\n const response = fixture.response;\n\n // Error response\n if (isErrorResponse(response)) {\n const status = response.status ?? 500;\n journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v1/embeddings\",\n headers: flattenHeaders(req.headers),\n body: syntheticReq,\n response: { status, fixture },\n });\n writeErrorResponse(res, status, JSON.stringify(response));\n return;\n }\n\n // Embedding response — use the fixture's embedding for each input\n if (isEmbeddingResponse(response)) {\n journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v1/embeddings\",\n headers: flattenHeaders(req.headers),\n body: syntheticReq,\n response: { status: 200, fixture },\n });\n const embeddings = inputs.map(() => [...response.embedding]);\n const body = buildEmbeddingResponse(embeddings, embeddingReq.model);\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify(body));\n return;\n }\n\n // Fixture matched but response type is not compatible with embeddings\n journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v1/embeddings\",\n headers: flattenHeaders(req.headers),\n body: syntheticReq,\n response: { status: 500, fixture },\n });\n writeErrorResponse(\n res,\n 500,\n JSON.stringify({\n error: {\n message:\n \"Fixture response did not match any known embedding type (must have embedding or error)\",\n type: \"server_error\",\n },\n }),\n );\n return;\n }\n\n // No fixture match — try record-and-replay proxy if configured\n if (defaults.record) {\n const proxied = await proxyAndRecord(\n req,\n res,\n syntheticReq,\n \"openai\",\n req.url ?? \"/v1/embeddings\",\n fixtures,\n defaults,\n raw,\n );\n if (proxied) {\n journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v1/embeddings\",\n headers: flattenHeaders(req.headers),\n body: syntheticReq,\n response: { status: res.statusCode ?? 200, fixture: null },\n });\n return;\n }\n }\n\n if (defaults.strict) {\n logger.error(\n `STRICT: No fixture matched for ${req.method ?? \"POST\"} ${req.url ?? \"/v1/embeddings\"}`,\n );\n journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v1/embeddings\",\n headers: flattenHeaders(req.headers),\n body: syntheticReq,\n response: { status: 503, fixture: null },\n });\n writeErrorResponse(\n res,\n 503,\n JSON.stringify({\n error: {\n message: \"Strict mode: no fixture matched\",\n type: \"invalid_request_error\",\n code: \"no_fixture_match\",\n },\n }),\n );\n return;\n }\n\n // No fixture match — generate deterministic embeddings from input text\n logger.warn(\n `No embedding fixture matched for \"${combinedInput.slice(0, 80)}\" — returning deterministic fallback`,\n );\n const dimensions = embeddingReq.dimensions ?? 1536;\n const embeddings = inputs.map((input) => generateDeterministicEmbedding(input, dimensions));\n\n journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v1/embeddings\",\n headers: flattenHeaders(req.headers),\n body: syntheticReq,\n response: { status: 200, fixture: null },\n });\n\n const body = buildEmbeddingResponse(embeddings, embeddingReq.model);\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify(body));\n}\n"],"mappings":"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"}
|
package/dist/embeddings.js
CHANGED
|
@@ -34,7 +34,8 @@ async function handleEmbeddings(req, res, raw, fixtures, journal, defaults, setC
|
|
|
34
34
|
const syntheticReq = {
|
|
35
35
|
model: embeddingReq.model,
|
|
36
36
|
messages: [],
|
|
37
|
-
embeddingInput: combinedInput
|
|
37
|
+
embeddingInput: combinedInput,
|
|
38
|
+
_endpointType: "embedding"
|
|
38
39
|
};
|
|
39
40
|
const testId = getTestId(req);
|
|
40
41
|
const fixture = matchFixture(fixtures, syntheticReq, journal.getFixtureMatchCountsForTest(testId), defaults.requestTransform);
|
package/dist/embeddings.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"embeddings.js","names":[],"sources":["../src/embeddings.ts"],"sourcesContent":["/**\n * OpenAI Embeddings API support for LLMock.\n *\n * Handles POST /v1/embeddings requests. Matches fixtures using the `inputText`\n * field, and falls back to generating a deterministic embedding from the input\n * text hash when no fixture matches.\n */\n\nimport type * as http from \"node:http\";\nimport type { ChatCompletionRequest, Fixture, HandlerDefaults } from \"./types.js\";\nimport {\n isEmbeddingResponse,\n isErrorResponse,\n generateDeterministicEmbedding,\n buildEmbeddingResponse,\n flattenHeaders,\n getTestId,\n} from \"./helpers.js\";\nimport { matchFixture } from \"./router.js\";\nimport { writeErrorResponse } from \"./sse-writer.js\";\nimport type { Journal } from \"./journal.js\";\nimport { applyChaos } from \"./chaos.js\";\nimport { proxyAndRecord } from \"./recorder.js\";\n\n// ─── Embeddings API request types ──────────────────────────────────────────\n\ninterface EmbeddingRequest {\n input: string | string[];\n model: string;\n encoding_format?: \"float\" | \"base64\";\n dimensions?: number;\n [key: string]: unknown;\n}\n\n// ─── Request handler ───────────────────────────────────────────────────────\n\nexport async function handleEmbeddings(\n req: http.IncomingMessage,\n res: http.ServerResponse,\n raw: string,\n fixtures: Fixture[],\n journal: Journal,\n defaults: HandlerDefaults,\n setCorsHeaders: (res: http.ServerResponse) => void,\n): Promise<void> {\n const { logger } = defaults;\n setCorsHeaders(res);\n\n let embeddingReq: EmbeddingRequest;\n try {\n embeddingReq = JSON.parse(raw) as EmbeddingRequest;\n } catch {\n journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v1/embeddings\",\n headers: flattenHeaders(req.headers),\n body: null,\n response: { status: 400, fixture: null },\n });\n writeErrorResponse(\n res,\n 400,\n JSON.stringify({\n error: {\n message: \"Malformed JSON\",\n type: \"invalid_request_error\",\n code: \"invalid_json\",\n },\n }),\n );\n return;\n }\n\n // Normalize input to array of strings\n const inputs: string[] = Array.isArray(embeddingReq.input)\n ? embeddingReq.input\n : [embeddingReq.input];\n\n // Concatenate all inputs for matching purposes\n const combinedInput = inputs.join(\" \");\n\n // Build a synthetic ChatCompletionRequest for the fixture router.\n // We attach `embeddingInput` so the router's inputText matching can use it.\n const syntheticReq: ChatCompletionRequest = {\n model: embeddingReq.model,\n messages: [],\n embeddingInput: combinedInput,\n };\n\n const testId = getTestId(req);\n const fixture = matchFixture(\n fixtures,\n syntheticReq,\n journal.getFixtureMatchCountsForTest(testId),\n defaults.requestTransform,\n );\n\n if (fixture) {\n journal.incrementFixtureMatchCount(fixture, fixtures, testId);\n }\n\n if (\n applyChaos(\n res,\n fixture,\n defaults.chaos,\n req.headers,\n journal,\n {\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v1/embeddings\",\n headers: flattenHeaders(req.headers),\n body: syntheticReq,\n },\n defaults.registry,\n defaults.logger,\n )\n )\n return;\n\n if (fixture) {\n const response = fixture.response;\n\n // Error response\n if (isErrorResponse(response)) {\n const status = response.status ?? 500;\n journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v1/embeddings\",\n headers: flattenHeaders(req.headers),\n body: syntheticReq,\n response: { status, fixture },\n });\n writeErrorResponse(res, status, JSON.stringify(response));\n return;\n }\n\n // Embedding response — use the fixture's embedding for each input\n if (isEmbeddingResponse(response)) {\n journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v1/embeddings\",\n headers: flattenHeaders(req.headers),\n body: syntheticReq,\n response: { status: 200, fixture },\n });\n const embeddings = inputs.map(() => [...response.embedding]);\n const body = buildEmbeddingResponse(embeddings, embeddingReq.model);\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify(body));\n return;\n }\n\n // Fixture matched but response type is not compatible with embeddings\n journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v1/embeddings\",\n headers: flattenHeaders(req.headers),\n body: syntheticReq,\n response: { status: 500, fixture },\n });\n writeErrorResponse(\n res,\n 500,\n JSON.stringify({\n error: {\n message:\n \"Fixture response did not match any known embedding type (must have embedding or error)\",\n type: \"server_error\",\n },\n }),\n );\n return;\n }\n\n // No fixture match — try record-and-replay proxy if configured\n if (defaults.record) {\n const proxied = await proxyAndRecord(\n req,\n res,\n syntheticReq,\n \"openai\",\n req.url ?? \"/v1/embeddings\",\n fixtures,\n defaults,\n raw,\n );\n if (proxied) {\n journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v1/embeddings\",\n headers: flattenHeaders(req.headers),\n body: syntheticReq,\n response: { status: res.statusCode ?? 200, fixture: null },\n });\n return;\n }\n }\n\n if (defaults.strict) {\n logger.error(\n `STRICT: No fixture matched for ${req.method ?? \"POST\"} ${req.url ?? \"/v1/embeddings\"}`,\n );\n journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v1/embeddings\",\n headers: flattenHeaders(req.headers),\n body: syntheticReq,\n response: { status: 503, fixture: null },\n });\n writeErrorResponse(\n res,\n 503,\n JSON.stringify({\n error: {\n message: \"Strict mode: no fixture matched\",\n type: \"invalid_request_error\",\n code: \"no_fixture_match\",\n },\n }),\n );\n return;\n }\n\n // No fixture match — generate deterministic embeddings from input text\n logger.warn(\n `No embedding fixture matched for \"${combinedInput.slice(0, 80)}\" — returning deterministic fallback`,\n );\n const dimensions = embeddingReq.dimensions ?? 1536;\n const embeddings = inputs.map((input) => generateDeterministicEmbedding(input, dimensions));\n\n journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v1/embeddings\",\n headers: flattenHeaders(req.headers),\n body: syntheticReq,\n response: { status: 200, fixture: null },\n });\n\n const body = buildEmbeddingResponse(embeddings, embeddingReq.model);\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify(body));\n}\n"],"mappings":";;;;;;;AAoCA,eAAsB,iBACpB,KACA,KACA,KACA,UACA,SACA,UACA,gBACe;CACf,MAAM,EAAE,WAAW;AACnB,gBAAe,IAAI;CAEnB,IAAI;AACJ,KAAI;AACF,iBAAe,KAAK,MAAM,IAAI;SACxB;AACN,UAAQ,IAAI;GACV,QAAQ,IAAI,UAAU;GACtB,MAAM,IAAI,OAAO;GACjB,SAAS,eAAe,IAAI,QAAQ;GACpC,MAAM;GACN,UAAU;IAAE,QAAQ;IAAK,SAAS;IAAM;GACzC,CAAC;AACF,qBACE,KACA,KACA,KAAK,UAAU,EACb,OAAO;GACL,SAAS;GACT,MAAM;GACN,MAAM;GACP,EACF,CAAC,CACH;AACD;;CAIF,MAAM,SAAmB,MAAM,QAAQ,aAAa,MAAM,GACtD,aAAa,QACb,CAAC,aAAa,MAAM;CAGxB,MAAM,gBAAgB,OAAO,KAAK,IAAI;CAItC,MAAM,eAAsC;EAC1C,OAAO,aAAa;EACpB,UAAU,EAAE;EACZ,gBAAgB;
|
|
1
|
+
{"version":3,"file":"embeddings.js","names":[],"sources":["../src/embeddings.ts"],"sourcesContent":["/**\n * OpenAI Embeddings API support for LLMock.\n *\n * Handles POST /v1/embeddings requests. Matches fixtures using the `inputText`\n * field, and falls back to generating a deterministic embedding from the input\n * text hash when no fixture matches.\n */\n\nimport type * as http from \"node:http\";\nimport type { ChatCompletionRequest, Fixture, HandlerDefaults } from \"./types.js\";\nimport {\n isEmbeddingResponse,\n isErrorResponse,\n generateDeterministicEmbedding,\n buildEmbeddingResponse,\n flattenHeaders,\n getTestId,\n} from \"./helpers.js\";\nimport { matchFixture } from \"./router.js\";\nimport { writeErrorResponse } from \"./sse-writer.js\";\nimport type { Journal } from \"./journal.js\";\nimport { applyChaos } from \"./chaos.js\";\nimport { proxyAndRecord } from \"./recorder.js\";\n\n// ─── Embeddings API request types ──────────────────────────────────────────\n\ninterface EmbeddingRequest {\n input: string | string[];\n model: string;\n encoding_format?: \"float\" | \"base64\";\n dimensions?: number;\n [key: string]: unknown;\n}\n\n// ─── Request handler ───────────────────────────────────────────────────────\n\nexport async function handleEmbeddings(\n req: http.IncomingMessage,\n res: http.ServerResponse,\n raw: string,\n fixtures: Fixture[],\n journal: Journal,\n defaults: HandlerDefaults,\n setCorsHeaders: (res: http.ServerResponse) => void,\n): Promise<void> {\n const { logger } = defaults;\n setCorsHeaders(res);\n\n let embeddingReq: EmbeddingRequest;\n try {\n embeddingReq = JSON.parse(raw) as EmbeddingRequest;\n } catch {\n journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v1/embeddings\",\n headers: flattenHeaders(req.headers),\n body: null,\n response: { status: 400, fixture: null },\n });\n writeErrorResponse(\n res,\n 400,\n JSON.stringify({\n error: {\n message: \"Malformed JSON\",\n type: \"invalid_request_error\",\n code: \"invalid_json\",\n },\n }),\n );\n return;\n }\n\n // Normalize input to array of strings\n const inputs: string[] = Array.isArray(embeddingReq.input)\n ? embeddingReq.input\n : [embeddingReq.input];\n\n // Concatenate all inputs for matching purposes\n const combinedInput = inputs.join(\" \");\n\n // Build a synthetic ChatCompletionRequest for the fixture router.\n // We attach `embeddingInput` so the router's inputText matching can use it.\n const syntheticReq: ChatCompletionRequest = {\n model: embeddingReq.model,\n messages: [],\n embeddingInput: combinedInput,\n _endpointType: \"embedding\",\n };\n\n const testId = getTestId(req);\n const fixture = matchFixture(\n fixtures,\n syntheticReq,\n journal.getFixtureMatchCountsForTest(testId),\n defaults.requestTransform,\n );\n\n if (fixture) {\n journal.incrementFixtureMatchCount(fixture, fixtures, testId);\n }\n\n if (\n applyChaos(\n res,\n fixture,\n defaults.chaos,\n req.headers,\n journal,\n {\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v1/embeddings\",\n headers: flattenHeaders(req.headers),\n body: syntheticReq,\n },\n defaults.registry,\n defaults.logger,\n )\n )\n return;\n\n if (fixture) {\n const response = fixture.response;\n\n // Error response\n if (isErrorResponse(response)) {\n const status = response.status ?? 500;\n journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v1/embeddings\",\n headers: flattenHeaders(req.headers),\n body: syntheticReq,\n response: { status, fixture },\n });\n writeErrorResponse(res, status, JSON.stringify(response));\n return;\n }\n\n // Embedding response — use the fixture's embedding for each input\n if (isEmbeddingResponse(response)) {\n journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v1/embeddings\",\n headers: flattenHeaders(req.headers),\n body: syntheticReq,\n response: { status: 200, fixture },\n });\n const embeddings = inputs.map(() => [...response.embedding]);\n const body = buildEmbeddingResponse(embeddings, embeddingReq.model);\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify(body));\n return;\n }\n\n // Fixture matched but response type is not compatible with embeddings\n journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v1/embeddings\",\n headers: flattenHeaders(req.headers),\n body: syntheticReq,\n response: { status: 500, fixture },\n });\n writeErrorResponse(\n res,\n 500,\n JSON.stringify({\n error: {\n message:\n \"Fixture response did not match any known embedding type (must have embedding or error)\",\n type: \"server_error\",\n },\n }),\n );\n return;\n }\n\n // No fixture match — try record-and-replay proxy if configured\n if (defaults.record) {\n const proxied = await proxyAndRecord(\n req,\n res,\n syntheticReq,\n \"openai\",\n req.url ?? \"/v1/embeddings\",\n fixtures,\n defaults,\n raw,\n );\n if (proxied) {\n journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v1/embeddings\",\n headers: flattenHeaders(req.headers),\n body: syntheticReq,\n response: { status: res.statusCode ?? 200, fixture: null },\n });\n return;\n }\n }\n\n if (defaults.strict) {\n logger.error(\n `STRICT: No fixture matched for ${req.method ?? \"POST\"} ${req.url ?? \"/v1/embeddings\"}`,\n );\n journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v1/embeddings\",\n headers: flattenHeaders(req.headers),\n body: syntheticReq,\n response: { status: 503, fixture: null },\n });\n writeErrorResponse(\n res,\n 503,\n JSON.stringify({\n error: {\n message: \"Strict mode: no fixture matched\",\n type: \"invalid_request_error\",\n code: \"no_fixture_match\",\n },\n }),\n );\n return;\n }\n\n // No fixture match — generate deterministic embeddings from input text\n logger.warn(\n `No embedding fixture matched for \"${combinedInput.slice(0, 80)}\" — returning deterministic fallback`,\n );\n const dimensions = embeddingReq.dimensions ?? 1536;\n const embeddings = inputs.map((input) => generateDeterministicEmbedding(input, dimensions));\n\n journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v1/embeddings\",\n headers: flattenHeaders(req.headers),\n body: syntheticReq,\n response: { status: 200, fixture: null },\n });\n\n const body = buildEmbeddingResponse(embeddings, embeddingReq.model);\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify(body));\n}\n"],"mappings":"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"}
|
package/dist/gemini.cjs
CHANGED
|
@@ -310,6 +310,7 @@ async function handleGemini(req, res, raw, model, streaming, fixtures, journal,
|
|
|
310
310
|
return;
|
|
311
311
|
}
|
|
312
312
|
const completionReq = geminiToCompletionRequest(geminiReq, model, streaming);
|
|
313
|
+
completionReq._endpointType = "chat";
|
|
313
314
|
const testId = require_helpers.getTestId(req);
|
|
314
315
|
const fixture = require_router.matchFixture(fixtures, completionReq, journal.getFixtureMatchCountsForTest(testId), defaults.requestTransform);
|
|
315
316
|
const path = req.url ?? `/v1beta/models/${model}:generateContent`;
|