llm-mock-server 1.0.5 → 1.0.7

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 (251) hide show
  1. package/README.md +1 -1
  2. package/dist/cli/cli.d.ts +3 -0
  3. package/dist/cli/cli.d.ts.map +1 -0
  4. package/dist/cli/cli.js +103 -0
  5. package/dist/cli/cli.js.map +1 -0
  6. package/dist/cli/validators.d.ts +7 -0
  7. package/dist/cli/validators.d.ts.map +1 -0
  8. package/dist/cli/validators.js +53 -0
  9. package/dist/cli/validators.js.map +1 -0
  10. package/dist/formats/anthropic/index.d.ts +1 -1
  11. package/dist/formats/anthropic/index.d.ts.map +1 -1
  12. package/dist/formats/anthropic/index.js +1 -1
  13. package/dist/formats/anthropic/index.js.map +1 -1
  14. package/dist/formats/anthropic/parse.d.ts +2 -2
  15. package/dist/formats/anthropic/parse.d.ts.map +1 -1
  16. package/dist/formats/anthropic/parse.js +4 -2
  17. package/dist/formats/anthropic/parse.js.map +1 -1
  18. package/dist/formats/anthropic/schema.d.ts +1 -1
  19. package/dist/formats/anthropic/schema.d.ts.map +1 -1
  20. package/dist/formats/anthropic/schema.js +9 -4
  21. package/dist/formats/anthropic/schema.js.map +1 -1
  22. package/dist/formats/anthropic/serialize.d.ts +2 -2
  23. package/dist/formats/anthropic/serialize.d.ts.map +1 -1
  24. package/dist/formats/anthropic/serialize.js +76 -19
  25. package/dist/formats/anthropic/serialize.js.map +1 -1
  26. package/dist/formats/openai/chat-completions/index.d.ts +3 -0
  27. package/dist/formats/openai/chat-completions/index.d.ts.map +1 -0
  28. package/dist/formats/openai/chat-completions/index.js +13 -0
  29. package/dist/formats/openai/chat-completions/index.js.map +1 -0
  30. package/dist/formats/openai/chat-completions/parse.d.ts +4 -0
  31. package/dist/formats/openai/chat-completions/parse.d.ts.map +1 -0
  32. package/dist/formats/openai/chat-completions/parse.js +33 -0
  33. package/dist/formats/openai/chat-completions/parse.js.map +1 -0
  34. package/dist/formats/openai/chat-completions/schema.d.ts +93 -0
  35. package/dist/formats/openai/chat-completions/schema.d.ts.map +1 -0
  36. package/dist/formats/openai/chat-completions/schema.js +74 -0
  37. package/dist/formats/openai/chat-completions/schema.js.map +1 -0
  38. package/dist/formats/openai/chat-completions/serialize.d.ts +10 -0
  39. package/dist/formats/openai/chat-completions/serialize.d.ts.map +1 -0
  40. package/dist/formats/openai/chat-completions/serialize.js +99 -0
  41. package/dist/formats/openai/chat-completions/serialize.js.map +1 -0
  42. package/dist/formats/openai/responses/index.d.ts +3 -0
  43. package/dist/formats/openai/responses/index.d.ts.map +1 -0
  44. package/dist/formats/openai/responses/index.js +13 -0
  45. package/dist/formats/openai/responses/index.js.map +1 -0
  46. package/dist/formats/openai/responses/parse.d.ts +4 -0
  47. package/dist/formats/openai/responses/parse.d.ts.map +1 -0
  48. package/dist/formats/openai/responses/parse.js +51 -0
  49. package/dist/formats/openai/responses/parse.js.map +1 -0
  50. package/dist/formats/openai/responses/schema.d.ts +103 -0
  51. package/dist/formats/openai/responses/schema.d.ts.map +1 -0
  52. package/dist/formats/openai/responses/schema.js +71 -0
  53. package/dist/formats/openai/responses/schema.js.map +1 -0
  54. package/dist/formats/openai/responses/serialize.d.ts +10 -0
  55. package/dist/formats/openai/responses/serialize.d.ts.map +1 -0
  56. package/dist/formats/openai/responses/serialize.js +273 -0
  57. package/dist/formats/openai/responses/serialize.js.map +1 -0
  58. package/dist/formats/request-helpers.d.ts +1 -1
  59. package/dist/formats/request-helpers.d.ts.map +1 -1
  60. package/dist/formats/request-helpers.js.map +1 -1
  61. package/dist/formats/serialize-helpers.d.ts +1 -1
  62. package/dist/formats/serialize-helpers.d.ts.map +1 -1
  63. package/dist/formats/serialize-helpers.js +6 -3
  64. package/dist/formats/serialize-helpers.js.map +1 -1
  65. package/dist/formats/types.d.ts +2 -1
  66. package/dist/formats/types.d.ts.map +1 -1
  67. package/dist/history.d.ts +6 -2
  68. package/dist/history.d.ts.map +1 -1
  69. package/dist/history.js +2 -0
  70. package/dist/history.js.map +1 -1
  71. package/dist/index.d.ts.map +1 -1
  72. package/dist/index.js.map +1 -1
  73. package/dist/loader.d.ts +1 -1
  74. package/dist/loader.d.ts.map +1 -1
  75. package/dist/loader.js +26 -9
  76. package/dist/loader.js.map +1 -1
  77. package/dist/logger.d.ts.map +1 -1
  78. package/dist/logger.js +12 -4
  79. package/dist/logger.js.map +1 -1
  80. package/dist/mock-server.d.ts +44 -48
  81. package/dist/mock-server.d.ts.map +1 -1
  82. package/dist/mock-server.js +37 -85
  83. package/dist/mock-server.js.map +1 -1
  84. package/dist/route-handler.d.ts +1 -1
  85. package/dist/route-handler.d.ts.map +1 -1
  86. package/dist/route-handler.js +19 -7
  87. package/dist/route-handler.js.map +1 -1
  88. package/dist/rule-builder.d.ts +21 -0
  89. package/dist/rule-builder.d.ts.map +1 -0
  90. package/dist/rule-builder.js +58 -0
  91. package/dist/rule-builder.js.map +1 -0
  92. package/dist/rule-engine.d.ts +3 -1
  93. package/dist/rule-engine.d.ts.map +1 -1
  94. package/dist/rule-engine.js +7 -2
  95. package/dist/rule-engine.js.map +1 -1
  96. package/dist/sse-writer.d.ts +1 -1
  97. package/dist/sse-writer.d.ts.map +1 -1
  98. package/dist/types/reply.d.ts +51 -8
  99. package/dist/types/reply.d.ts.map +1 -1
  100. package/dist/types/request.d.ts +21 -6
  101. package/dist/types/request.d.ts.map +1 -1
  102. package/dist/types/rule.d.ts +65 -7
  103. package/dist/types/rule.d.ts.map +1 -1
  104. package/dist/types.d.ts +3 -3
  105. package/dist/types.d.ts.map +1 -1
  106. package/package.json +20 -11
  107. package/.claude/skills/desloppify/SKILL.md +0 -308
  108. package/.desloppify/external_review_sessions/ext_20260315_000339_a6cdc3e6/canonical_import_20260315_000801.json +0 -242
  109. package/.desloppify/external_review_sessions/ext_20260315_000339_a6cdc3e6/canonical_import_20260315_000905.json +0 -248
  110. package/.desloppify/external_review_sessions/ext_20260315_000339_a6cdc3e6/canonical_import_20260315_000917.json +0 -248
  111. package/.desloppify/external_review_sessions/ext_20260315_000339_a6cdc3e6/canonical_import_20260315_000950.json +0 -311
  112. package/.desloppify/external_review_sessions/ext_20260315_000339_a6cdc3e6/claude_launch_prompt.md +0 -17
  113. package/.desloppify/external_review_sessions/ext_20260315_000339_a6cdc3e6/review_result.json +0 -255
  114. package/.desloppify/external_review_sessions/ext_20260315_000339_a6cdc3e6/review_result.template.json +0 -22
  115. package/.desloppify/external_review_sessions/ext_20260315_000339_a6cdc3e6/reviewer_instructions.md +0 -20
  116. package/.desloppify/external_review_sessions/ext_20260315_000339_a6cdc3e6/session.json +0 -20
  117. package/.desloppify/external_review_sessions/ext_20260315_045546_0587ea3b/canonical_import_20260315_050000.json +0 -286
  118. package/.desloppify/external_review_sessions/ext_20260315_045546_0587ea3b/canonical_import_20260315_050028.json +0 -303
  119. package/.desloppify/external_review_sessions/ext_20260315_045546_0587ea3b/claude_launch_prompt.md +0 -17
  120. package/.desloppify/external_review_sessions/ext_20260315_045546_0587ea3b/review_result.json +0 -297
  121. package/.desloppify/external_review_sessions/ext_20260315_045546_0587ea3b/review_result.template.json +0 -22
  122. package/.desloppify/external_review_sessions/ext_20260315_045546_0587ea3b/reviewer_instructions.md +0 -20
  123. package/.desloppify/external_review_sessions/ext_20260315_045546_0587ea3b/session.json +0 -20
  124. package/.desloppify/query.json +0 -1312
  125. package/.desloppify/review_packet_blind.json +0 -1249
  126. package/.desloppify/review_packets/holistic_packet_20260315_000339.json +0 -1471
  127. package/.desloppify/review_packets/holistic_packet_20260315_045546.json +0 -1480
  128. package/.desloppify/review_packets/holistic_packet_20260315_185401.json +0 -1407
  129. package/.desloppify/review_packets/holistic_packet_20260315_185613.json +0 -1407
  130. package/.desloppify/state-typescript.json +0 -8438
  131. package/.desloppify/state-typescript.json.bak +0 -8432
  132. package/.desloppify/subagents/runs/20260315_185401/logs/batch-1.log +0 -384
  133. package/.desloppify/subagents/runs/20260315_185401/logs/batch-10.log +0 -484
  134. package/.desloppify/subagents/runs/20260315_185401/logs/batch-2.log +0 -408
  135. package/.desloppify/subagents/runs/20260315_185401/logs/batch-3.log +0 -416
  136. package/.desloppify/subagents/runs/20260315_185401/logs/batch-4.log +0 -360
  137. package/.desloppify/subagents/runs/20260315_185401/logs/batch-5.log +0 -360
  138. package/.desloppify/subagents/runs/20260315_185401/logs/batch-6.log +0 -364
  139. package/.desloppify/subagents/runs/20260315_185401/logs/batch-7.log +0 -428
  140. package/.desloppify/subagents/runs/20260315_185401/logs/batch-8.log +0 -388
  141. package/.desloppify/subagents/runs/20260315_185401/logs/batch-9.log +0 -500
  142. package/.desloppify/subagents/runs/20260315_185401/prompts/batch-1.md +0 -83
  143. package/.desloppify/subagents/runs/20260315_185401/prompts/batch-10.md +0 -108
  144. package/.desloppify/subagents/runs/20260315_185401/prompts/batch-2.md +0 -89
  145. package/.desloppify/subagents/runs/20260315_185401/prompts/batch-3.md +0 -91
  146. package/.desloppify/subagents/runs/20260315_185401/prompts/batch-4.md +0 -77
  147. package/.desloppify/subagents/runs/20260315_185401/prompts/batch-5.md +0 -77
  148. package/.desloppify/subagents/runs/20260315_185401/prompts/batch-6.md +0 -78
  149. package/.desloppify/subagents/runs/20260315_185401/prompts/batch-7.md +0 -94
  150. package/.desloppify/subagents/runs/20260315_185401/prompts/batch-8.md +0 -84
  151. package/.desloppify/subagents/runs/20260315_185401/prompts/batch-9.md +0 -112
  152. package/.desloppify/subagents/runs/20260315_185401/results/batch-1.raw.txt +0 -0
  153. package/.desloppify/subagents/runs/20260315_185401/results/batch-10.raw.txt +0 -0
  154. package/.desloppify/subagents/runs/20260315_185401/results/batch-2.raw.txt +0 -0
  155. package/.desloppify/subagents/runs/20260315_185401/results/batch-3.raw.txt +0 -0
  156. package/.desloppify/subagents/runs/20260315_185401/results/batch-4.raw.txt +0 -0
  157. package/.desloppify/subagents/runs/20260315_185401/results/batch-5.raw.txt +0 -0
  158. package/.desloppify/subagents/runs/20260315_185401/results/batch-6.raw.txt +0 -0
  159. package/.desloppify/subagents/runs/20260315_185401/results/batch-7.raw.txt +0 -0
  160. package/.desloppify/subagents/runs/20260315_185401/results/batch-8.raw.txt +0 -0
  161. package/.desloppify/subagents/runs/20260315_185401/results/batch-9.raw.txt +0 -0
  162. package/.desloppify/subagents/runs/20260315_185401/run.log +0 -36
  163. package/.desloppify/subagents/runs/20260315_185401/run_summary.json +0 -156
  164. package/.desloppify/subagents/runs/20260315_185613/holistic_findings_merged.json +0 -741
  165. package/.desloppify/subagents/runs/20260315_185613/logs/batch-1.log +0 -579
  166. package/.desloppify/subagents/runs/20260315_185613/logs/batch-10.log +0 -1537
  167. package/.desloppify/subagents/runs/20260315_185613/logs/batch-2.log +0 -829
  168. package/.desloppify/subagents/runs/20260315_185613/logs/batch-3.log +0 -927
  169. package/.desloppify/subagents/runs/20260315_185613/logs/batch-4.log +0 -429
  170. package/.desloppify/subagents/runs/20260315_185613/logs/batch-5.log +0 -276
  171. package/.desloppify/subagents/runs/20260315_185613/logs/batch-6.log +0 -450
  172. package/.desloppify/subagents/runs/20260315_185613/logs/batch-7.log +0 -730
  173. package/.desloppify/subagents/runs/20260315_185613/logs/batch-8.log +0 -698
  174. package/.desloppify/subagents/runs/20260315_185613/logs/batch-9.log +0 -938
  175. package/.desloppify/subagents/runs/20260315_185613/prompts/batch-1.md +0 -83
  176. package/.desloppify/subagents/runs/20260315_185613/prompts/batch-10.md +0 -108
  177. package/.desloppify/subagents/runs/20260315_185613/prompts/batch-2.md +0 -89
  178. package/.desloppify/subagents/runs/20260315_185613/prompts/batch-3.md +0 -91
  179. package/.desloppify/subagents/runs/20260315_185613/prompts/batch-4.md +0 -77
  180. package/.desloppify/subagents/runs/20260315_185613/prompts/batch-5.md +0 -77
  181. package/.desloppify/subagents/runs/20260315_185613/prompts/batch-6.md +0 -78
  182. package/.desloppify/subagents/runs/20260315_185613/prompts/batch-7.md +0 -94
  183. package/.desloppify/subagents/runs/20260315_185613/prompts/batch-8.md +0 -84
  184. package/.desloppify/subagents/runs/20260315_185613/prompts/batch-9.md +0 -112
  185. package/.desloppify/subagents/runs/20260315_185613/results/batch-1.raw.txt +0 -78
  186. package/.desloppify/subagents/runs/20260315_185613/results/batch-10.raw.txt +0 -242
  187. package/.desloppify/subagents/runs/20260315_185613/results/batch-2.raw.txt +0 -102
  188. package/.desloppify/subagents/runs/20260315_185613/results/batch-3.raw.txt +0 -94
  189. package/.desloppify/subagents/runs/20260315_185613/results/batch-4.raw.txt +0 -86
  190. package/.desloppify/subagents/runs/20260315_185613/results/batch-5.raw.txt +0 -1
  191. package/.desloppify/subagents/runs/20260315_185613/results/batch-6.raw.txt +0 -87
  192. package/.desloppify/subagents/runs/20260315_185613/results/batch-7.raw.txt +0 -1
  193. package/.desloppify/subagents/runs/20260315_185613/results/batch-8.raw.txt +0 -107
  194. package/.desloppify/subagents/runs/20260315_185613/results/batch-9.raw.txt +0 -67
  195. package/.desloppify/subagents/runs/20260315_185613/run.log +0 -96
  196. package/.desloppify/subagents/runs/20260315_185613/run_summary.json +0 -156
  197. package/.editorconfig +0 -12
  198. package/.github/dependabot.yml +0 -11
  199. package/.github/workflows/docs.yml +0 -46
  200. package/.github/workflows/test.yml +0 -40
  201. package/.markdownlint.jsonc +0 -11
  202. package/.node-version +0 -1
  203. package/.oxfmtrc.json +0 -9
  204. package/.oxlintrc.json +0 -35
  205. package/docs/ARCHITECTURE.md +0 -125
  206. package/scorecard.png +0 -0
  207. package/src/cli/cli.ts +0 -141
  208. package/src/cli/validators.ts +0 -68
  209. package/src/formats/anthropic/index.ts +0 -14
  210. package/src/formats/anthropic/parse.ts +0 -67
  211. package/src/formats/anthropic/schema.ts +0 -74
  212. package/src/formats/anthropic/serialize.ts +0 -179
  213. package/src/formats/openai/chat-completions/index.ts +0 -14
  214. package/src/formats/openai/chat-completions/parse.ts +0 -44
  215. package/src/formats/openai/chat-completions/schema.ts +0 -92
  216. package/src/formats/openai/chat-completions/serialize.ts +0 -146
  217. package/src/formats/openai/responses/index.ts +0 -14
  218. package/src/formats/openai/responses/parse.ts +0 -70
  219. package/src/formats/openai/responses/schema.ts +0 -86
  220. package/src/formats/openai/responses/serialize.ts +0 -332
  221. package/src/formats/request-helpers.ts +0 -56
  222. package/src/formats/serialize-helpers.ts +0 -43
  223. package/src/formats/types.ts +0 -26
  224. package/src/history.ts +0 -70
  225. package/src/index.ts +0 -46
  226. package/src/loader.ts +0 -246
  227. package/src/logger.ts +0 -70
  228. package/src/mock-server.ts +0 -203
  229. package/src/route-handler.ts +0 -144
  230. package/src/rule-builder.ts +0 -73
  231. package/src/rule-engine.ts +0 -165
  232. package/src/sse-writer.ts +0 -35
  233. package/src/types/reply.ts +0 -92
  234. package/src/types/request.ts +0 -56
  235. package/src/types/rule.ts +0 -125
  236. package/src/types.ts +0 -24
  237. package/test/cli-validators.test.ts +0 -151
  238. package/test/formats/anthropic.test.ts +0 -336
  239. package/test/formats/openai.test.ts +0 -316
  240. package/test/formats/parse-helpers.test.ts +0 -315
  241. package/test/formats/responses.test.ts +0 -380
  242. package/test/helpers/make-req.ts +0 -18
  243. package/test/history.test.ts +0 -361
  244. package/test/loader.test.ts +0 -333
  245. package/test/logger.test.ts +0 -344
  246. package/test/mock-server.test.ts +0 -619
  247. package/test/rule-engine.test.ts +0 -229
  248. package/tsconfig.json +0 -26
  249. package/tsconfig.test.json +0 -11
  250. package/typedoc.json +0 -9
  251. package/vitest.config.ts +0 -18
@@ -1,146 +0,0 @@
1
- import type { ReplyObject, ReplyOptions } from "../../../types/reply.js";
2
- import type { SSEChunk } from "../../types.js";
3
- import {
4
- splitText,
5
- genId,
6
- toolId,
7
- finishReason,
8
- MS_PER_SECOND,
9
- DEFAULT_USAGE,
10
- } from "../../serialize-helpers.js";
11
-
12
- function buildUsage(usage: { input: number; output: number }) {
13
- return {
14
- prompt_tokens: usage.input,
15
- completion_tokens: usage.output,
16
- total_tokens: usage.input + usage.output,
17
- prompt_tokens_details: { cached_tokens: 0, audio_tokens: 0 },
18
- completion_tokens_details: {
19
- reasoning_tokens: 0,
20
- audio_tokens: 0,
21
- accepted_prediction_tokens: 0,
22
- rejected_prediction_tokens: 0,
23
- },
24
- };
25
- }
26
-
27
- function chunkEnvelope(
28
- id: string,
29
- created: number,
30
- model: string,
31
- delta: Record<string, unknown>,
32
- finish_reason: string | null = null,
33
- usage: Record<string, unknown> | null = null,
34
- ): SSEChunk {
35
- return {
36
- data: JSON.stringify({
37
- id,
38
- object: "chat.completion.chunk",
39
- created,
40
- model,
41
- system_fingerprint: null,
42
- service_tier: "default",
43
- choices: [{ index: 0, delta, logprobs: null, finish_reason }],
44
- usage,
45
- }),
46
- };
47
- }
48
-
49
- export function serialize(
50
- reply: ReplyObject,
51
- model: string,
52
- options: ReplyOptions = {},
53
- ): readonly SSEChunk[] {
54
- const id = genId("chatcmpl");
55
- const created = Math.floor(Date.now() / MS_PER_SECOND);
56
- const usage = reply.usage ?? DEFAULT_USAGE;
57
-
58
- const textChunks = reply.text
59
- ? splitText(reply.text, options.chunkSize ?? 0).map((piece) =>
60
- chunkEnvelope(id, created, model, { content: piece }),
61
- )
62
- : [];
63
-
64
- const toolChunks = (reply.tools ?? []).map((tool, i) =>
65
- chunkEnvelope(id, created, model, {
66
- tool_calls: [
67
- {
68
- index: i,
69
- id: toolId(tool, "call", i),
70
- type: "function",
71
- function: { name: tool.name, arguments: JSON.stringify(tool.args) },
72
- },
73
- ],
74
- }),
75
- );
76
-
77
- const usageChunk = buildUsage(usage);
78
-
79
- return [
80
- chunkEnvelope(id, created, model, { role: "assistant" }),
81
- ...textChunks,
82
- ...toolChunks,
83
- chunkEnvelope(
84
- id,
85
- created,
86
- model,
87
- {},
88
- finishReason(reply, "tool_calls", "stop"),
89
- ),
90
- chunkEnvelope(id, created, model, {}, null, usageChunk),
91
- { data: "[DONE]" },
92
- ];
93
- }
94
-
95
- export function serializeComplete(
96
- reply: ReplyObject,
97
- model: string,
98
- ): Record<string, unknown> {
99
- const id = genId("chatcmpl");
100
- const created = Math.floor(Date.now() / MS_PER_SECOND);
101
- const usage = reply.usage ?? DEFAULT_USAGE;
102
-
103
- const message: Record<string, unknown> = {
104
- role: "assistant",
105
- content: reply.text ?? null,
106
- ...(reply.tools?.length && {
107
- tool_calls: reply.tools.map((tool, i) => ({
108
- id: toolId(tool, "call", i),
109
- type: "function",
110
- function: { name: tool.name, arguments: JSON.stringify(tool.args) },
111
- })),
112
- }),
113
- };
114
-
115
- return {
116
- id,
117
- object: "chat.completion",
118
- created,
119
- model,
120
- system_fingerprint: null,
121
- service_tier: "default",
122
- choices: [
123
- {
124
- index: 0,
125
- message,
126
- logprobs: null,
127
- finish_reason: finishReason(reply, "tool_calls", "stop"),
128
- },
129
- ],
130
- usage: buildUsage(usage),
131
- };
132
- }
133
-
134
- export function serializeError(error: {
135
- status: number;
136
- message: string;
137
- type?: string;
138
- }): Record<string, unknown> {
139
- return {
140
- error: {
141
- message: error.message,
142
- type: error.type ?? "server_error",
143
- code: null,
144
- },
145
- };
146
- }
@@ -1,14 +0,0 @@
1
- import type { Format } from "../../types.js";
2
- import { isStreaming } from "../../request-helpers.js";
3
- import { parseRequest } from "./parse.js";
4
- import { serialize, serializeComplete, serializeError } from "./serialize.js";
5
-
6
- export const responsesFormat: Format = {
7
- name: "responses",
8
- route: "/v1/responses",
9
- parseRequest,
10
- isStreaming,
11
- serialize,
12
- serializeComplete,
13
- serializeError,
14
- };
@@ -1,70 +0,0 @@
1
- import type { MockRequest, Message, ToolDef } from "../../../types/request.js";
2
- import { buildMockRequest, type RequestMeta } from "../../request-helpers.js";
3
- import {
4
- ResponsesRequestSchema,
5
- FunctionToolSchema,
6
- type ResponsesRequest,
7
- } from "./schema.js";
8
-
9
- function extractInputContent(
10
- content: string | Record<string, unknown>[],
11
- ): string {
12
- if (typeof content === "string") return content;
13
- return content
14
- .filter((b) => b["type"] === "input_text" || b["type"] === "text")
15
- .map((b) => String(b["text"] ?? ""))
16
- .join("\n");
17
- }
18
-
19
- function parseInput(req: ResponsesRequest): readonly Message[] {
20
- const instructions: Message[] = req.instructions
21
- ? [{ role: "system", content: req.instructions }]
22
- : [];
23
-
24
- if (req.input === undefined) return instructions;
25
-
26
- if (typeof req.input === "string") {
27
- return [...instructions, { role: "user", content: req.input }];
28
- }
29
-
30
- const messages = req.input.map((item): Message => {
31
- if ("call_id" in item) {
32
- return {
33
- role: "tool",
34
- content: "output" in item ? item.output : item.arguments,
35
- toolCallId: item.call_id,
36
- };
37
- }
38
- return {
39
- role: item.role === "developer" ? "system" : item.role,
40
- content: extractInputContent(item.content),
41
- };
42
- });
43
-
44
- return [...instructions, ...messages];
45
- }
46
-
47
- function parseTools(req: ResponsesRequest): readonly ToolDef[] | undefined {
48
- if (!req.tools) return undefined;
49
- return req.tools
50
- .map((t) => FunctionToolSchema.safeParse(t))
51
- .filter((r) => r.success)
52
- .map((r) => ({
53
- name: r.data.name,
54
- description: r.data.description,
55
- parameters: r.data.parameters,
56
- }));
57
- }
58
-
59
- export function parseRequest(body: unknown, meta?: RequestMeta): MockRequest {
60
- const req = ResponsesRequestSchema.parse(body);
61
- return buildMockRequest(
62
- "responses",
63
- req,
64
- parseInput(req),
65
- parseTools(req),
66
- "codex-mini",
67
- body,
68
- meta,
69
- );
70
- }
@@ -1,86 +0,0 @@
1
- import { z } from "zod";
2
-
3
- export {
4
- ResponsesRequestSchema,
5
- FunctionToolSchema,
6
- type ResponsesRequest,
7
- } from "llm-schemas/openai/responses";
8
-
9
- const OutputContentSchema = z.object({
10
- type: z.string(),
11
- text: z.string(),
12
- annotations: z.array(z.unknown()).optional(),
13
- });
14
-
15
- const OutputItemSchema = z.object({
16
- type: z.string(),
17
- id: z.string().optional(),
18
- status: z.string().optional(),
19
- role: z.string().optional(),
20
- content: z.array(OutputContentSchema).optional(),
21
- call_id: z.string().optional(),
22
- name: z.string().optional(),
23
- arguments: z.string().optional(),
24
- summary: z.array(z.object({ type: z.string(), text: z.string() })).optional(),
25
- });
26
-
27
- export const ResponsesEventSchema = z.object({
28
- type: z.string(),
29
- sequence_number: z.number().optional(),
30
- response: z
31
- .object({
32
- id: z.string(),
33
- object: z.string(),
34
- created_at: z.number(),
35
- model: z.string(),
36
- status: z.string(),
37
- output: z.array(OutputItemSchema),
38
- usage: z
39
- .object({
40
- input_tokens: z.number(),
41
- output_tokens: z.number(),
42
- total_tokens: z.number(),
43
- })
44
- .optional(),
45
- })
46
- .optional(),
47
- item: OutputItemSchema.optional(),
48
- part: z
49
- .object({
50
- type: z.string(),
51
- text: z.string().optional(),
52
- annotations: z.array(z.unknown()).optional(),
53
- })
54
- .optional(),
55
- delta: z.string().optional(),
56
- item_id: z.string().optional(),
57
- });
58
-
59
- export type ResponsesEvent = z.infer<typeof ResponsesEventSchema>;
60
-
61
- export const ResponsesCompleteSchema = z.object({
62
- id: z.string(),
63
- object: z.literal("response"),
64
- created_at: z.number(),
65
- status: z.literal("completed"),
66
- model: z.string(),
67
- output: z.array(OutputItemSchema),
68
- usage: z.object({
69
- input_tokens: z.number(),
70
- output_tokens: z.number(),
71
- total_tokens: z.number(),
72
- }),
73
- });
74
-
75
- export type ResponsesComplete = z.infer<typeof ResponsesCompleteSchema>;
76
-
77
- export const ResponsesErrorSchema = z.object({
78
- type: z.literal("error"),
79
- error: z.object({
80
- message: z.string(),
81
- type: z.string().optional(),
82
- code: z.string().optional(),
83
- }),
84
- });
85
-
86
- export type ResponsesError = z.infer<typeof ResponsesErrorSchema>;
@@ -1,332 +0,0 @@
1
- import type {
2
- ReplyObject,
3
- ReplyOptions,
4
- ToolCall,
5
- } from "../../../types/reply.js";
6
- import type { SSEChunk } from "../../types.js";
7
- import {
8
- splitText,
9
- genId,
10
- toolId,
11
- shouldEmitText,
12
- MS_PER_SECOND,
13
- DEFAULT_USAGE,
14
- } from "../../serialize-helpers.js";
15
-
16
- function buildUsage(usage: { input: number; output: number }) {
17
- return {
18
- input_tokens: usage.input,
19
- output_tokens: usage.output,
20
- total_tokens: usage.input + usage.output,
21
- };
22
- }
23
-
24
- interface StreamBlock {
25
- chunks: SSEChunk[];
26
- outputItem: unknown;
27
- }
28
-
29
- const NO_ANNOTATIONS: readonly unknown[] = [];
30
-
31
- type Chunk = (payload: Record<string, unknown>) => SSEChunk;
32
-
33
- function createChunk(): Chunk {
34
- let seq = 0;
35
- return (payload) => ({
36
- data: JSON.stringify({ ...payload, sequence_number: seq++ }),
37
- });
38
- }
39
-
40
- function reasoningStreamBlock(
41
- c: Chunk,
42
- i: number,
43
- reasoning: string,
44
- ): StreamBlock {
45
- const itemId = `rs_${genId("rs")}`;
46
- const summaryPart = { type: "summary_text" as const, text: reasoning };
47
- const item = {
48
- type: "reasoning",
49
- id: itemId,
50
- status: "completed",
51
- summary: [summaryPart],
52
- };
53
-
54
- return {
55
- outputItem: item,
56
- chunks: [
57
- c({
58
- type: "response.output_item.added",
59
- output_index: i,
60
- item: {
61
- type: "reasoning",
62
- id: itemId,
63
- status: "in_progress",
64
- summary: [],
65
- },
66
- }),
67
- c({
68
- type: "response.reasoning_summary_part.added",
69
- item_id: itemId,
70
- output_index: i,
71
- summary_index: 0,
72
- part: { type: "summary_text", text: "" },
73
- }),
74
- c({
75
- type: "response.reasoning_summary_text.delta",
76
- item_id: itemId,
77
- output_index: i,
78
- summary_index: 0,
79
- delta: reasoning,
80
- }),
81
- c({
82
- type: "response.reasoning_summary_text.done",
83
- item_id: itemId,
84
- output_index: i,
85
- summary_index: 0,
86
- text: reasoning,
87
- }),
88
- c({
89
- type: "response.reasoning_summary_part.done",
90
- item_id: itemId,
91
- output_index: i,
92
- summary_index: 0,
93
- part: summaryPart,
94
- }),
95
- c({ type: "response.output_item.done", output_index: i, item }),
96
- ],
97
- };
98
- }
99
-
100
- function textStreamBlock(
101
- c: Chunk,
102
- i: number,
103
- text: string,
104
- chunkSize: number,
105
- ): StreamBlock {
106
- const itemId = `msg_${genId("msg")}`;
107
- const outputText = {
108
- type: "output_text" as const,
109
- text,
110
- annotations: NO_ANNOTATIONS,
111
- };
112
- const outputItem = {
113
- type: "message",
114
- id: itemId,
115
- status: "completed",
116
- role: "assistant",
117
- content: [outputText],
118
- };
119
-
120
- return {
121
- outputItem,
122
- chunks: [
123
- c({
124
- type: "response.output_item.added",
125
- output_index: i,
126
- item: {
127
- type: "message",
128
- id: itemId,
129
- status: "in_progress",
130
- role: "assistant",
131
- content: [],
132
- },
133
- }),
134
- c({
135
- type: "response.content_part.added",
136
- item_id: itemId,
137
- output_index: i,
138
- content_index: 0,
139
- part: { type: "output_text", text: "", annotations: [] },
140
- }),
141
- ...splitText(text, chunkSize).map((piece) =>
142
- c({
143
- type: "response.output_text.delta",
144
- item_id: itemId,
145
- output_index: i,
146
- content_index: 0,
147
- delta: piece,
148
- }),
149
- ),
150
- c({
151
- type: "response.output_text.done",
152
- item_id: itemId,
153
- output_index: i,
154
- content_index: 0,
155
- text,
156
- }),
157
- c({
158
- type: "response.content_part.done",
159
- item_id: itemId,
160
- output_index: i,
161
- content_index: 0,
162
- part: outputText,
163
- }),
164
- c({
165
- type: "response.output_item.done",
166
- output_index: i,
167
- item: outputItem,
168
- }),
169
- ],
170
- };
171
- }
172
-
173
- function toolStreamBlock(c: Chunk, i: number, tool: ToolCall): StreamBlock {
174
- const callId = toolId(tool, "call", i);
175
- const argsJson = JSON.stringify(tool.args);
176
- const outputItem = {
177
- type: "function_call",
178
- id: callId,
179
- status: "completed",
180
- name: tool.name,
181
- call_id: callId,
182
- arguments: argsJson,
183
- };
184
-
185
- return {
186
- outputItem,
187
- chunks: [
188
- c({
189
- type: "response.output_item.added",
190
- output_index: i,
191
- item: { ...outputItem, status: "in_progress", arguments: "" },
192
- }),
193
- c({
194
- type: "response.function_call_arguments.delta",
195
- item_id: callId,
196
- output_index: i,
197
- delta: argsJson,
198
- }),
199
- c({
200
- type: "response.function_call_arguments.done",
201
- item_id: callId,
202
- output_index: i,
203
- arguments: argsJson,
204
- }),
205
- c({
206
- type: "response.output_item.done",
207
- output_index: i,
208
- item: outputItem,
209
- }),
210
- ],
211
- };
212
- }
213
-
214
- export function serialize(
215
- reply: ReplyObject,
216
- model: string,
217
- options: ReplyOptions = {},
218
- ): readonly SSEChunk[] {
219
- const id = genId("resp");
220
- const createdAt = Math.floor(Date.now() / MS_PER_SECOND);
221
- const usage = reply.usage ?? DEFAULT_USAGE;
222
- const c = createChunk();
223
- let i = 0;
224
-
225
- const baseResponse = { id, object: "response", created_at: createdAt, model };
226
- const header = [
227
- c({
228
- type: "response.created",
229
- response: { ...baseResponse, status: "in_progress", output: [] },
230
- }),
231
- c({
232
- type: "response.in_progress",
233
- response: { ...baseResponse, status: "in_progress", output: [] },
234
- }),
235
- ];
236
-
237
- const blocks: StreamBlock[] = [
238
- ...(reply.reasoning ? [reasoningStreamBlock(c, i++, reply.reasoning)] : []),
239
- ...(shouldEmitText(reply)
240
- ? [textStreamBlock(c, i++, reply.text ?? "", options.chunkSize ?? 0)]
241
- : []),
242
- ...(reply.tools ?? []).map((tool) => toolStreamBlock(c, i++, tool)),
243
- ];
244
-
245
- const allChunks = blocks.flatMap((b) => b.chunks);
246
- const output = blocks.map((b) => b.outputItem);
247
-
248
- return [
249
- ...header,
250
- ...allChunks,
251
- c({
252
- type: "response.completed",
253
- response: {
254
- ...baseResponse,
255
- status: "completed",
256
- output,
257
- usage: buildUsage(usage),
258
- },
259
- }),
260
- ];
261
- }
262
-
263
- export function serializeComplete(
264
- reply: ReplyObject,
265
- model: string,
266
- ): Record<string, unknown> {
267
- const id = genId("resp");
268
- const createdAt = Math.floor(Date.now() / MS_PER_SECOND);
269
- const usage = reply.usage ?? DEFAULT_USAGE;
270
-
271
- const output: unknown[] = [
272
- ...(reply.reasoning
273
- ? [
274
- {
275
- type: "reasoning",
276
- id: `rs_${genId("rs")}`,
277
- status: "completed",
278
- summary: [{ type: "summary_text", text: reply.reasoning }],
279
- },
280
- ]
281
- : []),
282
- ...(shouldEmitText(reply)
283
- ? [
284
- {
285
- type: "message",
286
- id: `msg_${genId("msg")}`,
287
- status: "completed",
288
- role: "assistant",
289
- content: [
290
- { type: "output_text", text: reply.text ?? "", annotations: [] },
291
- ],
292
- },
293
- ]
294
- : []),
295
- ...(reply.tools ?? []).map((tool, i) => {
296
- const callId = toolId(tool, "call", i);
297
- return {
298
- type: "function_call",
299
- id: callId,
300
- status: "completed",
301
- name: tool.name,
302
- call_id: callId,
303
- arguments: JSON.stringify(tool.args),
304
- };
305
- }),
306
- ];
307
-
308
- return {
309
- id,
310
- object: "response",
311
- created_at: createdAt,
312
- status: "completed",
313
- model,
314
- output,
315
- usage: buildUsage(usage),
316
- };
317
- }
318
-
319
- export function serializeError(error: {
320
- status: number;
321
- message: string;
322
- type?: string;
323
- }): Record<string, unknown> {
324
- return {
325
- type: "error",
326
- error: {
327
- message: error.message,
328
- type: error.type ?? "server_error",
329
- code: error.type ?? "server_error",
330
- },
331
- };
332
- }
@@ -1,56 +0,0 @@
1
- import type {
2
- FormatName,
3
- Message,
4
- MockRequest,
5
- ToolDef,
6
- } from "../types/request.js";
7
-
8
- function asRecord(body: unknown): Record<string, unknown> {
9
- if (typeof body === "object" && body !== null)
10
- return body as Record<string, unknown>;
11
- return {};
12
- }
13
-
14
- export function isStreaming(body: unknown): boolean {
15
- return asRecord(body)["stream"] !== false;
16
- }
17
-
18
- export interface RequestMeta {
19
- readonly headers: Readonly<Record<string, string | undefined>>;
20
- readonly path: string;
21
- }
22
-
23
- const EMPTY_META: RequestMeta = { headers: {}, path: "" };
24
-
25
- interface ParsedBody {
26
- readonly model?: string | undefined;
27
- readonly stream?: boolean | undefined;
28
- }
29
-
30
- export function buildMockRequest(
31
- format: FormatName,
32
- body: ParsedBody,
33
- messages: readonly Message[],
34
- tools: readonly ToolDef[] | undefined,
35
- defaultModel: string,
36
- raw: unknown,
37
- meta: RequestMeta = EMPTY_META,
38
- ): MockRequest {
39
- const userMessages = messages.filter((m) => m.role === "user");
40
- const toolCallMsgs = messages.filter((m) => m.toolCallId !== undefined);
41
-
42
- return {
43
- format,
44
- model: body.model || defaultModel,
45
- streaming: body.stream !== false,
46
- messages,
47
- lastMessage: userMessages.at(-1)?.content ?? "",
48
- systemMessage: messages.find((m) => m.role === "system")?.content ?? "",
49
- tools,
50
- toolNames: tools?.map((t) => t.name) ?? [],
51
- lastToolCallId: toolCallMsgs.at(-1)?.toolCallId,
52
- raw,
53
- headers: meta.headers,
54
- path: meta.path,
55
- };
56
- }