@copilotkit/aimock 1.12.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.
Files changed (178) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/README.md +20 -2
  4. package/dist/_virtual/_rolldown/runtime.cjs +2 -0
  5. package/dist/_virtual/_rolldown/runtime.js +29 -0
  6. package/dist/a2a-types.d.cts.map +1 -1
  7. package/dist/a2a-types.d.ts.map +1 -1
  8. package/dist/aimock-cli.cjs +16 -0
  9. package/dist/aimock-cli.cjs.map +1 -1
  10. package/dist/aimock-cli.d.cts +2 -0
  11. package/dist/aimock-cli.d.cts.map +1 -1
  12. package/dist/aimock-cli.d.ts +2 -0
  13. package/dist/aimock-cli.d.ts.map +1 -1
  14. package/dist/aimock-cli.js +16 -0
  15. package/dist/aimock-cli.js.map +1 -1
  16. package/dist/config-loader.d.cts.map +1 -1
  17. package/dist/convert-mockllm.cjs +232 -0
  18. package/dist/convert-mockllm.cjs.map +1 -0
  19. package/dist/convert-mockllm.js +230 -0
  20. package/dist/convert-mockllm.js.map +1 -0
  21. package/dist/convert-vidaimock.cjs +110 -0
  22. package/dist/convert-vidaimock.cjs.map +1 -0
  23. package/dist/convert-vidaimock.js +108 -0
  24. package/dist/convert-vidaimock.js.map +1 -0
  25. package/dist/convert.cjs +158 -0
  26. package/dist/convert.cjs.map +1 -0
  27. package/dist/convert.d.cts +16 -0
  28. package/dist/convert.d.cts.map +1 -0
  29. package/dist/convert.d.ts +16 -0
  30. package/dist/convert.d.ts.map +1 -0
  31. package/dist/convert.js +157 -0
  32. package/dist/convert.js.map +1 -0
  33. package/dist/jest.cjs +70 -0
  34. package/dist/jest.cjs.map +1 -0
  35. package/dist/jest.d.cts +33 -0
  36. package/dist/jest.d.cts.map +1 -0
  37. package/dist/jest.d.ts +33 -0
  38. package/dist/jest.d.ts.map +1 -0
  39. package/dist/jest.js +67 -0
  40. package/dist/jest.js.map +1 -0
  41. package/dist/node_modules/.pnpm/@vitest_pretty-format@3.2.4/node_modules/@vitest/pretty-format/dist/index.cjs +934 -0
  42. package/dist/node_modules/.pnpm/@vitest_pretty-format@3.2.4/node_modules/@vitest/pretty-format/dist/index.cjs.map +1 -0
  43. package/dist/node_modules/.pnpm/@vitest_pretty-format@3.2.4/node_modules/@vitest/pretty-format/dist/index.js +934 -0
  44. package/dist/node_modules/.pnpm/@vitest_pretty-format@3.2.4/node_modules/@vitest/pretty-format/dist/index.js.map +1 -0
  45. package/dist/node_modules/.pnpm/@vitest_runner@3.2.4/node_modules/@vitest/runner/dist/chunk-hooks.cjs +1051 -0
  46. package/dist/node_modules/.pnpm/@vitest_runner@3.2.4/node_modules/@vitest/runner/dist/chunk-hooks.cjs.map +1 -0
  47. package/dist/node_modules/.pnpm/@vitest_runner@3.2.4/node_modules/@vitest/runner/dist/chunk-hooks.js +1042 -0
  48. package/dist/node_modules/.pnpm/@vitest_runner@3.2.4/node_modules/@vitest/runner/dist/chunk-hooks.js.map +1 -0
  49. package/dist/node_modules/.pnpm/@vitest_runner@3.2.4/node_modules/@vitest/runner/dist/index.cjs +1 -0
  50. package/dist/node_modules/.pnpm/@vitest_runner@3.2.4/node_modules/@vitest/runner/dist/index.js +3 -0
  51. package/dist/node_modules/.pnpm/@vitest_utils@3.2.4/node_modules/@vitest/utils/dist/chunk-_commonjsHelpers.cjs +96 -0
  52. package/dist/node_modules/.pnpm/@vitest_utils@3.2.4/node_modules/@vitest/utils/dist/chunk-_commonjsHelpers.cjs.map +1 -0
  53. package/dist/node_modules/.pnpm/@vitest_utils@3.2.4/node_modules/@vitest/utils/dist/chunk-_commonjsHelpers.js +93 -0
  54. package/dist/node_modules/.pnpm/@vitest_utils@3.2.4/node_modules/@vitest/utils/dist/chunk-_commonjsHelpers.js.map +1 -0
  55. package/dist/node_modules/.pnpm/@vitest_utils@3.2.4/node_modules/@vitest/utils/dist/helpers.cjs +49 -0
  56. package/dist/node_modules/.pnpm/@vitest_utils@3.2.4/node_modules/@vitest/utils/dist/helpers.cjs.map +1 -0
  57. package/dist/node_modules/.pnpm/@vitest_utils@3.2.4/node_modules/@vitest/utils/dist/helpers.js +43 -0
  58. package/dist/node_modules/.pnpm/@vitest_utils@3.2.4/node_modules/@vitest/utils/dist/helpers.js.map +1 -0
  59. package/dist/node_modules/.pnpm/@vitest_utils@3.2.4/node_modules/@vitest/utils/dist/index.cjs +456 -0
  60. package/dist/node_modules/.pnpm/@vitest_utils@3.2.4/node_modules/@vitest/utils/dist/index.cjs.map +1 -0
  61. package/dist/node_modules/.pnpm/@vitest_utils@3.2.4/node_modules/@vitest/utils/dist/index.js +456 -0
  62. package/dist/node_modules/.pnpm/@vitest_utils@3.2.4/node_modules/@vitest/utils/dist/index.js.map +1 -0
  63. package/dist/node_modules/.pnpm/@vitest_utils@3.2.4/node_modules/@vitest/utils/dist/source-map.cjs +170 -0
  64. package/dist/node_modules/.pnpm/@vitest_utils@3.2.4/node_modules/@vitest/utils/dist/source-map.cjs.map +1 -0
  65. package/dist/node_modules/.pnpm/@vitest_utils@3.2.4/node_modules/@vitest/utils/dist/source-map.js +169 -0
  66. package/dist/node_modules/.pnpm/@vitest_utils@3.2.4/node_modules/@vitest/utils/dist/source-map.js.map +1 -0
  67. package/dist/node_modules/.pnpm/js-tokens@9.0.1/node_modules/js-tokens/index.cjs +388 -0
  68. package/dist/node_modules/.pnpm/js-tokens@9.0.1/node_modules/js-tokens/index.cjs.map +1 -0
  69. package/dist/node_modules/.pnpm/js-tokens@9.0.1/node_modules/js-tokens/index.js +385 -0
  70. package/dist/node_modules/.pnpm/js-tokens@9.0.1/node_modules/js-tokens/index.js.map +1 -0
  71. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/arguments.cjs +12 -0
  72. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/arguments.cjs.map +1 -0
  73. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/arguments.js +12 -0
  74. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/arguments.js.map +1 -0
  75. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/array.cjs +17 -0
  76. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/array.cjs.map +1 -0
  77. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/array.js +17 -0
  78. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/array.js.map +1 -0
  79. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/bigint.cjs +12 -0
  80. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/bigint.cjs.map +1 -0
  81. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/bigint.js +12 -0
  82. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/bigint.js.map +1 -0
  83. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/class.cjs +16 -0
  84. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/class.cjs.map +1 -0
  85. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/class.js +16 -0
  86. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/class.js.map +1 -0
  87. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/date.cjs +14 -0
  88. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/date.cjs.map +1 -0
  89. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/date.js +14 -0
  90. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/date.js.map +1 -0
  91. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/error.cjs +35 -0
  92. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/error.cjs.map +1 -0
  93. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/error.js +35 -0
  94. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/error.js.map +1 -0
  95. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/function.cjs +13 -0
  96. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/function.cjs.map +1 -0
  97. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/function.js +13 -0
  98. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/function.js.map +1 -0
  99. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/helpers.cjs +128 -0
  100. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/helpers.cjs.map +1 -0
  101. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/helpers.js +123 -0
  102. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/helpers.js.map +1 -0
  103. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/html.cjs +41 -0
  104. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/html.cjs.map +1 -0
  105. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/html.js +40 -0
  106. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/html.js.map +1 -0
  107. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/index.cjs +100 -0
  108. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/index.cjs.map +1 -0
  109. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/index.js +100 -0
  110. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/index.js.map +1 -0
  111. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/map.cjs +26 -0
  112. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/map.cjs.map +1 -0
  113. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/map.js +26 -0
  114. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/map.js.map +1 -0
  115. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/number.cjs +15 -0
  116. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/number.cjs.map +1 -0
  117. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/number.js +15 -0
  118. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/number.js.map +1 -0
  119. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/object.cjs +22 -0
  120. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/object.cjs.map +1 -0
  121. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/object.js +22 -0
  122. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/object.js.map +1 -0
  123. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/promise.cjs +7 -0
  124. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/promise.cjs.map +1 -0
  125. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/promise.js +6 -0
  126. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/promise.js.map +1 -0
  127. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/regexp.cjs +13 -0
  128. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/regexp.cjs.map +1 -0
  129. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/regexp.js +13 -0
  130. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/regexp.js.map +1 -0
  131. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/set.cjs +19 -0
  132. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/set.cjs.map +1 -0
  133. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/set.js +19 -0
  134. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/set.js.map +1 -0
  135. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/string.cjs +26 -0
  136. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/string.cjs.map +1 -0
  137. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/string.js +26 -0
  138. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/string.js.map +1 -0
  139. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/symbol.cjs +10 -0
  140. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/symbol.cjs.map +1 -0
  141. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/symbol.js +9 -0
  142. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/symbol.js.map +1 -0
  143. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/typedarray.cjs +31 -0
  144. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/typedarray.cjs.map +1 -0
  145. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/typedarray.js +31 -0
  146. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/typedarray.js.map +1 -0
  147. package/dist/node_modules/.pnpm/strip-literal@3.1.0/node_modules/strip-literal/dist/index.cjs +52 -0
  148. package/dist/node_modules/.pnpm/strip-literal@3.1.0/node_modules/strip-literal/dist/index.cjs.map +1 -0
  149. package/dist/node_modules/.pnpm/strip-literal@3.1.0/node_modules/strip-literal/dist/index.js +52 -0
  150. package/dist/node_modules/.pnpm/strip-literal@3.1.0/node_modules/strip-literal/dist/index.js.map +1 -0
  151. package/dist/node_modules/.pnpm/tinyrainbow@2.0.0/node_modules/tinyrainbow/dist/chunk-BVHSVHOK.cjs +83 -0
  152. package/dist/node_modules/.pnpm/tinyrainbow@2.0.0/node_modules/tinyrainbow/dist/chunk-BVHSVHOK.cjs.map +1 -0
  153. package/dist/node_modules/.pnpm/tinyrainbow@2.0.0/node_modules/tinyrainbow/dist/chunk-BVHSVHOK.js +82 -0
  154. package/dist/node_modules/.pnpm/tinyrainbow@2.0.0/node_modules/tinyrainbow/dist/chunk-BVHSVHOK.js.map +1 -0
  155. package/dist/node_modules/.pnpm/tinyrainbow@2.0.0/node_modules/tinyrainbow/dist/node.cjs +10 -0
  156. package/dist/node_modules/.pnpm/tinyrainbow@2.0.0/node_modules/tinyrainbow/dist/node.cjs.map +1 -0
  157. package/dist/node_modules/.pnpm/tinyrainbow@2.0.0/node_modules/tinyrainbow/dist/node.js +10 -0
  158. package/dist/node_modules/.pnpm/tinyrainbow@2.0.0/node_modules/tinyrainbow/dist/node.js.map +1 -0
  159. package/dist/vitest.cjs +80 -0
  160. package/dist/vitest.cjs.map +1 -0
  161. package/dist/vitest.d.cts +30 -0
  162. package/dist/vitest.d.cts.map +1 -0
  163. package/dist/vitest.d.ts +30 -0
  164. package/dist/vitest.d.ts.map +1 -0
  165. package/dist/vitest.js +77 -0
  166. package/dist/vitest.js.map +1 -0
  167. package/fixtures/examples/a2a/a2a-config.json +42 -0
  168. package/fixtures/examples/agui/agui-text-response.json +35 -0
  169. package/fixtures/examples/chaos/chaos-config.json +10 -0
  170. package/fixtures/examples/full-suite.json +116 -0
  171. package/fixtures/examples/llm/embeddings.json +10 -0
  172. package/fixtures/examples/llm/error-injection.json +15 -0
  173. package/fixtures/examples/llm/sequential-responses.json +20 -0
  174. package/fixtures/examples/llm/streaming-physics.json +15 -0
  175. package/fixtures/examples/mcp/mcp-config.json +26 -0
  176. package/fixtures/examples/record-replay/record-config.json +11 -0
  177. package/fixtures/examples/vector/vector-config.json +34 -0
  178. package/package.json +59 -1
@@ -9,7 +9,7 @@
9
9
  "source": {
10
10
  "source": "npm",
11
11
  "package": "@copilotkit/aimock",
12
- "version": "^1.11.0"
12
+ "version": "^1.13.0"
13
13
  },
14
14
  "description": "Fixture authoring skill for @copilotkit/aimock — match fields, response types, embeddings, structured output, sequential responses, streaming physics, agent loop patterns, gotchas, and debugging"
15
15
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "llmock",
3
- "version": "1.11.0",
3
+ "version": "1.13.0",
4
4
  "description": "Fixture authoring guidance for @copilotkit/aimock",
5
5
  "author": {
6
6
  "name": "CopilotKit"
package/README.md CHANGED
@@ -1,6 +1,5 @@
1
1
  # aimock [![Unit Tests](https://github.com/CopilotKit/aimock/actions/workflows/test-unit.yml/badge.svg)](https://github.com/CopilotKit/aimock/actions/workflows/test-unit.yml) [![Drift Tests](https://github.com/CopilotKit/aimock/actions/workflows/test-drift.yml/badge.svg)](https://github.com/CopilotKit/aimock/actions/workflows/test-drift.yml) [![npm version](https://img.shields.io/npm/v/@copilotkit/aimock)](https://www.npmjs.com/package/@copilotkit/aimock)
2
2
 
3
- https://github.com/user-attachments/assets/646bf106-0320-41f2-a9b1-5090454830f3
4
3
 
5
4
  Mock infrastructure for AI application testing — LLM APIs, image generation, text-to-speech, transcription, video generation, MCP tools, A2A agents, AG-UI event streams, vector databases, search, rerank, and moderation. One package, one port, zero dependencies.
6
5
 
@@ -51,8 +50,23 @@ Run them all on one port with `npx aimock --config aimock.json`, or use the prog
51
50
  - **[WebSocket APIs](https://aimock.copilotkit.dev/websocket)** — OpenAI Realtime, Responses WS, Gemini Live
52
51
  - **[Prometheus Metrics](https://aimock.copilotkit.dev/metrics)** — Request counts, latencies, fixture match rates
53
52
  - **[Docker + Helm](https://aimock.copilotkit.dev/docker)** — Container image and Helm chart for CI/CD
53
+ - **[Vitest & Jest Plugins](https://aimock.copilotkit.dev/test-plugins)** — Zero-config `useAimock()` with auto lifecycle and env patching
54
54
  - **Zero dependencies** — Everything from Node.js builtins
55
55
 
56
+ ## GitHub Action
57
+
58
+ ```yaml
59
+ - uses: CopilotKit/aimock@v1
60
+ with:
61
+ fixtures: ./test/fixtures
62
+
63
+ - run: npm test
64
+ env:
65
+ OPENAI_BASE_URL: http://127.0.0.1:4010/v1
66
+ ```
67
+
68
+ See the [GitHub Action docs](https://aimock.copilotkit.dev/github-action) for all inputs and examples.
69
+
56
70
  ## CLI
57
71
 
58
72
  ```bash
@@ -65,6 +79,10 @@ npx aimock --config aimock.json
65
79
  # Record mode: proxy to real APIs, save fixtures
66
80
  npx aimock --record --provider-openai https://api.openai.com
67
81
 
82
+ # Convert fixtures from other tools
83
+ npx aimock convert vidaimock ./templates/ ./fixtures/
84
+ npx aimock convert mockllm ./config.yaml ./fixtures/
85
+
68
86
  # Docker
69
87
  docker run -d -p 4010:4010 -v ./fixtures:/fixtures ghcr.io/copilotkit/aimock -f /fixtures
70
88
  ```
@@ -75,7 +93,7 @@ Step-by-step migration guides: [MSW](https://aimock.copilotkit.dev/migrate-from-
75
93
 
76
94
  ## Documentation
77
95
 
78
- **[https://aimock.copilotkit.dev](https://aimock.copilotkit.dev)**
96
+ **[https://aimock.copilotkit.dev](https://aimock.copilotkit.dev)** · [Example fixtures](https://aimock.copilotkit.dev/examples)
79
97
 
80
98
  ## Real-World Usage
81
99
 
@@ -5,6 +5,7 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
6
  var __getProtoOf = Object.getPrototypeOf;
7
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __commonJSMin = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
8
9
  var __copyProps = (to, from, except, desc) => {
9
10
  if (from && typeof from === "object" || typeof from === "function") {
10
11
  for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
@@ -26,4 +27,5 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
26
27
 
27
28
  //#endregion
28
29
 
30
+ exports.__commonJSMin = __commonJSMin;
29
31
  exports.__toESM = __toESM;
@@ -0,0 +1,29 @@
1
+ //#region \0rolldown/runtime.js
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __commonJSMin = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
9
+ var __copyProps = (to, from, except, desc) => {
10
+ if (from && typeof from === "object" || typeof from === "function") {
11
+ for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
12
+ key = keys[i];
13
+ if (!__hasOwnProp.call(to, key) && key !== except) {
14
+ __defProp(to, key, {
15
+ get: ((k) => from[k]).bind(null, key),
16
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
17
+ });
18
+ }
19
+ }
20
+ }
21
+ return to;
22
+ };
23
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
24
+ value: mod,
25
+ enumerable: true
26
+ }) : target, mod));
27
+
28
+ //#endregion
29
+ export { __commonJSMin, __toESM };
@@ -1 +1 @@
1
- {"version":3,"file":"a2a-types.d.cts","names":[],"sources":["../src/a2a-types.ts"],"sourcesContent":[],"mappings":";UAAiB,cAAA;EAAA,IAAA,CAAA,EAAA,MAAA;EAKA,IAAA,CAAA,EAAA,MAAA;AAQjB;AAKiB,UAbA,kBAAA,CAiBD;EAGC,IAAA,EAAA,MAAA;EAIL,WAAA,CAAA,EAAA,MAAc;EAAA,OAAA,CAAA,EAAA,MAAA;QACG,CAAA,EArBlB,KAqBkB,CAAA;IACE,EAAA,EAAA,MAAA;IAAO,IAAA,EAAA,MAAA;IAErB,WAAO,CAAA,EAAA,MAAA;IAAA,IAAA,CAAA,EAAA,MAAA,EAAA;;cAIX,CAAA,EAAA;IACF,SAAA,CAAA,EAAA,OAAA;EAAU,CAAA;AAGrB;AAEiB,KA9BL,OAAA,GA8Be;EAAA,IAAA,EAAA,MAAA;;MAGlB,EAAA,OAAA;EAAO,SAAA,CAAA,EAAA,MAAA;AAGhB,CAAA,GAAY;;;;UA/BK,WAAA;;;;SAIR;;UAGQ,eAAA;cACH;;KAGF,cAAA;;SACiB;;;SACE;;;;;UAEd,OAAA;;;;WAGE;;;aACN;WACF;;KAGC,OAAA;UAEK,UAAA;;QAET;SACC;;KAGG,YAAA"}
1
+ {"version":3,"file":"a2a-types.d.cts","names":[],"sources":["../src/a2a-types.ts"],"sourcesContent":[],"mappings":";UAAiB,cAAA;EAAA,IAAA,CAAA,EAAA,MAAA;EAKA,IAAA,CAAA,EAAA,MAAA;AAQjB;AAKiB,UAbA,kBAAA,CAiBR;EAGQ,IAAA,EAAA,MAAA;EAIL,WAAA,CAAA,EAAA,MAAc;EAAA,OAAA,CAAA,EAAA,MAAA;QACG,CAAA,EArBlB,KAqBkB,CAAA;IACE,EAAA,EAAA,MAAA;IAAO,IAAA,EAAA,MAAA;IAErB,WAAO,CAAA,EAAA,MAAA;IAAA,IAAA,CAAA,EAAA,MAAA,EAAA;;cAIX,CAAA,EAAA;IACF,SAAA,CAAA,EAAA,OAAA;EAAU,CAAA;AAGrB;AAEiB,KA9BL,OAAA,GA8Be;EAAA,IAAA,EAAA,MAAA;;MAGlB,EAAA,OAAA;EAAO,SAAA,CAAA,EAAA,MAAA;AAGhB,CAAA,GAAY;;;;UA/BK,WAAA;;;;SAIR;;UAGQ,eAAA;cACH;;KAGF,cAAA;;SACiB;;;SACE;;;;;UAEd,OAAA;;;;WAGE;;;aACN;WACF;;KAGC,OAAA;UAEK,UAAA;;QAET;SACC;;KAGG,YAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"a2a-types.d.ts","names":[],"sources":["../src/a2a-types.ts"],"sourcesContent":[],"mappings":";UAAiB,cAAA;EAAA,IAAA,CAAA,EAAA,MAAA;EAKA,IAAA,CAAA,EAAA,MAAA;AAQjB;AAKiB,UAbA,kBAAA,CAiBD;EAGC,IAAA,EAAA,MAAA;EAIL,WAAA,CAAA,EAAA,MAAc;EAAA,OAAA,CAAA,EAAA,MAAA;QACG,CAAA,EArBlB,KAqBkB,CAAA;IACE,EAAA,EAAA,MAAA;IAAO,IAAA,EAAA,MAAA;IAErB,WAAO,CAAA,EAAA,MAAA;IAAA,IAAA,CAAA,EAAA,MAAA,EAAA;;cAIX,CAAA,EAAA;IACF,SAAA,CAAA,EAAA,OAAA;EAAU,CAAA;AAGrB;AAEiB,KA9BL,OAAA,GA8Be;EAAA,IAAA,EAAA,MAAA;;MAGlB,EAAA,OAAA;EAAO,SAAA,CAAA,EAAA,MAAA;AAGhB,CAAA,GAAY;;;;UA/BK,WAAA;;;;SAIR;;UAGQ,eAAA;cACH;;KAGF,cAAA;;SACiB;;;SACE;;;;;UAEd,OAAA;;;;WAGE;;;aACN;WACF;;KAGC,OAAA;UAEK,UAAA;;QAET;SACC;;KAGG,YAAA"}
1
+ {"version":3,"file":"a2a-types.d.ts","names":[],"sources":["../src/a2a-types.ts"],"sourcesContent":[],"mappings":";UAAiB,cAAA;EAAA,IAAA,CAAA,EAAA,MAAA;EAKA,IAAA,CAAA,EAAA,MAAA;AAQjB;AAKiB,UAbA,kBAAA,CAiBR;EAGQ,IAAA,EAAA,MAAA;EAIL,WAAA,CAAA,EAAA,MAAc;EAAA,OAAA,CAAA,EAAA,MAAA;QACG,CAAA,EArBlB,KAqBkB,CAAA;IACE,EAAA,EAAA,MAAA;IAAO,IAAA,EAAA,MAAA;IAErB,WAAO,CAAA,EAAA,MAAA;IAAA,IAAA,CAAA,EAAA,MAAA,EAAA;;cAIX,CAAA,EAAA;IACF,SAAA,CAAA,EAAA,OAAA;EAAU,CAAA;AAGrB;AAEiB,KA9BL,OAAA,GA8Be;EAAA,IAAA,EAAA,MAAA;;MAGlB,EAAA,OAAA;EAAO,SAAA,CAAA,EAAA,MAAA;AAGhB,CAAA,GAAY;;;;UA/BK,WAAA;;;;SAIR;;UAGQ,eAAA;cACH;;KAGF,cAAA;;SACiB;;;SACE;;;;;UAEd,OAAA;;;;WAGE;;;aACN;WACF;;KAGC,OAAA;UAEK,UAAA;;QAET;SACC;;KAGG,YAAA"}
@@ -2,18 +2,24 @@
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
3
3
  const require_runtime = require('./_virtual/_rolldown/runtime.cjs');
4
4
  const require_config_loader = require('./config-loader.cjs');
5
+ const require_convert = require('./convert.cjs');
5
6
  let node_util = require("node:util");
6
7
  let node_path = require("node:path");
7
8
 
8
9
  //#region src/aimock-cli.ts
9
10
  const HELP = `
10
11
  Usage: aimock [options]
12
+ aimock convert <format> <input> [output]
11
13
 
12
14
  Options:
13
15
  -c, --config <path> Path to aimock config JSON file (required)
14
16
  -p, --port <number> Port override (default: from config or 0)
15
17
  -h, --host <string> Host override (default: from config or 127.0.0.1)
16
18
  --help Show this help message
19
+
20
+ Subcommands:
21
+ convert Convert third-party mock configs to aimock format
22
+ Run "aimock convert --help" for details
17
23
  `.trim();
18
24
  function runAimockCli(deps = {}) {
19
25
  /* v8 ignore next 6 -- defaults used only when called from CLI entry point */
@@ -23,6 +29,16 @@ function runAimockCli(deps = {}) {
23
29
  const exit = deps.exit ?? process.exit.bind(process);
24
30
  const loadConfigFn = deps.loadConfigFn ?? require_config_loader.loadConfig;
25
31
  const startFromConfigFn = deps.startFromConfigFn ?? require_config_loader.startFromConfig;
32
+ if (argv[0] === "convert") {
33
+ require_convert.runConvertCli({
34
+ argv: argv.slice(1),
35
+ log,
36
+ logError,
37
+ exit,
38
+ ...deps.convertDeps
39
+ });
40
+ return;
41
+ }
26
42
  let values;
27
43
  try {
28
44
  ({values} = (0, node_util.parseArgs)({
@@ -1 +1 @@
1
- {"version":3,"file":"aimock-cli.cjs","names":["loadConfig","startFromConfig"],"sources":["../src/aimock-cli.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { parseArgs } from \"node:util\";\nimport { resolve } from \"node:path\";\nimport { loadConfig, startFromConfig } from \"./config-loader.js\";\n\nconst HELP = `\nUsage: aimock [options]\n\nOptions:\n -c, --config <path> Path to aimock config JSON file (required)\n -p, --port <number> Port override (default: from config or 0)\n -h, --host <string> Host override (default: from config or 127.0.0.1)\n --help Show this help message\n`.trim();\n\nexport interface AimockCliDeps {\n argv?: string[];\n log?: (msg: string) => void;\n logError?: (msg: string) => void;\n exit?: (code: number) => void;\n loadConfigFn?: typeof loadConfig;\n startFromConfigFn?: typeof startFromConfig;\n onReady?: (ctx: { shutdown: () => void }) => void;\n}\n\nexport function runAimockCli(deps: AimockCliDeps = {}): void {\n /* v8 ignore next 6 -- defaults used only when called from CLI entry point */\n const argv = deps.argv ?? process.argv.slice(2);\n const log = deps.log ?? console.log.bind(console);\n const logError = deps.logError ?? console.error.bind(console);\n const exit = deps.exit ?? process.exit.bind(process);\n const loadConfigFn = deps.loadConfigFn ?? loadConfig;\n const startFromConfigFn = deps.startFromConfigFn ?? startFromConfig;\n\n let values;\n try {\n ({ values } = parseArgs({\n args: argv,\n options: {\n config: { type: \"string\", short: \"c\" },\n port: { type: \"string\", short: \"p\" },\n host: { type: \"string\", short: \"h\" },\n help: { type: \"boolean\", default: false },\n },\n strict: true,\n }));\n } catch (err) {\n /* v8 ignore next -- parseArgs always throws Error subclasses */\n const msg = err instanceof Error ? err.message : String(err);\n logError(`Error: ${msg}\\n\\n${HELP}`);\n exit(1);\n return;\n }\n\n if (values.help) {\n log(HELP);\n exit(0);\n return;\n }\n if (!values.config) {\n logError(\"Error: --config is required.\\n\\n\" + HELP);\n exit(1);\n return;\n }\n\n const configPath = resolve(values.config);\n let config;\n try {\n config = loadConfigFn(configPath);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n logError(`Failed to load config from ${configPath}: ${msg}`);\n exit(1);\n return;\n }\n\n const port = values.port ? Number(values.port) : undefined;\n if (\n port !== undefined &&\n (Number.isNaN(port) || !Number.isInteger(port) || port < 0 || port > 65535)\n ) {\n logError(`Error: invalid port \"${values.port}\".\\n\\n${HELP}`);\n exit(1);\n return;\n }\n const host = values.host;\n\n async function main() {\n const { llmock, url } = await startFromConfigFn(config!, { port, host });\n log(`aimock server listening on ${url}`);\n\n function shutdown() {\n log(\"Shutting down...\");\n process.removeListener(\"SIGINT\", shutdown);\n process.removeListener(\"SIGTERM\", shutdown);\n llmock.stop().then(\n () => exit(0),\n (err) => {\n logError(`Shutdown error: ${err instanceof Error ? err.message : String(err)}`);\n exit(1);\n },\n );\n }\n process.on(\"SIGINT\", shutdown);\n process.on(\"SIGTERM\", shutdown);\n\n if (deps.onReady) {\n deps.onReady({ shutdown });\n }\n }\n\n main().catch((err) => {\n logError(err instanceof Error ? err.message : String(err));\n exit(1);\n });\n}\n\n// Run when executed as a script (not when imported for testing).\n/* v8 ignore start -- entry-point guard, exercised by integration tests */\nconst scriptName = process.argv[1] ?? \"\";\nif (scriptName.endsWith(\"aimock-cli.js\") || scriptName.endsWith(\"aimock-cli.ts\")) {\n runAimockCli();\n}\n/* v8 ignore stop */\n"],"mappings":";;;;;;;;AAKA,MAAM,OAAO;;;;;;;;EAQX,MAAM;AAYR,SAAgB,aAAa,OAAsB,EAAE,EAAQ;;CAE3D,MAAM,OAAO,KAAK,QAAQ,QAAQ,KAAK,MAAM,EAAE;CAC/C,MAAM,MAAM,KAAK,OAAO,QAAQ,IAAI,KAAK,QAAQ;CACjD,MAAM,WAAW,KAAK,YAAY,QAAQ,MAAM,KAAK,QAAQ;CAC7D,MAAM,OAAO,KAAK,QAAQ,QAAQ,KAAK,KAAK,QAAQ;CACpD,MAAM,eAAe,KAAK,gBAAgBA;CAC1C,MAAM,oBAAoB,KAAK,qBAAqBC;CAEpD,IAAI;AACJ,KAAI;AACF,GAAC,CAAE,mCAAqB;GACtB,MAAM;GACN,SAAS;IACP,QAAQ;KAAE,MAAM;KAAU,OAAO;KAAK;IACtC,MAAM;KAAE,MAAM;KAAU,OAAO;KAAK;IACpC,MAAM;KAAE,MAAM;KAAU,OAAO;KAAK;IACpC,MAAM;KAAE,MAAM;KAAW,SAAS;KAAO;IAC1C;GACD,QAAQ;GACT,CAAC;UACK,KAAK;AAGZ,WAAS,UADG,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,CACrC,MAAM,OAAO;AACpC,OAAK,EAAE;AACP;;AAGF,KAAI,OAAO,MAAM;AACf,MAAI,KAAK;AACT,OAAK,EAAE;AACP;;AAEF,KAAI,CAAC,OAAO,QAAQ;AAClB,WAAS,qCAAqC,KAAK;AACnD,OAAK,EAAE;AACP;;CAGF,MAAM,oCAAqB,OAAO,OAAO;CACzC,IAAI;AACJ,KAAI;AACF,WAAS,aAAa,WAAW;UAC1B,KAAK;AAEZ,WAAS,8BAA8B,WAAW,IADtC,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,GACA;AAC5D,OAAK,EAAE;AACP;;CAGF,MAAM,OAAO,OAAO,OAAO,OAAO,OAAO,KAAK,GAAG;AACjD,KACE,SAAS,WACR,OAAO,MAAM,KAAK,IAAI,CAAC,OAAO,UAAU,KAAK,IAAI,OAAO,KAAK,OAAO,QACrE;AACA,WAAS,wBAAwB,OAAO,KAAK,QAAQ,OAAO;AAC5D,OAAK,EAAE;AACP;;CAEF,MAAM,OAAO,OAAO;CAEpB,eAAe,OAAO;EACpB,MAAM,EAAE,QAAQ,QAAQ,MAAM,kBAAkB,QAAS;GAAE;GAAM;GAAM,CAAC;AACxE,MAAI,8BAA8B,MAAM;EAExC,SAAS,WAAW;AAClB,OAAI,mBAAmB;AACvB,WAAQ,eAAe,UAAU,SAAS;AAC1C,WAAQ,eAAe,WAAW,SAAS;AAC3C,UAAO,MAAM,CAAC,WACN,KAAK,EAAE,GACZ,QAAQ;AACP,aAAS,mBAAmB,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,GAAG;AAC/E,SAAK,EAAE;KAEV;;AAEH,UAAQ,GAAG,UAAU,SAAS;AAC9B,UAAQ,GAAG,WAAW,SAAS;AAE/B,MAAI,KAAK,QACP,MAAK,QAAQ,EAAE,UAAU,CAAC;;AAI9B,OAAM,CAAC,OAAO,QAAQ;AACpB,WAAS,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,CAAC;AAC1D,OAAK,EAAE;GACP;;;AAKJ,MAAM,aAAa,QAAQ,KAAK,MAAM;AACtC,IAAI,WAAW,SAAS,gBAAgB,IAAI,WAAW,SAAS,gBAAgB,CAC9E,eAAc"}
1
+ {"version":3,"file":"aimock-cli.cjs","names":["loadConfig","startFromConfig"],"sources":["../src/aimock-cli.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { parseArgs } from \"node:util\";\nimport { resolve } from \"node:path\";\nimport { loadConfig, startFromConfig } from \"./config-loader.js\";\nimport { runConvertCli, type ConvertCliDeps } from \"./convert.js\";\n\nconst HELP = `\nUsage: aimock [options]\n aimock convert <format> <input> [output]\n\nOptions:\n -c, --config <path> Path to aimock config JSON file (required)\n -p, --port <number> Port override (default: from config or 0)\n -h, --host <string> Host override (default: from config or 127.0.0.1)\n --help Show this help message\n\nSubcommands:\n convert Convert third-party mock configs to aimock format\n Run \"aimock convert --help\" for details\n`.trim();\n\nexport interface AimockCliDeps {\n argv?: string[];\n log?: (msg: string) => void;\n logError?: (msg: string) => void;\n exit?: (code: number) => void;\n loadConfigFn?: typeof loadConfig;\n startFromConfigFn?: typeof startFromConfig;\n onReady?: (ctx: { shutdown: () => void }) => void;\n convertDeps?: Partial<ConvertCliDeps>;\n}\n\nexport function runAimockCli(deps: AimockCliDeps = {}): void {\n /* v8 ignore next 6 -- defaults used only when called from CLI entry point */\n const argv = deps.argv ?? process.argv.slice(2);\n const log = deps.log ?? console.log.bind(console);\n const logError = deps.logError ?? console.error.bind(console);\n const exit = deps.exit ?? process.exit.bind(process);\n const loadConfigFn = deps.loadConfigFn ?? loadConfig;\n const startFromConfigFn = deps.startFromConfigFn ?? startFromConfig;\n\n // Intercept \"convert\" subcommand before parseArgs (which uses strict mode)\n if (argv[0] === \"convert\") {\n runConvertCli({\n argv: argv.slice(1),\n log,\n logError,\n exit,\n ...deps.convertDeps,\n });\n return;\n }\n\n let values;\n try {\n ({ values } = parseArgs({\n args: argv,\n options: {\n config: { type: \"string\", short: \"c\" },\n port: { type: \"string\", short: \"p\" },\n host: { type: \"string\", short: \"h\" },\n help: { type: \"boolean\", default: false },\n },\n strict: true,\n }));\n } catch (err) {\n /* v8 ignore next -- parseArgs always throws Error subclasses */\n const msg = err instanceof Error ? err.message : String(err);\n logError(`Error: ${msg}\\n\\n${HELP}`);\n exit(1);\n return;\n }\n\n if (values.help) {\n log(HELP);\n exit(0);\n return;\n }\n if (!values.config) {\n logError(\"Error: --config is required.\\n\\n\" + HELP);\n exit(1);\n return;\n }\n\n const configPath = resolve(values.config);\n let config;\n try {\n config = loadConfigFn(configPath);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n logError(`Failed to load config from ${configPath}: ${msg}`);\n exit(1);\n return;\n }\n\n const port = values.port ? Number(values.port) : undefined;\n if (\n port !== undefined &&\n (Number.isNaN(port) || !Number.isInteger(port) || port < 0 || port > 65535)\n ) {\n logError(`Error: invalid port \"${values.port}\".\\n\\n${HELP}`);\n exit(1);\n return;\n }\n const host = values.host;\n\n async function main() {\n const { llmock, url } = await startFromConfigFn(config!, { port, host });\n log(`aimock server listening on ${url}`);\n\n function shutdown() {\n log(\"Shutting down...\");\n process.removeListener(\"SIGINT\", shutdown);\n process.removeListener(\"SIGTERM\", shutdown);\n llmock.stop().then(\n () => exit(0),\n (err) => {\n logError(`Shutdown error: ${err instanceof Error ? err.message : String(err)}`);\n exit(1);\n },\n );\n }\n process.on(\"SIGINT\", shutdown);\n process.on(\"SIGTERM\", shutdown);\n\n if (deps.onReady) {\n deps.onReady({ shutdown });\n }\n }\n\n main().catch((err) => {\n logError(err instanceof Error ? err.message : String(err));\n exit(1);\n });\n}\n\n// Run when executed as a script (not when imported for testing).\n/* v8 ignore start -- entry-point guard, exercised by integration tests */\nconst scriptName = process.argv[1] ?? \"\";\nif (scriptName.endsWith(\"aimock-cli.js\") || scriptName.endsWith(\"aimock-cli.ts\")) {\n runAimockCli();\n}\n/* v8 ignore stop */\n"],"mappings":";;;;;;;;;AAMA,MAAM,OAAO;;;;;;;;;;;;;EAaX,MAAM;AAaR,SAAgB,aAAa,OAAsB,EAAE,EAAQ;;CAE3D,MAAM,OAAO,KAAK,QAAQ,QAAQ,KAAK,MAAM,EAAE;CAC/C,MAAM,MAAM,KAAK,OAAO,QAAQ,IAAI,KAAK,QAAQ;CACjD,MAAM,WAAW,KAAK,YAAY,QAAQ,MAAM,KAAK,QAAQ;CAC7D,MAAM,OAAO,KAAK,QAAQ,QAAQ,KAAK,KAAK,QAAQ;CACpD,MAAM,eAAe,KAAK,gBAAgBA;CAC1C,MAAM,oBAAoB,KAAK,qBAAqBC;AAGpD,KAAI,KAAK,OAAO,WAAW;AACzB,gCAAc;GACZ,MAAM,KAAK,MAAM,EAAE;GACnB;GACA;GACA;GACA,GAAG,KAAK;GACT,CAAC;AACF;;CAGF,IAAI;AACJ,KAAI;AACF,GAAC,CAAE,mCAAqB;GACtB,MAAM;GACN,SAAS;IACP,QAAQ;KAAE,MAAM;KAAU,OAAO;KAAK;IACtC,MAAM;KAAE,MAAM;KAAU,OAAO;KAAK;IACpC,MAAM;KAAE,MAAM;KAAU,OAAO;KAAK;IACpC,MAAM;KAAE,MAAM;KAAW,SAAS;KAAO;IAC1C;GACD,QAAQ;GACT,CAAC;UACK,KAAK;AAGZ,WAAS,UADG,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,CACrC,MAAM,OAAO;AACpC,OAAK,EAAE;AACP;;AAGF,KAAI,OAAO,MAAM;AACf,MAAI,KAAK;AACT,OAAK,EAAE;AACP;;AAEF,KAAI,CAAC,OAAO,QAAQ;AAClB,WAAS,qCAAqC,KAAK;AACnD,OAAK,EAAE;AACP;;CAGF,MAAM,oCAAqB,OAAO,OAAO;CACzC,IAAI;AACJ,KAAI;AACF,WAAS,aAAa,WAAW;UAC1B,KAAK;AAEZ,WAAS,8BAA8B,WAAW,IADtC,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,GACA;AAC5D,OAAK,EAAE;AACP;;CAGF,MAAM,OAAO,OAAO,OAAO,OAAO,OAAO,KAAK,GAAG;AACjD,KACE,SAAS,WACR,OAAO,MAAM,KAAK,IAAI,CAAC,OAAO,UAAU,KAAK,IAAI,OAAO,KAAK,OAAO,QACrE;AACA,WAAS,wBAAwB,OAAO,KAAK,QAAQ,OAAO;AAC5D,OAAK,EAAE;AACP;;CAEF,MAAM,OAAO,OAAO;CAEpB,eAAe,OAAO;EACpB,MAAM,EAAE,QAAQ,QAAQ,MAAM,kBAAkB,QAAS;GAAE;GAAM;GAAM,CAAC;AACxE,MAAI,8BAA8B,MAAM;EAExC,SAAS,WAAW;AAClB,OAAI,mBAAmB;AACvB,WAAQ,eAAe,UAAU,SAAS;AAC1C,WAAQ,eAAe,WAAW,SAAS;AAC3C,UAAO,MAAM,CAAC,WACN,KAAK,EAAE,GACZ,QAAQ;AACP,aAAS,mBAAmB,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,GAAG;AAC/E,SAAK,EAAE;KAEV;;AAEH,UAAQ,GAAG,UAAU,SAAS;AAC9B,UAAQ,GAAG,WAAW,SAAS;AAE/B,MAAI,KAAK,QACP,MAAK,QAAQ,EAAE,UAAU,CAAC;;AAI9B,OAAM,CAAC,OAAO,QAAQ;AACpB,WAAS,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,CAAC;AAC1D,OAAK,EAAE;GACP;;;AAKJ,MAAM,aAAa,QAAQ,KAAK,MAAM;AACtC,IAAI,WAAW,SAAS,gBAAgB,IAAI,WAAW,SAAS,gBAAgB,CAC9E,eAAc"}
@@ -1,4 +1,5 @@
1
1
  import { loadConfig, startFromConfig } from "./config-loader.cjs";
2
+ import { ConvertCliDeps } from "./convert.cjs";
2
3
 
3
4
  //#region src/aimock-cli.d.ts
4
5
  interface AimockCliDeps {
@@ -11,6 +12,7 @@ interface AimockCliDeps {
11
12
  onReady?: (ctx: {
12
13
  shutdown: () => void;
13
14
  }) => void;
15
+ convertDeps?: Partial<ConvertCliDeps>;
14
16
  }
15
17
  declare function runAimockCli(deps?: AimockCliDeps): void;
16
18
  //# sourceMappingURL=aimock-cli.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"aimock-cli.d.cts","names":[],"sources":["../src/aimock-cli.ts"],"sourcesContent":[],"mappings":";;;UAeiB,aAAA;EAAA,IAAA,CAAA,EAAA,MAAA,EAAA;EAAa,GAAA,CAAA,EAAA,CAAA,GAAA,EAAA,MAAA,EAAA,GAAA,IAAA;UAKN,CAAA,EAAA,CAAA,GAAA,EAAA,MAAA,EAAA,GAAA,IAAA;MACK,CAAA,EAAA,CAAA,IAAA,EAAA,MAAA,EAAA,GAAA,IAAA;EAAe,YAAA,CAAA,EAAA,OADpB,UACoB;EAI5B,iBAAY,CAAA,EAAA,OAJC,eAIwB;;;;;iBAArC,YAAA,QAAmB"}
1
+ {"version":3,"file":"aimock-cli.d.cts","names":[],"sources":["../src/aimock-cli.ts"],"sourcesContent":[],"mappings":";;;;UAqBiB,aAAA;EAAA,IAAA,CAAA,EAAA,MAAA,EAAA;EAAa,GAAA,CAAA,EAAA,CAAA,GAAA,EAAA,MAAA,EAAA,GAAA,IAAA;UAKN,CAAA,EAAA,CAAA,GAAA,EAAA,MAAA,EAAA,GAAA,IAAA;MACK,CAAA,EAAA,CAAA,IAAA,EAAA,MAAA,EAAA,GAAA,IAAA;cAEL,CAAA,EAAA,OAHA,UAGA;mBAAR,CAAA,EAAA,OAFa,eAEb;EAAO,OAAA,CAAA,EAAA,CAAA,GAAA,EAAA;IAGP,QAAA,EAAA,GAAY,GAAA,IAAA;;gBAHZ,QAAQ;;iBAGR,YAAA,QAAmB"}
@@ -1,4 +1,5 @@
1
1
  import { loadConfig, startFromConfig } from "./config-loader.js";
2
+ import { ConvertCliDeps } from "./convert.js";
2
3
 
3
4
  //#region src/aimock-cli.d.ts
4
5
  interface AimockCliDeps {
@@ -11,6 +12,7 @@ interface AimockCliDeps {
11
12
  onReady?: (ctx: {
12
13
  shutdown: () => void;
13
14
  }) => void;
15
+ convertDeps?: Partial<ConvertCliDeps>;
14
16
  }
15
17
  declare function runAimockCli(deps?: AimockCliDeps): void;
16
18
  //# sourceMappingURL=aimock-cli.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"aimock-cli.d.ts","names":[],"sources":["../src/aimock-cli.ts"],"sourcesContent":[],"mappings":";;;UAeiB,aAAA;EAAA,IAAA,CAAA,EAAA,MAAA,EAAA;EAAa,GAAA,CAAA,EAAA,CAAA,GAAA,EAAA,MAAA,EAAA,GAAA,IAAA;UAKN,CAAA,EAAA,CAAA,GAAA,EAAA,MAAA,EAAA,GAAA,IAAA;MACK,CAAA,EAAA,CAAA,IAAA,EAAA,MAAA,EAAA,GAAA,IAAA;EAAe,YAAA,CAAA,EAAA,OADpB,UACoB;EAI5B,iBAAY,CAAA,EAAA,OAJC,eAIwB;;;;;iBAArC,YAAA,QAAmB"}
1
+ {"version":3,"file":"aimock-cli.d.ts","names":[],"sources":["../src/aimock-cli.ts"],"sourcesContent":[],"mappings":";;;;UAqBiB,aAAA;EAAA,IAAA,CAAA,EAAA,MAAA,EAAA;EAAa,GAAA,CAAA,EAAA,CAAA,GAAA,EAAA,MAAA,EAAA,GAAA,IAAA;UAKN,CAAA,EAAA,CAAA,GAAA,EAAA,MAAA,EAAA,GAAA,IAAA;MACK,CAAA,EAAA,CAAA,IAAA,EAAA,MAAA,EAAA,GAAA,IAAA;cAEL,CAAA,EAAA,OAHA,UAGA;mBAAR,CAAA,EAAA,OAFa,eAEb;EAAO,OAAA,CAAA,EAAA,CAAA,GAAA,EAAA;IAGP,QAAA,EAAA,GAAY,GAAA,IAAA;;gBAHZ,QAAQ;;iBAGR,YAAA,QAAmB"}
@@ -1,17 +1,23 @@
1
1
  #!/usr/bin/env node
2
2
  import { loadConfig, startFromConfig } from "./config-loader.js";
3
+ import { runConvertCli } from "./convert.js";
3
4
  import { parseArgs } from "node:util";
4
5
  import { resolve } from "node:path";
5
6
 
6
7
  //#region src/aimock-cli.ts
7
8
  const HELP = `
8
9
  Usage: aimock [options]
10
+ aimock convert <format> <input> [output]
9
11
 
10
12
  Options:
11
13
  -c, --config <path> Path to aimock config JSON file (required)
12
14
  -p, --port <number> Port override (default: from config or 0)
13
15
  -h, --host <string> Host override (default: from config or 127.0.0.1)
14
16
  --help Show this help message
17
+
18
+ Subcommands:
19
+ convert Convert third-party mock configs to aimock format
20
+ Run "aimock convert --help" for details
15
21
  `.trim();
16
22
  function runAimockCli(deps = {}) {
17
23
  /* v8 ignore next 6 -- defaults used only when called from CLI entry point */
@@ -21,6 +27,16 @@ function runAimockCli(deps = {}) {
21
27
  const exit = deps.exit ?? process.exit.bind(process);
22
28
  const loadConfigFn = deps.loadConfigFn ?? loadConfig;
23
29
  const startFromConfigFn = deps.startFromConfigFn ?? startFromConfig;
30
+ if (argv[0] === "convert") {
31
+ runConvertCli({
32
+ argv: argv.slice(1),
33
+ log,
34
+ logError,
35
+ exit,
36
+ ...deps.convertDeps
37
+ });
38
+ return;
39
+ }
24
40
  let values;
25
41
  try {
26
42
  ({values} = parseArgs({
@@ -1 +1 @@
1
- {"version":3,"file":"aimock-cli.js","names":[],"sources":["../src/aimock-cli.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { parseArgs } from \"node:util\";\nimport { resolve } from \"node:path\";\nimport { loadConfig, startFromConfig } from \"./config-loader.js\";\n\nconst HELP = `\nUsage: aimock [options]\n\nOptions:\n -c, --config <path> Path to aimock config JSON file (required)\n -p, --port <number> Port override (default: from config or 0)\n -h, --host <string> Host override (default: from config or 127.0.0.1)\n --help Show this help message\n`.trim();\n\nexport interface AimockCliDeps {\n argv?: string[];\n log?: (msg: string) => void;\n logError?: (msg: string) => void;\n exit?: (code: number) => void;\n loadConfigFn?: typeof loadConfig;\n startFromConfigFn?: typeof startFromConfig;\n onReady?: (ctx: { shutdown: () => void }) => void;\n}\n\nexport function runAimockCli(deps: AimockCliDeps = {}): void {\n /* v8 ignore next 6 -- defaults used only when called from CLI entry point */\n const argv = deps.argv ?? process.argv.slice(2);\n const log = deps.log ?? console.log.bind(console);\n const logError = deps.logError ?? console.error.bind(console);\n const exit = deps.exit ?? process.exit.bind(process);\n const loadConfigFn = deps.loadConfigFn ?? loadConfig;\n const startFromConfigFn = deps.startFromConfigFn ?? startFromConfig;\n\n let values;\n try {\n ({ values } = parseArgs({\n args: argv,\n options: {\n config: { type: \"string\", short: \"c\" },\n port: { type: \"string\", short: \"p\" },\n host: { type: \"string\", short: \"h\" },\n help: { type: \"boolean\", default: false },\n },\n strict: true,\n }));\n } catch (err) {\n /* v8 ignore next -- parseArgs always throws Error subclasses */\n const msg = err instanceof Error ? err.message : String(err);\n logError(`Error: ${msg}\\n\\n${HELP}`);\n exit(1);\n return;\n }\n\n if (values.help) {\n log(HELP);\n exit(0);\n return;\n }\n if (!values.config) {\n logError(\"Error: --config is required.\\n\\n\" + HELP);\n exit(1);\n return;\n }\n\n const configPath = resolve(values.config);\n let config;\n try {\n config = loadConfigFn(configPath);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n logError(`Failed to load config from ${configPath}: ${msg}`);\n exit(1);\n return;\n }\n\n const port = values.port ? Number(values.port) : undefined;\n if (\n port !== undefined &&\n (Number.isNaN(port) || !Number.isInteger(port) || port < 0 || port > 65535)\n ) {\n logError(`Error: invalid port \"${values.port}\".\\n\\n${HELP}`);\n exit(1);\n return;\n }\n const host = values.host;\n\n async function main() {\n const { llmock, url } = await startFromConfigFn(config!, { port, host });\n log(`aimock server listening on ${url}`);\n\n function shutdown() {\n log(\"Shutting down...\");\n process.removeListener(\"SIGINT\", shutdown);\n process.removeListener(\"SIGTERM\", shutdown);\n llmock.stop().then(\n () => exit(0),\n (err) => {\n logError(`Shutdown error: ${err instanceof Error ? err.message : String(err)}`);\n exit(1);\n },\n );\n }\n process.on(\"SIGINT\", shutdown);\n process.on(\"SIGTERM\", shutdown);\n\n if (deps.onReady) {\n deps.onReady({ shutdown });\n }\n }\n\n main().catch((err) => {\n logError(err instanceof Error ? err.message : String(err));\n exit(1);\n });\n}\n\n// Run when executed as a script (not when imported for testing).\n/* v8 ignore start -- entry-point guard, exercised by integration tests */\nconst scriptName = process.argv[1] ?? \"\";\nif (scriptName.endsWith(\"aimock-cli.js\") || scriptName.endsWith(\"aimock-cli.ts\")) {\n runAimockCli();\n}\n/* v8 ignore stop */\n"],"mappings":";;;;;;AAKA,MAAM,OAAO;;;;;;;;EAQX,MAAM;AAYR,SAAgB,aAAa,OAAsB,EAAE,EAAQ;;CAE3D,MAAM,OAAO,KAAK,QAAQ,QAAQ,KAAK,MAAM,EAAE;CAC/C,MAAM,MAAM,KAAK,OAAO,QAAQ,IAAI,KAAK,QAAQ;CACjD,MAAM,WAAW,KAAK,YAAY,QAAQ,MAAM,KAAK,QAAQ;CAC7D,MAAM,OAAO,KAAK,QAAQ,QAAQ,KAAK,KAAK,QAAQ;CACpD,MAAM,eAAe,KAAK,gBAAgB;CAC1C,MAAM,oBAAoB,KAAK,qBAAqB;CAEpD,IAAI;AACJ,KAAI;AACF,GAAC,CAAE,UAAW,UAAU;GACtB,MAAM;GACN,SAAS;IACP,QAAQ;KAAE,MAAM;KAAU,OAAO;KAAK;IACtC,MAAM;KAAE,MAAM;KAAU,OAAO;KAAK;IACpC,MAAM;KAAE,MAAM;KAAU,OAAO;KAAK;IACpC,MAAM;KAAE,MAAM;KAAW,SAAS;KAAO;IAC1C;GACD,QAAQ;GACT,CAAC;UACK,KAAK;AAGZ,WAAS,UADG,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,CACrC,MAAM,OAAO;AACpC,OAAK,EAAE;AACP;;AAGF,KAAI,OAAO,MAAM;AACf,MAAI,KAAK;AACT,OAAK,EAAE;AACP;;AAEF,KAAI,CAAC,OAAO,QAAQ;AAClB,WAAS,qCAAqC,KAAK;AACnD,OAAK,EAAE;AACP;;CAGF,MAAM,aAAa,QAAQ,OAAO,OAAO;CACzC,IAAI;AACJ,KAAI;AACF,WAAS,aAAa,WAAW;UAC1B,KAAK;AAEZ,WAAS,8BAA8B,WAAW,IADtC,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,GACA;AAC5D,OAAK,EAAE;AACP;;CAGF,MAAM,OAAO,OAAO,OAAO,OAAO,OAAO,KAAK,GAAG;AACjD,KACE,SAAS,WACR,OAAO,MAAM,KAAK,IAAI,CAAC,OAAO,UAAU,KAAK,IAAI,OAAO,KAAK,OAAO,QACrE;AACA,WAAS,wBAAwB,OAAO,KAAK,QAAQ,OAAO;AAC5D,OAAK,EAAE;AACP;;CAEF,MAAM,OAAO,OAAO;CAEpB,eAAe,OAAO;EACpB,MAAM,EAAE,QAAQ,QAAQ,MAAM,kBAAkB,QAAS;GAAE;GAAM;GAAM,CAAC;AACxE,MAAI,8BAA8B,MAAM;EAExC,SAAS,WAAW;AAClB,OAAI,mBAAmB;AACvB,WAAQ,eAAe,UAAU,SAAS;AAC1C,WAAQ,eAAe,WAAW,SAAS;AAC3C,UAAO,MAAM,CAAC,WACN,KAAK,EAAE,GACZ,QAAQ;AACP,aAAS,mBAAmB,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,GAAG;AAC/E,SAAK,EAAE;KAEV;;AAEH,UAAQ,GAAG,UAAU,SAAS;AAC9B,UAAQ,GAAG,WAAW,SAAS;AAE/B,MAAI,KAAK,QACP,MAAK,QAAQ,EAAE,UAAU,CAAC;;AAI9B,OAAM,CAAC,OAAO,QAAQ;AACpB,WAAS,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,CAAC;AAC1D,OAAK,EAAE;GACP;;;AAKJ,MAAM,aAAa,QAAQ,KAAK,MAAM;AACtC,IAAI,WAAW,SAAS,gBAAgB,IAAI,WAAW,SAAS,gBAAgB,CAC9E,eAAc"}
1
+ {"version":3,"file":"aimock-cli.js","names":[],"sources":["../src/aimock-cli.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { parseArgs } from \"node:util\";\nimport { resolve } from \"node:path\";\nimport { loadConfig, startFromConfig } from \"./config-loader.js\";\nimport { runConvertCli, type ConvertCliDeps } from \"./convert.js\";\n\nconst HELP = `\nUsage: aimock [options]\n aimock convert <format> <input> [output]\n\nOptions:\n -c, --config <path> Path to aimock config JSON file (required)\n -p, --port <number> Port override (default: from config or 0)\n -h, --host <string> Host override (default: from config or 127.0.0.1)\n --help Show this help message\n\nSubcommands:\n convert Convert third-party mock configs to aimock format\n Run \"aimock convert --help\" for details\n`.trim();\n\nexport interface AimockCliDeps {\n argv?: string[];\n log?: (msg: string) => void;\n logError?: (msg: string) => void;\n exit?: (code: number) => void;\n loadConfigFn?: typeof loadConfig;\n startFromConfigFn?: typeof startFromConfig;\n onReady?: (ctx: { shutdown: () => void }) => void;\n convertDeps?: Partial<ConvertCliDeps>;\n}\n\nexport function runAimockCli(deps: AimockCliDeps = {}): void {\n /* v8 ignore next 6 -- defaults used only when called from CLI entry point */\n const argv = deps.argv ?? process.argv.slice(2);\n const log = deps.log ?? console.log.bind(console);\n const logError = deps.logError ?? console.error.bind(console);\n const exit = deps.exit ?? process.exit.bind(process);\n const loadConfigFn = deps.loadConfigFn ?? loadConfig;\n const startFromConfigFn = deps.startFromConfigFn ?? startFromConfig;\n\n // Intercept \"convert\" subcommand before parseArgs (which uses strict mode)\n if (argv[0] === \"convert\") {\n runConvertCli({\n argv: argv.slice(1),\n log,\n logError,\n exit,\n ...deps.convertDeps,\n });\n return;\n }\n\n let values;\n try {\n ({ values } = parseArgs({\n args: argv,\n options: {\n config: { type: \"string\", short: \"c\" },\n port: { type: \"string\", short: \"p\" },\n host: { type: \"string\", short: \"h\" },\n help: { type: \"boolean\", default: false },\n },\n strict: true,\n }));\n } catch (err) {\n /* v8 ignore next -- parseArgs always throws Error subclasses */\n const msg = err instanceof Error ? err.message : String(err);\n logError(`Error: ${msg}\\n\\n${HELP}`);\n exit(1);\n return;\n }\n\n if (values.help) {\n log(HELP);\n exit(0);\n return;\n }\n if (!values.config) {\n logError(\"Error: --config is required.\\n\\n\" + HELP);\n exit(1);\n return;\n }\n\n const configPath = resolve(values.config);\n let config;\n try {\n config = loadConfigFn(configPath);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n logError(`Failed to load config from ${configPath}: ${msg}`);\n exit(1);\n return;\n }\n\n const port = values.port ? Number(values.port) : undefined;\n if (\n port !== undefined &&\n (Number.isNaN(port) || !Number.isInteger(port) || port < 0 || port > 65535)\n ) {\n logError(`Error: invalid port \"${values.port}\".\\n\\n${HELP}`);\n exit(1);\n return;\n }\n const host = values.host;\n\n async function main() {\n const { llmock, url } = await startFromConfigFn(config!, { port, host });\n log(`aimock server listening on ${url}`);\n\n function shutdown() {\n log(\"Shutting down...\");\n process.removeListener(\"SIGINT\", shutdown);\n process.removeListener(\"SIGTERM\", shutdown);\n llmock.stop().then(\n () => exit(0),\n (err) => {\n logError(`Shutdown error: ${err instanceof Error ? err.message : String(err)}`);\n exit(1);\n },\n );\n }\n process.on(\"SIGINT\", shutdown);\n process.on(\"SIGTERM\", shutdown);\n\n if (deps.onReady) {\n deps.onReady({ shutdown });\n }\n }\n\n main().catch((err) => {\n logError(err instanceof Error ? err.message : String(err));\n exit(1);\n });\n}\n\n// Run when executed as a script (not when imported for testing).\n/* v8 ignore start -- entry-point guard, exercised by integration tests */\nconst scriptName = process.argv[1] ?? \"\";\nif (scriptName.endsWith(\"aimock-cli.js\") || scriptName.endsWith(\"aimock-cli.ts\")) {\n runAimockCli();\n}\n/* v8 ignore stop */\n"],"mappings":";;;;;;;AAMA,MAAM,OAAO;;;;;;;;;;;;;EAaX,MAAM;AAaR,SAAgB,aAAa,OAAsB,EAAE,EAAQ;;CAE3D,MAAM,OAAO,KAAK,QAAQ,QAAQ,KAAK,MAAM,EAAE;CAC/C,MAAM,MAAM,KAAK,OAAO,QAAQ,IAAI,KAAK,QAAQ;CACjD,MAAM,WAAW,KAAK,YAAY,QAAQ,MAAM,KAAK,QAAQ;CAC7D,MAAM,OAAO,KAAK,QAAQ,QAAQ,KAAK,KAAK,QAAQ;CACpD,MAAM,eAAe,KAAK,gBAAgB;CAC1C,MAAM,oBAAoB,KAAK,qBAAqB;AAGpD,KAAI,KAAK,OAAO,WAAW;AACzB,gBAAc;GACZ,MAAM,KAAK,MAAM,EAAE;GACnB;GACA;GACA;GACA,GAAG,KAAK;GACT,CAAC;AACF;;CAGF,IAAI;AACJ,KAAI;AACF,GAAC,CAAE,UAAW,UAAU;GACtB,MAAM;GACN,SAAS;IACP,QAAQ;KAAE,MAAM;KAAU,OAAO;KAAK;IACtC,MAAM;KAAE,MAAM;KAAU,OAAO;KAAK;IACpC,MAAM;KAAE,MAAM;KAAU,OAAO;KAAK;IACpC,MAAM;KAAE,MAAM;KAAW,SAAS;KAAO;IAC1C;GACD,QAAQ;GACT,CAAC;UACK,KAAK;AAGZ,WAAS,UADG,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,CACrC,MAAM,OAAO;AACpC,OAAK,EAAE;AACP;;AAGF,KAAI,OAAO,MAAM;AACf,MAAI,KAAK;AACT,OAAK,EAAE;AACP;;AAEF,KAAI,CAAC,OAAO,QAAQ;AAClB,WAAS,qCAAqC,KAAK;AACnD,OAAK,EAAE;AACP;;CAGF,MAAM,aAAa,QAAQ,OAAO,OAAO;CACzC,IAAI;AACJ,KAAI;AACF,WAAS,aAAa,WAAW;UAC1B,KAAK;AAEZ,WAAS,8BAA8B,WAAW,IADtC,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,GACA;AAC5D,OAAK,EAAE;AACP;;CAGF,MAAM,OAAO,OAAO,OAAO,OAAO,OAAO,KAAK,GAAG;AACjD,KACE,SAAS,WACR,OAAO,MAAM,KAAK,IAAI,CAAC,OAAO,UAAU,KAAK,IAAI,OAAO,KAAK,OAAO,QACrE;AACA,WAAS,wBAAwB,OAAO,KAAK,QAAQ,OAAO;AAC5D,OAAK,EAAE;AACP;;CAEF,MAAM,OAAO,OAAO;CAEpB,eAAe,OAAO;EACpB,MAAM,EAAE,QAAQ,QAAQ,MAAM,kBAAkB,QAAS;GAAE;GAAM;GAAM,CAAC;AACxE,MAAI,8BAA8B,MAAM;EAExC,SAAS,WAAW;AAClB,OAAI,mBAAmB;AACvB,WAAQ,eAAe,UAAU,SAAS;AAC1C,WAAQ,eAAe,WAAW,SAAS;AAC3C,UAAO,MAAM,CAAC,WACN,KAAK,EAAE,GACZ,QAAQ;AACP,aAAS,mBAAmB,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,GAAG;AAC/E,SAAK,EAAE;KAEV;;AAEH,UAAQ,GAAG,UAAU,SAAS;AAC9B,UAAQ,GAAG,WAAW,SAAS;AAE/B,MAAI,KAAK,QACP,MAAK,QAAQ,EAAE,UAAU,CAAC;;AAI9B,OAAM,CAAC,OAAO,QAAQ;AACpB,WAAS,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,CAAC;AAC1D,OAAK,EAAE;GACP;;;AAKJ,MAAM,aAAa,QAAQ,KAAK,MAAM;AACtC,IAAI,WAAW,SAAS,gBAAgB,IAAI,WAAW,SAAS,gBAAgB,CAC9E,eAAc"}
@@ -1 +1 @@
1
- {"version":3,"file":"config-loader.d.cts","names":[],"sources":["../src/config-loader.ts"],"sourcesContent":[],"mappings":";;;;;;;;UAciB,aAAA,SAAsB;;AAAvC;AAIiB,UAAA,iBAAA,CAAiB;EASjB,GAAA,EAAA,MAAA;EAAgB,IAAA,EAAA,MAAA;UAEnB,CAAA,EAAA,MAAA;aAF2B,CAAA,EAAA,MAAA;EAAmB,IAAA,CAAA,EAAA,MAAA;EAM3C,IAAA,CAAA,EAAA,MAAS;;AAGhB,UATO,eAAA,SAAwB,mBAS/B,CAAA;QACI,CAAA,EAAA;IACF,QAAA,EATE,KASF,CAAA;MAAe,IAAA,EAAA,MAAA;MAGV,OAAA,EAAA;QAAgB,IAAA,EAAA,MAAA;QAEvB,IAAA,EAAA,MAAA;MACI,CAAA;IACH,CAAA,CAAA;EAAc,CAAA;AAIzB;AAAgC,UAhBf,SAAA,CAgBe;MACnB,CAAA,EAAA,MAAA;YACH,CAAA,EAAA;IACS,IAAA,EAAA,MAAA;IAHqB,OAAA,EAAA,MAAA;EAAkB,CAAA;EAMzC,KAAA,CAAA,EAnBP,aAmBgB,EAEf;EAGM,SAAA,CAAA,EAvBH,iBAuBoB,EAGvB;EAIM,OAAA,CAAA,EA7BL,eA+BC,EAAA;AAGb;AAAuC,UA/BtB,gBAAA,CA+BsB;SAMxB,EAAA,MAAA;OAHH,CAAA,EAhCF,OAgCE,EAAA;WAKK,CAAA,EApCH,WAoCG,EAAA;EAAW,MAAA,CAAA,EAnCjB,cAmCiB,EAAA;EAGX,OAAA,CAAA,EAAA,MAAY;AAK7B;AAA6B,UAvCZ,cAAA,SAAuB,kBAuCX,CAAA;UAGjB,CAAA,EAzCC,gBAyCD,EAAA;OACC,CAAA,EAzCH,gBAyCG,EAAA;gBAEL,CAAA,EA1CW,gBA0CX,EAAA;;AAEC,UAzCQ,SAAA,CAyCR;MACE,CAAA,EAAA,MAAA;EAAY,MAAA,CAAA,EAxCZ,cAwCY,EAAA;AAQvB;AAKsB,UAlDL,iBAAA,CAkDoB;EAAA,KAAA,EAAA;IAC3B,OAAA,CAAA,EAAA,MAAA;IAEW,QAAA,CAAA,EAAA,MAAA;IAAlB,QAAA,CAAA,EAAA,MAAA;EAAO,CAAA;;WAlDC;;;UAIM,UAAA;;aAEJ;;UAGI,sBAAA;;;YAGL;;;eAGG;;iBAEE;;UAGA,YAAA;;gBAED;;UAGC,YAAA;;;YAGL;aACC;;QAEL;QACA;SACC;WACE;;;;;;;;;;;iBAQK,UAAA,sBAAgC;iBAK1B,eAAA,SACZ;;;IAEP;UAAkB"}
1
+ {"version":3,"file":"config-loader.d.cts","names":[],"sources":["../src/config-loader.ts"],"sourcesContent":[],"mappings":";;;;;;;;UAciB,aAAA,SAAsB;;AAAvC;AAIiB,UAAA,iBAAA,CAAiB;EASjB,GAAA,EAAA,MAAA;EAAgB,IAAA,EAAA,MAAA;UAEnB,CAAA,EAAA,MAAA;aAF2B,CAAA,EAAA,MAAA;EAAmB,IAAA,CAAA,EAAA,MAAA;EAM3C,IAAA,CAAA,EAAA,MAAS;;AAGhB,UATO,eAAA,SAAwB,mBAS/B,CAAA;QACI,CAAA,EAAA;IACF,QAAA,EATE,KASF,CAAA;MAAe,IAAA,EAAA,MAAA;MAGV,OAAA,EAAA;QAAgB,IAAA,EAAA,MAAA;QAEvB,IAAA,EAAA,MAAA;MACI,CAAA;IACH,CAAA,CAAA;EAAc,CAAA;AAIzB;AAAgC,UAhBf,SAAA,CAgBe;MACnB,CAAA,EAAA,MAAA;YACH,CAAA,EAAA;IACS,IAAA,EAAA,MAAA;IAHqB,OAAA,EAAA,MAAA;EAAkB,CAAA;EAMzC,KAAA,CAAA,EAnBP,aAmBgB,EAAA;EAKT,SAAA,CAAA,EAvBH,iBAuBoB,EAAA;EAOjB,OAAA,CAAA,EA7BL,eA+BC,EAAA;AAGb;AAAuC,UA/BtB,gBAAA,CA+BsB;SAMxB,EAAA,MAAA;OAHH,CAAA,EAhCF,OAgCE,EAAA;WAKK,CAAA,EApCH,WAoCG,EAAA;EAAW,MAAA,CAAA,EAnCjB,cAmCiB,EAAA;EAGX,OAAA,CAAA,EAAA,MAAY;AAK7B;AAA6B,UAvCZ,cAAA,SAAuB,kBAuCX,CAAA;UAGjB,CAAA,EAzCC,gBAyCD,EAAA;OACC,CAAA,EAzCH,gBAyCG,EAAA;gBAEL,CAAA,EA1CW,gBA0CX,EAAA;;AAEC,UAzCQ,SAAA,CAyCR;MACE,CAAA,EAAA,MAAA;EAAY,MAAA,CAAA,EAxCZ,cAwCY,EAAA;AAQvB;AAKsB,UAlDL,iBAAA,CAkDoB;EAAA,KAAA,EAAA;IAC3B,OAAA,CAAA,EAAA,MAAA;IAEW,QAAA,CAAA,EAAA,MAAA;IAAlB,QAAA,CAAA,EAAA,MAAA;EAAO,CAAA;;WAlDC;;;UAIM,UAAA;;aAEJ;;UAGI,sBAAA;;;YAGL;;;eAGG;;iBAEE;;UAGA,YAAA;;gBAED;;UAGC,YAAA;;;YAGL;aACC;;QAEL;QACA;SACC;WACE;;;;;;;;;;;iBAQK,UAAA,sBAAgC;iBAK1B,eAAA,SACZ;;;IAEP;UAAkB"}
@@ -0,0 +1,232 @@
1
+
2
+ //#region src/convert-mockllm.ts
3
+ function tokenizeYamlLines(input) {
4
+ const lines = [];
5
+ for (const raw of input.split("\n")) {
6
+ const trimmed = raw.trimStart();
7
+ if (trimmed === "" || trimmed.startsWith("#")) continue;
8
+ const indent = raw.length - raw.trimStart().length;
9
+ const content = stripTrailingComment(trimmed);
10
+ const isArrayItem = content.startsWith("- ");
11
+ const arrayItemContent = isArrayItem ? content.slice(2).trim() : "";
12
+ lines.push({
13
+ indent,
14
+ raw,
15
+ content,
16
+ isArrayItem,
17
+ arrayItemContent
18
+ });
19
+ }
20
+ return lines;
21
+ }
22
+ function stripTrailingComment(s) {
23
+ let inSingle = false;
24
+ let inDouble = false;
25
+ for (let i = 0; i < s.length; i++) {
26
+ const ch = s[i];
27
+ if (ch === "'" && !inDouble) inSingle = !inSingle;
28
+ if (ch === "\"" && !inSingle) inDouble = !inDouble;
29
+ if (ch === "#" && !inSingle && !inDouble && i > 0 && s[i - 1] === " ") return s.slice(0, i).trimEnd();
30
+ }
31
+ return s;
32
+ }
33
+ function parseScalar(value) {
34
+ if (value === "" || value === "~" || value === "null") return null;
35
+ if (value === "true") return true;
36
+ if (value === "false") return false;
37
+ if (value.startsWith("\"") && value.endsWith("\"") || value.startsWith("'") && value.endsWith("'")) return value.slice(1, -1);
38
+ const num = Number(value);
39
+ if (!Number.isNaN(num) && value !== "") return num;
40
+ return value;
41
+ }
42
+ function parseSimpleYaml(input) {
43
+ const lines = tokenizeYamlLines(input);
44
+ if (lines.length === 0) return null;
45
+ return parseBlock(lines, 0, 0).value;
46
+ }
47
+ function parseBlock(lines, startIndex, minIndent) {
48
+ if (startIndex >= lines.length) return {
49
+ value: null,
50
+ nextIndex: startIndex
51
+ };
52
+ const line = lines[startIndex];
53
+ if (line.isArrayItem && line.indent >= minIndent) return parseArray(lines, startIndex, line.indent);
54
+ if (line.content.includes(":")) return parseMap(lines, startIndex, line.indent);
55
+ return {
56
+ value: parseScalar(line.content),
57
+ nextIndex: startIndex + 1
58
+ };
59
+ }
60
+ function parseArray(lines, startIndex, baseIndent) {
61
+ const arr = [];
62
+ let i = startIndex;
63
+ while (i < lines.length) {
64
+ const line = lines[i];
65
+ if (line.indent < baseIndent) break;
66
+ if (line.indent > baseIndent) break;
67
+ if (!line.isArrayItem) break;
68
+ const itemContent = line.arrayItemContent;
69
+ if (itemContent === "") {
70
+ const nested = parseBlock(lines, i + 1, baseIndent + 1);
71
+ arr.push(nested.value);
72
+ i = nested.nextIndex;
73
+ } else if (itemContent.includes(":")) {
74
+ const inlineMap = parseArrayItemMap(lines, i, baseIndent);
75
+ arr.push(inlineMap.value);
76
+ i = inlineMap.nextIndex;
77
+ } else {
78
+ arr.push(parseScalar(itemContent));
79
+ i++;
80
+ }
81
+ }
82
+ return {
83
+ value: arr,
84
+ nextIndex: i
85
+ };
86
+ }
87
+ function parseArrayItemMap(lines, startIndex, arrayIndent) {
88
+ const map = {};
89
+ const firstContent = lines[startIndex].arrayItemContent;
90
+ const colonIdx = findColon(firstContent);
91
+ if (colonIdx === -1) return {
92
+ value: parseScalar(firstContent),
93
+ nextIndex: startIndex + 1
94
+ };
95
+ const key = firstContent.slice(0, colonIdx).trim();
96
+ const valueStr = firstContent.slice(colonIdx + 1).trim();
97
+ if (valueStr === "") {
98
+ const nested = parseBlock(lines, startIndex + 1, arrayIndent + 2);
99
+ map[key] = nested.value;
100
+ let i = nested.nextIndex;
101
+ const siblingIndent = arrayIndent + 2;
102
+ while (i < lines.length && lines[i].indent >= siblingIndent && !lines[i].isArrayItem) if (lines[i].indent === siblingIndent || lines[i].indent > siblingIndent) if (lines[i].indent === siblingIndent && lines[i].content.includes(":")) i = parseMapEntries(lines, i, siblingIndent, map).nextIndex;
103
+ else break;
104
+ return {
105
+ value: map,
106
+ nextIndex: i
107
+ };
108
+ } else map[key] = parseScalar(valueStr);
109
+ let i = startIndex + 1;
110
+ const contentIndent = arrayIndent + 2;
111
+ while (i < lines.length) {
112
+ const line = lines[i];
113
+ if (line.indent < contentIndent) break;
114
+ if (line.isArrayItem && line.indent <= arrayIndent) break;
115
+ if (line.indent === contentIndent && !line.isArrayItem && line.content.includes(":")) {
116
+ const colonPos = findColon(line.content);
117
+ if (colonPos === -1) break;
118
+ const k = line.content.slice(0, colonPos).trim();
119
+ const v = line.content.slice(colonPos + 1).trim();
120
+ if (v === "") {
121
+ const nested = parseBlock(lines, i + 1, contentIndent + 1);
122
+ map[k] = nested.value;
123
+ i = nested.nextIndex;
124
+ } else {
125
+ map[k] = parseScalar(v);
126
+ i++;
127
+ }
128
+ } else if (line.indent === contentIndent && line.isArrayItem) break;
129
+ else if (line.indent > contentIndent) i++;
130
+ else break;
131
+ }
132
+ return {
133
+ value: map,
134
+ nextIndex: i
135
+ };
136
+ }
137
+ function parseMap(lines, startIndex, baseIndent) {
138
+ const map = {};
139
+ return {
140
+ value: map,
141
+ nextIndex: parseMapEntries(lines, startIndex, baseIndent, map).nextIndex
142
+ };
143
+ }
144
+ function parseMapEntries(lines, startIndex, baseIndent, map) {
145
+ let i = startIndex;
146
+ while (i < lines.length) {
147
+ const line = lines[i];
148
+ if (line.indent < baseIndent) break;
149
+ if (line.indent > baseIndent) {
150
+ i++;
151
+ continue;
152
+ }
153
+ if (line.isArrayItem) break;
154
+ const colonIdx = findColon(line.content);
155
+ if (colonIdx === -1) break;
156
+ const key = line.content.slice(0, colonIdx).trim();
157
+ const valueStr = line.content.slice(colonIdx + 1).trim();
158
+ if (valueStr === "") {
159
+ const nested = parseBlock(lines, i + 1, baseIndent + 1);
160
+ map[key] = nested.value;
161
+ i = nested.nextIndex;
162
+ } else {
163
+ map[key] = parseScalar(valueStr);
164
+ i++;
165
+ }
166
+ }
167
+ return {
168
+ value: map,
169
+ nextIndex: i
170
+ };
171
+ }
172
+ function findColon(s) {
173
+ let inSingle = false;
174
+ let inDouble = false;
175
+ for (let i = 0; i < s.length; i++) {
176
+ const ch = s[i];
177
+ if (ch === "'" && !inDouble) inSingle = !inSingle;
178
+ if (ch === "\"" && !inSingle) inDouble = !inDouble;
179
+ if (ch === ":" && !inSingle && !inDouble) {
180
+ if (i === s.length - 1 || s[i + 1] === " ") return i;
181
+ }
182
+ }
183
+ return -1;
184
+ }
185
+ function convertConfig(config) {
186
+ const fixtures = [];
187
+ if (config.routes) for (const route of config.routes) {
188
+ const fixture = convertRoute(route);
189
+ if (fixture) fixtures.push(fixture);
190
+ }
191
+ const result = { fixtures };
192
+ if (config.mcp?.tools && config.mcp.tools.length > 0) result.mcpTools = config.mcp.tools.map(convertMCPTool);
193
+ return result;
194
+ }
195
+ function convertRoute(route) {
196
+ const content = extractResponseContent(route.response);
197
+ if (content === null) return null;
198
+ const fixture = {
199
+ match: {},
200
+ response: { content }
201
+ };
202
+ const userMessage = extractUserMessage(route);
203
+ if (userMessage) fixture.match = { userMessage };
204
+ else fixture._comment = `${route.method ?? "POST"} ${route.path}`;
205
+ return fixture;
206
+ }
207
+ function extractResponseContent(response) {
208
+ const choices = response.choices;
209
+ if (!Array.isArray(choices) || choices.length === 0) return null;
210
+ const message = choices[0].message;
211
+ if (!message) return null;
212
+ const content = message.content;
213
+ if (typeof content !== "string") return null;
214
+ return content;
215
+ }
216
+ function extractUserMessage(route) {
217
+ const messages = route.match?.body?.messages;
218
+ if (!Array.isArray(messages) || messages.length === 0) return null;
219
+ for (let i = messages.length - 1; i >= 0; i--) if (messages[i].role === "user") return messages[i].content;
220
+ return messages[messages.length - 1].content ?? null;
221
+ }
222
+ function convertMCPTool(tool) {
223
+ const result = { name: tool.name };
224
+ if (tool.description) result.description = tool.description;
225
+ if (tool.parameters) result.inputSchema = tool.parameters;
226
+ return result;
227
+ }
228
+
229
+ //#endregion
230
+ exports.convertConfig = convertConfig;
231
+ exports.parseSimpleYaml = parseSimpleYaml;
232
+ //# sourceMappingURL=convert-mockllm.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"convert-mockllm.cjs","names":[],"sources":["../src/convert-mockllm.ts"],"sourcesContent":["/**\n * mock-llm (dwmkerr) -> aimock fixture converter\n *\n * Core conversion logic. Used by both the CLI (`aimock convert mockllm`)\n * and the standalone script (`scripts/convert-mockllm.ts`).\n */\n\n// ---------------------------------------------------------------------------\n// Minimal YAML parser\n// ---------------------------------------------------------------------------\n// Handles the subset used by mock-llm configs: indented maps, arrays with\n// `-` prefix, quoted/unquoted strings, numbers, booleans, and null.\n// Does NOT handle: anchors, aliases, multi-line scalars, flow collections,\n// tags, or other advanced YAML features.\n\ninterface YamlLine {\n indent: number;\n raw: string;\n content: string; // trimmed, without trailing comment\n isArrayItem: boolean;\n arrayItemContent: string; // content after \"- \"\n}\n\nfunction tokenizeYamlLines(input: string): YamlLine[] {\n const lines: YamlLine[] = [];\n for (const raw of input.split(\"\\n\")) {\n // Skip blank lines and full-line comments\n const trimmed = raw.trimStart();\n if (trimmed === \"\" || trimmed.startsWith(\"#\")) continue;\n\n const indent = raw.length - raw.trimStart().length;\n // Strip trailing comments (but not inside quoted strings)\n const content = stripTrailingComment(trimmed);\n const isArrayItem = content.startsWith(\"- \");\n const arrayItemContent = isArrayItem ? content.slice(2).trim() : \"\";\n\n lines.push({ indent, raw, content, isArrayItem, arrayItemContent });\n }\n return lines;\n}\n\nfunction stripTrailingComment(s: string): string {\n // Naive: find # not inside quotes\n let inSingle = false;\n let inDouble = false;\n for (let i = 0; i < s.length; i++) {\n const ch = s[i];\n if (ch === \"'\" && !inDouble) inSingle = !inSingle;\n if (ch === '\"' && !inSingle) inDouble = !inDouble;\n if (ch === \"#\" && !inSingle && !inDouble && i > 0 && s[i - 1] === \" \") {\n return s.slice(0, i).trimEnd();\n }\n }\n return s;\n}\n\nfunction parseScalar(value: string): unknown {\n if (value === \"\" || value === \"~\" || value === \"null\") return null;\n if (value === \"true\") return true;\n if (value === \"false\") return false;\n\n // Quoted string\n if (\n (value.startsWith('\"') && value.endsWith('\"')) ||\n (value.startsWith(\"'\") && value.endsWith(\"'\"))\n ) {\n return value.slice(1, -1);\n }\n\n // Number\n const num = Number(value);\n if (!Number.isNaN(num) && value !== \"\") return num;\n\n // Unquoted string\n return value;\n}\n\nexport function parseSimpleYaml(input: string): unknown {\n const lines = tokenizeYamlLines(input);\n if (lines.length === 0) return null;\n\n const result = parseBlock(lines, 0, 0);\n return result.value;\n}\n\ninterface ParseResult {\n value: unknown;\n nextIndex: number;\n}\n\nfunction parseBlock(lines: YamlLine[], startIndex: number, minIndent: number): ParseResult {\n if (startIndex >= lines.length) {\n return { value: null, nextIndex: startIndex };\n }\n\n const line = lines[startIndex];\n\n // Determine if this block is an array or a map\n if (line.isArrayItem && line.indent >= minIndent) {\n return parseArray(lines, startIndex, line.indent);\n }\n\n // Map\n if (line.content.includes(\":\")) {\n return parseMap(lines, startIndex, line.indent);\n }\n\n // Single scalar\n return { value: parseScalar(line.content), nextIndex: startIndex + 1 };\n}\n\nfunction parseArray(lines: YamlLine[], startIndex: number, baseIndent: number): ParseResult {\n const arr: unknown[] = [];\n let i = startIndex;\n\n while (i < lines.length) {\n const line = lines[i];\n if (line.indent < baseIndent) break;\n if (line.indent > baseIndent) break; // shouldn't happen at array level\n if (!line.isArrayItem) break;\n\n const itemContent = line.arrayItemContent;\n\n if (itemContent === \"\") {\n // Array item with nested block on next lines\n const nested = parseBlock(lines, i + 1, baseIndent + 1);\n arr.push(nested.value);\n i = nested.nextIndex;\n } else if (itemContent.includes(\":\")) {\n // Inline map start: \"- key: value\" possibly with more keys below\n // Parse as a map, treating the \"- \" offset as extra indent\n const inlineMap = parseArrayItemMap(lines, i, baseIndent);\n arr.push(inlineMap.value);\n i = inlineMap.nextIndex;\n } else {\n // Simple scalar array item\n arr.push(parseScalar(itemContent));\n i++;\n }\n }\n\n return { value: arr, nextIndex: i };\n}\n\nfunction parseArrayItemMap(\n lines: YamlLine[],\n startIndex: number,\n arrayIndent: number,\n): ParseResult {\n // First line is \"- key: value\", subsequent lines at indent > arrayIndent are part of this map\n const map: Record<string, unknown> = {};\n const firstLine = lines[startIndex];\n const firstContent = firstLine.arrayItemContent;\n\n // Parse the first key: value from the array item line\n const colonIdx = findColon(firstContent);\n if (colonIdx === -1) {\n return { value: parseScalar(firstContent), nextIndex: startIndex + 1 };\n }\n\n const key = firstContent.slice(0, colonIdx).trim();\n const valueStr = firstContent.slice(colonIdx + 1).trim();\n\n if (valueStr === \"\") {\n // Value is a nested block\n const nested = parseBlock(lines, startIndex + 1, arrayIndent + 2);\n map[key] = nested.value;\n let i = nested.nextIndex;\n\n // Continue reading sibling keys at the array-item's content indent\n const siblingIndent = arrayIndent + 2;\n while (i < lines.length && lines[i].indent >= siblingIndent && !lines[i].isArrayItem) {\n if (lines[i].indent === siblingIndent || lines[i].indent > siblingIndent) {\n // Only parse if at exactly sibling indent and is a map key\n if (lines[i].indent === siblingIndent && lines[i].content.includes(\":\")) {\n const mapResult = parseMapEntries(lines, i, siblingIndent, map);\n i = mapResult.nextIndex;\n } else {\n break;\n }\n }\n }\n\n return { value: map, nextIndex: i };\n } else {\n map[key] = parseScalar(valueStr);\n }\n\n // Read additional keys at indent > arrayIndent (the \" key: value\" lines after \"- first: val\")\n let i = startIndex + 1;\n const contentIndent = arrayIndent + 2; // \"- \" adds 2 to effective indent\n\n while (i < lines.length) {\n const line = lines[i];\n if (line.indent < contentIndent) break;\n if (line.isArrayItem && line.indent <= arrayIndent) break;\n\n if (line.indent === contentIndent && !line.isArrayItem && line.content.includes(\":\")) {\n const colonPos = findColon(line.content);\n if (colonPos === -1) break;\n const k = line.content.slice(0, colonPos).trim();\n const v = line.content.slice(colonPos + 1).trim();\n\n if (v === \"\") {\n const nested = parseBlock(lines, i + 1, contentIndent + 1);\n map[k] = nested.value;\n i = nested.nextIndex;\n } else {\n map[k] = parseScalar(v);\n i++;\n }\n } else if (line.indent === contentIndent && line.isArrayItem) {\n // This is a new array item at the same level -- not part of this map\n break;\n } else if (line.indent > contentIndent) {\n // Skip nested content already consumed\n i++;\n } else {\n break;\n }\n }\n\n return { value: map, nextIndex: i };\n}\n\nfunction parseMap(lines: YamlLine[], startIndex: number, baseIndent: number): ParseResult {\n const map: Record<string, unknown> = {};\n const result = parseMapEntries(lines, startIndex, baseIndent, map);\n return { value: map, nextIndex: result.nextIndex };\n}\n\nfunction parseMapEntries(\n lines: YamlLine[],\n startIndex: number,\n baseIndent: number,\n map: Record<string, unknown>,\n): ParseResult {\n let i = startIndex;\n\n while (i < lines.length) {\n const line = lines[i];\n if (line.indent < baseIndent) break;\n if (line.indent > baseIndent) {\n // Shouldn't happen at map level if properly structured -- skip\n i++;\n continue;\n }\n if (line.isArrayItem) break;\n\n const colonIdx = findColon(line.content);\n if (colonIdx === -1) {\n // Not a map entry\n break;\n }\n\n const key = line.content.slice(0, colonIdx).trim();\n const valueStr = line.content.slice(colonIdx + 1).trim();\n\n if (valueStr === \"\") {\n // Value is a nested block on subsequent lines\n const nested = parseBlock(lines, i + 1, baseIndent + 1);\n map[key] = nested.value;\n i = nested.nextIndex;\n } else {\n map[key] = parseScalar(valueStr);\n i++;\n }\n }\n\n return { value: map, nextIndex: i };\n}\n\nfunction findColon(s: string): number {\n let inSingle = false;\n let inDouble = false;\n for (let i = 0; i < s.length; i++) {\n const ch = s[i];\n if (ch === \"'\" && !inDouble) inSingle = !inSingle;\n if (ch === '\"' && !inSingle) inDouble = !inDouble;\n if (ch === \":\" && !inSingle && !inDouble) {\n // Must be followed by space, end of line, or nothing\n if (i === s.length - 1 || s[i + 1] === \" \") {\n return i;\n }\n }\n }\n return -1;\n}\n\n// ---------------------------------------------------------------------------\n// mock-llm config types\n// ---------------------------------------------------------------------------\n\nexport interface MockLLMRoute {\n path: string;\n method?: string;\n match?: {\n body?: {\n messages?: Array<{ role: string; content: string }>;\n };\n };\n response: Record<string, unknown>;\n}\n\nexport interface MockLLMTool {\n name: string;\n description?: string;\n parameters?: Record<string, unknown>;\n}\n\nexport interface MockLLMConfig {\n routes?: MockLLMRoute[];\n mcp?: {\n tools?: MockLLMTool[];\n };\n}\n\n// ---------------------------------------------------------------------------\n// aimock output types\n// ---------------------------------------------------------------------------\n\nexport interface AimockFixture {\n match?: { userMessage?: string };\n response: { content?: string; toolCalls?: Array<{ name: string; arguments: string }> };\n _comment?: string;\n}\n\nexport interface AimockMCPTool {\n name: string;\n description?: string;\n inputSchema?: Record<string, unknown>;\n}\n\nexport interface ConvertResult {\n fixtures: AimockFixture[];\n mcpTools?: AimockMCPTool[];\n}\n\n// ---------------------------------------------------------------------------\n// Converter\n// ---------------------------------------------------------------------------\n\nexport function convertConfig(config: MockLLMConfig): ConvertResult {\n const fixtures: AimockFixture[] = [];\n\n if (config.routes) {\n for (const route of config.routes) {\n const fixture = convertRoute(route);\n if (fixture) {\n fixtures.push(fixture);\n }\n }\n }\n\n const result: ConvertResult = { fixtures };\n\n if (config.mcp?.tools && config.mcp.tools.length > 0) {\n result.mcpTools = config.mcp.tools.map(convertMCPTool);\n }\n\n return result;\n}\n\nfunction convertRoute(route: MockLLMRoute): AimockFixture | null {\n // Extract content from response.choices[0].message.content\n const content = extractResponseContent(route.response);\n if (content === null) return null;\n\n const fixture: AimockFixture = {\n match: {},\n response: { content },\n };\n\n // Extract match criteria from match.body.messages\n const userMessage = extractUserMessage(route);\n if (userMessage) {\n fixture.match = { userMessage };\n } else {\n // Use path as a comment/identifier when no match criteria\n fixture._comment = `${route.method ?? \"POST\"} ${route.path}`;\n }\n\n return fixture;\n}\n\nfunction extractResponseContent(response: Record<string, unknown>): string | null {\n const choices = response.choices as Array<Record<string, unknown>> | undefined;\n if (!Array.isArray(choices) || choices.length === 0) return null;\n\n const firstChoice = choices[0];\n const message = firstChoice.message as Record<string, unknown> | undefined;\n if (!message) return null;\n\n const content = message.content;\n if (typeof content !== \"string\") return null;\n\n return content;\n}\n\nfunction extractUserMessage(route: MockLLMRoute): string | null {\n const messages = route.match?.body?.messages;\n if (!Array.isArray(messages) || messages.length === 0) return null;\n\n // Find the last user message\n for (let i = messages.length - 1; i >= 0; i--) {\n if (messages[i].role === \"user\") {\n return messages[i].content;\n }\n }\n\n // Fall back to last message content regardless of role\n return messages[messages.length - 1].content ?? null;\n}\n\nfunction convertMCPTool(tool: MockLLMTool): AimockMCPTool {\n const result: AimockMCPTool = { name: tool.name };\n if (tool.description) result.description = tool.description;\n if (tool.parameters) result.inputSchema = tool.parameters;\n return result;\n}\n"],"mappings":";;AAuBA,SAAS,kBAAkB,OAA2B;CACpD,MAAM,QAAoB,EAAE;AAC5B,MAAK,MAAM,OAAO,MAAM,MAAM,KAAK,EAAE;EAEnC,MAAM,UAAU,IAAI,WAAW;AAC/B,MAAI,YAAY,MAAM,QAAQ,WAAW,IAAI,CAAE;EAE/C,MAAM,SAAS,IAAI,SAAS,IAAI,WAAW,CAAC;EAE5C,MAAM,UAAU,qBAAqB,QAAQ;EAC7C,MAAM,cAAc,QAAQ,WAAW,KAAK;EAC5C,MAAM,mBAAmB,cAAc,QAAQ,MAAM,EAAE,CAAC,MAAM,GAAG;AAEjE,QAAM,KAAK;GAAE;GAAQ;GAAK;GAAS;GAAa;GAAkB,CAAC;;AAErE,QAAO;;AAGT,SAAS,qBAAqB,GAAmB;CAE/C,IAAI,WAAW;CACf,IAAI,WAAW;AACf,MAAK,IAAI,IAAI,GAAG,IAAI,EAAE,QAAQ,KAAK;EACjC,MAAM,KAAK,EAAE;AACb,MAAI,OAAO,OAAO,CAAC,SAAU,YAAW,CAAC;AACzC,MAAI,OAAO,QAAO,CAAC,SAAU,YAAW,CAAC;AACzC,MAAI,OAAO,OAAO,CAAC,YAAY,CAAC,YAAY,IAAI,KAAK,EAAE,IAAI,OAAO,IAChE,QAAO,EAAE,MAAM,GAAG,EAAE,CAAC,SAAS;;AAGlC,QAAO;;AAGT,SAAS,YAAY,OAAwB;AAC3C,KAAI,UAAU,MAAM,UAAU,OAAO,UAAU,OAAQ,QAAO;AAC9D,KAAI,UAAU,OAAQ,QAAO;AAC7B,KAAI,UAAU,QAAS,QAAO;AAG9B,KACG,MAAM,WAAW,KAAI,IAAI,MAAM,SAAS,KAAI,IAC5C,MAAM,WAAW,IAAI,IAAI,MAAM,SAAS,IAAI,CAE7C,QAAO,MAAM,MAAM,GAAG,GAAG;CAI3B,MAAM,MAAM,OAAO,MAAM;AACzB,KAAI,CAAC,OAAO,MAAM,IAAI,IAAI,UAAU,GAAI,QAAO;AAG/C,QAAO;;AAGT,SAAgB,gBAAgB,OAAwB;CACtD,MAAM,QAAQ,kBAAkB,MAAM;AACtC,KAAI,MAAM,WAAW,EAAG,QAAO;AAG/B,QADe,WAAW,OAAO,GAAG,EAAE,CACxB;;AAQhB,SAAS,WAAW,OAAmB,YAAoB,WAAgC;AACzF,KAAI,cAAc,MAAM,OACtB,QAAO;EAAE,OAAO;EAAM,WAAW;EAAY;CAG/C,MAAM,OAAO,MAAM;AAGnB,KAAI,KAAK,eAAe,KAAK,UAAU,UACrC,QAAO,WAAW,OAAO,YAAY,KAAK,OAAO;AAInD,KAAI,KAAK,QAAQ,SAAS,IAAI,CAC5B,QAAO,SAAS,OAAO,YAAY,KAAK,OAAO;AAIjD,QAAO;EAAE,OAAO,YAAY,KAAK,QAAQ;EAAE,WAAW,aAAa;EAAG;;AAGxE,SAAS,WAAW,OAAmB,YAAoB,YAAiC;CAC1F,MAAM,MAAiB,EAAE;CACzB,IAAI,IAAI;AAER,QAAO,IAAI,MAAM,QAAQ;EACvB,MAAM,OAAO,MAAM;AACnB,MAAI,KAAK,SAAS,WAAY;AAC9B,MAAI,KAAK,SAAS,WAAY;AAC9B,MAAI,CAAC,KAAK,YAAa;EAEvB,MAAM,cAAc,KAAK;AAEzB,MAAI,gBAAgB,IAAI;GAEtB,MAAM,SAAS,WAAW,OAAO,IAAI,GAAG,aAAa,EAAE;AACvD,OAAI,KAAK,OAAO,MAAM;AACtB,OAAI,OAAO;aACF,YAAY,SAAS,IAAI,EAAE;GAGpC,MAAM,YAAY,kBAAkB,OAAO,GAAG,WAAW;AACzD,OAAI,KAAK,UAAU,MAAM;AACzB,OAAI,UAAU;SACT;AAEL,OAAI,KAAK,YAAY,YAAY,CAAC;AAClC;;;AAIJ,QAAO;EAAE,OAAO;EAAK,WAAW;EAAG;;AAGrC,SAAS,kBACP,OACA,YACA,aACa;CAEb,MAAM,MAA+B,EAAE;CAEvC,MAAM,eADY,MAAM,YACO;CAG/B,MAAM,WAAW,UAAU,aAAa;AACxC,KAAI,aAAa,GACf,QAAO;EAAE,OAAO,YAAY,aAAa;EAAE,WAAW,aAAa;EAAG;CAGxE,MAAM,MAAM,aAAa,MAAM,GAAG,SAAS,CAAC,MAAM;CAClD,MAAM,WAAW,aAAa,MAAM,WAAW,EAAE,CAAC,MAAM;AAExD,KAAI,aAAa,IAAI;EAEnB,MAAM,SAAS,WAAW,OAAO,aAAa,GAAG,cAAc,EAAE;AACjE,MAAI,OAAO,OAAO;EAClB,IAAI,IAAI,OAAO;EAGf,MAAM,gBAAgB,cAAc;AACpC,SAAO,IAAI,MAAM,UAAU,MAAM,GAAG,UAAU,iBAAiB,CAAC,MAAM,GAAG,YACvE,KAAI,MAAM,GAAG,WAAW,iBAAiB,MAAM,GAAG,SAAS,cAEzD,KAAI,MAAM,GAAG,WAAW,iBAAiB,MAAM,GAAG,QAAQ,SAAS,IAAI,CAErE,KADkB,gBAAgB,OAAO,GAAG,eAAe,IAAI,CACjD;MAEd;AAKN,SAAO;GAAE,OAAO;GAAK,WAAW;GAAG;OAEnC,KAAI,OAAO,YAAY,SAAS;CAIlC,IAAI,IAAI,aAAa;CACrB,MAAM,gBAAgB,cAAc;AAEpC,QAAO,IAAI,MAAM,QAAQ;EACvB,MAAM,OAAO,MAAM;AACnB,MAAI,KAAK,SAAS,cAAe;AACjC,MAAI,KAAK,eAAe,KAAK,UAAU,YAAa;AAEpD,MAAI,KAAK,WAAW,iBAAiB,CAAC,KAAK,eAAe,KAAK,QAAQ,SAAS,IAAI,EAAE;GACpF,MAAM,WAAW,UAAU,KAAK,QAAQ;AACxC,OAAI,aAAa,GAAI;GACrB,MAAM,IAAI,KAAK,QAAQ,MAAM,GAAG,SAAS,CAAC,MAAM;GAChD,MAAM,IAAI,KAAK,QAAQ,MAAM,WAAW,EAAE,CAAC,MAAM;AAEjD,OAAI,MAAM,IAAI;IACZ,MAAM,SAAS,WAAW,OAAO,IAAI,GAAG,gBAAgB,EAAE;AAC1D,QAAI,KAAK,OAAO;AAChB,QAAI,OAAO;UACN;AACL,QAAI,KAAK,YAAY,EAAE;AACvB;;aAEO,KAAK,WAAW,iBAAiB,KAAK,YAE/C;WACS,KAAK,SAAS,cAEvB;MAEA;;AAIJ,QAAO;EAAE,OAAO;EAAK,WAAW;EAAG;;AAGrC,SAAS,SAAS,OAAmB,YAAoB,YAAiC;CACxF,MAAM,MAA+B,EAAE;AAEvC,QAAO;EAAE,OAAO;EAAK,WADN,gBAAgB,OAAO,YAAY,YAAY,IAAI,CAC3B;EAAW;;AAGpD,SAAS,gBACP,OACA,YACA,YACA,KACa;CACb,IAAI,IAAI;AAER,QAAO,IAAI,MAAM,QAAQ;EACvB,MAAM,OAAO,MAAM;AACnB,MAAI,KAAK,SAAS,WAAY;AAC9B,MAAI,KAAK,SAAS,YAAY;AAE5B;AACA;;AAEF,MAAI,KAAK,YAAa;EAEtB,MAAM,WAAW,UAAU,KAAK,QAAQ;AACxC,MAAI,aAAa,GAEf;EAGF,MAAM,MAAM,KAAK,QAAQ,MAAM,GAAG,SAAS,CAAC,MAAM;EAClD,MAAM,WAAW,KAAK,QAAQ,MAAM,WAAW,EAAE,CAAC,MAAM;AAExD,MAAI,aAAa,IAAI;GAEnB,MAAM,SAAS,WAAW,OAAO,IAAI,GAAG,aAAa,EAAE;AACvD,OAAI,OAAO,OAAO;AAClB,OAAI,OAAO;SACN;AACL,OAAI,OAAO,YAAY,SAAS;AAChC;;;AAIJ,QAAO;EAAE,OAAO;EAAK,WAAW;EAAG;;AAGrC,SAAS,UAAU,GAAmB;CACpC,IAAI,WAAW;CACf,IAAI,WAAW;AACf,MAAK,IAAI,IAAI,GAAG,IAAI,EAAE,QAAQ,KAAK;EACjC,MAAM,KAAK,EAAE;AACb,MAAI,OAAO,OAAO,CAAC,SAAU,YAAW,CAAC;AACzC,MAAI,OAAO,QAAO,CAAC,SAAU,YAAW,CAAC;AACzC,MAAI,OAAO,OAAO,CAAC,YAAY,CAAC,UAE9B;OAAI,MAAM,EAAE,SAAS,KAAK,EAAE,IAAI,OAAO,IACrC,QAAO;;;AAIb,QAAO;;AAwDT,SAAgB,cAAc,QAAsC;CAClE,MAAM,WAA4B,EAAE;AAEpC,KAAI,OAAO,OACT,MAAK,MAAM,SAAS,OAAO,QAAQ;EACjC,MAAM,UAAU,aAAa,MAAM;AACnC,MAAI,QACF,UAAS,KAAK,QAAQ;;CAK5B,MAAM,SAAwB,EAAE,UAAU;AAE1C,KAAI,OAAO,KAAK,SAAS,OAAO,IAAI,MAAM,SAAS,EACjD,QAAO,WAAW,OAAO,IAAI,MAAM,IAAI,eAAe;AAGxD,QAAO;;AAGT,SAAS,aAAa,OAA2C;CAE/D,MAAM,UAAU,uBAAuB,MAAM,SAAS;AACtD,KAAI,YAAY,KAAM,QAAO;CAE7B,MAAM,UAAyB;EAC7B,OAAO,EAAE;EACT,UAAU,EAAE,SAAS;EACtB;CAGD,MAAM,cAAc,mBAAmB,MAAM;AAC7C,KAAI,YACF,SAAQ,QAAQ,EAAE,aAAa;KAG/B,SAAQ,WAAW,GAAG,MAAM,UAAU,OAAO,GAAG,MAAM;AAGxD,QAAO;;AAGT,SAAS,uBAAuB,UAAkD;CAChF,MAAM,UAAU,SAAS;AACzB,KAAI,CAAC,MAAM,QAAQ,QAAQ,IAAI,QAAQ,WAAW,EAAG,QAAO;CAG5D,MAAM,UADc,QAAQ,GACA;AAC5B,KAAI,CAAC,QAAS,QAAO;CAErB,MAAM,UAAU,QAAQ;AACxB,KAAI,OAAO,YAAY,SAAU,QAAO;AAExC,QAAO;;AAGT,SAAS,mBAAmB,OAAoC;CAC9D,MAAM,WAAW,MAAM,OAAO,MAAM;AACpC,KAAI,CAAC,MAAM,QAAQ,SAAS,IAAI,SAAS,WAAW,EAAG,QAAO;AAG9D,MAAK,IAAI,IAAI,SAAS,SAAS,GAAG,KAAK,GAAG,IACxC,KAAI,SAAS,GAAG,SAAS,OACvB,QAAO,SAAS,GAAG;AAKvB,QAAO,SAAS,SAAS,SAAS,GAAG,WAAW;;AAGlD,SAAS,eAAe,MAAkC;CACxD,MAAM,SAAwB,EAAE,MAAM,KAAK,MAAM;AACjD,KAAI,KAAK,YAAa,QAAO,cAAc,KAAK;AAChD,KAAI,KAAK,WAAY,QAAO,cAAc,KAAK;AAC/C,QAAO"}