@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/dist/codex.d.mts
ADDED
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
import { EmulatorEvidence, EmulatorRouteEvidence, emulatorEvidenceHeader } from "./route-evidence.mjs";
|
|
2
|
+
import { EmulatorCoverage, EmulatorFaultMatch, EmulatorFaultState, EmulatorRouteCoverage, EmulatorScriptedError } from "./emulator-kernel.mjs";
|
|
3
|
+
import { SubscriptionUsageEmulator, SubscriptionUsageFault, SubscriptionUsageLedgerEntry, SubscriptionUsageScriptedTurn } from "./subscription-usage.mjs";
|
|
4
|
+
import { ResponsesEmulator, ResponsesErrorEventFault, ResponsesFault, ResponsesFaultKind, ResponsesLedgerEntry, ResponsesScriptedFunctionCall, ResponsesScriptedResponse, ResponsesScriptedTurn, ResponsesScriptedUsage, ResponsesStreamError } from "./responses.mjs";
|
|
5
|
+
import * as Schema from "effect/Schema";
|
|
6
|
+
|
|
7
|
+
//#region src/codex.d.ts
|
|
8
|
+
declare const codexResponsesPath = "/backend-api/codex/responses";
|
|
9
|
+
/** The Codex subscription-usage path (`openAiCodexSubscriptionUsageUrl` in the SDK). */
|
|
10
|
+
declare const codexSubscriptionUsagePath = "/backend-api/wham/usage";
|
|
11
|
+
/**
|
|
12
|
+
* Route evidence manifest of the Codex subscription-usage route (served by the same fetch handler
|
|
13
|
+
* as the Responses route, with its own ledger and coverage). Synthetic, unverified.
|
|
14
|
+
*/
|
|
15
|
+
declare const codexSubscriptionUsageEmulatorRoutes: ReadonlyArray<EmulatorRouteEvidence>;
|
|
16
|
+
/**
|
|
17
|
+
* The recorded Codex usage body (the synthetic `openai.codex.usage.snapshot` fixture, copied as
|
|
18
|
+
* data): `rate_limit.primary_window` and `secondary_window` as
|
|
19
|
+
* `{ used_percent, limit_window_seconds, reset_after_seconds, reset_at }`.
|
|
20
|
+
*/
|
|
21
|
+
declare const codexSubscriptionUsageDefault: Schema.Json;
|
|
22
|
+
/** Synthetic-safe default model ids, including the Codex conformance defaults. */
|
|
23
|
+
declare const codexEmulatorDefaultModels: ReadonlyArray<string>;
|
|
24
|
+
/**
|
|
25
|
+
* Route evidence manifest: every emulated Codex route and the conformance cases whose (currently
|
|
26
|
+
* synthetic, unverified) wire shapes it follows.
|
|
27
|
+
*/
|
|
28
|
+
declare const codexEmulatorRoutes: ReadonlyArray<EmulatorRouteEvidence>;
|
|
29
|
+
/** Optional fault filter; an omitted field matches every request. `path` ending in `*` is a prefix. */
|
|
30
|
+
declare const CodexFaultMatch: Schema.Struct<{
|
|
31
|
+
readonly path: Schema.optionalKey<Schema.String>;
|
|
32
|
+
readonly model: Schema.optionalKey<Schema.String>;
|
|
33
|
+
}>;
|
|
34
|
+
type CodexFaultMatch = typeof EmulatorFaultMatch.Type;
|
|
35
|
+
/** A mid-stream Responses error (`{ code, message }`). */
|
|
36
|
+
declare const CodexStreamError: Schema.Struct<{
|
|
37
|
+
readonly code: Schema.NonEmptyString;
|
|
38
|
+
readonly message: Schema.String;
|
|
39
|
+
}>;
|
|
40
|
+
type CodexStreamError = ResponsesStreamError;
|
|
41
|
+
/** A mid-stream `error` or `response.failed` event fault, streamed responses only. */
|
|
42
|
+
declare const CodexErrorEventFault: Schema.Struct<{
|
|
43
|
+
readonly match: Schema.optionalKey<Schema.Struct<{
|
|
44
|
+
readonly path: Schema.optionalKey<Schema.String>;
|
|
45
|
+
readonly model: Schema.optionalKey<Schema.String>;
|
|
46
|
+
}>>;
|
|
47
|
+
readonly count: Schema.optionalKey<Schema.Int>;
|
|
48
|
+
readonly kind: Schema.Literal<"error-event-after-chunks">;
|
|
49
|
+
readonly chunks: Schema.Int;
|
|
50
|
+
readonly event: Schema.optionalKey<Schema.Literals<readonly ["error", "response.failed"]>>;
|
|
51
|
+
readonly error: Schema.optionalKey<Schema.Struct<{
|
|
52
|
+
readonly code: Schema.NonEmptyString;
|
|
53
|
+
readonly message: Schema.String;
|
|
54
|
+
}>>;
|
|
55
|
+
}>;
|
|
56
|
+
type CodexErrorEventFault = typeof ResponsesErrorEventFault.Type;
|
|
57
|
+
/**
|
|
58
|
+
* Wire faults:
|
|
59
|
+
*
|
|
60
|
+
* - `status`: answer with this status, headers, and body (for example 429 with `retry-after`).
|
|
61
|
+
* The body defaults to the OpenAI error envelope for the status.
|
|
62
|
+
* - `error-after-chunks`: send N body chunks, then error the body stream (a dropped connection).
|
|
63
|
+
* - `truncate-after-chunks`: send N body chunks, then close cleanly (no `response.completed`).
|
|
64
|
+
* - `error-event-after-chunks`: send N SSE events, then one `error` (default) or
|
|
65
|
+
* `response.failed` event and close.
|
|
66
|
+
*
|
|
67
|
+
* Statuses that cannot carry a body and redirects are rejected, as are invalid headers and
|
|
68
|
+
* `location`. A fault that cannot take effect answers 500 and is not consumed.
|
|
69
|
+
*/
|
|
70
|
+
declare const CodexFault: Schema.Union<readonly [Schema.Struct<{
|
|
71
|
+
readonly match: Schema.optionalKey<Schema.Struct<{
|
|
72
|
+
readonly path: Schema.optionalKey<Schema.String>;
|
|
73
|
+
readonly model: Schema.optionalKey<Schema.String>;
|
|
74
|
+
}>>;
|
|
75
|
+
readonly count: Schema.optionalKey<Schema.Int>;
|
|
76
|
+
readonly kind: Schema.Literal<"status">;
|
|
77
|
+
readonly status: Schema.Int;
|
|
78
|
+
readonly headers: Schema.optionalKey<Schema.$Record<Schema.String, Schema.String>>;
|
|
79
|
+
readonly body: Schema.optionalKey<Schema.Codec<Schema.Json, Schema.Json, never, never>>;
|
|
80
|
+
}>, Schema.Struct<{
|
|
81
|
+
readonly match: Schema.optionalKey<Schema.Struct<{
|
|
82
|
+
readonly path: Schema.optionalKey<Schema.String>;
|
|
83
|
+
readonly model: Schema.optionalKey<Schema.String>;
|
|
84
|
+
}>>;
|
|
85
|
+
readonly count: Schema.optionalKey<Schema.Int>;
|
|
86
|
+
readonly kind: Schema.Literal<"error-after-chunks">;
|
|
87
|
+
readonly chunks: Schema.Int;
|
|
88
|
+
}>, Schema.Struct<{
|
|
89
|
+
readonly match: Schema.optionalKey<Schema.Struct<{
|
|
90
|
+
readonly path: Schema.optionalKey<Schema.String>;
|
|
91
|
+
readonly model: Schema.optionalKey<Schema.String>;
|
|
92
|
+
}>>;
|
|
93
|
+
readonly count: Schema.optionalKey<Schema.Int>;
|
|
94
|
+
readonly kind: Schema.Literal<"truncate-after-chunks">;
|
|
95
|
+
readonly chunks: Schema.Int;
|
|
96
|
+
}>, Schema.Struct<{
|
|
97
|
+
readonly match: Schema.optionalKey<Schema.Struct<{
|
|
98
|
+
readonly path: Schema.optionalKey<Schema.String>;
|
|
99
|
+
readonly model: Schema.optionalKey<Schema.String>;
|
|
100
|
+
}>>;
|
|
101
|
+
readonly count: Schema.optionalKey<Schema.Int>;
|
|
102
|
+
readonly kind: Schema.Literal<"error-event-after-chunks">;
|
|
103
|
+
readonly chunks: Schema.Int;
|
|
104
|
+
readonly event: Schema.optionalKey<Schema.Literals<readonly ["error", "response.failed"]>>;
|
|
105
|
+
readonly error: Schema.optionalKey<Schema.Struct<{
|
|
106
|
+
readonly code: Schema.NonEmptyString;
|
|
107
|
+
readonly message: Schema.String;
|
|
108
|
+
}>>;
|
|
109
|
+
}>]>;
|
|
110
|
+
type CodexFault = ResponsesFault;
|
|
111
|
+
type CodexFaultKind = ResponsesFaultKind;
|
|
112
|
+
/** Usage for a scripted turn (sent in `response.completed` or the JSON body). */
|
|
113
|
+
declare const CodexScriptedUsage: Schema.Struct<{
|
|
114
|
+
readonly inputTokens: Schema.Int;
|
|
115
|
+
readonly outputTokens: Schema.Int;
|
|
116
|
+
readonly reasoningTokens: Schema.optionalKey<Schema.Int>;
|
|
117
|
+
}>;
|
|
118
|
+
type CodexScriptedUsage = ResponsesScriptedUsage;
|
|
119
|
+
/** One scripted `function_call` item; its arguments stream as these fragments. */
|
|
120
|
+
declare const CodexScriptedFunctionCall: Schema.Struct<{
|
|
121
|
+
readonly name: Schema.NonEmptyString;
|
|
122
|
+
readonly argumentFragments: Schema.$Array<Schema.String>;
|
|
123
|
+
readonly callId: Schema.optionalKey<Schema.NonEmptyString>;
|
|
124
|
+
}>;
|
|
125
|
+
type CodexScriptedFunctionCall = ResponsesScriptedFunctionCall;
|
|
126
|
+
/**
|
|
127
|
+
* A scripted response: `reasoning` (summary fragments), `text`, `functionCalls`, `order`,
|
|
128
|
+
* `usage` (`null` drops it), and `format` (`sse` or `json`, default: the request's `stream`).
|
|
129
|
+
*/
|
|
130
|
+
declare const CodexScriptedResponse: Schema.Struct<{
|
|
131
|
+
readonly reasoning: Schema.optionalKey<Schema.$Array<Schema.String>>;
|
|
132
|
+
readonly text: Schema.optionalKey<Schema.$Array<Schema.String>>;
|
|
133
|
+
readonly functionCalls: Schema.optionalKey<Schema.$Array<Schema.Struct<{
|
|
134
|
+
readonly name: Schema.NonEmptyString;
|
|
135
|
+
readonly argumentFragments: Schema.$Array<Schema.String>;
|
|
136
|
+
readonly callId: Schema.optionalKey<Schema.NonEmptyString>;
|
|
137
|
+
}>>>;
|
|
138
|
+
readonly order: Schema.optionalKey<Schema.Literals<readonly ["reasoning-first", "text-first"]>>;
|
|
139
|
+
readonly usage: Schema.optionalKey<Schema.NullOr<Schema.Struct<{
|
|
140
|
+
readonly inputTokens: Schema.Int;
|
|
141
|
+
readonly outputTokens: Schema.Int;
|
|
142
|
+
readonly reasoningTokens: Schema.optionalKey<Schema.Int>;
|
|
143
|
+
}>>>;
|
|
144
|
+
readonly format: Schema.optionalKey<Schema.Literals<readonly ["sse", "json"]>>;
|
|
145
|
+
}>;
|
|
146
|
+
type CodexScriptedResponse = ResponsesScriptedResponse;
|
|
147
|
+
/** A scripted error response: status, body (a string is sent as is), and optional headers. */
|
|
148
|
+
declare const CodexScriptedError: Schema.Struct<{
|
|
149
|
+
readonly error: Schema.Struct<{
|
|
150
|
+
readonly status: Schema.Int;
|
|
151
|
+
readonly body: Schema.Codec<Schema.Json, Schema.Json, never, never>;
|
|
152
|
+
readonly headers: Schema.optionalKey<Schema.$Record<Schema.String, Schema.String>>;
|
|
153
|
+
}>;
|
|
154
|
+
}>;
|
|
155
|
+
type CodexScriptedError = typeof EmulatorScriptedError.Type;
|
|
156
|
+
/** A turn queued for the next Codex request. */
|
|
157
|
+
declare const CodexScriptedTurn: Schema.Union<readonly [Schema.Struct<{
|
|
158
|
+
readonly error: Schema.Struct<{
|
|
159
|
+
readonly status: Schema.Int;
|
|
160
|
+
readonly body: Schema.Codec<Schema.Json, Schema.Json, never, never>;
|
|
161
|
+
readonly headers: Schema.optionalKey<Schema.$Record<Schema.String, Schema.String>>;
|
|
162
|
+
}>;
|
|
163
|
+
}>, Schema.Struct<{
|
|
164
|
+
readonly reasoning: Schema.optionalKey<Schema.$Array<Schema.String>>;
|
|
165
|
+
readonly text: Schema.optionalKey<Schema.$Array<Schema.String>>;
|
|
166
|
+
readonly functionCalls: Schema.optionalKey<Schema.$Array<Schema.Struct<{
|
|
167
|
+
readonly name: Schema.NonEmptyString;
|
|
168
|
+
readonly argumentFragments: Schema.$Array<Schema.String>;
|
|
169
|
+
readonly callId: Schema.optionalKey<Schema.NonEmptyString>;
|
|
170
|
+
}>>>;
|
|
171
|
+
readonly order: Schema.optionalKey<Schema.Literals<readonly ["reasoning-first", "text-first"]>>;
|
|
172
|
+
readonly usage: Schema.optionalKey<Schema.NullOr<Schema.Struct<{
|
|
173
|
+
readonly inputTokens: Schema.Int;
|
|
174
|
+
readonly outputTokens: Schema.Int;
|
|
175
|
+
readonly reasoningTokens: Schema.optionalKey<Schema.Int>;
|
|
176
|
+
}>>>;
|
|
177
|
+
readonly format: Schema.optionalKey<Schema.Literals<readonly ["sse", "json"]>>;
|
|
178
|
+
}>]>;
|
|
179
|
+
type CodexScriptedTurn = ResponsesScriptedTurn;
|
|
180
|
+
declare const CodexEmulatorInputInvalid_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P] }>) => import("effect/Cause").YieldableError & {
|
|
181
|
+
readonly _tag: "CodexEmulatorInputInvalid";
|
|
182
|
+
} & Readonly<A>;
|
|
183
|
+
/** Thrown by the JS API (`faults.add`, `script.enqueue`) for invalid input; a programmer error. */
|
|
184
|
+
declare class CodexEmulatorInputInvalid extends CodexEmulatorInputInvalid_base<{
|
|
185
|
+
readonly input: 'fault' | 'turn';
|
|
186
|
+
readonly reason: string;
|
|
187
|
+
}> {
|
|
188
|
+
get message(): string;
|
|
189
|
+
}
|
|
190
|
+
type CodexLedgerEntry = ResponsesLedgerEntry;
|
|
191
|
+
type CodexFaultState = EmulatorFaultState<CodexFault>;
|
|
192
|
+
type CodexRouteCoverage = EmulatorRouteCoverage;
|
|
193
|
+
type CodexCoverage = EmulatorCoverage;
|
|
194
|
+
/** A usage-route fault (`status`, `error-after-chunks`, `truncate-after-chunks`). */
|
|
195
|
+
declare const CodexUsageFault: Schema.Union<readonly [Schema.Struct<{
|
|
196
|
+
readonly status: Schema.Int;
|
|
197
|
+
readonly match: Schema.optionalKey<Schema.Struct<{
|
|
198
|
+
readonly path: Schema.optionalKey<Schema.String>;
|
|
199
|
+
readonly model: Schema.optionalKey<Schema.String>;
|
|
200
|
+
}>>;
|
|
201
|
+
readonly count: Schema.optionalKey<Schema.Int>;
|
|
202
|
+
readonly kind: Schema.Literal<"status">;
|
|
203
|
+
readonly headers: Schema.optionalKey<Schema.$Record<Schema.String, Schema.String>>;
|
|
204
|
+
readonly body: Schema.optionalKey<Schema.Codec<Schema.Json, Schema.Json, never, never>>;
|
|
205
|
+
}>, Schema.Struct<{
|
|
206
|
+
readonly match: Schema.optionalKey<Schema.Struct<{
|
|
207
|
+
readonly path: Schema.optionalKey<Schema.String>;
|
|
208
|
+
readonly model: Schema.optionalKey<Schema.String>;
|
|
209
|
+
}>>;
|
|
210
|
+
readonly count: Schema.optionalKey<Schema.Int>;
|
|
211
|
+
readonly kind: Schema.Literal<"error-after-chunks">;
|
|
212
|
+
readonly chunks: Schema.Int;
|
|
213
|
+
}>, Schema.Struct<{
|
|
214
|
+
readonly match: Schema.optionalKey<Schema.Struct<{
|
|
215
|
+
readonly path: Schema.optionalKey<Schema.String>;
|
|
216
|
+
readonly model: Schema.optionalKey<Schema.String>;
|
|
217
|
+
}>>;
|
|
218
|
+
readonly count: Schema.optionalKey<Schema.Int>;
|
|
219
|
+
readonly kind: Schema.Literal<"truncate-after-chunks">;
|
|
220
|
+
readonly chunks: Schema.Int;
|
|
221
|
+
}>]>;
|
|
222
|
+
type CodexUsageFault = SubscriptionUsageFault;
|
|
223
|
+
/** A usage turn: `{ usage }` (a body with the recorded JSON shape) or `{ error }`. */
|
|
224
|
+
type CodexUsageScriptedTurn = SubscriptionUsageScriptedTurn;
|
|
225
|
+
type CodexUsageLedgerEntry = SubscriptionUsageLedgerEntry;
|
|
226
|
+
type CodexUsageEmulator = SubscriptionUsageEmulator;
|
|
227
|
+
type CodexEmulatorOptions = {
|
|
228
|
+
/** Model ids that exist. Defaults to `codexEmulatorDefaultModels`. */readonly knownModels?: ReadonlyArray<string>;
|
|
229
|
+
/**
|
|
230
|
+
* Replacement usage-route body; must have the recorded JSON shape (same keys and value kinds).
|
|
231
|
+
* Defaults to the recorded body (`codexSubscriptionUsageDefault`).
|
|
232
|
+
*/
|
|
233
|
+
readonly subscriptionUsage?: Schema.Json;
|
|
234
|
+
};
|
|
235
|
+
/** The Responses emulator, plus `usage`: the subscription-usage route's own emulator API. */
|
|
236
|
+
type CodexEmulator = ResponsesEmulator & {
|
|
237
|
+
readonly usage: CodexUsageEmulator;
|
|
238
|
+
};
|
|
239
|
+
/**
|
|
240
|
+
* Create a Codex Responses emulator. Each call has independent ledger, fault, and script state.
|
|
241
|
+
*
|
|
242
|
+
* Without a script, `POST /backend-api/codex/responses` answers a known model with synthetic
|
|
243
|
+
* output: `stream: true` streams `response.created`, `response.in_progress`, the output items
|
|
244
|
+
* (`response.output_item.added`, their parts and deltas, `response.output_item.done`), and
|
|
245
|
+
* `response.completed` with usage; `stream: false` returns one `response` JSON body. A request
|
|
246
|
+
* whose `reasoning` asks for a `summary` (the Codex provider always does) gets a reasoning item
|
|
247
|
+
* first. A request with function `tools` gets one `function_call` item whose arguments are
|
|
248
|
+
* synthesized from the tool's JSON Schema and streamed as `response.function_call_arguments.delta`
|
|
249
|
+
* fragments; `tool_choice: { type: 'function', name }` picks that tool (otherwise the first) and
|
|
250
|
+
* `tool_choice: 'none'` answers with text. Unknown models get 400 `model_not_found`; a request
|
|
251
|
+
* without a bearer credential gets 401 `invalid_api_key`; `max_output_tokens` gets 400
|
|
252
|
+
* `unsupported_parameter`; unknown routes get a 404 envelope. Not enforced: `store: false`,
|
|
253
|
+
* `stream: true`, `instructions`, `originator`, and `ChatGPT-Account-Id`.
|
|
254
|
+
*
|
|
255
|
+
* `GET /backend-api/wham/usage` is fixture-only: a request with a non-empty bearer credential and
|
|
256
|
+
* a non-empty `ChatGPT-Account-Id` (neither checked or recorded), `accept: application/json`, and
|
|
257
|
+
* no query gets the recorded body (`codexSubscriptionUsageDefault`, or a same-shaped
|
|
258
|
+
* `options.subscriptionUsage` / scripted `{ usage }`); anything else answers 400 not-emulated.
|
|
259
|
+
* Its ledger, faults, turns, and coverage are `emulator.usage` (control plane
|
|
260
|
+
* `/_emulate/usage/*`); `reset()` and `POST /_emulate/reset` reset both routes.
|
|
261
|
+
*/
|
|
262
|
+
declare const makeCodexEmulator: (options?: CodexEmulatorOptions) => CodexEmulator;
|
|
263
|
+
//#endregion
|
|
264
|
+
export { CodexCoverage, CodexEmulator, CodexEmulatorInputInvalid, CodexEmulatorOptions, CodexErrorEventFault, CodexFault, CodexFaultKind, CodexFaultMatch, CodexFaultState, CodexLedgerEntry, CodexRouteCoverage, CodexScriptedError, CodexScriptedFunctionCall, CodexScriptedResponse, CodexScriptedTurn, CodexScriptedUsage, CodexStreamError, CodexUsageEmulator, CodexUsageFault, CodexUsageLedgerEntry, CodexUsageScriptedTurn, type EmulatorEvidence, type EmulatorRouteEvidence, codexEmulatorDefaultModels, codexEmulatorRoutes, codexResponsesPath, codexSubscriptionUsageDefault, codexSubscriptionUsageEmulatorRoutes, codexSubscriptionUsagePath, emulatorEvidenceHeader, makeCodexEmulator };
|
|
265
|
+
//# sourceMappingURL=codex.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codex.d.mts","names":[],"sources":["../src/codex.ts"],"mappings":";;;;;;;cAgEa,kBAAA;;cAGA,0BAAA;AAHkB;AAG/B;;;AAH+B,cASlB,oCAAA,EAAsC,aAAa,CAAC,qBAAA;AAN1B;AAMvC;;;;AANuC,cAuB1B,6BAAA,EAA+B,MAAA,CAAO,IAA6C;AAAhG;AAAA,cAGa,0BAAA,EAA4B,aAAa;;;AAH0C;AAGhG;cAMa,mBAAA,EAAqB,aAAa,CAAC,qBAAA;;cAkBnC,eAAA,EAAe,MAAA,CAAA,MAAA;EAAA;;;KAEhB,eAAA,UAAyB,kBAAA,CAAmB,IAAI;;cAG/C,gBAAA,EAAgB,MAAA,CAAA,MAAA;EAAA;;;KAEjB,gBAAA,GAAmB,oBAAoB;;cAGtC,oBAAA,EAAoB,MAAA,CAAA,MAAA;EAAA;;;;;;;;;;;;;KAErB,oBAAA,UAA8B,wBAAA,CAAyB,IAAI;;;;;AAVvE;;;;AAA4D;AAG5D;;;;cAsBa,UAAA,EAAU,MAAA,CAAA,KAAA,WAAA,MAAA,CAAA,MAAA;EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAEX,UAAA,GAAa,cAAc;AAAA,KAE3B,cAAA,GAAiB,kBAAkB;;cAGlC,kBAAA,EAAkB,MAAA,CAAA,MAAA;EAAA;;;;KAEnB,kBAAA,GAAqB,sBAAsB;;cAG1C,yBAAA,EAAyB,MAAA,CAAA,MAAA;EAAA;;;;KAE1B,yBAAA,GAA4B,6BAA6B;;;;;cAMxD,qBAAA,EAAqB,MAAA,CAAA,MAAA;EAAA;;;;;;;;;;;;;;;KAEtB,qBAAA,GAAwB,yBAAyB;;cAGhD,kBAAA,EAAkB,MAAA,CAAA,MAAA;EAAA;;;;;;KAEnB,kBAAA,UAA4B,qBAAA,CAAsB,IAAI;;cAGrD,iBAAA,EAAiB,MAAA,CAAA,KAAA,WAAA,MAAA,CAAA,MAAA;EAAA;;;;;;;;;;;;;;;;;;;;;KAElB,iBAAA,GAAoB,qBAAqB;AAAA,cAAA,8BAAA;;;;cAGxC,yBAAA,SAAkC,8BAAA;EAAA,SACpC,KAAA;EAAA,SACA,MAAA;AAAA;EAAA,IAEI,OAAA,CAAA;AAAA;AAAA,KAKH,gBAAA,GAAmB,oBAAoB;AAAA,KAEvC,eAAA,GAAkB,kBAAkB,CAAC,UAAA;AAAA,KAErC,kBAAA,GAAqB,qBAAqB;AAAA,KAE1C,aAAA,GAAgB,gBAAgB;;cAG/B,eAAA,EAAe,MAAA,CAAA,KAAA,WAAA,MAAA,CAAA,MAAA;EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;KAEhB,eAAA,GAAkB,sBAAsB;;KAGxC,sBAAA,GAAyB,6BAA6B;AAAA,KAEtD,qBAAA,GAAwB,4BAA4B;AAAA,KAEpD,kBAAA,GAAqB,yBAAyB;AAAA,KAE9C,oBAAA;EAhEW,+EAkEZ,WAAA,GAAc,aAAA;;;;;WAKd,iBAAA,GAAoB,MAAA,CAAO,IAAI;AAAA;;KAI9B,aAAA,GAAgB,iBAAA;EAAA,SAA+B,KAAA,EAAO,kBAAkB;AAAA;;;;;;;;;;;;;;;;;;;;;;;;cAkCvE,iBAAA,GAAqB,OAAA,GAAS,oBAAA,KAA4B,aAKpE"}
|
package/dist/codex.mjs
ADDED
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
import { emulatorEvidenceHeader } from "./route-evidence.mjs";
|
|
2
|
+
import { EmulatorFaultMatch, EmulatorScriptedError } from "./emulator-kernel.mjs";
|
|
3
|
+
import { withSubscriptionUsage } from "./emulator-compose.mjs";
|
|
4
|
+
import { SubscriptionUsageFault, makeSubscriptionUsageEmulator, recordedUsageBody } from "./subscription-usage.mjs";
|
|
5
|
+
import { codexUsageRecording } from "./subscription-usage-recordings.mjs";
|
|
6
|
+
import { ResponsesErrorEventFault, ResponsesFault, ResponsesScriptedFunctionCall, ResponsesScriptedResponse, ResponsesScriptedTurn, ResponsesScriptedUsage, ResponsesStreamError, makeResponsesEmulator } from "./responses.mjs";
|
|
7
|
+
import { Data } from "effect";
|
|
8
|
+
//#region src/codex.ts
|
|
9
|
+
/**
|
|
10
|
+
* OpenAI Codex (ChatGPT subscription) Responses emulator: a plain fetch handler for
|
|
11
|
+
* `POST /backend-api/codex/responses` (origin `https://chatgpt.com`), with scripted turns, wire
|
|
12
|
+
* faults, a request ledger, and an `/_emulate/*` control plane.
|
|
13
|
+
*
|
|
14
|
+
* It never imports SDK code: its wire shapes follow the synthetic Codex Responses conformance
|
|
15
|
+
* fixtures (Responses SSE with typed `event:` names, the `response` JSON body, and the
|
|
16
|
+
* `{ error: { message, type, param, code } }` envelope) and are linked to those conformance case
|
|
17
|
+
* ids in `codexEmulatorRoutes`. The Responses machinery lives in the internal `responses.ts` core
|
|
18
|
+
* and is shared with the xAI Grok emulator.
|
|
19
|
+
*
|
|
20
|
+
* Requests authenticate with a non-empty `Authorization: Bearer` credential (a ChatGPT OAuth
|
|
21
|
+
* access token), never checked or stored. The ChatGPT Codex endpoint does not take an output
|
|
22
|
+
* limit, so a request with `max_output_tokens` answers 400 `unsupported_parameter`. The
|
|
23
|
+
* `originator` header is recorded in the ledger; `ChatGPT-Account-Id` is neither required nor
|
|
24
|
+
* recorded.
|
|
25
|
+
*
|
|
26
|
+
* The same fetch handler also answers the Codex subscription-usage route
|
|
27
|
+
* (`GET /backend-api/wham/usage`, `emulator.usage`) with its own manifest
|
|
28
|
+
* (`codexSubscriptionUsageEmulatorRoutes`), ledger, faults, and turns; see `makeCodexEmulator`.
|
|
29
|
+
*
|
|
30
|
+
* Runtime-portable Web APIs only (`Request`, `Response`, `ReadableStream`, `TextEncoder`, `URL`);
|
|
31
|
+
* no Effect runtime is required to use it.
|
|
32
|
+
*
|
|
33
|
+
* @experimental
|
|
34
|
+
*/
|
|
35
|
+
const codexResponsesPath = "/backend-api/codex/responses";
|
|
36
|
+
/** The Codex subscription-usage path (`openAiCodexSubscriptionUsageUrl` in the SDK). */
|
|
37
|
+
const codexSubscriptionUsagePath = "/backend-api/wham/usage";
|
|
38
|
+
/**
|
|
39
|
+
* Route evidence manifest of the Codex subscription-usage route (served by the same fetch handler
|
|
40
|
+
* as the Responses route, with its own ledger and coverage). Synthetic, unverified.
|
|
41
|
+
*/
|
|
42
|
+
const codexSubscriptionUsageEmulatorRoutes = [{
|
|
43
|
+
method: "GET",
|
|
44
|
+
path: codexSubscriptionUsagePath,
|
|
45
|
+
kind: "provider",
|
|
46
|
+
write: false,
|
|
47
|
+
caseIds: ["openai.codex.usage.snapshot"],
|
|
48
|
+
evidence: "unverified",
|
|
49
|
+
observedAt: void 0
|
|
50
|
+
}];
|
|
51
|
+
/**
|
|
52
|
+
* The recorded Codex usage body (the synthetic `openai.codex.usage.snapshot` fixture, copied as
|
|
53
|
+
* data): `rate_limit.primary_window` and `secondary_window` as
|
|
54
|
+
* `{ used_percent, limit_window_seconds, reset_after_seconds, reset_at }`.
|
|
55
|
+
*/
|
|
56
|
+
const codexSubscriptionUsageDefault = recordedUsageBody(codexUsageRecording);
|
|
57
|
+
/** Synthetic-safe default model ids, including the Codex conformance defaults. */
|
|
58
|
+
const codexEmulatorDefaultModels = ["gpt-5.4", "gpt-5.5"];
|
|
59
|
+
/**
|
|
60
|
+
* Route evidence manifest: every emulated Codex route and the conformance cases whose (currently
|
|
61
|
+
* synthetic, unverified) wire shapes it follows.
|
|
62
|
+
*/
|
|
63
|
+
const codexEmulatorRoutes = [{
|
|
64
|
+
method: "POST",
|
|
65
|
+
path: codexResponsesPath,
|
|
66
|
+
kind: "provider",
|
|
67
|
+
write: false,
|
|
68
|
+
caseIds: [
|
|
69
|
+
"openai.codex.stream.plain-text",
|
|
70
|
+
"openai.codex.stream.function-call-arguments",
|
|
71
|
+
"openai.codex.stream.error-envelope",
|
|
72
|
+
"openai.codex.stream.terminal-event"
|
|
73
|
+
],
|
|
74
|
+
evidence: "unverified",
|
|
75
|
+
observedAt: void 0
|
|
76
|
+
}];
|
|
77
|
+
/** Optional fault filter; an omitted field matches every request. `path` ending in `*` is a prefix. */
|
|
78
|
+
const CodexFaultMatch = EmulatorFaultMatch;
|
|
79
|
+
/** A mid-stream Responses error (`{ code, message }`). */
|
|
80
|
+
const CodexStreamError = ResponsesStreamError;
|
|
81
|
+
/** A mid-stream `error` or `response.failed` event fault, streamed responses only. */
|
|
82
|
+
const CodexErrorEventFault = ResponsesErrorEventFault;
|
|
83
|
+
/**
|
|
84
|
+
* Wire faults:
|
|
85
|
+
*
|
|
86
|
+
* - `status`: answer with this status, headers, and body (for example 429 with `retry-after`).
|
|
87
|
+
* The body defaults to the OpenAI error envelope for the status.
|
|
88
|
+
* - `error-after-chunks`: send N body chunks, then error the body stream (a dropped connection).
|
|
89
|
+
* - `truncate-after-chunks`: send N body chunks, then close cleanly (no `response.completed`).
|
|
90
|
+
* - `error-event-after-chunks`: send N SSE events, then one `error` (default) or
|
|
91
|
+
* `response.failed` event and close.
|
|
92
|
+
*
|
|
93
|
+
* Statuses that cannot carry a body and redirects are rejected, as are invalid headers and
|
|
94
|
+
* `location`. A fault that cannot take effect answers 500 and is not consumed.
|
|
95
|
+
*/
|
|
96
|
+
const CodexFault = ResponsesFault;
|
|
97
|
+
/** Usage for a scripted turn (sent in `response.completed` or the JSON body). */
|
|
98
|
+
const CodexScriptedUsage = ResponsesScriptedUsage;
|
|
99
|
+
/** One scripted `function_call` item; its arguments stream as these fragments. */
|
|
100
|
+
const CodexScriptedFunctionCall = ResponsesScriptedFunctionCall;
|
|
101
|
+
/**
|
|
102
|
+
* A scripted response: `reasoning` (summary fragments), `text`, `functionCalls`, `order`,
|
|
103
|
+
* `usage` (`null` drops it), and `format` (`sse` or `json`, default: the request's `stream`).
|
|
104
|
+
*/
|
|
105
|
+
const CodexScriptedResponse = ResponsesScriptedResponse;
|
|
106
|
+
/** A scripted error response: status, body (a string is sent as is), and optional headers. */
|
|
107
|
+
const CodexScriptedError = EmulatorScriptedError;
|
|
108
|
+
/** A turn queued for the next Codex request. */
|
|
109
|
+
const CodexScriptedTurn = ResponsesScriptedTurn;
|
|
110
|
+
/** Thrown by the JS API (`faults.add`, `script.enqueue`) for invalid input; a programmer error. */
|
|
111
|
+
var CodexEmulatorInputInvalid = class extends Data.TaggedError("CodexEmulatorInputInvalid") {
|
|
112
|
+
get message() {
|
|
113
|
+
return `Invalid Codex emulator ${this.input}: ${this.reason}`;
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
/** A usage-route fault (`status`, `error-after-chunks`, `truncate-after-chunks`). */
|
|
117
|
+
const CodexUsageFault = SubscriptionUsageFault;
|
|
118
|
+
const openAiErrorEnvelope = (error) => ({ error: {
|
|
119
|
+
message: error.message,
|
|
120
|
+
type: error.type,
|
|
121
|
+
param: error.param ?? null,
|
|
122
|
+
code: error.code
|
|
123
|
+
} });
|
|
124
|
+
/**
|
|
125
|
+
* Create a Codex Responses emulator. Each call has independent ledger, fault, and script state.
|
|
126
|
+
*
|
|
127
|
+
* Without a script, `POST /backend-api/codex/responses` answers a known model with synthetic
|
|
128
|
+
* output: `stream: true` streams `response.created`, `response.in_progress`, the output items
|
|
129
|
+
* (`response.output_item.added`, their parts and deltas, `response.output_item.done`), and
|
|
130
|
+
* `response.completed` with usage; `stream: false` returns one `response` JSON body. A request
|
|
131
|
+
* whose `reasoning` asks for a `summary` (the Codex provider always does) gets a reasoning item
|
|
132
|
+
* first. A request with function `tools` gets one `function_call` item whose arguments are
|
|
133
|
+
* synthesized from the tool's JSON Schema and streamed as `response.function_call_arguments.delta`
|
|
134
|
+
* fragments; `tool_choice: { type: 'function', name }` picks that tool (otherwise the first) and
|
|
135
|
+
* `tool_choice: 'none'` answers with text. Unknown models get 400 `model_not_found`; a request
|
|
136
|
+
* without a bearer credential gets 401 `invalid_api_key`; `max_output_tokens` gets 400
|
|
137
|
+
* `unsupported_parameter`; unknown routes get a 404 envelope. Not enforced: `store: false`,
|
|
138
|
+
* `stream: true`, `instructions`, `originator`, and `ChatGPT-Account-Id`.
|
|
139
|
+
*
|
|
140
|
+
* `GET /backend-api/wham/usage` is fixture-only: a request with a non-empty bearer credential and
|
|
141
|
+
* a non-empty `ChatGPT-Account-Id` (neither checked or recorded), `accept: application/json`, and
|
|
142
|
+
* no query gets the recorded body (`codexSubscriptionUsageDefault`, or a same-shaped
|
|
143
|
+
* `options.subscriptionUsage` / scripted `{ usage }`); anything else answers 400 not-emulated.
|
|
144
|
+
* Its ledger, faults, turns, and coverage are `emulator.usage` (control plane
|
|
145
|
+
* `/_emulate/usage/*`); `reset()` and `POST /_emulate/reset` reset both routes.
|
|
146
|
+
*/
|
|
147
|
+
const makeCodexEmulator = (options = {}) => withSubscriptionUsage(makeCodexResponsesEmulator(options), makeCodexUsageEmulator(options), codexSubscriptionUsagePath);
|
|
148
|
+
const makeCodexUsageEmulator = (options) => makeSubscriptionUsageEmulator({
|
|
149
|
+
path: codexSubscriptionUsagePath,
|
|
150
|
+
routes: codexSubscriptionUsageEmulatorRoutes,
|
|
151
|
+
recording: codexUsageRecording,
|
|
152
|
+
headers: [{
|
|
153
|
+
name: "chatgpt-account-id",
|
|
154
|
+
record: false
|
|
155
|
+
}],
|
|
156
|
+
subscriptionUsage: options.subscriptionUsage,
|
|
157
|
+
inputInvalid: (input, reason) => new CodexEmulatorInputInvalid({
|
|
158
|
+
input,
|
|
159
|
+
reason
|
|
160
|
+
})
|
|
161
|
+
});
|
|
162
|
+
const makeCodexResponsesEmulator = (options) => makeResponsesEmulator({
|
|
163
|
+
path: codexResponsesPath,
|
|
164
|
+
routes: codexEmulatorRoutes,
|
|
165
|
+
knownModels: options.knownModels ?? codexEmulatorDefaultModels,
|
|
166
|
+
errorEnvelope: openAiErrorEnvelope,
|
|
167
|
+
unknownModel: {
|
|
168
|
+
status: 400,
|
|
169
|
+
error: {
|
|
170
|
+
message: "Synthetic placeholder: the requested model is not supported.",
|
|
171
|
+
type: "invalid_request_error",
|
|
172
|
+
code: "model_not_found",
|
|
173
|
+
param: "model"
|
|
174
|
+
}
|
|
175
|
+
},
|
|
176
|
+
unauthorized: {
|
|
177
|
+
message: "Synthetic: missing or invalid bearer credential.",
|
|
178
|
+
type: "invalid_request_error",
|
|
179
|
+
code: "invalid_api_key"
|
|
180
|
+
},
|
|
181
|
+
headers: [{
|
|
182
|
+
name: "originator",
|
|
183
|
+
record: true
|
|
184
|
+
}],
|
|
185
|
+
outputTokenLimit: "rejected",
|
|
186
|
+
defaultText: [
|
|
187
|
+
"Hello",
|
|
188
|
+
" from the",
|
|
189
|
+
" synthetic Codex emulator."
|
|
190
|
+
],
|
|
191
|
+
inputInvalid: (input, reason) => new CodexEmulatorInputInvalid({
|
|
192
|
+
input,
|
|
193
|
+
reason
|
|
194
|
+
})
|
|
195
|
+
});
|
|
196
|
+
//#endregion
|
|
197
|
+
export { CodexEmulatorInputInvalid, CodexErrorEventFault, CodexFault, CodexFaultMatch, CodexScriptedError, CodexScriptedFunctionCall, CodexScriptedResponse, CodexScriptedTurn, CodexScriptedUsage, CodexStreamError, CodexUsageFault, codexEmulatorDefaultModels, codexEmulatorRoutes, codexResponsesPath, codexSubscriptionUsageDefault, codexSubscriptionUsageEmulatorRoutes, codexSubscriptionUsagePath, emulatorEvidenceHeader, makeCodexEmulator };
|
|
198
|
+
|
|
199
|
+
//# sourceMappingURL=codex.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codex.mjs","names":[],"sources":["../src/codex.ts"],"sourcesContent":["/**\n * OpenAI Codex (ChatGPT subscription) Responses emulator: a plain fetch handler for\n * `POST /backend-api/codex/responses` (origin `https://chatgpt.com`), with scripted turns, wire\n * faults, a request ledger, and an `/_emulate/*` control plane.\n *\n * It never imports SDK code: its wire shapes follow the synthetic Codex Responses conformance\n * fixtures (Responses SSE with typed `event:` names, the `response` JSON body, and the\n * `{ error: { message, type, param, code } }` envelope) and are linked to those conformance case\n * ids in `codexEmulatorRoutes`. The Responses machinery lives in the internal `responses.ts` core\n * and is shared with the xAI Grok emulator.\n *\n * Requests authenticate with a non-empty `Authorization: Bearer` credential (a ChatGPT OAuth\n * access token), never checked or stored. The ChatGPT Codex endpoint does not take an output\n * limit, so a request with `max_output_tokens` answers 400 `unsupported_parameter`. The\n * `originator` header is recorded in the ledger; `ChatGPT-Account-Id` is neither required nor\n * recorded.\n *\n * The same fetch handler also answers the Codex subscription-usage route\n * (`GET /backend-api/wham/usage`, `emulator.usage`) with its own manifest\n * (`codexSubscriptionUsageEmulatorRoutes`), ledger, faults, and turns; see `makeCodexEmulator`.\n *\n * Runtime-portable Web APIs only (`Request`, `Response`, `ReadableStream`, `TextEncoder`, `URL`);\n * no Effect runtime is required to use it.\n *\n * @experimental\n */\nimport { Data } from 'effect'\nimport type * as Schema from 'effect/Schema'\nimport { withSubscriptionUsage } from './emulator-compose.ts'\nimport type {\n EmulatorCoverage,\n EmulatorFaultState,\n EmulatorRouteCoverage\n} from './emulator-kernel.ts'\nimport { EmulatorFaultMatch, EmulatorScriptedError } from './emulator-kernel.ts'\nimport {\n makeResponsesEmulator,\n ResponsesErrorEventFault,\n ResponsesFault,\n ResponsesScriptedFunctionCall,\n ResponsesScriptedResponse,\n ResponsesScriptedTurn,\n ResponsesScriptedUsage,\n ResponsesStreamError,\n type ResponsesEmulator,\n type ResponsesFaultKind,\n type ResponsesLedgerEntry,\n type ResponsesWireError\n} from './responses.ts'\nimport type { EmulatorRouteEvidence } from './route-evidence.ts'\nimport {\n makeSubscriptionUsageEmulator,\n recordedUsageBody,\n SubscriptionUsageFault,\n type SubscriptionUsageEmulator,\n type SubscriptionUsageLedgerEntry,\n type SubscriptionUsageScriptedTurn\n} from './subscription-usage.ts'\nimport { codexUsageRecording } from './subscription-usage-recordings.ts'\n\nexport type { EmulatorEvidence, EmulatorRouteEvidence } from './route-evidence.ts'\n\nexport { emulatorEvidenceHeader } from './route-evidence.ts'\n\nexport const codexResponsesPath = '/backend-api/codex/responses'\n\n/** The Codex subscription-usage path (`openAiCodexSubscriptionUsageUrl` in the SDK). */\nexport const codexSubscriptionUsagePath = '/backend-api/wham/usage'\n\n/**\n * Route evidence manifest of the Codex subscription-usage route (served by the same fetch handler\n * as the Responses route, with its own ledger and coverage). Synthetic, unverified.\n */\nexport const codexSubscriptionUsageEmulatorRoutes: ReadonlyArray<EmulatorRouteEvidence> = [\n {\n method: 'GET',\n path: codexSubscriptionUsagePath,\n kind: 'provider',\n write: false,\n caseIds: ['openai.codex.usage.snapshot'],\n evidence: 'unverified',\n observedAt: undefined\n }\n]\n\n/**\n * The recorded Codex usage body (the synthetic `openai.codex.usage.snapshot` fixture, copied as\n * data): `rate_limit.primary_window` and `secondary_window` as\n * `{ used_percent, limit_window_seconds, reset_after_seconds, reset_at }`.\n */\nexport const codexSubscriptionUsageDefault: Schema.Json = recordedUsageBody(codexUsageRecording)\n\n/** Synthetic-safe default model ids, including the Codex conformance defaults. */\nexport const codexEmulatorDefaultModels: ReadonlyArray<string> = ['gpt-5.4', 'gpt-5.5']\n\n/**\n * Route evidence manifest: every emulated Codex route and the conformance cases whose (currently\n * synthetic, unverified) wire shapes it follows.\n */\nexport const codexEmulatorRoutes: ReadonlyArray<EmulatorRouteEvidence> = [\n {\n method: 'POST',\n path: codexResponsesPath,\n kind: 'provider',\n write: false,\n caseIds: [\n 'openai.codex.stream.plain-text',\n 'openai.codex.stream.function-call-arguments',\n 'openai.codex.stream.error-envelope',\n 'openai.codex.stream.terminal-event'\n ],\n evidence: 'unverified',\n observedAt: undefined\n }\n]\n\n/** Optional fault filter; an omitted field matches every request. `path` ending in `*` is a prefix. */\nexport const CodexFaultMatch = EmulatorFaultMatch\n\nexport type CodexFaultMatch = typeof EmulatorFaultMatch.Type\n\n/** A mid-stream Responses error (`{ code, message }`). */\nexport const CodexStreamError = ResponsesStreamError\n\nexport type CodexStreamError = ResponsesStreamError\n\n/** A mid-stream `error` or `response.failed` event fault, streamed responses only. */\nexport const CodexErrorEventFault = ResponsesErrorEventFault\n\nexport type CodexErrorEventFault = typeof ResponsesErrorEventFault.Type\n\n/**\n * Wire faults:\n *\n * - `status`: answer with this status, headers, and body (for example 429 with `retry-after`).\n * The body defaults to the OpenAI error envelope for the status.\n * - `error-after-chunks`: send N body chunks, then error the body stream (a dropped connection).\n * - `truncate-after-chunks`: send N body chunks, then close cleanly (no `response.completed`).\n * - `error-event-after-chunks`: send N SSE events, then one `error` (default) or\n * `response.failed` event and close.\n *\n * Statuses that cannot carry a body and redirects are rejected, as are invalid headers and\n * `location`. A fault that cannot take effect answers 500 and is not consumed.\n */\nexport const CodexFault = ResponsesFault\n\nexport type CodexFault = ResponsesFault\n\nexport type CodexFaultKind = ResponsesFaultKind\n\n/** Usage for a scripted turn (sent in `response.completed` or the JSON body). */\nexport const CodexScriptedUsage = ResponsesScriptedUsage\n\nexport type CodexScriptedUsage = ResponsesScriptedUsage\n\n/** One scripted `function_call` item; its arguments stream as these fragments. */\nexport const CodexScriptedFunctionCall = ResponsesScriptedFunctionCall\n\nexport type CodexScriptedFunctionCall = ResponsesScriptedFunctionCall\n\n/**\n * A scripted response: `reasoning` (summary fragments), `text`, `functionCalls`, `order`,\n * `usage` (`null` drops it), and `format` (`sse` or `json`, default: the request's `stream`).\n */\nexport const CodexScriptedResponse = ResponsesScriptedResponse\n\nexport type CodexScriptedResponse = ResponsesScriptedResponse\n\n/** A scripted error response: status, body (a string is sent as is), and optional headers. */\nexport const CodexScriptedError = EmulatorScriptedError\n\nexport type CodexScriptedError = typeof EmulatorScriptedError.Type\n\n/** A turn queued for the next Codex request. */\nexport const CodexScriptedTurn = ResponsesScriptedTurn\n\nexport type CodexScriptedTurn = ResponsesScriptedTurn\n\n/** Thrown by the JS API (`faults.add`, `script.enqueue`) for invalid input; a programmer error. */\nexport class CodexEmulatorInputInvalid extends Data.TaggedError('CodexEmulatorInputInvalid')<{\n readonly input: 'fault' | 'turn'\n readonly reason: string\n}> {\n override get message(): string {\n return `Invalid Codex emulator ${this.input}: ${this.reason}`\n }\n}\n\nexport type CodexLedgerEntry = ResponsesLedgerEntry\n\nexport type CodexFaultState = EmulatorFaultState<CodexFault>\n\nexport type CodexRouteCoverage = EmulatorRouteCoverage\n\nexport type CodexCoverage = EmulatorCoverage\n\n/** A usage-route fault (`status`, `error-after-chunks`, `truncate-after-chunks`). */\nexport const CodexUsageFault = SubscriptionUsageFault\n\nexport type CodexUsageFault = SubscriptionUsageFault\n\n/** A usage turn: `{ usage }` (a body with the recorded JSON shape) or `{ error }`. */\nexport type CodexUsageScriptedTurn = SubscriptionUsageScriptedTurn\n\nexport type CodexUsageLedgerEntry = SubscriptionUsageLedgerEntry\n\nexport type CodexUsageEmulator = SubscriptionUsageEmulator\n\nexport type CodexEmulatorOptions = {\n /** Model ids that exist. Defaults to `codexEmulatorDefaultModels`. */\n readonly knownModels?: ReadonlyArray<string>\n /**\n * Replacement usage-route body; must have the recorded JSON shape (same keys and value kinds).\n * Defaults to the recorded body (`codexSubscriptionUsageDefault`).\n */\n readonly subscriptionUsage?: Schema.Json\n}\n\n/** The Responses emulator, plus `usage`: the subscription-usage route's own emulator API. */\nexport type CodexEmulator = ResponsesEmulator & { readonly usage: CodexUsageEmulator }\n\nconst openAiErrorEnvelope = (error: ResponsesWireError): Schema.Json => ({\n error: {\n message: error.message,\n type: error.type,\n param: error.param ?? null,\n code: error.code\n }\n})\n\n/**\n * Create a Codex Responses emulator. Each call has independent ledger, fault, and script state.\n *\n * Without a script, `POST /backend-api/codex/responses` answers a known model with synthetic\n * output: `stream: true` streams `response.created`, `response.in_progress`, the output items\n * (`response.output_item.added`, their parts and deltas, `response.output_item.done`), and\n * `response.completed` with usage; `stream: false` returns one `response` JSON body. A request\n * whose `reasoning` asks for a `summary` (the Codex provider always does) gets a reasoning item\n * first. A request with function `tools` gets one `function_call` item whose arguments are\n * synthesized from the tool's JSON Schema and streamed as `response.function_call_arguments.delta`\n * fragments; `tool_choice: { type: 'function', name }` picks that tool (otherwise the first) and\n * `tool_choice: 'none'` answers with text. Unknown models get 400 `model_not_found`; a request\n * without a bearer credential gets 401 `invalid_api_key`; `max_output_tokens` gets 400\n * `unsupported_parameter`; unknown routes get a 404 envelope. Not enforced: `store: false`,\n * `stream: true`, `instructions`, `originator`, and `ChatGPT-Account-Id`.\n *\n * `GET /backend-api/wham/usage` is fixture-only: a request with a non-empty bearer credential and\n * a non-empty `ChatGPT-Account-Id` (neither checked or recorded), `accept: application/json`, and\n * no query gets the recorded body (`codexSubscriptionUsageDefault`, or a same-shaped\n * `options.subscriptionUsage` / scripted `{ usage }`); anything else answers 400 not-emulated.\n * Its ledger, faults, turns, and coverage are `emulator.usage` (control plane\n * `/_emulate/usage/*`); `reset()` and `POST /_emulate/reset` reset both routes.\n */\nexport const makeCodexEmulator = (options: CodexEmulatorOptions = {}): CodexEmulator =>\n withSubscriptionUsage(\n makeCodexResponsesEmulator(options),\n makeCodexUsageEmulator(options),\n codexSubscriptionUsagePath\n )\n\nconst makeCodexUsageEmulator = (options: CodexEmulatorOptions): CodexUsageEmulator =>\n makeSubscriptionUsageEmulator({\n path: codexSubscriptionUsagePath,\n routes: codexSubscriptionUsageEmulatorRoutes,\n recording: codexUsageRecording,\n headers: [{ name: 'chatgpt-account-id', record: false }],\n subscriptionUsage: options.subscriptionUsage,\n inputInvalid: (input, reason) => new CodexEmulatorInputInvalid({ input, reason })\n })\n\nconst makeCodexResponsesEmulator = (options: CodexEmulatorOptions): ResponsesEmulator =>\n makeResponsesEmulator({\n path: codexResponsesPath,\n routes: codexEmulatorRoutes,\n knownModels: options.knownModels ?? codexEmulatorDefaultModels,\n errorEnvelope: openAiErrorEnvelope,\n // Copied data shape of the synthetic Codex error-envelope fixture (unknown model id).\n unknownModel: {\n status: 400,\n error: {\n message: 'Synthetic placeholder: the requested model is not supported.',\n type: 'invalid_request_error',\n code: 'model_not_found',\n param: 'model'\n }\n },\n unauthorized: {\n message: 'Synthetic: missing or invalid bearer credential.',\n type: 'invalid_request_error',\n code: 'invalid_api_key'\n },\n headers: [{ name: 'originator', record: true }],\n outputTokenLimit: 'rejected',\n defaultText: ['Hello', ' from the', ' synthetic Codex emulator.'],\n inputInvalid: (input, reason) => new CodexEmulatorInputInvalid({ input, reason })\n })\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgEA,MAAa,qBAAqB;;AAGlC,MAAa,6BAA6B;;;;;AAM1C,MAAa,uCAA6E,CACxF;CACE,QAAQ;CACR,MAAM;CACN,MAAM;CACN,OAAO;CACP,SAAS,CAAC,6BAA6B;CACvC,UAAU;CACV,YAAY,KAAA;AACd,CACF;;;;;;AAOA,MAAa,gCAA6C,kBAAkB,mBAAmB;;AAG/F,MAAa,6BAAoD,CAAC,WAAW,SAAS;;;;;AAMtF,MAAa,sBAA4D,CACvE;CACE,QAAQ;CACR,MAAM;CACN,MAAM;CACN,OAAO;CACP,SAAS;EACP;EACA;EACA;EACA;CACF;CACA,UAAU;CACV,YAAY,KAAA;AACd,CACF;;AAGA,MAAa,kBAAkB;;AAK/B,MAAa,mBAAmB;;AAKhC,MAAa,uBAAuB;;;;;;;;;;;;;;AAiBpC,MAAa,aAAa;;AAO1B,MAAa,qBAAqB;;AAKlC,MAAa,4BAA4B;;;;;AAQzC,MAAa,wBAAwB;;AAKrC,MAAa,qBAAqB;;AAKlC,MAAa,oBAAoB;;AAKjC,IAAa,4BAAb,cAA+C,KAAK,YAAY,2BAA2B,EAGxF;CACD,IAAa,UAAkB;EAC7B,OAAO,0BAA0B,KAAK,MAAM,IAAI,KAAK;CACvD;AACF;;AAWA,MAAa,kBAAkB;AAwB/B,MAAM,uBAAuB,WAA4C,EACvE,OAAO;CACL,SAAS,MAAM;CACf,MAAM,MAAM;CACZ,OAAO,MAAM,SAAS;CACtB,MAAM,MAAM;AACd,EACF;;;;;;;;;;;;;;;;;;;;;;;;AAyBA,MAAa,qBAAqB,UAAgC,CAAC,MACjE,sBACE,2BAA2B,OAAO,GAClC,uBAAuB,OAAO,GAC9B,0BACF;AAEF,MAAM,0BAA0B,YAC9B,8BAA8B;CAC5B,MAAM;CACN,QAAQ;CACR,WAAW;CACX,SAAS,CAAC;EAAE,MAAM;EAAsB,QAAQ;CAAM,CAAC;CACvD,mBAAmB,QAAQ;CAC3B,eAAe,OAAO,WAAW,IAAI,0BAA0B;EAAE;EAAO;CAAO,CAAC;AAClF,CAAC;AAEH,MAAM,8BAA8B,YAClC,sBAAsB;CACpB,MAAM;CACN,QAAQ;CACR,aAAa,QAAQ,eAAe;CACpC,eAAe;CAEf,cAAc;EACZ,QAAQ;EACR,OAAO;GACL,SAAS;GACT,MAAM;GACN,MAAM;GACN,OAAO;EACT;CACF;CACA,cAAc;EACZ,SAAS;EACT,MAAM;EACN,MAAM;CACR;CACA,SAAS,CAAC;EAAE,MAAM;EAAc,QAAQ;CAAK,CAAC;CAC9C,kBAAkB;CAClB,aAAa;EAAC;EAAS;EAAa;CAA4B;CAChE,eAAe,OAAO,WAAW,IAAI,0BAA0B;EAAE;EAAO;CAAO,CAAC;AAClF,CAAC"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { StatefulRoute } from "../stateful-emulator.mjs";
|
|
2
|
+
import { DropboxEmulatorState } from "./state.mjs";
|
|
3
|
+
|
|
4
|
+
//#region src/dropbox/api.d.ts
|
|
5
|
+
/** API version prefix of every Dropbox route. */
|
|
6
|
+
declare const dropboxEmulatorBasePath = "/2";
|
|
7
|
+
/**
|
|
8
|
+
* The fixture error envelopes, byte for byte (`not-found-envelope.ts`, `create-folder-conflict.ts`,
|
|
9
|
+
* and `upload-rev-precondition.ts`), each answered with HTTP 409.
|
|
10
|
+
*/
|
|
11
|
+
declare const dropboxEmulatorErrorBodies: {
|
|
12
|
+
readonly notFound: "{\"error_summary\": \"path/not_found/.\", \"error\": {\".tag\": \"path\", \"path\": {\".tag\": \"not_found\"}}}";
|
|
13
|
+
readonly folderConflict: "{\"error_summary\": \"path/conflict/folder/..\", \"error\": {\".tag\": \"path\", \"path\": {\".tag\": \"conflict\", \"conflict\": {\".tag\": \"folder\"}}}}";
|
|
14
|
+
readonly uploadConflict: "{\"error_summary\": \"path/conflict/file/..\", \"error\": {\".tag\": \"path\", \"path\": {\"reason\": {\".tag\": \"conflict\", \"conflict\": {\".tag\": \"file\"}}}}}";
|
|
15
|
+
};
|
|
16
|
+
/** Drill knobs (tests only): each makes the emulator disagree with one conformance claim. */
|
|
17
|
+
type DropboxEmulatorDrills = {
|
|
18
|
+
/** `list_folder` ignores `limit`: one page with every entry and `has_more: false`. */readonly listFolderSinglePage?: boolean; /** `get_metadata` matches path components case-sensitively. */
|
|
19
|
+
readonly getMetadataCaseSensitive?: boolean; /** `search/continue_v2` answers the earlier pages' matches again before the new ones. */
|
|
20
|
+
readonly searchRepeatsMatches?: boolean; /** A missing path answers a `path_lookup/not_found` envelope (still 409). */
|
|
21
|
+
readonly notFoundAsPathLookup?: boolean; /** A folder create conflict answers `path/conflict/file` instead of `path/conflict/folder`. */
|
|
22
|
+
readonly folderConflictAsFile?: boolean; /** `delete_v2` keeps no deleted-entry record, so `include_deleted` is not emulated. */
|
|
23
|
+
readonly deleteLeavesNoTombstone?: boolean; /** `move_v2` gives the moved file a new id. */
|
|
24
|
+
readonly moveMintsNewId?: boolean; /** An `update` upload naming a stale rev overwrites instead of conflicting. */
|
|
25
|
+
readonly uploadIgnoresRev?: boolean;
|
|
26
|
+
};
|
|
27
|
+
declare const dropboxEmulatorDrillKnobs: ReadonlyArray<keyof DropboxEmulatorDrills>;
|
|
28
|
+
/** A `list_folder` cursor (runtime data, not state). */
|
|
29
|
+
type DropboxListCursor = {
|
|
30
|
+
readonly kind: 'list';
|
|
31
|
+
readonly folderId: string; /** The whole listing as rendered when the cursor was issued; any change is not emulated. */
|
|
32
|
+
readonly fingerprint: string;
|
|
33
|
+
readonly offset: number;
|
|
34
|
+
readonly limit: number;
|
|
35
|
+
};
|
|
36
|
+
/** A `search_v2` cursor (runtime data, not state). */
|
|
37
|
+
type DropboxSearchCursor = {
|
|
38
|
+
readonly kind: 'search';
|
|
39
|
+
readonly query: string; /** Every match as rendered when the cursor was issued; any change is not emulated. */
|
|
40
|
+
readonly fingerprint: string;
|
|
41
|
+
readonly offset: number;
|
|
42
|
+
readonly maxResults: number;
|
|
43
|
+
};
|
|
44
|
+
type DropboxCursor = DropboxListCursor | DropboxSearchCursor;
|
|
45
|
+
type DropboxApiEnv = {
|
|
46
|
+
/** Clock in epoch milliseconds (upload timestamps only). */readonly now: () => number;
|
|
47
|
+
readonly drills: Readonly<Record<keyof DropboxEmulatorDrills, boolean>>; /** Issued cursors by value (runtime-only; cleared by reset and seed). */
|
|
48
|
+
readonly cursors: Map<string, DropboxCursor>; /** Cursor numbers; never reset, so a cursor issued before a reset is never issued again. */
|
|
49
|
+
readonly cursorCounters: {
|
|
50
|
+
list: number;
|
|
51
|
+
search: number;
|
|
52
|
+
};
|
|
53
|
+
};
|
|
54
|
+
type Route = StatefulRoute<DropboxEmulatorState, DropboxApiEnv>;
|
|
55
|
+
/** Origin of the RPC routes. */
|
|
56
|
+
declare const dropboxEmulatorApiOrigin = "https://api.dropboxapi.com";
|
|
57
|
+
/** Origin of the upload route. */
|
|
58
|
+
declare const dropboxEmulatorContentOrigin = "https://content.dropboxapi.com";
|
|
59
|
+
/** The route table: evidence plus handlers. `dropboxEmulatorRoutes` is its evidence part. */
|
|
60
|
+
declare const dropboxApiRoutes: ReadonlyArray<Route>;
|
|
61
|
+
//#endregion
|
|
62
|
+
export { DropboxApiEnv, DropboxCursor, DropboxEmulatorDrills, DropboxListCursor, DropboxSearchCursor, dropboxApiRoutes, dropboxEmulatorApiOrigin, dropboxEmulatorBasePath, dropboxEmulatorContentOrigin, dropboxEmulatorDrillKnobs, dropboxEmulatorErrorBodies };
|
|
63
|
+
//# sourceMappingURL=api.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api.d.mts","names":[],"sources":["../../src/dropbox/api.ts"],"mappings":";;;;;cAwCa,uBAAA;AAAb;;;;AAAA,cAMa,0BAAA;EAAA;;;;;KAkBD,qBAAA;iGAED,oBAAA;WAEA,wBAAA,YAJsB;EAAA,SAMtB,oBAAA,YANsB;EAAA,SAQtB,oBAAA,YAJA;EAAA,SAMA,oBAAA,YAFA;EAAA,SAIA,uBAAA;EAAA,SAEA,cAAA,YAEA;EAAA,SAAA,gBAAA;AAAA;AAAA,cAGE,yBAAA,EAA2B,aAAa,OAAO,qBAAA;;KAYhD,iBAAA;EAAA,SACD,IAAA;EAAA,SACA,QAAA,UAFC;EAAA,SAID,WAAA;EAAA,SACA,MAAA;EAAA,SACA,KAAA;AAAA;;KAIC,mBAAA;EAAA,SACD,IAAA;EAAA,SACA,KAAA,UANK;EAAA,SAQL,WAAA;EAAA,SACA,MAAA;EAAA,SACA,UAAA;AAAA;AAAA,KAGC,aAAA,GAAgB,iBAAA,GAAoB,mBAAmB;AAAA,KAEvD,aAAA;EATD,qEAWA,GAAA;EAAA,SACA,MAAA,EAAQ,QAAA,CAAS,MAAA,OAAa,qBAAA,aAR9B;EAAA,SAUA,OAAA,EAAS,GAAA,SAAY,aAAA,GAVX;EAAA,SAYV,cAAA;IAAkB,IAAA;IAAc,MAAA;EAAA;AAAA;AAAA,KAGtC,KAAA,GAAQ,aAAA,CAAc,oBAAA,EAAsB,aAAA;;cAGpC,wBAAA;;cAGA,4BAAA;;cA46BA,gBAAA,EAAkB,aAAa,CAAC,KAAA"}
|