@lingara/api 0.0.0-reserved.0 → 0.1.0-alpha.10

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.
@@ -0,0 +1,1512 @@
1
+ declare const INSPECT: unique symbol;
2
+ /** The base of every error this library raises. */
3
+ declare class LingaraError extends Error {
4
+ static [Symbol.hasInstance](value: unknown): boolean;
5
+ constructor(message: string, options?: {
6
+ cause?: unknown;
7
+ });
8
+ /** The fields a caller reads, for `JSON.stringify` and inspection. */
9
+ toJSON(): Record<string, unknown>;
10
+ [INSPECT](): string;
11
+ protected fields(): Record<string, unknown>;
12
+ }
13
+ interface ApiErrorInit {
14
+ status: number;
15
+ code: string;
16
+ message: string;
17
+ retryAfter?: number | undefined;
18
+ planId?: string | undefined;
19
+ servedVersion?: string | undefined;
20
+ }
21
+ /** A `/v1` refusal, or a stream's `error` event (then `status` is 200). */
22
+ declare class ApiError extends LingaraError {
23
+ static [Symbol.hasInstance](value: unknown): boolean;
24
+ readonly status: number;
25
+ readonly code: string;
26
+ readonly retryAfter?: number;
27
+ readonly planId?: string;
28
+ readonly servedVersion?: string;
29
+ constructor(init: ApiErrorInit);
30
+ protected fields(): Record<string, unknown>;
31
+ }
32
+ interface OAuthErrorInit {
33
+ status: number;
34
+ error: string;
35
+ description?: string | undefined;
36
+ retryAfter?: number | undefined;
37
+ }
38
+ /** A token-endpoint refusal (RFC 6749 §5.2, or `http_<status>`). */
39
+ declare class OAuthError extends LingaraError {
40
+ static [Symbol.hasInstance](value: unknown): boolean;
41
+ readonly status: number;
42
+ readonly error: string;
43
+ readonly description?: string;
44
+ readonly retryAfter?: number;
45
+ constructor(init: OAuthErrorInit);
46
+ protected fields(): Record<string, unknown>;
47
+ }
48
+ /** A 503 whose body is not JSON: the service is in maintenance. */
49
+ declare class MaintenanceError extends LingaraError {
50
+ static [Symbol.hasInstance](value: unknown): boolean;
51
+ /** The response text, at most 1 KiB. */
52
+ readonly body: string;
53
+ readonly retryAfter?: number;
54
+ constructor(body: string, retryAfter?: number);
55
+ protected fields(): Record<string, unknown>;
56
+ }
57
+ type TransportKind = "connect" | "tls" | "reset" | "timeout" | "stream_ended_early" | "malformed_response" | "malformed_event";
58
+ /** No usable HTTP answer. `cause` is the runtime's error, redacted. */
59
+ declare class TransportError extends LingaraError {
60
+ static [Symbol.hasInstance](value: unknown): boolean;
61
+ readonly kind: TransportKind;
62
+ constructor(kind: TransportKind, cause?: unknown);
63
+ protected fields(): Record<string, unknown>;
64
+ }
65
+
66
+ interface components {
67
+ schemas: {
68
+ VocabRequest: {
69
+ /** Format: uint8 */
70
+ level: number;
71
+ source_lang: string;
72
+ target_lang: string;
73
+ /** Format: uint8 */
74
+ count?: number | null;
75
+ };
76
+ LessonPlanCreateRequest: {
77
+ context: string;
78
+ source_lang: string;
79
+ target_lang: string;
80
+ /** Format: uint8 */
81
+ level: number;
82
+ };
83
+ TutorTurnRequest: {
84
+ message: string;
85
+ /** @default [] */
86
+ history: components["schemas"]["TurnEntry"][];
87
+ source_lang: string;
88
+ target_lang: string;
89
+ /** Format: uint8 */
90
+ level?: number | null;
91
+ character?: string | null;
92
+ situation?: string | null;
93
+ };
94
+ TurnEntry: {
95
+ role: components["schemas"]["TurnRole"];
96
+ content: string;
97
+ };
98
+ /** @enum {string} */
99
+ TurnRole: "user" | "assistant";
100
+ VocabStarted: {
101
+ meta: components["schemas"]["VocabMeta"];
102
+ };
103
+ VocabMeta: {
104
+ /** Format: uint8 */
105
+ level: number;
106
+ source_lang: string;
107
+ target_lang: string;
108
+ framework: string;
109
+ /** Format: uint32 */
110
+ count: number;
111
+ ai_generated: boolean;
112
+ };
113
+ VocabItem: {
114
+ word: string;
115
+ pronunciation?: string | null;
116
+ reading?: string | null;
117
+ translation: string;
118
+ example?: components["schemas"]["VocabExample"] | null;
119
+ image_url?: string | null;
120
+ };
121
+ VocabExample: {
122
+ sentence: string;
123
+ translation: string;
124
+ };
125
+ LessonPlan: {
126
+ /** Format: uuid */
127
+ id: string;
128
+ status: components["schemas"]["PlanStatus"];
129
+ title?: string | null;
130
+ source_lang: string;
131
+ target_lang: string;
132
+ /** Format: uint8 */
133
+ level: number;
134
+ /** Format: date-time */
135
+ created_at: string;
136
+ /** Format: date-time */
137
+ completed_at?: string | null;
138
+ ai_generated: boolean;
139
+ content?: components["schemas"]["LessonPlanContent"] | null;
140
+ };
141
+ /** @enum {string} */
142
+ PlanStatus: "generating" | "partial" | "complete";
143
+ LessonPlanContent: {
144
+ introduction?: string | null;
145
+ learning_objectives: string[];
146
+ vocabulary: components["schemas"]["PlanWord"][];
147
+ sets: components["schemas"]["PlanSet"][];
148
+ };
149
+ PlanWord: {
150
+ word: string;
151
+ pronunciation?: string | null;
152
+ translation: string;
153
+ };
154
+ PlanSet: {
155
+ /** Format: uint8 */
156
+ number: number;
157
+ context?: string | null;
158
+ questions: components["schemas"]["PlanQuestion"][];
159
+ };
160
+ PlanQuestion: {
161
+ type: string;
162
+ prompt: string;
163
+ options?: string[] | null;
164
+ answer: string;
165
+ explanation: string;
166
+ hint?: string | null;
167
+ };
168
+ PlanStarted: {
169
+ /** Format: uuid */
170
+ plan_id: string;
171
+ };
172
+ PlanPhase: {
173
+ phase: string;
174
+ /** Format: uint8 */
175
+ attempt: number;
176
+ };
177
+ PlanResult: {
178
+ plan: components["schemas"]["LessonPlan"];
179
+ };
180
+ PlanPending: {
181
+ /** Format: uuid */
182
+ plan_id: string;
183
+ status: components["schemas"]["PlanStatus"];
184
+ };
185
+ TurnDelta: {
186
+ text: string;
187
+ };
188
+ Usage: {
189
+ allowance: components["schemas"]["AllowanceRow"][];
190
+ /** @description This client's calls and units since midnight UTC on the first of the month. Present only for a metered client, whose calls spend no allowance. It can trail your latest call by up to five seconds. */
191
+ ledger?: components["schemas"]["UsageLedger"] | null;
192
+ };
193
+ UsageLedger: {
194
+ /** Format: date-time */
195
+ since: string;
196
+ /** Format: uint64 */
197
+ calls: number;
198
+ /** Format: uint64 */
199
+ units: number;
200
+ };
201
+ AllowanceRow: {
202
+ feature: string;
203
+ window: string;
204
+ /** Format: uint32 */
205
+ limit: number;
206
+ /** Format: uint32 */
207
+ used: number;
208
+ /** Format: uint32 */
209
+ remaining: number;
210
+ /** Format: int64 */
211
+ reset_at?: number | null;
212
+ };
213
+ VersionList: {
214
+ current: string | null;
215
+ development: string | null;
216
+ versions: components["schemas"]["VersionSummary"][];
217
+ };
218
+ VersionSummary: {
219
+ id: string;
220
+ state: components["schemas"]["VersionState"];
221
+ lts: boolean;
222
+ /** Format: date-time */
223
+ minted_at: string;
224
+ /** Format: date-time */
225
+ sunset_at: string | null;
226
+ };
227
+ VersionDetail: {
228
+ id: string;
229
+ state: components["schemas"]["VersionState"];
230
+ lts: boolean;
231
+ /** Format: date-time */
232
+ minted_at: string;
233
+ /** Format: date-time */
234
+ sunset_at: string | null;
235
+ summary: string | null;
236
+ history: components["schemas"]["VersionHistoryEntry"][];
237
+ spec: components["schemas"]["VersionSpec"];
238
+ asyncapi: components["schemas"]["VersionSpec"];
239
+ };
240
+ /** @enum {string} */
241
+ VersionState: "development" | "supported" | "lts" | "deprecated" | "discontinued";
242
+ VersionHistoryEntry: {
243
+ state: components["schemas"]["VersionState"];
244
+ /** Format: date-time */
245
+ at: string;
246
+ };
247
+ VersionSpec: {
248
+ url: string;
249
+ sha256: string | null;
250
+ };
251
+ Error: {
252
+ /** @description Why the request was refused, as a stable code to branch on: for example `insufficient_scope` (`403`), `rate_limited` (`429`) and, for a metered client, `spend_cap_reached` (`402`) and `metered_billing_inactive` (`402`). */
253
+ code: string;
254
+ error: string;
255
+ };
256
+ Notice: {
257
+ code: string;
258
+ message: string;
259
+ };
260
+ StreamError: {
261
+ code: string;
262
+ message: string;
263
+ /** Format: uuid */
264
+ plan_id?: string | null;
265
+ };
266
+ Done: Record<string, never>;
267
+ EventEnvelope: {
268
+ id: string;
269
+ type: string;
270
+ /** Format: date-time */
271
+ created_at: string;
272
+ api_version: string;
273
+ subject: string;
274
+ data: {
275
+ [key: string]: unknown;
276
+ };
277
+ };
278
+ LessonPlanReadyData: {
279
+ /** Format: uuid */
280
+ plan_id: string;
281
+ status: components["schemas"]["PlanReadyStatus"];
282
+ title: string | null;
283
+ source_lang: string;
284
+ target_lang: string;
285
+ /** Format: int16 */
286
+ level: number;
287
+ };
288
+ /** @enum {string} */
289
+ PlanReadyStatus: "complete" | "partial";
290
+ LessonPlanFailedData: {
291
+ /** Format: uuid */
292
+ plan_id: string;
293
+ reason: components["schemas"]["PlanFailReason"];
294
+ };
295
+ /** @enum {string} */
296
+ PlanFailReason: "generation_failed" | "timed_out";
297
+ UsageThresholdReachedData: {
298
+ scope: components["schemas"]["ThresholdScope"];
299
+ /** @enum {integer} */
300
+ threshold_pct: 50 | 70 | 90 | 100;
301
+ month: string;
302
+ client_id?: string | null;
303
+ };
304
+ /** @enum {string} */
305
+ ThresholdScope: "account" | "client";
306
+ WebhookTestData: Record<string, never>;
307
+ AppInstalledData: {
308
+ client_id: string;
309
+ /** Format: uuid */
310
+ install_id: string;
311
+ context: components["schemas"]["AppContextSlice"][];
312
+ tutor_note: boolean;
313
+ };
314
+ AppUninstalledData: {
315
+ client_id: string;
316
+ /** Format: uuid */
317
+ install_id: string;
318
+ };
319
+ /** @enum {string} */
320
+ AppContextSlice: "languages" | "plan_summary" | "review_due" | "tutor_topic";
321
+ EventPage: {
322
+ items: components["schemas"]["EventEnvelope"][];
323
+ next_cursor: string;
324
+ has_more: boolean;
325
+ };
326
+ WorldContextChanged: {
327
+ scene: string;
328
+ npc?: components["schemas"]["Npc"] | null;
329
+ source_lang: string;
330
+ target_lang: string;
331
+ /** Format: uint8 */
332
+ level: number;
333
+ tags?: string[];
334
+ generate?: boolean | null;
335
+ };
336
+ WorldPracticeRequested: {
337
+ topic: string;
338
+ source_lang: string;
339
+ target_lang: string;
340
+ /** Format: uint8 */
341
+ level: number;
342
+ tags?: string[];
343
+ generate?: boolean | null;
344
+ };
345
+ Npc: {
346
+ name: string;
347
+ persona?: string | null;
348
+ };
349
+ InboundEventAccepted: {
350
+ id: string;
351
+ type: string;
352
+ /** Format: date-time */
353
+ created_at: string;
354
+ reaction?: components["schemas"]["ReactionReport"] | null;
355
+ };
356
+ ReactionReport: {
357
+ status: components["schemas"]["ReactionStatus"];
358
+ /** Format: uuid */
359
+ plan_id?: string | null;
360
+ /** @description The plan's status when the event was accepted. Only `generating` promises that `lesson_plan.ready` or `lesson_plan.failed` will follow. Any other value is a plan served from the library, which you can read now with `GET /v1/lesson-plans/{id}`. */
361
+ plan_status?: components["schemas"]["PlanStatus"] | null;
362
+ code?: string | null;
363
+ error?: string | null;
364
+ };
365
+ /** @enum {string} */
366
+ ReactionStatus: "started" | "refused" | "failed";
367
+ GenerateVocabularyEventStarted: {
368
+ /**
369
+ * @description discriminator enum property added by openapi-typescript
370
+ * @enum {string}
371
+ */
372
+ event: "started";
373
+ data: components["schemas"]["VocabStarted"];
374
+ };
375
+ GenerateVocabularyEventItem: {
376
+ /**
377
+ * @description discriminator enum property added by openapi-typescript
378
+ * @enum {string}
379
+ */
380
+ event: "item";
381
+ data: components["schemas"]["VocabItem"];
382
+ };
383
+ GenerateVocabularyEventDone: {
384
+ /**
385
+ * @description discriminator enum property added by openapi-typescript
386
+ * @enum {string}
387
+ */
388
+ event: "done";
389
+ data: components["schemas"]["Done"];
390
+ };
391
+ GenerateVocabularyEventError: {
392
+ /**
393
+ * @description discriminator enum property added by openapi-typescript
394
+ * @enum {string}
395
+ */
396
+ event: "error";
397
+ data: components["schemas"]["StreamError"];
398
+ };
399
+ GenerateVocabularyEvent: components["schemas"]["GenerateVocabularyEventStarted"] | components["schemas"]["GenerateVocabularyEventItem"] | components["schemas"]["GenerateVocabularyEventDone"] | components["schemas"]["GenerateVocabularyEventError"];
400
+ CreateLessonPlanEventStarted: {
401
+ /**
402
+ * @description discriminator enum property added by openapi-typescript
403
+ * @enum {string}
404
+ */
405
+ event: "started";
406
+ data: components["schemas"]["PlanStarted"];
407
+ };
408
+ CreateLessonPlanEventPhase: {
409
+ /**
410
+ * @description discriminator enum property added by openapi-typescript
411
+ * @enum {string}
412
+ */
413
+ event: "phase";
414
+ data: components["schemas"]["PlanPhase"];
415
+ };
416
+ CreateLessonPlanEventResult: {
417
+ /**
418
+ * @description discriminator enum property added by openapi-typescript
419
+ * @enum {string}
420
+ */
421
+ event: "result";
422
+ data: components["schemas"]["PlanResult"];
423
+ };
424
+ CreateLessonPlanEventError: {
425
+ /**
426
+ * @description discriminator enum property added by openapi-typescript
427
+ * @enum {string}
428
+ */
429
+ event: "error";
430
+ data: components["schemas"]["StreamError"];
431
+ };
432
+ CreateLessonPlanEvent: components["schemas"]["CreateLessonPlanEventStarted"] | components["schemas"]["CreateLessonPlanEventPhase"] | components["schemas"]["CreateLessonPlanEventResult"] | components["schemas"]["CreateLessonPlanEventError"];
433
+ StreamLessonPlanEventStarted: {
434
+ /**
435
+ * @description discriminator enum property added by openapi-typescript
436
+ * @enum {string}
437
+ */
438
+ event: "started";
439
+ data: components["schemas"]["PlanStarted"];
440
+ };
441
+ StreamLessonPlanEventPhase: {
442
+ /**
443
+ * @description discriminator enum property added by openapi-typescript
444
+ * @enum {string}
445
+ */
446
+ event: "phase";
447
+ data: components["schemas"]["PlanPhase"];
448
+ };
449
+ StreamLessonPlanEventResult: {
450
+ /**
451
+ * @description discriminator enum property added by openapi-typescript
452
+ * @enum {string}
453
+ */
454
+ event: "result";
455
+ data: components["schemas"]["PlanResult"];
456
+ };
457
+ StreamLessonPlanEventPending: {
458
+ /**
459
+ * @description discriminator enum property added by openapi-typescript
460
+ * @enum {string}
461
+ */
462
+ event: "pending";
463
+ data: components["schemas"]["PlanPending"];
464
+ };
465
+ StreamLessonPlanEventError: {
466
+ /**
467
+ * @description discriminator enum property added by openapi-typescript
468
+ * @enum {string}
469
+ */
470
+ event: "error";
471
+ data: components["schemas"]["StreamError"];
472
+ };
473
+ StreamLessonPlanEvent: components["schemas"]["StreamLessonPlanEventStarted"] | components["schemas"]["StreamLessonPlanEventPhase"] | components["schemas"]["StreamLessonPlanEventResult"] | components["schemas"]["StreamLessonPlanEventPending"] | components["schemas"]["StreamLessonPlanEventError"];
474
+ SendTutorMessageEventDelta: {
475
+ /**
476
+ * @description discriminator enum property added by openapi-typescript
477
+ * @enum {string}
478
+ */
479
+ event: "delta";
480
+ data: components["schemas"]["TurnDelta"];
481
+ };
482
+ SendTutorMessageEventNotice: {
483
+ /**
484
+ * @description discriminator enum property added by openapi-typescript
485
+ * @enum {string}
486
+ */
487
+ event: "notice";
488
+ data: components["schemas"]["Notice"];
489
+ };
490
+ SendTutorMessageEventDone: {
491
+ /**
492
+ * @description discriminator enum property added by openapi-typescript
493
+ * @enum {string}
494
+ */
495
+ event: "done";
496
+ data: components["schemas"]["Done"];
497
+ };
498
+ SendTutorMessageEventError: {
499
+ /**
500
+ * @description discriminator enum property added by openapi-typescript
501
+ * @enum {string}
502
+ */
503
+ event: "error";
504
+ data: components["schemas"]["StreamError"];
505
+ };
506
+ SendTutorMessageEvent: components["schemas"]["SendTutorMessageEventDelta"] | components["schemas"]["SendTutorMessageEventNotice"] | components["schemas"]["SendTutorMessageEventDone"] | components["schemas"]["SendTutorMessageEventError"];
507
+ StreamEventsEventEvent: {
508
+ /**
509
+ * @description discriminator enum property added by openapi-typescript
510
+ * @enum {string}
511
+ */
512
+ event: "event";
513
+ data: components["schemas"]["EventEnvelope"];
514
+ };
515
+ StreamEventsEventDone: {
516
+ /**
517
+ * @description discriminator enum property added by openapi-typescript
518
+ * @enum {string}
519
+ */
520
+ event: "done";
521
+ data: components["schemas"]["Done"];
522
+ };
523
+ StreamEventsEventError: {
524
+ /**
525
+ * @description discriminator enum property added by openapi-typescript
526
+ * @enum {string}
527
+ */
528
+ event: "error";
529
+ data: components["schemas"]["StreamError"];
530
+ };
531
+ StreamEventsEvent: components["schemas"]["StreamEventsEventEvent"] | components["schemas"]["StreamEventsEventDone"] | components["schemas"]["StreamEventsEventError"];
532
+ };
533
+ responses: {
534
+ /** @description The request was refused. `code` says why, and `error` says it in words. */
535
+ Error: {
536
+ headers: {
537
+ [name: string]: unknown;
538
+ };
539
+ content: {
540
+ "application/json": components["schemas"]["Error"];
541
+ };
542
+ };
543
+ /** @description A metered client's call was refused before it spent anything. `spend_cap_reached`: the client or its account has reached its monthly spending limit; raise the limit on the Integrations page. `metered_billing_inactive`: usage billing is not active for this account; set it up, or update the payment method, on the Integrations page. */
544
+ PaymentRequired: {
545
+ headers: {
546
+ [name: string]: unknown;
547
+ };
548
+ content: {
549
+ "application/json": components["schemas"]["Error"];
550
+ };
551
+ };
552
+ /** @description The API version this request is answered under has been discontinued. Send a supported version in `Lingara-Version`, or re-pin the client. */
553
+ VersionDiscontinued: {
554
+ headers: {
555
+ [name: string]: unknown;
556
+ };
557
+ content: {
558
+ "application/json": components["schemas"]["Error"];
559
+ };
560
+ };
561
+ /** @description `api_version_discontinued`: this request's API version has been discontinued. `cursor_expired`: the cursor is older than 30 days; start again without one. */
562
+ Gone: {
563
+ headers: {
564
+ [name: string]: unknown;
565
+ };
566
+ content: {
567
+ "application/json": components["schemas"]["Error"];
568
+ };
569
+ };
570
+ /** @description The service is temporarily unavailable; retry after the number of seconds in `Retry-After`. During maintenance the body is plain text rather than the error envelope. */
571
+ Unavailable: {
572
+ headers: {
573
+ [name: string]: unknown;
574
+ };
575
+ content: {
576
+ "application/json": components["schemas"]["Error"];
577
+ "text/plain": string;
578
+ };
579
+ };
580
+ };
581
+ parameters: {
582
+ PlanId: string;
583
+ VersionId: string;
584
+ /** @description The API version to answer this request under. Without it, an access token gets the version its client is pinned to, and a request with no token gets the current version. The version still in development is reached only by naming it here. An unknown version answers `400` with code `api_version_unknown`. `GET /v1/versions` lists the versions. */
585
+ LingaraVersion: string;
586
+ /** @description Where to continue from: an earlier page's `next_cursor`, or a stream event's `id:`. A cursor older than 30 days answers `410` with code `cursor_expired`. */
587
+ EventCursor: string;
588
+ /** @description Where to begin without a cursor: `latest` for events from now on, or `oldest` for every event still kept. */
589
+ EventStart: "latest" | "oldest";
590
+ /** @description Only these event types, comma-separated. Without it, every type your token's scopes can read. */
591
+ EventTypes: string[];
592
+ /** @description The most events one page returns, from 1 to 100. */
593
+ EventLimit: number;
594
+ /** @description The `id:` of the last event you received. It takes precedence over `cursor` and `start`. */
595
+ LastEventId: string;
596
+ /** @description A value you choose for each event and reuse when you retry it: 1 to 255 visible ASCII characters, such as a UUID. A retry with the same key gets the first answer back and is not billed again, even if its body differs. Without a valid key the request answers `400` with code `idempotency_key_required`. */
597
+ IdempotencyKey: string;
598
+ };
599
+ requestBodies: never;
600
+ headers: {
601
+ /** @description The API version this response was answered under. Absent until the first version is frozen. */
602
+ LingaraVersion: string;
603
+ /** @description When this response's API version was deprecated, as `@` followed by Unix seconds. Present only on a deprecated version. */
604
+ Deprecation: string;
605
+ /** @description The date from which this response's API version may be discontinued. Present only on a deprecated version. */
606
+ Sunset: string;
607
+ /** @description A link, with relation `deprecation`, to this API version's details. Present only on a deprecated version. */
608
+ Link: string;
609
+ };
610
+ pathItems: never;
611
+ }
612
+ interface operations {
613
+ getLessonPlan: {
614
+ parameters: {
615
+ query?: never;
616
+ header?: {
617
+ /** @description The API version to answer this request under. Without it, an access token gets the version its client is pinned to, and a request with no token gets the current version. The version still in development is reached only by naming it here. An unknown version answers `400` with code `api_version_unknown`. `GET /v1/versions` lists the versions. */
618
+ "Lingara-Version"?: components["parameters"]["LingaraVersion"];
619
+ };
620
+ path: {
621
+ id: components["parameters"]["PlanId"];
622
+ };
623
+ cookie?: never;
624
+ };
625
+ requestBody?: never;
626
+ responses: {
627
+ /** @description The lesson plan */
628
+ 200: {
629
+ headers: {
630
+ "Lingara-Version": components["headers"]["LingaraVersion"];
631
+ Deprecation: components["headers"]["Deprecation"];
632
+ Sunset: components["headers"]["Sunset"];
633
+ Link: components["headers"]["Link"];
634
+ [name: string]: unknown;
635
+ };
636
+ content: {
637
+ /**
638
+ * @example {
639
+ * "id": "3f1c2a9e-5b7d-4e21-9a0c-6d8e4f2b1a37",
640
+ * "status": "complete",
641
+ * "title": "At the night market",
642
+ * "source_lang": "en",
643
+ * "target_lang": "zh",
644
+ * "level": 2,
645
+ * "created_at": "2026-09-23T10:00:00Z",
646
+ * "completed_at": "2026-09-23T10:00:41Z",
647
+ * "ai_generated": true,
648
+ * "content": {
649
+ * "introduction": "Order food and ask prices at a night market.",
650
+ * "learning_objectives": [
651
+ * "Ask how much something costs"
652
+ * ],
653
+ * "vocabulary": [
654
+ * {
655
+ * "word": "多少钱",
656
+ * "pronunciation": "duōshao qián",
657
+ * "translation": "how much"
658
+ * }
659
+ * ],
660
+ * "sets": [
661
+ * {
662
+ * "number": 1,
663
+ * "questions": [
664
+ * {
665
+ * "type": "multiple_choice_word",
666
+ * "prompt": "Which word asks for a price?",
667
+ * "options": [
668
+ * "多少钱",
669
+ * "谢谢"
670
+ * ],
671
+ * "answer": "多少钱",
672
+ * "explanation": "多少钱 means how much money."
673
+ * }
674
+ * ]
675
+ * }
676
+ * ]
677
+ * }
678
+ * }
679
+ */
680
+ "application/json": components["schemas"]["LessonPlan"];
681
+ };
682
+ };
683
+ 410: components["responses"]["VersionDiscontinued"];
684
+ 503: components["responses"]["Unavailable"];
685
+ "4XX": components["responses"]["Error"];
686
+ "5XX": components["responses"]["Error"];
687
+ };
688
+ };
689
+ getUsage: {
690
+ parameters: {
691
+ query?: never;
692
+ header?: {
693
+ /** @description The API version to answer this request under. Without it, an access token gets the version its client is pinned to, and a request with no token gets the current version. The version still in development is reached only by naming it here. An unknown version answers `400` with code `api_version_unknown`. `GET /v1/versions` lists the versions. */
694
+ "Lingara-Version"?: components["parameters"]["LingaraVersion"];
695
+ };
696
+ path?: never;
697
+ cookie?: never;
698
+ };
699
+ requestBody?: never;
700
+ responses: {
701
+ /** @description Your allowance */
702
+ 200: {
703
+ headers: {
704
+ "Lingara-Version": components["headers"]["LingaraVersion"];
705
+ Deprecation: components["headers"]["Deprecation"];
706
+ Sunset: components["headers"]["Sunset"];
707
+ Link: components["headers"]["Link"];
708
+ [name: string]: unknown;
709
+ };
710
+ content: {
711
+ /**
712
+ * @example {
713
+ * "allowance": [
714
+ * {
715
+ * "feature": "vocab",
716
+ * "window": "daily",
717
+ * "limit": 50,
718
+ * "used": 12,
719
+ * "remaining": 38,
720
+ * "reset_at": 1790208000
721
+ * },
722
+ * {
723
+ * "feature": "lesson_plans",
724
+ * "window": "lifetime",
725
+ * "limit": 3,
726
+ * "used": 1,
727
+ * "remaining": 2
728
+ * }
729
+ * ]
730
+ * }
731
+ */
732
+ "application/json": components["schemas"]["Usage"];
733
+ };
734
+ };
735
+ 410: components["responses"]["VersionDiscontinued"];
736
+ 503: components["responses"]["Unavailable"];
737
+ "4XX": components["responses"]["Error"];
738
+ "5XX": components["responses"]["Error"];
739
+ };
740
+ };
741
+ listEvents: {
742
+ parameters: {
743
+ query?: {
744
+ /** @description Where to continue from: an earlier page's `next_cursor`, or a stream event's `id:`. A cursor older than 30 days answers `410` with code `cursor_expired`. */
745
+ cursor?: components["parameters"]["EventCursor"];
746
+ /** @description Where to begin without a cursor: `latest` for events from now on, or `oldest` for every event still kept. */
747
+ start?: components["parameters"]["EventStart"];
748
+ /** @description Only these event types, comma-separated. Without it, every type your token's scopes can read. */
749
+ types?: components["parameters"]["EventTypes"];
750
+ /** @description The most events one page returns, from 1 to 100. */
751
+ limit?: components["parameters"]["EventLimit"];
752
+ };
753
+ header?: {
754
+ /** @description The API version to answer this request under. Without it, an access token gets the version its client is pinned to, and a request with no token gets the current version. The version still in development is reached only by naming it here. An unknown version answers `400` with code `api_version_unknown`. `GET /v1/versions` lists the versions. */
755
+ "Lingara-Version"?: components["parameters"]["LingaraVersion"];
756
+ };
757
+ path?: never;
758
+ cookie?: never;
759
+ };
760
+ requestBody?: never;
761
+ responses: {
762
+ /** @description A page of events and the cursor to continue from */
763
+ 200: {
764
+ headers: {
765
+ "Lingara-Version": components["headers"]["LingaraVersion"];
766
+ Deprecation: components["headers"]["Deprecation"];
767
+ Sunset: components["headers"]["Sunset"];
768
+ Link: components["headers"]["Link"];
769
+ [name: string]: unknown;
770
+ };
771
+ content: {
772
+ /**
773
+ * @example {
774
+ * "items": [
775
+ * {
776
+ * "id": "lgr_evt_4f2a9c1e7b3d4e5f8a9b0c1d2e3f4a5b",
777
+ * "type": "lesson_plan.ready",
778
+ * "created_at": "2026-10-01T09:12:44Z",
779
+ * "api_version": "2026-09-equipped-boxfish",
780
+ * "subject": "lgr_sub_0f1e2d3c4b5a69788796a5b4c3d2e1f0",
781
+ * "data": {
782
+ * "plan_id": "3f1c2a9e-5b7d-4e21-9a0c-6d8e4f2b1a37",
783
+ * "status": "complete",
784
+ * "title": "At the night market",
785
+ * "source_lang": "en",
786
+ * "target_lang": "zh",
787
+ * "level": 2
788
+ * }
789
+ * }
790
+ * ],
791
+ * "next_cursor": "djEuNzQ0MTIuOTkxLjE3OTAyNDk1NjQ",
792
+ * "has_more": false
793
+ * }
794
+ */
795
+ "application/json": components["schemas"]["EventPage"];
796
+ };
797
+ };
798
+ 410: components["responses"]["Gone"];
799
+ 503: components["responses"]["Unavailable"];
800
+ "4XX": components["responses"]["Error"];
801
+ "5XX": components["responses"]["Error"];
802
+ };
803
+ };
804
+ sendEvent: {
805
+ parameters: {
806
+ query?: never;
807
+ header: {
808
+ /** @description The API version to answer this request under. Without it, an access token gets the version its client is pinned to, and a request with no token gets the current version. The version still in development is reached only by naming it here. An unknown version answers `400` with code `api_version_unknown`. `GET /v1/versions` lists the versions. */
809
+ "Lingara-Version"?: components["parameters"]["LingaraVersion"];
810
+ /** @description A value you choose for each event and reuse when you retry it: 1 to 255 visible ASCII characters, such as a UUID. A retry with the same key gets the first answer back and is not billed again, even if its body differs. Without a valid key the request answers `400` with code `idempotency_key_required`. */
811
+ "Idempotency-Key": components["parameters"]["IdempotencyKey"];
812
+ };
813
+ path?: never;
814
+ cookie?: never;
815
+ };
816
+ requestBody: {
817
+ content: {
818
+ "application/json": Record<string, never>;
819
+ };
820
+ };
821
+ responses: {
822
+ /** @description The event is recorded */
823
+ 202: {
824
+ headers: {
825
+ "Lingara-Version": components["headers"]["LingaraVersion"];
826
+ Deprecation: components["headers"]["Deprecation"];
827
+ Sunset: components["headers"]["Sunset"];
828
+ Link: components["headers"]["Link"];
829
+ [name: string]: unknown;
830
+ };
831
+ content: {
832
+ /**
833
+ * @example {
834
+ * "id": "lgr_evt_4f2a9c1e7b3d4e5f8a9b0c1d2e3f4a5b",
835
+ * "type": "world.context_changed",
836
+ * "created_at": "2026-10-01T09:12:44Z",
837
+ * "reaction": {
838
+ * "status": "started",
839
+ * "plan_id": "3f1c2a9e-5b7d-4e21-9a0c-6d8e4f2b1a37",
840
+ * "plan_status": "generating"
841
+ * }
842
+ * }
843
+ */
844
+ "application/json": components["schemas"]["InboundEventAccepted"];
845
+ };
846
+ };
847
+ 402: components["responses"]["PaymentRequired"];
848
+ 410: components["responses"]["VersionDiscontinued"];
849
+ 503: components["responses"]["Unavailable"];
850
+ "4XX": components["responses"]["Error"];
851
+ "5XX": components["responses"]["Error"];
852
+ };
853
+ };
854
+ getOpenApiDocument: {
855
+ parameters: {
856
+ query?: never;
857
+ header?: {
858
+ /** @description The API version to answer this request under. Without it, an access token gets the version its client is pinned to, and a request with no token gets the current version. The version still in development is reached only by naming it here. An unknown version answers `400` with code `api_version_unknown`. `GET /v1/versions` lists the versions. */
859
+ "Lingara-Version"?: components["parameters"]["LingaraVersion"];
860
+ };
861
+ path?: never;
862
+ cookie?: never;
863
+ };
864
+ requestBody?: never;
865
+ responses: {
866
+ /** @description The OpenAPI document */
867
+ 200: {
868
+ headers: {
869
+ "Lingara-Version": components["headers"]["LingaraVersion"];
870
+ Deprecation: components["headers"]["Deprecation"];
871
+ Sunset: components["headers"]["Sunset"];
872
+ Link: components["headers"]["Link"];
873
+ [name: string]: unknown;
874
+ };
875
+ content: {
876
+ "application/json": Record<string, never>;
877
+ };
878
+ };
879
+ 410: components["responses"]["VersionDiscontinued"];
880
+ 503: components["responses"]["Unavailable"];
881
+ "4XX": components["responses"]["Error"];
882
+ };
883
+ };
884
+ getAsyncApiDocument: {
885
+ parameters: {
886
+ query?: never;
887
+ header?: {
888
+ /** @description The API version to answer this request under. Without it, an access token gets the version its client is pinned to, and a request with no token gets the current version. The version still in development is reached only by naming it here. An unknown version answers `400` with code `api_version_unknown`. `GET /v1/versions` lists the versions. */
889
+ "Lingara-Version"?: components["parameters"]["LingaraVersion"];
890
+ };
891
+ path?: never;
892
+ cookie?: never;
893
+ };
894
+ requestBody?: never;
895
+ responses: {
896
+ /** @description The AsyncAPI document */
897
+ 200: {
898
+ headers: {
899
+ "Lingara-Version": components["headers"]["LingaraVersion"];
900
+ Deprecation: components["headers"]["Deprecation"];
901
+ Sunset: components["headers"]["Sunset"];
902
+ Link: components["headers"]["Link"];
903
+ [name: string]: unknown;
904
+ };
905
+ content: {
906
+ "application/json": Record<string, never>;
907
+ };
908
+ };
909
+ 410: components["responses"]["VersionDiscontinued"];
910
+ 503: components["responses"]["Unavailable"];
911
+ "4XX": components["responses"]["Error"];
912
+ };
913
+ };
914
+ listApiVersions: {
915
+ parameters: {
916
+ query?: never;
917
+ header?: {
918
+ /** @description The API version to answer this request under. Without it, an access token gets the version its client is pinned to, and a request with no token gets the current version. The version still in development is reached only by naming it here. An unknown version answers `400` with code `api_version_unknown`. `GET /v1/versions` lists the versions. */
919
+ "Lingara-Version"?: components["parameters"]["LingaraVersion"];
920
+ };
921
+ path?: never;
922
+ cookie?: never;
923
+ };
924
+ requestBody?: never;
925
+ responses: {
926
+ /** @description Every API version */
927
+ 200: {
928
+ headers: {
929
+ "Lingara-Version": components["headers"]["LingaraVersion"];
930
+ Deprecation: components["headers"]["Deprecation"];
931
+ Sunset: components["headers"]["Sunset"];
932
+ Link: components["headers"]["Link"];
933
+ [name: string]: unknown;
934
+ };
935
+ content: {
936
+ /**
937
+ * @example {
938
+ * "current": "2026-10-brave-otter",
939
+ * "development": "2026-11-quiet-lantern",
940
+ * "versions": [
941
+ * {
942
+ * "id": "2026-10-gentle-heron",
943
+ * "state": "deprecated",
944
+ * "lts": true,
945
+ * "minted_at": "2026-10-01T09:00:00Z",
946
+ * "sunset_at": "2027-03-01T00:00:00Z"
947
+ * },
948
+ * {
949
+ * "id": "2026-10-brave-otter",
950
+ * "state": "supported",
951
+ * "lts": false,
952
+ * "minted_at": "2026-10-01T09:00:05Z",
953
+ * "sunset_at": null
954
+ * },
955
+ * {
956
+ * "id": "2026-11-quiet-lantern",
957
+ * "state": "development",
958
+ * "lts": false,
959
+ * "minted_at": "2026-11-02T10:00:00Z",
960
+ * "sunset_at": null
961
+ * }
962
+ * ]
963
+ * }
964
+ */
965
+ "application/json": components["schemas"]["VersionList"];
966
+ };
967
+ };
968
+ 410: components["responses"]["VersionDiscontinued"];
969
+ 503: components["responses"]["Unavailable"];
970
+ "4XX": components["responses"]["Error"];
971
+ "5XX": components["responses"]["Error"];
972
+ };
973
+ };
974
+ getApiVersion: {
975
+ parameters: {
976
+ query?: never;
977
+ header?: {
978
+ /** @description The API version to answer this request under. Without it, an access token gets the version its client is pinned to, and a request with no token gets the current version. The version still in development is reached only by naming it here. An unknown version answers `400` with code `api_version_unknown`. `GET /v1/versions` lists the versions. */
979
+ "Lingara-Version"?: components["parameters"]["LingaraVersion"];
980
+ };
981
+ path: {
982
+ id: components["parameters"]["VersionId"];
983
+ };
984
+ cookie?: never;
985
+ };
986
+ requestBody?: never;
987
+ responses: {
988
+ /** @description The API version */
989
+ 200: {
990
+ headers: {
991
+ "Lingara-Version": components["headers"]["LingaraVersion"];
992
+ Deprecation: components["headers"]["Deprecation"];
993
+ Sunset: components["headers"]["Sunset"];
994
+ Link: components["headers"]["Link"];
995
+ [name: string]: unknown;
996
+ };
997
+ content: {
998
+ /**
999
+ * @example {
1000
+ * "id": "2026-10-brave-otter",
1001
+ * "state": "supported",
1002
+ * "lts": false,
1003
+ * "minted_at": "2026-10-01T09:00:05Z",
1004
+ * "sunset_at": null,
1005
+ * "summary": "The first surface.",
1006
+ * "history": [
1007
+ * {
1008
+ * "state": "development",
1009
+ * "at": "2026-10-01T09:00:05Z"
1010
+ * },
1011
+ * {
1012
+ * "state": "supported",
1013
+ * "at": "2026-11-02T10:00:00Z"
1014
+ * }
1015
+ * ],
1016
+ * "spec": {
1017
+ * "url": "/v1/openapi.json",
1018
+ * "sha256": "3b7e0c1f9a2d4e5b6c7d8e9f0a1b2c3d4e5f60718293a4b5c6d7e8f9a0b1c2d3"
1019
+ * },
1020
+ * "asyncapi": {
1021
+ * "url": "/v1/asyncapi.json",
1022
+ * "sha256": null
1023
+ * }
1024
+ * }
1025
+ */
1026
+ "application/json": components["schemas"]["VersionDetail"];
1027
+ };
1028
+ };
1029
+ 410: components["responses"]["VersionDiscontinued"];
1030
+ 503: components["responses"]["Unavailable"];
1031
+ "4XX": components["responses"]["Error"];
1032
+ "5XX": components["responses"]["Error"];
1033
+ };
1034
+ };
1035
+ }
1036
+
1037
+ type Schemas$1 = components["schemas"];
1038
+ /** The envelope every event carries, with its type and its typed `data`. */
1039
+ interface EventOf<T extends string, D> {
1040
+ readonly id: string;
1041
+ readonly type: T;
1042
+ readonly createdAt: string;
1043
+ readonly apiVersion: string;
1044
+ readonly subject: string;
1045
+ readonly data: D;
1046
+ }
1047
+ /** `lesson_plan.ready`. */
1048
+ type LessonPlanReady = EventOf<"lesson_plan.ready", Schemas$1["LessonPlanReadyData"]>;
1049
+ /** `lesson_plan.failed`. */
1050
+ type LessonPlanFailed = EventOf<"lesson_plan.failed", Schemas$1["LessonPlanFailedData"]>;
1051
+ /** `usage.threshold_reached`. */
1052
+ type UsageThresholdReached = EventOf<"usage.threshold_reached", Schemas$1["UsageThresholdReachedData"]>;
1053
+ /** `webhook.test`. */
1054
+ type WebhookTest = EventOf<"webhook.test", Schemas$1["WebhookTestData"]>;
1055
+ /** `app.installed`. */
1056
+ type AppInstalled = EventOf<"app.installed", Schemas$1["AppInstalledData"]>;
1057
+ /** `app.uninstalled`. */
1058
+ type AppUninstalled = EventOf<"app.uninstalled", Schemas$1["AppUninstalledData"]>;
1059
+ /**
1060
+ * An event type this library does not know: the catalogue is additive, so a
1061
+ * newer type than the library is this, never an error. Acknowledge it (and
1062
+ * log it), or the sender keeps retrying it.
1063
+ */
1064
+ declare class UnknownEvent implements EventOf<string, unknown> {
1065
+ #private;
1066
+ static [Symbol.hasInstance](value: unknown): value is UnknownEvent;
1067
+ readonly id: string;
1068
+ readonly type: string;
1069
+ readonly createdAt: string;
1070
+ readonly apiVersion: string;
1071
+ readonly subject: string;
1072
+ /** The raw JSON value. */
1073
+ readonly data: unknown;
1074
+ constructor(fields: EventOf<string, unknown>);
1075
+ }
1076
+ /** Every outbound event, discriminated on `type`; `instanceof UnknownEvent` first. */
1077
+ type Event = LessonPlanReady | LessonPlanFailed | UsageThresholdReached | WebhookTest | AppInstalled | AppUninstalled | UnknownEvent;
1078
+ /** An event your game sends with `sendEvent`, serialised as `{type, data}`. */
1079
+ type InboundEvent = {
1080
+ readonly type: "world.context_changed";
1081
+ readonly data: Schemas$1["WorldContextChanged"];
1082
+ } | {
1083
+ readonly type: "world.practice_requested";
1084
+ readonly data: Schemas$1["WorldPracticeRequested"];
1085
+ };
1086
+ /** One constructor per inbound type, named after its `data` model. */
1087
+ declare const InboundEvent: {
1088
+ /** `world.context_changed`. */
1089
+ readonly worldContextChanged: (data: Schemas$1["WorldContextChanged"]) => InboundEvent;
1090
+ /** `world.practice_requested`. */
1091
+ readonly worldPracticeRequested: (data: Schemas$1["WorldPracticeRequested"]) => InboundEvent;
1092
+ };
1093
+ /**
1094
+ * One event from its JSON (text, or an already-decoded value). A known type
1095
+ * is its arm; an unknown type is `UnknownEvent`. Throws
1096
+ * `TransportError{kind: "malformed_event"}` for anything that is not an
1097
+ * envelope, or a known type whose `data` does not decode.
1098
+ */
1099
+ declare function parseEvent(json: unknown): Event;
1100
+
1101
+ type Schemas = components["schemas"];
1102
+ type VocabRequest = Schemas["VocabRequest"];
1103
+ type LessonPlanCreateRequest = Schemas["LessonPlanCreateRequest"];
1104
+ type TutorTurnRequest = Schemas["TutorTurnRequest"];
1105
+ type GenerateVocabularyEvent = Schemas["GenerateVocabularyEvent"];
1106
+ type CreateLessonPlanEvent = Schemas["CreateLessonPlanEvent"];
1107
+ type StreamLessonPlanEvent = Schemas["StreamLessonPlanEvent"];
1108
+ type SendTutorMessageEvent = Schemas["SendTutorMessageEvent"];
1109
+ type StreamEventsEvent = Schemas["StreamEventsEvent"];
1110
+ type VocabStarted = Schemas["VocabStarted"];
1111
+ type VocabItem = Schemas["VocabItem"];
1112
+ type VocabMeta = Schemas["VocabMeta"];
1113
+ type VocabExample = Schemas["VocabExample"];
1114
+ type PlanStarted = Schemas["PlanStarted"];
1115
+ type PlanPhase = Schemas["PlanPhase"];
1116
+ type PlanResult = Schemas["PlanResult"];
1117
+ type PlanPending = Schemas["PlanPending"];
1118
+ type TurnDelta = Schemas["TurnDelta"];
1119
+ type Notice = Schemas["Notice"];
1120
+ type StreamError = Schemas["StreamError"];
1121
+ type LessonPlan = Schemas["LessonPlan"];
1122
+ type LessonPlanContent = Schemas["LessonPlanContent"];
1123
+ type PlanStatus = Schemas["PlanStatus"];
1124
+ type Usage = Schemas["Usage"];
1125
+ type AllowanceRow = Schemas["AllowanceRow"];
1126
+ type VersionList = Schemas["VersionList"];
1127
+ type VersionDetail = Schemas["VersionDetail"];
1128
+ type VersionSummary = Schemas["VersionSummary"];
1129
+ type VersionState = Schemas["VersionState"];
1130
+ type EventEnvelope = Schemas["EventEnvelope"];
1131
+ type EventPage = Schemas["EventPage"];
1132
+ type LessonPlanReadyData = Schemas["LessonPlanReadyData"];
1133
+ type LessonPlanFailedData = Schemas["LessonPlanFailedData"];
1134
+ type UsageThresholdReachedData = Schemas["UsageThresholdReachedData"];
1135
+ type WebhookTestData = Schemas["WebhookTestData"];
1136
+ type AppInstalledData = Schemas["AppInstalledData"];
1137
+ type AppUninstalledData = Schemas["AppUninstalledData"];
1138
+ type WorldContextChanged = Schemas["WorldContextChanged"];
1139
+ type WorldPracticeRequested = Schemas["WorldPracticeRequested"];
1140
+ type Npc = Schemas["Npc"];
1141
+ type InboundEventAccepted = Schemas["InboundEventAccepted"];
1142
+ type ReactionReport = Schemas["ReactionReport"];
1143
+
1144
+ /** Where a feed or a tail starts, and which types it carries. */
1145
+ interface EventsParams {
1146
+ /** An earlier `cursor` (a page's `next_cursor`, or a stream `id:`). */
1147
+ cursor?: string | undefined;
1148
+ /** Without a `cursor`: `"latest"` (the server's default) or `"oldest"`. */
1149
+ start?: "latest" | "oldest" | undefined;
1150
+ /** Only these types. */
1151
+ types?: readonly string[] | undefined;
1152
+ }
1153
+ /** `listEvents`' query: one page. */
1154
+ interface ListEventsParams extends EventsParams {
1155
+ /** 1–100; the server's default is 50. */
1156
+ limit?: number | undefined;
1157
+ }
1158
+ /** Fetches one page. */
1159
+ type PageSource = (query: ListEventsParams) => Promise<EventPage>;
1160
+ /**
1161
+ * Every event from `cursor` (or `start`) to where the feed is caught up.
1162
+ * `for await` it, then save `cursor` and call `events({ cursor })` again
1163
+ * later, or hand it to `tailEvents`.
1164
+ */
1165
+ declare class EventFeed implements AsyncIterableIterator<Event> {
1166
+ #private;
1167
+ constructor(params: EventsParams, page: PageSource);
1168
+ /**
1169
+ * Where to resume: once a page's last item has been yielded (or the page
1170
+ * was empty), that page's `next_cursor`; before the first page, the
1171
+ * caller's `cursor`.
1172
+ */
1173
+ get cursor(): string | undefined;
1174
+ [Symbol.asyncIterator](): this;
1175
+ next(): Promise<IteratorResult<Event>>;
1176
+ return(): Promise<IteratorResult<Event>>;
1177
+ }
1178
+
1179
+ /** Wall-clock time, in epoch milliseconds. A testing seam. */
1180
+ interface Clock {
1181
+ now(): number;
1182
+ }
1183
+ /**
1184
+ * Waits `ms` milliseconds, or rejects with `signal.reason` as soon as the
1185
+ * signal aborts. A testing seam.
1186
+ */
1187
+ type Sleeper = (ms: number, signal?: AbortSignal) => Promise<void>;
1188
+
1189
+ type FetchLike = (input: string, init: RequestInit) => Promise<Response>;
1190
+
1191
+ /** Where the client gets its access tokens. A caller may supply their own. */
1192
+ interface TokenSource {
1193
+ /** An access token. `signal` abandons this caller's wait only. */
1194
+ token(options?: {
1195
+ signal?: AbortSignal;
1196
+ }): Promise<string>;
1197
+ /** Forgets `token` only if it is still the cached one. */
1198
+ invalidate(token: string): void;
1199
+ }
1200
+ interface ClientCredentialsOptions {
1201
+ clientId: string;
1202
+ clientSecret: string;
1203
+ /** `"basic"` (the default) is `client_secret_basic`; `"post"` is `client_secret_post`. */
1204
+ auth?: "basic" | "post" | undefined;
1205
+ scopes?: readonly string[] | undefined;
1206
+ tokenUrl?: string | undefined;
1207
+ maxAttempts?: number | undefined;
1208
+ retryAfterCapSeconds?: number | undefined;
1209
+ tokenRequestTimeoutMs?: number | undefined;
1210
+ userAgentSuffix?: string | undefined;
1211
+ /** A testing seam. */
1212
+ clock?: Clock | undefined;
1213
+ /** A testing seam. */
1214
+ sleeper?: Sleeper | undefined;
1215
+ fetch?: FetchLike | undefined;
1216
+ }
1217
+ declare const DEFAULT_TOKEN_URL = "https://api.getlingara.com/oauth/token";
1218
+ /** The OAuth 2.0 client-credentials grant against `/oauth/token`. */
1219
+ declare class ClientCredentials implements TokenSource {
1220
+ #private;
1221
+ readonly clientId: string;
1222
+ constructor(options: ClientCredentialsOptions);
1223
+ token(options?: {
1224
+ signal?: AbortSignal;
1225
+ }): Promise<string>;
1226
+ invalidate(token: string): void;
1227
+ /** The cached access token, raw. The one accessor that does not redact. */
1228
+ exposeToken(): string | undefined;
1229
+ toJSON(): Record<string, unknown>;
1230
+ [INSPECT](): string;
1231
+ toString(): string;
1232
+ }
1233
+
1234
+ /** What a response under a deprecated version says about it. */
1235
+ interface DeprecationNotice {
1236
+ /** The `Lingara-Version` echo. */
1237
+ version?: string;
1238
+ /** `Deprecation`, parsed from `@<unix seconds>`; absent when unparseable. */
1239
+ deprecatedAt?: Date;
1240
+ /** `Sunset`, parsed from an IMF-fixdate; absent when unparseable or missing. */
1241
+ sunsetAt?: Date;
1242
+ /** `Link`: the raw value, and its target resolved against the request URL. */
1243
+ link?: {
1244
+ raw: string;
1245
+ url?: URL;
1246
+ };
1247
+ /** The raw `Deprecation` header. */
1248
+ deprecation: string;
1249
+ /** The raw `Sunset` header. */
1250
+ sunset?: string;
1251
+ }
1252
+ type DeprecationHook = (notice: DeprecationNotice) => void;
1253
+
1254
+ interface LingaraOptions {
1255
+ clientId?: string;
1256
+ clientSecret?: string;
1257
+ /** `"basic"` (the default) or `"post"` (`client_secret_post`). */
1258
+ auth?: "basic" | "post";
1259
+ scopes?: readonly string[];
1260
+ /** Replaces the built-in client-credentials source. Not with `clientSecret`. */
1261
+ tokenSource?: TokenSource;
1262
+ baseUrl?: string;
1263
+ tokenUrl?: string;
1264
+ /** Pins every `/v1` request to this API version. */
1265
+ version?: string;
1266
+ /** Called once per response under a deprecated version. */
1267
+ onDeprecation?: DeprecationHook;
1268
+ /** Tries per HTTP request; `1` turns retries off. Default 3. */
1269
+ maxAttempts?: number;
1270
+ /** Default 60. */
1271
+ retryAfterCapSeconds?: number;
1272
+ /** Default 120 000. */
1273
+ streamIdleTimeoutMs?: number;
1274
+ /** Consecutive failed reopens before `tailEvents` raises the last (CONTRACT.md K5a). Default 8. */
1275
+ tailMaxFailures?: number;
1276
+ /** Default 30 000. */
1277
+ tokenRequestTimeoutMs?: number;
1278
+ /** Appended to the `User-Agent` after one space. */
1279
+ userAgentSuffix?: string;
1280
+ /** A testing seam: epoch milliseconds. */
1281
+ clock?: Clock;
1282
+ /** A testing seam. */
1283
+ sleeper?: Sleeper;
1284
+ /** Defaults to `globalThis.fetch`. */
1285
+ fetch?: FetchLike;
1286
+ }
1287
+ interface CallOptions {
1288
+ signal?: AbortSignal;
1289
+ }
1290
+
1291
+ interface SendEventOptions extends CallOptions {
1292
+ /**
1293
+ * Sent unchanged as `Idempotency-Key`. Supply your own when you may resend
1294
+ * after a crash: a generated key is gone once the call returns. A reused
1295
+ * key returns the first answer, whatever the body.
1296
+ */
1297
+ idempotencyKey?: string;
1298
+ }
1299
+
1300
+ declare const STREAMS: {
1301
+ readonly generateVocabulary: {
1302
+ readonly method: "POST";
1303
+ readonly path: "/v1/vocab/stream";
1304
+ readonly requestBody: "VocabRequest";
1305
+ readonly union: "GenerateVocabularyEvent";
1306
+ readonly events: readonly ["started", "item", "done", "error"];
1307
+ readonly ends: {
1308
+ readonly done: "end";
1309
+ readonly error: "raise";
1310
+ };
1311
+ };
1312
+ readonly createLessonPlan: {
1313
+ readonly method: "POST";
1314
+ readonly path: "/v1/lesson-plans";
1315
+ readonly requestBody: "LessonPlanCreateRequest";
1316
+ readonly union: "CreateLessonPlanEvent";
1317
+ readonly events: readonly ["started", "phase", "result", "error"];
1318
+ readonly ends: {
1319
+ readonly result: "yield";
1320
+ readonly error: "raise";
1321
+ };
1322
+ };
1323
+ readonly streamLessonPlan: {
1324
+ readonly method: "GET";
1325
+ readonly path: "/v1/lesson-plans/{id}/stream";
1326
+ readonly requestBody: null;
1327
+ readonly union: "StreamLessonPlanEvent";
1328
+ readonly events: readonly ["started", "phase", "result", "pending", "error"];
1329
+ readonly ends: {
1330
+ readonly result: "yield";
1331
+ readonly pending: "yield";
1332
+ readonly error: "raise";
1333
+ };
1334
+ };
1335
+ readonly sendTutorMessage: {
1336
+ readonly method: "POST";
1337
+ readonly path: "/v1/tutor/message";
1338
+ readonly requestBody: "TutorTurnRequest";
1339
+ readonly union: "SendTutorMessageEvent";
1340
+ readonly events: readonly ["delta", "notice", "done", "error"];
1341
+ readonly ends: {
1342
+ readonly done: "end";
1343
+ readonly error: "raise";
1344
+ };
1345
+ };
1346
+ readonly streamEvents: {
1347
+ readonly method: "GET";
1348
+ readonly path: "/v1/events/stream";
1349
+ readonly requestBody: null;
1350
+ readonly union: "StreamEventsEvent";
1351
+ readonly events: readonly ["event", "done", "error"];
1352
+ readonly ends: {
1353
+ readonly done: "end";
1354
+ readonly error: "raise";
1355
+ };
1356
+ };
1357
+ };
1358
+ type StreamOperation = keyof typeof STREAMS;
1359
+
1360
+ /** What a stream yields: every event but `done` and `error`. */
1361
+ type Yielded<E> = Exclude<E, {
1362
+ event: "done";
1363
+ } | {
1364
+ event: "error";
1365
+ }>;
1366
+ /** An opened stream: a 200 `text/event-stream` response and its echo. */
1367
+ interface OpenedStream {
1368
+ response: Response;
1369
+ servedVersion: string | undefined;
1370
+ }
1371
+ interface EventStreamInit {
1372
+ operation: StreamOperation;
1373
+ /** Sends the request (auth, retries, error mapping) under `signal`. */
1374
+ open: (signal: AbortSignal) => Promise<OpenedStream>;
1375
+ signal?: AbortSignal | undefined;
1376
+ idleTimeoutMs: number;
1377
+ }
1378
+ /** A stream of events. `for await` it; `break` or `close()` ends it. */
1379
+ declare class EventStream<E extends {
1380
+ event: string;
1381
+ }> implements AsyncIterableIterator<Yielded<E>> {
1382
+ #private;
1383
+ constructor(init: EventStreamInit);
1384
+ /**
1385
+ * The `Lingara-Version` echo. Reading it starts the request if iteration
1386
+ * has not. Never rejects: `undefined` when the request fails or the stream
1387
+ * closes first.
1388
+ */
1389
+ get servedVersion(): Promise<string | undefined>;
1390
+ /**
1391
+ * The last `id:` the stream has carried, as of the frame last handled
1392
+ * (CONTRACT.md K5, Parsing). Only the tail reads it (K5a).
1393
+ */
1394
+ get lastEventId(): string | undefined;
1395
+ [Symbol.asyncIterator](): this;
1396
+ next(): Promise<IteratorResult<Yielded<E>>>;
1397
+ return(): Promise<IteratorResult<Yielded<E>>>;
1398
+ /** Ends the stream and closes the connection. Idempotent. */
1399
+ close(): Promise<void>;
1400
+ }
1401
+
1402
+ interface EventTailInit {
1403
+ /** One connection: the raw operation, sent with `Last-Event-ID` when given and without K4's retries. */
1404
+ open: (lastEventId: string | undefined, signal: AbortSignal) => EventStream<StreamEventsEvent>;
1405
+ cursor: string | undefined;
1406
+ sleeper: Sleeper;
1407
+ retryAfterCapSeconds: number;
1408
+ maxFailures: number;
1409
+ signal?: AbortSignal | undefined;
1410
+ }
1411
+ /**
1412
+ * Live events from `cursor`, reconnecting after every ending. `for await` it;
1413
+ * `break` or the signal ends it. `cursor` is the `id:` of the last frame
1414
+ * that carried one, an event's or a `done`'s.
1415
+ */
1416
+ declare class EventTail implements AsyncIterableIterator<Event> {
1417
+ #private;
1418
+ constructor(init: EventTailInit);
1419
+ /** Where to resume: hand it to `tailEvents` or `events` later. */
1420
+ get cursor(): string | undefined;
1421
+ [Symbol.asyncIterator](): this;
1422
+ next(): Promise<IteratorResult<Event>>;
1423
+ return(): Promise<IteratorResult<Event>>;
1424
+ /** Ends the tail and closes the connection. Idempotent. */
1425
+ close(): Promise<void>;
1426
+ }
1427
+
1428
+ /** A JSON result, with the `Lingara-Version` echo beside it (non-enumerable). */
1429
+ type WithServedVersion<T> = T & {
1430
+ readonly servedVersion?: string;
1431
+ };
1432
+ type JsonOk<Op extends keyof operations> = operations[Op]["responses"] extends {
1433
+ 200: {
1434
+ content: {
1435
+ "application/json": infer T;
1436
+ };
1437
+ };
1438
+ } ? T : never;
1439
+ declare const DEFAULT_BASE_URL = "https://api.getlingara.com";
1440
+ /** The Lingara API. Server-side only: Node, Deno and Bun. */
1441
+ declare class Lingara {
1442
+ #private;
1443
+ readonly clientId: string | undefined;
1444
+ constructor(options?: LingaraOptions);
1445
+ /** The token source in use, if the client has credentials. */
1446
+ get tokenSource(): TokenSource | undefined;
1447
+ generateVocabulary(body: VocabRequest, options?: CallOptions): EventStream<GenerateVocabularyEvent>;
1448
+ createLessonPlan(body: LessonPlanCreateRequest, options?: CallOptions): EventStream<CreateLessonPlanEvent>;
1449
+ streamLessonPlan(params: {
1450
+ id: string;
1451
+ }, options?: CallOptions): EventStream<StreamLessonPlanEvent>;
1452
+ sendTutorMessage(body: TutorTurnRequest, options?: CallOptions): EventStream<SendTutorMessageEvent>;
1453
+ /** One connection under K5; `tailEvents` is the one that reconnects. */
1454
+ streamEvents(params?: EventsParams & {
1455
+ lastEventId?: string;
1456
+ }, options?: CallOptions): EventStream<StreamEventsEvent>;
1457
+ /** Every event from `cursor` (or `start`) to where the feed is caught up; never polls. */
1458
+ events(params?: EventsParams, options?: CallOptions): EventFeed;
1459
+ /** Live events, reconnecting from `cursor` after every ending (CONTRACT.md K5a). */
1460
+ tailEvents(params?: EventsParams, options?: CallOptions): EventTail;
1461
+ /** `{type, data}` with one `Idempotency-Key` across K4's attempts; the `202` body. */
1462
+ sendEvent(event: InboundEvent, options?: SendEventOptions): Promise<WithServedVersion<InboundEventAccepted>>;
1463
+ getLessonPlan(params: {
1464
+ id: string;
1465
+ }, options?: CallOptions): Promise<WithServedVersion<JsonOk<"getLessonPlan">>>;
1466
+ getUsage(options?: CallOptions): Promise<WithServedVersion<JsonOk<"getUsage">>>;
1467
+ /** One page of events; `events()` walks them. */
1468
+ listEvents(params?: ListEventsParams, options?: CallOptions): Promise<WithServedVersion<JsonOk<"listEvents">>>;
1469
+ getOpenApiDocument(options?: CallOptions): Promise<WithServedVersion<JsonOk<"getOpenApiDocument">>>;
1470
+ getAsyncApiDocument(options?: CallOptions): Promise<WithServedVersion<JsonOk<"getAsyncApiDocument">>>;
1471
+ listApiVersions(options?: CallOptions): Promise<WithServedVersion<JsonOk<"listApiVersions">>>;
1472
+ getApiVersion(params: {
1473
+ id: string;
1474
+ }, options?: CallOptions): Promise<WithServedVersion<JsonOk<"getApiVersion">>>;
1475
+ toJSON(): Record<string, unknown>;
1476
+ [INSPECT](): string;
1477
+ toString(): string;
1478
+ }
1479
+
1480
+ type WebhookVerificationReason = "missing_header" | "malformed_header" | "timestamp_too_old" | "timestamp_too_new" | "no_matching_signature" | "malformed_payload";
1481
+ /**
1482
+ * A webhook that failed verification. Deliberately not a `LingaraError`: a
1483
+ * catch around API calls must not also swallow a forged delivery. The
1484
+ * message never carries a secret, a signature or the body.
1485
+ */
1486
+ declare class WebhookVerificationError extends Error {
1487
+ static [Symbol.hasInstance](value: unknown): boolean;
1488
+ readonly reason: WebhookVerificationReason;
1489
+ constructor(reason: WebhookVerificationReason);
1490
+ }
1491
+ /** A Fetch `Headers`, or a plain map such as Node's `req.headers`. */
1492
+ type WebhookHeaders = Headers | Readonly<Record<string, string | readonly string[] | undefined>>;
1493
+ interface WebhookOptions {
1494
+ /** A testing seam: epoch milliseconds. */
1495
+ clock?: Clock;
1496
+ }
1497
+ /**
1498
+ * Verifies Lingara webhooks. Pass the raw body exactly as received, never a
1499
+ * parsed object. Two secrets verify during a rotation.
1500
+ */
1501
+ declare class Webhook {
1502
+ #private;
1503
+ constructor(secret: string | readonly string[], options?: WebhookOptions);
1504
+ /** Signature checks, then the body parsed into an `Event` whose `id` is `webhook-id`. */
1505
+ verify(body: string | Uint8Array, headers: WebhookHeaders): Promise<Event>;
1506
+ /** The signature checks alone, for a signed body that is not an event (an app-kit request). */
1507
+ verifySignature(body: string | Uint8Array, headers: WebhookHeaders): Promise<void>;
1508
+ toJSON(): Record<string, unknown>;
1509
+ toString(): string;
1510
+ }
1511
+
1512
+ export { type AllowanceRow, ApiError, type AppInstalled, type AppInstalledData, type AppUninstalled, type AppUninstalledData, type CallOptions, ClientCredentials, type ClientCredentialsOptions, type Clock, type CreateLessonPlanEvent, DEFAULT_BASE_URL, DEFAULT_TOKEN_URL, type DeprecationHook, type DeprecationNotice, type Event, type EventEnvelope, EventFeed, type EventOf, type EventPage, EventStream, EventTail, type EventsParams, type FetchLike, type GenerateVocabularyEvent, InboundEvent, type InboundEventAccepted, type LessonPlan, type LessonPlanContent, type LessonPlanCreateRequest, type LessonPlanFailed, type LessonPlanFailedData, type LessonPlanReady, type LessonPlanReadyData, Lingara, LingaraError, type LingaraOptions, type ListEventsParams, MaintenanceError, type Notice, type Npc, OAuthError, type PlanPending, type PlanPhase, type PlanResult, type PlanStarted, type PlanStatus, type ReactionReport, type SendEventOptions, type SendTutorMessageEvent, type Sleeper, type StreamError, type StreamEventsEvent, type StreamLessonPlanEvent, type TokenSource, TransportError, type TransportKind, type TurnDelta, type TutorTurnRequest, UnknownEvent, type Usage, type UsageThresholdReached, type UsageThresholdReachedData, type VersionDetail, type VersionList, type VersionState, type VersionSummary, type VocabExample, type VocabItem, type VocabMeta, type VocabRequest, type VocabStarted, Webhook, type WebhookHeaders, type WebhookOptions, type WebhookTest, type WebhookTestData, WebhookVerificationError, type WebhookVerificationReason, type WithServedVersion, type WorldContextChanged, type WorldPracticeRequested, type Yielded, type components, type operations, parseEvent };