@copilotkit/aimock 1.16.3 → 1.17.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 (268) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/CHANGELOG.md +30 -0
  4. package/README.md +10 -10
  5. package/dist/a2a-mock.d.cts +2 -2
  6. package/dist/a2a-mock.d.cts.map +1 -1
  7. package/dist/a2a-mock.d.ts +2 -2
  8. package/dist/a2a-mock.d.ts.map +1 -1
  9. package/dist/a2a-mock.js +2 -2
  10. package/dist/a2a-mock.js.map +1 -1
  11. package/dist/agui-handler.cjs +120 -5
  12. package/dist/agui-handler.cjs.map +1 -1
  13. package/dist/agui-handler.d.cts +41 -5
  14. package/dist/agui-handler.d.cts.map +1 -1
  15. package/dist/agui-handler.d.ts +41 -5
  16. package/dist/agui-handler.d.ts.map +1 -1
  17. package/dist/agui-handler.js +114 -6
  18. package/dist/agui-handler.js.map +1 -1
  19. package/dist/agui-mock.cjs +18 -7
  20. package/dist/agui-mock.cjs.map +1 -1
  21. package/dist/agui-mock.d.cts +2 -2
  22. package/dist/agui-mock.d.cts.map +1 -1
  23. package/dist/agui-mock.d.ts +2 -2
  24. package/dist/agui-mock.d.ts.map +1 -1
  25. package/dist/agui-mock.js +20 -9
  26. package/dist/agui-mock.js.map +1 -1
  27. package/dist/agui-recorder.cjs +43 -22
  28. package/dist/agui-recorder.cjs.map +1 -1
  29. package/dist/agui-recorder.d.cts +4 -3
  30. package/dist/agui-recorder.d.cts.map +1 -1
  31. package/dist/agui-recorder.d.ts +4 -3
  32. package/dist/agui-recorder.d.ts.map +1 -1
  33. package/dist/agui-recorder.js +45 -24
  34. package/dist/agui-recorder.js.map +1 -1
  35. package/dist/agui-stub.cjs +28 -0
  36. package/dist/agui-stub.d.cts +5 -0
  37. package/dist/agui-stub.d.ts +5 -0
  38. package/dist/agui-stub.js +5 -0
  39. package/dist/agui-types.d.cts +33 -6
  40. package/dist/agui-types.d.cts.map +1 -1
  41. package/dist/agui-types.d.ts +33 -6
  42. package/dist/agui-types.d.ts.map +1 -1
  43. package/dist/aimock-cli.cjs +1 -1
  44. package/dist/aimock-cli.js +1 -1
  45. package/dist/aws-event-stream.d.cts +2 -2
  46. package/dist/aws-event-stream.d.cts.map +1 -1
  47. package/dist/aws-event-stream.d.ts +2 -2
  48. package/dist/aws-event-stream.d.ts.map +1 -1
  49. package/dist/bedrock-converse.d.cts +3 -3
  50. package/dist/bedrock-converse.d.cts.map +1 -1
  51. package/dist/bedrock-converse.d.ts +3 -3
  52. package/dist/bedrock-converse.d.ts.map +1 -1
  53. package/dist/bedrock.d.cts +3 -3
  54. package/dist/bedrock.d.cts.map +1 -1
  55. package/dist/bedrock.d.ts +3 -3
  56. package/dist/bedrock.d.ts.map +1 -1
  57. package/dist/chaos.d.cts +3 -3
  58. package/dist/chaos.d.cts.map +1 -1
  59. package/dist/chaos.d.ts +3 -3
  60. package/dist/chaos.d.ts.map +1 -1
  61. package/dist/cli.cjs +6 -5
  62. package/dist/cli.cjs.map +1 -1
  63. package/dist/cli.js +6 -5
  64. package/dist/cli.js.map +1 -1
  65. package/dist/cohere.d.cts +2 -2
  66. package/dist/cohere.d.cts.map +1 -1
  67. package/dist/cohere.d.ts +2 -2
  68. package/dist/cohere.d.ts.map +1 -1
  69. package/dist/config-loader.cjs +3 -3
  70. package/dist/config-loader.d.cts +1 -1
  71. package/dist/config-loader.d.cts.map +1 -1
  72. package/dist/config-loader.d.ts +1 -1
  73. package/dist/config-loader.js +2 -2
  74. package/dist/convert-vidaimock.cjs +1 -1
  75. package/dist/convert-vidaimock.js +1 -1
  76. package/dist/convert.cjs +1 -1
  77. package/dist/convert.js +1 -1
  78. package/dist/elevenlabs-audio.cjs +209 -0
  79. package/dist/elevenlabs-audio.cjs.map +1 -0
  80. package/dist/elevenlabs-audio.d.cts +11 -0
  81. package/dist/elevenlabs-audio.d.cts.map +1 -0
  82. package/dist/elevenlabs-audio.d.ts +11 -0
  83. package/dist/elevenlabs-audio.d.ts.map +1 -0
  84. package/dist/elevenlabs-audio.js +209 -0
  85. package/dist/elevenlabs-audio.js.map +1 -0
  86. package/dist/embeddings.d.cts +2 -2
  87. package/dist/embeddings.d.cts.map +1 -1
  88. package/dist/embeddings.d.ts +2 -2
  89. package/dist/embeddings.d.ts.map +1 -1
  90. package/dist/fal-audio.cjs +477 -0
  91. package/dist/fal-audio.cjs.map +1 -0
  92. package/dist/fal-audio.d.cts +10 -0
  93. package/dist/fal-audio.d.cts.map +1 -0
  94. package/dist/fal-audio.d.ts +10 -0
  95. package/dist/fal-audio.d.ts.map +1 -0
  96. package/dist/fal-audio.js +474 -0
  97. package/dist/fal-audio.js.map +1 -0
  98. package/dist/fixture-loader.cjs +14 -1
  99. package/dist/fixture-loader.cjs.map +1 -1
  100. package/dist/fixture-loader.js +14 -1
  101. package/dist/fixture-loader.js.map +1 -1
  102. package/dist/fixtures-remote.cjs +1 -1
  103. package/dist/fixtures-remote.js +1 -1
  104. package/dist/gemini-interactions.cjs +617 -0
  105. package/dist/gemini-interactions.cjs.map +1 -0
  106. package/dist/gemini-interactions.d.cts +46 -0
  107. package/dist/gemini-interactions.d.cts.map +1 -0
  108. package/dist/gemini-interactions.d.ts +46 -0
  109. package/dist/gemini-interactions.d.ts.map +1 -0
  110. package/dist/gemini-interactions.js +616 -0
  111. package/dist/gemini-interactions.js.map +1 -0
  112. package/dist/gemini.cjs +76 -0
  113. package/dist/gemini.cjs.map +1 -1
  114. package/dist/gemini.d.cts +2 -2
  115. package/dist/gemini.d.cts.map +1 -1
  116. package/dist/gemini.d.ts +2 -2
  117. package/dist/gemini.d.ts.map +1 -1
  118. package/dist/gemini.js +77 -1
  119. package/dist/gemini.js.map +1 -1
  120. package/dist/helpers.cjs +24 -1
  121. package/dist/helpers.cjs.map +1 -1
  122. package/dist/helpers.d.cts +13 -3
  123. package/dist/helpers.d.cts.map +1 -1
  124. package/dist/helpers.d.ts +13 -3
  125. package/dist/helpers.d.ts.map +1 -1
  126. package/dist/helpers.js +23 -2
  127. package/dist/helpers.js.map +1 -1
  128. package/dist/images.d.cts +2 -2
  129. package/dist/images.d.cts.map +1 -1
  130. package/dist/images.d.ts +2 -2
  131. package/dist/images.d.ts.map +1 -1
  132. package/dist/index.cjs +21 -4
  133. package/dist/index.d.cts +10 -7
  134. package/dist/index.d.ts +10 -7
  135. package/dist/index.js +10 -7
  136. package/dist/jest.cjs +1 -1
  137. package/dist/jest.js +1 -1
  138. package/dist/jsonrpc.d.cts +3 -3
  139. package/dist/jsonrpc.d.cts.map +1 -1
  140. package/dist/jsonrpc.d.ts +3 -3
  141. package/dist/jsonrpc.d.ts.map +1 -1
  142. package/dist/llmock.cjs +38 -2
  143. package/dist/llmock.cjs.map +1 -1
  144. package/dist/llmock.d.cts +4 -0
  145. package/dist/llmock.d.cts.map +1 -1
  146. package/dist/llmock.d.ts +4 -0
  147. package/dist/llmock.d.ts.map +1 -1
  148. package/dist/llmock.js +38 -2
  149. package/dist/llmock.js.map +1 -1
  150. package/dist/logger.cjs +5 -4
  151. package/dist/logger.cjs.map +1 -1
  152. package/dist/logger.d.cts +1 -1
  153. package/dist/logger.d.cts.map +1 -1
  154. package/dist/logger.d.ts +1 -1
  155. package/dist/logger.d.ts.map +1 -1
  156. package/dist/logger.js +5 -4
  157. package/dist/logger.js.map +1 -1
  158. package/dist/mcp-mock.d.cts +2 -2
  159. package/dist/mcp-mock.d.cts.map +1 -1
  160. package/dist/mcp-mock.d.ts +2 -2
  161. package/dist/mcp-mock.d.ts.map +1 -1
  162. package/dist/mcp-mock.js +2 -2
  163. package/dist/mcp-mock.js.map +1 -1
  164. package/dist/messages.d.cts +2 -2
  165. package/dist/messages.d.cts.map +1 -1
  166. package/dist/messages.d.ts +2 -2
  167. package/dist/messages.d.ts.map +1 -1
  168. package/dist/moderation.d.cts +3 -3
  169. package/dist/moderation.d.cts.map +1 -1
  170. package/dist/moderation.d.ts +3 -3
  171. package/dist/moderation.d.ts.map +1 -1
  172. package/dist/ndjson-writer.d.cts +2 -2
  173. package/dist/ndjson-writer.d.cts.map +1 -1
  174. package/dist/ndjson-writer.d.ts +2 -2
  175. package/dist/ndjson-writer.d.ts.map +1 -1
  176. package/dist/ollama.d.cts +3 -3
  177. package/dist/ollama.d.cts.map +1 -1
  178. package/dist/ollama.d.ts +3 -3
  179. package/dist/ollama.d.ts.map +1 -1
  180. package/dist/recorder.cjs +64 -21
  181. package/dist/recorder.cjs.map +1 -1
  182. package/dist/recorder.d.cts +2 -2
  183. package/dist/recorder.d.cts.map +1 -1
  184. package/dist/recorder.d.ts +2 -2
  185. package/dist/recorder.d.ts.map +1 -1
  186. package/dist/recorder.js +66 -23
  187. package/dist/recorder.js.map +1 -1
  188. package/dist/rerank.d.cts +3 -3
  189. package/dist/rerank.d.cts.map +1 -1
  190. package/dist/rerank.d.ts +3 -3
  191. package/dist/rerank.d.ts.map +1 -1
  192. package/dist/responses.d.cts +2 -2
  193. package/dist/responses.d.cts.map +1 -1
  194. package/dist/responses.d.ts +2 -2
  195. package/dist/responses.d.ts.map +1 -1
  196. package/dist/router.cjs +3 -3
  197. package/dist/router.cjs.map +1 -1
  198. package/dist/router.js +3 -3
  199. package/dist/router.js.map +1 -1
  200. package/dist/search.d.cts +3 -3
  201. package/dist/search.d.cts.map +1 -1
  202. package/dist/search.d.ts +3 -3
  203. package/dist/search.d.ts.map +1 -1
  204. package/dist/server.cjs +170 -1
  205. package/dist/server.cjs.map +1 -1
  206. package/dist/server.d.cts +2 -2
  207. package/dist/server.d.cts.map +1 -1
  208. package/dist/server.d.ts +2 -2
  209. package/dist/server.d.ts.map +1 -1
  210. package/dist/server.js +173 -4
  211. package/dist/server.js.map +1 -1
  212. package/dist/speech.cjs +18 -9
  213. package/dist/speech.cjs.map +1 -1
  214. package/dist/speech.d.cts +2 -2
  215. package/dist/speech.d.cts.map +1 -1
  216. package/dist/speech.d.ts +2 -2
  217. package/dist/speech.d.ts.map +1 -1
  218. package/dist/speech.js +18 -9
  219. package/dist/speech.js.map +1 -1
  220. package/dist/sse-writer.d.cts +3 -3
  221. package/dist/sse-writer.d.cts.map +1 -1
  222. package/dist/sse-writer.d.ts +3 -3
  223. package/dist/sse-writer.d.ts.map +1 -1
  224. package/dist/stream-collapse.cjs +80 -9
  225. package/dist/stream-collapse.cjs.map +1 -1
  226. package/dist/stream-collapse.d.cts +11 -1
  227. package/dist/stream-collapse.d.cts.map +1 -1
  228. package/dist/stream-collapse.d.ts +11 -1
  229. package/dist/stream-collapse.d.ts.map +1 -1
  230. package/dist/stream-collapse.js +80 -10
  231. package/dist/stream-collapse.js.map +1 -1
  232. package/dist/suite.cjs +1 -1
  233. package/dist/suite.d.cts +2 -2
  234. package/dist/suite.d.ts +2 -2
  235. package/dist/suite.js +1 -1
  236. package/dist/transcription.d.cts +2 -2
  237. package/dist/transcription.d.cts.map +1 -1
  238. package/dist/transcription.d.ts +2 -2
  239. package/dist/transcription.d.ts.map +1 -1
  240. package/dist/types.d.cts +10 -7
  241. package/dist/types.d.cts.map +1 -1
  242. package/dist/types.d.ts +10 -7
  243. package/dist/types.d.ts.map +1 -1
  244. package/dist/vector-mock.d.cts +2 -2
  245. package/dist/vector-mock.d.cts.map +1 -1
  246. package/dist/vector-mock.d.ts +2 -2
  247. package/dist/vector-mock.d.ts.map +1 -1
  248. package/dist/vector-mock.js +2 -2
  249. package/dist/vector-mock.js.map +1 -1
  250. package/dist/vector-types.d.ts.map +1 -1
  251. package/dist/video.d.cts +3 -3
  252. package/dist/video.d.cts.map +1 -1
  253. package/dist/video.d.ts +3 -3
  254. package/dist/video.d.ts.map +1 -1
  255. package/dist/vitest.cjs +1 -1
  256. package/dist/vitest.js +1 -1
  257. package/dist/ws-framing.d.cts +2 -2
  258. package/dist/ws-framing.d.cts.map +1 -1
  259. package/dist/ws-framing.d.ts +2 -2
  260. package/dist/ws-framing.d.ts.map +1 -1
  261. package/dist/ws-gemini-live.cjs +145 -2
  262. package/dist/ws-gemini-live.cjs.map +1 -1
  263. package/dist/ws-gemini-live.d.cts.map +1 -1
  264. package/dist/ws-gemini-live.d.ts.map +1 -1
  265. package/dist/ws-gemini-live.js +146 -3
  266. package/dist/ws-gemini-live.js.map +1 -1
  267. package/package.json +16 -2
  268. package/skills/write-fixtures/SKILL.md +10 -10
@@ -1 +1 @@
1
- {"version":3,"file":"jsonrpc.d.ts","names":[],"sources":["../src/jsonrpc.ts"],"sourcesContent":[],"mappings":";;;KAEY,eAAA;;EAAA,EAAA,EAAA,MAAA,GAAA,MAAe,GAAA,IAAA;EAOf,MAAA,CAAA,EAAA,OAAa;EAAA,KAAA,CAAA,EAAA;IAGlB,IAAK,EAAA,MAAA;IACC,OAAA,EAAA,MAAA;IAAR,IAAA,CAAA,EAAA,OAAA;EAAO,CAAA;AAEZ,CAAA;AAAyC,KAN7B,aAAA,GAM6B,CAAA,MAAA,EAAA,OAAA,EAAA,EAAA,EAAA,MAAA,GAAA,MAAA,EAAA,GAAA,EAHlC,IAAA,CAAK,eAG6B,EAAA,GAFpC,OAEoC,CAF5B,eAE4B,GAAA,IAAA,CAAA;AACf,UADT,wBAAA,CACS;SAAf,EAAA,MAAA,CAAA,MAAA,EAAe,aAAf,CAAA;EAAM,cAAA,CAAA,EAAA,CAAA,MAAA,EAAA,MAAA,EAAA,MAAA,EAAA,OAAA,EAAA,GAAA,IAAA;AAsEjB;AAAuC,iBAAvB,uBAAA,CAAuB,OAAA,EAC5B,wBAD4B,CAAA,EAAA,CAAA,GAAA,EAE9B,IAAA,CAAK,eAFyB,EAAA,GAAA,EAEH,IAAA,CAAK,cAFF,EAAA,IAAA,EAAA,MAAA,EAAA,GAEmC,OAFnC,CAAA,IAAA,CAAA"}
1
+ {"version":3,"file":"jsonrpc.d.ts","names":[],"sources":["../src/jsonrpc.ts"],"sourcesContent":[],"mappings":";;;KAEY,eAAA;;EAAA,EAAA,EAAA,MAAA,GAAA,MAAe,GAAA,IAAA;EAOf,MAAA,CAAA,EAAA,OAAa;EAAA,KAAA,CAAA,EAAA;IAGlB,IAAA,EAAK,MAAA;IACC,OAAA,EAAA,MAAA;IAAR,IAAA,CAAA,EAAA,OAAA;EAAO,CAAA;AAEZ,CAAA;AAAyC,KAN7B,aAAA,GAM6B,CAAA,MAAA,EAAA,OAAA,EAAA,EAAA,EAAA,MAAA,GAAA,MAAA,EAAA,GAAA,EAHlC,MAAA,CAAK,eAG6B,EAAA,GAFpC,OAEoC,CAF5B,eAE4B,GAAA,IAAA,CAAA;AACf,UADT,wBAAA,CACS;SAAf,EAAA,MAAA,CAAA,MAAA,EAAe,aAAf,CAAA;EAAM,cAAA,CAAA,EAAA,CAAA,MAAA,EAAA,MAAA,EAAA,MAAA,EAAA,OAAA,EAAA,GAAA,IAAA;AAsEjB;AAAuC,iBAAvB,uBAAA,CAAuB,OAAA,EAC5B,wBAD4B,CAAA,EAAA,CAAA,GAAA,EAE9B,MAAA,CAAK,eAFyB,EAAA,GAAA,EAEH,MAAA,CAAK,cAFF,EAAA,IAAA,EAAA,MAAA,EAAA,GAEmC,OAFnC,CAAA,IAAA,CAAA"}
package/dist/llmock.cjs CHANGED
@@ -1,4 +1,5 @@
1
1
  const require_fixture_loader = require('./fixture-loader.cjs');
2
+ const require_fal_audio = require('./fal-audio.cjs');
2
3
  const require_server = require('./server.cjs');
3
4
 
4
5
  //#region src/llmock.ts
@@ -116,6 +117,40 @@ var LLMock = class LLMock {
116
117
  response
117
118
  });
118
119
  }
120
+ onAudio(input, response) {
121
+ return this.addFixture({
122
+ match: { userMessage: input },
123
+ response
124
+ });
125
+ }
126
+ onSoundEffect(text, response) {
127
+ return this.addFixture({
128
+ match: {
129
+ userMessage: text,
130
+ endpoint: "audio-gen"
131
+ },
132
+ response
133
+ });
134
+ }
135
+ onMusic(prompt, response) {
136
+ return this.addFixture({
137
+ match: {
138
+ userMessage: prompt,
139
+ endpoint: "audio-gen"
140
+ },
141
+ response
142
+ });
143
+ }
144
+ onFalAudio(prompt, response, model) {
145
+ return this.addFixture({
146
+ match: {
147
+ userMessage: prompt,
148
+ endpoint: "fal-audio",
149
+ ...model ? { model } : {}
150
+ },
151
+ response
152
+ });
153
+ }
119
154
  onSearch(pattern, results) {
120
155
  this.searchFixtures.push({
121
156
  match: pattern,
@@ -159,10 +194,10 @@ var LLMock = class LLMock {
159
194
  const original = fixture.match.predicate;
160
195
  fixture.match.predicate = (req) => {
161
196
  const result = original(req);
162
- if (result) queueMicrotask(() => {
197
+ if (result) {
163
198
  const idx = this.fixtures.indexOf(fixture);
164
199
  if (idx !== -1) this.fixtures.splice(idx, 1);
165
- });
200
+ }
166
201
  return result;
167
202
  };
168
203
  return this;
@@ -214,6 +249,7 @@ var LLMock = class LLMock {
214
249
  this.searchFixtures.length = 0;
215
250
  this.rerankFixtures.length = 0;
216
251
  this.moderationFixtures.length = 0;
252
+ require_fal_audio.falJobs.clear();
217
253
  if (this.serverInstance) {
218
254
  this.serverInstance.journal.clear();
219
255
  this.serverInstance.videoStates.clear();
@@ -1 +1 @@
1
- {"version":3,"file":"llmock.cjs","names":["loadFixtureFile","loadFixturesFromDir","entryToFixture","validateFixtures","normalizeResponse","createServer"],"sources":["../src/llmock.ts"],"sourcesContent":["import type {\n AudioResponse,\n ChaosConfig,\n EmbeddingFixtureOpts,\n Fixture,\n FixtureFileEntry,\n FixtureFileResponse,\n FixtureMatch,\n FixtureOpts,\n FixtureResponse,\n ImageResponse,\n MockServerOptions,\n Mountable,\n RecordConfig,\n TranscriptionResponse,\n VideoResponse,\n} from \"./types.js\";\nimport { createServer, type ServerInstance } from \"./server.js\";\nimport {\n loadFixtureFile,\n loadFixturesFromDir,\n entryToFixture,\n normalizeResponse,\n validateFixtures,\n} from \"./fixture-loader.js\";\nimport { Journal } from \"./journal.js\";\nimport type { SearchFixture, SearchResult } from \"./search.js\";\nimport type { RerankFixture, RerankResult } from \"./rerank.js\";\nimport type { ModerationFixture, ModerationResult } from \"./moderation.js\";\n\nexport class LLMock {\n private fixtures: Fixture[] = [];\n private searchFixtures: SearchFixture[] = [];\n private rerankFixtures: RerankFixture[] = [];\n private moderationFixtures: ModerationFixture[] = [];\n private mounts: Array<{ path: string; handler: Mountable }> = [];\n private serverInstance: ServerInstance | null = null;\n private options: MockServerOptions;\n\n constructor(options?: MockServerOptions) {\n this.options = options ?? {};\n }\n\n // ---- Fixture management ----\n\n addFixture(fixture: Fixture): this {\n this.fixtures.push(fixture);\n return this;\n }\n\n addFixtures(fixtures: Fixture[]): this {\n this.fixtures.push(...fixtures);\n return this;\n }\n\n prependFixture(fixture: Fixture): this {\n this.fixtures.unshift(fixture);\n return this;\n }\n\n getFixtures(): readonly Fixture[] {\n return this.fixtures;\n }\n\n loadFixtureFile(filePath: string): this {\n this.fixtures.push(...loadFixtureFile(filePath));\n return this;\n }\n\n loadFixtureDir(dirPath: string): this {\n this.fixtures.push(...loadFixturesFromDir(dirPath));\n return this;\n }\n\n /**\n * Add fixtures from a JSON string or pre-parsed array of fixture entries.\n * Validates all fixtures and throws if any have severity \"error\".\n */\n addFixturesFromJSON(input: string | FixtureFileEntry[]): this {\n const entries: FixtureFileEntry[] = typeof input === \"string\" ? JSON.parse(input) : input;\n const converted = entries.map(entryToFixture);\n const issues = validateFixtures(converted);\n const errors = issues.filter((i) => i.severity === \"error\");\n if (errors.length > 0) {\n throw new Error(`Fixture validation failed: ${JSON.stringify(errors)}`);\n }\n this.fixtures.push(...converted);\n return this;\n }\n\n // Uses length = 0 to preserve array reference identity — the running\n // server reads this same array on every request.\n clearFixtures(): this {\n this.fixtures.length = 0;\n return this;\n }\n\n // ---- Convenience ----\n\n on(match: FixtureMatch, response: FixtureFileResponse, opts?: FixtureOpts): this {\n return this.addFixture({\n match,\n response: normalizeResponse(response),\n ...opts,\n });\n }\n\n onMessage(pattern: string | RegExp, response: FixtureFileResponse, opts?: FixtureOpts): this {\n return this.on({ userMessage: pattern }, response, opts);\n }\n\n onEmbedding(\n pattern: string | RegExp,\n response: FixtureFileResponse,\n opts?: EmbeddingFixtureOpts,\n ): this {\n return this.on({ inputText: pattern }, response, opts);\n }\n\n onJsonOutput(pattern: string | RegExp, jsonContent: object | string, opts?: FixtureOpts): this {\n const content = typeof jsonContent === \"string\" ? jsonContent : JSON.stringify(jsonContent);\n return this.on({ userMessage: pattern, responseFormat: \"json_object\" }, { content }, opts);\n }\n\n onToolCall(name: string, response: FixtureFileResponse, opts?: FixtureOpts): this {\n return this.on({ toolName: name }, response, opts);\n }\n\n onToolResult(id: string, response: FixtureFileResponse, opts?: FixtureOpts): this {\n return this.on({ toolCallId: id }, response, opts);\n }\n\n onTurn(\n turn: number,\n pattern: string | RegExp,\n response: FixtureFileResponse,\n opts?: FixtureOpts,\n ): this {\n return this.on({ userMessage: pattern, turnIndex: turn }, response, opts);\n }\n\n onImage(prompt: string | RegExp, response: ImageResponse): this {\n return this.addFixture({\n match: { userMessage: prompt, endpoint: \"image\" },\n response,\n });\n }\n\n onSpeech(input: string | RegExp, response: AudioResponse): this {\n return this.addFixture({\n match: { userMessage: input, endpoint: \"speech\" },\n response,\n });\n }\n\n onTranscription(response: TranscriptionResponse): this {\n return this.addFixture({\n match: { endpoint: \"transcription\" },\n response,\n });\n }\n\n onVideo(prompt: string | RegExp, response: VideoResponse): this {\n return this.addFixture({\n match: { userMessage: prompt, endpoint: \"video\" },\n response,\n });\n }\n\n // ---- Service mock convenience methods ----\n\n onSearch(pattern: string | RegExp, results: SearchResult[]): this {\n this.searchFixtures.push({ match: pattern, results });\n return this;\n }\n\n onRerank(pattern: string | RegExp, results: RerankResult[]): this {\n this.rerankFixtures.push({ match: pattern, results });\n return this;\n }\n\n onModerate(pattern: string | RegExp, result: ModerationResult): this {\n this.moderationFixtures.push({ match: pattern, result });\n return this;\n }\n\n /**\n * Queue a one-shot error that will be returned for the next matching\n * request, then automatically removed. Implemented as an internal fixture\n * with a `predicate` that always matches (so it fires first) and spliced\n * at the front of the fixture list.\n */\n nextRequestError(\n status: number,\n errorBody?: { message?: string; type?: string; code?: string },\n ): this {\n const errorResponse: FixtureResponse = {\n error: {\n message: errorBody?.message ?? \"Injected error\",\n type: errorBody?.type ?? \"server_error\",\n code: errorBody?.code,\n },\n status,\n };\n const fixture: Fixture = {\n match: { predicate: () => true },\n response: errorResponse,\n };\n // Insert at front so it matches before everything else\n this.fixtures.unshift(fixture);\n // Remove after first match — the journal records it so tests can assert\n const original = fixture.match.predicate!;\n fixture.match.predicate = (req) => {\n const result = original(req);\n if (result) {\n // Defer splice so it doesn't mutate the array while matchFixture iterates it\n queueMicrotask(() => {\n const idx = this.fixtures.indexOf(fixture);\n if (idx !== -1) this.fixtures.splice(idx, 1);\n });\n }\n return result;\n };\n return this;\n }\n\n // ---- Mounts ----\n\n mount(path: string, handler: Mountable): this {\n this.mounts.push({ path, handler });\n\n // If server is already running, wire up journal, registry, and baseUrl immediately\n // so late mounts behave identically to pre-start mounts.\n if (this.serverInstance) {\n if (handler.setJournal) handler.setJournal(this.serverInstance.journal);\n if (handler.setBaseUrl) handler.setBaseUrl(this.serverInstance.url + path);\n const registry = this.serverInstance.defaults.registry;\n if (registry && handler.setRegistry) handler.setRegistry(registry);\n }\n\n return this;\n }\n\n // ---- Journal proxies ----\n\n getRequests(): import(\"./types.js\").JournalEntry[] {\n return this.journal.getAll();\n }\n\n getLastRequest(): import(\"./types.js\").JournalEntry | null {\n return this.journal.getLast();\n }\n\n clearRequests(): void {\n this.journal.clear();\n }\n\n resetMatchCounts(testId?: string): this {\n if (this.serverInstance) {\n this.serverInstance.journal.clearMatchCounts(testId);\n }\n return this;\n }\n\n // ---- Chaos ----\n\n setChaos(config: ChaosConfig): this {\n this.options.chaos = config;\n return this;\n }\n\n clearChaos(): this {\n delete this.options.chaos;\n return this;\n }\n\n // ---- Recording ----\n\n enableRecording(config: RecordConfig): this {\n this.options.record = config;\n return this;\n }\n\n disableRecording(): this {\n delete this.options.record;\n return this;\n }\n\n // ---- Reset ----\n\n reset(): this {\n this.clearFixtures();\n this.searchFixtures.length = 0;\n this.rerankFixtures.length = 0;\n this.moderationFixtures.length = 0;\n if (this.serverInstance) {\n this.serverInstance.journal.clear();\n this.serverInstance.videoStates.clear();\n }\n return this;\n }\n\n // ---- Server lifecycle ----\n\n async start(): Promise<string> {\n if (this.serverInstance) {\n throw new Error(\"Server already started\");\n }\n this.serverInstance = await createServer(this.fixtures, this.options, this.mounts, {\n search: this.searchFixtures,\n rerank: this.rerankFixtures,\n moderation: this.moderationFixtures,\n });\n return this.serverInstance.url;\n }\n\n async stop(): Promise<void> {\n if (!this.serverInstance) {\n throw new Error(\"Server not started\");\n }\n const { server } = this.serverInstance;\n await new Promise<void>((resolve, reject) => {\n server.close((err: Error | undefined) => (err ? reject(err) : resolve()));\n });\n this.serverInstance = null;\n }\n\n // ---- Accessors ----\n\n get journal(): Journal {\n if (!this.serverInstance) {\n throw new Error(\"Server not started\");\n }\n return this.serverInstance.journal;\n }\n\n get url(): string {\n if (!this.serverInstance) {\n throw new Error(\"Server not started\");\n }\n return this.serverInstance.url;\n }\n\n get baseUrl(): string {\n return this.url;\n }\n\n get port(): number {\n const parsed = new URL(this.url); // this.url throws if not started\n if (!parsed.port) {\n throw new Error(`Server URL has no explicit port: ${this.url}`);\n }\n return parseInt(parsed.port, 10);\n }\n\n // ---- Static factory ----\n\n static async create(options?: MockServerOptions): Promise<LLMock> {\n const instance = new LLMock(options);\n await instance.start();\n return instance;\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"llmock.cjs","names":["loadFixtureFile","loadFixturesFromDir","entryToFixture","validateFixtures","normalizeResponse","createServer"],"sources":["../src/llmock.ts"],"sourcesContent":["import type {\n AudioResponse,\n ChaosConfig,\n EmbeddingFixtureOpts,\n Fixture,\n FixtureFileEntry,\n FixtureFileResponse,\n FixtureMatch,\n FixtureOpts,\n FixtureResponse,\n ImageResponse,\n MockServerOptions,\n Mountable,\n RecordConfig,\n TranscriptionResponse,\n VideoResponse,\n} from \"./types.js\";\nimport { createServer, type ServerInstance } from \"./server.js\";\nimport {\n loadFixtureFile,\n loadFixturesFromDir,\n entryToFixture,\n normalizeResponse,\n validateFixtures,\n} from \"./fixture-loader.js\";\nimport { Journal } from \"./journal.js\";\nimport type { SearchFixture, SearchResult } from \"./search.js\";\nimport type { RerankFixture, RerankResult } from \"./rerank.js\";\nimport type { ModerationFixture, ModerationResult } from \"./moderation.js\";\nimport { falJobs } from \"./fal-audio.js\";\n\nexport class LLMock {\n private fixtures: Fixture[] = [];\n private searchFixtures: SearchFixture[] = [];\n private rerankFixtures: RerankFixture[] = [];\n private moderationFixtures: ModerationFixture[] = [];\n private mounts: Array<{ path: string; handler: Mountable }> = [];\n private serverInstance: ServerInstance | null = null;\n private options: MockServerOptions;\n\n constructor(options?: MockServerOptions) {\n this.options = options ?? {};\n }\n\n // ---- Fixture management ----\n\n addFixture(fixture: Fixture): this {\n this.fixtures.push(fixture);\n return this;\n }\n\n addFixtures(fixtures: Fixture[]): this {\n this.fixtures.push(...fixtures);\n return this;\n }\n\n prependFixture(fixture: Fixture): this {\n this.fixtures.unshift(fixture);\n return this;\n }\n\n getFixtures(): readonly Fixture[] {\n return this.fixtures;\n }\n\n loadFixtureFile(filePath: string): this {\n this.fixtures.push(...loadFixtureFile(filePath));\n return this;\n }\n\n loadFixtureDir(dirPath: string): this {\n this.fixtures.push(...loadFixturesFromDir(dirPath));\n return this;\n }\n\n /**\n * Add fixtures from a JSON string or pre-parsed array of fixture entries.\n * Validates all fixtures and throws if any have severity \"error\".\n */\n addFixturesFromJSON(input: string | FixtureFileEntry[]): this {\n const entries: FixtureFileEntry[] = typeof input === \"string\" ? JSON.parse(input) : input;\n const converted = entries.map(entryToFixture);\n const issues = validateFixtures(converted);\n const errors = issues.filter((i) => i.severity === \"error\");\n if (errors.length > 0) {\n throw new Error(`Fixture validation failed: ${JSON.stringify(errors)}`);\n }\n this.fixtures.push(...converted);\n return this;\n }\n\n // Uses length = 0 to preserve array reference identity — the running\n // server reads this same array on every request.\n clearFixtures(): this {\n this.fixtures.length = 0;\n return this;\n }\n\n // ---- Convenience ----\n\n on(match: FixtureMatch, response: FixtureFileResponse, opts?: FixtureOpts): this {\n return this.addFixture({\n match,\n response: normalizeResponse(response),\n ...opts,\n });\n }\n\n onMessage(pattern: string | RegExp, response: FixtureFileResponse, opts?: FixtureOpts): this {\n return this.on({ userMessage: pattern }, response, opts);\n }\n\n onEmbedding(\n pattern: string | RegExp,\n response: FixtureFileResponse,\n opts?: EmbeddingFixtureOpts,\n ): this {\n return this.on({ inputText: pattern }, response, opts);\n }\n\n onJsonOutput(pattern: string | RegExp, jsonContent: object | string, opts?: FixtureOpts): this {\n const content = typeof jsonContent === \"string\" ? jsonContent : JSON.stringify(jsonContent);\n return this.on({ userMessage: pattern, responseFormat: \"json_object\" }, { content }, opts);\n }\n\n onToolCall(name: string, response: FixtureFileResponse, opts?: FixtureOpts): this {\n return this.on({ toolName: name }, response, opts);\n }\n\n onToolResult(id: string, response: FixtureFileResponse, opts?: FixtureOpts): this {\n return this.on({ toolCallId: id }, response, opts);\n }\n\n onTurn(\n turn: number,\n pattern: string | RegExp,\n response: FixtureFileResponse,\n opts?: FixtureOpts,\n ): this {\n return this.on({ userMessage: pattern, turnIndex: turn }, response, opts);\n }\n\n onImage(prompt: string | RegExp, response: ImageResponse): this {\n return this.addFixture({\n match: { userMessage: prompt, endpoint: \"image\" },\n response,\n });\n }\n\n onSpeech(input: string | RegExp, response: AudioResponse): this {\n return this.addFixture({\n match: { userMessage: input, endpoint: \"speech\" },\n response,\n });\n }\n\n onTranscription(response: TranscriptionResponse): this {\n return this.addFixture({\n match: { endpoint: \"transcription\" },\n response,\n });\n }\n\n onVideo(prompt: string | RegExp, response: VideoResponse): this {\n return this.addFixture({\n match: { userMessage: prompt, endpoint: \"video\" },\n response,\n });\n }\n\n onAudio(input: string | RegExp, response: AudioResponse): this {\n return this.addFixture({ match: { userMessage: input }, response });\n }\n\n onSoundEffect(text: string | RegExp, response: AudioResponse): this {\n return this.addFixture({\n match: { userMessage: text, endpoint: \"audio-gen\" },\n response,\n });\n }\n\n onMusic(prompt: string | RegExp, response: AudioResponse): this {\n return this.addFixture({\n match: { userMessage: prompt, endpoint: \"audio-gen\" },\n response,\n });\n }\n\n onFalAudio(prompt: string | RegExp, response: AudioResponse, model?: string): this {\n return this.addFixture({\n match: { userMessage: prompt, endpoint: \"fal-audio\", ...(model ? { model } : {}) },\n response,\n });\n }\n\n // ---- Service mock convenience methods ----\n\n onSearch(pattern: string | RegExp, results: SearchResult[]): this {\n this.searchFixtures.push({ match: pattern, results });\n return this;\n }\n\n onRerank(pattern: string | RegExp, results: RerankResult[]): this {\n this.rerankFixtures.push({ match: pattern, results });\n return this;\n }\n\n onModerate(pattern: string | RegExp, result: ModerationResult): this {\n this.moderationFixtures.push({ match: pattern, result });\n return this;\n }\n\n /**\n * Queue a one-shot error that will be returned for the next matching\n * request, then automatically removed. Implemented as an internal fixture\n * with a `predicate` that always matches (so it fires first) and spliced\n * at the front of the fixture list.\n */\n nextRequestError(\n status: number,\n errorBody?: { message?: string; type?: string; code?: string },\n ): this {\n const errorResponse: FixtureResponse = {\n error: {\n message: errorBody?.message ?? \"Injected error\",\n type: errorBody?.type ?? \"server_error\",\n code: errorBody?.code,\n },\n status,\n };\n const fixture: Fixture = {\n match: { predicate: () => true },\n response: errorResponse,\n };\n // Insert at front so it matches before everything else\n this.fixtures.unshift(fixture);\n // Remove after first match — the journal records it so tests can assert\n const original = fixture.match.predicate!;\n fixture.match.predicate = (req) => {\n const result = original(req);\n if (result) {\n // Remove synchronously on first match to prevent race conditions\n const idx = this.fixtures.indexOf(fixture);\n if (idx !== -1) this.fixtures.splice(idx, 1);\n }\n return result;\n };\n return this;\n }\n\n // ---- Mounts ----\n\n mount(path: string, handler: Mountable): this {\n this.mounts.push({ path, handler });\n\n // If server is already running, wire up journal, registry, and baseUrl immediately\n // so late mounts behave identically to pre-start mounts.\n if (this.serverInstance) {\n if (handler.setJournal) handler.setJournal(this.serverInstance.journal);\n if (handler.setBaseUrl) handler.setBaseUrl(this.serverInstance.url + path);\n const registry = this.serverInstance.defaults.registry;\n if (registry && handler.setRegistry) handler.setRegistry(registry);\n }\n\n return this;\n }\n\n // ---- Journal proxies ----\n\n getRequests(): import(\"./types.js\").JournalEntry[] {\n return this.journal.getAll();\n }\n\n getLastRequest(): import(\"./types.js\").JournalEntry | null {\n return this.journal.getLast();\n }\n\n clearRequests(): void {\n this.journal.clear();\n }\n\n resetMatchCounts(testId?: string): this {\n if (this.serverInstance) {\n this.serverInstance.journal.clearMatchCounts(testId);\n }\n return this;\n }\n\n // ---- Chaos ----\n\n setChaos(config: ChaosConfig): this {\n this.options.chaos = config;\n return this;\n }\n\n clearChaos(): this {\n delete this.options.chaos;\n return this;\n }\n\n // ---- Recording ----\n\n enableRecording(config: RecordConfig): this {\n this.options.record = config;\n return this;\n }\n\n disableRecording(): this {\n delete this.options.record;\n return this;\n }\n\n // ---- Reset ----\n\n reset(): this {\n this.clearFixtures();\n this.searchFixtures.length = 0;\n this.rerankFixtures.length = 0;\n this.moderationFixtures.length = 0;\n falJobs.clear();\n if (this.serverInstance) {\n this.serverInstance.journal.clear();\n this.serverInstance.videoStates.clear();\n }\n return this;\n }\n\n // ---- Server lifecycle ----\n\n async start(): Promise<string> {\n if (this.serverInstance) {\n throw new Error(\"Server already started\");\n }\n this.serverInstance = await createServer(this.fixtures, this.options, this.mounts, {\n search: this.searchFixtures,\n rerank: this.rerankFixtures,\n moderation: this.moderationFixtures,\n });\n return this.serverInstance.url;\n }\n\n async stop(): Promise<void> {\n if (!this.serverInstance) {\n throw new Error(\"Server not started\");\n }\n const { server } = this.serverInstance;\n await new Promise<void>((resolve, reject) => {\n server.close((err: Error | undefined) => (err ? reject(err) : resolve()));\n });\n this.serverInstance = null;\n }\n\n // ---- Accessors ----\n\n get journal(): Journal {\n if (!this.serverInstance) {\n throw new Error(\"Server not started\");\n }\n return this.serverInstance.journal;\n }\n\n get url(): string {\n if (!this.serverInstance) {\n throw new Error(\"Server not started\");\n }\n return this.serverInstance.url;\n }\n\n get baseUrl(): string {\n return this.url;\n }\n\n get port(): number {\n const parsed = new URL(this.url); // this.url throws if not started\n if (!parsed.port) {\n throw new Error(`Server URL has no explicit port: ${this.url}`);\n }\n return parseInt(parsed.port, 10);\n }\n\n // ---- Static factory ----\n\n static async create(options?: MockServerOptions): Promise<LLMock> {\n const instance = new LLMock(options);\n await instance.start();\n return instance;\n }\n}\n"],"mappings":";;;;;AA+BA,IAAa,SAAb,MAAa,OAAO;CAClB,AAAQ,WAAsB,EAAE;CAChC,AAAQ,iBAAkC,EAAE;CAC5C,AAAQ,iBAAkC,EAAE;CAC5C,AAAQ,qBAA0C,EAAE;CACpD,AAAQ,SAAsD,EAAE;CAChE,AAAQ,iBAAwC;CAChD,AAAQ;CAER,YAAY,SAA6B;AACvC,OAAK,UAAU,WAAW,EAAE;;CAK9B,WAAW,SAAwB;AACjC,OAAK,SAAS,KAAK,QAAQ;AAC3B,SAAO;;CAGT,YAAY,UAA2B;AACrC,OAAK,SAAS,KAAK,GAAG,SAAS;AAC/B,SAAO;;CAGT,eAAe,SAAwB;AACrC,OAAK,SAAS,QAAQ,QAAQ;AAC9B,SAAO;;CAGT,cAAkC;AAChC,SAAO,KAAK;;CAGd,gBAAgB,UAAwB;AACtC,OAAK,SAAS,KAAK,GAAGA,uCAAgB,SAAS,CAAC;AAChD,SAAO;;CAGT,eAAe,SAAuB;AACpC,OAAK,SAAS,KAAK,GAAGC,2CAAoB,QAAQ,CAAC;AACnD,SAAO;;;;;;CAOT,oBAAoB,OAA0C;EAE5D,MAAM,aAD8B,OAAO,UAAU,WAAW,KAAK,MAAM,MAAM,GAAG,OAC1D,IAAIC,sCAAe;EAE7C,MAAM,SADSC,wCAAiB,UAAU,CACpB,QAAQ,MAAM,EAAE,aAAa,QAAQ;AAC3D,MAAI,OAAO,SAAS,EAClB,OAAM,IAAI,MAAM,8BAA8B,KAAK,UAAU,OAAO,GAAG;AAEzE,OAAK,SAAS,KAAK,GAAG,UAAU;AAChC,SAAO;;CAKT,gBAAsB;AACpB,OAAK,SAAS,SAAS;AACvB,SAAO;;CAKT,GAAG,OAAqB,UAA+B,MAA0B;AAC/E,SAAO,KAAK,WAAW;GACrB;GACA,UAAUC,yCAAkB,SAAS;GACrC,GAAG;GACJ,CAAC;;CAGJ,UAAU,SAA0B,UAA+B,MAA0B;AAC3F,SAAO,KAAK,GAAG,EAAE,aAAa,SAAS,EAAE,UAAU,KAAK;;CAG1D,YACE,SACA,UACA,MACM;AACN,SAAO,KAAK,GAAG,EAAE,WAAW,SAAS,EAAE,UAAU,KAAK;;CAGxD,aAAa,SAA0B,aAA8B,MAA0B;EAC7F,MAAM,UAAU,OAAO,gBAAgB,WAAW,cAAc,KAAK,UAAU,YAAY;AAC3F,SAAO,KAAK,GAAG;GAAE,aAAa;GAAS,gBAAgB;GAAe,EAAE,EAAE,SAAS,EAAE,KAAK;;CAG5F,WAAW,MAAc,UAA+B,MAA0B;AAChF,SAAO,KAAK,GAAG,EAAE,UAAU,MAAM,EAAE,UAAU,KAAK;;CAGpD,aAAa,IAAY,UAA+B,MAA0B;AAChF,SAAO,KAAK,GAAG,EAAE,YAAY,IAAI,EAAE,UAAU,KAAK;;CAGpD,OACE,MACA,SACA,UACA,MACM;AACN,SAAO,KAAK,GAAG;GAAE,aAAa;GAAS,WAAW;GAAM,EAAE,UAAU,KAAK;;CAG3E,QAAQ,QAAyB,UAA+B;AAC9D,SAAO,KAAK,WAAW;GACrB,OAAO;IAAE,aAAa;IAAQ,UAAU;IAAS;GACjD;GACD,CAAC;;CAGJ,SAAS,OAAwB,UAA+B;AAC9D,SAAO,KAAK,WAAW;GACrB,OAAO;IAAE,aAAa;IAAO,UAAU;IAAU;GACjD;GACD,CAAC;;CAGJ,gBAAgB,UAAuC;AACrD,SAAO,KAAK,WAAW;GACrB,OAAO,EAAE,UAAU,iBAAiB;GACpC;GACD,CAAC;;CAGJ,QAAQ,QAAyB,UAA+B;AAC9D,SAAO,KAAK,WAAW;GACrB,OAAO;IAAE,aAAa;IAAQ,UAAU;IAAS;GACjD;GACD,CAAC;;CAGJ,QAAQ,OAAwB,UAA+B;AAC7D,SAAO,KAAK,WAAW;GAAE,OAAO,EAAE,aAAa,OAAO;GAAE;GAAU,CAAC;;CAGrE,cAAc,MAAuB,UAA+B;AAClE,SAAO,KAAK,WAAW;GACrB,OAAO;IAAE,aAAa;IAAM,UAAU;IAAa;GACnD;GACD,CAAC;;CAGJ,QAAQ,QAAyB,UAA+B;AAC9D,SAAO,KAAK,WAAW;GACrB,OAAO;IAAE,aAAa;IAAQ,UAAU;IAAa;GACrD;GACD,CAAC;;CAGJ,WAAW,QAAyB,UAAyB,OAAsB;AACjF,SAAO,KAAK,WAAW;GACrB,OAAO;IAAE,aAAa;IAAQ,UAAU;IAAa,GAAI,QAAQ,EAAE,OAAO,GAAG,EAAE;IAAG;GAClF;GACD,CAAC;;CAKJ,SAAS,SAA0B,SAA+B;AAChE,OAAK,eAAe,KAAK;GAAE,OAAO;GAAS;GAAS,CAAC;AACrD,SAAO;;CAGT,SAAS,SAA0B,SAA+B;AAChE,OAAK,eAAe,KAAK;GAAE,OAAO;GAAS;GAAS,CAAC;AACrD,SAAO;;CAGT,WAAW,SAA0B,QAAgC;AACnE,OAAK,mBAAmB,KAAK;GAAE,OAAO;GAAS;GAAQ,CAAC;AACxD,SAAO;;;;;;;;CAST,iBACE,QACA,WACM;EASN,MAAM,UAAmB;GACvB,OAAO,EAAE,iBAAiB,MAAM;GAChC,UAVqC;IACrC,OAAO;KACL,SAAS,WAAW,WAAW;KAC/B,MAAM,WAAW,QAAQ;KACzB,MAAM,WAAW;KAClB;IACD;IACD;GAIA;AAED,OAAK,SAAS,QAAQ,QAAQ;EAE9B,MAAM,WAAW,QAAQ,MAAM;AAC/B,UAAQ,MAAM,aAAa,QAAQ;GACjC,MAAM,SAAS,SAAS,IAAI;AAC5B,OAAI,QAAQ;IAEV,MAAM,MAAM,KAAK,SAAS,QAAQ,QAAQ;AAC1C,QAAI,QAAQ,GAAI,MAAK,SAAS,OAAO,KAAK,EAAE;;AAE9C,UAAO;;AAET,SAAO;;CAKT,MAAM,MAAc,SAA0B;AAC5C,OAAK,OAAO,KAAK;GAAE;GAAM;GAAS,CAAC;AAInC,MAAI,KAAK,gBAAgB;AACvB,OAAI,QAAQ,WAAY,SAAQ,WAAW,KAAK,eAAe,QAAQ;AACvE,OAAI,QAAQ,WAAY,SAAQ,WAAW,KAAK,eAAe,MAAM,KAAK;GAC1E,MAAM,WAAW,KAAK,eAAe,SAAS;AAC9C,OAAI,YAAY,QAAQ,YAAa,SAAQ,YAAY,SAAS;;AAGpE,SAAO;;CAKT,cAAmD;AACjD,SAAO,KAAK,QAAQ,QAAQ;;CAG9B,iBAA2D;AACzD,SAAO,KAAK,QAAQ,SAAS;;CAG/B,gBAAsB;AACpB,OAAK,QAAQ,OAAO;;CAGtB,iBAAiB,QAAuB;AACtC,MAAI,KAAK,eACP,MAAK,eAAe,QAAQ,iBAAiB,OAAO;AAEtD,SAAO;;CAKT,SAAS,QAA2B;AAClC,OAAK,QAAQ,QAAQ;AACrB,SAAO;;CAGT,aAAmB;AACjB,SAAO,KAAK,QAAQ;AACpB,SAAO;;CAKT,gBAAgB,QAA4B;AAC1C,OAAK,QAAQ,SAAS;AACtB,SAAO;;CAGT,mBAAyB;AACvB,SAAO,KAAK,QAAQ;AACpB,SAAO;;CAKT,QAAc;AACZ,OAAK,eAAe;AACpB,OAAK,eAAe,SAAS;AAC7B,OAAK,eAAe,SAAS;AAC7B,OAAK,mBAAmB,SAAS;AACjC,4BAAQ,OAAO;AACf,MAAI,KAAK,gBAAgB;AACvB,QAAK,eAAe,QAAQ,OAAO;AACnC,QAAK,eAAe,YAAY,OAAO;;AAEzC,SAAO;;CAKT,MAAM,QAAyB;AAC7B,MAAI,KAAK,eACP,OAAM,IAAI,MAAM,yBAAyB;AAE3C,OAAK,iBAAiB,MAAMC,4BAAa,KAAK,UAAU,KAAK,SAAS,KAAK,QAAQ;GACjF,QAAQ,KAAK;GACb,QAAQ,KAAK;GACb,YAAY,KAAK;GAClB,CAAC;AACF,SAAO,KAAK,eAAe;;CAG7B,MAAM,OAAsB;AAC1B,MAAI,CAAC,KAAK,eACR,OAAM,IAAI,MAAM,qBAAqB;EAEvC,MAAM,EAAE,WAAW,KAAK;AACxB,QAAM,IAAI,SAAe,SAAS,WAAW;AAC3C,UAAO,OAAO,QAA4B,MAAM,OAAO,IAAI,GAAG,SAAS,CAAE;IACzE;AACF,OAAK,iBAAiB;;CAKxB,IAAI,UAAmB;AACrB,MAAI,CAAC,KAAK,eACR,OAAM,IAAI,MAAM,qBAAqB;AAEvC,SAAO,KAAK,eAAe;;CAG7B,IAAI,MAAc;AAChB,MAAI,CAAC,KAAK,eACR,OAAM,IAAI,MAAM,qBAAqB;AAEvC,SAAO,KAAK,eAAe;;CAG7B,IAAI,UAAkB;AACpB,SAAO,KAAK;;CAGd,IAAI,OAAe;EACjB,MAAM,SAAS,IAAI,IAAI,KAAK,IAAI;AAChC,MAAI,CAAC,OAAO,KACV,OAAM,IAAI,MAAM,oCAAoC,KAAK,MAAM;AAEjE,SAAO,SAAS,OAAO,MAAM,GAAG;;CAKlC,aAAa,OAAO,SAA8C;EAChE,MAAM,WAAW,IAAI,OAAO,QAAQ;AACpC,QAAM,SAAS,OAAO;AACtB,SAAO"}
package/dist/llmock.d.cts CHANGED
@@ -37,6 +37,10 @@ declare class LLMock {
37
37
  onSpeech(input: string | RegExp, response: AudioResponse): this;
38
38
  onTranscription(response: TranscriptionResponse): this;
39
39
  onVideo(prompt: string | RegExp, response: VideoResponse): this;
40
+ onAudio(input: string | RegExp, response: AudioResponse): this;
41
+ onSoundEffect(text: string | RegExp, response: AudioResponse): this;
42
+ onMusic(prompt: string | RegExp, response: AudioResponse): this;
43
+ onFalAudio(prompt: string | RegExp, response: AudioResponse, model?: string): this;
40
44
  onSearch(pattern: string | RegExp, results: SearchResult[]): this;
41
45
  onRerank(pattern: string | RegExp, results: RerankResult[]): this;
42
46
  onModerate(pattern: string | RegExp, result: ModerationResult): this;
@@ -1 +1 @@
1
- {"version":3,"file":"llmock.d.cts","names":[],"sources":["../src/llmock.ts"],"sourcesContent":[],"mappings":"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"}
1
+ {"version":3,"file":"llmock.d.cts","names":[],"sources":["../src/llmock.ts"],"sourcesContent":[],"mappings":"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"}
package/dist/llmock.d.ts CHANGED
@@ -37,6 +37,10 @@ declare class LLMock {
37
37
  onSpeech(input: string | RegExp, response: AudioResponse): this;
38
38
  onTranscription(response: TranscriptionResponse): this;
39
39
  onVideo(prompt: string | RegExp, response: VideoResponse): this;
40
+ onAudio(input: string | RegExp, response: AudioResponse): this;
41
+ onSoundEffect(text: string | RegExp, response: AudioResponse): this;
42
+ onMusic(prompt: string | RegExp, response: AudioResponse): this;
43
+ onFalAudio(prompt: string | RegExp, response: AudioResponse, model?: string): this;
40
44
  onSearch(pattern: string | RegExp, results: SearchResult[]): this;
41
45
  onRerank(pattern: string | RegExp, results: RerankResult[]): this;
42
46
  onModerate(pattern: string | RegExp, result: ModerationResult): this;
@@ -1 +1 @@
1
- {"version":3,"file":"llmock.d.ts","names":[],"sources":["../src/llmock.ts"],"sourcesContent":[],"mappings":"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"}
1
+ {"version":3,"file":"llmock.d.ts","names":[],"sources":["../src/llmock.ts"],"sourcesContent":[],"mappings":"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"}
package/dist/llmock.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import { entryToFixture, loadFixtureFile, loadFixturesFromDir, normalizeResponse, validateFixtures } from "./fixture-loader.js";
2
+ import { falJobs } from "./fal-audio.js";
2
3
  import { createServer } from "./server.js";
3
4
 
4
5
  //#region src/llmock.ts
@@ -116,6 +117,40 @@ var LLMock = class LLMock {
116
117
  response
117
118
  });
118
119
  }
120
+ onAudio(input, response) {
121
+ return this.addFixture({
122
+ match: { userMessage: input },
123
+ response
124
+ });
125
+ }
126
+ onSoundEffect(text, response) {
127
+ return this.addFixture({
128
+ match: {
129
+ userMessage: text,
130
+ endpoint: "audio-gen"
131
+ },
132
+ response
133
+ });
134
+ }
135
+ onMusic(prompt, response) {
136
+ return this.addFixture({
137
+ match: {
138
+ userMessage: prompt,
139
+ endpoint: "audio-gen"
140
+ },
141
+ response
142
+ });
143
+ }
144
+ onFalAudio(prompt, response, model) {
145
+ return this.addFixture({
146
+ match: {
147
+ userMessage: prompt,
148
+ endpoint: "fal-audio",
149
+ ...model ? { model } : {}
150
+ },
151
+ response
152
+ });
153
+ }
119
154
  onSearch(pattern, results) {
120
155
  this.searchFixtures.push({
121
156
  match: pattern,
@@ -159,10 +194,10 @@ var LLMock = class LLMock {
159
194
  const original = fixture.match.predicate;
160
195
  fixture.match.predicate = (req) => {
161
196
  const result = original(req);
162
- if (result) queueMicrotask(() => {
197
+ if (result) {
163
198
  const idx = this.fixtures.indexOf(fixture);
164
199
  if (idx !== -1) this.fixtures.splice(idx, 1);
165
- });
200
+ }
166
201
  return result;
167
202
  };
168
203
  return this;
@@ -214,6 +249,7 @@ var LLMock = class LLMock {
214
249
  this.searchFixtures.length = 0;
215
250
  this.rerankFixtures.length = 0;
216
251
  this.moderationFixtures.length = 0;
252
+ falJobs.clear();
217
253
  if (this.serverInstance) {
218
254
  this.serverInstance.journal.clear();
219
255
  this.serverInstance.videoStates.clear();
@@ -1 +1 @@
1
- {"version":3,"file":"llmock.js","names":[],"sources":["../src/llmock.ts"],"sourcesContent":["import type {\n AudioResponse,\n ChaosConfig,\n EmbeddingFixtureOpts,\n Fixture,\n FixtureFileEntry,\n FixtureFileResponse,\n FixtureMatch,\n FixtureOpts,\n FixtureResponse,\n ImageResponse,\n MockServerOptions,\n Mountable,\n RecordConfig,\n TranscriptionResponse,\n VideoResponse,\n} from \"./types.js\";\nimport { createServer, type ServerInstance } from \"./server.js\";\nimport {\n loadFixtureFile,\n loadFixturesFromDir,\n entryToFixture,\n normalizeResponse,\n validateFixtures,\n} from \"./fixture-loader.js\";\nimport { Journal } from \"./journal.js\";\nimport type { SearchFixture, SearchResult } from \"./search.js\";\nimport type { RerankFixture, RerankResult } from \"./rerank.js\";\nimport type { ModerationFixture, ModerationResult } from \"./moderation.js\";\n\nexport class LLMock {\n private fixtures: Fixture[] = [];\n private searchFixtures: SearchFixture[] = [];\n private rerankFixtures: RerankFixture[] = [];\n private moderationFixtures: ModerationFixture[] = [];\n private mounts: Array<{ path: string; handler: Mountable }> = [];\n private serverInstance: ServerInstance | null = null;\n private options: MockServerOptions;\n\n constructor(options?: MockServerOptions) {\n this.options = options ?? {};\n }\n\n // ---- Fixture management ----\n\n addFixture(fixture: Fixture): this {\n this.fixtures.push(fixture);\n return this;\n }\n\n addFixtures(fixtures: Fixture[]): this {\n this.fixtures.push(...fixtures);\n return this;\n }\n\n prependFixture(fixture: Fixture): this {\n this.fixtures.unshift(fixture);\n return this;\n }\n\n getFixtures(): readonly Fixture[] {\n return this.fixtures;\n }\n\n loadFixtureFile(filePath: string): this {\n this.fixtures.push(...loadFixtureFile(filePath));\n return this;\n }\n\n loadFixtureDir(dirPath: string): this {\n this.fixtures.push(...loadFixturesFromDir(dirPath));\n return this;\n }\n\n /**\n * Add fixtures from a JSON string or pre-parsed array of fixture entries.\n * Validates all fixtures and throws if any have severity \"error\".\n */\n addFixturesFromJSON(input: string | FixtureFileEntry[]): this {\n const entries: FixtureFileEntry[] = typeof input === \"string\" ? JSON.parse(input) : input;\n const converted = entries.map(entryToFixture);\n const issues = validateFixtures(converted);\n const errors = issues.filter((i) => i.severity === \"error\");\n if (errors.length > 0) {\n throw new Error(`Fixture validation failed: ${JSON.stringify(errors)}`);\n }\n this.fixtures.push(...converted);\n return this;\n }\n\n // Uses length = 0 to preserve array reference identity — the running\n // server reads this same array on every request.\n clearFixtures(): this {\n this.fixtures.length = 0;\n return this;\n }\n\n // ---- Convenience ----\n\n on(match: FixtureMatch, response: FixtureFileResponse, opts?: FixtureOpts): this {\n return this.addFixture({\n match,\n response: normalizeResponse(response),\n ...opts,\n });\n }\n\n onMessage(pattern: string | RegExp, response: FixtureFileResponse, opts?: FixtureOpts): this {\n return this.on({ userMessage: pattern }, response, opts);\n }\n\n onEmbedding(\n pattern: string | RegExp,\n response: FixtureFileResponse,\n opts?: EmbeddingFixtureOpts,\n ): this {\n return this.on({ inputText: pattern }, response, opts);\n }\n\n onJsonOutput(pattern: string | RegExp, jsonContent: object | string, opts?: FixtureOpts): this {\n const content = typeof jsonContent === \"string\" ? jsonContent : JSON.stringify(jsonContent);\n return this.on({ userMessage: pattern, responseFormat: \"json_object\" }, { content }, opts);\n }\n\n onToolCall(name: string, response: FixtureFileResponse, opts?: FixtureOpts): this {\n return this.on({ toolName: name }, response, opts);\n }\n\n onToolResult(id: string, response: FixtureFileResponse, opts?: FixtureOpts): this {\n return this.on({ toolCallId: id }, response, opts);\n }\n\n onTurn(\n turn: number,\n pattern: string | RegExp,\n response: FixtureFileResponse,\n opts?: FixtureOpts,\n ): this {\n return this.on({ userMessage: pattern, turnIndex: turn }, response, opts);\n }\n\n onImage(prompt: string | RegExp, response: ImageResponse): this {\n return this.addFixture({\n match: { userMessage: prompt, endpoint: \"image\" },\n response,\n });\n }\n\n onSpeech(input: string | RegExp, response: AudioResponse): this {\n return this.addFixture({\n match: { userMessage: input, endpoint: \"speech\" },\n response,\n });\n }\n\n onTranscription(response: TranscriptionResponse): this {\n return this.addFixture({\n match: { endpoint: \"transcription\" },\n response,\n });\n }\n\n onVideo(prompt: string | RegExp, response: VideoResponse): this {\n return this.addFixture({\n match: { userMessage: prompt, endpoint: \"video\" },\n response,\n });\n }\n\n // ---- Service mock convenience methods ----\n\n onSearch(pattern: string | RegExp, results: SearchResult[]): this {\n this.searchFixtures.push({ match: pattern, results });\n return this;\n }\n\n onRerank(pattern: string | RegExp, results: RerankResult[]): this {\n this.rerankFixtures.push({ match: pattern, results });\n return this;\n }\n\n onModerate(pattern: string | RegExp, result: ModerationResult): this {\n this.moderationFixtures.push({ match: pattern, result });\n return this;\n }\n\n /**\n * Queue a one-shot error that will be returned for the next matching\n * request, then automatically removed. Implemented as an internal fixture\n * with a `predicate` that always matches (so it fires first) and spliced\n * at the front of the fixture list.\n */\n nextRequestError(\n status: number,\n errorBody?: { message?: string; type?: string; code?: string },\n ): this {\n const errorResponse: FixtureResponse = {\n error: {\n message: errorBody?.message ?? \"Injected error\",\n type: errorBody?.type ?? \"server_error\",\n code: errorBody?.code,\n },\n status,\n };\n const fixture: Fixture = {\n match: { predicate: () => true },\n response: errorResponse,\n };\n // Insert at front so it matches before everything else\n this.fixtures.unshift(fixture);\n // Remove after first match — the journal records it so tests can assert\n const original = fixture.match.predicate!;\n fixture.match.predicate = (req) => {\n const result = original(req);\n if (result) {\n // Defer splice so it doesn't mutate the array while matchFixture iterates it\n queueMicrotask(() => {\n const idx = this.fixtures.indexOf(fixture);\n if (idx !== -1) this.fixtures.splice(idx, 1);\n });\n }\n return result;\n };\n return this;\n }\n\n // ---- Mounts ----\n\n mount(path: string, handler: Mountable): this {\n this.mounts.push({ path, handler });\n\n // If server is already running, wire up journal, registry, and baseUrl immediately\n // so late mounts behave identically to pre-start mounts.\n if (this.serverInstance) {\n if (handler.setJournal) handler.setJournal(this.serverInstance.journal);\n if (handler.setBaseUrl) handler.setBaseUrl(this.serverInstance.url + path);\n const registry = this.serverInstance.defaults.registry;\n if (registry && handler.setRegistry) handler.setRegistry(registry);\n }\n\n return this;\n }\n\n // ---- Journal proxies ----\n\n getRequests(): import(\"./types.js\").JournalEntry[] {\n return this.journal.getAll();\n }\n\n getLastRequest(): import(\"./types.js\").JournalEntry | null {\n return this.journal.getLast();\n }\n\n clearRequests(): void {\n this.journal.clear();\n }\n\n resetMatchCounts(testId?: string): this {\n if (this.serverInstance) {\n this.serverInstance.journal.clearMatchCounts(testId);\n }\n return this;\n }\n\n // ---- Chaos ----\n\n setChaos(config: ChaosConfig): this {\n this.options.chaos = config;\n return this;\n }\n\n clearChaos(): this {\n delete this.options.chaos;\n return this;\n }\n\n // ---- Recording ----\n\n enableRecording(config: RecordConfig): this {\n this.options.record = config;\n return this;\n }\n\n disableRecording(): this {\n delete this.options.record;\n return this;\n }\n\n // ---- Reset ----\n\n reset(): this {\n this.clearFixtures();\n this.searchFixtures.length = 0;\n this.rerankFixtures.length = 0;\n this.moderationFixtures.length = 0;\n if (this.serverInstance) {\n this.serverInstance.journal.clear();\n this.serverInstance.videoStates.clear();\n }\n return this;\n }\n\n // ---- Server lifecycle ----\n\n async start(): Promise<string> {\n if (this.serverInstance) {\n throw new Error(\"Server already started\");\n }\n this.serverInstance = await createServer(this.fixtures, this.options, this.mounts, {\n search: this.searchFixtures,\n rerank: this.rerankFixtures,\n moderation: this.moderationFixtures,\n });\n return this.serverInstance.url;\n }\n\n async stop(): Promise<void> {\n if (!this.serverInstance) {\n throw new Error(\"Server not started\");\n }\n const { server } = this.serverInstance;\n await new Promise<void>((resolve, reject) => {\n server.close((err: Error | undefined) => (err ? reject(err) : resolve()));\n });\n this.serverInstance = null;\n }\n\n // ---- Accessors ----\n\n get journal(): Journal {\n if (!this.serverInstance) {\n throw new Error(\"Server not started\");\n }\n return this.serverInstance.journal;\n }\n\n get url(): string {\n if (!this.serverInstance) {\n throw new Error(\"Server not started\");\n }\n return this.serverInstance.url;\n }\n\n get baseUrl(): string {\n return this.url;\n }\n\n get port(): number {\n const parsed = new URL(this.url); // this.url throws if not started\n if (!parsed.port) {\n throw new Error(`Server URL has no explicit port: ${this.url}`);\n }\n return parseInt(parsed.port, 10);\n }\n\n // ---- Static factory ----\n\n static async create(options?: MockServerOptions): Promise<LLMock> {\n const instance = new LLMock(options);\n await instance.start();\n return instance;\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"llmock.js","names":[],"sources":["../src/llmock.ts"],"sourcesContent":["import type {\n AudioResponse,\n ChaosConfig,\n EmbeddingFixtureOpts,\n Fixture,\n FixtureFileEntry,\n FixtureFileResponse,\n FixtureMatch,\n FixtureOpts,\n FixtureResponse,\n ImageResponse,\n MockServerOptions,\n Mountable,\n RecordConfig,\n TranscriptionResponse,\n VideoResponse,\n} from \"./types.js\";\nimport { createServer, type ServerInstance } from \"./server.js\";\nimport {\n loadFixtureFile,\n loadFixturesFromDir,\n entryToFixture,\n normalizeResponse,\n validateFixtures,\n} from \"./fixture-loader.js\";\nimport { Journal } from \"./journal.js\";\nimport type { SearchFixture, SearchResult } from \"./search.js\";\nimport type { RerankFixture, RerankResult } from \"./rerank.js\";\nimport type { ModerationFixture, ModerationResult } from \"./moderation.js\";\nimport { falJobs } from \"./fal-audio.js\";\n\nexport class LLMock {\n private fixtures: Fixture[] = [];\n private searchFixtures: SearchFixture[] = [];\n private rerankFixtures: RerankFixture[] = [];\n private moderationFixtures: ModerationFixture[] = [];\n private mounts: Array<{ path: string; handler: Mountable }> = [];\n private serverInstance: ServerInstance | null = null;\n private options: MockServerOptions;\n\n constructor(options?: MockServerOptions) {\n this.options = options ?? {};\n }\n\n // ---- Fixture management ----\n\n addFixture(fixture: Fixture): this {\n this.fixtures.push(fixture);\n return this;\n }\n\n addFixtures(fixtures: Fixture[]): this {\n this.fixtures.push(...fixtures);\n return this;\n }\n\n prependFixture(fixture: Fixture): this {\n this.fixtures.unshift(fixture);\n return this;\n }\n\n getFixtures(): readonly Fixture[] {\n return this.fixtures;\n }\n\n loadFixtureFile(filePath: string): this {\n this.fixtures.push(...loadFixtureFile(filePath));\n return this;\n }\n\n loadFixtureDir(dirPath: string): this {\n this.fixtures.push(...loadFixturesFromDir(dirPath));\n return this;\n }\n\n /**\n * Add fixtures from a JSON string or pre-parsed array of fixture entries.\n * Validates all fixtures and throws if any have severity \"error\".\n */\n addFixturesFromJSON(input: string | FixtureFileEntry[]): this {\n const entries: FixtureFileEntry[] = typeof input === \"string\" ? JSON.parse(input) : input;\n const converted = entries.map(entryToFixture);\n const issues = validateFixtures(converted);\n const errors = issues.filter((i) => i.severity === \"error\");\n if (errors.length > 0) {\n throw new Error(`Fixture validation failed: ${JSON.stringify(errors)}`);\n }\n this.fixtures.push(...converted);\n return this;\n }\n\n // Uses length = 0 to preserve array reference identity — the running\n // server reads this same array on every request.\n clearFixtures(): this {\n this.fixtures.length = 0;\n return this;\n }\n\n // ---- Convenience ----\n\n on(match: FixtureMatch, response: FixtureFileResponse, opts?: FixtureOpts): this {\n return this.addFixture({\n match,\n response: normalizeResponse(response),\n ...opts,\n });\n }\n\n onMessage(pattern: string | RegExp, response: FixtureFileResponse, opts?: FixtureOpts): this {\n return this.on({ userMessage: pattern }, response, opts);\n }\n\n onEmbedding(\n pattern: string | RegExp,\n response: FixtureFileResponse,\n opts?: EmbeddingFixtureOpts,\n ): this {\n return this.on({ inputText: pattern }, response, opts);\n }\n\n onJsonOutput(pattern: string | RegExp, jsonContent: object | string, opts?: FixtureOpts): this {\n const content = typeof jsonContent === \"string\" ? jsonContent : JSON.stringify(jsonContent);\n return this.on({ userMessage: pattern, responseFormat: \"json_object\" }, { content }, opts);\n }\n\n onToolCall(name: string, response: FixtureFileResponse, opts?: FixtureOpts): this {\n return this.on({ toolName: name }, response, opts);\n }\n\n onToolResult(id: string, response: FixtureFileResponse, opts?: FixtureOpts): this {\n return this.on({ toolCallId: id }, response, opts);\n }\n\n onTurn(\n turn: number,\n pattern: string | RegExp,\n response: FixtureFileResponse,\n opts?: FixtureOpts,\n ): this {\n return this.on({ userMessage: pattern, turnIndex: turn }, response, opts);\n }\n\n onImage(prompt: string | RegExp, response: ImageResponse): this {\n return this.addFixture({\n match: { userMessage: prompt, endpoint: \"image\" },\n response,\n });\n }\n\n onSpeech(input: string | RegExp, response: AudioResponse): this {\n return this.addFixture({\n match: { userMessage: input, endpoint: \"speech\" },\n response,\n });\n }\n\n onTranscription(response: TranscriptionResponse): this {\n return this.addFixture({\n match: { endpoint: \"transcription\" },\n response,\n });\n }\n\n onVideo(prompt: string | RegExp, response: VideoResponse): this {\n return this.addFixture({\n match: { userMessage: prompt, endpoint: \"video\" },\n response,\n });\n }\n\n onAudio(input: string | RegExp, response: AudioResponse): this {\n return this.addFixture({ match: { userMessage: input }, response });\n }\n\n onSoundEffect(text: string | RegExp, response: AudioResponse): this {\n return this.addFixture({\n match: { userMessage: text, endpoint: \"audio-gen\" },\n response,\n });\n }\n\n onMusic(prompt: string | RegExp, response: AudioResponse): this {\n return this.addFixture({\n match: { userMessage: prompt, endpoint: \"audio-gen\" },\n response,\n });\n }\n\n onFalAudio(prompt: string | RegExp, response: AudioResponse, model?: string): this {\n return this.addFixture({\n match: { userMessage: prompt, endpoint: \"fal-audio\", ...(model ? { model } : {}) },\n response,\n });\n }\n\n // ---- Service mock convenience methods ----\n\n onSearch(pattern: string | RegExp, results: SearchResult[]): this {\n this.searchFixtures.push({ match: pattern, results });\n return this;\n }\n\n onRerank(pattern: string | RegExp, results: RerankResult[]): this {\n this.rerankFixtures.push({ match: pattern, results });\n return this;\n }\n\n onModerate(pattern: string | RegExp, result: ModerationResult): this {\n this.moderationFixtures.push({ match: pattern, result });\n return this;\n }\n\n /**\n * Queue a one-shot error that will be returned for the next matching\n * request, then automatically removed. Implemented as an internal fixture\n * with a `predicate` that always matches (so it fires first) and spliced\n * at the front of the fixture list.\n */\n nextRequestError(\n status: number,\n errorBody?: { message?: string; type?: string; code?: string },\n ): this {\n const errorResponse: FixtureResponse = {\n error: {\n message: errorBody?.message ?? \"Injected error\",\n type: errorBody?.type ?? \"server_error\",\n code: errorBody?.code,\n },\n status,\n };\n const fixture: Fixture = {\n match: { predicate: () => true },\n response: errorResponse,\n };\n // Insert at front so it matches before everything else\n this.fixtures.unshift(fixture);\n // Remove after first match — the journal records it so tests can assert\n const original = fixture.match.predicate!;\n fixture.match.predicate = (req) => {\n const result = original(req);\n if (result) {\n // Remove synchronously on first match to prevent race conditions\n const idx = this.fixtures.indexOf(fixture);\n if (idx !== -1) this.fixtures.splice(idx, 1);\n }\n return result;\n };\n return this;\n }\n\n // ---- Mounts ----\n\n mount(path: string, handler: Mountable): this {\n this.mounts.push({ path, handler });\n\n // If server is already running, wire up journal, registry, and baseUrl immediately\n // so late mounts behave identically to pre-start mounts.\n if (this.serverInstance) {\n if (handler.setJournal) handler.setJournal(this.serverInstance.journal);\n if (handler.setBaseUrl) handler.setBaseUrl(this.serverInstance.url + path);\n const registry = this.serverInstance.defaults.registry;\n if (registry && handler.setRegistry) handler.setRegistry(registry);\n }\n\n return this;\n }\n\n // ---- Journal proxies ----\n\n getRequests(): import(\"./types.js\").JournalEntry[] {\n return this.journal.getAll();\n }\n\n getLastRequest(): import(\"./types.js\").JournalEntry | null {\n return this.journal.getLast();\n }\n\n clearRequests(): void {\n this.journal.clear();\n }\n\n resetMatchCounts(testId?: string): this {\n if (this.serverInstance) {\n this.serverInstance.journal.clearMatchCounts(testId);\n }\n return this;\n }\n\n // ---- Chaos ----\n\n setChaos(config: ChaosConfig): this {\n this.options.chaos = config;\n return this;\n }\n\n clearChaos(): this {\n delete this.options.chaos;\n return this;\n }\n\n // ---- Recording ----\n\n enableRecording(config: RecordConfig): this {\n this.options.record = config;\n return this;\n }\n\n disableRecording(): this {\n delete this.options.record;\n return this;\n }\n\n // ---- Reset ----\n\n reset(): this {\n this.clearFixtures();\n this.searchFixtures.length = 0;\n this.rerankFixtures.length = 0;\n this.moderationFixtures.length = 0;\n falJobs.clear();\n if (this.serverInstance) {\n this.serverInstance.journal.clear();\n this.serverInstance.videoStates.clear();\n }\n return this;\n }\n\n // ---- Server lifecycle ----\n\n async start(): Promise<string> {\n if (this.serverInstance) {\n throw new Error(\"Server already started\");\n }\n this.serverInstance = await createServer(this.fixtures, this.options, this.mounts, {\n search: this.searchFixtures,\n rerank: this.rerankFixtures,\n moderation: this.moderationFixtures,\n });\n return this.serverInstance.url;\n }\n\n async stop(): Promise<void> {\n if (!this.serverInstance) {\n throw new Error(\"Server not started\");\n }\n const { server } = this.serverInstance;\n await new Promise<void>((resolve, reject) => {\n server.close((err: Error | undefined) => (err ? reject(err) : resolve()));\n });\n this.serverInstance = null;\n }\n\n // ---- Accessors ----\n\n get journal(): Journal {\n if (!this.serverInstance) {\n throw new Error(\"Server not started\");\n }\n return this.serverInstance.journal;\n }\n\n get url(): string {\n if (!this.serverInstance) {\n throw new Error(\"Server not started\");\n }\n return this.serverInstance.url;\n }\n\n get baseUrl(): string {\n return this.url;\n }\n\n get port(): number {\n const parsed = new URL(this.url); // this.url throws if not started\n if (!parsed.port) {\n throw new Error(`Server URL has no explicit port: ${this.url}`);\n }\n return parseInt(parsed.port, 10);\n }\n\n // ---- Static factory ----\n\n static async create(options?: MockServerOptions): Promise<LLMock> {\n const instance = new LLMock(options);\n await instance.start();\n return instance;\n }\n}\n"],"mappings":"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"}
package/dist/logger.cjs CHANGED
@@ -2,8 +2,9 @@
2
2
  //#region src/logger.ts
3
3
  const LEVELS = {
4
4
  silent: 0,
5
- info: 1,
6
- debug: 2
5
+ warn: 1,
6
+ info: 2,
7
+ debug: 3
7
8
  };
8
9
  var Logger = class {
9
10
  level;
@@ -17,10 +18,10 @@ var Logger = class {
17
18
  if (this.level >= LEVELS.debug) console.log("[aimock]", ...args);
18
19
  }
19
20
  warn(...args) {
20
- console.warn("[aimock]", ...args);
21
+ if (this.level >= LEVELS.warn) console.warn("[aimock]", ...args);
21
22
  }
22
23
  error(...args) {
23
- console.error("[aimock]", ...args);
24
+ if (this.level >= LEVELS.warn) console.error("[aimock]", ...args);
24
25
  }
25
26
  };
26
27
 
@@ -1 +1 @@
1
- {"version":3,"file":"logger.cjs","names":[],"sources":["../src/logger.ts"],"sourcesContent":["export type LogLevel = \"silent\" | \"info\" | \"debug\";\n\nconst LEVELS: Record<LogLevel, number> = {\n silent: 0,\n info: 1,\n debug: 2,\n};\n\nexport class Logger {\n private level: number;\n\n constructor(level: LogLevel = \"silent\") {\n this.level = LEVELS[level];\n }\n\n info(...args: unknown[]): void {\n if (this.level >= LEVELS.info) {\n console.log(\"[aimock]\", ...args);\n }\n }\n\n debug(...args: unknown[]): void {\n if (this.level >= LEVELS.debug) {\n console.log(\"[aimock]\", ...args);\n }\n }\n\n warn(...args: unknown[]): void {\n console.warn(\"[aimock]\", ...args);\n }\n\n error(...args: unknown[]): void {\n console.error(\"[aimock]\", ...args);\n }\n}\n"],"mappings":";;AAEA,MAAM,SAAmC;CACvC,QAAQ;CACR,MAAM;CACN,OAAO;CACR;AAED,IAAa,SAAb,MAAoB;CAClB,AAAQ;CAER,YAAY,QAAkB,UAAU;AACtC,OAAK,QAAQ,OAAO;;CAGtB,KAAK,GAAG,MAAuB;AAC7B,MAAI,KAAK,SAAS,OAAO,KACvB,SAAQ,IAAI,YAAY,GAAG,KAAK;;CAIpC,MAAM,GAAG,MAAuB;AAC9B,MAAI,KAAK,SAAS,OAAO,MACvB,SAAQ,IAAI,YAAY,GAAG,KAAK;;CAIpC,KAAK,GAAG,MAAuB;AAC7B,UAAQ,KAAK,YAAY,GAAG,KAAK;;CAGnC,MAAM,GAAG,MAAuB;AAC9B,UAAQ,MAAM,YAAY,GAAG,KAAK"}
1
+ {"version":3,"file":"logger.cjs","names":[],"sources":["../src/logger.ts"],"sourcesContent":["export type LogLevel = \"silent\" | \"warn\" | \"info\" | \"debug\";\n\nconst LEVELS: Record<LogLevel, number> = {\n silent: 0,\n warn: 1,\n info: 2,\n debug: 3,\n};\n\nexport class Logger {\n private level: number;\n\n constructor(level: LogLevel = \"silent\") {\n this.level = LEVELS[level];\n }\n\n info(...args: unknown[]): void {\n if (this.level >= LEVELS.info) {\n console.log(\"[aimock]\", ...args);\n }\n }\n\n debug(...args: unknown[]): void {\n if (this.level >= LEVELS.debug) {\n console.log(\"[aimock]\", ...args);\n }\n }\n\n warn(...args: unknown[]): void {\n if (this.level >= LEVELS.warn) {\n console.warn(\"[aimock]\", ...args);\n }\n }\n\n error(...args: unknown[]): void {\n if (this.level >= LEVELS.warn) {\n console.error(\"[aimock]\", ...args);\n }\n }\n}\n"],"mappings":";;AAEA,MAAM,SAAmC;CACvC,QAAQ;CACR,MAAM;CACN,MAAM;CACN,OAAO;CACR;AAED,IAAa,SAAb,MAAoB;CAClB,AAAQ;CAER,YAAY,QAAkB,UAAU;AACtC,OAAK,QAAQ,OAAO;;CAGtB,KAAK,GAAG,MAAuB;AAC7B,MAAI,KAAK,SAAS,OAAO,KACvB,SAAQ,IAAI,YAAY,GAAG,KAAK;;CAIpC,MAAM,GAAG,MAAuB;AAC9B,MAAI,KAAK,SAAS,OAAO,MACvB,SAAQ,IAAI,YAAY,GAAG,KAAK;;CAIpC,KAAK,GAAG,MAAuB;AAC7B,MAAI,KAAK,SAAS,OAAO,KACvB,SAAQ,KAAK,YAAY,GAAG,KAAK;;CAIrC,MAAM,GAAG,MAAuB;AAC9B,MAAI,KAAK,SAAS,OAAO,KACvB,SAAQ,MAAM,YAAY,GAAG,KAAK"}
package/dist/logger.d.cts CHANGED
@@ -1,5 +1,5 @@
1
1
  //#region src/logger.d.ts
2
- type LogLevel = "silent" | "info" | "debug";
2
+ type LogLevel = "silent" | "warn" | "info" | "debug";
3
3
  declare class Logger {
4
4
  private level;
5
5
  constructor(level?: LogLevel);
@@ -1 +1 @@
1
- {"version":3,"file":"logger.d.cts","names":[],"sources":["../src/logger.ts"],"sourcesContent":[],"mappings":";KAAY,QAAA;AAAA,cAQC,MAAA,CARO;EAQP,QAAA,KAAM;sBAGE"}
1
+ {"version":3,"file":"logger.d.cts","names":[],"sources":["../src/logger.ts"],"sourcesContent":[],"mappings":";KAAY,QAAA;AAAA,cASC,MAAA,CATO;EASP,QAAA,KAAM;sBAGE"}
package/dist/logger.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  //#region src/logger.d.ts
2
- type LogLevel = "silent" | "info" | "debug";
2
+ type LogLevel = "silent" | "warn" | "info" | "debug";
3
3
  declare class Logger {
4
4
  private level;
5
5
  constructor(level?: LogLevel);
@@ -1 +1 @@
1
- {"version":3,"file":"logger.d.ts","names":[],"sources":["../src/logger.ts"],"sourcesContent":[],"mappings":";KAAY,QAAA;AAAA,cAQC,MAAA,CARO;EAQP,QAAA,KAAM;sBAGE"}
1
+ {"version":3,"file":"logger.d.ts","names":[],"sources":["../src/logger.ts"],"sourcesContent":[],"mappings":";KAAY,QAAA;AAAA,cASC,MAAA,CATO;EASP,QAAA,KAAM;sBAGE"}
package/dist/logger.js CHANGED
@@ -1,8 +1,9 @@
1
1
  //#region src/logger.ts
2
2
  const LEVELS = {
3
3
  silent: 0,
4
- info: 1,
5
- debug: 2
4
+ warn: 1,
5
+ info: 2,
6
+ debug: 3
6
7
  };
7
8
  var Logger = class {
8
9
  level;
@@ -16,10 +17,10 @@ var Logger = class {
16
17
  if (this.level >= LEVELS.debug) console.log("[aimock]", ...args);
17
18
  }
18
19
  warn(...args) {
19
- console.warn("[aimock]", ...args);
20
+ if (this.level >= LEVELS.warn) console.warn("[aimock]", ...args);
20
21
  }
21
22
  error(...args) {
22
- console.error("[aimock]", ...args);
23
+ if (this.level >= LEVELS.warn) console.error("[aimock]", ...args);
23
24
  }
24
25
  };
25
26
 
@@ -1 +1 @@
1
- {"version":3,"file":"logger.js","names":[],"sources":["../src/logger.ts"],"sourcesContent":["export type LogLevel = \"silent\" | \"info\" | \"debug\";\n\nconst LEVELS: Record<LogLevel, number> = {\n silent: 0,\n info: 1,\n debug: 2,\n};\n\nexport class Logger {\n private level: number;\n\n constructor(level: LogLevel = \"silent\") {\n this.level = LEVELS[level];\n }\n\n info(...args: unknown[]): void {\n if (this.level >= LEVELS.info) {\n console.log(\"[aimock]\", ...args);\n }\n }\n\n debug(...args: unknown[]): void {\n if (this.level >= LEVELS.debug) {\n console.log(\"[aimock]\", ...args);\n }\n }\n\n warn(...args: unknown[]): void {\n console.warn(\"[aimock]\", ...args);\n }\n\n error(...args: unknown[]): void {\n console.error(\"[aimock]\", ...args);\n }\n}\n"],"mappings":";AAEA,MAAM,SAAmC;CACvC,QAAQ;CACR,MAAM;CACN,OAAO;CACR;AAED,IAAa,SAAb,MAAoB;CAClB,AAAQ;CAER,YAAY,QAAkB,UAAU;AACtC,OAAK,QAAQ,OAAO;;CAGtB,KAAK,GAAG,MAAuB;AAC7B,MAAI,KAAK,SAAS,OAAO,KACvB,SAAQ,IAAI,YAAY,GAAG,KAAK;;CAIpC,MAAM,GAAG,MAAuB;AAC9B,MAAI,KAAK,SAAS,OAAO,MACvB,SAAQ,IAAI,YAAY,GAAG,KAAK;;CAIpC,KAAK,GAAG,MAAuB;AAC7B,UAAQ,KAAK,YAAY,GAAG,KAAK;;CAGnC,MAAM,GAAG,MAAuB;AAC9B,UAAQ,MAAM,YAAY,GAAG,KAAK"}
1
+ {"version":3,"file":"logger.js","names":[],"sources":["../src/logger.ts"],"sourcesContent":["export type LogLevel = \"silent\" | \"warn\" | \"info\" | \"debug\";\n\nconst LEVELS: Record<LogLevel, number> = {\n silent: 0,\n warn: 1,\n info: 2,\n debug: 3,\n};\n\nexport class Logger {\n private level: number;\n\n constructor(level: LogLevel = \"silent\") {\n this.level = LEVELS[level];\n }\n\n info(...args: unknown[]): void {\n if (this.level >= LEVELS.info) {\n console.log(\"[aimock]\", ...args);\n }\n }\n\n debug(...args: unknown[]): void {\n if (this.level >= LEVELS.debug) {\n console.log(\"[aimock]\", ...args);\n }\n }\n\n warn(...args: unknown[]): void {\n if (this.level >= LEVELS.warn) {\n console.warn(\"[aimock]\", ...args);\n }\n }\n\n error(...args: unknown[]): void {\n if (this.level >= LEVELS.warn) {\n console.error(\"[aimock]\", ...args);\n }\n }\n}\n"],"mappings":";AAEA,MAAM,SAAmC;CACvC,QAAQ;CACR,MAAM;CACN,MAAM;CACN,OAAO;CACR;AAED,IAAa,SAAb,MAAoB;CAClB,AAAQ;CAER,YAAY,QAAkB,UAAU;AACtC,OAAK,QAAQ,OAAO;;CAGtB,KAAK,GAAG,MAAuB;AAC7B,MAAI,KAAK,SAAS,OAAO,KACvB,SAAQ,IAAI,YAAY,GAAG,KAAK;;CAIpC,MAAM,GAAG,MAAuB;AAC9B,MAAI,KAAK,SAAS,OAAO,MACvB,SAAQ,IAAI,YAAY,GAAG,KAAK;;CAIpC,KAAK,GAAG,MAAuB;AAC7B,MAAI,KAAK,SAAS,OAAO,KACvB,SAAQ,KAAK,YAAY,GAAG,KAAK;;CAIrC,MAAM,GAAG,MAAuB;AAC9B,MAAI,KAAK,SAAS,OAAO,KACvB,SAAQ,MAAM,YAAY,GAAG,KAAK"}
@@ -2,7 +2,7 @@ import { Journal } from "./journal.cjs";
2
2
  import { MetricsRegistry } from "./metrics.cjs";
3
3
  import { Mountable } from "./types.cjs";
4
4
  import { MCPContent, MCPMockOptions, MCPPromptDefinition, MCPPromptResult, MCPResourceContent, MCPResourceDefinition, MCPSession, MCPToolDefinition } from "./mcp-types.cjs";
5
- import * as http from "node:http";
5
+ import * as http$1 from "node:http";
6
6
 
7
7
  //#region src/mcp-mock.d.ts
8
8
  declare class MCPMock implements Mountable {
@@ -20,7 +20,7 @@ declare class MCPMock implements Mountable {
20
20
  onToolCall(name: string, handler: (args: unknown) => MCPContent[] | string | Promise<MCPContent[] | string>): this;
21
21
  addResource(def: MCPResourceDefinition, content?: MCPResourceContent): this;
22
22
  addPrompt(def: MCPPromptDefinition, handler?: (args: unknown) => MCPPromptResult | Promise<MCPPromptResult>): this;
23
- handleRequest(req: http.IncomingMessage, res: http.ServerResponse, pathname: string): Promise<boolean>;
23
+ handleRequest(req: http$1.IncomingMessage, res: http$1.ServerResponse, pathname: string): Promise<boolean>;
24
24
  health(): {
25
25
  status: string;
26
26
  [key: string]: unknown;
@@ -1 +1 @@
1
- {"version":3,"file":"mcp-mock.d.cts","names":[],"sources":["../src/mcp-mock.ts"],"sourcesContent":[],"mappings":";;;;;;;cAiBa,OAAA,YAAmB;;EAAnB,QAAA,SAAQ;EAAA,QAAA,OAAA;UAqBG,QAAA;UAOT,MAAA;UAOiB,OAAA;UAAgC,QAAA;UAAR,OAAA;UAarC,cAAA;aAAiC,CAAA,OAAA,CAAA,EA3B5B,cA2B4B;SAQ3C,CAAA,GAAA,EA5BM,iBA4BN,CAAA,EAAA,IAAA;YACwB,CAAA,IAAA,EAAA,MAAA,EAAA,OAAA,EAAA,CAAA,IAAA,EAAA,OAAA,EAAA,GAtBD,UAsBC,EAAA,GAAA,MAAA,GAtBuB,OAsBvB,CAtB+B,UAsB/B,EAAA,GAAA,MAAA,CAAA,CAAA,EAAA,IAAA;aAA0B,CAAA,GAAA,EATxC,qBASwC,EAAA,OAAA,CAAA,EATP,kBASO,CAAA,EAAA,IAAA;WAAR,CAAA,GAAA,EAD1C,mBAC0C,EAAA,OAAA,CAAA,EAAA,CAAA,IAAA,EAAA,OAAA,EAAA,GAAlB,eAAkB,GAAA,OAAA,CAAQ,eAAR,CAAA,CAAA,EAAA,IAAA;eASrC,CAAA,GAAA,EAAL,IAAA,CAAK,eAAA,EAAA,GAAA,EACL,IAAA,CAAK,cADA,EAAA,QAAA,EAAA,MAAA,CAAA,EAGT,OAHS,CAAA,OAAA,CAAA;QACL,CAAA,CAAK,EAAA;IAET,MAAA,EAAA,MAAA;IAwDiB,CAAA,GAAA,EAAA,MAAA,CAAA,EAAA,OAAA;;YAUL,CAAA,OAAA,EAVK,OAUL,CAAA,EAAA,IAAA;aAoDD,CAAA,QAAA,EA1DQ,eA0DR,CAAA,EAAA,IAAA;OAkBa,CAAA,CAAA,EAtEZ,OAsEY,CAAA,MAAA,CAAA;MAAZ,CAAA,CAAA,EAlBD,OAkBC,CAAA,IAAA,CAAA;aA7Me,CAAA,CAAA,EAAA,OAAA,EAAA;EAAS,WAAA,CAAA,CAAA,EA6MxB,GA7MwB,CAAA,MAAA,EA6MZ,UA7MY,CAAA"}
1
+ {"version":3,"file":"mcp-mock.d.cts","names":[],"sources":["../src/mcp-mock.ts"],"sourcesContent":[],"mappings":";;;;;;;cAiBa,OAAA,YAAmB;;EAAnB,QAAA,SAAQ;EAAA,QAAA,OAAA;UAqBG,QAAA;UAOT,MAAA;UAOiB,OAAA;UAAgC,QAAA;UAAR,OAAA;UAarC,cAAA;aAAiC,CAAA,OAAA,CAAA,EA3B5B,cA2B4B;SAQ3C,CAAA,GAAA,EA5BM,iBA4BN,CAAA,EAAA,IAAA;YACwB,CAAA,IAAA,EAAA,MAAA,EAAA,OAAA,EAAA,CAAA,IAAA,EAAA,OAAA,EAAA,GAtBD,UAsBC,EAAA,GAAA,MAAA,GAtBuB,OAsBvB,CAtB+B,UAsB/B,EAAA,GAAA,MAAA,CAAA,CAAA,EAAA,IAAA;aAA0B,CAAA,GAAA,EATxC,qBASwC,EAAA,OAAA,CAAA,EATP,kBASO,CAAA,EAAA,IAAA;WAAR,CAAA,GAAA,EAD1C,mBAC0C,EAAA,OAAA,CAAA,EAAA,CAAA,IAAA,EAAA,OAAA,EAAA,GAAlB,eAAkB,GAAA,OAAA,CAAQ,eAAR,CAAA,CAAA,EAAA,IAAA;eASrC,CAAA,GAAA,EAAL,MAAA,CAAK,eAAA,EAAA,GAAA,EACL,MAAA,CAAK,cADA,EAAA,QAAA,EAAA,MAAA,CAAA,EAGT,OAHS,CAAA,OAAA,CAAA;QACL,CAAA,CAAA,EAAK;IAET,MAAA,EAAA,MAAA;IAwDiB,CAAA,GAAA,EAAA,MAAA,CAAA,EAAA,OAAA;;YAUL,CAAA,OAAA,EAVK,OAUL,CAAA,EAAA,IAAA;aAoDD,CAAA,QAAA,EA1DQ,eA0DR,CAAA,EAAA,IAAA;OAkBa,CAAA,CAAA,EAtEZ,OAsEY,CAAA,MAAA,CAAA;MAAZ,CAAA,CAAA,EAlBD,OAkBC,CAAA,IAAA,CAAA;aA7Me,CAAA,CAAA,EAAA,OAAA,EAAA;EAAS,WAAA,CAAA,CAAA,EA6MxB,GA7MwB,CAAA,MAAA,EA6MZ,UA7MY,CAAA"}
@@ -2,7 +2,7 @@ import { Journal } from "./journal.js";
2
2
  import { MetricsRegistry } from "./metrics.js";
3
3
  import { Mountable } from "./types.js";
4
4
  import { MCPContent, MCPMockOptions, MCPPromptDefinition, MCPPromptResult, MCPResourceContent, MCPResourceDefinition, MCPSession, MCPToolDefinition } from "./mcp-types.js";
5
- import * as http from "node:http";
5
+ import * as http$1 from "node:http";
6
6
 
7
7
  //#region src/mcp-mock.d.ts
8
8
  declare class MCPMock implements Mountable {
@@ -20,7 +20,7 @@ declare class MCPMock implements Mountable {
20
20
  onToolCall(name: string, handler: (args: unknown) => MCPContent[] | string | Promise<MCPContent[] | string>): this;
21
21
  addResource(def: MCPResourceDefinition, content?: MCPResourceContent): this;
22
22
  addPrompt(def: MCPPromptDefinition, handler?: (args: unknown) => MCPPromptResult | Promise<MCPPromptResult>): this;
23
- handleRequest(req: http.IncomingMessage, res: http.ServerResponse, pathname: string): Promise<boolean>;
23
+ handleRequest(req: http$1.IncomingMessage, res: http$1.ServerResponse, pathname: string): Promise<boolean>;
24
24
  health(): {
25
25
  status: string;
26
26
  [key: string]: unknown;
@@ -1 +1 @@
1
- {"version":3,"file":"mcp-mock.d.ts","names":[],"sources":["../src/mcp-mock.ts"],"sourcesContent":[],"mappings":";;;;;;;cAiBa,OAAA,YAAmB;;EAAnB,QAAA,SAAQ;EAAA,QAAA,OAAA;UAqBG,QAAA;UAOT,MAAA;UAOiB,OAAA;UAAgC,QAAA;UAAR,OAAA;UAarC,cAAA;aAAiC,CAAA,OAAA,CAAA,EA3B5B,cA2B4B;SAQ3C,CAAA,GAAA,EA5BM,iBA4BN,CAAA,EAAA,IAAA;YACwB,CAAA,IAAA,EAAA,MAAA,EAAA,OAAA,EAAA,CAAA,IAAA,EAAA,OAAA,EAAA,GAtBD,UAsBC,EAAA,GAAA,MAAA,GAtBuB,OAsBvB,CAtB+B,UAsB/B,EAAA,GAAA,MAAA,CAAA,CAAA,EAAA,IAAA;aAA0B,CAAA,GAAA,EATxC,qBASwC,EAAA,OAAA,CAAA,EATP,kBASO,CAAA,EAAA,IAAA;WAAR,CAAA,GAAA,EAD1C,mBAC0C,EAAA,OAAA,CAAA,EAAA,CAAA,IAAA,EAAA,OAAA,EAAA,GAAlB,eAAkB,GAAA,OAAA,CAAQ,eAAR,CAAA,CAAA,EAAA,IAAA;eASrC,CAAA,GAAA,EAAL,IAAA,CAAK,eAAA,EAAA,GAAA,EACL,IAAA,CAAK,cADA,EAAA,QAAA,EAAA,MAAA,CAAA,EAGT,OAHS,CAAA,OAAA,CAAA;QACL,CAAA,CAAK,EAAA;IAET,MAAA,EAAA,MAAA;IAwDiB,CAAA,GAAA,EAAA,MAAA,CAAA,EAAA,OAAA;;YAUL,CAAA,OAAA,EAVK,OAUL,CAAA,EAAA,IAAA;aAoDD,CAAA,QAAA,EA1DQ,eA0DR,CAAA,EAAA,IAAA;OAkBa,CAAA,CAAA,EAtEZ,OAsEY,CAAA,MAAA,CAAA;MAAZ,CAAA,CAAA,EAlBD,OAkBC,CAAA,IAAA,CAAA;aA7Me,CAAA,CAAA,EAAA,OAAA,EAAA;EAAS,WAAA,CAAA,CAAA,EA6MxB,GA7MwB,CAAA,MAAA,EA6MZ,UA7MY,CAAA"}
1
+ {"version":3,"file":"mcp-mock.d.ts","names":[],"sources":["../src/mcp-mock.ts"],"sourcesContent":[],"mappings":";;;;;;;cAiBa,OAAA,YAAmB;;EAAnB,QAAA,SAAQ;EAAA,QAAA,OAAA;UAqBG,QAAA;UAOT,MAAA;UAOiB,OAAA;UAAgC,QAAA;UAAR,OAAA;UAarC,cAAA;aAAiC,CAAA,OAAA,CAAA,EA3B5B,cA2B4B;SAQ3C,CAAA,GAAA,EA5BM,iBA4BN,CAAA,EAAA,IAAA;YACwB,CAAA,IAAA,EAAA,MAAA,EAAA,OAAA,EAAA,CAAA,IAAA,EAAA,OAAA,EAAA,GAtBD,UAsBC,EAAA,GAAA,MAAA,GAtBuB,OAsBvB,CAtB+B,UAsB/B,EAAA,GAAA,MAAA,CAAA,CAAA,EAAA,IAAA;aAA0B,CAAA,GAAA,EATxC,qBASwC,EAAA,OAAA,CAAA,EATP,kBASO,CAAA,EAAA,IAAA;WAAR,CAAA,GAAA,EAD1C,mBAC0C,EAAA,OAAA,CAAA,EAAA,CAAA,IAAA,EAAA,OAAA,EAAA,GAAlB,eAAkB,GAAA,OAAA,CAAQ,eAAR,CAAA,CAAA,EAAA,IAAA;eASrC,CAAA,GAAA,EAAL,MAAA,CAAK,eAAA,EAAA,GAAA,EACL,MAAA,CAAK,cADA,EAAA,QAAA,EAAA,MAAA,CAAA,EAGT,OAHS,CAAA,OAAA,CAAA;QACL,CAAA,CAAA,EAAK;IAET,MAAA,EAAA,MAAA;IAwDiB,CAAA,GAAA,EAAA,MAAA,CAAA,EAAA,OAAA;;YAUL,CAAA,OAAA,EAVK,OAUL,CAAA,EAAA,IAAA;aAoDD,CAAA,QAAA,EA1DQ,eA0DR,CAAA,EAAA,IAAA;OAkBa,CAAA,CAAA,EAtEZ,OAsEY,CAAA,MAAA,CAAA;MAAZ,CAAA,CAAA,EAlBD,OAkBC,CAAA,IAAA,CAAA;aA7Me,CAAA,CAAA,EAAA,OAAA,EAAA;EAAS,WAAA,CAAA,CAAA,EA6MxB,GA7MwB,CAAA,MAAA,EA6MZ,UA7MY,CAAA"}
package/dist/mcp-mock.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { flattenHeaders, readBody } from "./helpers.js";
2
2
  import { createMCPRequestHandler } from "./mcp-handler.js";
3
- import * as http from "node:http";
3
+ import * as http$1 from "node:http";
4
4
 
5
5
  //#region src/mcp-mock.ts
6
6
  var MCPMock = class {
@@ -90,7 +90,7 @@ var MCPMock = class {
90
90
  const host = this.options.host ?? "127.0.0.1";
91
91
  const port = this.options.port ?? 0;
92
92
  return new Promise((resolve, reject) => {
93
- const srv = http.createServer((req, res) => {
93
+ const srv = http$1.createServer((req, res) => {
94
94
  const chunks = [];
95
95
  req.on("data", (chunk) => chunks.push(chunk));
96
96
  req.on("end", () => {
@@ -1 +1 @@
1
- {"version":3,"file":"mcp-mock.js","names":[],"sources":["../src/mcp-mock.ts"],"sourcesContent":["import * as http from \"node:http\";\nimport type { Mountable } from \"./types.js\";\nimport type { Journal } from \"./journal.js\";\nimport type { MetricsRegistry } from \"./metrics.js\";\nimport type {\n MCPMockOptions,\n MCPToolDefinition,\n MCPResourceDefinition,\n MCPResourceContent,\n MCPPromptDefinition,\n MCPPromptResult,\n MCPContent,\n MCPSession,\n} from \"./mcp-types.js\";\nimport { createMCPRequestHandler, type MCPState } from \"./mcp-handler.js\";\nimport { flattenHeaders, readBody } from \"./helpers.js\";\n\nexport class MCPMock implements Mountable {\n private tools: Map<\n string,\n { def: MCPToolDefinition; handler?: (...args: unknown[]) => unknown }\n > = new Map();\n private resources: Map<string, { def: MCPResourceDefinition; content?: MCPResourceContent }> =\n new Map();\n private prompts: Map<\n string,\n {\n def: MCPPromptDefinition;\n handler?: (...args: unknown[]) => MCPPromptResult | Promise<MCPPromptResult>;\n }\n > = new Map();\n private sessions: Map<string, MCPSession> = new Map();\n private server: http.Server | null = null;\n private journal: Journal | null = null;\n private registry: MetricsRegistry | null = null;\n private options: MCPMockOptions;\n private requestHandler: ReturnType<typeof createMCPRequestHandler>;\n\n constructor(options?: MCPMockOptions) {\n this.options = options ?? {};\n this.requestHandler = this.buildHandler();\n }\n\n // ---- Configuration: Tools ----\n\n addTool(def: MCPToolDefinition): this {\n this.tools.set(def.name, { def });\n return this;\n }\n\n onToolCall(\n name: string,\n handler: (args: unknown) => MCPContent[] | string | Promise<MCPContent[] | string>,\n ): this {\n const entry = this.tools.get(name);\n if (entry) {\n entry.handler = handler;\n } else {\n this.tools.set(name, { def: { name }, handler });\n }\n return this;\n }\n\n // ---- Configuration: Resources ----\n\n addResource(def: MCPResourceDefinition, content?: MCPResourceContent): this {\n this.resources.set(def.uri, { def, content });\n return this;\n }\n\n // ---- Configuration: Prompts ----\n\n addPrompt(\n def: MCPPromptDefinition,\n handler?: (args: unknown) => MCPPromptResult | Promise<MCPPromptResult>,\n ): this {\n this.prompts.set(def.name, { def, handler });\n return this;\n }\n\n // ---- Mountable interface ----\n\n async handleRequest(\n req: http.IncomingMessage,\n res: http.ServerResponse,\n pathname: string,\n ): Promise<boolean> {\n // Only handle POST and DELETE to the root of the mount\n if (pathname !== \"/\" && pathname !== \"\") {\n return false;\n }\n if (req.method !== \"POST\" && req.method !== \"DELETE\") {\n return false;\n }\n\n const body = await readBody(req);\n\n // Extract JSON-RPC method for metrics (skip for DELETE — no JSON-RPC body)\n if (this.registry) {\n if (req.method === \"DELETE\") {\n this.registry.incrementCounter(\"aimock_mcp_requests_total\", { method: \"session/delete\" });\n } else {\n try {\n const parsed = JSON.parse(body);\n const method =\n typeof parsed === \"object\" && parsed !== null && \"method\" in parsed\n ? String(parsed.method)\n : \"unknown\";\n this.registry.incrementCounter(\"aimock_mcp_requests_total\", { method });\n } catch {\n this.registry.incrementCounter(\"aimock_mcp_requests_total\", { method: \"unknown\" });\n }\n }\n }\n\n await this.requestHandler(req, res, body);\n\n // Journal the request after the handler completes\n if (this.journal) {\n this.journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/\",\n headers: flattenHeaders(req.headers),\n body: null,\n service: \"mcp\",\n response: { status: res.statusCode, fixture: null },\n });\n }\n\n return true;\n }\n\n health(): { status: string; [key: string]: unknown } {\n return {\n status: \"ok\",\n tools: this.tools.size,\n resources: this.resources.size,\n prompts: this.prompts.size,\n sessions: this.sessions.size,\n };\n }\n\n setJournal(journal: Journal): void {\n this.journal = journal;\n }\n\n setRegistry(registry: MetricsRegistry): void {\n this.registry = registry;\n }\n\n // ---- Standalone mode ----\n\n async start(): Promise<string> {\n if (this.server) {\n throw new Error(\"Server already started\");\n }\n\n const host = this.options.host ?? \"127.0.0.1\";\n const port = this.options.port ?? 0;\n\n return new Promise((resolve, reject) => {\n const srv = http.createServer((req, res) => {\n const chunks: Buffer[] = [];\n req.on(\"data\", (chunk: Buffer) => chunks.push(chunk));\n req.on(\"end\", () => {\n const body = Buffer.concat(chunks).toString();\n\n this.requestHandler(req, res, body)\n .then(() => {\n if (this.journal) {\n this.journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/\",\n headers: flattenHeaders(req.headers),\n body: null,\n service: \"mcp\",\n response: { status: res.statusCode, fixture: null },\n });\n }\n })\n .catch((err) => {\n console.error(\"MCPMock request error:\", err);\n if (!res.headersSent) {\n res.writeHead(500);\n res.end(\"Internal server error\");\n }\n });\n });\n });\n\n srv.listen(port, host, () => {\n this.server = srv;\n const addr = srv.address();\n if (typeof addr === \"object\" && addr !== null) {\n resolve(`http://${host}:${addr.port}`);\n } else {\n resolve(`http://${host}:${port}`);\n }\n });\n\n srv.on(\"error\", reject);\n });\n }\n\n async stop(): Promise<void> {\n if (!this.server) {\n throw new Error(\"Server not started\");\n }\n const srv = this.server;\n this.server = null;\n await new Promise<void>((resolve, reject) => {\n srv.close((err) => (err ? reject(err) : resolve()));\n });\n }\n\n // ---- Inspection ----\n\n getRequests(): unknown[] {\n if (!this.journal) return [];\n return this.journal.getAll().filter((e) => e.service === \"mcp\");\n }\n\n getSessions(): Map<string, MCPSession> {\n return new Map(this.sessions);\n }\n\n reset(): this {\n this.tools.clear();\n this.resources.clear();\n this.prompts.clear();\n this.sessions.clear();\n this.requestHandler = this.buildHandler();\n return this;\n }\n\n // ---- Internal ----\n\n private buildHandler() {\n const state: MCPState = {\n serverInfo: this.options.serverInfo ?? { name: \"mcp-mock\", version: \"1.0.0\" },\n tools: this.tools,\n resources: this.resources,\n prompts: this.prompts,\n sessions: this.sessions,\n };\n return createMCPRequestHandler(state);\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"mcp-mock.js","names":["http"],"sources":["../src/mcp-mock.ts"],"sourcesContent":["import * as http from \"node:http\";\nimport type { Mountable } from \"./types.js\";\nimport type { Journal } from \"./journal.js\";\nimport type { MetricsRegistry } from \"./metrics.js\";\nimport type {\n MCPMockOptions,\n MCPToolDefinition,\n MCPResourceDefinition,\n MCPResourceContent,\n MCPPromptDefinition,\n MCPPromptResult,\n MCPContent,\n MCPSession,\n} from \"./mcp-types.js\";\nimport { createMCPRequestHandler, type MCPState } from \"./mcp-handler.js\";\nimport { flattenHeaders, readBody } from \"./helpers.js\";\n\nexport class MCPMock implements Mountable {\n private tools: Map<\n string,\n { def: MCPToolDefinition; handler?: (...args: unknown[]) => unknown }\n > = new Map();\n private resources: Map<string, { def: MCPResourceDefinition; content?: MCPResourceContent }> =\n new Map();\n private prompts: Map<\n string,\n {\n def: MCPPromptDefinition;\n handler?: (...args: unknown[]) => MCPPromptResult | Promise<MCPPromptResult>;\n }\n > = new Map();\n private sessions: Map<string, MCPSession> = new Map();\n private server: http.Server | null = null;\n private journal: Journal | null = null;\n private registry: MetricsRegistry | null = null;\n private options: MCPMockOptions;\n private requestHandler: ReturnType<typeof createMCPRequestHandler>;\n\n constructor(options?: MCPMockOptions) {\n this.options = options ?? {};\n this.requestHandler = this.buildHandler();\n }\n\n // ---- Configuration: Tools ----\n\n addTool(def: MCPToolDefinition): this {\n this.tools.set(def.name, { def });\n return this;\n }\n\n onToolCall(\n name: string,\n handler: (args: unknown) => MCPContent[] | string | Promise<MCPContent[] | string>,\n ): this {\n const entry = this.tools.get(name);\n if (entry) {\n entry.handler = handler;\n } else {\n this.tools.set(name, { def: { name }, handler });\n }\n return this;\n }\n\n // ---- Configuration: Resources ----\n\n addResource(def: MCPResourceDefinition, content?: MCPResourceContent): this {\n this.resources.set(def.uri, { def, content });\n return this;\n }\n\n // ---- Configuration: Prompts ----\n\n addPrompt(\n def: MCPPromptDefinition,\n handler?: (args: unknown) => MCPPromptResult | Promise<MCPPromptResult>,\n ): this {\n this.prompts.set(def.name, { def, handler });\n return this;\n }\n\n // ---- Mountable interface ----\n\n async handleRequest(\n req: http.IncomingMessage,\n res: http.ServerResponse,\n pathname: string,\n ): Promise<boolean> {\n // Only handle POST and DELETE to the root of the mount\n if (pathname !== \"/\" && pathname !== \"\") {\n return false;\n }\n if (req.method !== \"POST\" && req.method !== \"DELETE\") {\n return false;\n }\n\n const body = await readBody(req);\n\n // Extract JSON-RPC method for metrics (skip for DELETE — no JSON-RPC body)\n if (this.registry) {\n if (req.method === \"DELETE\") {\n this.registry.incrementCounter(\"aimock_mcp_requests_total\", { method: \"session/delete\" });\n } else {\n try {\n const parsed = JSON.parse(body);\n const method =\n typeof parsed === \"object\" && parsed !== null && \"method\" in parsed\n ? String(parsed.method)\n : \"unknown\";\n this.registry.incrementCounter(\"aimock_mcp_requests_total\", { method });\n } catch {\n this.registry.incrementCounter(\"aimock_mcp_requests_total\", { method: \"unknown\" });\n }\n }\n }\n\n await this.requestHandler(req, res, body);\n\n // Journal the request after the handler completes\n if (this.journal) {\n this.journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/\",\n headers: flattenHeaders(req.headers),\n body: null,\n service: \"mcp\",\n response: { status: res.statusCode, fixture: null },\n });\n }\n\n return true;\n }\n\n health(): { status: string; [key: string]: unknown } {\n return {\n status: \"ok\",\n tools: this.tools.size,\n resources: this.resources.size,\n prompts: this.prompts.size,\n sessions: this.sessions.size,\n };\n }\n\n setJournal(journal: Journal): void {\n this.journal = journal;\n }\n\n setRegistry(registry: MetricsRegistry): void {\n this.registry = registry;\n }\n\n // ---- Standalone mode ----\n\n async start(): Promise<string> {\n if (this.server) {\n throw new Error(\"Server already started\");\n }\n\n const host = this.options.host ?? \"127.0.0.1\";\n const port = this.options.port ?? 0;\n\n return new Promise((resolve, reject) => {\n const srv = http.createServer((req, res) => {\n const chunks: Buffer[] = [];\n req.on(\"data\", (chunk: Buffer) => chunks.push(chunk));\n req.on(\"end\", () => {\n const body = Buffer.concat(chunks).toString();\n\n this.requestHandler(req, res, body)\n .then(() => {\n if (this.journal) {\n this.journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/\",\n headers: flattenHeaders(req.headers),\n body: null,\n service: \"mcp\",\n response: { status: res.statusCode, fixture: null },\n });\n }\n })\n .catch((err) => {\n console.error(\"MCPMock request error:\", err);\n if (!res.headersSent) {\n res.writeHead(500);\n res.end(\"Internal server error\");\n }\n });\n });\n });\n\n srv.listen(port, host, () => {\n this.server = srv;\n const addr = srv.address();\n if (typeof addr === \"object\" && addr !== null) {\n resolve(`http://${host}:${addr.port}`);\n } else {\n resolve(`http://${host}:${port}`);\n }\n });\n\n srv.on(\"error\", reject);\n });\n }\n\n async stop(): Promise<void> {\n if (!this.server) {\n throw new Error(\"Server not started\");\n }\n const srv = this.server;\n this.server = null;\n await new Promise<void>((resolve, reject) => {\n srv.close((err) => (err ? reject(err) : resolve()));\n });\n }\n\n // ---- Inspection ----\n\n getRequests(): unknown[] {\n if (!this.journal) return [];\n return this.journal.getAll().filter((e) => e.service === \"mcp\");\n }\n\n getSessions(): Map<string, MCPSession> {\n return new Map(this.sessions);\n }\n\n reset(): this {\n this.tools.clear();\n this.resources.clear();\n this.prompts.clear();\n this.sessions.clear();\n this.requestHandler = this.buildHandler();\n return this;\n }\n\n // ---- Internal ----\n\n private buildHandler() {\n const state: MCPState = {\n serverInfo: this.options.serverInfo ?? { name: \"mcp-mock\", version: \"1.0.0\" },\n tools: this.tools,\n resources: this.resources,\n prompts: this.prompts,\n sessions: this.sessions,\n };\n return createMCPRequestHandler(state);\n }\n}\n"],"mappings":"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"}
@@ -1,10 +1,10 @@
1
1
  import { Journal } from "./journal.cjs";
2
2
  import { Fixture, HandlerDefaults } from "./types.cjs";
3
- import * as http from "node:http";
3
+ import * as http$1 from "node:http";
4
4
 
5
5
  //#region src/messages.d.ts
6
6
 
7
- declare function handleMessages(req: http.IncomingMessage, res: http.ServerResponse, raw: string, fixtures: Fixture[], journal: Journal, defaults: HandlerDefaults, setCorsHeaders: (res: http.ServerResponse) => void): Promise<void>;
7
+ declare function handleMessages(req: http$1.IncomingMessage, res: http$1.ServerResponse, raw: string, fixtures: Fixture[], journal: Journal, defaults: HandlerDefaults, setCorsHeaders: (res: http$1.ServerResponse) => void): Promise<void>;
8
8
  //#endregion
9
9
  export { handleMessages };
10
10
  //# sourceMappingURL=messages.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"messages.d.cts","names":[],"sources":["../src/messages.ts"],"sourcesContent":[],"mappings":";;;;;;iBAirBsB,cAAA,MACf,IAAA,CAAK,sBACL,IAAA,CAAK,uCAEA,oBACD,mBACC,uCACY,IAAA,CAAK,0BAC1B"}
1
+ {"version":3,"file":"messages.d.cts","names":[],"sources":["../src/messages.ts"],"sourcesContent":[],"mappings":";;;;;;iBAirBsB,cAAA,MACf,MAAA,CAAK,sBACL,MAAA,CAAK,uCAEA,oBACD,mBACC,uCACY,MAAA,CAAK,0BAC1B"}
@@ -1,10 +1,10 @@
1
1
  import { Journal } from "./journal.js";
2
2
  import { Fixture, HandlerDefaults } from "./types.js";
3
- import * as http from "node:http";
3
+ import * as http$1 from "node:http";
4
4
 
5
5
  //#region src/messages.d.ts
6
6
 
7
- declare function handleMessages(req: http.IncomingMessage, res: http.ServerResponse, raw: string, fixtures: Fixture[], journal: Journal, defaults: HandlerDefaults, setCorsHeaders: (res: http.ServerResponse) => void): Promise<void>;
7
+ declare function handleMessages(req: http$1.IncomingMessage, res: http$1.ServerResponse, raw: string, fixtures: Fixture[], journal: Journal, defaults: HandlerDefaults, setCorsHeaders: (res: http$1.ServerResponse) => void): Promise<void>;
8
8
  //#endregion
9
9
  export { handleMessages };
10
10
  //# sourceMappingURL=messages.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"messages.d.ts","names":[],"sources":["../src/messages.ts"],"sourcesContent":[],"mappings":";;;;;;iBAirBsB,cAAA,MACf,IAAA,CAAK,sBACL,IAAA,CAAK,uCAEA,oBACD,mBACC,uCACY,IAAA,CAAK,0BAC1B"}
1
+ {"version":3,"file":"messages.d.ts","names":[],"sources":["../src/messages.ts"],"sourcesContent":[],"mappings":";;;;;;iBAirBsB,cAAA,MACf,MAAA,CAAK,sBACL,MAAA,CAAK,uCAEA,oBACD,mBACC,uCACY,MAAA,CAAK,0BAC1B"}