@24klynx/llm 0.1.0
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/dist/index.d.mts +352 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +1357 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +29 -0
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,352 @@
|
|
|
1
|
+
import { ContentBlock } from "@lynx/core";
|
|
2
|
+
|
|
3
|
+
//#region src/types.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* A chat message with a role and content, matching the OpenAI-compatible wire format.
|
|
6
|
+
* Unlike {@link import('@lynx/core').Message}, this is a wire-format type for the LLM API.
|
|
7
|
+
*/
|
|
8
|
+
interface ChatMessage {
|
|
9
|
+
/** Who sent this message. */
|
|
10
|
+
role: "user" | "assistant" | "system";
|
|
11
|
+
/** Message content — ContentBlock array or plain string. */
|
|
12
|
+
content: ContentBlock[] | string;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* A single model that a provider can serve.
|
|
16
|
+
*/
|
|
17
|
+
interface ModelInfo {
|
|
18
|
+
/** Provider‑unique model identifier, e.g. "deepseek-chat". */
|
|
19
|
+
id: string;
|
|
20
|
+
/** Human‑readable label shown in model pickers. */
|
|
21
|
+
label: string;
|
|
22
|
+
/** Maximum combined context window in tokens. */
|
|
23
|
+
contextWindow: number;
|
|
24
|
+
/** Maximum tokens the model can emit in one response. */
|
|
25
|
+
maxOutput: number;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Static capabilities declared by a provider for a given model.
|
|
29
|
+
* Used by the router to decide which model can handle a request.
|
|
30
|
+
*/
|
|
31
|
+
interface ProviderCapability {
|
|
32
|
+
contextWindow: number;
|
|
33
|
+
maxOutput: number;
|
|
34
|
+
supportsReasoning: boolean;
|
|
35
|
+
supportsStreaming: boolean;
|
|
36
|
+
supportsToolUse: boolean;
|
|
37
|
+
supportsVision: boolean;
|
|
38
|
+
/** Provider supports Anthropic‑style cache_control or DeepSeek implicit prefix cache. */
|
|
39
|
+
promptCacheEnabled: boolean;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Every LLM provider (DeepSeek, OpenAI, etc.) implements this interface.
|
|
43
|
+
*
|
|
44
|
+
* The factory pattern is used instead of a class so the provider can be
|
|
45
|
+
* constructed without DI and tested with a mock.
|
|
46
|
+
*/
|
|
47
|
+
interface LlmProvider {
|
|
48
|
+
/** Unique provider id, e.g. "deepseek". */
|
|
49
|
+
readonly id: string;
|
|
50
|
+
/** List models this provider currently serves. */
|
|
51
|
+
listModels(): ModelInfo[];
|
|
52
|
+
/**
|
|
53
|
+
* Return the static capability blob for a model.
|
|
54
|
+
* Throws {@link import('@lynx/core').LlmError} if the model is unknown.
|
|
55
|
+
*/
|
|
56
|
+
getCapability(modelId: string): ProviderCapability;
|
|
57
|
+
/**
|
|
58
|
+
* Stream completions from the provider.
|
|
59
|
+
*
|
|
60
|
+
* `messages` is an array of chat messages with roles and content blocks.
|
|
61
|
+
* `systemPrompt` is an optional system-level instruction prepended as
|
|
62
|
+
* a system message before `messages`. If empty, no system message is added.
|
|
63
|
+
*
|
|
64
|
+
* The returned AsyncGenerator yields {@link StreamEvent} values.
|
|
65
|
+
* The consumer drives iteration; when the consumer stops iterating
|
|
66
|
+
* the underlying HTTP request is aborted via the signal.
|
|
67
|
+
*/
|
|
68
|
+
stream(modelId: string, messages: ChatMessage[], systemPrompt: string, tools: unknown[], signal: AbortSignal): AsyncGenerator<StreamEvent, void, void>;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Discriminated union of every event the LLM stream can emit.
|
|
72
|
+
*
|
|
73
|
+
* The consumer pattern‑matches on `type`:
|
|
74
|
+
* ```ts
|
|
75
|
+
* for await (const ev of provider.stream(...)) {
|
|
76
|
+
* switch (ev.type) {
|
|
77
|
+
* case 'text_delta': ...; break;
|
|
78
|
+
* case 'tool_use': ...; break;
|
|
79
|
+
* // ...
|
|
80
|
+
* }
|
|
81
|
+
* }
|
|
82
|
+
* ```
|
|
83
|
+
*/
|
|
84
|
+
type StreamEvent = TextDeltaEvent | ReasoningDeltaEvent | ToolUseStartEvent | ToolUseDeltaEvent | ToolUseEndEvent | ToolResultEvent | ToolRecapEvent | ErrorEvent | DoneEvent;
|
|
85
|
+
/** Incremental text chunk from the assistant. */
|
|
86
|
+
interface TextDeltaEvent {
|
|
87
|
+
type: "text_delta";
|
|
88
|
+
/** Monotonically increasing index for this chunk. */
|
|
89
|
+
index: number;
|
|
90
|
+
/** The text fragment (may be an empty string for flush frames). */
|
|
91
|
+
text: string;
|
|
92
|
+
}
|
|
93
|
+
/** Reasoning / thinking token chunk (DeepSeek R1, o1, etc.). */
|
|
94
|
+
interface ReasoningDeltaEvent {
|
|
95
|
+
type: "reasoning_delta";
|
|
96
|
+
index: number;
|
|
97
|
+
text: string;
|
|
98
|
+
}
|
|
99
|
+
/** A new tool_use block has started in the response. */
|
|
100
|
+
interface ToolUseStartEvent {
|
|
101
|
+
type: "tool_use_start";
|
|
102
|
+
/** Unique call id generated by the provider. */
|
|
103
|
+
callId: string;
|
|
104
|
+
/** Tool name as registered in the tool catalog. */
|
|
105
|
+
name: string;
|
|
106
|
+
}
|
|
107
|
+
/** Incremental JSON fragment for the current tool_use block. */
|
|
108
|
+
interface ToolUseDeltaEvent {
|
|
109
|
+
type: "tool_use_delta";
|
|
110
|
+
callId: string;
|
|
111
|
+
/** Partial JSON text. Concatenate to form the complete input. */
|
|
112
|
+
text: string;
|
|
113
|
+
}
|
|
114
|
+
/** The current tool_use block is complete. */
|
|
115
|
+
interface ToolUseEndEvent {
|
|
116
|
+
type: "tool_use_end";
|
|
117
|
+
callId: string;
|
|
118
|
+
/** Parsed input object (provider‑side consolidation). */
|
|
119
|
+
input: Record<string, unknown>;
|
|
120
|
+
}
|
|
121
|
+
/** A tool_result block being fed back into the conversation. */
|
|
122
|
+
interface ToolResultEvent {
|
|
123
|
+
type: "tool_result";
|
|
124
|
+
toolUseId: string;
|
|
125
|
+
content: string;
|
|
126
|
+
isError: boolean;
|
|
127
|
+
}
|
|
128
|
+
/** A non‑fatal stream error (e.g. a single turn failed but the session continues). */
|
|
129
|
+
interface ErrorEvent {
|
|
130
|
+
type: "error";
|
|
131
|
+
code: string;
|
|
132
|
+
message: string;
|
|
133
|
+
}
|
|
134
|
+
/** Tool execution batch summary — generated locally after tools finish. */
|
|
135
|
+
interface ToolRecapEvent {
|
|
136
|
+
type: "tool_recap";
|
|
137
|
+
/** Human-readable summary of completed tools (Chinese). */
|
|
138
|
+
summary: string;
|
|
139
|
+
/** Number of tools executed in this batch. */
|
|
140
|
+
toolCount: number;
|
|
141
|
+
/** Wall‑clock duration of the tool batch in ms. */
|
|
142
|
+
durationMs: number;
|
|
143
|
+
}
|
|
144
|
+
/** The stream completed successfully. */
|
|
145
|
+
interface DoneEvent {
|
|
146
|
+
type: "done";
|
|
147
|
+
/** Total tokens consumed by this request (input + output). */
|
|
148
|
+
totalTokens?: number;
|
|
149
|
+
}
|
|
150
|
+
//#endregion
|
|
151
|
+
//#region src/stream.d.ts
|
|
152
|
+
/**
|
|
153
|
+
* Stream\<T\> — pull‑based AsyncIterator backed by an internal queue.
|
|
154
|
+
*
|
|
155
|
+
* Producers call `enqueue()` / `done()` / `error()`.
|
|
156
|
+
* Consumers use `for await … of`.
|
|
157
|
+
*
|
|
158
|
+
* This is deliberately a class (not EventEmitter) so the consumer
|
|
159
|
+
* controls back‑pressure — when nobody is iterating, values stay in
|
|
160
|
+
* the queue until `maxQueueSize` is reached.
|
|
161
|
+
*/
|
|
162
|
+
/**
|
|
163
|
+
* A cold, single‑consumer async iterator.
|
|
164
|
+
*
|
|
165
|
+
* ```ts
|
|
166
|
+
* const stream = new Stream<string>();
|
|
167
|
+
* producer(stream);
|
|
168
|
+
* for await (const chunk of stream) {
|
|
169
|
+
* console.log(chunk);
|
|
170
|
+
* }
|
|
171
|
+
* ```
|
|
172
|
+
*/
|
|
173
|
+
declare class Stream<T> implements AsyncIterator<T>, AsyncIterable<T> {
|
|
174
|
+
private _queue;
|
|
175
|
+
private _resolvers;
|
|
176
|
+
private _done;
|
|
177
|
+
private _error;
|
|
178
|
+
private readonly _maxQueue;
|
|
179
|
+
constructor(maxQueueSize?: number);
|
|
180
|
+
/** Push a value into the stream. */
|
|
181
|
+
enqueue(value: T): void;
|
|
182
|
+
/** Signal that the stream has finished normally. */
|
|
183
|
+
done(): void;
|
|
184
|
+
/** Propagate an error to the consumer. */
|
|
185
|
+
error(err: Error): void;
|
|
186
|
+
[Symbol.asyncIterator](): AsyncIterator<T>;
|
|
187
|
+
next(): Promise<IteratorResult<T>>;
|
|
188
|
+
}
|
|
189
|
+
//#endregion
|
|
190
|
+
//#region src/retry.d.ts
|
|
191
|
+
/**
|
|
192
|
+
* withRetry — exponential backoff with jitter and Retry‑After respect.
|
|
193
|
+
*
|
|
194
|
+
* Used by every LLM provider for transient errors (429, 529, ECONNRESET, etc.).
|
|
195
|
+
*
|
|
196
|
+
* Algorithm:
|
|
197
|
+
* delay = min(baseMs * 2^(attempt-1), maxMs)
|
|
198
|
+
* jitter = delay * uniform(0.75, 1.25)
|
|
199
|
+
* final = min(jitter, maxMs)
|
|
200
|
+
*/
|
|
201
|
+
interface RetryOptions {
|
|
202
|
+
/** Base delay for the first retry (default 500ms). */
|
|
203
|
+
baseMs?: number;
|
|
204
|
+
/** Hard ceiling on delay (default 32s). */
|
|
205
|
+
maxMs?: number;
|
|
206
|
+
/** Maximum number of retries before giving up (default 10). */
|
|
207
|
+
maxRetries?: number;
|
|
208
|
+
/** Function that returns true if this error is retryable. */
|
|
209
|
+
isRetryable?: (err: Error) => boolean;
|
|
210
|
+
/**
|
|
211
|
+
* Whether this request is in the foreground (user-facing).
|
|
212
|
+
* Foreground requests retry on 529; background requests discard
|
|
213
|
+
* immediately to prevent cascade amplification. Defaults to true.
|
|
214
|
+
*/
|
|
215
|
+
isForeground?: boolean;
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Execute `fn` with exponential backoff.
|
|
219
|
+
*
|
|
220
|
+
* Only retries on transient errors. Non‑retryable errors are re‑thrown
|
|
221
|
+
* immediately.
|
|
222
|
+
*
|
|
223
|
+
* ```ts
|
|
224
|
+
* const result = await withRetry(() => fetchFromApi(), {
|
|
225
|
+
* baseMs: 500,
|
|
226
|
+
* maxMs: 32_000,
|
|
227
|
+
* });
|
|
228
|
+
* ```
|
|
229
|
+
*/
|
|
230
|
+
declare function withRetry<T>(fn: () => Promise<T>, opts?: RetryOptions): Promise<T>;
|
|
231
|
+
//#endregion
|
|
232
|
+
//#region src/capabilities.d.ts
|
|
233
|
+
/**
|
|
234
|
+
* Return the capability blob for `provider/modelId`.
|
|
235
|
+
* Returns `undefined` for unknown models — callers should fall back
|
|
236
|
+
* or throw a {@link import('@lynx/core').ConfigError}.
|
|
237
|
+
*/
|
|
238
|
+
declare function getCapability(providerId: string, modelId: string): ProviderCapability | undefined;
|
|
239
|
+
/**
|
|
240
|
+
* Return every known capability entry.
|
|
241
|
+
* Used by the model picker UI in the TUI layer.
|
|
242
|
+
*/
|
|
243
|
+
declare function listCapabilities(): Array<{
|
|
244
|
+
key: string;
|
|
245
|
+
} & ProviderCapability>;
|
|
246
|
+
//#endregion
|
|
247
|
+
//#region src/fallback.d.ts
|
|
248
|
+
/**
|
|
249
|
+
* Model/Provider fallback logic.
|
|
250
|
+
*
|
|
251
|
+
* When a provider returns a transient error (rate‑limit, overload) the
|
|
252
|
+
* fallback engine tries the next candidate in the configured chain.
|
|
253
|
+
* Permanent errors (auth) skip the provider entirely and move to the next.
|
|
254
|
+
*
|
|
255
|
+
* The primary use‑case is keeping the agent loop running when the
|
|
256
|
+
* preferred model is temporarily unavailable.
|
|
257
|
+
*/
|
|
258
|
+
/** A candidate provider+model pair in the fallback chain. */
|
|
259
|
+
interface ModelCandidate {
|
|
260
|
+
provider: string;
|
|
261
|
+
model: string;
|
|
262
|
+
}
|
|
263
|
+
/** Record of a single fallback attempt for diagnostics. */
|
|
264
|
+
interface FallbackAttempt {
|
|
265
|
+
provider: string;
|
|
266
|
+
model: string;
|
|
267
|
+
error: string;
|
|
268
|
+
code?: string;
|
|
269
|
+
/** HTTP status code if available. */
|
|
270
|
+
status?: number;
|
|
271
|
+
}
|
|
272
|
+
/** Result of a fallback run — which candidate succeeded and what was tried. */
|
|
273
|
+
interface FallbackResult<T> {
|
|
274
|
+
result: T;
|
|
275
|
+
provider: string;
|
|
276
|
+
model: string;
|
|
277
|
+
attempts: FallbackAttempt[];
|
|
278
|
+
}
|
|
279
|
+
/** Error thrown when every candidate in the chain has been exhausted. */
|
|
280
|
+
declare class FallbackExhaustedError extends Error {
|
|
281
|
+
readonly attempts: FallbackAttempt[];
|
|
282
|
+
constructor(attempts: FallbackAttempt[]);
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
285
|
+
* Run `fn` with automatic fallback across a chain of model candidates.
|
|
286
|
+
*
|
|
287
|
+
* `fn` is called with (provider, model) and should return a result.
|
|
288
|
+
* If `fn` throws, the error is classified — transient errors move to the
|
|
289
|
+
* next candidate, permanent errors skip the provider, and fatal errors
|
|
290
|
+
* (like user abort) are re‑thrown immediately.
|
|
291
|
+
*/
|
|
292
|
+
declare function runWithFallback<T>(candidates: ModelCandidate[], fn: (candidate: ModelCandidate) => Promise<T>, opts?: {
|
|
293
|
+
signal?: AbortSignal;
|
|
294
|
+
}): Promise<FallbackResult<T>>;
|
|
295
|
+
/**
|
|
296
|
+
* Build a fallback chain from a primary model and a list of fallback refs.
|
|
297
|
+
*
|
|
298
|
+
* Fallback refs use the format `"provider/model"` (e.g. `"openai/gpt-4o-mini"`).
|
|
299
|
+
* If the provider prefix is omitted the primary's provider is used.
|
|
300
|
+
*/
|
|
301
|
+
declare function buildCandidateChain(primaryProvider: string, primaryModel: string, fallbackRefs: string[]): ModelCandidate[];
|
|
302
|
+
//#endregion
|
|
303
|
+
//#region src/providers/deepseek.d.ts
|
|
304
|
+
interface DeepSeekConfig {
|
|
305
|
+
/** API key read from auth store. */
|
|
306
|
+
apiKey: string;
|
|
307
|
+
/** Base URL (defaults to https://api.deepseek.com). */
|
|
308
|
+
baseUrl?: string;
|
|
309
|
+
/** Request timeout in ms (default 120s). */
|
|
310
|
+
timeoutMs?: number;
|
|
311
|
+
}
|
|
312
|
+
/**
|
|
313
|
+
* Create a DeepSeek provider instance.
|
|
314
|
+
*
|
|
315
|
+
* Each call to `stream()` opens a fresh HTTP connection.
|
|
316
|
+
* The provider itself is stateless — the API key is the only configuration.
|
|
317
|
+
*/
|
|
318
|
+
declare function createDeepSeekProvider(config: DeepSeekConfig): LlmProvider;
|
|
319
|
+
//#endregion
|
|
320
|
+
//#region src/providers/openai.d.ts
|
|
321
|
+
interface OpenAiConfig {
|
|
322
|
+
apiKey: string;
|
|
323
|
+
baseUrl?: string;
|
|
324
|
+
timeoutMs?: number;
|
|
325
|
+
}
|
|
326
|
+
/**
|
|
327
|
+
* Create an OpenAI provider instance.
|
|
328
|
+
*
|
|
329
|
+
* Same SSE parsing logic as DeepSeek — both follow the same wire protocol.
|
|
330
|
+
* The only differences are the base URL, models, and capability metadata.
|
|
331
|
+
*/
|
|
332
|
+
declare function createOpenAiProvider(config: OpenAiConfig): LlmProvider;
|
|
333
|
+
//#endregion
|
|
334
|
+
//#region src/providers/anthropic.d.ts
|
|
335
|
+
interface AnthropicConfig {
|
|
336
|
+
/** API key from ANTHROPIC_API_KEY env var. */
|
|
337
|
+
apiKey: string;
|
|
338
|
+
/** Base URL (defaults to https://api.anthropic.com). */
|
|
339
|
+
baseUrl?: string;
|
|
340
|
+
/** Request timeout in ms (default 120s). */
|
|
341
|
+
timeoutMs?: number;
|
|
342
|
+
}
|
|
343
|
+
/**
|
|
344
|
+
* Create an Anthropic provider instance.
|
|
345
|
+
*
|
|
346
|
+
* Each call to `stream()` opens a fresh HTTP connection.
|
|
347
|
+
* The provider itself is stateless — the API key is the only configuration.
|
|
348
|
+
*/
|
|
349
|
+
declare function createAnthropicProvider(config: AnthropicConfig): LlmProvider;
|
|
350
|
+
//#endregion
|
|
351
|
+
export { type AnthropicConfig, type ChatMessage, type DeepSeekConfig, type DoneEvent, type ErrorEvent, type FallbackAttempt, FallbackExhaustedError, type FallbackResult, type LlmProvider, type ModelCandidate, type ModelInfo, type OpenAiConfig, type ProviderCapability, type ReasoningDeltaEvent, type RetryOptions, Stream, type StreamEvent, type TextDeltaEvent, type ToolResultEvent, type ToolUseDeltaEvent, type ToolUseEndEvent, type ToolUseStartEvent, buildCandidateChain, createAnthropicProvider, createDeepSeekProvider, createOpenAiProvider, getCapability, listCapabilities, runWithFallback, withRetry };
|
|
352
|
+
//# sourceMappingURL=index.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/types.ts","../src/stream.ts","../src/retry.ts","../src/capabilities.ts","../src/fallback.ts","../src/providers/deepseek.ts","../src/providers/openai.ts","../src/providers/anthropic.ts"],"mappings":";;;;;;AAoBuB;UAJN,WAAA;EAYS;EAVxB,IAAA;EAUwB;EARxB,OAAA,EAAS,YAAY;AAAA;;;;UAQN,SAAA;EAeA;EAbf,EAAA;;EAEA,KAAA;EAYA;EAVA,aAAA;EAYA;EAVA,SAAA;AAAA;;;;AAekB;UARH,kBAAA;EACf,aAAA;EACA,SAAA;EACA,iBAAA;EACA,iBAAA;EACA,eAAA;EACA,cAAA;EAyCkB;EAvClB,kBAAA;AAAA;;;;;;;UASe,WAAA;EAwBf;EAAA,SAtBS,EAAA;EAwBG;EArBZ,UAAA,IAAc,SAAA;EAsBZ;;;;EAhBF,aAAA,CAAc,OAAA,WAAkB,kBAAA;EAmBd;;AAAW;AAmB/B;;;;;;;;EAzBE,MAAA,CACE,OAAA,UACA,QAAA,EAAU,WAAA,IACV,YAAA,UACA,KAAA,aACA,MAAA,EAAQ,WAAA,GACP,cAAA,CAAe,WAAA;AAAA;;;;;;;;;;;;;;;KAmBR,WAAA,GACR,cAAA,GACA,mBAAA,GACA,iBAAA,GACA,iBAAA,GACA,eAAA,GACA,eAAA,GACA,cAAA,GACA,UAAA,GACA,SAAA;AAGJ;AAAA,UAAiB,cAAA;EACf,IAAA;EAD6B;EAG7B,KAAA;EAAA;EAEA,IAAA;AAAA;AAAI;AAAA,UAIW,mBAAA;EACf,IAAA;EACA,KAAA;EACA,IAAA;AAAA;;UAIe,iBAAA;EACf,IAAA;EALI;EAOJ,MAAA;EAHgC;EAKhC,IAAA;AAAA;;UAIe,iBAAA;EACf,IAAA;EACA,MAAA;EANI;EAQJ,IAAA;AAAA;;UAIe,eAAA;EACf,IAAA;EACA,MAAA;EANA;EAQA,KAAA,EAAO,MAAM;AAAA;AAJf;AAAA,UAQiB,eAAA;EACf,IAAA;EACA,SAAA;EACA,OAAA;EACA,OAAA;AAAA;;UAIe,UAAA;EACf,IAAA;EACA,IAAA;EACA,OAAA;AAAA;;UAIe,cAAA;EACf,IAAA;EAbA;EAeA,OAAA;EAdO;EAgBP,SAAA;EAZe;EAcf,UAAA;AAAA;;UAIe,SAAA;EACf,IAAA;EAhBA;EAkBA,WAAW;AAAA;;;;;;AA/Kb;;;;;;;;AAIuB;AAQvB;;;;;;;;;cCCa,MAAA,eAAqB,aAAA,CAAc,CAAA,GAAI,aAAA,CAAc,CAAA;EAAA,QACxD,MAAA;EAAA,QACA,UAAA;EAAA,QACA,KAAA;EAAA,QACA,MAAA;EAAA,iBACS,SAAA;cAEL,YAAA;EDUZ;ECHA,OAAA,CAAQ,KAAA,EAAO,CAAA;EDKf;ECWA,IAAA;EDRA;ECmBA,KAAA,CAAM,GAAA,EAAK,KAAA;EAAA,CAeV,MAAA,CAAO,aAAA,KAAkB,aAAA,CAAc,CAAA;EAIxC,IAAA,IAAQ,OAAA,CAAQ,cAAA,CAAe,CAAA;AAAA;;;;;;ADzEjC;;;;;;;UEKiB,YAAA;EFDM;EEGrB,MAAA;EFKwB;EEHxB,KAAA;EFGwB;EEDxB,UAAA;EFKA;EEHA,WAAA,IAAe,GAAA,EAAK,KAAK;EFOzB;;AAAS;AAOX;;EERE,YAAA;AAAA;;;;;;;;;AFgBkB;AASpB;;;;iBEsBsB,SAAA,IAAa,EAAA,QAAU,OAAA,CAAQ,CAAA,GAAI,IAAA,GAAM,YAAA,GAAoB,OAAA,CAAQ,CAAA;;;;;;AF9DpE;AAQvB;iBGyEgB,aAAA,CAAc,UAAA,UAAoB,OAAA,WAAkB,kBAAkB;;;;;iBAQtE,gBAAA,IAAoB,KAAK;EAAG,GAAA;AAAA,IAAgB,kBAAA;;;;;;AH7F5D;;;;;;;;UIAiB,cAAA;EACf,QAAA;EACA,KAAK;AAAA;;UAIU,eAAA;EACf,QAAA;EACA,KAAA;EACA,KAAA;EACA,IAAA;EJUS;EIRT,MAAA;AAAA;;UAIe,cAAA;EACf,MAAA,EAAQ,CAAA;EACR,QAAA;EACA,KAAA;EACA,QAAA,EAAU,eAAe;AAAA;;cAId,sBAAA,SAA+B,KAAA;EAAA,SACjC,QAAA,EAAU,eAAA;cAEP,QAAA,EAAU,eAAA;AAAA;;;;;;;;;iBAsCF,eAAA,IACpB,UAAA,EAAY,cAAA,IACZ,EAAA,GAAK,SAAA,EAAW,cAAA,KAAmB,OAAA,CAAQ,CAAA,GAC3C,IAAA;EAAS,MAAA,GAAS,WAAA;AAAA,IACjB,OAAA,CAAQ,cAAA,CAAe,CAAA;;;;;;;iBAqDV,mBAAA,CACd,eAAA,UACA,YAAA,UACA,YAAA,aACC,cAAc;;;UC9HA,cAAA;ELIN;EKFT,MAAA;ELEqB;EKArB,OAAA;ELQwB;EKNxB,SAAA;AAAA;;;;;;ALcS;iBK4IK,sBAAA,CAAuB,MAAA,EAAQ,cAAA,GAAiB,WAAW;;;UCjK1D,YAAA;EACf,MAAA;EACA,OAAA;EACA,SAAA;AAAA;ANUF;;;;;;AAAA,iBMoIgB,oBAAA,CAAqB,MAAA,EAAQ,YAAA,GAAe,WAAW;;;UChJtD,eAAA;EPIM;EOFrB,MAAA;EPUe;EORf,OAAA;;EAEA,SAAA;AAAA;;;;;APcS;AAOX;iBOwUgB,uBAAA,CAAwB,MAAA,EAAQ,eAAA,GAAkB,WAAW"}
|