@yolk-sdk/emulators 0.1.0-canary.96

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 (333) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +2135 -0
  3. package/dist/anthropic.d.mts +269 -0
  4. package/dist/anthropic.d.mts.map +1 -0
  5. package/dist/anthropic.mjs +177 -0
  6. package/dist/anthropic.mjs.map +1 -0
  7. package/dist/chat-completions.d.mts +288 -0
  8. package/dist/chat-completions.d.mts.map +1 -0
  9. package/dist/chat-completions.mjs +451 -0
  10. package/dist/chat-completions.mjs.map +1 -0
  11. package/dist/codex.d.mts +265 -0
  12. package/dist/codex.d.mts.map +1 -0
  13. package/dist/codex.mjs +199 -0
  14. package/dist/codex.mjs.map +1 -0
  15. package/dist/dropbox/api.d.mts +63 -0
  16. package/dist/dropbox/api.d.mts.map +1 -0
  17. package/dist/dropbox/api.mjs +565 -0
  18. package/dist/dropbox/api.mjs.map +1 -0
  19. package/dist/dropbox/state.d.mts +136 -0
  20. package/dist/dropbox/state.d.mts.map +1 -0
  21. package/dist/dropbox/state.mjs +209 -0
  22. package/dist/dropbox/state.mjs.map +1 -0
  23. package/dist/dropbox.d.mts +79 -0
  24. package/dist/dropbox.d.mts.map +1 -0
  25. package/dist/dropbox.mjs +124 -0
  26. package/dist/dropbox.mjs.map +1 -0
  27. package/dist/email-fixtures.d.mts +36 -0
  28. package/dist/email-fixtures.d.mts.map +1 -0
  29. package/dist/email-fixtures.mjs +1080 -0
  30. package/dist/email-fixtures.mjs.map +1 -0
  31. package/dist/email.d.mts +160 -0
  32. package/dist/email.d.mts.map +1 -0
  33. package/dist/email.mjs +608 -0
  34. package/dist/email.mjs.map +1 -0
  35. package/dist/emulator-compose.d.mts +40 -0
  36. package/dist/emulator-compose.d.mts.map +1 -0
  37. package/dist/emulator-compose.mjs +91 -0
  38. package/dist/emulator-compose.mjs.map +1 -0
  39. package/dist/emulator-http.d.mts +53 -0
  40. package/dist/emulator-http.d.mts.map +1 -0
  41. package/dist/emulator-http.mjs +117 -0
  42. package/dist/emulator-http.mjs.map +1 -0
  43. package/dist/emulator-kernel.d.mts +176 -0
  44. package/dist/emulator-kernel.d.mts.map +1 -0
  45. package/dist/emulator-kernel.mjs +413 -0
  46. package/dist/emulator-kernel.mjs.map +1 -0
  47. package/dist/fixture-route.d.mts +129 -0
  48. package/dist/fixture-route.d.mts.map +1 -0
  49. package/dist/fixture-route.mjs +257 -0
  50. package/dist/fixture-route.mjs.map +1 -0
  51. package/dist/fortnox/api.d.mts +92 -0
  52. package/dist/fortnox/api.d.mts.map +1 -0
  53. package/dist/fortnox/api.mjs +750 -0
  54. package/dist/fortnox/api.mjs.map +1 -0
  55. package/dist/fortnox/state.d.mts +533 -0
  56. package/dist/fortnox/state.d.mts.map +1 -0
  57. package/dist/fortnox/state.mjs +612 -0
  58. package/dist/fortnox/state.mjs.map +1 -0
  59. package/dist/fortnox.d.mts +128 -0
  60. package/dist/fortnox.d.mts.map +1 -0
  61. package/dist/fortnox.mjs +403 -0
  62. package/dist/fortnox.mjs.map +1 -0
  63. package/dist/gateway-evaluate-recordings.d.mts +12 -0
  64. package/dist/gateway-evaluate-recordings.d.mts.map +1 -0
  65. package/dist/gateway-evaluate-recordings.mjs +128 -0
  66. package/dist/gateway-evaluate-recordings.mjs.map +1 -0
  67. package/dist/gateway.d.mts +272 -0
  68. package/dist/gateway.d.mts.map +1 -0
  69. package/dist/gateway.mjs +400 -0
  70. package/dist/gateway.mjs.map +1 -0
  71. package/dist/github/api.d.mts +63 -0
  72. package/dist/github/api.d.mts.map +1 -0
  73. package/dist/github/api.mjs +527 -0
  74. package/dist/github/api.mjs.map +1 -0
  75. package/dist/github/state.d.mts +272 -0
  76. package/dist/github/state.d.mts.map +1 -0
  77. package/dist/github/state.mjs +303 -0
  78. package/dist/github/state.mjs.map +1 -0
  79. package/dist/github.d.mts +77 -0
  80. package/dist/github.d.mts.map +1 -0
  81. package/dist/github.mjs +180 -0
  82. package/dist/github.mjs.map +1 -0
  83. package/dist/google/calendar.d.mts +10 -0
  84. package/dist/google/calendar.d.mts.map +1 -0
  85. package/dist/google/calendar.mjs +252 -0
  86. package/dist/google/calendar.mjs.map +1 -0
  87. package/dist/google/drive.d.mts +8 -0
  88. package/dist/google/drive.d.mts.map +1 -0
  89. package/dist/google/drive.mjs +252 -0
  90. package/dist/google/drive.mjs.map +1 -0
  91. package/dist/google/gmail.d.mts +10 -0
  92. package/dist/google/gmail.d.mts.map +1 -0
  93. package/dist/google/gmail.mjs +591 -0
  94. package/dist/google/gmail.mjs.map +1 -0
  95. package/dist/google/shared.d.mts +107 -0
  96. package/dist/google/shared.d.mts.map +1 -0
  97. package/dist/google/shared.mjs +146 -0
  98. package/dist/google/shared.mjs.map +1 -0
  99. package/dist/google/state.d.mts +385 -0
  100. package/dist/google/state.d.mts.map +1 -0
  101. package/dist/google/state.mjs +496 -0
  102. package/dist/google/state.mjs.map +1 -0
  103. package/dist/google.d.mts +75 -0
  104. package/dist/google.d.mts.map +1 -0
  105. package/dist/google.mjs +210 -0
  106. package/dist/google.mjs.map +1 -0
  107. package/dist/linkedin-search/api.d.mts +45 -0
  108. package/dist/linkedin-search/api.d.mts.map +1 -0
  109. package/dist/linkedin-search/api.mjs +181 -0
  110. package/dist/linkedin-search/api.mjs.map +1 -0
  111. package/dist/linkedin-search/state.d.mts +123 -0
  112. package/dist/linkedin-search/state.d.mts.map +1 -0
  113. package/dist/linkedin-search/state.mjs +261 -0
  114. package/dist/linkedin-search/state.mjs.map +1 -0
  115. package/dist/linkedin-search.d.mts +69 -0
  116. package/dist/linkedin-search.d.mts.map +1 -0
  117. package/dist/linkedin-search.mjs +158 -0
  118. package/dist/linkedin-search.mjs.map +1 -0
  119. package/dist/mcp/api.d.mts +44 -0
  120. package/dist/mcp/api.d.mts.map +1 -0
  121. package/dist/mcp/api.mjs +557 -0
  122. package/dist/mcp/api.mjs.map +1 -0
  123. package/dist/mcp/recordings.d.mts +40 -0
  124. package/dist/mcp/recordings.d.mts.map +1 -0
  125. package/dist/mcp/recordings.mjs +2390 -0
  126. package/dist/mcp/recordings.mjs.map +1 -0
  127. package/dist/mcp/state.d.mts +71 -0
  128. package/dist/mcp/state.d.mts.map +1 -0
  129. package/dist/mcp/state.mjs +83 -0
  130. package/dist/mcp/state.mjs.map +1 -0
  131. package/dist/mcp.d.mts +84 -0
  132. package/dist/mcp.d.mts.map +1 -0
  133. package/dist/mcp.mjs +241 -0
  134. package/dist/mcp.mjs.map +1 -0
  135. package/dist/messages.d.mts +183 -0
  136. package/dist/messages.d.mts.map +1 -0
  137. package/dist/messages.mjs +532 -0
  138. package/dist/messages.mjs.map +1 -0
  139. package/dist/microsoft/api.d.mts +47 -0
  140. package/dist/microsoft/api.d.mts.map +1 -0
  141. package/dist/microsoft/api.mjs +178 -0
  142. package/dist/microsoft/api.mjs.map +1 -0
  143. package/dist/microsoft/calendar.d.mts +30 -0
  144. package/dist/microsoft/calendar.d.mts.map +1 -0
  145. package/dist/microsoft/calendar.mjs +271 -0
  146. package/dist/microsoft/calendar.mjs.map +1 -0
  147. package/dist/microsoft/drive.d.mts +36 -0
  148. package/dist/microsoft/drive.d.mts.map +1 -0
  149. package/dist/microsoft/drive.mjs +298 -0
  150. package/dist/microsoft/drive.mjs.map +1 -0
  151. package/dist/microsoft/graph.d.mts +198 -0
  152. package/dist/microsoft/graph.d.mts.map +1 -0
  153. package/dist/microsoft/graph.mjs +264 -0
  154. package/dist/microsoft/graph.mjs.map +1 -0
  155. package/dist/microsoft/mail.d.mts +48 -0
  156. package/dist/microsoft/mail.d.mts.map +1 -0
  157. package/dist/microsoft/mail.mjs +488 -0
  158. package/dist/microsoft/mail.mjs.map +1 -0
  159. package/dist/microsoft/state.d.mts +480 -0
  160. package/dist/microsoft/state.d.mts.map +1 -0
  161. package/dist/microsoft/state.mjs +625 -0
  162. package/dist/microsoft/state.mjs.map +1 -0
  163. package/dist/microsoft.d.mts +168 -0
  164. package/dist/microsoft.d.mts.map +1 -0
  165. package/dist/microsoft.mjs +483 -0
  166. package/dist/microsoft.mjs.map +1 -0
  167. package/dist/node.d.mts +47 -0
  168. package/dist/node.d.mts.map +1 -0
  169. package/dist/node.mjs +178 -0
  170. package/dist/node.mjs.map +1 -0
  171. package/dist/notion/api.d.mts +51 -0
  172. package/dist/notion/api.d.mts.map +1 -0
  173. package/dist/notion/api.mjs +507 -0
  174. package/dist/notion/api.mjs.map +1 -0
  175. package/dist/notion/state.d.mts +329 -0
  176. package/dist/notion/state.d.mts.map +1 -0
  177. package/dist/notion/state.mjs +432 -0
  178. package/dist/notion/state.mjs.map +1 -0
  179. package/dist/notion.d.mts +72 -0
  180. package/dist/notion.d.mts.map +1 -0
  181. package/dist/notion.mjs +127 -0
  182. package/dist/notion.mjs.map +1 -0
  183. package/dist/openai.d.mts +165 -0
  184. package/dist/openai.d.mts.map +1 -0
  185. package/dist/openai.mjs +141 -0
  186. package/dist/openai.mjs.map +1 -0
  187. package/dist/opencode-recordings.d.mts +7 -0
  188. package/dist/opencode-recordings.d.mts.map +1 -0
  189. package/dist/opencode-recordings.mjs +222 -0
  190. package/dist/opencode-recordings.mjs.map +1 -0
  191. package/dist/opencode.d.mts +70 -0
  192. package/dist/opencode.d.mts.map +1 -0
  193. package/dist/opencode.mjs +217 -0
  194. package/dist/opencode.mjs.map +1 -0
  195. package/dist/r2-fixtures.d.mts +36 -0
  196. package/dist/r2-fixtures.d.mts.map +1 -0
  197. package/dist/r2-fixtures.mjs +245 -0
  198. package/dist/r2-fixtures.mjs.map +1 -0
  199. package/dist/r2-guard.d.mts +43 -0
  200. package/dist/r2-guard.d.mts.map +1 -0
  201. package/dist/r2-guard.mjs +215 -0
  202. package/dist/r2-guard.mjs.map +1 -0
  203. package/dist/r2.d.mts +166 -0
  204. package/dist/r2.d.mts.map +1 -0
  205. package/dist/r2.mjs +517 -0
  206. package/dist/r2.mjs.map +1 -0
  207. package/dist/responses.d.mts +231 -0
  208. package/dist/responses.d.mts.map +1 -0
  209. package/dist/responses.mjs +556 -0
  210. package/dist/responses.mjs.map +1 -0
  211. package/dist/route-evidence.d.mts +45 -0
  212. package/dist/route-evidence.d.mts.map +1 -0
  213. package/dist/route-evidence.mjs +56 -0
  214. package/dist/route-evidence.mjs.map +1 -0
  215. package/dist/router.d.mts +93 -0
  216. package/dist/router.d.mts.map +1 -0
  217. package/dist/router.mjs +259 -0
  218. package/dist/router.mjs.map +1 -0
  219. package/dist/stateful-core.d.mts +17 -0
  220. package/dist/stateful-core.d.mts.map +1 -0
  221. package/dist/stateful-core.mjs +41 -0
  222. package/dist/stateful-core.mjs.map +1 -0
  223. package/dist/stateful-emulator.d.mts +565 -0
  224. package/dist/stateful-emulator.d.mts.map +1 -0
  225. package/dist/stateful-emulator.mjs +1228 -0
  226. package/dist/stateful-emulator.mjs.map +1 -0
  227. package/dist/stateful-secrets.d.mts +84 -0
  228. package/dist/stateful-secrets.d.mts.map +1 -0
  229. package/dist/stateful-secrets.mjs +216 -0
  230. package/dist/stateful-secrets.mjs.map +1 -0
  231. package/dist/subscription-usage-recordings.d.mts +9 -0
  232. package/dist/subscription-usage-recordings.d.mts.map +1 -0
  233. package/dist/subscription-usage-recordings.mjs +53 -0
  234. package/dist/subscription-usage-recordings.mjs.map +1 -0
  235. package/dist/subscription-usage.d.mts +53 -0
  236. package/dist/subscription-usage.d.mts.map +1 -0
  237. package/dist/subscription-usage.mjs +21 -0
  238. package/dist/subscription-usage.mjs.map +1 -0
  239. package/dist/telegram/api.d.mts +34 -0
  240. package/dist/telegram/api.d.mts.map +1 -0
  241. package/dist/telegram/api.mjs +257 -0
  242. package/dist/telegram/api.mjs.map +1 -0
  243. package/dist/telegram/state.d.mts +128 -0
  244. package/dist/telegram/state.d.mts.map +1 -0
  245. package/dist/telegram/state.mjs +154 -0
  246. package/dist/telegram/state.mjs.map +1 -0
  247. package/dist/telegram.d.mts +62 -0
  248. package/dist/telegram.d.mts.map +1 -0
  249. package/dist/telegram.mjs +127 -0
  250. package/dist/telegram.mjs.map +1 -0
  251. package/dist/todoist/api.d.mts +55 -0
  252. package/dist/todoist/api.d.mts.map +1 -0
  253. package/dist/todoist/api.mjs +415 -0
  254. package/dist/todoist/api.mjs.map +1 -0
  255. package/dist/todoist/state.d.mts +275 -0
  256. package/dist/todoist/state.d.mts.map +1 -0
  257. package/dist/todoist/state.mjs +345 -0
  258. package/dist/todoist/state.mjs.map +1 -0
  259. package/dist/todoist.d.mts +68 -0
  260. package/dist/todoist.d.mts.map +1 -0
  261. package/dist/todoist.mjs +181 -0
  262. package/dist/todoist.mjs.map +1 -0
  263. package/dist/xai.d.mts +267 -0
  264. package/dist/xai.d.mts.map +1 -0
  265. package/dist/xai.mjs +252 -0
  266. package/dist/xai.mjs.map +1 -0
  267. package/package.json +157 -0
  268. package/src/anthropic.ts +289 -0
  269. package/src/chat-completions.ts +924 -0
  270. package/src/codex.ts +296 -0
  271. package/src/dropbox/api.ts +1084 -0
  272. package/src/dropbox/state.ts +364 -0
  273. package/src/dropbox.ts +203 -0
  274. package/src/email-fixtures.ts +1297 -0
  275. package/src/email.ts +1108 -0
  276. package/src/emulator-compose.ts +147 -0
  277. package/src/emulator-http.ts +184 -0
  278. package/src/emulator-kernel.ts +844 -0
  279. package/src/fixture-route.ts +561 -0
  280. package/src/fortnox/api.ts +1352 -0
  281. package/src/fortnox/state.ts +798 -0
  282. package/src/fortnox.ts +801 -0
  283. package/src/gateway-evaluate-recordings.ts +153 -0
  284. package/src/gateway.ts +530 -0
  285. package/src/github/api.ts +986 -0
  286. package/src/github/state.ts +439 -0
  287. package/src/github.ts +271 -0
  288. package/src/google/calendar.ts +486 -0
  289. package/src/google/drive.ts +471 -0
  290. package/src/google/gmail.ts +1011 -0
  291. package/src/google/shared.ts +321 -0
  292. package/src/google/state.ts +686 -0
  293. package/src/google.ts +298 -0
  294. package/src/linkedin-search/api.ts +363 -0
  295. package/src/linkedin-search/state.ts +373 -0
  296. package/src/linkedin-search.ts +241 -0
  297. package/src/mcp/api.ts +995 -0
  298. package/src/mcp/recordings.ts +2665 -0
  299. package/src/mcp/state.ts +125 -0
  300. package/src/mcp.ts +319 -0
  301. package/src/messages.ts +844 -0
  302. package/src/microsoft/api.ts +426 -0
  303. package/src/microsoft/calendar.ts +491 -0
  304. package/src/microsoft/drive.ts +541 -0
  305. package/src/microsoft/graph.ts +550 -0
  306. package/src/microsoft/mail.ts +833 -0
  307. package/src/microsoft/state.ts +822 -0
  308. package/src/microsoft.ts +982 -0
  309. package/src/node.ts +293 -0
  310. package/src/notion/api.ts +976 -0
  311. package/src/notion/state.ts +512 -0
  312. package/src/notion.ts +210 -0
  313. package/src/openai.ts +198 -0
  314. package/src/opencode-recordings.ts +257 -0
  315. package/src/opencode.ts +271 -0
  316. package/src/r2-fixtures.ts +295 -0
  317. package/src/r2-guard.ts +323 -0
  318. package/src/r2.ts +890 -0
  319. package/src/responses.ts +901 -0
  320. package/src/route-evidence.ts +90 -0
  321. package/src/router.ts +490 -0
  322. package/src/stateful-core.ts +70 -0
  323. package/src/stateful-emulator.ts +2571 -0
  324. package/src/stateful-secrets.ts +299 -0
  325. package/src/subscription-usage-recordings.ts +77 -0
  326. package/src/subscription-usage.ts +68 -0
  327. package/src/telegram/api.ts +437 -0
  328. package/src/telegram/state.ts +229 -0
  329. package/src/telegram.ts +227 -0
  330. package/src/todoist/api.ts +736 -0
  331. package/src/todoist/state.ts +456 -0
  332. package/src/todoist.ts +316 -0
  333. package/src/xai.ts +341 -0
package/src/codex.ts ADDED
@@ -0,0 +1,296 @@
1
+ /**
2
+ * OpenAI Codex (ChatGPT subscription) Responses emulator: a plain fetch handler for
3
+ * `POST /backend-api/codex/responses` (origin `https://chatgpt.com`), with scripted turns, wire
4
+ * faults, a request ledger, and an `/_emulate/*` control plane.
5
+ *
6
+ * It never imports SDK code: its wire shapes follow the synthetic Codex Responses conformance
7
+ * fixtures (Responses SSE with typed `event:` names, the `response` JSON body, and the
8
+ * `{ error: { message, type, param, code } }` envelope) and are linked to those conformance case
9
+ * ids in `codexEmulatorRoutes`. The Responses machinery lives in the internal `responses.ts` core
10
+ * and is shared with the xAI Grok emulator.
11
+ *
12
+ * Requests authenticate with a non-empty `Authorization: Bearer` credential (a ChatGPT OAuth
13
+ * access token), never checked or stored. The ChatGPT Codex endpoint does not take an output
14
+ * limit, so a request with `max_output_tokens` answers 400 `unsupported_parameter`. The
15
+ * `originator` header is recorded in the ledger; `ChatGPT-Account-Id` is neither required nor
16
+ * recorded.
17
+ *
18
+ * The same fetch handler also answers the Codex subscription-usage route
19
+ * (`GET /backend-api/wham/usage`, `emulator.usage`) with its own manifest
20
+ * (`codexSubscriptionUsageEmulatorRoutes`), ledger, faults, and turns; see `makeCodexEmulator`.
21
+ *
22
+ * Runtime-portable Web APIs only (`Request`, `Response`, `ReadableStream`, `TextEncoder`, `URL`);
23
+ * no Effect runtime is required to use it.
24
+ *
25
+ * @experimental
26
+ */
27
+ import { Data } from 'effect'
28
+ import type * as Schema from 'effect/Schema'
29
+ import { withSubscriptionUsage } from './emulator-compose.ts'
30
+ import type {
31
+ EmulatorCoverage,
32
+ EmulatorFaultState,
33
+ EmulatorRouteCoverage
34
+ } from './emulator-kernel.ts'
35
+ import { EmulatorFaultMatch, EmulatorScriptedError } from './emulator-kernel.ts'
36
+ import {
37
+ makeResponsesEmulator,
38
+ ResponsesErrorEventFault,
39
+ ResponsesFault,
40
+ ResponsesScriptedFunctionCall,
41
+ ResponsesScriptedResponse,
42
+ ResponsesScriptedTurn,
43
+ ResponsesScriptedUsage,
44
+ ResponsesStreamError,
45
+ type ResponsesEmulator,
46
+ type ResponsesFaultKind,
47
+ type ResponsesLedgerEntry,
48
+ type ResponsesWireError
49
+ } from './responses.ts'
50
+ import type { EmulatorRouteEvidence } from './route-evidence.ts'
51
+ import {
52
+ makeSubscriptionUsageEmulator,
53
+ recordedUsageBody,
54
+ SubscriptionUsageFault,
55
+ type SubscriptionUsageEmulator,
56
+ type SubscriptionUsageLedgerEntry,
57
+ type SubscriptionUsageScriptedTurn
58
+ } from './subscription-usage.ts'
59
+ import { codexUsageRecording } from './subscription-usage-recordings.ts'
60
+
61
+ export type { EmulatorEvidence, EmulatorRouteEvidence } from './route-evidence.ts'
62
+
63
+ export { emulatorEvidenceHeader } from './route-evidence.ts'
64
+
65
+ export const codexResponsesPath = '/backend-api/codex/responses'
66
+
67
+ /** The Codex subscription-usage path (`openAiCodexSubscriptionUsageUrl` in the SDK). */
68
+ export const codexSubscriptionUsagePath = '/backend-api/wham/usage'
69
+
70
+ /**
71
+ * Route evidence manifest of the Codex subscription-usage route (served by the same fetch handler
72
+ * as the Responses route, with its own ledger and coverage). Synthetic, unverified.
73
+ */
74
+ export const codexSubscriptionUsageEmulatorRoutes: ReadonlyArray<EmulatorRouteEvidence> = [
75
+ {
76
+ method: 'GET',
77
+ path: codexSubscriptionUsagePath,
78
+ kind: 'provider',
79
+ write: false,
80
+ caseIds: ['openai.codex.usage.snapshot'],
81
+ evidence: 'unverified',
82
+ observedAt: undefined
83
+ }
84
+ ]
85
+
86
+ /**
87
+ * The recorded Codex usage body (the synthetic `openai.codex.usage.snapshot` fixture, copied as
88
+ * data): `rate_limit.primary_window` and `secondary_window` as
89
+ * `{ used_percent, limit_window_seconds, reset_after_seconds, reset_at }`.
90
+ */
91
+ export const codexSubscriptionUsageDefault: Schema.Json = recordedUsageBody(codexUsageRecording)
92
+
93
+ /** Synthetic-safe default model ids, including the Codex conformance defaults. */
94
+ export const codexEmulatorDefaultModels: ReadonlyArray<string> = ['gpt-5.4', 'gpt-5.5']
95
+
96
+ /**
97
+ * Route evidence manifest: every emulated Codex route and the conformance cases whose (currently
98
+ * synthetic, unverified) wire shapes it follows.
99
+ */
100
+ export const codexEmulatorRoutes: ReadonlyArray<EmulatorRouteEvidence> = [
101
+ {
102
+ method: 'POST',
103
+ path: codexResponsesPath,
104
+ kind: 'provider',
105
+ write: false,
106
+ caseIds: [
107
+ 'openai.codex.stream.plain-text',
108
+ 'openai.codex.stream.function-call-arguments',
109
+ 'openai.codex.stream.error-envelope',
110
+ 'openai.codex.stream.terminal-event'
111
+ ],
112
+ evidence: 'unverified',
113
+ observedAt: undefined
114
+ }
115
+ ]
116
+
117
+ /** Optional fault filter; an omitted field matches every request. `path` ending in `*` is a prefix. */
118
+ export const CodexFaultMatch = EmulatorFaultMatch
119
+
120
+ export type CodexFaultMatch = typeof EmulatorFaultMatch.Type
121
+
122
+ /** A mid-stream Responses error (`{ code, message }`). */
123
+ export const CodexStreamError = ResponsesStreamError
124
+
125
+ export type CodexStreamError = ResponsesStreamError
126
+
127
+ /** A mid-stream `error` or `response.failed` event fault, streamed responses only. */
128
+ export const CodexErrorEventFault = ResponsesErrorEventFault
129
+
130
+ export type CodexErrorEventFault = typeof ResponsesErrorEventFault.Type
131
+
132
+ /**
133
+ * Wire faults:
134
+ *
135
+ * - `status`: answer with this status, headers, and body (for example 429 with `retry-after`).
136
+ * The body defaults to the OpenAI error envelope for the status.
137
+ * - `error-after-chunks`: send N body chunks, then error the body stream (a dropped connection).
138
+ * - `truncate-after-chunks`: send N body chunks, then close cleanly (no `response.completed`).
139
+ * - `error-event-after-chunks`: send N SSE events, then one `error` (default) or
140
+ * `response.failed` event and close.
141
+ *
142
+ * Statuses that cannot carry a body and redirects are rejected, as are invalid headers and
143
+ * `location`. A fault that cannot take effect answers 500 and is not consumed.
144
+ */
145
+ export const CodexFault = ResponsesFault
146
+
147
+ export type CodexFault = ResponsesFault
148
+
149
+ export type CodexFaultKind = ResponsesFaultKind
150
+
151
+ /** Usage for a scripted turn (sent in `response.completed` or the JSON body). */
152
+ export const CodexScriptedUsage = ResponsesScriptedUsage
153
+
154
+ export type CodexScriptedUsage = ResponsesScriptedUsage
155
+
156
+ /** One scripted `function_call` item; its arguments stream as these fragments. */
157
+ export const CodexScriptedFunctionCall = ResponsesScriptedFunctionCall
158
+
159
+ export type CodexScriptedFunctionCall = ResponsesScriptedFunctionCall
160
+
161
+ /**
162
+ * A scripted response: `reasoning` (summary fragments), `text`, `functionCalls`, `order`,
163
+ * `usage` (`null` drops it), and `format` (`sse` or `json`, default: the request's `stream`).
164
+ */
165
+ export const CodexScriptedResponse = ResponsesScriptedResponse
166
+
167
+ export type CodexScriptedResponse = ResponsesScriptedResponse
168
+
169
+ /** A scripted error response: status, body (a string is sent as is), and optional headers. */
170
+ export const CodexScriptedError = EmulatorScriptedError
171
+
172
+ export type CodexScriptedError = typeof EmulatorScriptedError.Type
173
+
174
+ /** A turn queued for the next Codex request. */
175
+ export const CodexScriptedTurn = ResponsesScriptedTurn
176
+
177
+ export type CodexScriptedTurn = ResponsesScriptedTurn
178
+
179
+ /** Thrown by the JS API (`faults.add`, `script.enqueue`) for invalid input; a programmer error. */
180
+ export class CodexEmulatorInputInvalid extends Data.TaggedError('CodexEmulatorInputInvalid')<{
181
+ readonly input: 'fault' | 'turn'
182
+ readonly reason: string
183
+ }> {
184
+ override get message(): string {
185
+ return `Invalid Codex emulator ${this.input}: ${this.reason}`
186
+ }
187
+ }
188
+
189
+ export type CodexLedgerEntry = ResponsesLedgerEntry
190
+
191
+ export type CodexFaultState = EmulatorFaultState<CodexFault>
192
+
193
+ export type CodexRouteCoverage = EmulatorRouteCoverage
194
+
195
+ export type CodexCoverage = EmulatorCoverage
196
+
197
+ /** A usage-route fault (`status`, `error-after-chunks`, `truncate-after-chunks`). */
198
+ export const CodexUsageFault = SubscriptionUsageFault
199
+
200
+ export type CodexUsageFault = SubscriptionUsageFault
201
+
202
+ /** A usage turn: `{ usage }` (a body with the recorded JSON shape) or `{ error }`. */
203
+ export type CodexUsageScriptedTurn = SubscriptionUsageScriptedTurn
204
+
205
+ export type CodexUsageLedgerEntry = SubscriptionUsageLedgerEntry
206
+
207
+ export type CodexUsageEmulator = SubscriptionUsageEmulator
208
+
209
+ export type CodexEmulatorOptions = {
210
+ /** Model ids that exist. Defaults to `codexEmulatorDefaultModels`. */
211
+ readonly knownModels?: ReadonlyArray<string>
212
+ /**
213
+ * Replacement usage-route body; must have the recorded JSON shape (same keys and value kinds).
214
+ * Defaults to the recorded body (`codexSubscriptionUsageDefault`).
215
+ */
216
+ readonly subscriptionUsage?: Schema.Json
217
+ }
218
+
219
+ /** The Responses emulator, plus `usage`: the subscription-usage route's own emulator API. */
220
+ export type CodexEmulator = ResponsesEmulator & { readonly usage: CodexUsageEmulator }
221
+
222
+ const openAiErrorEnvelope = (error: ResponsesWireError): Schema.Json => ({
223
+ error: {
224
+ message: error.message,
225
+ type: error.type,
226
+ param: error.param ?? null,
227
+ code: error.code
228
+ }
229
+ })
230
+
231
+ /**
232
+ * Create a Codex Responses emulator. Each call has independent ledger, fault, and script state.
233
+ *
234
+ * Without a script, `POST /backend-api/codex/responses` answers a known model with synthetic
235
+ * output: `stream: true` streams `response.created`, `response.in_progress`, the output items
236
+ * (`response.output_item.added`, their parts and deltas, `response.output_item.done`), and
237
+ * `response.completed` with usage; `stream: false` returns one `response` JSON body. A request
238
+ * whose `reasoning` asks for a `summary` (the Codex provider always does) gets a reasoning item
239
+ * first. A request with function `tools` gets one `function_call` item whose arguments are
240
+ * synthesized from the tool's JSON Schema and streamed as `response.function_call_arguments.delta`
241
+ * fragments; `tool_choice: { type: 'function', name }` picks that tool (otherwise the first) and
242
+ * `tool_choice: 'none'` answers with text. Unknown models get 400 `model_not_found`; a request
243
+ * without a bearer credential gets 401 `invalid_api_key`; `max_output_tokens` gets 400
244
+ * `unsupported_parameter`; unknown routes get a 404 envelope. Not enforced: `store: false`,
245
+ * `stream: true`, `instructions`, `originator`, and `ChatGPT-Account-Id`.
246
+ *
247
+ * `GET /backend-api/wham/usage` is fixture-only: a request with a non-empty bearer credential and
248
+ * a non-empty `ChatGPT-Account-Id` (neither checked or recorded), `accept: application/json`, and
249
+ * no query gets the recorded body (`codexSubscriptionUsageDefault`, or a same-shaped
250
+ * `options.subscriptionUsage` / scripted `{ usage }`); anything else answers 400 not-emulated.
251
+ * Its ledger, faults, turns, and coverage are `emulator.usage` (control plane
252
+ * `/_emulate/usage/*`); `reset()` and `POST /_emulate/reset` reset both routes.
253
+ */
254
+ export const makeCodexEmulator = (options: CodexEmulatorOptions = {}): CodexEmulator =>
255
+ withSubscriptionUsage(
256
+ makeCodexResponsesEmulator(options),
257
+ makeCodexUsageEmulator(options),
258
+ codexSubscriptionUsagePath
259
+ )
260
+
261
+ const makeCodexUsageEmulator = (options: CodexEmulatorOptions): CodexUsageEmulator =>
262
+ makeSubscriptionUsageEmulator({
263
+ path: codexSubscriptionUsagePath,
264
+ routes: codexSubscriptionUsageEmulatorRoutes,
265
+ recording: codexUsageRecording,
266
+ headers: [{ name: 'chatgpt-account-id', record: false }],
267
+ subscriptionUsage: options.subscriptionUsage,
268
+ inputInvalid: (input, reason) => new CodexEmulatorInputInvalid({ input, reason })
269
+ })
270
+
271
+ const makeCodexResponsesEmulator = (options: CodexEmulatorOptions): ResponsesEmulator =>
272
+ makeResponsesEmulator({
273
+ path: codexResponsesPath,
274
+ routes: codexEmulatorRoutes,
275
+ knownModels: options.knownModels ?? codexEmulatorDefaultModels,
276
+ errorEnvelope: openAiErrorEnvelope,
277
+ // Copied data shape of the synthetic Codex error-envelope fixture (unknown model id).
278
+ unknownModel: {
279
+ status: 400,
280
+ error: {
281
+ message: 'Synthetic placeholder: the requested model is not supported.',
282
+ type: 'invalid_request_error',
283
+ code: 'model_not_found',
284
+ param: 'model'
285
+ }
286
+ },
287
+ unauthorized: {
288
+ message: 'Synthetic: missing or invalid bearer credential.',
289
+ type: 'invalid_request_error',
290
+ code: 'invalid_api_key'
291
+ },
292
+ headers: [{ name: 'originator', record: true }],
293
+ outputTokenLimit: 'rejected',
294
+ defaultText: ['Hello', ' from the', ' synthetic Codex emulator.'],
295
+ inputInvalid: (input, reason) => new CodexEmulatorInputInvalid({ input, reason })
296
+ })