@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.
- package/LICENSE +21 -0
- package/README.md +2135 -0
- package/dist/anthropic.d.mts +269 -0
- package/dist/anthropic.d.mts.map +1 -0
- package/dist/anthropic.mjs +177 -0
- package/dist/anthropic.mjs.map +1 -0
- package/dist/chat-completions.d.mts +288 -0
- package/dist/chat-completions.d.mts.map +1 -0
- package/dist/chat-completions.mjs +451 -0
- package/dist/chat-completions.mjs.map +1 -0
- package/dist/codex.d.mts +265 -0
- package/dist/codex.d.mts.map +1 -0
- package/dist/codex.mjs +199 -0
- package/dist/codex.mjs.map +1 -0
- package/dist/dropbox/api.d.mts +63 -0
- package/dist/dropbox/api.d.mts.map +1 -0
- package/dist/dropbox/api.mjs +565 -0
- package/dist/dropbox/api.mjs.map +1 -0
- package/dist/dropbox/state.d.mts +136 -0
- package/dist/dropbox/state.d.mts.map +1 -0
- package/dist/dropbox/state.mjs +209 -0
- package/dist/dropbox/state.mjs.map +1 -0
- package/dist/dropbox.d.mts +79 -0
- package/dist/dropbox.d.mts.map +1 -0
- package/dist/dropbox.mjs +124 -0
- package/dist/dropbox.mjs.map +1 -0
- package/dist/email-fixtures.d.mts +36 -0
- package/dist/email-fixtures.d.mts.map +1 -0
- package/dist/email-fixtures.mjs +1080 -0
- package/dist/email-fixtures.mjs.map +1 -0
- package/dist/email.d.mts +160 -0
- package/dist/email.d.mts.map +1 -0
- package/dist/email.mjs +608 -0
- package/dist/email.mjs.map +1 -0
- package/dist/emulator-compose.d.mts +40 -0
- package/dist/emulator-compose.d.mts.map +1 -0
- package/dist/emulator-compose.mjs +91 -0
- package/dist/emulator-compose.mjs.map +1 -0
- package/dist/emulator-http.d.mts +53 -0
- package/dist/emulator-http.d.mts.map +1 -0
- package/dist/emulator-http.mjs +117 -0
- package/dist/emulator-http.mjs.map +1 -0
- package/dist/emulator-kernel.d.mts +176 -0
- package/dist/emulator-kernel.d.mts.map +1 -0
- package/dist/emulator-kernel.mjs +413 -0
- package/dist/emulator-kernel.mjs.map +1 -0
- package/dist/fixture-route.d.mts +129 -0
- package/dist/fixture-route.d.mts.map +1 -0
- package/dist/fixture-route.mjs +257 -0
- package/dist/fixture-route.mjs.map +1 -0
- package/dist/fortnox/api.d.mts +92 -0
- package/dist/fortnox/api.d.mts.map +1 -0
- package/dist/fortnox/api.mjs +750 -0
- package/dist/fortnox/api.mjs.map +1 -0
- package/dist/fortnox/state.d.mts +533 -0
- package/dist/fortnox/state.d.mts.map +1 -0
- package/dist/fortnox/state.mjs +612 -0
- package/dist/fortnox/state.mjs.map +1 -0
- package/dist/fortnox.d.mts +128 -0
- package/dist/fortnox.d.mts.map +1 -0
- package/dist/fortnox.mjs +403 -0
- package/dist/fortnox.mjs.map +1 -0
- package/dist/gateway-evaluate-recordings.d.mts +12 -0
- package/dist/gateway-evaluate-recordings.d.mts.map +1 -0
- package/dist/gateway-evaluate-recordings.mjs +128 -0
- package/dist/gateway-evaluate-recordings.mjs.map +1 -0
- package/dist/gateway.d.mts +272 -0
- package/dist/gateway.d.mts.map +1 -0
- package/dist/gateway.mjs +400 -0
- package/dist/gateway.mjs.map +1 -0
- package/dist/github/api.d.mts +63 -0
- package/dist/github/api.d.mts.map +1 -0
- package/dist/github/api.mjs +527 -0
- package/dist/github/api.mjs.map +1 -0
- package/dist/github/state.d.mts +272 -0
- package/dist/github/state.d.mts.map +1 -0
- package/dist/github/state.mjs +303 -0
- package/dist/github/state.mjs.map +1 -0
- package/dist/github.d.mts +77 -0
- package/dist/github.d.mts.map +1 -0
- package/dist/github.mjs +180 -0
- package/dist/github.mjs.map +1 -0
- package/dist/google/calendar.d.mts +10 -0
- package/dist/google/calendar.d.mts.map +1 -0
- package/dist/google/calendar.mjs +252 -0
- package/dist/google/calendar.mjs.map +1 -0
- package/dist/google/drive.d.mts +8 -0
- package/dist/google/drive.d.mts.map +1 -0
- package/dist/google/drive.mjs +252 -0
- package/dist/google/drive.mjs.map +1 -0
- package/dist/google/gmail.d.mts +10 -0
- package/dist/google/gmail.d.mts.map +1 -0
- package/dist/google/gmail.mjs +591 -0
- package/dist/google/gmail.mjs.map +1 -0
- package/dist/google/shared.d.mts +107 -0
- package/dist/google/shared.d.mts.map +1 -0
- package/dist/google/shared.mjs +146 -0
- package/dist/google/shared.mjs.map +1 -0
- package/dist/google/state.d.mts +385 -0
- package/dist/google/state.d.mts.map +1 -0
- package/dist/google/state.mjs +496 -0
- package/dist/google/state.mjs.map +1 -0
- package/dist/google.d.mts +75 -0
- package/dist/google.d.mts.map +1 -0
- package/dist/google.mjs +210 -0
- package/dist/google.mjs.map +1 -0
- package/dist/linkedin-search/api.d.mts +45 -0
- package/dist/linkedin-search/api.d.mts.map +1 -0
- package/dist/linkedin-search/api.mjs +181 -0
- package/dist/linkedin-search/api.mjs.map +1 -0
- package/dist/linkedin-search/state.d.mts +123 -0
- package/dist/linkedin-search/state.d.mts.map +1 -0
- package/dist/linkedin-search/state.mjs +261 -0
- package/dist/linkedin-search/state.mjs.map +1 -0
- package/dist/linkedin-search.d.mts +69 -0
- package/dist/linkedin-search.d.mts.map +1 -0
- package/dist/linkedin-search.mjs +158 -0
- package/dist/linkedin-search.mjs.map +1 -0
- package/dist/mcp/api.d.mts +44 -0
- package/dist/mcp/api.d.mts.map +1 -0
- package/dist/mcp/api.mjs +557 -0
- package/dist/mcp/api.mjs.map +1 -0
- package/dist/mcp/recordings.d.mts +40 -0
- package/dist/mcp/recordings.d.mts.map +1 -0
- package/dist/mcp/recordings.mjs +2390 -0
- package/dist/mcp/recordings.mjs.map +1 -0
- package/dist/mcp/state.d.mts +71 -0
- package/dist/mcp/state.d.mts.map +1 -0
- package/dist/mcp/state.mjs +83 -0
- package/dist/mcp/state.mjs.map +1 -0
- package/dist/mcp.d.mts +84 -0
- package/dist/mcp.d.mts.map +1 -0
- package/dist/mcp.mjs +241 -0
- package/dist/mcp.mjs.map +1 -0
- package/dist/messages.d.mts +183 -0
- package/dist/messages.d.mts.map +1 -0
- package/dist/messages.mjs +532 -0
- package/dist/messages.mjs.map +1 -0
- package/dist/microsoft/api.d.mts +47 -0
- package/dist/microsoft/api.d.mts.map +1 -0
- package/dist/microsoft/api.mjs +178 -0
- package/dist/microsoft/api.mjs.map +1 -0
- package/dist/microsoft/calendar.d.mts +30 -0
- package/dist/microsoft/calendar.d.mts.map +1 -0
- package/dist/microsoft/calendar.mjs +271 -0
- package/dist/microsoft/calendar.mjs.map +1 -0
- package/dist/microsoft/drive.d.mts +36 -0
- package/dist/microsoft/drive.d.mts.map +1 -0
- package/dist/microsoft/drive.mjs +298 -0
- package/dist/microsoft/drive.mjs.map +1 -0
- package/dist/microsoft/graph.d.mts +198 -0
- package/dist/microsoft/graph.d.mts.map +1 -0
- package/dist/microsoft/graph.mjs +264 -0
- package/dist/microsoft/graph.mjs.map +1 -0
- package/dist/microsoft/mail.d.mts +48 -0
- package/dist/microsoft/mail.d.mts.map +1 -0
- package/dist/microsoft/mail.mjs +488 -0
- package/dist/microsoft/mail.mjs.map +1 -0
- package/dist/microsoft/state.d.mts +480 -0
- package/dist/microsoft/state.d.mts.map +1 -0
- package/dist/microsoft/state.mjs +625 -0
- package/dist/microsoft/state.mjs.map +1 -0
- package/dist/microsoft.d.mts +168 -0
- package/dist/microsoft.d.mts.map +1 -0
- package/dist/microsoft.mjs +483 -0
- package/dist/microsoft.mjs.map +1 -0
- package/dist/node.d.mts +47 -0
- package/dist/node.d.mts.map +1 -0
- package/dist/node.mjs +178 -0
- package/dist/node.mjs.map +1 -0
- package/dist/notion/api.d.mts +51 -0
- package/dist/notion/api.d.mts.map +1 -0
- package/dist/notion/api.mjs +507 -0
- package/dist/notion/api.mjs.map +1 -0
- package/dist/notion/state.d.mts +329 -0
- package/dist/notion/state.d.mts.map +1 -0
- package/dist/notion/state.mjs +432 -0
- package/dist/notion/state.mjs.map +1 -0
- package/dist/notion.d.mts +72 -0
- package/dist/notion.d.mts.map +1 -0
- package/dist/notion.mjs +127 -0
- package/dist/notion.mjs.map +1 -0
- package/dist/openai.d.mts +165 -0
- package/dist/openai.d.mts.map +1 -0
- package/dist/openai.mjs +141 -0
- package/dist/openai.mjs.map +1 -0
- package/dist/opencode-recordings.d.mts +7 -0
- package/dist/opencode-recordings.d.mts.map +1 -0
- package/dist/opencode-recordings.mjs +222 -0
- package/dist/opencode-recordings.mjs.map +1 -0
- package/dist/opencode.d.mts +70 -0
- package/dist/opencode.d.mts.map +1 -0
- package/dist/opencode.mjs +217 -0
- package/dist/opencode.mjs.map +1 -0
- package/dist/r2-fixtures.d.mts +36 -0
- package/dist/r2-fixtures.d.mts.map +1 -0
- package/dist/r2-fixtures.mjs +245 -0
- package/dist/r2-fixtures.mjs.map +1 -0
- package/dist/r2-guard.d.mts +43 -0
- package/dist/r2-guard.d.mts.map +1 -0
- package/dist/r2-guard.mjs +215 -0
- package/dist/r2-guard.mjs.map +1 -0
- package/dist/r2.d.mts +166 -0
- package/dist/r2.d.mts.map +1 -0
- package/dist/r2.mjs +517 -0
- package/dist/r2.mjs.map +1 -0
- package/dist/responses.d.mts +231 -0
- package/dist/responses.d.mts.map +1 -0
- package/dist/responses.mjs +556 -0
- package/dist/responses.mjs.map +1 -0
- package/dist/route-evidence.d.mts +45 -0
- package/dist/route-evidence.d.mts.map +1 -0
- package/dist/route-evidence.mjs +56 -0
- package/dist/route-evidence.mjs.map +1 -0
- package/dist/router.d.mts +93 -0
- package/dist/router.d.mts.map +1 -0
- package/dist/router.mjs +259 -0
- package/dist/router.mjs.map +1 -0
- package/dist/stateful-core.d.mts +17 -0
- package/dist/stateful-core.d.mts.map +1 -0
- package/dist/stateful-core.mjs +41 -0
- package/dist/stateful-core.mjs.map +1 -0
- package/dist/stateful-emulator.d.mts +565 -0
- package/dist/stateful-emulator.d.mts.map +1 -0
- package/dist/stateful-emulator.mjs +1228 -0
- package/dist/stateful-emulator.mjs.map +1 -0
- package/dist/stateful-secrets.d.mts +84 -0
- package/dist/stateful-secrets.d.mts.map +1 -0
- package/dist/stateful-secrets.mjs +216 -0
- package/dist/stateful-secrets.mjs.map +1 -0
- package/dist/subscription-usage-recordings.d.mts +9 -0
- package/dist/subscription-usage-recordings.d.mts.map +1 -0
- package/dist/subscription-usage-recordings.mjs +53 -0
- package/dist/subscription-usage-recordings.mjs.map +1 -0
- package/dist/subscription-usage.d.mts +53 -0
- package/dist/subscription-usage.d.mts.map +1 -0
- package/dist/subscription-usage.mjs +21 -0
- package/dist/subscription-usage.mjs.map +1 -0
- package/dist/telegram/api.d.mts +34 -0
- package/dist/telegram/api.d.mts.map +1 -0
- package/dist/telegram/api.mjs +257 -0
- package/dist/telegram/api.mjs.map +1 -0
- package/dist/telegram/state.d.mts +128 -0
- package/dist/telegram/state.d.mts.map +1 -0
- package/dist/telegram/state.mjs +154 -0
- package/dist/telegram/state.mjs.map +1 -0
- package/dist/telegram.d.mts +62 -0
- package/dist/telegram.d.mts.map +1 -0
- package/dist/telegram.mjs +127 -0
- package/dist/telegram.mjs.map +1 -0
- package/dist/todoist/api.d.mts +55 -0
- package/dist/todoist/api.d.mts.map +1 -0
- package/dist/todoist/api.mjs +415 -0
- package/dist/todoist/api.mjs.map +1 -0
- package/dist/todoist/state.d.mts +275 -0
- package/dist/todoist/state.d.mts.map +1 -0
- package/dist/todoist/state.mjs +345 -0
- package/dist/todoist/state.mjs.map +1 -0
- package/dist/todoist.d.mts +68 -0
- package/dist/todoist.d.mts.map +1 -0
- package/dist/todoist.mjs +181 -0
- package/dist/todoist.mjs.map +1 -0
- package/dist/xai.d.mts +267 -0
- package/dist/xai.d.mts.map +1 -0
- package/dist/xai.mjs +252 -0
- package/dist/xai.mjs.map +1 -0
- package/package.json +157 -0
- package/src/anthropic.ts +289 -0
- package/src/chat-completions.ts +924 -0
- package/src/codex.ts +296 -0
- package/src/dropbox/api.ts +1084 -0
- package/src/dropbox/state.ts +364 -0
- package/src/dropbox.ts +203 -0
- package/src/email-fixtures.ts +1297 -0
- package/src/email.ts +1108 -0
- package/src/emulator-compose.ts +147 -0
- package/src/emulator-http.ts +184 -0
- package/src/emulator-kernel.ts +844 -0
- package/src/fixture-route.ts +561 -0
- package/src/fortnox/api.ts +1352 -0
- package/src/fortnox/state.ts +798 -0
- package/src/fortnox.ts +801 -0
- package/src/gateway-evaluate-recordings.ts +153 -0
- package/src/gateway.ts +530 -0
- package/src/github/api.ts +986 -0
- package/src/github/state.ts +439 -0
- package/src/github.ts +271 -0
- package/src/google/calendar.ts +486 -0
- package/src/google/drive.ts +471 -0
- package/src/google/gmail.ts +1011 -0
- package/src/google/shared.ts +321 -0
- package/src/google/state.ts +686 -0
- package/src/google.ts +298 -0
- package/src/linkedin-search/api.ts +363 -0
- package/src/linkedin-search/state.ts +373 -0
- package/src/linkedin-search.ts +241 -0
- package/src/mcp/api.ts +995 -0
- package/src/mcp/recordings.ts +2665 -0
- package/src/mcp/state.ts +125 -0
- package/src/mcp.ts +319 -0
- package/src/messages.ts +844 -0
- package/src/microsoft/api.ts +426 -0
- package/src/microsoft/calendar.ts +491 -0
- package/src/microsoft/drive.ts +541 -0
- package/src/microsoft/graph.ts +550 -0
- package/src/microsoft/mail.ts +833 -0
- package/src/microsoft/state.ts +822 -0
- package/src/microsoft.ts +982 -0
- package/src/node.ts +293 -0
- package/src/notion/api.ts +976 -0
- package/src/notion/state.ts +512 -0
- package/src/notion.ts +210 -0
- package/src/openai.ts +198 -0
- package/src/opencode-recordings.ts +257 -0
- package/src/opencode.ts +271 -0
- package/src/r2-fixtures.ts +295 -0
- package/src/r2-guard.ts +323 -0
- package/src/r2.ts +890 -0
- package/src/responses.ts +901 -0
- package/src/route-evidence.ts +90 -0
- package/src/router.ts +490 -0
- package/src/stateful-core.ts +70 -0
- package/src/stateful-emulator.ts +2571 -0
- package/src/stateful-secrets.ts +299 -0
- package/src/subscription-usage-recordings.ts +77 -0
- package/src/subscription-usage.ts +68 -0
- package/src/telegram/api.ts +437 -0
- package/src/telegram/state.ts +229 -0
- package/src/telegram.ts +227 -0
- package/src/todoist/api.ts +736 -0
- package/src/todoist/state.ts +456 -0
- package/src/todoist.ts +316 -0
- 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
|
+
})
|