@copilotkit/aimock 1.10.0 → 1.12.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 (167) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/README.md +4 -2
  4. package/dist/a2a-types.d.cts.map +1 -1
  5. package/dist/a2a-types.d.ts.map +1 -1
  6. package/dist/agui-handler.cjs +340 -0
  7. package/dist/agui-handler.cjs.map +1 -0
  8. package/dist/agui-handler.d.cts +96 -0
  9. package/dist/agui-handler.d.cts.map +1 -0
  10. package/dist/agui-handler.d.ts +96 -0
  11. package/dist/agui-handler.d.ts.map +1 -0
  12. package/dist/agui-handler.js +326 -0
  13. package/dist/agui-handler.js.map +1 -0
  14. package/dist/agui-mock.cjs +190 -0
  15. package/dist/agui-mock.cjs.map +1 -0
  16. package/dist/agui-mock.d.cts +50 -0
  17. package/dist/agui-mock.d.cts.map +1 -0
  18. package/dist/agui-mock.d.ts +50 -0
  19. package/dist/agui-mock.d.ts.map +1 -0
  20. package/dist/agui-mock.js +188 -0
  21. package/dist/agui-mock.js.map +1 -0
  22. package/dist/agui-recorder.cjs +153 -0
  23. package/dist/agui-recorder.cjs.map +1 -0
  24. package/dist/agui-recorder.d.cts +19 -0
  25. package/dist/agui-recorder.d.cts.map +1 -0
  26. package/dist/agui-recorder.d.ts +19 -0
  27. package/dist/agui-recorder.d.ts.map +1 -0
  28. package/dist/agui-recorder.js +147 -0
  29. package/dist/agui-recorder.js.map +1 -0
  30. package/dist/agui-types.d.cts +231 -0
  31. package/dist/agui-types.d.cts.map +1 -0
  32. package/dist/agui-types.d.ts +231 -0
  33. package/dist/agui-types.d.ts.map +1 -0
  34. package/dist/bedrock-converse.cjs +2 -0
  35. package/dist/bedrock-converse.cjs.map +1 -1
  36. package/dist/bedrock-converse.d.cts.map +1 -1
  37. package/dist/bedrock-converse.d.ts.map +1 -1
  38. package/dist/bedrock-converse.js +2 -0
  39. package/dist/bedrock-converse.js.map +1 -1
  40. package/dist/bedrock.cjs +2 -0
  41. package/dist/bedrock.cjs.map +1 -1
  42. package/dist/bedrock.d.cts.map +1 -1
  43. package/dist/bedrock.d.ts.map +1 -1
  44. package/dist/bedrock.js +2 -0
  45. package/dist/bedrock.js.map +1 -1
  46. package/dist/cli.cjs +32 -1
  47. package/dist/cli.cjs.map +1 -1
  48. package/dist/cli.js +32 -1
  49. package/dist/cli.js.map +1 -1
  50. package/dist/cohere.cjs +1 -0
  51. package/dist/cohere.cjs.map +1 -1
  52. package/dist/cohere.js +1 -0
  53. package/dist/cohere.js.map +1 -1
  54. package/dist/config-loader.cjs +19 -0
  55. package/dist/config-loader.cjs.map +1 -1
  56. package/dist/config-loader.d.cts +16 -0
  57. package/dist/config-loader.d.cts.map +1 -1
  58. package/dist/config-loader.d.ts +16 -0
  59. package/dist/config-loader.d.ts.map +1 -1
  60. package/dist/config-loader.js +19 -0
  61. package/dist/config-loader.js.map +1 -1
  62. package/dist/embeddings.cjs +2 -1
  63. package/dist/embeddings.cjs.map +1 -1
  64. package/dist/embeddings.js +2 -1
  65. package/dist/embeddings.js.map +1 -1
  66. package/dist/gemini.cjs +1 -0
  67. package/dist/gemini.cjs.map +1 -1
  68. package/dist/gemini.js +1 -0
  69. package/dist/gemini.js.map +1 -1
  70. package/dist/helpers.cjs +16 -0
  71. package/dist/helpers.cjs.map +1 -1
  72. package/dist/helpers.d.cts +6 -2
  73. package/dist/helpers.d.cts.map +1 -1
  74. package/dist/helpers.d.ts +6 -2
  75. package/dist/helpers.d.ts.map +1 -1
  76. package/dist/helpers.js +13 -1
  77. package/dist/helpers.js.map +1 -1
  78. package/dist/images.cjs +166 -0
  79. package/dist/images.cjs.map +1 -0
  80. package/dist/images.d.cts +11 -0
  81. package/dist/images.d.cts.map +1 -0
  82. package/dist/images.d.ts +11 -0
  83. package/dist/images.d.ts.map +1 -0
  84. package/dist/images.js +166 -0
  85. package/dist/images.js.map +1 -0
  86. package/dist/index.cjs +32 -0
  87. package/dist/index.d.cts +11 -3
  88. package/dist/index.d.ts +11 -3
  89. package/dist/index.js +9 -2
  90. package/dist/llmock.cjs +37 -1
  91. package/dist/llmock.cjs.map +1 -1
  92. package/dist/llmock.d.cts +5 -1
  93. package/dist/llmock.d.cts.map +1 -1
  94. package/dist/llmock.d.ts +5 -1
  95. package/dist/llmock.d.ts.map +1 -1
  96. package/dist/llmock.js +37 -1
  97. package/dist/llmock.js.map +1 -1
  98. package/dist/messages.cjs +1 -0
  99. package/dist/messages.cjs.map +1 -1
  100. package/dist/messages.js +1 -0
  101. package/dist/messages.js.map +1 -1
  102. package/dist/ollama.cjs +2 -0
  103. package/dist/ollama.cjs.map +1 -1
  104. package/dist/ollama.d.cts.map +1 -1
  105. package/dist/ollama.d.ts.map +1 -1
  106. package/dist/ollama.js +2 -0
  107. package/dist/ollama.js.map +1 -1
  108. package/dist/recorder.cjs +50 -7
  109. package/dist/recorder.cjs.map +1 -1
  110. package/dist/recorder.js +50 -7
  111. package/dist/recorder.js.map +1 -1
  112. package/dist/responses.cjs +1 -0
  113. package/dist/responses.cjs.map +1 -1
  114. package/dist/responses.js +1 -0
  115. package/dist/responses.js.map +1 -1
  116. package/dist/router.cjs +8 -0
  117. package/dist/router.cjs.map +1 -1
  118. package/dist/router.d.cts.map +1 -1
  119. package/dist/router.d.ts.map +1 -1
  120. package/dist/router.js +9 -0
  121. package/dist/router.js.map +1 -1
  122. package/dist/server.cjs +80 -3
  123. package/dist/server.cjs.map +1 -1
  124. package/dist/server.d.cts +2 -0
  125. package/dist/server.d.cts.map +1 -1
  126. package/dist/server.d.ts +2 -0
  127. package/dist/server.d.ts.map +1 -1
  128. package/dist/server.js +80 -3
  129. package/dist/server.js.map +1 -1
  130. package/dist/speech.cjs +144 -0
  131. package/dist/speech.cjs.map +1 -0
  132. package/dist/speech.d.cts +11 -0
  133. package/dist/speech.d.cts.map +1 -0
  134. package/dist/speech.d.ts +11 -0
  135. package/dist/speech.d.ts.map +1 -0
  136. package/dist/speech.js +144 -0
  137. package/dist/speech.js.map +1 -0
  138. package/dist/suite.cjs +8 -0
  139. package/dist/suite.cjs.map +1 -1
  140. package/dist/suite.d.cts +4 -0
  141. package/dist/suite.d.cts.map +1 -1
  142. package/dist/suite.d.ts +4 -0
  143. package/dist/suite.d.ts.map +1 -1
  144. package/dist/suite.js +8 -0
  145. package/dist/suite.js.map +1 -1
  146. package/dist/transcription.cjs +134 -0
  147. package/dist/transcription.cjs.map +1 -0
  148. package/dist/transcription.d.cts +11 -0
  149. package/dist/transcription.d.cts.map +1 -0
  150. package/dist/transcription.d.ts +11 -0
  151. package/dist/transcription.d.ts.map +1 -0
  152. package/dist/transcription.js +134 -0
  153. package/dist/transcription.js.map +1 -0
  154. package/dist/types.d.cts +44 -2
  155. package/dist/types.d.cts.map +1 -1
  156. package/dist/types.d.ts +44 -2
  157. package/dist/types.d.ts.map +1 -1
  158. package/dist/vector-types.d.ts.map +1 -1
  159. package/dist/video.cjs +196 -0
  160. package/dist/video.cjs.map +1 -0
  161. package/dist/video.d.cts +14 -0
  162. package/dist/video.d.cts.map +1 -0
  163. package/dist/video.d.ts +14 -0
  164. package/dist/video.d.ts.map +1 -0
  165. package/dist/video.js +195 -0
  166. package/dist/video.js.map +1 -0
  167. package/package.json +2 -2
@@ -0,0 +1,144 @@
1
+ const require_helpers = require('./helpers.cjs');
2
+ const require_router = require('./router.cjs');
3
+ const require_sse_writer = require('./sse-writer.cjs');
4
+ const require_chaos = require('./chaos.cjs');
5
+ const require_recorder = require('./recorder.cjs');
6
+
7
+ //#region src/speech.ts
8
+ const FORMAT_TO_CONTENT_TYPE = {
9
+ mp3: "audio/mpeg",
10
+ opus: "audio/opus",
11
+ aac: "audio/aac",
12
+ flac: "audio/flac",
13
+ wav: "audio/wav",
14
+ pcm: "audio/pcm"
15
+ };
16
+ async function handleSpeech(req, res, raw, fixtures, journal, defaults, setCorsHeaders) {
17
+ setCorsHeaders(res);
18
+ const path = req.url ?? "/v1/audio/speech";
19
+ const method = req.method ?? "POST";
20
+ let speechReq;
21
+ try {
22
+ speechReq = JSON.parse(raw);
23
+ } catch {
24
+ journal.add({
25
+ method,
26
+ path,
27
+ headers: require_helpers.flattenHeaders(req.headers),
28
+ body: null,
29
+ response: {
30
+ status: 400,
31
+ fixture: null
32
+ }
33
+ });
34
+ require_sse_writer.writeErrorResponse(res, 400, JSON.stringify({ error: {
35
+ message: "Malformed JSON",
36
+ type: "invalid_request_error",
37
+ code: "invalid_json"
38
+ } }));
39
+ return;
40
+ }
41
+ const syntheticReq = {
42
+ model: speechReq.model ?? "tts-1",
43
+ messages: [{
44
+ role: "user",
45
+ content: speechReq.input
46
+ }],
47
+ _endpointType: "speech"
48
+ };
49
+ const testId = require_helpers.getTestId(req);
50
+ const fixture = require_router.matchFixture(fixtures, syntheticReq, journal.getFixtureMatchCountsForTest(testId), defaults.requestTransform);
51
+ if (fixture) journal.incrementFixtureMatchCount(fixture, fixtures, testId);
52
+ if (require_chaos.applyChaos(res, fixture, defaults.chaos, req.headers, journal, {
53
+ method,
54
+ path,
55
+ headers: require_helpers.flattenHeaders(req.headers),
56
+ body: syntheticReq
57
+ }, defaults.registry, defaults.logger)) return;
58
+ if (!fixture) {
59
+ if (defaults.record) {
60
+ if (await require_recorder.proxyAndRecord(req, res, syntheticReq, "openai", req.url ?? "/v1/audio/speech", fixtures, defaults, raw)) {
61
+ journal.add({
62
+ method,
63
+ path,
64
+ headers: require_helpers.flattenHeaders(req.headers),
65
+ body: syntheticReq,
66
+ response: {
67
+ status: res.statusCode ?? 200,
68
+ fixture: null
69
+ }
70
+ });
71
+ return;
72
+ }
73
+ }
74
+ const strictStatus = defaults.strict ? 503 : 404;
75
+ const strictMessage = defaults.strict ? "Strict mode: no fixture matched" : "No fixture matched";
76
+ journal.add({
77
+ method,
78
+ path,
79
+ headers: require_helpers.flattenHeaders(req.headers),
80
+ body: syntheticReq,
81
+ response: {
82
+ status: strictStatus,
83
+ fixture: null
84
+ }
85
+ });
86
+ require_sse_writer.writeErrorResponse(res, strictStatus, JSON.stringify({ error: {
87
+ message: strictMessage,
88
+ type: "invalid_request_error",
89
+ code: "no_fixture_match"
90
+ } }));
91
+ return;
92
+ }
93
+ const response = fixture.response;
94
+ if (require_helpers.isErrorResponse(response)) {
95
+ const status = response.status ?? 500;
96
+ journal.add({
97
+ method,
98
+ path,
99
+ headers: require_helpers.flattenHeaders(req.headers),
100
+ body: syntheticReq,
101
+ response: {
102
+ status,
103
+ fixture
104
+ }
105
+ });
106
+ require_sse_writer.writeErrorResponse(res, status, JSON.stringify(response));
107
+ return;
108
+ }
109
+ if (!require_helpers.isAudioResponse(response)) {
110
+ journal.add({
111
+ method,
112
+ path,
113
+ headers: require_helpers.flattenHeaders(req.headers),
114
+ body: syntheticReq,
115
+ response: {
116
+ status: 500,
117
+ fixture
118
+ }
119
+ });
120
+ require_sse_writer.writeErrorResponse(res, 500, JSON.stringify({ error: {
121
+ message: "Fixture response is not an audio type",
122
+ type: "server_error"
123
+ } }));
124
+ return;
125
+ }
126
+ journal.add({
127
+ method,
128
+ path,
129
+ headers: require_helpers.flattenHeaders(req.headers),
130
+ body: syntheticReq,
131
+ response: {
132
+ status: 200,
133
+ fixture
134
+ }
135
+ });
136
+ const contentType = FORMAT_TO_CONTENT_TYPE[response.format ?? "mp3"] ?? "audio/mpeg";
137
+ const audioBytes = Buffer.from(response.audio, "base64");
138
+ res.writeHead(200, { "Content-Type": contentType });
139
+ res.end(audioBytes);
140
+ }
141
+
142
+ //#endregion
143
+ exports.handleSpeech = handleSpeech;
144
+ //# sourceMappingURL=speech.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"speech.cjs","names":["flattenHeaders","getTestId","matchFixture","applyChaos","proxyAndRecord","isErrorResponse","isAudioResponse"],"sources":["../src/speech.ts"],"sourcesContent":["import type * as http from \"node:http\";\nimport type { ChatCompletionRequest, Fixture, HandlerDefaults } from \"./types.js\";\nimport { isAudioResponse, isErrorResponse, flattenHeaders, getTestId } from \"./helpers.js\";\nimport { matchFixture } from \"./router.js\";\nimport { writeErrorResponse } from \"./sse-writer.js\";\nimport type { Journal } from \"./journal.js\";\nimport { applyChaos } from \"./chaos.js\";\nimport { proxyAndRecord } from \"./recorder.js\";\n\ninterface SpeechRequest {\n model?: string;\n input: string;\n voice?: string;\n response_format?: string;\n speed?: number;\n [key: string]: unknown;\n}\n\nconst FORMAT_TO_CONTENT_TYPE: Record<string, string> = {\n mp3: \"audio/mpeg\",\n opus: \"audio/opus\",\n aac: \"audio/aac\",\n flac: \"audio/flac\",\n wav: \"audio/wav\",\n pcm: \"audio/pcm\",\n};\n\nexport async function handleSpeech(\n req: http.IncomingMessage,\n res: http.ServerResponse,\n raw: string,\n fixtures: Fixture[],\n journal: Journal,\n defaults: HandlerDefaults,\n setCorsHeaders: (res: http.ServerResponse) => void,\n): Promise<void> {\n setCorsHeaders(res);\n const path = req.url ?? \"/v1/audio/speech\";\n const method = req.method ?? \"POST\";\n\n let speechReq: SpeechRequest;\n try {\n speechReq = JSON.parse(raw) as SpeechRequest;\n } catch {\n journal.add({\n method,\n path,\n headers: flattenHeaders(req.headers),\n body: null,\n response: { status: 400, fixture: null },\n });\n writeErrorResponse(\n res,\n 400,\n JSON.stringify({\n error: { message: \"Malformed JSON\", type: \"invalid_request_error\", code: \"invalid_json\" },\n }),\n );\n return;\n }\n\n const syntheticReq: ChatCompletionRequest = {\n model: speechReq.model ?? \"tts-1\",\n messages: [{ role: \"user\", content: speechReq.input }],\n _endpointType: \"speech\",\n };\n\n const testId = getTestId(req);\n const fixture = matchFixture(\n fixtures,\n syntheticReq,\n journal.getFixtureMatchCountsForTest(testId),\n defaults.requestTransform,\n );\n\n if (fixture) {\n journal.incrementFixtureMatchCount(fixture, fixtures, testId);\n }\n\n if (\n applyChaos(\n res,\n fixture,\n defaults.chaos,\n req.headers,\n journal,\n { method, path, headers: flattenHeaders(req.headers), body: syntheticReq },\n defaults.registry,\n defaults.logger,\n )\n )\n return;\n\n if (!fixture) {\n if (defaults.record) {\n const proxied = await proxyAndRecord(\n req,\n res,\n syntheticReq,\n \"openai\",\n req.url ?? \"/v1/audio/speech\",\n fixtures,\n defaults,\n raw,\n );\n if (proxied) {\n journal.add({\n method,\n path,\n headers: flattenHeaders(req.headers),\n body: syntheticReq,\n response: { status: res.statusCode ?? 200, fixture: null },\n });\n return;\n }\n }\n\n const strictStatus = defaults.strict ? 503 : 404;\n const strictMessage = defaults.strict\n ? \"Strict mode: no fixture matched\"\n : \"No fixture matched\";\n journal.add({\n method,\n path,\n headers: flattenHeaders(req.headers),\n body: syntheticReq,\n response: { status: strictStatus, fixture: null },\n });\n writeErrorResponse(\n res,\n strictStatus,\n JSON.stringify({\n error: { message: strictMessage, type: \"invalid_request_error\", code: \"no_fixture_match\" },\n }),\n );\n return;\n }\n\n const response = fixture.response;\n\n if (isErrorResponse(response)) {\n const status = response.status ?? 500;\n journal.add({\n method,\n path,\n headers: flattenHeaders(req.headers),\n body: syntheticReq,\n response: { status, fixture },\n });\n writeErrorResponse(res, status, JSON.stringify(response));\n return;\n }\n\n if (!isAudioResponse(response)) {\n journal.add({\n method,\n path,\n headers: flattenHeaders(req.headers),\n body: syntheticReq,\n response: { status: 500, fixture },\n });\n writeErrorResponse(\n res,\n 500,\n JSON.stringify({\n error: { message: \"Fixture response is not an audio type\", type: \"server_error\" },\n }),\n );\n return;\n }\n\n journal.add({\n method,\n path,\n headers: flattenHeaders(req.headers),\n body: syntheticReq,\n response: { status: 200, fixture },\n });\n\n const format = response.format ?? \"mp3\";\n const contentType = FORMAT_TO_CONTENT_TYPE[format] ?? \"audio/mpeg\";\n const audioBytes = Buffer.from(response.audio, \"base64\");\n\n res.writeHead(200, { \"Content-Type\": contentType });\n res.end(audioBytes);\n}\n"],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import { Journal } from "./journal.cjs";
2
+ import { Fixture, HandlerDefaults } from "./types.cjs";
3
+ import * as http from "node:http";
4
+
5
+ //#region src/speech.d.ts
6
+ declare function handleSpeech(req: http.IncomingMessage, res: http.ServerResponse, raw: string, fixtures: Fixture[], journal: Journal, defaults: HandlerDefaults, setCorsHeaders: (res: http.ServerResponse) => void): Promise<void>;
7
+ //# sourceMappingURL=speech.d.ts.map
8
+
9
+ //#endregion
10
+ export { handleSpeech };
11
+ //# sourceMappingURL=speech.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"speech.d.cts","names":[],"sources":["../src/speech.ts"],"sourcesContent":[],"mappings":";;;;;iBA2BsB,YAAA,MACf,IAAA,CAAK,sBACL,IAAA,CAAK,uCAEA,oBACD,mBACC,uCACY,IAAA,CAAK,0BAC1B"}
@@ -0,0 +1,11 @@
1
+ import { Journal } from "./journal.js";
2
+ import { Fixture, HandlerDefaults } from "./types.js";
3
+ import * as http from "node:http";
4
+
5
+ //#region src/speech.d.ts
6
+ declare function handleSpeech(req: http.IncomingMessage, res: http.ServerResponse, raw: string, fixtures: Fixture[], journal: Journal, defaults: HandlerDefaults, setCorsHeaders: (res: http.ServerResponse) => void): Promise<void>;
7
+ //# sourceMappingURL=speech.d.ts.map
8
+
9
+ //#endregion
10
+ export { handleSpeech };
11
+ //# sourceMappingURL=speech.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"speech.d.ts","names":[],"sources":["../src/speech.ts"],"sourcesContent":[],"mappings":";;;;;iBA2BsB,YAAA,MACf,IAAA,CAAK,sBACL,IAAA,CAAK,uCAEA,oBACD,mBACC,uCACY,IAAA,CAAK,0BAC1B"}
package/dist/speech.js ADDED
@@ -0,0 +1,144 @@
1
+ import { flattenHeaders, getTestId, isAudioResponse, isErrorResponse } from "./helpers.js";
2
+ import { matchFixture } from "./router.js";
3
+ import { writeErrorResponse } from "./sse-writer.js";
4
+ import { applyChaos } from "./chaos.js";
5
+ import { proxyAndRecord } from "./recorder.js";
6
+
7
+ //#region src/speech.ts
8
+ const FORMAT_TO_CONTENT_TYPE = {
9
+ mp3: "audio/mpeg",
10
+ opus: "audio/opus",
11
+ aac: "audio/aac",
12
+ flac: "audio/flac",
13
+ wav: "audio/wav",
14
+ pcm: "audio/pcm"
15
+ };
16
+ async function handleSpeech(req, res, raw, fixtures, journal, defaults, setCorsHeaders) {
17
+ setCorsHeaders(res);
18
+ const path = req.url ?? "/v1/audio/speech";
19
+ const method = req.method ?? "POST";
20
+ let speechReq;
21
+ try {
22
+ speechReq = JSON.parse(raw);
23
+ } catch {
24
+ journal.add({
25
+ method,
26
+ path,
27
+ headers: flattenHeaders(req.headers),
28
+ body: null,
29
+ response: {
30
+ status: 400,
31
+ fixture: null
32
+ }
33
+ });
34
+ writeErrorResponse(res, 400, JSON.stringify({ error: {
35
+ message: "Malformed JSON",
36
+ type: "invalid_request_error",
37
+ code: "invalid_json"
38
+ } }));
39
+ return;
40
+ }
41
+ const syntheticReq = {
42
+ model: speechReq.model ?? "tts-1",
43
+ messages: [{
44
+ role: "user",
45
+ content: speechReq.input
46
+ }],
47
+ _endpointType: "speech"
48
+ };
49
+ const testId = getTestId(req);
50
+ const fixture = matchFixture(fixtures, syntheticReq, journal.getFixtureMatchCountsForTest(testId), defaults.requestTransform);
51
+ if (fixture) journal.incrementFixtureMatchCount(fixture, fixtures, testId);
52
+ if (applyChaos(res, fixture, defaults.chaos, req.headers, journal, {
53
+ method,
54
+ path,
55
+ headers: flattenHeaders(req.headers),
56
+ body: syntheticReq
57
+ }, defaults.registry, defaults.logger)) return;
58
+ if (!fixture) {
59
+ if (defaults.record) {
60
+ if (await proxyAndRecord(req, res, syntheticReq, "openai", req.url ?? "/v1/audio/speech", fixtures, defaults, raw)) {
61
+ journal.add({
62
+ method,
63
+ path,
64
+ headers: flattenHeaders(req.headers),
65
+ body: syntheticReq,
66
+ response: {
67
+ status: res.statusCode ?? 200,
68
+ fixture: null
69
+ }
70
+ });
71
+ return;
72
+ }
73
+ }
74
+ const strictStatus = defaults.strict ? 503 : 404;
75
+ const strictMessage = defaults.strict ? "Strict mode: no fixture matched" : "No fixture matched";
76
+ journal.add({
77
+ method,
78
+ path,
79
+ headers: flattenHeaders(req.headers),
80
+ body: syntheticReq,
81
+ response: {
82
+ status: strictStatus,
83
+ fixture: null
84
+ }
85
+ });
86
+ writeErrorResponse(res, strictStatus, JSON.stringify({ error: {
87
+ message: strictMessage,
88
+ type: "invalid_request_error",
89
+ code: "no_fixture_match"
90
+ } }));
91
+ return;
92
+ }
93
+ const response = fixture.response;
94
+ if (isErrorResponse(response)) {
95
+ const status = response.status ?? 500;
96
+ journal.add({
97
+ method,
98
+ path,
99
+ headers: flattenHeaders(req.headers),
100
+ body: syntheticReq,
101
+ response: {
102
+ status,
103
+ fixture
104
+ }
105
+ });
106
+ writeErrorResponse(res, status, JSON.stringify(response));
107
+ return;
108
+ }
109
+ if (!isAudioResponse(response)) {
110
+ journal.add({
111
+ method,
112
+ path,
113
+ headers: flattenHeaders(req.headers),
114
+ body: syntheticReq,
115
+ response: {
116
+ status: 500,
117
+ fixture
118
+ }
119
+ });
120
+ writeErrorResponse(res, 500, JSON.stringify({ error: {
121
+ message: "Fixture response is not an audio type",
122
+ type: "server_error"
123
+ } }));
124
+ return;
125
+ }
126
+ journal.add({
127
+ method,
128
+ path,
129
+ headers: flattenHeaders(req.headers),
130
+ body: syntheticReq,
131
+ response: {
132
+ status: 200,
133
+ fixture
134
+ }
135
+ });
136
+ const contentType = FORMAT_TO_CONTENT_TYPE[response.format ?? "mp3"] ?? "audio/mpeg";
137
+ const audioBytes = Buffer.from(response.audio, "base64");
138
+ res.writeHead(200, { "Content-Type": contentType });
139
+ res.end(audioBytes);
140
+ }
141
+
142
+ //#endregion
143
+ export { handleSpeech };
144
+ //# sourceMappingURL=speech.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"speech.js","names":[],"sources":["../src/speech.ts"],"sourcesContent":["import type * as http from \"node:http\";\nimport type { ChatCompletionRequest, Fixture, HandlerDefaults } from \"./types.js\";\nimport { isAudioResponse, isErrorResponse, flattenHeaders, getTestId } from \"./helpers.js\";\nimport { matchFixture } from \"./router.js\";\nimport { writeErrorResponse } from \"./sse-writer.js\";\nimport type { Journal } from \"./journal.js\";\nimport { applyChaos } from \"./chaos.js\";\nimport { proxyAndRecord } from \"./recorder.js\";\n\ninterface SpeechRequest {\n model?: string;\n input: string;\n voice?: string;\n response_format?: string;\n speed?: number;\n [key: string]: unknown;\n}\n\nconst FORMAT_TO_CONTENT_TYPE: Record<string, string> = {\n mp3: \"audio/mpeg\",\n opus: \"audio/opus\",\n aac: \"audio/aac\",\n flac: \"audio/flac\",\n wav: \"audio/wav\",\n pcm: \"audio/pcm\",\n};\n\nexport async function handleSpeech(\n req: http.IncomingMessage,\n res: http.ServerResponse,\n raw: string,\n fixtures: Fixture[],\n journal: Journal,\n defaults: HandlerDefaults,\n setCorsHeaders: (res: http.ServerResponse) => void,\n): Promise<void> {\n setCorsHeaders(res);\n const path = req.url ?? \"/v1/audio/speech\";\n const method = req.method ?? \"POST\";\n\n let speechReq: SpeechRequest;\n try {\n speechReq = JSON.parse(raw) as SpeechRequest;\n } catch {\n journal.add({\n method,\n path,\n headers: flattenHeaders(req.headers),\n body: null,\n response: { status: 400, fixture: null },\n });\n writeErrorResponse(\n res,\n 400,\n JSON.stringify({\n error: { message: \"Malformed JSON\", type: \"invalid_request_error\", code: \"invalid_json\" },\n }),\n );\n return;\n }\n\n const syntheticReq: ChatCompletionRequest = {\n model: speechReq.model ?? \"tts-1\",\n messages: [{ role: \"user\", content: speechReq.input }],\n _endpointType: \"speech\",\n };\n\n const testId = getTestId(req);\n const fixture = matchFixture(\n fixtures,\n syntheticReq,\n journal.getFixtureMatchCountsForTest(testId),\n defaults.requestTransform,\n );\n\n if (fixture) {\n journal.incrementFixtureMatchCount(fixture, fixtures, testId);\n }\n\n if (\n applyChaos(\n res,\n fixture,\n defaults.chaos,\n req.headers,\n journal,\n { method, path, headers: flattenHeaders(req.headers), body: syntheticReq },\n defaults.registry,\n defaults.logger,\n )\n )\n return;\n\n if (!fixture) {\n if (defaults.record) {\n const proxied = await proxyAndRecord(\n req,\n res,\n syntheticReq,\n \"openai\",\n req.url ?? \"/v1/audio/speech\",\n fixtures,\n defaults,\n raw,\n );\n if (proxied) {\n journal.add({\n method,\n path,\n headers: flattenHeaders(req.headers),\n body: syntheticReq,\n response: { status: res.statusCode ?? 200, fixture: null },\n });\n return;\n }\n }\n\n const strictStatus = defaults.strict ? 503 : 404;\n const strictMessage = defaults.strict\n ? \"Strict mode: no fixture matched\"\n : \"No fixture matched\";\n journal.add({\n method,\n path,\n headers: flattenHeaders(req.headers),\n body: syntheticReq,\n response: { status: strictStatus, fixture: null },\n });\n writeErrorResponse(\n res,\n strictStatus,\n JSON.stringify({\n error: { message: strictMessage, type: \"invalid_request_error\", code: \"no_fixture_match\" },\n }),\n );\n return;\n }\n\n const response = fixture.response;\n\n if (isErrorResponse(response)) {\n const status = response.status ?? 500;\n journal.add({\n method,\n path,\n headers: flattenHeaders(req.headers),\n body: syntheticReq,\n response: { status, fixture },\n });\n writeErrorResponse(res, status, JSON.stringify(response));\n return;\n }\n\n if (!isAudioResponse(response)) {\n journal.add({\n method,\n path,\n headers: flattenHeaders(req.headers),\n body: syntheticReq,\n response: { status: 500, fixture },\n });\n writeErrorResponse(\n res,\n 500,\n JSON.stringify({\n error: { message: \"Fixture response is not an audio type\", type: \"server_error\" },\n }),\n );\n return;\n }\n\n journal.add({\n method,\n path,\n headers: flattenHeaders(req.headers),\n body: syntheticReq,\n response: { status: 200, fixture },\n });\n\n const format = response.format ?? \"mp3\";\n const contentType = FORMAT_TO_CONTENT_TYPE[format] ?? \"audio/mpeg\";\n const audioBytes = Buffer.from(response.audio, \"base64\");\n\n res.writeHead(200, { \"Content-Type\": contentType });\n res.end(audioBytes);\n}\n"],"mappings":"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"}
package/dist/suite.cjs CHANGED
@@ -1,6 +1,7 @@
1
1
  const require_a2a_mock = require('./a2a-mock.cjs');
2
2
  const require_llmock = require('./llmock.cjs');
3
3
  const require_mcp_mock = require('./mcp-mock.cjs');
4
+ const require_agui_mock = require('./agui-mock.cjs');
4
5
  const require_vector_mock = require('./vector-mock.cjs');
5
6
 
6
7
  //#region src/suite.ts
@@ -9,6 +10,7 @@ async function createMockSuite(options = {}) {
9
10
  let mcp;
10
11
  let a2a;
11
12
  let vector;
13
+ let agui;
12
14
  if (options.mcp) {
13
15
  mcp = new require_mcp_mock.MCPMock(options.mcp);
14
16
  llm.mount("/mcp", mcp);
@@ -21,11 +23,16 @@ async function createMockSuite(options = {}) {
21
23
  vector = new require_vector_mock.VectorMock(options.vector);
22
24
  llm.mount("/vector", vector);
23
25
  }
26
+ if (options.agui) {
27
+ agui = new require_agui_mock.AGUIMock(options.agui);
28
+ llm.mount("/agui", agui);
29
+ }
24
30
  return {
25
31
  llm,
26
32
  mcp,
27
33
  a2a,
28
34
  vector,
35
+ agui,
29
36
  async start() {
30
37
  await llm.start();
31
38
  },
@@ -37,6 +44,7 @@ async function createMockSuite(options = {}) {
37
44
  if (mcp) mcp.reset();
38
45
  if (a2a) a2a.reset();
39
46
  if (vector) vector.reset();
47
+ if (agui) agui.reset();
40
48
  }
41
49
  };
42
50
  }
@@ -1 +1 @@
1
- {"version":3,"file":"suite.cjs","names":["LLMock","MCPMock","A2AMock","VectorMock"],"sources":["../src/suite.ts"],"sourcesContent":["import { LLMock } from \"./llmock.js\";\nimport { MCPMock } from \"./mcp-mock.js\";\nimport { A2AMock } from \"./a2a-mock.js\";\nimport { VectorMock } from \"./vector-mock.js\";\nimport type { MockServerOptions } from \"./types.js\";\nimport type { MCPMockOptions } from \"./mcp-types.js\";\nimport type { A2AMockOptions } from \"./a2a-types.js\";\nimport type { VectorMockOptions } from \"./vector-types.js\";\n\nexport interface MockSuiteOptions {\n llm?: MockServerOptions;\n mcp?: MCPMockOptions;\n a2a?: A2AMockOptions;\n vector?: VectorMockOptions;\n}\n\nexport interface MockSuite {\n llm: LLMock;\n mcp?: MCPMock;\n a2a?: A2AMock;\n vector?: VectorMock;\n start(): Promise<void>;\n stop(): Promise<void>;\n reset(): void;\n}\n\nexport async function createMockSuite(options: MockSuiteOptions = {}): Promise<MockSuite> {\n const llm = new LLMock(options.llm);\n let mcp: MCPMock | undefined;\n let a2a: A2AMock | undefined;\n let vector: VectorMock | undefined;\n\n if (options.mcp) {\n mcp = new MCPMock(options.mcp);\n llm.mount(\"/mcp\", mcp);\n }\n\n if (options.a2a) {\n a2a = new A2AMock(options.a2a);\n llm.mount(\"/a2a\", a2a);\n }\n\n if (options.vector) {\n vector = new VectorMock(options.vector);\n llm.mount(\"/vector\", vector);\n }\n\n return {\n llm,\n mcp,\n a2a,\n vector,\n async start() {\n await llm.start();\n },\n async stop() {\n await llm.stop();\n },\n reset() {\n llm.reset();\n if (mcp) mcp.reset();\n if (a2a) a2a.reset();\n if (vector) vector.reset();\n },\n };\n}\n"],"mappings":";;;;;;AA0BA,eAAsB,gBAAgB,UAA4B,EAAE,EAAsB;CACxF,MAAM,MAAM,IAAIA,sBAAO,QAAQ,IAAI;CACnC,IAAI;CACJ,IAAI;CACJ,IAAI;AAEJ,KAAI,QAAQ,KAAK;AACf,QAAM,IAAIC,yBAAQ,QAAQ,IAAI;AAC9B,MAAI,MAAM,QAAQ,IAAI;;AAGxB,KAAI,QAAQ,KAAK;AACf,QAAM,IAAIC,yBAAQ,QAAQ,IAAI;AAC9B,MAAI,MAAM,QAAQ,IAAI;;AAGxB,KAAI,QAAQ,QAAQ;AAClB,WAAS,IAAIC,+BAAW,QAAQ,OAAO;AACvC,MAAI,MAAM,WAAW,OAAO;;AAG9B,QAAO;EACL;EACA;EACA;EACA;EACA,MAAM,QAAQ;AACZ,SAAM,IAAI,OAAO;;EAEnB,MAAM,OAAO;AACX,SAAM,IAAI,MAAM;;EAElB,QAAQ;AACN,OAAI,OAAO;AACX,OAAI,IAAK,KAAI,OAAO;AACpB,OAAI,IAAK,KAAI,OAAO;AACpB,OAAI,OAAQ,QAAO,OAAO;;EAE7B"}
1
+ {"version":3,"file":"suite.cjs","names":["LLMock","MCPMock","A2AMock","VectorMock","AGUIMock"],"sources":["../src/suite.ts"],"sourcesContent":["import { LLMock } from \"./llmock.js\";\nimport { MCPMock } from \"./mcp-mock.js\";\nimport { A2AMock } from \"./a2a-mock.js\";\nimport { VectorMock } from \"./vector-mock.js\";\nimport { AGUIMock } from \"./agui-mock.js\";\nimport type { MockServerOptions } from \"./types.js\";\nimport type { MCPMockOptions } from \"./mcp-types.js\";\nimport type { A2AMockOptions } from \"./a2a-types.js\";\nimport type { VectorMockOptions } from \"./vector-types.js\";\nimport type { AGUIMockOptions } from \"./agui-types.js\";\n\nexport interface MockSuiteOptions {\n llm?: MockServerOptions;\n mcp?: MCPMockOptions;\n a2a?: A2AMockOptions;\n vector?: VectorMockOptions;\n agui?: AGUIMockOptions;\n}\n\nexport interface MockSuite {\n llm: LLMock;\n mcp?: MCPMock;\n a2a?: A2AMock;\n vector?: VectorMock;\n agui?: AGUIMock;\n start(): Promise<void>;\n stop(): Promise<void>;\n reset(): void;\n}\n\nexport async function createMockSuite(options: MockSuiteOptions = {}): Promise<MockSuite> {\n const llm = new LLMock(options.llm);\n let mcp: MCPMock | undefined;\n let a2a: A2AMock | undefined;\n let vector: VectorMock | undefined;\n let agui: AGUIMock | undefined;\n\n if (options.mcp) {\n mcp = new MCPMock(options.mcp);\n llm.mount(\"/mcp\", mcp);\n }\n\n if (options.a2a) {\n a2a = new A2AMock(options.a2a);\n llm.mount(\"/a2a\", a2a);\n }\n\n if (options.vector) {\n vector = new VectorMock(options.vector);\n llm.mount(\"/vector\", vector);\n }\n\n if (options.agui) {\n agui = new AGUIMock(options.agui);\n llm.mount(\"/agui\", agui);\n }\n\n return {\n llm,\n mcp,\n a2a,\n vector,\n agui,\n async start() {\n await llm.start();\n },\n async stop() {\n await llm.stop();\n },\n reset() {\n llm.reset();\n if (mcp) mcp.reset();\n if (a2a) a2a.reset();\n if (vector) vector.reset();\n if (agui) agui.reset();\n },\n };\n}\n"],"mappings":";;;;;;;AA8BA,eAAsB,gBAAgB,UAA4B,EAAE,EAAsB;CACxF,MAAM,MAAM,IAAIA,sBAAO,QAAQ,IAAI;CACnC,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;AAEJ,KAAI,QAAQ,KAAK;AACf,QAAM,IAAIC,yBAAQ,QAAQ,IAAI;AAC9B,MAAI,MAAM,QAAQ,IAAI;;AAGxB,KAAI,QAAQ,KAAK;AACf,QAAM,IAAIC,yBAAQ,QAAQ,IAAI;AAC9B,MAAI,MAAM,QAAQ,IAAI;;AAGxB,KAAI,QAAQ,QAAQ;AAClB,WAAS,IAAIC,+BAAW,QAAQ,OAAO;AACvC,MAAI,MAAM,WAAW,OAAO;;AAG9B,KAAI,QAAQ,MAAM;AAChB,SAAO,IAAIC,2BAAS,QAAQ,KAAK;AACjC,MAAI,MAAM,SAAS,KAAK;;AAG1B,QAAO;EACL;EACA;EACA;EACA;EACA;EACA,MAAM,QAAQ;AACZ,SAAM,IAAI,OAAO;;EAEnB,MAAM,OAAO;AACX,SAAM,IAAI,MAAM;;EAElB,QAAQ;AACN,OAAI,OAAO;AACX,OAAI,IAAK,KAAI,OAAO;AACpB,OAAI,IAAK,KAAI,OAAO;AACpB,OAAI,OAAQ,QAAO,OAAO;AAC1B,OAAI,KAAM,MAAK,OAAO;;EAEzB"}
package/dist/suite.d.cts CHANGED
@@ -3,9 +3,11 @@ import { A2AMockOptions } from "./a2a-types.cjs";
3
3
  import { A2AMock } from "./a2a-mock.cjs";
4
4
  import { LLMock } from "./llmock.cjs";
5
5
  import { MCPMockOptions } from "./mcp-types.cjs";
6
+ import { AGUIMockOptions } from "./agui-types.cjs";
6
7
  import { VectorMockOptions } from "./vector-types.cjs";
7
8
  import { MCPMock } from "./mcp-mock.cjs";
8
9
  import { VectorMock } from "./vector-mock.cjs";
10
+ import { AGUIMock } from "./agui-mock.cjs";
9
11
 
10
12
  //#region src/suite.d.ts
11
13
  interface MockSuiteOptions {
@@ -13,12 +15,14 @@ interface MockSuiteOptions {
13
15
  mcp?: MCPMockOptions;
14
16
  a2a?: A2AMockOptions;
15
17
  vector?: VectorMockOptions;
18
+ agui?: AGUIMockOptions;
16
19
  }
17
20
  interface MockSuite {
18
21
  llm: LLMock;
19
22
  mcp?: MCPMock;
20
23
  a2a?: A2AMock;
21
24
  vector?: VectorMock;
25
+ agui?: AGUIMock;
22
26
  start(): Promise<void>;
23
27
  stop(): Promise<void>;
24
28
  reset(): void;
@@ -1 +1 @@
1
- {"version":3,"file":"suite.d.cts","names":[],"sources":["../src/suite.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;UASiB,gBAAA;QACT;EADS,GAAA,CAAA,EAET,cAFyB;EAAA,GAAA,CAAA,EAGzB,cAHyB;QACzB,CAAA,EAGG,iBAHH;;AAEA,UAIS,SAAA,CAJT;KACG,EAIJ,MAJI;EAAiB,GAAA,CAAA,EAKpB,OALoB;EAGX,GAAA,CAAA,EAGT,OAHkB;EAAA,MAAA,CAAA,EAIf,UAJe;OACnB,EAAA,EAII,OAJJ,CAAA,IAAA,CAAA;MACC,EAAA,EAIE,OAJF,CAAA,IAAA,CAAA;OACA,EAAA,EAAA,IAAA;;AAEG,iBAKW,eAAA,CALX,OAAA,CAAA,EAKoC,gBALpC,CAAA,EAK4D,OAL5D,CAKoE,SALpE,CAAA"}
1
+ {"version":3,"file":"suite.d.cts","names":[],"sources":["../src/suite.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;;;UAWiB,gBAAA;QACT;EADS,GAAA,CAAA,EAET,cAFyB;EAAA,GAAA,CAAA,EAGzB,cAHyB;QACzB,CAAA,EAGG,iBAHH;MACA,CAAA,EAGC,eAHD;;AAEG,UAIM,SAAA,CAJN;KACF,EAIF,MAJE;EAAe,GAAA,CAAA,EAKhB,OALgB;EAGP,GAAA,CAAA,EAGT,OAHkB;EAAA,MAAA,CAAA,EAIf,UAJe;MACnB,CAAA,EAIE,QAJF;OACC,EAAA,EAIG,OAJH,CAAA,IAAA,CAAA;MACA,EAAA,EAIE,OAJF,CAAA,IAAA,CAAA;OACG,EAAA,EAAA,IAAA;;AAEA,iBAKW,eAAA,CALX,OAAA,CAAA,EAKoC,gBALpC,CAAA,EAK4D,OAL5D,CAKoE,SALpE,CAAA"}
package/dist/suite.d.ts CHANGED
@@ -3,9 +3,11 @@ import { A2AMockOptions } from "./a2a-types.js";
3
3
  import { A2AMock } from "./a2a-mock.js";
4
4
  import { LLMock } from "./llmock.js";
5
5
  import { MCPMockOptions } from "./mcp-types.js";
6
+ import { AGUIMockOptions } from "./agui-types.js";
6
7
  import { VectorMockOptions } from "./vector-types.js";
7
8
  import { MCPMock } from "./mcp-mock.js";
8
9
  import { VectorMock } from "./vector-mock.js";
10
+ import { AGUIMock } from "./agui-mock.js";
9
11
 
10
12
  //#region src/suite.d.ts
11
13
  interface MockSuiteOptions {
@@ -13,12 +15,14 @@ interface MockSuiteOptions {
13
15
  mcp?: MCPMockOptions;
14
16
  a2a?: A2AMockOptions;
15
17
  vector?: VectorMockOptions;
18
+ agui?: AGUIMockOptions;
16
19
  }
17
20
  interface MockSuite {
18
21
  llm: LLMock;
19
22
  mcp?: MCPMock;
20
23
  a2a?: A2AMock;
21
24
  vector?: VectorMock;
25
+ agui?: AGUIMock;
22
26
  start(): Promise<void>;
23
27
  stop(): Promise<void>;
24
28
  reset(): void;
@@ -1 +1 @@
1
- {"version":3,"file":"suite.d.ts","names":[],"sources":["../src/suite.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;UASiB,gBAAA;QACT;EADS,GAAA,CAAA,EAET,cAFyB;EAAA,GAAA,CAAA,EAGzB,cAHyB;QACzB,CAAA,EAGG,iBAHH;;AAEA,UAIS,SAAA,CAJT;KACG,EAIJ,MAJI;EAAiB,GAAA,CAAA,EAKpB,OALoB;EAGX,GAAA,CAAA,EAGT,OAHkB;EAAA,MAAA,CAAA,EAIf,UAJe;OACnB,EAAA,EAII,OAJJ,CAAA,IAAA,CAAA;MACC,EAAA,EAIE,OAJF,CAAA,IAAA,CAAA;OACA,EAAA,EAAA,IAAA;;AAEG,iBAKW,eAAA,CALX,OAAA,CAAA,EAKoC,gBALpC,CAAA,EAK4D,OAL5D,CAKoE,SALpE,CAAA"}
1
+ {"version":3,"file":"suite.d.ts","names":[],"sources":["../src/suite.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;;;UAWiB,gBAAA;QACT;EADS,GAAA,CAAA,EAET,cAFyB;EAAA,GAAA,CAAA,EAGzB,cAHyB;QACzB,CAAA,EAGG,iBAHH;MACA,CAAA,EAGC,eAHD;;AAEG,UAIM,SAAA,CAJN;KACF,EAIF,MAJE;EAAe,GAAA,CAAA,EAKhB,OALgB;EAGP,GAAA,CAAA,EAGT,OAHkB;EAAA,MAAA,CAAA,EAIf,UAJe;MACnB,CAAA,EAIE,QAJF;OACC,EAAA,EAIG,OAJH,CAAA,IAAA,CAAA;MACA,EAAA,EAIE,OAJF,CAAA,IAAA,CAAA;OACG,EAAA,EAAA,IAAA;;AAEA,iBAKW,eAAA,CALX,OAAA,CAAA,EAKoC,gBALpC,CAAA,EAK4D,OAL5D,CAKoE,SALpE,CAAA"}
package/dist/suite.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import { A2AMock } from "./a2a-mock.js";
2
2
  import { LLMock } from "./llmock.js";
3
3
  import { MCPMock } from "./mcp-mock.js";
4
+ import { AGUIMock } from "./agui-mock.js";
4
5
  import { VectorMock } from "./vector-mock.js";
5
6
 
6
7
  //#region src/suite.ts
@@ -9,6 +10,7 @@ async function createMockSuite(options = {}) {
9
10
  let mcp;
10
11
  let a2a;
11
12
  let vector;
13
+ let agui;
12
14
  if (options.mcp) {
13
15
  mcp = new MCPMock(options.mcp);
14
16
  llm.mount("/mcp", mcp);
@@ -21,11 +23,16 @@ async function createMockSuite(options = {}) {
21
23
  vector = new VectorMock(options.vector);
22
24
  llm.mount("/vector", vector);
23
25
  }
26
+ if (options.agui) {
27
+ agui = new AGUIMock(options.agui);
28
+ llm.mount("/agui", agui);
29
+ }
24
30
  return {
25
31
  llm,
26
32
  mcp,
27
33
  a2a,
28
34
  vector,
35
+ agui,
29
36
  async start() {
30
37
  await llm.start();
31
38
  },
@@ -37,6 +44,7 @@ async function createMockSuite(options = {}) {
37
44
  if (mcp) mcp.reset();
38
45
  if (a2a) a2a.reset();
39
46
  if (vector) vector.reset();
47
+ if (agui) agui.reset();
40
48
  }
41
49
  };
42
50
  }
package/dist/suite.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"suite.js","names":[],"sources":["../src/suite.ts"],"sourcesContent":["import { LLMock } from \"./llmock.js\";\nimport { MCPMock } from \"./mcp-mock.js\";\nimport { A2AMock } from \"./a2a-mock.js\";\nimport { VectorMock } from \"./vector-mock.js\";\nimport type { MockServerOptions } from \"./types.js\";\nimport type { MCPMockOptions } from \"./mcp-types.js\";\nimport type { A2AMockOptions } from \"./a2a-types.js\";\nimport type { VectorMockOptions } from \"./vector-types.js\";\n\nexport interface MockSuiteOptions {\n llm?: MockServerOptions;\n mcp?: MCPMockOptions;\n a2a?: A2AMockOptions;\n vector?: VectorMockOptions;\n}\n\nexport interface MockSuite {\n llm: LLMock;\n mcp?: MCPMock;\n a2a?: A2AMock;\n vector?: VectorMock;\n start(): Promise<void>;\n stop(): Promise<void>;\n reset(): void;\n}\n\nexport async function createMockSuite(options: MockSuiteOptions = {}): Promise<MockSuite> {\n const llm = new LLMock(options.llm);\n let mcp: MCPMock | undefined;\n let a2a: A2AMock | undefined;\n let vector: VectorMock | undefined;\n\n if (options.mcp) {\n mcp = new MCPMock(options.mcp);\n llm.mount(\"/mcp\", mcp);\n }\n\n if (options.a2a) {\n a2a = new A2AMock(options.a2a);\n llm.mount(\"/a2a\", a2a);\n }\n\n if (options.vector) {\n vector = new VectorMock(options.vector);\n llm.mount(\"/vector\", vector);\n }\n\n return {\n llm,\n mcp,\n a2a,\n vector,\n async start() {\n await llm.start();\n },\n async stop() {\n await llm.stop();\n },\n reset() {\n llm.reset();\n if (mcp) mcp.reset();\n if (a2a) a2a.reset();\n if (vector) vector.reset();\n },\n };\n}\n"],"mappings":";;;;;;AA0BA,eAAsB,gBAAgB,UAA4B,EAAE,EAAsB;CACxF,MAAM,MAAM,IAAI,OAAO,QAAQ,IAAI;CACnC,IAAI;CACJ,IAAI;CACJ,IAAI;AAEJ,KAAI,QAAQ,KAAK;AACf,QAAM,IAAI,QAAQ,QAAQ,IAAI;AAC9B,MAAI,MAAM,QAAQ,IAAI;;AAGxB,KAAI,QAAQ,KAAK;AACf,QAAM,IAAI,QAAQ,QAAQ,IAAI;AAC9B,MAAI,MAAM,QAAQ,IAAI;;AAGxB,KAAI,QAAQ,QAAQ;AAClB,WAAS,IAAI,WAAW,QAAQ,OAAO;AACvC,MAAI,MAAM,WAAW,OAAO;;AAG9B,QAAO;EACL;EACA;EACA;EACA;EACA,MAAM,QAAQ;AACZ,SAAM,IAAI,OAAO;;EAEnB,MAAM,OAAO;AACX,SAAM,IAAI,MAAM;;EAElB,QAAQ;AACN,OAAI,OAAO;AACX,OAAI,IAAK,KAAI,OAAO;AACpB,OAAI,IAAK,KAAI,OAAO;AACpB,OAAI,OAAQ,QAAO,OAAO;;EAE7B"}
1
+ {"version":3,"file":"suite.js","names":[],"sources":["../src/suite.ts"],"sourcesContent":["import { LLMock } from \"./llmock.js\";\nimport { MCPMock } from \"./mcp-mock.js\";\nimport { A2AMock } from \"./a2a-mock.js\";\nimport { VectorMock } from \"./vector-mock.js\";\nimport { AGUIMock } from \"./agui-mock.js\";\nimport type { MockServerOptions } from \"./types.js\";\nimport type { MCPMockOptions } from \"./mcp-types.js\";\nimport type { A2AMockOptions } from \"./a2a-types.js\";\nimport type { VectorMockOptions } from \"./vector-types.js\";\nimport type { AGUIMockOptions } from \"./agui-types.js\";\n\nexport interface MockSuiteOptions {\n llm?: MockServerOptions;\n mcp?: MCPMockOptions;\n a2a?: A2AMockOptions;\n vector?: VectorMockOptions;\n agui?: AGUIMockOptions;\n}\n\nexport interface MockSuite {\n llm: LLMock;\n mcp?: MCPMock;\n a2a?: A2AMock;\n vector?: VectorMock;\n agui?: AGUIMock;\n start(): Promise<void>;\n stop(): Promise<void>;\n reset(): void;\n}\n\nexport async function createMockSuite(options: MockSuiteOptions = {}): Promise<MockSuite> {\n const llm = new LLMock(options.llm);\n let mcp: MCPMock | undefined;\n let a2a: A2AMock | undefined;\n let vector: VectorMock | undefined;\n let agui: AGUIMock | undefined;\n\n if (options.mcp) {\n mcp = new MCPMock(options.mcp);\n llm.mount(\"/mcp\", mcp);\n }\n\n if (options.a2a) {\n a2a = new A2AMock(options.a2a);\n llm.mount(\"/a2a\", a2a);\n }\n\n if (options.vector) {\n vector = new VectorMock(options.vector);\n llm.mount(\"/vector\", vector);\n }\n\n if (options.agui) {\n agui = new AGUIMock(options.agui);\n llm.mount(\"/agui\", agui);\n }\n\n return {\n llm,\n mcp,\n a2a,\n vector,\n agui,\n async start() {\n await llm.start();\n },\n async stop() {\n await llm.stop();\n },\n reset() {\n llm.reset();\n if (mcp) mcp.reset();\n if (a2a) a2a.reset();\n if (vector) vector.reset();\n if (agui) agui.reset();\n },\n };\n}\n"],"mappings":";;;;;;;AA8BA,eAAsB,gBAAgB,UAA4B,EAAE,EAAsB;CACxF,MAAM,MAAM,IAAI,OAAO,QAAQ,IAAI;CACnC,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;AAEJ,KAAI,QAAQ,KAAK;AACf,QAAM,IAAI,QAAQ,QAAQ,IAAI;AAC9B,MAAI,MAAM,QAAQ,IAAI;;AAGxB,KAAI,QAAQ,KAAK;AACf,QAAM,IAAI,QAAQ,QAAQ,IAAI;AAC9B,MAAI,MAAM,QAAQ,IAAI;;AAGxB,KAAI,QAAQ,QAAQ;AAClB,WAAS,IAAI,WAAW,QAAQ,OAAO;AACvC,MAAI,MAAM,WAAW,OAAO;;AAG9B,KAAI,QAAQ,MAAM;AAChB,SAAO,IAAI,SAAS,QAAQ,KAAK;AACjC,MAAI,MAAM,SAAS,KAAK;;AAG1B,QAAO;EACL;EACA;EACA;EACA;EACA;EACA,MAAM,QAAQ;AACZ,SAAM,IAAI,OAAO;;EAEnB,MAAM,OAAO;AACX,SAAM,IAAI,MAAM;;EAElB,QAAQ;AACN,OAAI,OAAO;AACX,OAAI,IAAK,KAAI,OAAO;AACpB,OAAI,IAAK,KAAI,OAAO;AACpB,OAAI,OAAQ,QAAO,OAAO;AAC1B,OAAI,KAAM,MAAK,OAAO;;EAEzB"}
@@ -0,0 +1,134 @@
1
+ const require_helpers = require('./helpers.cjs');
2
+ const require_router = require('./router.cjs');
3
+ const require_sse_writer = require('./sse-writer.cjs');
4
+ const require_chaos = require('./chaos.cjs');
5
+ const require_recorder = require('./recorder.cjs');
6
+
7
+ //#region src/transcription.ts
8
+ /**
9
+ * Extract a named field value from a multipart/form-data body.
10
+ * Lightweight parser — scans for Content-Disposition headers
11
+ * to find simple string field values.
12
+ */
13
+ function extractFormField(raw, fieldName) {
14
+ const pattern = new RegExp(`Content-Disposition:\\s*form-data;[^\\r\\n]*name="${fieldName}"[^\\r\\n]*\\r\\n\\r\\n([^\\r\\n]*)`, "i");
15
+ return raw.match(pattern)?.[1];
16
+ }
17
+ async function handleTranscription(req, res, raw, fixtures, journal, defaults, setCorsHeaders) {
18
+ setCorsHeaders(res);
19
+ const path = req.url ?? "/v1/audio/transcriptions";
20
+ const method = req.method ?? "POST";
21
+ const model = extractFormField(raw, "model") ?? "whisper-1";
22
+ const responseFormat = extractFormField(raw, "response_format") ?? "json";
23
+ const syntheticReq = {
24
+ model,
25
+ messages: [],
26
+ _endpointType: "transcription"
27
+ };
28
+ const testId = require_helpers.getTestId(req);
29
+ const fixture = require_router.matchFixture(fixtures, syntheticReq, journal.getFixtureMatchCountsForTest(testId), defaults.requestTransform);
30
+ if (fixture) journal.incrementFixtureMatchCount(fixture, fixtures, testId);
31
+ if (require_chaos.applyChaos(res, fixture, defaults.chaos, req.headers, journal, {
32
+ method,
33
+ path,
34
+ headers: require_helpers.flattenHeaders(req.headers),
35
+ body: syntheticReq
36
+ }, defaults.registry, defaults.logger)) return;
37
+ if (!fixture) {
38
+ if (defaults.record) {
39
+ if (await require_recorder.proxyAndRecord(req, res, syntheticReq, "openai", req.url ?? "/v1/audio/transcriptions", fixtures, defaults, raw)) {
40
+ journal.add({
41
+ method,
42
+ path,
43
+ headers: require_helpers.flattenHeaders(req.headers),
44
+ body: syntheticReq,
45
+ response: {
46
+ status: res.statusCode ?? 200,
47
+ fixture: null
48
+ }
49
+ });
50
+ return;
51
+ }
52
+ }
53
+ const strictStatus = defaults.strict ? 503 : 404;
54
+ const strictMessage = defaults.strict ? "Strict mode: no fixture matched" : "No fixture matched";
55
+ journal.add({
56
+ method,
57
+ path,
58
+ headers: require_helpers.flattenHeaders(req.headers),
59
+ body: syntheticReq,
60
+ response: {
61
+ status: strictStatus,
62
+ fixture: null
63
+ }
64
+ });
65
+ require_sse_writer.writeErrorResponse(res, strictStatus, JSON.stringify({ error: {
66
+ message: strictMessage,
67
+ type: "invalid_request_error",
68
+ code: "no_fixture_match"
69
+ } }));
70
+ return;
71
+ }
72
+ const response = fixture.response;
73
+ if (require_helpers.isErrorResponse(response)) {
74
+ const status = response.status ?? 500;
75
+ journal.add({
76
+ method,
77
+ path,
78
+ headers: require_helpers.flattenHeaders(req.headers),
79
+ body: syntheticReq,
80
+ response: {
81
+ status,
82
+ fixture
83
+ }
84
+ });
85
+ require_sse_writer.writeErrorResponse(res, status, JSON.stringify(response));
86
+ return;
87
+ }
88
+ if (!require_helpers.isTranscriptionResponse(response)) {
89
+ journal.add({
90
+ method,
91
+ path,
92
+ headers: require_helpers.flattenHeaders(req.headers),
93
+ body: syntheticReq,
94
+ response: {
95
+ status: 500,
96
+ fixture
97
+ }
98
+ });
99
+ require_sse_writer.writeErrorResponse(res, 500, JSON.stringify({ error: {
100
+ message: "Fixture response is not a transcription type",
101
+ type: "server_error"
102
+ } }));
103
+ return;
104
+ }
105
+ journal.add({
106
+ method,
107
+ path,
108
+ headers: require_helpers.flattenHeaders(req.headers),
109
+ body: syntheticReq,
110
+ response: {
111
+ status: 200,
112
+ fixture
113
+ }
114
+ });
115
+ const t = response.transcription;
116
+ if (responseFormat === "verbose_json" || t.words != null || t.segments != null) {
117
+ res.writeHead(200, { "Content-Type": "application/json" });
118
+ res.end(JSON.stringify({
119
+ task: "transcribe",
120
+ language: t.language ?? "english",
121
+ duration: t.duration ?? 0,
122
+ text: t.text,
123
+ words: t.words ?? [],
124
+ segments: t.segments ?? []
125
+ }));
126
+ } else {
127
+ res.writeHead(200, { "Content-Type": "application/json" });
128
+ res.end(JSON.stringify({ text: t.text }));
129
+ }
130
+ }
131
+
132
+ //#endregion
133
+ exports.handleTranscription = handleTranscription;
134
+ //# sourceMappingURL=transcription.cjs.map