@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/notion.mjs
ADDED
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { emulatorEvidenceHeader } from "./route-evidence.mjs";
|
|
2
|
+
import { StatefulFault, StatefulFaultMatch, checkBooleanDrills, makeStatefulEmulator, routeEvidence } from "./stateful-emulator.mjs";
|
|
3
|
+
import { statefulCoreRuntime } from "./stateful-core.mjs";
|
|
4
|
+
import { NotionEmulatorBlock, NotionEmulatorBotUser, NotionEmulatorDataSource, NotionEmulatorDatabase, NotionEmulatorImpliedPage, NotionEmulatorPage, NotionEmulatorParent, NotionEmulatorProfile, NotionEmulatorPropertyItems, NotionEmulatorSeed, NotionEmulatorStateSchema, buildSeedState, decodeState } from "./notion/state.mjs";
|
|
5
|
+
import { notionApiRoutes, notionEmulatorBasePath, notionEmulatorDrillKnobs, notionEmulatorOrigin, notionEmulatorVersion } from "./notion/api.mjs";
|
|
6
|
+
import { Data, Predicate } from "effect";
|
|
7
|
+
//#region src/notion.ts
|
|
8
|
+
/**
|
|
9
|
+
* Stateful Notion emulator (the `/v1` routes on `https://api.notion.com` at API version
|
|
10
|
+
* 2025-09-03), built on the upstream `@emulators/core` custom runtime, with a request ledger,
|
|
11
|
+
* status faults, and an `/_emulate/*` control plane.
|
|
12
|
+
*
|
|
13
|
+
* It never imports SDK code: its wire shapes, error envelopes, and default seed are copied as data
|
|
14
|
+
* from the synthetic Notion conformance fixtures, and every route names the conformance cases it
|
|
15
|
+
* follows in `notionEmulatorRoutes`. Only the routes those eight cases (with their cleanup) send
|
|
16
|
+
* are emulated. Response behaviour comes only from the fixtures: anything they do not show answers
|
|
17
|
+
* one ledgered 400 not-emulated, writes nothing, and uses up no fault. That includes a search
|
|
18
|
+
* without matches or matching a trashed page, so the read-only leftover lookup fails on a clean
|
|
19
|
+
* workspace and after the write case (the live runner prints its lookup-failed WARN). Search
|
|
20
|
+
* considers only the pages whose content the state holds (an implied page never matches) and
|
|
21
|
+
* refuses a match shown only as a query row. Every route answers only on the recorded origin
|
|
22
|
+
* `https://api.notion.com` (`fetchOn(origin)` serves it behind a loopback rewrite).
|
|
23
|
+
*
|
|
24
|
+
* Request-shape latitude (`/notion`, the only accepted deviations): any bearer value (never
|
|
25
|
+
* checked or stored); extra request headers; JSON key order; `content-type` media-type
|
|
26
|
+
* parameters; the order of query parameters; Notion ids with or without dashes, in any case; any
|
|
27
|
+
* search `query` (looked up in the state); and any `page_size` from 1 to 100 whose page shows
|
|
28
|
+
* only recorded results (the data source query: 1). `Notion-Version` must be `2025-09-03`.
|
|
29
|
+
* Everything else (other keys, filters, booleans, sorts, query parameters, another origin,
|
|
30
|
+
* titles, repeated or missing `page_size`, and cursors not issued for the same list since the
|
|
31
|
+
* last reset or whose list changed) is not emulated.
|
|
32
|
+
*
|
|
33
|
+
* Node-only: `@emulators/core` imports Node builtins, so the core is loaded lazily by
|
|
34
|
+
* `makeNotionEmulator` (importing this module has no side effects).
|
|
35
|
+
*
|
|
36
|
+
* @experimental
|
|
37
|
+
*/
|
|
38
|
+
/**
|
|
39
|
+
* Route evidence manifest: every emulated route, whether it writes, and the conformance cases
|
|
40
|
+
* whose (currently synthetic, unverified) wire claims it follows. Kept in sync with the handlers
|
|
41
|
+
* by construction (both come from one route table).
|
|
42
|
+
*/
|
|
43
|
+
const notionEmulatorRoutes = notionApiRoutes.map(routeEvidence);
|
|
44
|
+
/**
|
|
45
|
+
* Optional fault filter; an omitted field matches every request. `method` is the HTTP method;
|
|
46
|
+
* `path` is the raw request path (ending in `*`, a prefix); `route` is a route template of the
|
|
47
|
+
* manifest (another value is rejected when the fault is added).
|
|
48
|
+
*/
|
|
49
|
+
const NotionFaultMatch = StatefulFaultMatch;
|
|
50
|
+
/**
|
|
51
|
+
* A status fault (400-599): answer matching requests with this status, headers, and body instead
|
|
52
|
+
* of the route's write, so nothing is written. The body defaults to
|
|
53
|
+
* `{ error: { type: 'emulator_fault', message } }`; `count` limits how many requests it answers.
|
|
54
|
+
* Only a request the emulator would answer reaches a fault: a request that is not emulated, by
|
|
55
|
+
* its shape or by the state, never uses one up.
|
|
56
|
+
*/
|
|
57
|
+
const NotionFault = StatefulFault;
|
|
58
|
+
/** Invalid emulator input from the JS API: a seed, a fault, or an option. A programmer error. */
|
|
59
|
+
var NotionEmulatorInputInvalid = class extends Data.TaggedError("NotionEmulatorInputInvalid") {
|
|
60
|
+
get message() {
|
|
61
|
+
return `Invalid Notion emulator ${this.input}: ${this.reason}`;
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
const inputInvalid = (input, reason) => new NotionEmulatorInputInvalid({
|
|
65
|
+
input,
|
|
66
|
+
reason
|
|
67
|
+
});
|
|
68
|
+
/**
|
|
69
|
+
* Create a stateful Notion emulator on the `@emulators/core` custom runtime. Each call has its
|
|
70
|
+
* own state, ledger, and faults. Rejects with `NotionEmulatorInputInvalid` for an invalid seed or
|
|
71
|
+
* option. Every request needs `Notion-Version: 2025-09-03` (else not emulated). See
|
|
72
|
+
* `src/stateful-emulator.ts` for the request precedence.
|
|
73
|
+
*/
|
|
74
|
+
const makeNotionEmulator = async (options = {}) => {
|
|
75
|
+
const initial = buildSeedState(options.seed ?? {});
|
|
76
|
+
if (Predicate.isString(initial)) throw inputInvalid("seed", initial);
|
|
77
|
+
checkBooleanDrills(options.drills, notionEmulatorDrillKnobs, inputInvalid);
|
|
78
|
+
const drills = options.drills ?? {};
|
|
79
|
+
const env = {
|
|
80
|
+
now: options.now ?? (() => Date.now()),
|
|
81
|
+
drills: {
|
|
82
|
+
searchRepeatsResults: drills.searchRepeatsResults === true,
|
|
83
|
+
botUserAsPerson: drills.botUserAsPerson === true,
|
|
84
|
+
envelopeStatusMismatch: drills.envelopeStatusMismatch === true,
|
|
85
|
+
omitTitlePlainText: drills.omitTitlePlainText === true,
|
|
86
|
+
blockCursorRepeats: drills.blockCursorRepeats === true,
|
|
87
|
+
rejectDoubleEncodedPropertyId: drills.rejectDoubleEncodedPropertyId === true,
|
|
88
|
+
rowParentAsDatabase: drills.rowParentAsDatabase === true,
|
|
89
|
+
trashedPageNotFound: drills.trashedPageNotFound === true
|
|
90
|
+
},
|
|
91
|
+
cursors: /* @__PURE__ */ new Map(),
|
|
92
|
+
propertyCursorCounter: { next: 1 },
|
|
93
|
+
generation: { current: 0 },
|
|
94
|
+
firstIssued: /* @__PURE__ */ new Map()
|
|
95
|
+
};
|
|
96
|
+
return await makeStatefulEmulator({
|
|
97
|
+
routes: notionApiRoutes,
|
|
98
|
+
env,
|
|
99
|
+
initial,
|
|
100
|
+
buildSeed: buildSeedState,
|
|
101
|
+
requestProblem: (header) => header("notion-version") === "2025-09-03" ? void 0 : `Notion-Version other than ${notionEmulatorVersion} (the version every fixture sends) is not emulated`,
|
|
102
|
+
recordHeaders: [{
|
|
103
|
+
name: "notion-version",
|
|
104
|
+
json: false
|
|
105
|
+
}],
|
|
106
|
+
clearRuntime: () => {
|
|
107
|
+
env.cursors.clear();
|
|
108
|
+
env.generation.current += 1;
|
|
109
|
+
},
|
|
110
|
+
runtimeState: () => ({}),
|
|
111
|
+
seedSummary: (state) => ({
|
|
112
|
+
pages: state.pages.length,
|
|
113
|
+
blocks: state.blocks.length,
|
|
114
|
+
dataSources: state.dataSources.length
|
|
115
|
+
}),
|
|
116
|
+
inputInvalid
|
|
117
|
+
}, statefulCoreRuntime({
|
|
118
|
+
name: "notion",
|
|
119
|
+
initial,
|
|
120
|
+
decodeState,
|
|
121
|
+
inputInvalid
|
|
122
|
+
}));
|
|
123
|
+
};
|
|
124
|
+
//#endregion
|
|
125
|
+
export { NotionEmulatorBlock, NotionEmulatorBotUser, NotionEmulatorDataSource, NotionEmulatorDatabase, NotionEmulatorImpliedPage, NotionEmulatorInputInvalid, NotionEmulatorPage, NotionEmulatorParent, NotionEmulatorProfile, NotionEmulatorPropertyItems, NotionEmulatorSeed, NotionEmulatorStateSchema, NotionFault, NotionFaultMatch, emulatorEvidenceHeader, makeNotionEmulator, notionEmulatorBasePath, notionEmulatorOrigin, notionEmulatorRoutes, notionEmulatorVersion };
|
|
126
|
+
|
|
127
|
+
//# sourceMappingURL=notion.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notion.mjs","names":[],"sources":["../src/notion.ts"],"sourcesContent":["/**\n * Stateful Notion emulator (the `/v1` routes on `https://api.notion.com` at API version\n * 2025-09-03), built on the upstream `@emulators/core` custom runtime, with a request ledger,\n * status faults, and an `/_emulate/*` control plane.\n *\n * It never imports SDK code: its wire shapes, error envelopes, and default seed are copied as data\n * from the synthetic Notion conformance fixtures, and every route names the conformance cases it\n * follows in `notionEmulatorRoutes`. Only the routes those eight cases (with their cleanup) send\n * are emulated. Response behaviour comes only from the fixtures: anything they do not show answers\n * one ledgered 400 not-emulated, writes nothing, and uses up no fault. That includes a search\n * without matches or matching a trashed page, so the read-only leftover lookup fails on a clean\n * workspace and after the write case (the live runner prints its lookup-failed WARN). Search\n * considers only the pages whose content the state holds (an implied page never matches) and\n * refuses a match shown only as a query row. Every route answers only on the recorded origin\n * `https://api.notion.com` (`fetchOn(origin)` serves it behind a loopback rewrite).\n *\n * Request-shape latitude (`/notion`, the only accepted deviations): any bearer value (never\n * checked or stored); extra request headers; JSON key order; `content-type` media-type\n * parameters; the order of query parameters; Notion ids with or without dashes, in any case; any\n * search `query` (looked up in the state); and any `page_size` from 1 to 100 whose page shows\n * only recorded results (the data source query: 1). `Notion-Version` must be `2025-09-03`.\n * Everything else (other keys, filters, booleans, sorts, query parameters, another origin,\n * titles, repeated or missing `page_size`, and cursors not issued for the same list since the\n * last reset or whose list changed) is not emulated.\n *\n * Node-only: `@emulators/core` imports Node builtins, so the core is loaded lazily by\n * `makeNotionEmulator` (importing this module has no side effects).\n *\n * @experimental\n */\nimport { Data, Predicate } from 'effect'\nimport {\n notionApiRoutes,\n notionEmulatorDrillKnobs,\n notionEmulatorVersion,\n type NotionApiEnv,\n type NotionEmulatorDrills\n} from './notion/api.ts'\nimport {\n buildSeedState,\n decodeState,\n type NotionEmulatorSeed,\n type NotionEmulatorState\n} from './notion/state.ts'\nimport type { EmulatorRouteEvidence } from './route-evidence.ts'\nimport {\n StatefulFault,\n StatefulFaultMatch,\n checkBooleanDrills,\n makeStatefulEmulator,\n routeEvidence,\n type StatefulCoverage,\n type StatefulEmulatorApi,\n type StatefulFaultState,\n type StatefulInputKind,\n type StatefulLedgerEntry\n} from './stateful-emulator.ts'\nimport { statefulCoreRuntime } from './stateful-core.ts'\n\nexport type { EmulatorEvidence, EmulatorRouteEvidence } from './route-evidence.ts'\n\nexport { emulatorEvidenceHeader } from './route-evidence.ts'\n\nexport {\n notionEmulatorBasePath,\n notionEmulatorOrigin,\n notionEmulatorVersion,\n type NotionEmulatorDrills\n} from './notion/api.ts'\n\nexport {\n NotionEmulatorBlock,\n NotionEmulatorBotUser,\n NotionEmulatorDataSource,\n NotionEmulatorDatabase,\n NotionEmulatorImpliedPage,\n NotionEmulatorPage,\n NotionEmulatorParent,\n NotionEmulatorProfile,\n NotionEmulatorPropertyItems,\n NotionEmulatorSeed,\n NotionEmulatorStateSchema,\n type NotionEmulatorState\n} from './notion/state.ts'\n\n/**\n * Route evidence manifest: every emulated route, whether it writes, and the conformance cases\n * whose (currently synthetic, unverified) wire claims it follows. Kept in sync with the handlers\n * by construction (both come from one route table).\n */\nexport const notionEmulatorRoutes: ReadonlyArray<EmulatorRouteEvidence> =\n notionApiRoutes.map(routeEvidence)\n\n/**\n * Optional fault filter; an omitted field matches every request. `method` is the HTTP method;\n * `path` is the raw request path (ending in `*`, a prefix); `route` is a route template of the\n * manifest (another value is rejected when the fault is added).\n */\nexport const NotionFaultMatch = StatefulFaultMatch\n\nexport type NotionFaultMatch = typeof StatefulFaultMatch.Type\n\n/**\n * A status fault (400-599): answer matching requests with this status, headers, and body instead\n * of the route's write, so nothing is written. The body defaults to\n * `{ error: { type: 'emulator_fault', message } }`; `count` limits how many requests it answers.\n * Only a request the emulator would answer reaches a fault: a request that is not emulated, by\n * its shape or by the state, never uses one up.\n */\nexport const NotionFault = StatefulFault\n\nexport type NotionFault = StatefulFault\n\nexport type NotionFaultState = StatefulFaultState\n\nexport type NotionLedgerEntry = StatefulLedgerEntry\n\nexport type NotionCoverage = StatefulCoverage\n\n/** Invalid emulator input from the JS API: a seed, a fault, or an option. A programmer error. */\nexport class NotionEmulatorInputInvalid extends Data.TaggedError('NotionEmulatorInputInvalid')<{\n readonly input: StatefulInputKind\n readonly reason: string\n}> {\n override get message(): string {\n return `Invalid Notion emulator ${this.input}: ${this.reason}`\n }\n}\n\nexport type NotionEmulatorOptions = {\n /** Typed seed; defaults to the fixture entities (`profile: 'default'`). */\n readonly seed?: NotionEmulatorSeed\n /** Clock in epoch milliseconds (created page timestamps). Defaults to `Date.now`. */\n readonly now?: () => number\n /** Drill knobs (tests only): make the emulator disagree with one conformance claim. */\n readonly drills?: NotionEmulatorDrills\n}\n\nexport type NotionEmulator = StatefulEmulatorApi<NotionEmulatorState, NotionEmulatorSeed>\n\nconst inputInvalid = (input: StatefulInputKind, reason: string) =>\n new NotionEmulatorInputInvalid({ input, reason })\n\n/**\n * Create a stateful Notion emulator on the `@emulators/core` custom runtime. Each call has its\n * own state, ledger, and faults. Rejects with `NotionEmulatorInputInvalid` for an invalid seed or\n * option. Every request needs `Notion-Version: 2025-09-03` (else not emulated). See\n * `src/stateful-emulator.ts` for the request precedence.\n */\nexport const makeNotionEmulator = async (\n options: NotionEmulatorOptions = {}\n): Promise<NotionEmulator> => {\n const initial = buildSeedState(options.seed ?? {})\n\n if (Predicate.isString(initial)) {\n throw inputInvalid('seed', initial)\n }\n\n checkBooleanDrills(options.drills, notionEmulatorDrillKnobs, inputInvalid)\n\n const drills = options.drills ?? {}\n\n const env: NotionApiEnv = {\n now: options.now ?? (() => Date.now()),\n drills: {\n searchRepeatsResults: drills.searchRepeatsResults === true,\n botUserAsPerson: drills.botUserAsPerson === true,\n envelopeStatusMismatch: drills.envelopeStatusMismatch === true,\n omitTitlePlainText: drills.omitTitlePlainText === true,\n blockCursorRepeats: drills.blockCursorRepeats === true,\n rejectDoubleEncodedPropertyId: drills.rejectDoubleEncodedPropertyId === true,\n rowParentAsDatabase: drills.rowParentAsDatabase === true,\n trashedPageNotFound: drills.trashedPageNotFound === true\n },\n cursors: new Map(),\n propertyCursorCounter: { next: 1 },\n generation: { current: 0 },\n firstIssued: new Map()\n }\n\n const api = await makeStatefulEmulator<NotionEmulatorState, NotionApiEnv, NotionEmulatorSeed>(\n {\n routes: notionApiRoutes,\n env,\n initial,\n buildSeed: buildSeedState,\n requestProblem: header =>\n header('notion-version') === notionEmulatorVersion\n ? undefined\n : `Notion-Version other than ${notionEmulatorVersion} (the version every fixture sends) is not emulated`,\n recordHeaders: [{ name: 'notion-version', json: false }],\n // Cursor values never cross a reset or seed: property cursor numbers keep advancing, and the\n // generation makes later search and block cursors distinct from earlier ones.\n clearRuntime: () => {\n env.cursors.clear()\n env.generation.current += 1\n },\n runtimeState: () => ({}),\n seedSummary: state => ({\n pages: state.pages.length,\n blocks: state.blocks.length,\n dataSources: state.dataSources.length\n }),\n inputInvalid\n },\n statefulCoreRuntime({ name: 'notion', initial, decodeState, inputInvalid })\n )\n\n return api\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0FA,MAAa,uBACX,gBAAgB,IAAI,aAAa;;;;;;AAOnC,MAAa,mBAAmB;;;;;;;;AAWhC,MAAa,cAAc;;AAW3B,IAAa,6BAAb,cAAgD,KAAK,YAAY,4BAA4B,EAG1F;CACD,IAAa,UAAkB;EAC7B,OAAO,2BAA2B,KAAK,MAAM,IAAI,KAAK;CACxD;AACF;AAaA,MAAM,gBAAgB,OAA0B,WAC9C,IAAI,2BAA2B;CAAE;CAAO;AAAO,CAAC;;;;;;;AAQlD,MAAa,qBAAqB,OAChC,UAAiC,CAAC,MACN;CAC5B,MAAM,UAAU,eAAe,QAAQ,QAAQ,CAAC,CAAC;CAEjD,IAAI,UAAU,SAAS,OAAO,GAC5B,MAAM,aAAa,QAAQ,OAAO;CAGpC,mBAAmB,QAAQ,QAAQ,0BAA0B,YAAY;CAEzE,MAAM,SAAS,QAAQ,UAAU,CAAC;CAElC,MAAM,MAAoB;EACxB,KAAK,QAAQ,cAAc,KAAK,IAAI;EACpC,QAAQ;GACN,sBAAsB,OAAO,yBAAyB;GACtD,iBAAiB,OAAO,oBAAoB;GAC5C,wBAAwB,OAAO,2BAA2B;GAC1D,oBAAoB,OAAO,uBAAuB;GAClD,oBAAoB,OAAO,uBAAuB;GAClD,+BAA+B,OAAO,kCAAkC;GACxE,qBAAqB,OAAO,wBAAwB;GACpD,qBAAqB,OAAO,wBAAwB;EACtD;EACA,yBAAS,IAAI,IAAI;EACjB,uBAAuB,EAAE,MAAM,EAAE;EACjC,YAAY,EAAE,SAAS,EAAE;EACzB,6BAAa,IAAI,IAAI;CACvB;CA8BA,OAAO,MA5BW,qBAChB;EACE,QAAQ;EACR;EACA;EACA,WAAW;EACX,iBAAgB,WACd,OAAO,gBAAgB,MAAA,eACnB,KAAA,IACA,6BAA6B,sBAAsB;EACzD,eAAe,CAAC;GAAE,MAAM;GAAkB,MAAM;EAAM,CAAC;EAGvD,oBAAoB;GAClB,IAAI,QAAQ,MAAM;GAClB,IAAI,WAAW,WAAW;EAC5B;EACA,qBAAqB,CAAC;EACtB,cAAa,WAAU;GACrB,OAAO,MAAM,MAAM;GACnB,QAAQ,MAAM,OAAO;GACrB,aAAa,MAAM,YAAY;EACjC;EACA;CACF,GACA,oBAAoB;EAAE,MAAM;EAAU;EAAS;EAAa;CAAa,CAAC,CAC5E;AAGF"}
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import { EmulatorEvidence, EmulatorRouteEvidence, emulatorEvidenceHeader } from "./route-evidence.mjs";
|
|
2
|
+
import { ChatCompletionsEmulator, ChatCoverage, ChatFault, ChatFaultKind, ChatFaultMatch, ChatFaultState, ChatLedgerEntry, ChatRouteCoverage, ChatScriptedError, ChatScriptedToolCall, ChatScriptedUsage } from "./chat-completions.mjs";
|
|
3
|
+
import * as Schema from "effect/Schema";
|
|
4
|
+
|
|
5
|
+
//#region src/openai.d.ts
|
|
6
|
+
declare const openAiChatCompletionsPath = "/v1/chat/completions";
|
|
7
|
+
/** Synthetic-safe default model ids, including the OpenAI chat conformance defaults. */
|
|
8
|
+
declare const openAiEmulatorDefaultModels: ReadonlyArray<string>;
|
|
9
|
+
/**
|
|
10
|
+
* Route evidence manifest: every emulated OpenAI route and the conformance
|
|
11
|
+
* cases whose (currently synthetic, unverified) wire shapes it follows.
|
|
12
|
+
*/
|
|
13
|
+
declare const openAiEmulatorRoutes: ReadonlyArray<EmulatorRouteEvidence>;
|
|
14
|
+
/** Optional fault filter; an omitted field matches every request. `path` ending in `*` is a prefix. */
|
|
15
|
+
declare const OpenAiFaultMatch: Schema.Struct<{
|
|
16
|
+
readonly path: Schema.optionalKey<Schema.String>;
|
|
17
|
+
readonly model: Schema.optionalKey<Schema.String>;
|
|
18
|
+
}>;
|
|
19
|
+
type OpenAiFaultMatch = ChatFaultMatch;
|
|
20
|
+
/**
|
|
21
|
+
* Wire faults for emulated routes, the same kinds as the Gateway emulator:
|
|
22
|
+
* `status` (the body defaults to an OpenAI error envelope),
|
|
23
|
+
* `error-after-chunks`, and `truncate-after-chunks`. Statuses that cannot
|
|
24
|
+
* carry a body and redirects are rejected, as are invalid headers and
|
|
25
|
+
* `location`. A chunk fault that cannot take effect answers 500 and is not
|
|
26
|
+
* consumed.
|
|
27
|
+
*/
|
|
28
|
+
declare const OpenAiFault: Schema.Union<readonly [Schema.Struct<{
|
|
29
|
+
readonly match: Schema.optionalKey<Schema.Struct<{
|
|
30
|
+
readonly path: Schema.optionalKey<Schema.String>;
|
|
31
|
+
readonly model: Schema.optionalKey<Schema.String>;
|
|
32
|
+
}>>;
|
|
33
|
+
readonly count: Schema.optionalKey<Schema.Int>;
|
|
34
|
+
readonly kind: Schema.Literal<"status">;
|
|
35
|
+
readonly status: Schema.Int;
|
|
36
|
+
readonly headers: Schema.optionalKey<Schema.$Record<Schema.String, Schema.String>>;
|
|
37
|
+
readonly body: Schema.optionalKey<Schema.Codec<Schema.Json, Schema.Json, never, never>>;
|
|
38
|
+
}>, Schema.Struct<{
|
|
39
|
+
readonly match: Schema.optionalKey<Schema.Struct<{
|
|
40
|
+
readonly path: Schema.optionalKey<Schema.String>;
|
|
41
|
+
readonly model: Schema.optionalKey<Schema.String>;
|
|
42
|
+
}>>;
|
|
43
|
+
readonly count: Schema.optionalKey<Schema.Int>;
|
|
44
|
+
readonly kind: Schema.Literal<"error-after-chunks">;
|
|
45
|
+
readonly chunks: Schema.Int;
|
|
46
|
+
}>, Schema.Struct<{
|
|
47
|
+
readonly match: Schema.optionalKey<Schema.Struct<{
|
|
48
|
+
readonly path: Schema.optionalKey<Schema.String>;
|
|
49
|
+
readonly model: Schema.optionalKey<Schema.String>;
|
|
50
|
+
}>>;
|
|
51
|
+
readonly count: Schema.optionalKey<Schema.Int>;
|
|
52
|
+
readonly kind: Schema.Literal<"truncate-after-chunks">;
|
|
53
|
+
readonly chunks: Schema.Int;
|
|
54
|
+
}>]>;
|
|
55
|
+
type OpenAiFault = ChatFault;
|
|
56
|
+
type OpenAiFaultKind = ChatFaultKind;
|
|
57
|
+
/** Usage for a scripted turn (sent as the wire `usage` object). */
|
|
58
|
+
declare const OpenAiScriptedUsage: Schema.Struct<{
|
|
59
|
+
readonly promptTokens: Schema.Int;
|
|
60
|
+
readonly completionTokens: Schema.Int;
|
|
61
|
+
readonly reasoningTokens: Schema.optionalKey<Schema.Int>;
|
|
62
|
+
}>;
|
|
63
|
+
type OpenAiScriptedUsage = ChatScriptedUsage;
|
|
64
|
+
/** One scripted tool call; its JSON arguments stream as these fragments. */
|
|
65
|
+
declare const OpenAiScriptedToolCall: Schema.Struct<{
|
|
66
|
+
readonly name: Schema.NonEmptyString;
|
|
67
|
+
readonly argumentFragments: Schema.$Array<Schema.String>;
|
|
68
|
+
readonly id: Schema.optionalKey<Schema.NonEmptyString>;
|
|
69
|
+
}>;
|
|
70
|
+
type OpenAiScriptedToolCall = ChatScriptedToolCall;
|
|
71
|
+
/**
|
|
72
|
+
* A scripted completion. Every field is exact (nothing is filled in) except:
|
|
73
|
+
* `usage` omitted is synthesized when the request asks for usage, and `null`
|
|
74
|
+
* drops it; `finishReason` omitted is `tool_calls` with tool calls, else
|
|
75
|
+
* `stop`. Reasoning is not emulated: reasoning fields are rejected.
|
|
76
|
+
*/
|
|
77
|
+
declare const OpenAiScriptedCompletion: Schema.Struct<{
|
|
78
|
+
text: Schema.optionalKey<Schema.$Array<Schema.String>>;
|
|
79
|
+
toolCalls: Schema.optionalKey<Schema.$Array<Schema.Struct<{
|
|
80
|
+
readonly name: Schema.NonEmptyString;
|
|
81
|
+
readonly argumentFragments: Schema.$Array<Schema.String>;
|
|
82
|
+
readonly id: Schema.optionalKey<Schema.NonEmptyString>;
|
|
83
|
+
}>>>;
|
|
84
|
+
usage: Schema.optionalKey<Schema.NullOr<Schema.Struct<{
|
|
85
|
+
readonly promptTokens: Schema.Int;
|
|
86
|
+
readonly completionTokens: Schema.Int;
|
|
87
|
+
readonly reasoningTokens: Schema.optionalKey<Schema.Int>;
|
|
88
|
+
}>>>;
|
|
89
|
+
finishReason: Schema.optionalKey<Schema.NonEmptyString>;
|
|
90
|
+
}>;
|
|
91
|
+
type OpenAiScriptedCompletion = typeof OpenAiScriptedCompletion.Type;
|
|
92
|
+
/** A scripted error response: status, body (a string is sent as is), and optional headers. */
|
|
93
|
+
declare const OpenAiScriptedError: Schema.Struct<{
|
|
94
|
+
readonly error: Schema.Struct<{
|
|
95
|
+
readonly status: Schema.Int;
|
|
96
|
+
readonly body: Schema.Codec<Schema.Json, Schema.Json, never, never>;
|
|
97
|
+
readonly headers: Schema.optionalKey<Schema.$Record<Schema.String, Schema.String>>;
|
|
98
|
+
}>;
|
|
99
|
+
}>;
|
|
100
|
+
type OpenAiScriptedError = ChatScriptedError;
|
|
101
|
+
/** A turn queued for the next chat completion request. */
|
|
102
|
+
declare const OpenAiScriptedTurn: Schema.Union<readonly [Schema.Struct<{
|
|
103
|
+
readonly error: Schema.Struct<{
|
|
104
|
+
readonly status: Schema.Int;
|
|
105
|
+
readonly body: Schema.Codec<Schema.Json, Schema.Json, never, never>;
|
|
106
|
+
readonly headers: Schema.optionalKey<Schema.$Record<Schema.String, Schema.String>>;
|
|
107
|
+
}>;
|
|
108
|
+
}>, Schema.Struct<{
|
|
109
|
+
text: Schema.optionalKey<Schema.$Array<Schema.String>>;
|
|
110
|
+
toolCalls: Schema.optionalKey<Schema.$Array<Schema.Struct<{
|
|
111
|
+
readonly name: Schema.NonEmptyString;
|
|
112
|
+
readonly argumentFragments: Schema.$Array<Schema.String>;
|
|
113
|
+
readonly id: Schema.optionalKey<Schema.NonEmptyString>;
|
|
114
|
+
}>>>;
|
|
115
|
+
usage: Schema.optionalKey<Schema.NullOr<Schema.Struct<{
|
|
116
|
+
readonly promptTokens: Schema.Int;
|
|
117
|
+
readonly completionTokens: Schema.Int;
|
|
118
|
+
readonly reasoningTokens: Schema.optionalKey<Schema.Int>;
|
|
119
|
+
}>>>;
|
|
120
|
+
finishReason: Schema.optionalKey<Schema.NonEmptyString>;
|
|
121
|
+
}>]>;
|
|
122
|
+
type OpenAiScriptedTurn = typeof OpenAiScriptedTurn.Type;
|
|
123
|
+
declare const OpenAiEmulatorInputInvalid_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 & {
|
|
124
|
+
readonly _tag: "OpenAiEmulatorInputInvalid";
|
|
125
|
+
} & Readonly<A>;
|
|
126
|
+
/** Thrown by the JS API (`faults.add`, `script.enqueue`) for invalid input; a programmer error. */
|
|
127
|
+
declare class OpenAiEmulatorInputInvalid extends OpenAiEmulatorInputInvalid_base<{
|
|
128
|
+
readonly input: 'fault' | 'turn';
|
|
129
|
+
readonly reason: string;
|
|
130
|
+
}> {
|
|
131
|
+
get message(): string;
|
|
132
|
+
}
|
|
133
|
+
type OpenAiLedgerEntry = ChatLedgerEntry;
|
|
134
|
+
type OpenAiFaultState = ChatFaultState;
|
|
135
|
+
type OpenAiRouteCoverage = ChatRouteCoverage;
|
|
136
|
+
type OpenAiCoverage = ChatCoverage;
|
|
137
|
+
type OpenAiEmulatorOptions = {
|
|
138
|
+
/** Model ids that exist. Defaults to `openAiEmulatorDefaultModels`. */readonly knownModels?: ReadonlyArray<string>;
|
|
139
|
+
};
|
|
140
|
+
type OpenAiEmulator = ChatCompletionsEmulator<OpenAiScriptedTurn>;
|
|
141
|
+
/**
|
|
142
|
+
* Create an OpenAI Chat Completions emulator. Each call has independent
|
|
143
|
+
* ledger, fault, and script state.
|
|
144
|
+
*
|
|
145
|
+
* Without a script, `POST /v1/chat/completions` answers a known model with
|
|
146
|
+
* synthetic text deltas (`stream: true`: `chat.completion.chunk` SSE, a finish
|
|
147
|
+
* chunk, a usage chunk when `stream_options.include_usage` is set, and
|
|
148
|
+
* `data: [DONE]`; `stream: false`: one `chat.completion` JSON body). A request
|
|
149
|
+
* with `tools` gets one tool call whose arguments are synthesized from the
|
|
150
|
+
* tool's JSON Schema and streamed in fragments, finishing with `tool_calls`.
|
|
151
|
+
* Unknown models get the OpenAI error envelope (404, `model_not_found`); a
|
|
152
|
+
* missing bearer credential gets a 401 envelope (`invalid_api_key`); unknown
|
|
153
|
+
* routes get a 404 JSON error. The ledger records the
|
|
154
|
+
* `max_completion_tokens` limit as `maxCompletionTokens`.
|
|
155
|
+
*
|
|
156
|
+
* Precedence per chat request matches the Gateway emulator: authentication and
|
|
157
|
+
* JSON validation, then the first matching `status` fault, then the next
|
|
158
|
+
* scripted turn, then model validation and defaults; a first matching chunk
|
|
159
|
+
* fault then shapes the body. Credential headers are never recorded, and the
|
|
160
|
+
* bearer value is never checked or stored.
|
|
161
|
+
*/
|
|
162
|
+
declare const makeOpenAiEmulator: (options?: OpenAiEmulatorOptions) => OpenAiEmulator;
|
|
163
|
+
//#endregion
|
|
164
|
+
export { type EmulatorEvidence, type EmulatorRouteEvidence, OpenAiCoverage, OpenAiEmulator, OpenAiEmulatorInputInvalid, OpenAiEmulatorOptions, OpenAiFault, OpenAiFaultKind, OpenAiFaultMatch, OpenAiFaultState, OpenAiLedgerEntry, OpenAiRouteCoverage, OpenAiScriptedCompletion, OpenAiScriptedError, OpenAiScriptedToolCall, OpenAiScriptedTurn, OpenAiScriptedUsage, emulatorEvidenceHeader, makeOpenAiEmulator, openAiChatCompletionsPath, openAiEmulatorDefaultModels, openAiEmulatorRoutes };
|
|
165
|
+
//# sourceMappingURL=openai.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openai.d.mts","names":[],"sources":["../src/openai.ts"],"mappings":";;;;;cA4Ca,yBAAA;;cAGA,2BAAA,EAA6B,aAAa;;AAHjB;AAGtC;;cAMa,oBAAA,EAAsB,aAAa,CAAC,qBAAA;;cAkBpC,gBAAA,EAAgB,MAAA,CAAA,MAAA;EAAA;;;KAEjB,gBAAA,GAAmB,cAAc;AApByB;AAkBtE;;;;;;;AAlBsE,cA8BzD,WAAA,EAAW,MAAA,CAAA,KAAA,WAAA,MAAA,CAAA,MAAA;EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;KAEZ,WAAA,GAAc,SAAS;AAAA,KAEvB,eAAA,GAAkB,aAAa;;cAG9B,mBAAA,EAAmB,MAAA,CAAA,MAAA;EAAA;;;;KAEpB,mBAAA,GAAsB,iBAAiB;;cAGtC,sBAAA,EAAsB,MAAA,CAAA,MAAA;EAAA;;;;KAEvB,sBAAA,GAAyB,oBAAoB;;;;;;;cAQ5C,wBAAA,EAAwB,MAAA,CAAA,MAAA;;;;;;;;;;;;;;KAEzB,wBAAA,UAAkC,wBAAA,CAAyB,IAAI;;cAG9D,mBAAA,EAAmB,MAAA,CAAA,MAAA;EAAA;;;;;;KAEpB,mBAAA,GAAsB,iBAAiB;;cAGtC,kBAAA,EAAkB,MAAA,CAAA,KAAA,WAAA,MAAA,CAAA,MAAA;EAAA;;;;;;;;;;;;;;;;;;;KAEnB,kBAAA,UAA4B,kBAAA,CAAmB,IAAI;AAAA,cAAA,+BAAA;;;;cAGlD,0BAAA,SAAmC,+BAAA;EAAA,SACrC,KAAA;EAAA,SACA,MAAA;AAAA;EAAA,IAEI,OAAA,CAAA;AAAA;AAAA,KAKH,iBAAA,GAAoB,eAAe;AAAA,KAEnC,gBAAA,GAAmB,cAAc;AAAA,KAEjC,mBAAA,GAAsB,iBAAiB;AAAA,KAEvC,cAAA,GAAiB,YAAY;AAAA,KAE7B,qBAAA;kFAED,WAAA,GAAc,aAAa;AAAA;AAAA,KAG1B,cAAA,GAAiB,uBAAuB,CAAC,kBAAA;;;;;;;;;;;;;;;;;;;;;;cA2BxC,kBAAA,GAAsB,OAAA,GAAS,qBAAA,KAA6B,cA4BrE"}
|
package/dist/openai.mjs
ADDED
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import { emulatorEvidenceHeader } from "./route-evidence.mjs";
|
|
2
|
+
import { ChatFault, ChatFaultMatch, ChatScriptedError, ChatScriptedToolCall, ChatScriptedUsage, chatScriptedCompletionFields, makeChatCompletionsEmulator } from "./chat-completions.mjs";
|
|
3
|
+
import { Data } from "effect";
|
|
4
|
+
import * as Schema from "effect/Schema";
|
|
5
|
+
//#region src/openai.ts
|
|
6
|
+
/**
|
|
7
|
+
* OpenAI Chat Completions emulator: a plain fetch handler for
|
|
8
|
+
* `POST /v1/chat/completions` (origin `https://api.openai.com`), with scripted
|
|
9
|
+
* turns, wire faults, a request ledger, and an `/_emulate/*` control plane.
|
|
10
|
+
*
|
|
11
|
+
* It never imports SDK code: its wire shapes follow the synthetic OpenAI chat
|
|
12
|
+
* conformance fixtures (`chat.completion.chunk` SSE, usage chunk,
|
|
13
|
+
* `data: [DONE]`, the `chat.completion` JSON body, and the
|
|
14
|
+
* `{ error: { message, type, param, code } }` envelope) and are linked to
|
|
15
|
+
* those conformance case ids in `openAiEmulatorRoutes`. The Chat Completions
|
|
16
|
+
* machinery is shared with the Gateway emulator (`chat-completions.ts`).
|
|
17
|
+
*
|
|
18
|
+
* Reasoning models are not emulated yet: no default model streams reasoning,
|
|
19
|
+
* and scripted turns cannot carry reasoning.
|
|
20
|
+
*
|
|
21
|
+
* Runtime-portable Web APIs only (`Request`, `Response`, `ReadableStream`,
|
|
22
|
+
* `TextEncoder`, `URL`); no Effect runtime is required to use it.
|
|
23
|
+
*
|
|
24
|
+
* @experimental
|
|
25
|
+
*/
|
|
26
|
+
const openAiChatCompletionsPath = "/v1/chat/completions";
|
|
27
|
+
/** Synthetic-safe default model ids, including the OpenAI chat conformance defaults. */
|
|
28
|
+
const openAiEmulatorDefaultModels = ["gpt-4.1-nano", "gpt-4.1-mini"];
|
|
29
|
+
/**
|
|
30
|
+
* Route evidence manifest: every emulated OpenAI route and the conformance
|
|
31
|
+
* cases whose (currently synthetic, unverified) wire shapes it follows.
|
|
32
|
+
*/
|
|
33
|
+
const openAiEmulatorRoutes = [{
|
|
34
|
+
method: "POST",
|
|
35
|
+
path: openAiChatCompletionsPath,
|
|
36
|
+
kind: "provider",
|
|
37
|
+
write: false,
|
|
38
|
+
caseIds: [
|
|
39
|
+
"openai.chat.stream.plain-text",
|
|
40
|
+
"openai.chat.stream.tool-call-deltas",
|
|
41
|
+
"openai.chat.stream.error-envelope",
|
|
42
|
+
"openai.chat.json.plain-text"
|
|
43
|
+
],
|
|
44
|
+
evidence: "unverified",
|
|
45
|
+
observedAt: void 0
|
|
46
|
+
}];
|
|
47
|
+
/** Optional fault filter; an omitted field matches every request. `path` ending in `*` is a prefix. */
|
|
48
|
+
const OpenAiFaultMatch = ChatFaultMatch;
|
|
49
|
+
/**
|
|
50
|
+
* Wire faults for emulated routes, the same kinds as the Gateway emulator:
|
|
51
|
+
* `status` (the body defaults to an OpenAI error envelope),
|
|
52
|
+
* `error-after-chunks`, and `truncate-after-chunks`. Statuses that cannot
|
|
53
|
+
* carry a body and redirects are rejected, as are invalid headers and
|
|
54
|
+
* `location`. A chunk fault that cannot take effect answers 500 and is not
|
|
55
|
+
* consumed.
|
|
56
|
+
*/
|
|
57
|
+
const OpenAiFault = ChatFault;
|
|
58
|
+
/** Usage for a scripted turn (sent as the wire `usage` object). */
|
|
59
|
+
const OpenAiScriptedUsage = ChatScriptedUsage;
|
|
60
|
+
/** One scripted tool call; its JSON arguments stream as these fragments. */
|
|
61
|
+
const OpenAiScriptedToolCall = ChatScriptedToolCall;
|
|
62
|
+
/**
|
|
63
|
+
* A scripted completion. Every field is exact (nothing is filled in) except:
|
|
64
|
+
* `usage` omitted is synthesized when the request asks for usage, and `null`
|
|
65
|
+
* drops it; `finishReason` omitted is `tool_calls` with tool calls, else
|
|
66
|
+
* `stop`. Reasoning is not emulated: reasoning fields are rejected.
|
|
67
|
+
*/
|
|
68
|
+
const OpenAiScriptedCompletion = Schema.Struct(chatScriptedCompletionFields);
|
|
69
|
+
/** A scripted error response: status, body (a string is sent as is), and optional headers. */
|
|
70
|
+
const OpenAiScriptedError = ChatScriptedError;
|
|
71
|
+
/** A turn queued for the next chat completion request. */
|
|
72
|
+
const OpenAiScriptedTurn = Schema.Union([OpenAiScriptedError, OpenAiScriptedCompletion]);
|
|
73
|
+
/** Thrown by the JS API (`faults.add`, `script.enqueue`) for invalid input; a programmer error. */
|
|
74
|
+
var OpenAiEmulatorInputInvalid = class extends Data.TaggedError("OpenAiEmulatorInputInvalid") {
|
|
75
|
+
get message() {
|
|
76
|
+
return `Invalid OpenAI emulator ${this.input}: ${this.reason}`;
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
const openAiErrorEnvelope = (error) => ({ error: {
|
|
80
|
+
message: error.message,
|
|
81
|
+
type: error.type,
|
|
82
|
+
param: null,
|
|
83
|
+
code: error.code
|
|
84
|
+
} });
|
|
85
|
+
/**
|
|
86
|
+
* Create an OpenAI Chat Completions emulator. Each call has independent
|
|
87
|
+
* ledger, fault, and script state.
|
|
88
|
+
*
|
|
89
|
+
* Without a script, `POST /v1/chat/completions` answers a known model with
|
|
90
|
+
* synthetic text deltas (`stream: true`: `chat.completion.chunk` SSE, a finish
|
|
91
|
+
* chunk, a usage chunk when `stream_options.include_usage` is set, and
|
|
92
|
+
* `data: [DONE]`; `stream: false`: one `chat.completion` JSON body). A request
|
|
93
|
+
* with `tools` gets one tool call whose arguments are synthesized from the
|
|
94
|
+
* tool's JSON Schema and streamed in fragments, finishing with `tool_calls`.
|
|
95
|
+
* Unknown models get the OpenAI error envelope (404, `model_not_found`); a
|
|
96
|
+
* missing bearer credential gets a 401 envelope (`invalid_api_key`); unknown
|
|
97
|
+
* routes get a 404 JSON error. The ledger records the
|
|
98
|
+
* `max_completion_tokens` limit as `maxCompletionTokens`.
|
|
99
|
+
*
|
|
100
|
+
* Precedence per chat request matches the Gateway emulator: authentication and
|
|
101
|
+
* JSON validation, then the first matching `status` fault, then the next
|
|
102
|
+
* scripted turn, then model validation and defaults; a first matching chunk
|
|
103
|
+
* fault then shapes the body. Credential headers are never recorded, and the
|
|
104
|
+
* bearer value is never checked or stored.
|
|
105
|
+
*/
|
|
106
|
+
const makeOpenAiEmulator = (options = {}) => makeChatCompletionsEmulator({
|
|
107
|
+
path: openAiChatCompletionsPath,
|
|
108
|
+
routes: openAiEmulatorRoutes,
|
|
109
|
+
knownModels: options.knownModels ?? openAiEmulatorDefaultModels,
|
|
110
|
+
reasoningModels: void 0,
|
|
111
|
+
errorEnvelope: openAiErrorEnvelope,
|
|
112
|
+
unknownModel: {
|
|
113
|
+
status: 404,
|
|
114
|
+
error: {
|
|
115
|
+
message: "Synthetic placeholder: the requested model does not exist.",
|
|
116
|
+
type: "invalid_request_error",
|
|
117
|
+
code: "model_not_found"
|
|
118
|
+
}
|
|
119
|
+
},
|
|
120
|
+
auth: { unauthorized: {
|
|
121
|
+
message: "Synthetic: missing or invalid API key.",
|
|
122
|
+
type: "invalid_request_error",
|
|
123
|
+
code: "invalid_api_key"
|
|
124
|
+
} },
|
|
125
|
+
completionTokenField: "max_completion_tokens",
|
|
126
|
+
responseIdPrefix: "chatcmpl-synthetic",
|
|
127
|
+
defaultText: [
|
|
128
|
+
"Hello",
|
|
129
|
+
" from the",
|
|
130
|
+
" synthetic OpenAI emulator."
|
|
131
|
+
],
|
|
132
|
+
turnSchema: OpenAiScriptedTurn,
|
|
133
|
+
inputInvalid: (input, reason) => new OpenAiEmulatorInputInvalid({
|
|
134
|
+
input,
|
|
135
|
+
reason
|
|
136
|
+
})
|
|
137
|
+
});
|
|
138
|
+
//#endregion
|
|
139
|
+
export { OpenAiEmulatorInputInvalid, OpenAiFault, OpenAiFaultMatch, OpenAiScriptedCompletion, OpenAiScriptedError, OpenAiScriptedToolCall, OpenAiScriptedTurn, OpenAiScriptedUsage, emulatorEvidenceHeader, makeOpenAiEmulator, openAiChatCompletionsPath, openAiEmulatorDefaultModels, openAiEmulatorRoutes };
|
|
140
|
+
|
|
141
|
+
//# sourceMappingURL=openai.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openai.mjs","names":[],"sources":["../src/openai.ts"],"sourcesContent":["/**\n * OpenAI Chat Completions emulator: a plain fetch handler for\n * `POST /v1/chat/completions` (origin `https://api.openai.com`), with scripted\n * turns, wire faults, a request ledger, and an `/_emulate/*` control plane.\n *\n * It never imports SDK code: its wire shapes follow the synthetic OpenAI chat\n * conformance fixtures (`chat.completion.chunk` SSE, usage chunk,\n * `data: [DONE]`, the `chat.completion` JSON body, and the\n * `{ error: { message, type, param, code } }` envelope) and are linked to\n * those conformance case ids in `openAiEmulatorRoutes`. The Chat Completions\n * machinery is shared with the Gateway emulator (`chat-completions.ts`).\n *\n * Reasoning models are not emulated yet: no default model streams reasoning,\n * and scripted turns cannot carry reasoning.\n *\n * Runtime-portable Web APIs only (`Request`, `Response`, `ReadableStream`,\n * `TextEncoder`, `URL`); no Effect runtime is required to use it.\n *\n * @experimental\n */\nimport { Data } from 'effect'\nimport * as Schema from 'effect/Schema'\nimport {\n ChatFault,\n ChatFaultMatch,\n ChatScriptedError,\n ChatScriptedToolCall,\n ChatScriptedUsage,\n chatScriptedCompletionFields,\n makeChatCompletionsEmulator,\n type ChatCompletionsEmulator,\n type ChatCoverage,\n type ChatFaultKind,\n type ChatFaultState,\n type ChatLedgerEntry,\n type ChatRouteCoverage,\n type ChatWireError\n} from './chat-completions.ts'\nimport type { EmulatorRouteEvidence } from './route-evidence.ts'\n\nexport type { EmulatorEvidence, EmulatorRouteEvidence } from './route-evidence.ts'\n\nexport { emulatorEvidenceHeader } from './route-evidence.ts'\n\nexport const openAiChatCompletionsPath = '/v1/chat/completions'\n\n/** Synthetic-safe default model ids, including the OpenAI chat conformance defaults. */\nexport const openAiEmulatorDefaultModels: ReadonlyArray<string> = ['gpt-4.1-nano', 'gpt-4.1-mini']\n\n/**\n * Route evidence manifest: every emulated OpenAI route and the conformance\n * cases whose (currently synthetic, unverified) wire shapes it follows.\n */\nexport const openAiEmulatorRoutes: ReadonlyArray<EmulatorRouteEvidence> = [\n {\n method: 'POST',\n path: openAiChatCompletionsPath,\n kind: 'provider',\n write: false,\n caseIds: [\n 'openai.chat.stream.plain-text',\n 'openai.chat.stream.tool-call-deltas',\n 'openai.chat.stream.error-envelope',\n 'openai.chat.json.plain-text'\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 OpenAiFaultMatch = ChatFaultMatch\n\nexport type OpenAiFaultMatch = ChatFaultMatch\n\n/**\n * Wire faults for emulated routes, the same kinds as the Gateway emulator:\n * `status` (the body defaults to an OpenAI error envelope),\n * `error-after-chunks`, and `truncate-after-chunks`. Statuses that cannot\n * carry a body and redirects are rejected, as are invalid headers and\n * `location`. A chunk fault that cannot take effect answers 500 and is not\n * consumed.\n */\nexport const OpenAiFault = ChatFault\n\nexport type OpenAiFault = ChatFault\n\nexport type OpenAiFaultKind = ChatFaultKind\n\n/** Usage for a scripted turn (sent as the wire `usage` object). */\nexport const OpenAiScriptedUsage = ChatScriptedUsage\n\nexport type OpenAiScriptedUsage = ChatScriptedUsage\n\n/** One scripted tool call; its JSON arguments stream as these fragments. */\nexport const OpenAiScriptedToolCall = ChatScriptedToolCall\n\nexport type OpenAiScriptedToolCall = ChatScriptedToolCall\n\n/**\n * A scripted completion. Every field is exact (nothing is filled in) except:\n * `usage` omitted is synthesized when the request asks for usage, and `null`\n * drops it; `finishReason` omitted is `tool_calls` with tool calls, else\n * `stop`. Reasoning is not emulated: reasoning fields are rejected.\n */\nexport const OpenAiScriptedCompletion = Schema.Struct(chatScriptedCompletionFields)\n\nexport type OpenAiScriptedCompletion = typeof OpenAiScriptedCompletion.Type\n\n/** A scripted error response: status, body (a string is sent as is), and optional headers. */\nexport const OpenAiScriptedError = ChatScriptedError\n\nexport type OpenAiScriptedError = ChatScriptedError\n\n/** A turn queued for the next chat completion request. */\nexport const OpenAiScriptedTurn = Schema.Union([OpenAiScriptedError, OpenAiScriptedCompletion])\n\nexport type OpenAiScriptedTurn = typeof OpenAiScriptedTurn.Type\n\n/** Thrown by the JS API (`faults.add`, `script.enqueue`) for invalid input; a programmer error. */\nexport class OpenAiEmulatorInputInvalid extends Data.TaggedError('OpenAiEmulatorInputInvalid')<{\n readonly input: 'fault' | 'turn'\n readonly reason: string\n}> {\n override get message(): string {\n return `Invalid OpenAI emulator ${this.input}: ${this.reason}`\n }\n}\n\nexport type OpenAiLedgerEntry = ChatLedgerEntry\n\nexport type OpenAiFaultState = ChatFaultState\n\nexport type OpenAiRouteCoverage = ChatRouteCoverage\n\nexport type OpenAiCoverage = ChatCoverage\n\nexport type OpenAiEmulatorOptions = {\n /** Model ids that exist. Defaults to `openAiEmulatorDefaultModels`. */\n readonly knownModels?: ReadonlyArray<string>\n}\n\nexport type OpenAiEmulator = ChatCompletionsEmulator<OpenAiScriptedTurn>\n\nconst openAiErrorEnvelope = (error: ChatWireError): Schema.Json => ({\n error: { message: error.message, type: error.type, param: null, code: error.code }\n})\n\n/**\n * Create an OpenAI Chat Completions emulator. Each call has independent\n * ledger, fault, and script state.\n *\n * Without a script, `POST /v1/chat/completions` answers a known model with\n * synthetic text deltas (`stream: true`: `chat.completion.chunk` SSE, a finish\n * chunk, a usage chunk when `stream_options.include_usage` is set, and\n * `data: [DONE]`; `stream: false`: one `chat.completion` JSON body). A request\n * with `tools` gets one tool call whose arguments are synthesized from the\n * tool's JSON Schema and streamed in fragments, finishing with `tool_calls`.\n * Unknown models get the OpenAI error envelope (404, `model_not_found`); a\n * missing bearer credential gets a 401 envelope (`invalid_api_key`); unknown\n * routes get a 404 JSON error. The ledger records the\n * `max_completion_tokens` limit as `maxCompletionTokens`.\n *\n * Precedence per chat request matches the Gateway emulator: authentication and\n * JSON validation, then the first matching `status` fault, then the next\n * scripted turn, then model validation and defaults; a first matching chunk\n * fault then shapes the body. Credential headers are never recorded, and the\n * bearer value is never checked or stored.\n */\nexport const makeOpenAiEmulator = (options: OpenAiEmulatorOptions = {}): OpenAiEmulator =>\n makeChatCompletionsEmulator({\n path: openAiChatCompletionsPath,\n routes: openAiEmulatorRoutes,\n knownModels: options.knownModels ?? openAiEmulatorDefaultModels,\n reasoningModels: undefined,\n errorEnvelope: openAiErrorEnvelope,\n // Copied data shape of the synthetic OpenAI error-envelope fixture (unknown model id).\n unknownModel: {\n status: 404,\n error: {\n message: 'Synthetic placeholder: the requested model does not exist.',\n type: 'invalid_request_error',\n code: 'model_not_found'\n }\n },\n auth: {\n unauthorized: {\n message: 'Synthetic: missing or invalid API key.',\n type: 'invalid_request_error',\n code: 'invalid_api_key'\n }\n },\n completionTokenField: 'max_completion_tokens',\n responseIdPrefix: 'chatcmpl-synthetic',\n defaultText: ['Hello', ' from the', ' synthetic OpenAI emulator.'],\n turnSchema: OpenAiScriptedTurn,\n inputInvalid: (input, reason) => new OpenAiEmulatorInputInvalid({ input, reason })\n })\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AA4CA,MAAa,4BAA4B;;AAGzC,MAAa,8BAAqD,CAAC,gBAAgB,cAAc;;;;;AAMjG,MAAa,uBAA6D,CACxE;CACE,QAAQ;CACR,MAAM;CACN,MAAM;CACN,OAAO;CACP,SAAS;EACP;EACA;EACA;EACA;CACF;CACA,UAAU;CACV,YAAY,KAAA;AACd,CACF;;AAGA,MAAa,mBAAmB;;;;;;;;;AAYhC,MAAa,cAAc;;AAO3B,MAAa,sBAAsB;;AAKnC,MAAa,yBAAyB;;;;;;;AAUtC,MAAa,2BAA2B,OAAO,OAAO,4BAA4B;;AAKlF,MAAa,sBAAsB;;AAKnC,MAAa,qBAAqB,OAAO,MAAM,CAAC,qBAAqB,wBAAwB,CAAC;;AAK9F,IAAa,6BAAb,cAAgD,KAAK,YAAY,4BAA4B,EAG1F;CACD,IAAa,UAAkB;EAC7B,OAAO,2BAA2B,KAAK,MAAM,IAAI,KAAK;CACxD;AACF;AAiBA,MAAM,uBAAuB,WAAuC,EAClE,OAAO;CAAE,SAAS,MAAM;CAAS,MAAM,MAAM;CAAM,OAAO;CAAM,MAAM,MAAM;AAAK,EACnF;;;;;;;;;;;;;;;;;;;;;;AAuBA,MAAa,sBAAsB,UAAiC,CAAC,MACnE,4BAA4B;CAC1B,MAAM;CACN,QAAQ;CACR,aAAa,QAAQ,eAAe;CACpC,iBAAiB,KAAA;CACjB,eAAe;CAEf,cAAc;EACZ,QAAQ;EACR,OAAO;GACL,SAAS;GACT,MAAM;GACN,MAAM;EACR;CACF;CACA,MAAM,EACJ,cAAc;EACZ,SAAS;EACT,MAAM;EACN,MAAM;CACR,EACF;CACA,sBAAsB;CACtB,kBAAkB;CAClB,aAAa;EAAC;EAAS;EAAa;CAA6B;CACjE,YAAY;CACZ,eAAe,OAAO,WAAW,IAAI,2BAA2B;EAAE;EAAO;CAAO,CAAC;AACnF,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { FixtureRecording } from "./fixture-route.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/opencode-recordings.d.ts
|
|
4
|
+
declare const openCodeGoRecordings: ReadonlyArray<FixtureRecording>;
|
|
5
|
+
//#endregion
|
|
6
|
+
export { openCodeGoRecordings };
|
|
7
|
+
//# sourceMappingURL=opencode-recordings.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"opencode-recordings.d.mts","names":[],"sources":["../src/opencode-recordings.ts"],"mappings":";;;cASa,oBAAA,EAAsB,aAAa,CAAC,gBAAA"}
|