@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
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { EmulatorEvidence, EmulatorRouteEvidence, emulatorEvidenceHeader } from "./route-evidence.mjs";
|
|
2
|
+
import { StatefulCoverage, StatefulFault, StatefulFaultMatch, StatefulFaultState, StatefulHeaderlessLedgerEntry } from "./stateful-emulator.mjs";
|
|
3
|
+
import { TodoistEmulatorDue, TodoistEmulatorLabel, TodoistEmulatorProfile, TodoistEmulatorProject, TodoistEmulatorProjectSeed, TodoistEmulatorSeed, TodoistEmulatorState, TodoistEmulatorStateSchema, TodoistEmulatorTask, TodoistEmulatorTaskSeed } from "./todoist/state.mjs";
|
|
4
|
+
import { TodoistCursor, TodoistEmulatorDrills, todoistEmulatorBasePath } from "./todoist/api.mjs";
|
|
5
|
+
|
|
6
|
+
//#region src/todoist.d.ts
|
|
7
|
+
/** Origin the connector calls. */
|
|
8
|
+
declare const todoistEmulatorDefaultOrigin = "https://api.todoist.com";
|
|
9
|
+
/**
|
|
10
|
+
* Route evidence manifest: every emulated route, whether it writes, and the conformance cases
|
|
11
|
+
* whose (currently synthetic, unverified) wire claims it follows. Kept in sync with the handlers
|
|
12
|
+
* by construction (both come from one route table). Every route cites at least one case.
|
|
13
|
+
*/
|
|
14
|
+
declare const todoistEmulatorRoutes: ReadonlyArray<EmulatorRouteEvidence>;
|
|
15
|
+
type TodoistFaultState = StatefulFaultState;
|
|
16
|
+
type TodoistLedgerEntry = StatefulHeaderlessLedgerEntry;
|
|
17
|
+
type TodoistCoverage = StatefulCoverage;
|
|
18
|
+
declare const TodoistEmulatorInputInvalid_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 & {
|
|
19
|
+
readonly _tag: "TodoistEmulatorInputInvalid";
|
|
20
|
+
} & Readonly<A>;
|
|
21
|
+
/** Invalid emulator input from the JS API: a seed or a fault. A programmer error. */
|
|
22
|
+
declare class TodoistEmulatorInputInvalid extends TodoistEmulatorInputInvalid_base<{
|
|
23
|
+
readonly input: 'seed' | 'fault';
|
|
24
|
+
readonly reason: string;
|
|
25
|
+
}> {
|
|
26
|
+
get message(): string;
|
|
27
|
+
}
|
|
28
|
+
type TodoistEmulatorOptions = {
|
|
29
|
+
/** Typed seed; defaults to the fixture entities (`profile: 'default'`). */readonly seed?: TodoistEmulatorSeed; /** Clock in epoch milliseconds (created and closed timestamps). Defaults to `Date.now`. */
|
|
30
|
+
readonly now?: () => number; /** Drill knobs (tests only): make the emulator disagree with one conformance claim. */
|
|
31
|
+
readonly drills?: TodoistEmulatorDrills;
|
|
32
|
+
};
|
|
33
|
+
type TodoistEmulator = {
|
|
34
|
+
/** The fetch handler (Todoist routes and `/_emulate/*`). Never rejects. */readonly fetch: (request: Request) => Promise<Response>;
|
|
35
|
+
readonly ledger: {
|
|
36
|
+
readonly entries: () => ReadonlyArray<TodoistLedgerEntry>;
|
|
37
|
+
readonly clear: () => void;
|
|
38
|
+
};
|
|
39
|
+
readonly faults: {
|
|
40
|
+
/** Add a fault; throws `TodoistEmulatorInputInvalid` for an invalid fault. */readonly add: (fault: StatefulFault) => TodoistFaultState;
|
|
41
|
+
readonly list: () => ReadonlyArray<TodoistFaultState>;
|
|
42
|
+
readonly clear: () => void;
|
|
43
|
+
}; /** Task-listing cursors answered since the last reset or seed (runtime data). */
|
|
44
|
+
readonly cursors: () => ReadonlyArray<TodoistCursor>; /** Restore the current seed and clear the ledger, faults, and cursors. */
|
|
45
|
+
readonly reset: () => Promise<void>;
|
|
46
|
+
/**
|
|
47
|
+
* Replace the state with a new seed, which becomes what `reset` restores (cursors are cleared).
|
|
48
|
+
* Rejects with `TodoistEmulatorInputInvalid` for an invalid seed.
|
|
49
|
+
*/
|
|
50
|
+
readonly seed: (seed: TodoistEmulatorSeed) => Promise<void>; /** A deep copy of the current state (entities and counters). */
|
|
51
|
+
readonly snapshot: () => TodoistEmulatorState;
|
|
52
|
+
readonly coverage: () => TodoistCoverage; /** Close the core runtime. Later requests answer 503. Idempotent. */
|
|
53
|
+
readonly close: () => Promise<void>;
|
|
54
|
+
};
|
|
55
|
+
/**
|
|
56
|
+
* Create a stateful Todoist emulator on the `@emulators/core` custom runtime. Each call has its
|
|
57
|
+
* own state, ledger, faults, and cursors. Rejects with `TodoistEmulatorInputInvalid` for an
|
|
58
|
+
* invalid seed.
|
|
59
|
+
*
|
|
60
|
+
* Routes (under `/api/v1`, `Authorization: Bearer <token of at least 8 characters>`): task
|
|
61
|
+
* listing with cursor paging, task read, create, update, and close, label listing, and project
|
|
62
|
+
* create, read, and delete.
|
|
63
|
+
* See `README.md` (Todoist emulator) for the wire claims.
|
|
64
|
+
*/
|
|
65
|
+
declare const makeTodoistEmulator: (options?: TodoistEmulatorOptions) => Promise<TodoistEmulator>;
|
|
66
|
+
//#endregion
|
|
67
|
+
export { type EmulatorEvidence, type EmulatorRouteEvidence, TodoistCoverage, TodoistEmulator, type TodoistEmulatorDrills, TodoistEmulatorDue, TodoistEmulatorInputInvalid, TodoistEmulatorLabel, TodoistEmulatorOptions, TodoistEmulatorProfile, TodoistEmulatorProject, TodoistEmulatorProjectSeed, TodoistEmulatorSeed, type TodoistEmulatorState, TodoistEmulatorStateSchema, TodoistEmulatorTask, TodoistEmulatorTaskSeed, StatefulFault as TodoistFault, StatefulFaultMatch as TodoistFaultMatch, TodoistFaultState, TodoistLedgerEntry, emulatorEvidenceHeader, makeTodoistEmulator, todoistEmulatorBasePath, todoistEmulatorDefaultOrigin, todoistEmulatorRoutes };
|
|
68
|
+
//# sourceMappingURL=todoist.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"todoist.d.mts","names":[],"sources":["../src/todoist.ts"],"mappings":";;;;;;;cAiGa,4BAAA;AAOb;;;;AAAuE;AAAvE,cAAa,qBAAA,EAAuB,aAAa,CAAC,qBAAA;AAAA,KAItC,iBAAA,GAAoB,kBAAkB;AAAA,KAEtC,kBAAA,GAAqB,6BAA6B;AAAA,KAElD,eAAA,GAAkB,gBAAgB;AAAA,cAAA,gCAAA;;;;cAGjC,2BAAA,SAAoC,gCAAA;EAAA,SACtC,KAAA;EAAA,SACA,MAAA;AAAA;EAAA,IAEI,OAAA,CAAA;AAAA;AAAA,KAKH,sBAAA;EAZkC,oFAcnC,IAAA,GAAO,mBAAA;WAEP,GAAA;WAEA,MAAA,GAAS,qBAAqB;AAAA;AAAA,KAG7B,eAAA;sFAED,KAAA,GAAQ,OAAA,EAAS,OAAA,KAAY,OAAA,CAAQ,QAAA;EAAA,SACrC,MAAA;IAAA,SACE,OAAA,QAAe,aAAA,CAAc,kBAAA;IAAA,SAC7B,KAAA;EAAA;EAAA,SAEF,MAAA;2FAEE,GAAA,GAAM,KAAA,EAAO,aAAA,KAAkB,iBAAA;IAAA,SAC/B,IAAA,QAAY,aAAA,CAAc,iBAAA;IAAA,SAC1B,KAAA;EAAA;WAGF,OAAA,QAAe,aAAA,CAAc,aAAA;WAE7B,KAAA,QAAa,OAAA;;;;;WAKb,IAAA,GAAO,IAAA,EAAM,mBAAA,KAAwB,OAAA,QAvCnC;EAAA,SAyCF,QAAA,QAAgB,oBAAA;EAAA,SAChB,QAAA,QAAgB,eAAA,EA1CsB;EAAA,SA4CtC,KAAA,QAAa,OAAA;AAAA;;;;AAxCF;AAKtB;;;;;;cAwHa,mBAAA,GACX,OAAA,GAAS,sBAAA,KACR,OAAA,CAAQ,eAAA"}
|
package/dist/todoist.mjs
ADDED
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import { emulatorEvidenceHeader } from "./route-evidence.mjs";
|
|
2
|
+
import { StatefulFault, StatefulFaultMatch, makeHeaderlessStatefulEmulator, routeEvidence } from "./stateful-emulator.mjs";
|
|
3
|
+
import { statefulCoreRuntime } from "./stateful-core.mjs";
|
|
4
|
+
import { TodoistEmulatorDue, TodoistEmulatorLabel, TodoistEmulatorProfile, TodoistEmulatorProject, TodoistEmulatorProjectSeed, TodoistEmulatorSeed, TodoistEmulatorStateSchema, TodoistEmulatorTask, TodoistEmulatorTaskSeed, buildTodoistSeedState, decodeTodoistState } from "./todoist/state.mjs";
|
|
5
|
+
import { matchTodoistRoute, todoistApiRoutes, todoistEmulatorBasePath, todoistQueryProblem } from "./todoist/api.mjs";
|
|
6
|
+
import { Data, Predicate } from "effect";
|
|
7
|
+
//#region src/todoist.ts
|
|
8
|
+
/**
|
|
9
|
+
* Stateful Todoist emulator (API v1 under `https://api.todoist.com/api/v1`), built on the upstream
|
|
10
|
+
* `@emulators/core` custom runtime, with a request ledger, status faults, and an `/_emulate/*`
|
|
11
|
+
* control plane.
|
|
12
|
+
*
|
|
13
|
+
* Fixture-only: it never imports SDK code; its wire shapes and default seed are copied as data
|
|
14
|
+
* from the synthetic Todoist conformance fixtures, and every route names the conformance cases it
|
|
15
|
+
* follows in `todoistEmulatorRoutes`. Only the routes the seven Todoist cases (with their cleanup)
|
|
16
|
+
* need are emulated; anything the fixtures do not record answers one ledgered 400
|
|
17
|
+
* `{ error: { type: 'not_emulated', message } }`. That includes the project listing of the
|
|
18
|
+
* read-only leftover lookup (`findTodoistConformanceLeftovers`), which no fixture records: the
|
|
19
|
+
* lookup fails (`todoist_list_projects_failed`, HTTP 400), and runners print their lookup-failed
|
|
20
|
+
* WARN instead of leftover warnings.
|
|
21
|
+
*
|
|
22
|
+
* Fail closed: a request on no emulated route (or with a raw id segment that is not a Todoist id)
|
|
23
|
+
* is ledgered and answered with constant text only (`/<unrecognised>`, a standard method or
|
|
24
|
+
* `<other>`, no query or body, a constant reason). So is a request whose `Authorization` header is
|
|
25
|
+
* present but is not one recognisable bearer, whatever its route: its credential cannot be
|
|
26
|
+
* extracted and scrubbed.
|
|
27
|
+
*
|
|
28
|
+
* No answer is synthesised: a seeded project (whose object no fixture records) answers
|
|
29
|
+
* not-emulated on a read; only items created through the recorded create flow are updated,
|
|
30
|
+
* closed, or deleted; a case project takes one task and a seeded parent one sub-project (the
|
|
31
|
+
* fixtures record `child_order: 1` only). Minted ids use the reserved prefix `6XEmu`, which seeds
|
|
32
|
+
* may not use. The bearer value is guarded like the Telegram token: scrubbed from everything
|
|
33
|
+
* ledgered or answered, and a path, query, or body that repeats it is refused.
|
|
34
|
+
*
|
|
35
|
+
* Request-shape latitude (the only accepted deviations from the fixture requests): any credential
|
|
36
|
+
* value of at least 8 characters that occurs nowhere else in the request (its path, query, or body;
|
|
37
|
+
* never checked against anything, stored, or ledgered); extra request headers; `content-type`
|
|
38
|
+
* parameters; query parameters in any order; any Todoist id (1-64 of `[A-Za-z0-9_-]`) of an
|
|
39
|
+
* existing item where a fixture has an id (reads: seeded or created tasks and created projects;
|
|
40
|
+
* task listings: the paging project with `limit=2` and case projects created here without `limit`;
|
|
41
|
+
* writes: only items created through the recorded create flow; a new project's `parent_id`: a
|
|
42
|
+
* seeded project); any `run-` run id (at most 40 characters) in a case project name; any non-empty
|
|
43
|
+
* task `content`; a task update sending `content`, `due_datetime`, or both; a label listing `limit`
|
|
44
|
+
* of 1 to 200 that covers every label.
|
|
45
|
+
*
|
|
46
|
+
* Node-only: `@emulators/core` imports Node builtins, so the core is loaded lazily by
|
|
47
|
+
* `makeTodoistEmulator` (importing this module has no side effects).
|
|
48
|
+
*
|
|
49
|
+
* @experimental
|
|
50
|
+
*/
|
|
51
|
+
/** Origin the connector calls. */
|
|
52
|
+
const todoistEmulatorDefaultOrigin = "https://api.todoist.com";
|
|
53
|
+
/**
|
|
54
|
+
* Route evidence manifest: every emulated route, whether it writes, and the conformance cases
|
|
55
|
+
* whose (currently synthetic, unverified) wire claims it follows. Kept in sync with the handlers
|
|
56
|
+
* by construction (both come from one route table). Every route cites at least one case.
|
|
57
|
+
*/
|
|
58
|
+
const todoistEmulatorRoutes = todoistApiRoutes.map(({ route }) => routeEvidence(route));
|
|
59
|
+
/** Invalid emulator input from the JS API: a seed or a fault. A programmer error. */
|
|
60
|
+
var TodoistEmulatorInputInvalid = class extends Data.TaggedError("TodoistEmulatorInputInvalid") {
|
|
61
|
+
get message() {
|
|
62
|
+
return `Invalid Todoist emulator ${this.input}: ${this.reason}`;
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
const bearerPattern = /^bearer\s+(\S{8,})\s*$/i;
|
|
66
|
+
const resolve = (request, url) => {
|
|
67
|
+
const ledgerPath = url.pathname;
|
|
68
|
+
const authorization = request.headers.get("authorization");
|
|
69
|
+
const bearer = bearerPattern.exec(authorization ?? "")?.[1];
|
|
70
|
+
if (authorization !== null && bearer === void 0) return {
|
|
71
|
+
kind: "unrecognised",
|
|
72
|
+
reason: "an unrecognisable Authorization header is not emulated"
|
|
73
|
+
};
|
|
74
|
+
const secrets = bearer === void 0 ? [] : [bearer];
|
|
75
|
+
const matched = matchTodoistRoute(request.method, url.pathname);
|
|
76
|
+
if (matched === void 0) return {
|
|
77
|
+
kind: "unrecognised",
|
|
78
|
+
reason: "no emulated Todoist route for this method and path"
|
|
79
|
+
};
|
|
80
|
+
const refuse = (reason) => ({
|
|
81
|
+
kind: "refused",
|
|
82
|
+
ledgerPath,
|
|
83
|
+
reason,
|
|
84
|
+
route: matched.route.route,
|
|
85
|
+
secrets
|
|
86
|
+
});
|
|
87
|
+
if (bearer === void 0) return refuse("requests without Authorization: Bearer <token of at least 8 characters> are not emulated");
|
|
88
|
+
const problem = todoistQueryProblem(matched.route, url.searchParams);
|
|
89
|
+
if (problem !== void 0) return refuse(problem);
|
|
90
|
+
return {
|
|
91
|
+
kind: "route",
|
|
92
|
+
ledgerPath,
|
|
93
|
+
route: matched.route.route,
|
|
94
|
+
params: matched.params,
|
|
95
|
+
guardedPath: `${url.pathname}${url.search}`,
|
|
96
|
+
secrets
|
|
97
|
+
};
|
|
98
|
+
};
|
|
99
|
+
/** The texts of Todoist's recovery answers (500 failed, 503 closed, 500 unhandled). */
|
|
100
|
+
const errorTexts = {
|
|
101
|
+
failed: "Synthetic: the emulator could not build the response.",
|
|
102
|
+
closed: "Synthetic: the emulator is closed.",
|
|
103
|
+
unhandled: "emulator failed to handle the request"
|
|
104
|
+
};
|
|
105
|
+
/** The wrapper reports invalid seeds and faults only (Todoist takes no other option input). */
|
|
106
|
+
const inputInvalid = (input, reason) => new TodoistEmulatorInputInvalid({
|
|
107
|
+
input: input === "seed" ? "seed" : "fault",
|
|
108
|
+
reason
|
|
109
|
+
});
|
|
110
|
+
/**
|
|
111
|
+
* Create a stateful Todoist emulator on the `@emulators/core` custom runtime. Each call has its
|
|
112
|
+
* own state, ledger, faults, and cursors. Rejects with `TodoistEmulatorInputInvalid` for an
|
|
113
|
+
* invalid seed.
|
|
114
|
+
*
|
|
115
|
+
* Routes (under `/api/v1`, `Authorization: Bearer <token of at least 8 characters>`): task
|
|
116
|
+
* listing with cursor paging, task read, create, update, and close, label listing, and project
|
|
117
|
+
* create, read, and delete.
|
|
118
|
+
* See `README.md` (Todoist emulator) for the wire claims.
|
|
119
|
+
*/
|
|
120
|
+
const makeTodoistEmulator = async (options = {}) => {
|
|
121
|
+
const initial = buildTodoistSeedState(options.seed ?? {});
|
|
122
|
+
if (Predicate.isString(initial)) throw new TodoistEmulatorInputInvalid({
|
|
123
|
+
input: "seed",
|
|
124
|
+
reason: initial
|
|
125
|
+
});
|
|
126
|
+
const drills = options.drills ?? {};
|
|
127
|
+
const env = {
|
|
128
|
+
now: options.now ?? (() => Date.now()),
|
|
129
|
+
drills: {
|
|
130
|
+
cursorRestarts: drills.cursorRestarts ?? false,
|
|
131
|
+
notFoundWithoutError: drills.notFoundWithoutError ?? false,
|
|
132
|
+
taskLabelsAsIds: drills.taskLabelsAsIds ?? false,
|
|
133
|
+
listIncludesClosed: drills.listIncludesClosed ?? false,
|
|
134
|
+
ignoreDue: drills.ignoreDue ?? false,
|
|
135
|
+
createOmitsParent: drills.createOmitsParent ?? false,
|
|
136
|
+
deleteKeepsTasks: drills.deleteKeepsTasks ?? false
|
|
137
|
+
},
|
|
138
|
+
cursors: /* @__PURE__ */ new Map(),
|
|
139
|
+
cursorCounter: { next: 1 }
|
|
140
|
+
};
|
|
141
|
+
const cursorList = () => [...env.cursors.values()];
|
|
142
|
+
const emulator = await makeHeaderlessStatefulEmulator({
|
|
143
|
+
routes: todoistApiRoutes.map(({ route }) => route),
|
|
144
|
+
env,
|
|
145
|
+
initial,
|
|
146
|
+
buildSeed: buildTodoistSeedState,
|
|
147
|
+
resolveRequest: resolve,
|
|
148
|
+
errorTexts,
|
|
149
|
+
clearRuntime: () => {
|
|
150
|
+
env.cursors.clear();
|
|
151
|
+
env.cursorCounter.next = 1;
|
|
152
|
+
},
|
|
153
|
+
runtimeState: () => ({ runtime: { cursors: cursorList().map((cursor) => ({ ...cursor })) } }),
|
|
154
|
+
seedSummary: (state) => ({
|
|
155
|
+
projects: state.projects.length,
|
|
156
|
+
tasks: state.tasks.length,
|
|
157
|
+
labels: state.labels.length
|
|
158
|
+
}),
|
|
159
|
+
inputInvalid
|
|
160
|
+
}, statefulCoreRuntime({
|
|
161
|
+
name: "todoist",
|
|
162
|
+
initial,
|
|
163
|
+
decodeState: decodeTodoistState,
|
|
164
|
+
inputInvalid
|
|
165
|
+
}));
|
|
166
|
+
return {
|
|
167
|
+
fetch: emulator.fetch,
|
|
168
|
+
ledger: emulator.ledger,
|
|
169
|
+
faults: emulator.faults,
|
|
170
|
+
cursors: cursorList,
|
|
171
|
+
reset: emulator.reset,
|
|
172
|
+
seed: emulator.seed,
|
|
173
|
+
snapshot: emulator.snapshot,
|
|
174
|
+
coverage: emulator.coverage,
|
|
175
|
+
close: emulator.close
|
|
176
|
+
};
|
|
177
|
+
};
|
|
178
|
+
//#endregion
|
|
179
|
+
export { TodoistEmulatorDue, TodoistEmulatorInputInvalid, TodoistEmulatorLabel, TodoistEmulatorProfile, TodoistEmulatorProject, TodoistEmulatorProjectSeed, TodoistEmulatorSeed, TodoistEmulatorStateSchema, TodoistEmulatorTask, TodoistEmulatorTaskSeed, StatefulFault as TodoistFault, StatefulFaultMatch as TodoistFaultMatch, emulatorEvidenceHeader, makeTodoistEmulator, todoistEmulatorBasePath, todoistEmulatorDefaultOrigin, todoistEmulatorRoutes };
|
|
180
|
+
|
|
181
|
+
//# sourceMappingURL=todoist.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"todoist.mjs","names":[],"sources":["../src/todoist.ts"],"sourcesContent":["/**\n * Stateful Todoist emulator (API v1 under `https://api.todoist.com/api/v1`), built on the upstream\n * `@emulators/core` custom runtime, with a request ledger, status faults, and an `/_emulate/*`\n * control plane.\n *\n * Fixture-only: it never imports SDK code; its wire shapes and default seed are copied as data\n * from the synthetic Todoist conformance fixtures, and every route names the conformance cases it\n * follows in `todoistEmulatorRoutes`. Only the routes the seven Todoist cases (with their cleanup)\n * need are emulated; anything the fixtures do not record answers one ledgered 400\n * `{ error: { type: 'not_emulated', message } }`. That includes the project listing of the\n * read-only leftover lookup (`findTodoistConformanceLeftovers`), which no fixture records: the\n * lookup fails (`todoist_list_projects_failed`, HTTP 400), and runners print their lookup-failed\n * WARN instead of leftover warnings.\n *\n * Fail closed: a request on no emulated route (or with a raw id segment that is not a Todoist id)\n * is ledgered and answered with constant text only (`/<unrecognised>`, a standard method or\n * `<other>`, no query or body, a constant reason). So is a request whose `Authorization` header is\n * present but is not one recognisable bearer, whatever its route: its credential cannot be\n * extracted and scrubbed.\n *\n * No answer is synthesised: a seeded project (whose object no fixture records) answers\n * not-emulated on a read; only items created through the recorded create flow are updated,\n * closed, or deleted; a case project takes one task and a seeded parent one sub-project (the\n * fixtures record `child_order: 1` only). Minted ids use the reserved prefix `6XEmu`, which seeds\n * may not use. The bearer value is guarded like the Telegram token: scrubbed from everything\n * ledgered or answered, and a path, query, or body that repeats it is refused.\n *\n * Request-shape latitude (the only accepted deviations from the fixture requests): any credential\n * value of at least 8 characters that occurs nowhere else in the request (its path, query, or body;\n * never checked against anything, stored, or ledgered); extra request headers; `content-type`\n * parameters; query parameters in any order; any Todoist id (1-64 of `[A-Za-z0-9_-]`) of an\n * existing item where a fixture has an id (reads: seeded or created tasks and created projects;\n * task listings: the paging project with `limit=2` and case projects created here without `limit`;\n * writes: only items created through the recorded create flow; a new project's `parent_id`: a\n * seeded project); any `run-` run id (at most 40 characters) in a case project name; any non-empty\n * task `content`; a task update sending `content`, `due_datetime`, or both; a label listing `limit`\n * of 1 to 200 that covers every label.\n *\n * Node-only: `@emulators/core` imports Node builtins, so the core is loaded lazily by\n * `makeTodoistEmulator` (importing this module has no side effects).\n *\n * @experimental\n */\nimport { Data, Predicate } from 'effect'\nimport type { EmulatorRouteEvidence } from './route-evidence.ts'\nimport { statefulCoreRuntime } from './stateful-core.ts'\nimport {\n makeHeaderlessStatefulEmulator,\n routeEvidence,\n type StatefulCoverage,\n type StatefulFault,\n type StatefulFaultState,\n type StatefulHeaderlessLedgerEntry,\n type StatefulErrorTexts,\n type StatefulInputKind,\n type StatefulResolution\n} from './stateful-emulator.ts'\nimport {\n matchTodoistRoute,\n todoistApiRoutes,\n todoistQueryProblem,\n type TodoistApiEnv,\n type TodoistCursor,\n type TodoistEmulatorDrills\n} from './todoist/api.ts'\nimport {\n buildTodoistSeedState,\n decodeTodoistState,\n type TodoistEmulatorSeed,\n type TodoistEmulatorState\n} from './todoist/state.ts'\n\nexport type { EmulatorEvidence, EmulatorRouteEvidence } from './route-evidence.ts'\n\nexport { emulatorEvidenceHeader } from './route-evidence.ts'\n\nexport {\n StatefulFault as TodoistFault,\n StatefulFaultMatch as TodoistFaultMatch\n} from './stateful-emulator.ts'\n\nexport { todoistEmulatorBasePath, type TodoistEmulatorDrills } from './todoist/api.ts'\n\nexport {\n TodoistEmulatorDue,\n TodoistEmulatorLabel,\n TodoistEmulatorProfile,\n TodoistEmulatorProject,\n TodoistEmulatorProjectSeed,\n TodoistEmulatorSeed,\n TodoistEmulatorStateSchema,\n TodoistEmulatorTask,\n TodoistEmulatorTaskSeed,\n type TodoistEmulatorState\n} from './todoist/state.ts'\n\n/** Origin the connector calls. */\nexport const todoistEmulatorDefaultOrigin = 'https://api.todoist.com'\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). Every route cites at least one case.\n */\nexport const todoistEmulatorRoutes: ReadonlyArray<EmulatorRouteEvidence> = todoistApiRoutes.map(\n ({ route }) => routeEvidence(route)\n)\n\nexport type TodoistFaultState = StatefulFaultState\n\nexport type TodoistLedgerEntry = StatefulHeaderlessLedgerEntry\n\nexport type TodoistCoverage = StatefulCoverage\n\n/** Invalid emulator input from the JS API: a seed or a fault. A programmer error. */\nexport class TodoistEmulatorInputInvalid extends Data.TaggedError('TodoistEmulatorInputInvalid')<{\n readonly input: 'seed' | 'fault'\n readonly reason: string\n}> {\n override get message(): string {\n return `Invalid Todoist emulator ${this.input}: ${this.reason}`\n }\n}\n\nexport type TodoistEmulatorOptions = {\n /** Typed seed; defaults to the fixture entities (`profile: 'default'`). */\n readonly seed?: TodoistEmulatorSeed\n /** Clock in epoch milliseconds (created and closed 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?: TodoistEmulatorDrills\n}\n\nexport type TodoistEmulator = {\n /** The fetch handler (Todoist routes and `/_emulate/*`). Never rejects. */\n readonly fetch: (request: Request) => Promise<Response>\n readonly ledger: {\n readonly entries: () => ReadonlyArray<TodoistLedgerEntry>\n readonly clear: () => void\n }\n readonly faults: {\n /** Add a fault; throws `TodoistEmulatorInputInvalid` for an invalid fault. */\n readonly add: (fault: StatefulFault) => TodoistFaultState\n readonly list: () => ReadonlyArray<TodoistFaultState>\n readonly clear: () => void\n }\n /** Task-listing cursors answered since the last reset or seed (runtime data). */\n readonly cursors: () => ReadonlyArray<TodoistCursor>\n /** Restore the current seed and clear the ledger, faults, and cursors. */\n readonly reset: () => Promise<void>\n /**\n * Replace the state with a new seed, which becomes what `reset` restores (cursors are cleared).\n * Rejects with `TodoistEmulatorInputInvalid` for an invalid seed.\n */\n readonly seed: (seed: TodoistEmulatorSeed) => Promise<void>\n /** A deep copy of the current state (entities and counters). */\n readonly snapshot: () => TodoistEmulatorState\n readonly coverage: () => TodoistCoverage\n /** Close the core runtime. Later requests answer 503. Idempotent. */\n readonly close: () => Promise<void>\n}\n\n// A bearer credential of at least 8 characters. The value is never checked against anything,\n// stored, forwarded, or ledgered; it is guarded like the Telegram token: a path, query, or body\n// that repeats it is refused, and it is scrubbed from everything ledgered or answered.\nconst bearerPattern = /^bearer\\s+(\\S{8,})\\s*$/i\n\nconst resolve = (\n request: Request,\n url: URL\n): StatefulResolution<TodoistEmulatorState, TodoistApiEnv> => {\n const ledgerPath = url.pathname\n const authorization = request.headers.get('authorization')\n const bearer = bearerPattern.exec(authorization ?? '')?.[1]\n\n // Fail closed: an Authorization header that is present but not one recognisable bearer (extra\n // words, duplicated headers) means the credential cannot be extracted and scrubbed, so the\n // request is ledgered and answered with constant text only, whatever the route.\n if (authorization !== null && bearer === undefined) {\n return {\n kind: 'unrecognised',\n reason: 'an unrecognisable Authorization header is not emulated'\n }\n }\n\n // On a recognised route the bearer value is guarded (scrubbed and never repeated).\n const secrets = bearer === undefined ? [] : [bearer]\n const matched = matchTodoistRoute(request.method, url.pathname)\n\n // Fail closed: a request on no emulated route is ledgered and answered with constant text only.\n if (matched === undefined) {\n return { kind: 'unrecognised', reason: 'no emulated Todoist route for this method and path' }\n }\n\n const refuse = (reason: string): StatefulResolution<TodoistEmulatorState, TodoistApiEnv> => ({\n kind: 'refused',\n ledgerPath,\n reason,\n route: matched.route.route,\n secrets\n })\n\n if (bearer === undefined) {\n return refuse(\n 'requests without Authorization: Bearer <token of at least 8 characters> are not emulated'\n )\n }\n\n const problem = todoistQueryProblem(matched.route, url.searchParams)\n\n if (problem !== undefined) return refuse(problem)\n\n return {\n kind: 'route',\n ledgerPath,\n route: matched.route.route,\n params: matched.params,\n // The path and query the request must not repeat the bearer in.\n guardedPath: `${url.pathname}${url.search}`,\n secrets\n }\n}\n\n/** The texts of Todoist's recovery answers (500 failed, 503 closed, 500 unhandled). */\nconst errorTexts: StatefulErrorTexts = {\n failed: 'Synthetic: the emulator could not build the response.',\n closed: 'Synthetic: the emulator is closed.',\n unhandled: 'emulator failed to handle the request'\n}\n\n/** The wrapper reports invalid seeds and faults only (Todoist takes no other option input). */\nconst inputInvalid = (input: StatefulInputKind, reason: string) =>\n new TodoistEmulatorInputInvalid({ input: input === 'seed' ? 'seed' : 'fault', reason })\n\n/**\n * Create a stateful Todoist emulator on the `@emulators/core` custom runtime. Each call has its\n * own state, ledger, faults, and cursors. Rejects with `TodoistEmulatorInputInvalid` for an\n * invalid seed.\n *\n * Routes (under `/api/v1`, `Authorization: Bearer <token of at least 8 characters>`): task\n * listing with cursor paging, task read, create, update, and close, label listing, and project\n * create, read, and delete.\n * See `README.md` (Todoist emulator) for the wire claims.\n */\nexport const makeTodoistEmulator = async (\n options: TodoistEmulatorOptions = {}\n): Promise<TodoistEmulator> => {\n const initial = buildTodoistSeedState(options.seed ?? {})\n\n if (Predicate.isString(initial)) {\n throw new TodoistEmulatorInputInvalid({ input: 'seed', reason: initial })\n }\n\n const drills = options.drills ?? {}\n\n const env: TodoistApiEnv = {\n now: options.now ?? (() => Date.now()),\n drills: {\n cursorRestarts: drills.cursorRestarts ?? false,\n notFoundWithoutError: drills.notFoundWithoutError ?? false,\n taskLabelsAsIds: drills.taskLabelsAsIds ?? false,\n listIncludesClosed: drills.listIncludesClosed ?? false,\n ignoreDue: drills.ignoreDue ?? false,\n createOmitsParent: drills.createOmitsParent ?? false,\n deleteKeepsTasks: drills.deleteKeepsTasks ?? false\n },\n cursors: new Map(),\n cursorCounter: { next: 1 }\n }\n\n const cursorList = (): ReadonlyArray<TodoistCursor> => [...env.cursors.values()]\n\n const emulator = await makeHeaderlessStatefulEmulator<\n TodoistEmulatorState,\n TodoistApiEnv,\n TodoistEmulatorSeed\n >(\n {\n routes: todoistApiRoutes.map(({ route }) => route),\n env,\n initial,\n buildSeed: buildTodoistSeedState,\n resolveRequest: resolve,\n errorTexts,\n clearRuntime: () => {\n env.cursors.clear()\n env.cursorCounter.next = 1\n },\n runtimeState: () => ({ runtime: { cursors: cursorList().map(cursor => ({ ...cursor })) } }),\n seedSummary: state => ({\n projects: state.projects.length,\n tasks: state.tasks.length,\n labels: state.labels.length\n }),\n inputInvalid\n },\n statefulCoreRuntime({\n name: 'todoist',\n initial,\n decodeState: decodeTodoistState,\n inputInvalid\n })\n )\n\n return {\n fetch: emulator.fetch,\n ledger: emulator.ledger,\n faults: emulator.faults,\n cursors: cursorList,\n reset: emulator.reset,\n seed: emulator.seed,\n snapshot: emulator.snapshot,\n coverage: emulator.coverage,\n close: emulator.close\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiGA,MAAa,+BAA+B;;;;;;AAO5C,MAAa,wBAA8D,iBAAiB,KACzF,EAAE,YAAY,cAAc,KAAK,CACpC;;AASA,IAAa,8BAAb,cAAiD,KAAK,YAAY,6BAA6B,EAG5F;CACD,IAAa,UAAkB;EAC7B,OAAO,4BAA4B,KAAK,MAAM,IAAI,KAAK;CACzD;AACF;AA2CA,MAAM,gBAAgB;AAEtB,MAAM,WACJ,SACA,QAC4D;CAC5D,MAAM,aAAa,IAAI;CACvB,MAAM,gBAAgB,QAAQ,QAAQ,IAAI,eAAe;CACzD,MAAM,SAAS,cAAc,KAAK,iBAAiB,EAAE,IAAI;CAKzD,IAAI,kBAAkB,QAAQ,WAAW,KAAA,GACvC,OAAO;EACL,MAAM;EACN,QAAQ;CACV;CAIF,MAAM,UAAU,WAAW,KAAA,IAAY,CAAC,IAAI,CAAC,MAAM;CACnD,MAAM,UAAU,kBAAkB,QAAQ,QAAQ,IAAI,QAAQ;CAG9D,IAAI,YAAY,KAAA,GACd,OAAO;EAAE,MAAM;EAAgB,QAAQ;CAAqD;CAG9F,MAAM,UAAU,YAA6E;EAC3F,MAAM;EACN;EACA;EACA,OAAO,QAAQ,MAAM;EACrB;CACF;CAEA,IAAI,WAAW,KAAA,GACb,OAAO,OACL,0FACF;CAGF,MAAM,UAAU,oBAAoB,QAAQ,OAAO,IAAI,YAAY;CAEnE,IAAI,YAAY,KAAA,GAAW,OAAO,OAAO,OAAO;CAEhD,OAAO;EACL,MAAM;EACN;EACA,OAAO,QAAQ,MAAM;EACrB,QAAQ,QAAQ;EAEhB,aAAa,GAAG,IAAI,WAAW,IAAI;EACnC;CACF;AACF;;AAGA,MAAM,aAAiC;CACrC,QAAQ;CACR,QAAQ;CACR,WAAW;AACb;;AAGA,MAAM,gBAAgB,OAA0B,WAC9C,IAAI,4BAA4B;CAAE,OAAO,UAAU,SAAS,SAAS;CAAS;AAAO,CAAC;;;;;;;;;;;AAYxF,MAAa,sBAAsB,OACjC,UAAkC,CAAC,MACN;CAC7B,MAAM,UAAU,sBAAsB,QAAQ,QAAQ,CAAC,CAAC;CAExD,IAAI,UAAU,SAAS,OAAO,GAC5B,MAAM,IAAI,4BAA4B;EAAE,OAAO;EAAQ,QAAQ;CAAQ,CAAC;CAG1E,MAAM,SAAS,QAAQ,UAAU,CAAC;CAElC,MAAM,MAAqB;EACzB,KAAK,QAAQ,cAAc,KAAK,IAAI;EACpC,QAAQ;GACN,gBAAgB,OAAO,kBAAkB;GACzC,sBAAsB,OAAO,wBAAwB;GACrD,iBAAiB,OAAO,mBAAmB;GAC3C,oBAAoB,OAAO,sBAAsB;GACjD,WAAW,OAAO,aAAa;GAC/B,mBAAmB,OAAO,qBAAqB;GAC/C,kBAAkB,OAAO,oBAAoB;EAC/C;EACA,yBAAS,IAAI,IAAI;EACjB,eAAe,EAAE,MAAM,EAAE;CAC3B;CAEA,MAAM,mBAAiD,CAAC,GAAG,IAAI,QAAQ,OAAO,CAAC;CAE/E,MAAM,WAAW,MAAM,+BAKrB;EACE,QAAQ,iBAAiB,KAAK,EAAE,YAAY,KAAK;EACjD;EACA;EACA,WAAW;EACX,gBAAgB;EAChB;EACA,oBAAoB;GAClB,IAAI,QAAQ,MAAM;GAClB,IAAI,cAAc,OAAO;EAC3B;EACA,qBAAqB,EAAE,SAAS,EAAE,SAAS,WAAW,EAAE,KAAI,YAAW,EAAE,GAAG,OAAO,EAAE,EAAE,EAAE;EACzF,cAAa,WAAU;GACrB,UAAU,MAAM,SAAS;GACzB,OAAO,MAAM,MAAM;GACnB,QAAQ,MAAM,OAAO;EACvB;EACA;CACF,GACA,oBAAoB;EAClB,MAAM;EACN;EACA,aAAa;EACb;CACF,CAAC,CACH;CAEA,OAAO;EACL,OAAO,SAAS;EAChB,QAAQ,SAAS;EACjB,QAAQ,SAAS;EACjB,SAAS;EACT,OAAO,SAAS;EAChB,MAAM,SAAS;EACf,UAAU,SAAS;EACnB,UAAU,SAAS;EACnB,OAAO,SAAS;CAClB;AACF"}
|
package/dist/xai.d.mts
ADDED
|
@@ -0,0 +1,267 @@
|
|
|
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/xai.d.ts
|
|
8
|
+
declare const xAiGrokResponsesPath = "/v1/responses";
|
|
9
|
+
/**
|
|
10
|
+
* The Grok subscription-usage path; the SDK fetcher (`xAiGrokSubscriptionUsageUrl`) adds
|
|
11
|
+
* `?format=credits`, the recorded query.
|
|
12
|
+
*/
|
|
13
|
+
declare const xAiGrokSubscriptionUsagePath = "/v1/billing";
|
|
14
|
+
/**
|
|
15
|
+
* Route evidence manifest of the Grok subscription-usage route (served by the same fetch handler
|
|
16
|
+
* as the Responses route, with its own ledger and coverage). Synthetic, unverified.
|
|
17
|
+
*/
|
|
18
|
+
declare const xAiGrokSubscriptionUsageEmulatorRoutes: ReadonlyArray<EmulatorRouteEvidence>;
|
|
19
|
+
/**
|
|
20
|
+
* The recorded Grok usage body (the synthetic `xai.grok.usage.snapshot` fixture, copied as data):
|
|
21
|
+
* `config.creditUsagePercent` and `config.currentPeriod` `{ type, start, end }`.
|
|
22
|
+
*/
|
|
23
|
+
declare const xAiGrokSubscriptionUsageDefault: Schema.Json;
|
|
24
|
+
/** Synthetic-safe default model ids, including the Grok conformance defaults. */
|
|
25
|
+
declare const xAiGrokEmulatorDefaultModels: ReadonlyArray<string>;
|
|
26
|
+
/**
|
|
27
|
+
* Route evidence manifest: every emulated Grok route and the conformance cases whose (currently
|
|
28
|
+
* synthetic, unverified) wire shapes it follows.
|
|
29
|
+
*/
|
|
30
|
+
declare const xAiGrokEmulatorRoutes: ReadonlyArray<EmulatorRouteEvidence>;
|
|
31
|
+
/** Optional fault filter; an omitted field matches every request. `path` ending in `*` is a prefix. */
|
|
32
|
+
declare const XAiGrokFaultMatch: Schema.Struct<{
|
|
33
|
+
readonly path: Schema.optionalKey<Schema.String>;
|
|
34
|
+
readonly model: Schema.optionalKey<Schema.String>;
|
|
35
|
+
}>;
|
|
36
|
+
type XAiGrokFaultMatch = typeof EmulatorFaultMatch.Type;
|
|
37
|
+
/** A mid-stream Responses error (`{ code, message }`). */
|
|
38
|
+
declare const XAiGrokStreamError: Schema.Struct<{
|
|
39
|
+
readonly code: Schema.NonEmptyString;
|
|
40
|
+
readonly message: Schema.String;
|
|
41
|
+
}>;
|
|
42
|
+
type XAiGrokStreamError = ResponsesStreamError;
|
|
43
|
+
/** A mid-stream `error` or `response.failed` event fault, streamed responses only. */
|
|
44
|
+
declare const XAiGrokErrorEventFault: Schema.Struct<{
|
|
45
|
+
readonly match: Schema.optionalKey<Schema.Struct<{
|
|
46
|
+
readonly path: Schema.optionalKey<Schema.String>;
|
|
47
|
+
readonly model: Schema.optionalKey<Schema.String>;
|
|
48
|
+
}>>;
|
|
49
|
+
readonly count: Schema.optionalKey<Schema.Int>;
|
|
50
|
+
readonly kind: Schema.Literal<"error-event-after-chunks">;
|
|
51
|
+
readonly chunks: Schema.Int;
|
|
52
|
+
readonly event: Schema.optionalKey<Schema.Literals<readonly ["error", "response.failed"]>>;
|
|
53
|
+
readonly error: Schema.optionalKey<Schema.Struct<{
|
|
54
|
+
readonly code: Schema.NonEmptyString;
|
|
55
|
+
readonly message: Schema.String;
|
|
56
|
+
}>>;
|
|
57
|
+
}>;
|
|
58
|
+
type XAiGrokErrorEventFault = typeof ResponsesErrorEventFault.Type;
|
|
59
|
+
/**
|
|
60
|
+
* Wire faults: `status` (for example 429 with `retry-after`; the body defaults to the error
|
|
61
|
+
* envelope for the status), `error-after-chunks` (a dropped connection),
|
|
62
|
+
* `truncate-after-chunks` (a clean close, for example before `response.completed`), and
|
|
63
|
+
* `error-event-after-chunks` (a mid-stream `error` or `response.failed` event). Statuses that
|
|
64
|
+
* cannot carry a body and redirects are rejected, as are invalid headers and `location`. A fault
|
|
65
|
+
* that cannot take effect answers 500 and is not consumed.
|
|
66
|
+
*/
|
|
67
|
+
declare const XAiGrokFault: Schema.Union<readonly [Schema.Struct<{
|
|
68
|
+
readonly match: Schema.optionalKey<Schema.Struct<{
|
|
69
|
+
readonly path: Schema.optionalKey<Schema.String>;
|
|
70
|
+
readonly model: Schema.optionalKey<Schema.String>;
|
|
71
|
+
}>>;
|
|
72
|
+
readonly count: Schema.optionalKey<Schema.Int>;
|
|
73
|
+
readonly kind: Schema.Literal<"status">;
|
|
74
|
+
readonly status: Schema.Int;
|
|
75
|
+
readonly headers: Schema.optionalKey<Schema.$Record<Schema.String, Schema.String>>;
|
|
76
|
+
readonly body: Schema.optionalKey<Schema.Codec<Schema.Json, Schema.Json, never, never>>;
|
|
77
|
+
}>, Schema.Struct<{
|
|
78
|
+
readonly match: Schema.optionalKey<Schema.Struct<{
|
|
79
|
+
readonly path: Schema.optionalKey<Schema.String>;
|
|
80
|
+
readonly model: Schema.optionalKey<Schema.String>;
|
|
81
|
+
}>>;
|
|
82
|
+
readonly count: Schema.optionalKey<Schema.Int>;
|
|
83
|
+
readonly kind: Schema.Literal<"error-after-chunks">;
|
|
84
|
+
readonly chunks: Schema.Int;
|
|
85
|
+
}>, Schema.Struct<{
|
|
86
|
+
readonly match: Schema.optionalKey<Schema.Struct<{
|
|
87
|
+
readonly path: Schema.optionalKey<Schema.String>;
|
|
88
|
+
readonly model: Schema.optionalKey<Schema.String>;
|
|
89
|
+
}>>;
|
|
90
|
+
readonly count: Schema.optionalKey<Schema.Int>;
|
|
91
|
+
readonly kind: Schema.Literal<"truncate-after-chunks">;
|
|
92
|
+
readonly chunks: Schema.Int;
|
|
93
|
+
}>, Schema.Struct<{
|
|
94
|
+
readonly match: Schema.optionalKey<Schema.Struct<{
|
|
95
|
+
readonly path: Schema.optionalKey<Schema.String>;
|
|
96
|
+
readonly model: Schema.optionalKey<Schema.String>;
|
|
97
|
+
}>>;
|
|
98
|
+
readonly count: Schema.optionalKey<Schema.Int>;
|
|
99
|
+
readonly kind: Schema.Literal<"error-event-after-chunks">;
|
|
100
|
+
readonly chunks: Schema.Int;
|
|
101
|
+
readonly event: Schema.optionalKey<Schema.Literals<readonly ["error", "response.failed"]>>;
|
|
102
|
+
readonly error: Schema.optionalKey<Schema.Struct<{
|
|
103
|
+
readonly code: Schema.NonEmptyString;
|
|
104
|
+
readonly message: Schema.String;
|
|
105
|
+
}>>;
|
|
106
|
+
}>]>;
|
|
107
|
+
type XAiGrokFault = ResponsesFault;
|
|
108
|
+
type XAiGrokFaultKind = ResponsesFaultKind;
|
|
109
|
+
/** Usage for a scripted turn (sent in `response.completed` or the JSON body). */
|
|
110
|
+
declare const XAiGrokScriptedUsage: Schema.Struct<{
|
|
111
|
+
readonly inputTokens: Schema.Int;
|
|
112
|
+
readonly outputTokens: Schema.Int;
|
|
113
|
+
readonly reasoningTokens: Schema.optionalKey<Schema.Int>;
|
|
114
|
+
}>;
|
|
115
|
+
type XAiGrokScriptedUsage = ResponsesScriptedUsage;
|
|
116
|
+
/** One scripted `function_call` item; its arguments stream as these fragments. */
|
|
117
|
+
declare const XAiGrokScriptedFunctionCall: Schema.Struct<{
|
|
118
|
+
readonly name: Schema.NonEmptyString;
|
|
119
|
+
readonly argumentFragments: Schema.$Array<Schema.String>;
|
|
120
|
+
readonly callId: Schema.optionalKey<Schema.NonEmptyString>;
|
|
121
|
+
}>;
|
|
122
|
+
type XAiGrokScriptedFunctionCall = ResponsesScriptedFunctionCall;
|
|
123
|
+
/**
|
|
124
|
+
* A scripted response: `reasoning` (summary fragments), `text`, `functionCalls`, `order`,
|
|
125
|
+
* `usage` (`null` drops it), and `format` (`sse` or `json`, default: the request's `stream`).
|
|
126
|
+
*/
|
|
127
|
+
declare const XAiGrokScriptedResponse: Schema.Struct<{
|
|
128
|
+
readonly reasoning: Schema.optionalKey<Schema.$Array<Schema.String>>;
|
|
129
|
+
readonly text: Schema.optionalKey<Schema.$Array<Schema.String>>;
|
|
130
|
+
readonly functionCalls: Schema.optionalKey<Schema.$Array<Schema.Struct<{
|
|
131
|
+
readonly name: Schema.NonEmptyString;
|
|
132
|
+
readonly argumentFragments: Schema.$Array<Schema.String>;
|
|
133
|
+
readonly callId: Schema.optionalKey<Schema.NonEmptyString>;
|
|
134
|
+
}>>>;
|
|
135
|
+
readonly order: Schema.optionalKey<Schema.Literals<readonly ["reasoning-first", "text-first"]>>;
|
|
136
|
+
readonly usage: Schema.optionalKey<Schema.NullOr<Schema.Struct<{
|
|
137
|
+
readonly inputTokens: Schema.Int;
|
|
138
|
+
readonly outputTokens: Schema.Int;
|
|
139
|
+
readonly reasoningTokens: Schema.optionalKey<Schema.Int>;
|
|
140
|
+
}>>>;
|
|
141
|
+
readonly format: Schema.optionalKey<Schema.Literals<readonly ["sse", "json"]>>;
|
|
142
|
+
}>;
|
|
143
|
+
type XAiGrokScriptedResponse = ResponsesScriptedResponse;
|
|
144
|
+
/** A scripted error response: status, body (a string is sent as is), and optional headers. */
|
|
145
|
+
declare const XAiGrokScriptedError: Schema.Struct<{
|
|
146
|
+
readonly error: Schema.Struct<{
|
|
147
|
+
readonly status: Schema.Int;
|
|
148
|
+
readonly body: Schema.Codec<Schema.Json, Schema.Json, never, never>;
|
|
149
|
+
readonly headers: Schema.optionalKey<Schema.$Record<Schema.String, Schema.String>>;
|
|
150
|
+
}>;
|
|
151
|
+
}>;
|
|
152
|
+
type XAiGrokScriptedError = typeof EmulatorScriptedError.Type;
|
|
153
|
+
/** A turn queued for the next Grok request. */
|
|
154
|
+
declare const XAiGrokScriptedTurn: Schema.Union<readonly [Schema.Struct<{
|
|
155
|
+
readonly error: Schema.Struct<{
|
|
156
|
+
readonly status: Schema.Int;
|
|
157
|
+
readonly body: Schema.Codec<Schema.Json, Schema.Json, never, never>;
|
|
158
|
+
readonly headers: Schema.optionalKey<Schema.$Record<Schema.String, Schema.String>>;
|
|
159
|
+
}>;
|
|
160
|
+
}>, Schema.Struct<{
|
|
161
|
+
readonly reasoning: Schema.optionalKey<Schema.$Array<Schema.String>>;
|
|
162
|
+
readonly text: Schema.optionalKey<Schema.$Array<Schema.String>>;
|
|
163
|
+
readonly functionCalls: Schema.optionalKey<Schema.$Array<Schema.Struct<{
|
|
164
|
+
readonly name: Schema.NonEmptyString;
|
|
165
|
+
readonly argumentFragments: Schema.$Array<Schema.String>;
|
|
166
|
+
readonly callId: Schema.optionalKey<Schema.NonEmptyString>;
|
|
167
|
+
}>>>;
|
|
168
|
+
readonly order: Schema.optionalKey<Schema.Literals<readonly ["reasoning-first", "text-first"]>>;
|
|
169
|
+
readonly usage: Schema.optionalKey<Schema.NullOr<Schema.Struct<{
|
|
170
|
+
readonly inputTokens: Schema.Int;
|
|
171
|
+
readonly outputTokens: Schema.Int;
|
|
172
|
+
readonly reasoningTokens: Schema.optionalKey<Schema.Int>;
|
|
173
|
+
}>>>;
|
|
174
|
+
readonly format: Schema.optionalKey<Schema.Literals<readonly ["sse", "json"]>>;
|
|
175
|
+
}>]>;
|
|
176
|
+
type XAiGrokScriptedTurn = ResponsesScriptedTurn;
|
|
177
|
+
declare const XAiGrokEmulatorInputInvalid_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 & {
|
|
178
|
+
readonly _tag: "XAiGrokEmulatorInputInvalid";
|
|
179
|
+
} & Readonly<A>;
|
|
180
|
+
/** Thrown by the JS API (`faults.add`, `script.enqueue`) for invalid input; a programmer error. */
|
|
181
|
+
declare class XAiGrokEmulatorInputInvalid extends XAiGrokEmulatorInputInvalid_base<{
|
|
182
|
+
readonly input: 'fault' | 'turn';
|
|
183
|
+
readonly reason: string;
|
|
184
|
+
}> {
|
|
185
|
+
get message(): string;
|
|
186
|
+
}
|
|
187
|
+
type XAiGrokLedgerEntry = ResponsesLedgerEntry;
|
|
188
|
+
type XAiGrokFaultState = EmulatorFaultState<XAiGrokFault>;
|
|
189
|
+
type XAiGrokRouteCoverage = EmulatorRouteCoverage;
|
|
190
|
+
type XAiGrokCoverage = EmulatorCoverage;
|
|
191
|
+
/** A usage-route fault (`status`, `error-after-chunks`, `truncate-after-chunks`). */
|
|
192
|
+
declare const XAiGrokUsageFault: Schema.Union<readonly [Schema.Struct<{
|
|
193
|
+
readonly status: Schema.Int;
|
|
194
|
+
readonly match: Schema.optionalKey<Schema.Struct<{
|
|
195
|
+
readonly path: Schema.optionalKey<Schema.String>;
|
|
196
|
+
readonly model: Schema.optionalKey<Schema.String>;
|
|
197
|
+
}>>;
|
|
198
|
+
readonly count: Schema.optionalKey<Schema.Int>;
|
|
199
|
+
readonly kind: Schema.Literal<"status">;
|
|
200
|
+
readonly headers: Schema.optionalKey<Schema.$Record<Schema.String, Schema.String>>;
|
|
201
|
+
readonly body: Schema.optionalKey<Schema.Codec<Schema.Json, Schema.Json, never, never>>;
|
|
202
|
+
}>, Schema.Struct<{
|
|
203
|
+
readonly match: Schema.optionalKey<Schema.Struct<{
|
|
204
|
+
readonly path: Schema.optionalKey<Schema.String>;
|
|
205
|
+
readonly model: Schema.optionalKey<Schema.String>;
|
|
206
|
+
}>>;
|
|
207
|
+
readonly count: Schema.optionalKey<Schema.Int>;
|
|
208
|
+
readonly kind: Schema.Literal<"error-after-chunks">;
|
|
209
|
+
readonly chunks: Schema.Int;
|
|
210
|
+
}>, Schema.Struct<{
|
|
211
|
+
readonly match: Schema.optionalKey<Schema.Struct<{
|
|
212
|
+
readonly path: Schema.optionalKey<Schema.String>;
|
|
213
|
+
readonly model: Schema.optionalKey<Schema.String>;
|
|
214
|
+
}>>;
|
|
215
|
+
readonly count: Schema.optionalKey<Schema.Int>;
|
|
216
|
+
readonly kind: Schema.Literal<"truncate-after-chunks">;
|
|
217
|
+
readonly chunks: Schema.Int;
|
|
218
|
+
}>]>;
|
|
219
|
+
type XAiGrokUsageFault = SubscriptionUsageFault;
|
|
220
|
+
/** A usage turn: `{ usage }` (a body with the recorded JSON shape) or `{ error }`. */
|
|
221
|
+
type XAiGrokUsageScriptedTurn = SubscriptionUsageScriptedTurn;
|
|
222
|
+
type XAiGrokUsageLedgerEntry = SubscriptionUsageLedgerEntry;
|
|
223
|
+
type XAiGrokUsageEmulator = SubscriptionUsageEmulator;
|
|
224
|
+
type XAiGrokEmulatorOptions = {
|
|
225
|
+
/** Model ids that exist. Defaults to `xAiGrokEmulatorDefaultModels`. */readonly knownModels?: ReadonlyArray<string>;
|
|
226
|
+
/**
|
|
227
|
+
* Replacement usage-route body; must have the recorded JSON shape (same keys and value kinds).
|
|
228
|
+
* Defaults to the recorded body (`xAiGrokSubscriptionUsageDefault`).
|
|
229
|
+
*/
|
|
230
|
+
readonly subscriptionUsage?: Schema.Json;
|
|
231
|
+
};
|
|
232
|
+
/** The Responses emulator, plus `usage`: the subscription-usage route's own emulator API. */
|
|
233
|
+
type XAiGrokEmulator = ResponsesEmulator & {
|
|
234
|
+
readonly usage: XAiGrokUsageEmulator;
|
|
235
|
+
};
|
|
236
|
+
/**
|
|
237
|
+
* Create a Grok CLI proxy Responses emulator. Each call has independent ledger, fault, and script
|
|
238
|
+
* state.
|
|
239
|
+
*
|
|
240
|
+
* Without a script, `POST /v1/responses` answers a known model with synthetic output: `stream:
|
|
241
|
+
* true` streams `response.created`, `response.in_progress`, the output items
|
|
242
|
+
* (`response.output_item.added`, their parts and deltas, `response.output_item.done`), and
|
|
243
|
+
* `response.completed` with usage; `stream: false` returns one `response` JSON body. A request
|
|
244
|
+
* whose `reasoning` asks for a `summary` gets a reasoning item first. A request with function
|
|
245
|
+
* `tools` gets one `function_call` item whose arguments are synthesized from the tool's JSON
|
|
246
|
+
* Schema and streamed as `response.function_call_arguments.delta` fragments. Unknown models get
|
|
247
|
+
* 400 `model_not_found`; a request without a bearer credential gets 401 `invalid_api_key`,
|
|
248
|
+
* without `X-XAI-Token-Auth` 401, without `x-grok-client-version` 426, and without
|
|
249
|
+
* `x-grok-model-override` 400; a non-positive `max_output_tokens` gets 400; unknown routes get a
|
|
250
|
+
* 404 envelope. Not enforced: that `x-grok-model-override` matches the body `model`, the client
|
|
251
|
+
* version value, and the output limit itself (recorded as `maxOutputTokens`).
|
|
252
|
+
*
|
|
253
|
+
* `GET /v1/billing?format=credits` is fixture-only: a request with the headers the SDK fetcher
|
|
254
|
+
* sends (a non-empty bearer, `X-XAI-Token-Auth: xai-grok-cli`, a non-empty `x-userid`, a
|
|
255
|
+
* non-empty `x-grok-client-version`, and `x-grok-client-mode: headless`; the bearer, user id, and
|
|
256
|
+
* client-version values are request-shape latitude, and the user id and token-auth are never
|
|
257
|
+
* recorded),
|
|
258
|
+
* `accept: application/json`, and exactly the recorded `format=credits` query gets the recorded
|
|
259
|
+
* body (`xAiGrokSubscriptionUsageDefault`, or a same-shaped `options.subscriptionUsage` / scripted
|
|
260
|
+
* `{ usage }`); anything else answers 400 not-emulated. The client version and mode are recorded.
|
|
261
|
+
* Its ledger, faults, turns, and coverage are `emulator.usage`
|
|
262
|
+
* (control plane `/_emulate/usage/*`); `reset()` and `POST /_emulate/reset` reset both routes.
|
|
263
|
+
*/
|
|
264
|
+
declare const makeXAiGrokEmulator: (options?: XAiGrokEmulatorOptions) => XAiGrokEmulator;
|
|
265
|
+
//#endregion
|
|
266
|
+
export { type EmulatorEvidence, type EmulatorRouteEvidence, XAiGrokCoverage, XAiGrokEmulator, XAiGrokEmulatorInputInvalid, XAiGrokEmulatorOptions, XAiGrokErrorEventFault, XAiGrokFault, XAiGrokFaultKind, XAiGrokFaultMatch, XAiGrokFaultState, XAiGrokLedgerEntry, XAiGrokRouteCoverage, XAiGrokScriptedError, XAiGrokScriptedFunctionCall, XAiGrokScriptedResponse, XAiGrokScriptedTurn, XAiGrokScriptedUsage, XAiGrokStreamError, XAiGrokUsageEmulator, XAiGrokUsageFault, XAiGrokUsageLedgerEntry, XAiGrokUsageScriptedTurn, emulatorEvidenceHeader, makeXAiGrokEmulator, xAiGrokEmulatorDefaultModels, xAiGrokEmulatorRoutes, xAiGrokResponsesPath, xAiGrokSubscriptionUsageDefault, xAiGrokSubscriptionUsageEmulatorRoutes, xAiGrokSubscriptionUsagePath };
|
|
267
|
+
//# sourceMappingURL=xai.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"xai.d.mts","names":[],"sources":["../src/xai.ts"],"mappings":";;;;;;;cAiEa,oBAAA;;;AAAoB;AAMjC;cAAa,4BAAA;;;AAA4B;AAMzC;cAAa,sCAAA,EAAwC,aAAa,CAAC,qBAAA;;;AAAqB;AAgBxF;cAAa,+BAAA,EAAiC,MAAA,CAAO,IAA+C;;cAGvF,4BAAA,EAA8B,aAAa;AAH4C;AAGpG;;;AAHoG,cASvF,qBAAA,EAAuB,aAAa,CAAC,qBAAA;AANM;AAAA,cAwB3C,iBAAA,EAAiB,MAAA,CAAA,MAAA;EAAA;;;KAElB,iBAAA,UAA2B,kBAAA,CAAmB,IAAI;AAF9D;AAAA,cAKa,kBAAA,EAAkB,MAAA,CAAA,MAAA;EAAA;;;KAEnB,kBAAA,GAAqB,oBAAoB;;cAGxC,sBAAA,EAAsB,MAAA,CAAA,MAAA;EAAA;;;;;;;;;;;;;KAEvB,sBAAA,UAAgC,wBAAA,CAAyB,IAAI;;;AAVzE;;;;AAA8D;AAG9D;cAiBa,YAAA,EAAY,MAAA,CAAA,KAAA,WAAA,MAAA,CAAA,MAAA;EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAEb,YAAA,GAAe,cAAc;AAAA,KAE7B,gBAAA,GAAmB,kBAAkB;;cAGpC,oBAAA,EAAoB,MAAA,CAAA,MAAA;EAAA;;;;KAErB,oBAAA,GAAuB,sBAAsB;;cAG5C,2BAAA,EAA2B,MAAA,CAAA,MAAA;EAAA;;;;KAE5B,2BAAA,GAA8B,6BAA6B;;;;;cAM1D,uBAAA,EAAuB,MAAA,CAAA,MAAA;EAAA;;;;;;;;;;;;;;;KAExB,uBAAA,GAA0B,yBAAyB;;cAGlD,oBAAA,EAAoB,MAAA,CAAA,MAAA;EAAA;;;;;;KAErB,oBAAA,UAA8B,qBAAA,CAAsB,IAAI;;cAGvD,mBAAA,EAAmB,MAAA,CAAA,KAAA,WAAA,MAAA,CAAA,MAAA;EAAA;;;;;;;;;;;;;;;;;;;;;KAEpB,mBAAA,GAAsB,qBAAqB;AAAA,cAAA,gCAAA;;;;cAG1C,2BAAA,SAAoC,gCAAA;EAAA,SACtC,KAAA;EAAA,SACA,MAAA;AAAA;EAAA,IAEI,OAAA,CAAA;AAAA;AAAA,KAKH,kBAAA,GAAqB,oBAAoB;AAAA,KAEzC,iBAAA,GAAoB,kBAAkB,CAAC,YAAA;AAAA,KAEvC,oBAAA,GAAuB,qBAAqB;AAAA,KAE5C,eAAA,GAAkB,gBAAgB;;cAGjC,iBAAA,EAAiB,MAAA,CAAA,KAAA,WAAA,MAAA,CAAA,MAAA;EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;KAElB,iBAAA,GAAoB,sBAAsB;;KAG1C,wBAAA,GAA2B,6BAA6B;AAAA,KAExD,uBAAA,GAA0B,4BAA4B;AAAA,KAEtD,oBAAA,GAAuB,yBAAyB;AAAA,KAEhD,sBAAA;EAhEa,iFAkEd,WAAA,GAAc,aAAA;EAlEA;;;;EAAA,SAuEd,iBAAA,GAAoB,MAAA,CAAO,IAAI;AAAA;;KAI9B,eAAA,GAAkB,iBAAA;EAAA,SAA+B,KAAA,EAAO,oBAAoB;AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAuC3E,mBAAA,GAAuB,OAAA,GAAS,sBAAA,KAA8B,eAKxE"}
|