@avasis-ai/synthcode 1.0.6 → 1.0.8

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.
@@ -439,6 +439,338 @@ var OllamaProvider = class {
439
439
  }
440
440
  };
441
441
 
442
+ // src/llm/cluster.ts
443
+ var DEFAULT_BASE = "http://localhost:11434/v1";
444
+ function defaultCluster(baseURL) {
445
+ const url = baseURL || DEFAULT_BASE;
446
+ return [
447
+ { model: "gemma4:31b", role: "planner", baseURL: url, temperature: 0.3 },
448
+ { model: "gemma4:26b", role: "worker", baseURL: url, temperature: 0.3 },
449
+ { model: "gemma4:26b", role: "worker", baseURL: url, temperature: 0.35 },
450
+ { model: "gemma4:26b", role: "reviewer", baseURL: url, temperature: 0.3 },
451
+ { model: "gemma4:e4b", role: "drafter", baseURL: url, temperature: 0.3 }
452
+ ];
453
+ }
454
+ function classifyComplexity(messages, hasTools) {
455
+ let totalTokens = 0;
456
+ let turns = messages.length;
457
+ let hasToolResults = false;
458
+ let hasCode = false;
459
+ let hasErrors = false;
460
+ for (const m of messages) {
461
+ const text = typeof m.content === "string" ? m.content : JSON.stringify(m.content);
462
+ totalTokens += text.length / 4;
463
+ if (m.role === "tool") hasToolResults = true;
464
+ if (text.includes("```") || text.includes("function ") || text.includes("class ")) hasCode = true;
465
+ if (text.includes("error") || text.includes("Error") || text.includes("FAIL")) hasErrors = true;
466
+ }
467
+ if (totalTokens > 1e4 || hasToolResults && hasErrors) return "complex";
468
+ if (totalTokens > 2e3 || hasTools || hasCode || hasErrors || turns > 4) return "medium";
469
+ return "simple";
470
+ }
471
+ function selectSlots(config, complexity) {
472
+ const planners = config.slots.filter((s) => s.role === "planner");
473
+ const workers = config.slots.filter((s) => s.role === "worker");
474
+ const reviewers = config.slots.filter((s) => s.role === "reviewer");
475
+ const drafters = config.slots.filter((s) => s.role === "drafter");
476
+ switch (complexity) {
477
+ case "complex":
478
+ return { planner: planners[0], workers, reviewers, drafters: drafters[0] };
479
+ case "medium":
480
+ return { planner: planners[0], workers: workers.slice(0, 1), reviewers: reviewers.slice(0, 1), drafters: drafters[0] };
481
+ case "simple":
482
+ default:
483
+ return { planner: planners[0], workers: workers.slice(0, 1), reviewers: reviewers.slice(0, 1), drafters: drafters[0] };
484
+ }
485
+ }
486
+ async function callModel(slot, request, baseURL, timeoutMs, extraOpts) {
487
+ const url = (slot.baseURL || baseURL) + "/chat/completions";
488
+ const messages = [];
489
+ if (request.systemPrompt) {
490
+ messages.push({ role: "system", content: request.systemPrompt });
491
+ }
492
+ for (const m of request.messages) {
493
+ if (m.role === "tool") {
494
+ messages.push({ role: "tool", tool_call_id: m.tool_use_id, content: m.content });
495
+ continue;
496
+ }
497
+ if (m.role === "assistant" && Array.isArray(m.content)) {
498
+ const textParts = m.content.filter((b) => b.type === "text");
499
+ const toolParts = m.content.filter((b) => b.type === "tool_use");
500
+ const msg = {};
501
+ if (textParts.length) msg.content = textParts.map((p) => p.text).join("");
502
+ if (toolParts.length) {
503
+ msg.tool_calls = toolParts.map((b) => {
504
+ const tb = b;
505
+ return { id: tb.id, type: "function", function: { name: tb.name, arguments: JSON.stringify(tb.input) } };
506
+ });
507
+ }
508
+ msg.role = "assistant";
509
+ messages.push(msg);
510
+ continue;
511
+ }
512
+ messages.push({ role: m.role, content: m.content });
513
+ }
514
+ const body = {
515
+ model: slot.model,
516
+ messages,
517
+ stream: false,
518
+ options: {
519
+ num_predict: request.maxOutputTokens || slot.maxTokens || 4096,
520
+ temperature: request.temperature ?? slot.temperature ?? 0.3,
521
+ top_p: 0.95,
522
+ top_k: 64
523
+ },
524
+ ...extraOpts
525
+ };
526
+ if (request.tools?.length) {
527
+ body.tools = request.tools.map((t) => ({
528
+ type: "function",
529
+ function: { name: t.name, description: t.description, parameters: t.input_schema }
530
+ }));
531
+ }
532
+ const start = Date.now();
533
+ let response;
534
+ try {
535
+ response = await fetch(url, {
536
+ method: "POST",
537
+ headers: { "Content-Type": "application/json" },
538
+ body: JSON.stringify(body),
539
+ signal: AbortSignal.timeout(timeoutMs)
540
+ });
541
+ } catch (err) {
542
+ if (err instanceof RetryableError) throw err;
543
+ throw new RetryableError(`Cluster slot ${slot.model} connection failed: ${err instanceof Error ? err.message : String(err)}`);
544
+ }
545
+ if (!response.ok) {
546
+ const text2 = await response.text();
547
+ if (response.status === 429 || response.status === 503 || response.status === 529) {
548
+ throw new RetryableError(`Cluster slot ${slot.model} rate limited: ${response.status}`);
549
+ }
550
+ throw new Error(`Cluster slot ${slot.model} error ${response.status}: ${text2.slice(0, 200)}`);
551
+ }
552
+ const data = await response.json();
553
+ const choice = data.choices?.[0];
554
+ if (!choice) throw new Error(`Cluster slot ${slot.model} returned no choices`);
555
+ let text = choice.message?.content || "";
556
+ text = text.replace(/<think[^>]*>[\s\S]*?<\/think>/gi, "").trim();
557
+ text = text.replace(/<thinking>[\s\S]*?<\/thinking>/gi, "").trim();
558
+ text = text.replace(/<channel>thought[\s\S]*?<channel|>/gi, "").trim();
559
+ text = text.replace(/\[Thinking[^\]]*\]/gi, "").trim();
560
+ return {
561
+ content: text,
562
+ usage: {
563
+ inputTokens: data.usage?.prompt_tokens ?? 0,
564
+ outputTokens: data.usage?.completion_tokens ?? 0,
565
+ cacheReadTokens: 0,
566
+ cacheWriteTokens: 0
567
+ },
568
+ stopReason: choice.finish_reason === "tool_calls" ? "tool_use" : "end_turn",
569
+ model: slot.model,
570
+ durationMs: Date.now() - start
571
+ };
572
+ }
573
+ function mergeUsage(...usages) {
574
+ return {
575
+ inputTokens: usages.reduce((s, u) => s + u.inputTokens, 0),
576
+ outputTokens: usages.reduce((s, u) => s + u.outputTokens, 0),
577
+ cacheReadTokens: usages.reduce((s, u) => s + (u.cacheReadTokens || 0), 0),
578
+ cacheWriteTokens: usages.reduce((s, u) => s + (u.cacheWriteTokens || 0), 0)
579
+ };
580
+ }
581
+ var ClusterProvider = class {
582
+ model;
583
+ config;
584
+ stats;
585
+ constructor(config) {
586
+ this.config = {
587
+ baseURL: DEFAULT_BASE,
588
+ timeoutMs: 18e4,
589
+ strategy: "auto",
590
+ draftCount: 1,
591
+ debateRounds: 1,
592
+ slots: defaultCluster(config?.baseURL),
593
+ ...config
594
+ };
595
+ const models = [...new Set(this.config.slots.map((s) => s.model))];
596
+ this.model = `cluster[${models.join(",")}]`;
597
+ this.stats = { calls: 0, tokensIn: 0, tokensOut: 0, byModel: {} };
598
+ for (const m of models) this.stats.byModel[m] = 0;
599
+ }
600
+ getStats() {
601
+ return { ...this.stats };
602
+ }
603
+ async chat(request) {
604
+ const strategy = this.config.strategy || "auto";
605
+ const complexity = strategy === "auto" ? classifyComplexity(request.messages, !!request.tools?.length) : "medium";
606
+ let result;
607
+ switch (strategy === "auto" ? complexity : "simple") {
608
+ case "simple":
609
+ result = await this.speculative(request);
610
+ break;
611
+ case "complex":
612
+ result = await this.debate(request);
613
+ break;
614
+ default:
615
+ result = await this.draftVerify(request);
616
+ break;
617
+ }
618
+ const content = [];
619
+ if (result.content) {
620
+ content.push({ type: "text", text: result.content });
621
+ }
622
+ return {
623
+ content,
624
+ stopReason: result.stopReason,
625
+ usage: result.usage
626
+ };
627
+ }
628
+ async speculative(request) {
629
+ const slots = selectSlots(this.config, "simple");
630
+ const drafter = slots.drafters;
631
+ const worker = slots.workers[0];
632
+ if (!drafter || !worker) {
633
+ return this.fallback(request);
634
+ }
635
+ const draft = await this.safeCall(drafter, request, { num_predict: request.maxOutputTokens || 4096 });
636
+ if (!draft || draft.content.length < 20) {
637
+ const fb = await this.safeCall(worker, request);
638
+ return fb || this.fallback(request);
639
+ }
640
+ const verifyMessages = [
641
+ ...request.messages.slice(0, -1),
642
+ { role: "user", content: `${typeof request.messages[request.messages.length - 1].content === "string" ? request.messages[request.messages.length - 1].content : ""}
643
+
644
+ Here is a draft response. Review it. If it is correct and complete, return exactly the same text. If it has errors, fix them. Return ONLY the final corrected text, nothing else.
645
+
646
+ DRAFT:
647
+ ${draft.content.slice(0, 8e3)}` }
648
+ ];
649
+ const verifyRequest = { ...request, messages: verifyMessages };
650
+ const verified = await this.safeCall(worker, verifyRequest);
651
+ if (!verified) return { ...draft, model: this.model };
652
+ const similarity = jaccardSimilarity(draft.content, verified.content);
653
+ if (similarity > 0.7) {
654
+ return { ...draft, usage: mergeUsage(draft.usage) };
655
+ }
656
+ return { ...verified, usage: mergeUsage(draft.usage, verified.usage) };
657
+ }
658
+ async draftVerify(request) {
659
+ const slots = selectSlots(this.config, "medium");
660
+ const worker = slots.workers[0];
661
+ const reviewer = slots.reviewers[0];
662
+ if (!worker) return this.fallback(request);
663
+ const primary = await this.safeCall(worker, request);
664
+ if (!primary) return this.fallback(request);
665
+ if (!reviewer || primary.content.length < 50) {
666
+ return primary;
667
+ }
668
+ const reviewMessages = [
669
+ { role: "user", content: `Review this response for correctness. Fix any errors. Return ONLY the corrected text.
670
+
671
+ ORIGINAL REQUEST:
672
+ ${typeof request.messages[request.messages.length - 1].content === "string" ? request.messages[request.messages.length - 1].content : ""}
673
+
674
+ RESPONSE TO REVIEW:
675
+ ${primary.content.slice(0, 6e3)}` }
676
+ ];
677
+ const reviewed = await this.safeCall(reviewer, { ...request, messages: reviewMessages, maxOutputTokens: request.maxOutputTokens });
678
+ if (!reviewed) return primary;
679
+ return { ...reviewed, usage: mergeUsage(primary.usage, reviewed.usage) };
680
+ }
681
+ async debate(request) {
682
+ const slots = selectSlots(this.config, "complex");
683
+ const workers = slots.workers;
684
+ const planner = slots.planner;
685
+ if (!workers.length) return this.fallback(request);
686
+ const roundRounds = this.config.debateRounds || 1;
687
+ let currentContent = "";
688
+ for (let round = 0; round < roundRounds; round++) {
689
+ const workerSlot = workers[round % workers.length];
690
+ const implMessages = round === 0 ? request.messages : [
691
+ ...request.messages.slice(0, -1),
692
+ {
693
+ role: "user",
694
+ content: `${typeof request.messages[request.messages.length - 1].content === "string" ? request.messages[request.messages.length - 1].content : ""}
695
+
696
+ PREVIOUS ATTEMPT (Round ${round}):
697
+ ${currentContent.slice(0, 4e3)}
698
+
699
+ Improve this. Fix any issues.`
700
+ }
701
+ ];
702
+ const impl = await this.safeCall(workerSlot, { ...request, messages: implMessages });
703
+ if (!impl) continue;
704
+ currentContent = impl.content;
705
+ }
706
+ if (!currentContent) return this.fallback(request);
707
+ if (planner && workers.length > 1) {
708
+ const candidates = [];
709
+ for (const w of workers) {
710
+ const c = await this.safeCall(w, request);
711
+ if (c && c.content.length > 30) candidates.push(c);
712
+ }
713
+ if (candidates.length > 1) {
714
+ const best = candidates.sort((a, b) => b.content.length - a.content.length)[0];
715
+ const arbMessages = [
716
+ {
717
+ role: "user",
718
+ content: `Select the best response or synthesize a better one. Return ONLY the final text.
719
+
720
+ TASK:
721
+ ${typeof request.messages[request.messages.length - 1].content === "string" ? request.messages[request.messages.length - 1].content : ""}
722
+
723
+ CANDIDATES:
724
+ ${candidates.map((c, i) => `--- Candidate ${i + 1} (${c.model}) ---
725
+ ${c.content.slice(0, 3e3)}`).join("\n\n")}`
726
+ }
727
+ ];
728
+ const arbitrated = await this.safeCall(planner, { ...request, messages: arbMessages, maxOutputTokens: request.maxOutputTokens });
729
+ if (arbitrated && arbitrated.content.length > 20) {
730
+ const allUsages = candidates.map((c) => c.usage).concat(arbitrated.usage);
731
+ return { ...arbitrated, usage: mergeUsage(...allUsages) };
732
+ }
733
+ }
734
+ }
735
+ return {
736
+ content: currentContent,
737
+ usage: { inputTokens: 0, outputTokens: 0 },
738
+ stopReason: "end_turn",
739
+ model: this.model,
740
+ durationMs: 0
741
+ };
742
+ }
743
+ async safeCall(slot, request, extraOpts) {
744
+ try {
745
+ const result = await callModel(slot, request, this.config.baseURL || DEFAULT_BASE, this.config.timeoutMs || 18e4, extraOpts);
746
+ this.stats.calls++;
747
+ this.stats.tokensIn += result.usage.inputTokens;
748
+ this.stats.tokensOut += result.usage.outputTokens;
749
+ this.stats.byModel[slot.model] = (this.stats.byModel[slot.model] || 0) + 1;
750
+ return result;
751
+ } catch (e) {
752
+ return null;
753
+ }
754
+ }
755
+ async fallback(request) {
756
+ const anySlot = this.config.slots[0];
757
+ const result = await callModel(anySlot, request, this.config.baseURL || DEFAULT_BASE, this.config.timeoutMs || 18e4);
758
+ this.stats.calls++;
759
+ this.stats.tokensIn += result.usage.inputTokens;
760
+ this.stats.tokensOut += result.usage.outputTokens;
761
+ this.stats.byModel[anySlot.model] = (this.stats.byModel[anySlot.model] || 0) + 1;
762
+ return result;
763
+ }
764
+ };
765
+ function jaccardSimilarity(a, b) {
766
+ const aWords = new Set(a.toLowerCase().split(/\s+/).filter((w) => w.length > 2));
767
+ const bWords = new Set(b.toLowerCase().split(/\s+/).filter((w) => w.length > 2));
768
+ if (aWords.size === 0 && bWords.size === 0) return 1;
769
+ const intersection = [...aWords].filter((w) => bWords.has(w)).length;
770
+ const union = (/* @__PURE__ */ new Set([...aWords, ...bWords])).size;
771
+ return union > 0 ? intersection / union : 0;
772
+ }
773
+
442
774
  // src/llm/index.ts
443
775
  function anthropic(config) {
444
776
  return new AnthropicProvider(config);
@@ -449,6 +781,9 @@ function openai(config) {
449
781
  function ollama(config) {
450
782
  return new OllamaProvider(config);
451
783
  }
784
+ function cluster(config) {
785
+ return new ClusterProvider(config);
786
+ }
452
787
  var CustomProvider = class {
453
788
  model;
454
789
  chatFn;
@@ -479,9 +814,11 @@ export {
479
814
  AnthropicProvider,
480
815
  OpenAIProvider,
481
816
  OllamaProvider,
817
+ ClusterProvider,
482
818
  anthropic,
483
819
  openai,
484
820
  ollama,
821
+ cluster,
485
822
  createProvider
486
823
  };
487
- //# sourceMappingURL=chunk-F34HO4RA.js.map
824
+ //# sourceMappingURL=chunk-KPJDLUMB.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/llm/provider.ts","../src/llm/anthropic.ts","../src/llm/openai.ts","../src/llm/ollama.ts","../src/llm/cluster.ts","../src/llm/index.ts"],"sourcesContent":["import type { ModelResponse, ContentBlock, TokenUsage, ProviderConfig } from '../types.js';\nimport type { APIToolDefinition } from '../tools/tool.js';\n\nexport interface Provider {\n readonly model: string;\n chat(request: ChatRequest): Promise<ModelResponse>;\n}\n\nexport interface ChatRequest {\n messages: ChatMessage[];\n tools?: APIToolDefinition[];\n systemPrompt?: string;\n maxOutputTokens?: number;\n temperature?: number;\n abortSignal?: AbortSignal;\n}\n\nexport interface ChatMessage {\n role: \"user\" | \"assistant\" | \"tool\";\n content: string | ContentBlock[];\n tool_use_id?: string;\n is_error?: boolean;\n}\n\nexport type { APIToolDefinition } from '../tools/tool.js';\n\nexport class RetryableError extends Error {\n readonly cause?: Error;\n\n constructor(message: string, cause?: Error) {\n super(message);\n this.name = 'RetryableError';\n this.cause = cause;\n }\n}\n\nexport abstract class BaseProvider implements Provider {\n readonly model: string;\n readonly maxOutputTokens?: number;\n readonly temperature?: number;\n\n constructor(config: ProviderConfig) {\n this.model = config.model;\n this.maxOutputTokens = config.maxOutputTokens;\n this.temperature = config.temperature;\n }\n\n abstract chat(request: ChatRequest): Promise<ModelResponse>;\n\n protected abstract mapMessages(messages: ChatMessage[]): unknown[];\n\n protected abstract mapTools(tools?: APIToolDefinition[]): unknown[] | undefined;\n\n protected abstract mapUsage(providerUsage: unknown): TokenUsage;\n\n protected mapStopReason(reason: string): ModelResponse[\"stopReason\"] {\n switch (reason) {\n case 'end_turn':\n case 'stop':\n return 'end_turn';\n case 'tool_use':\n case 'tool_calls':\n return 'tool_use';\n case 'max_tokens':\n case 'length':\n return 'max_tokens';\n case 'stop_sequence':\n return 'stop_sequence';\n default:\n return 'end_turn';\n }\n }\n}\n","import type { ModelResponse, ContentBlock, TextBlock, ToolUseBlock, ThinkingBlock, TokenUsage, ProviderConfig } from '../types.js';\nimport type { ChatRequest, ChatMessage, APIToolDefinition } from './provider.js';\nimport { BaseProvider, RetryableError } from './provider.js';\n\nexport interface AnthropicProviderConfig extends ProviderConfig {\n apiKey: string;\n baseURL?: string;\n dangerouslySkipAuth?: boolean;\n enableCaching?: boolean;\n}\n\nexport class AnthropicProvider extends BaseProvider {\n private readonly apiKey: string;\n private readonly baseURL?: string;\n private readonly dangerouslySkipAuth?: boolean;\n private readonly enableCaching: boolean;\n private client: any = null;\n\n constructor(config: AnthropicProviderConfig) {\n super(config);\n this.apiKey = config.apiKey;\n this.baseURL = config.baseURL;\n this.dangerouslySkipAuth = config.dangerouslySkipAuth;\n this.enableCaching = config.enableCaching ?? false;\n }\n\n async chat(request: ChatRequest): Promise<ModelResponse> {\n const AnthropicSDK = (await import('@anthropic-ai/sdk')).default;\n\n if (!this.client) {\n const opts: Record<string, unknown> = { apiKey: this.apiKey };\n if (this.baseURL) opts.baseURL = this.baseURL;\n if (this.dangerouslySkipAuth) opts.dangerouslySkipAuth = true;\n this.client = new AnthropicSDK(opts);\n }\n\n const messages = this.mapMessages(request.messages);\n const tools = this.mapTools(request.tools);\n const maxTokens = request.maxOutputTokens ?? this.maxOutputTokens ?? 4096;\n const temperature = request.temperature ?? this.temperature;\n\n const body: Record<string, unknown> = {\n model: this.model,\n max_tokens: maxTokens,\n messages,\n };\n\n if (request.systemPrompt) {\n if (this.enableCaching) {\n body.system = [\n { type: \"text\", text: request.systemPrompt, cache_control: { type: \"ephemeral\" } },\n ];\n } else {\n body.system = request.systemPrompt;\n }\n }\n if (tools) body.tools = tools;\n if (temperature !== undefined) body.temperature = temperature;\n\n const reqOptions: Record<string, unknown> = {};\n if (request.abortSignal) reqOptions.signal = request.abortSignal;\n\n let response: any;\n try {\n response = await this.client.messages.create(body, reqOptions);\n } catch (err: unknown) {\n const status = (err as any)?.status;\n const code = (err as any)?.code;\n const isNetwork =\n err instanceof TypeError ||\n (typeof code === 'string' &&\n ['ECONNRESET', 'ECONNREFUSED', 'ENOTFOUND', 'ETIMEDOUT'].includes(code));\n\n if (status === 429 || status === 529 || isNetwork) {\n throw new RetryableError(\n err instanceof Error ? err.message : String(err),\n err instanceof Error ? err : undefined,\n );\n }\n throw new Error(\n `Anthropic API error: ${err instanceof Error ? err.message : String(err)}`,\n err instanceof Error ? { cause: err } : undefined,\n );\n }\n\n const content: ContentBlock[] = [];\n for (const block of response.content) {\n if (block.type === 'text') {\n content.push({ type: 'text', text: block.text } as TextBlock);\n } else if (block.type === 'tool_use') {\n content.push({ type: 'tool_use', id: block.id, name: block.name, input: block.input } as ToolUseBlock);\n } else if (block.type === 'thinking') {\n content.push({ type: 'thinking', thinking: block.thinking } as ThinkingBlock);\n }\n }\n\n return {\n content,\n usage: this.mapUsage(response.usage),\n stopReason: this.mapStopReason(response.stop_reason),\n };\n }\n\n protected mapMessages(messages: ChatMessage[]): unknown[] {\n return messages.map((msg) => {\n if (msg.role === 'tool') {\n const textContent =\n typeof msg.content === 'string'\n ? msg.content\n : msg.content\n .filter((b): b is TextBlock => b.type === 'text')\n .map((b) => b.text)\n .join('\\n');\n\n return {\n role: 'user',\n content: [\n {\n type: 'tool_result',\n tool_use_id: msg.tool_use_id ?? '',\n content: textContent,\n ...(msg.is_error ? { is_error: true } : {}),\n },\n ],\n };\n }\n\n if (msg.role === 'assistant') {\n const content =\n typeof msg.content === 'string'\n ? [{ type: 'text', text: msg.content }]\n : msg.content.map((block) => this.mapOutgoingBlock(block));\n return { role: 'assistant', content };\n }\n\n if (typeof msg.content === 'string') {\n return { role: 'user', content: msg.content };\n }\n\n return {\n role: 'user',\n content: msg.content.map((block) => this.mapOutgoingBlock(block)),\n };\n });\n }\n\n protected mapTools(tools?: APIToolDefinition[]): unknown[] | undefined {\n if (!tools || tools.length === 0) return undefined;\n return tools.map((tool) => ({\n name: tool.name,\n description: tool.description,\n input_schema: tool.input_schema,\n type: 'tool',\n }));\n }\n\n protected mapUsage(providerUsage: unknown): TokenUsage {\n const u = providerUsage as {\n input_tokens: number;\n output_tokens: number;\n cache_read_input_tokens?: number;\n cache_creation_input_tokens?: number;\n };\n return {\n inputTokens: u.input_tokens,\n outputTokens: u.output_tokens,\n cacheReadTokens: u.cache_read_input_tokens,\n cacheWriteTokens: u.cache_creation_input_tokens,\n };\n }\n\n private mapOutgoingBlock(block: ContentBlock): Record<string, unknown> {\n switch (block.type) {\n case 'text':\n return { type: 'text', text: block.text };\n case 'tool_use':\n return { type: 'tool_use', id: block.id, name: block.name, input: block.input };\n case 'thinking':\n return { type: 'thinking', thinking: block.thinking };\n default:\n return { type: 'text', text: '' };\n }\n }\n}\n","import type { ModelResponse, ContentBlock, TextBlock, ToolUseBlock, TokenUsage, ProviderConfig } from '../types.js';\nimport type { ChatRequest, ChatMessage, APIToolDefinition } from './provider.js';\nimport { BaseProvider, RetryableError } from './provider.js';\n\nexport interface OpenAIProviderConfig extends ProviderConfig {\n apiKey: string;\n baseURL?: string;\n organization?: string;\n}\n\nexport class OpenAIProvider extends BaseProvider {\n private readonly apiKey: string;\n private readonly baseURL?: string;\n private readonly organization?: string;\n private client: any = null;\n\n constructor(config: OpenAIProviderConfig) {\n super(config);\n this.apiKey = config.apiKey;\n this.baseURL = config.baseURL;\n this.organization = config.organization;\n }\n\n async chat(request: ChatRequest): Promise<ModelResponse> {\n const OpenAI = (await import('openai')).default;\n\n if (!this.client) {\n const opts: Record<string, unknown> = { apiKey: this.apiKey };\n if (this.baseURL) opts.baseURL = this.baseURL;\n if (this.organization) opts.organization = this.organization;\n this.client = new OpenAI(opts);\n }\n\n const mappedMessages = this.mapMessages(request.messages);\n const messages: unknown[] = [];\n if (request.systemPrompt) {\n messages.push({ role: 'system', content: request.systemPrompt });\n }\n messages.push(...mappedMessages);\n\n const tools = this.mapTools(request.tools);\n const maxTokens = request.maxOutputTokens ?? this.maxOutputTokens;\n const temperature = request.temperature ?? this.temperature;\n\n const body: Record<string, unknown> = {\n model: this.model,\n messages,\n stream: false,\n };\n\n if (tools) body.tools = tools;\n if (maxTokens !== undefined) body.max_tokens = maxTokens;\n if (temperature !== undefined) body.temperature = temperature;\n\n const reqOptions: Record<string, unknown> = {};\n if (request.abortSignal) reqOptions.signal = request.abortSignal;\n\n let response: any;\n try {\n response = await this.client.chat.completions.create(body, reqOptions);\n } catch (err: unknown) {\n const status = (err as any)?.status;\n const code = (err as any)?.code;\n const isNetwork =\n err instanceof TypeError ||\n (typeof code === 'string' &&\n ['ECONNRESET', 'ECONNREFUSED', 'ENOTFOUND', 'ETIMEDOUT'].includes(code));\n\n if (status === 429 || isNetwork) {\n throw new RetryableError(\n err instanceof Error ? err.message : String(err),\n err instanceof Error ? err : undefined,\n );\n }\n throw new Error(\n `OpenAI API error: ${err instanceof Error ? err.message : String(err)}`,\n err instanceof Error ? { cause: err } : undefined,\n );\n }\n\n const choice = response.choices[0];\n const content: ContentBlock[] = [];\n\n if (choice.message.content) {\n content.push({ type: 'text', text: choice.message.content } as TextBlock);\n }\n\n if (choice.message.tool_calls) {\n for (const tc of choice.message.tool_calls) {\n let input: Record<string, unknown> = {};\n try {\n input = JSON.parse(tc.function.arguments);\n } catch {}\n content.push({\n type: 'tool_use',\n id: tc.id,\n name: tc.function.name,\n input,\n } as ToolUseBlock);\n }\n }\n\n return {\n content,\n usage: this.mapUsage(response.usage),\n stopReason: this.mapStopReason(choice.finish_reason),\n };\n }\n\n protected mapMessages(messages: ChatMessage[]): unknown[] {\n return messages.map((msg) => {\n if (msg.role === 'tool') {\n return {\n role: 'tool',\n tool_call_id: msg.tool_use_id ?? '',\n content:\n typeof msg.content === 'string'\n ? msg.content\n : msg.content\n .filter((b): b is TextBlock => b.type === 'text')\n .map((b) => b.text)\n .join('\\n'),\n };\n }\n\n if (msg.role === 'assistant') {\n if (typeof msg.content === 'string') {\n return { role: 'assistant', content: msg.content };\n }\n\n const textParts = msg.content\n .filter((b): b is TextBlock => b.type === 'text')\n .map((b) => b.text)\n .join('');\n const toolCalls = msg.content\n .filter((b): b is ToolUseBlock => b.type === 'tool_use')\n .map((b) => ({\n id: b.id,\n type: 'function' as const,\n function: { name: b.name, arguments: JSON.stringify(b.input) },\n }));\n\n return {\n role: 'assistant',\n content: textParts || null,\n ...(toolCalls.length > 0 ? { tool_calls: toolCalls } : {}),\n };\n }\n\n return {\n role: 'user',\n content:\n typeof msg.content === 'string'\n ? msg.content\n : msg.content\n .filter((b): b is TextBlock => b.type === 'text')\n .map((b) => b.text)\n .join('\\n'),\n };\n });\n }\n\n protected mapTools(tools?: APIToolDefinition[]): unknown[] | undefined {\n if (!tools || tools.length === 0) return undefined;\n return tools.map((tool) => ({\n type: 'function',\n function: {\n name: tool.name,\n description: tool.description,\n parameters: tool.input_schema,\n },\n }));\n }\n\n protected mapUsage(providerUsage: unknown): TokenUsage {\n const u = providerUsage as {\n prompt_tokens: number;\n completion_tokens: number;\n prompt_tokens_details?: { cached_tokens?: number };\n };\n return {\n inputTokens: u.prompt_tokens,\n outputTokens: u.completion_tokens,\n cacheReadTokens: u.prompt_tokens_details?.cached_tokens,\n };\n }\n}\n","import type { Provider, ChatRequest } from \"./provider.js\";\nimport { RetryableError } from \"./provider.js\";\nimport type { ModelResponse, ContentBlock } from \"../types.js\";\nimport type { APIToolDefinition } from \"../tools/tool.js\";\n\nexport interface OllamaProviderConfig {\n model: string;\n baseURL?: string;\n}\n\nexport class OllamaProvider implements Provider {\n readonly model: string;\n private readonly baseURL: string;\n\n constructor(config: OllamaProviderConfig) {\n this.model = config.model;\n this.baseURL = config.baseURL ?? \"http://localhost:11434/v1\";\n }\n\n async chat(request: ChatRequest): Promise<ModelResponse> {\n const messages: any[] = [];\n\n if (request.systemPrompt) {\n messages.push({ role: \"system\", content: request.systemPrompt });\n }\n\n for (const m of request.messages) {\n if (m.role === \"tool\") {\n messages.push({\n role: \"tool\" as const,\n tool_call_id: m.tool_use_id,\n content: m.content,\n });\n continue;\n }\n if (m.role === \"assistant\" && Array.isArray(m.content)) {\n const textParts = (m.content as ContentBlock[]).filter(b => b.type === \"text\");\n const toolParts = (m.content as ContentBlock[]).filter(b => b.type === \"tool_use\");\n\n const msg: any = {};\n if (textParts.length > 0) {\n msg.content = textParts.map(p => (p as { text: string }).text).join(\"\");\n }\n if (toolParts.length > 0) {\n msg.tool_calls = toolParts.map(b => {\n const tb = b as { type: \"tool_use\"; id: string; name: string; input: Record<string, unknown> };\n return {\n id: tb.id,\n type: \"function\",\n function: { name: tb.name, arguments: JSON.stringify(tb.input) },\n };\n });\n }\n msg.role = \"assistant\";\n messages.push(msg);\n continue;\n }\n messages.push({ role: m.role, content: m.content });\n }\n\n const body: any = {\n model: this.model,\n messages,\n stream: false,\n };\n\n if (request.maxOutputTokens) {\n body.max_tokens = request.maxOutputTokens;\n }\n\n if (request.tools?.length) {\n body.tools = request.tools.map(t => ({\n type: \"function\",\n function: {\n name: t.name,\n description: t.description,\n parameters: t.input_schema,\n },\n }));\n }\n\n let response;\n try {\n response = await fetch(`${this.baseURL}/chat/completions`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(body),\n signal: request.abortSignal,\n });\n } catch (err) {\n if (err instanceof RetryableError) throw err;\n throw new RetryableError(\n `Ollama connection failed: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n\n if (!response.ok) {\n const text = await response.text();\n if (response.status === 429 || response.status === 503 || response.status === 529) {\n throw new RetryableError(`Ollama API error ${response.status}: ${text.slice(0, 200)}`);\n }\n throw new Error(`Ollama API error ${response.status}: ${text.slice(0, 200)}`);\n }\n\n const data = await response.json();\n const choice = data.choices?.[0];\n if (!choice) {\n throw new Error(\"Ollama returned no choices\");\n }\n\n const content: any[] = [];\n let stopReason: ModelResponse[\"stopReason\"] = \"end_turn\";\n\n if (choice.message?.content) {\n let text = choice.message.content;\n text = text.replace(/<think[^>]*>[\\s\\S]*?<\\/think>/gi, \"\").trim();\n text = text.replace(/<thinking>[\\s\\S]*?<\\/thinking>/gi, \"\").trim();\n text = text.replace(/\\[Thinking[^\\]]*\\]/gi, \"\").trim();\n if (text.length > 0) {\n content.push({ type: \"text\" as const, text });\n }\n }\n\n if (choice.message?.tool_calls?.length) {\n stopReason = \"tool_use\";\n for (const tc of choice.message.tool_calls) {\n let input: Record<string, unknown>;\n try {\n input = JSON.parse(tc.function.arguments);\n } catch {\n input = {};\n }\n content.push({\n type: \"tool_use\" as const,\n id: tc.id,\n name: tc.function.name,\n input,\n });\n }\n }\n\n return {\n content,\n stopReason,\n usage: {\n inputTokens: data.usage?.prompt_tokens ?? 0,\n outputTokens: data.usage?.completion_tokens ?? 0,\n cacheReadTokens: 0,\n cacheWriteTokens: 0,\n },\n };\n }\n}\n","import type { Provider, ChatRequest, ChatMessage } from \"./provider.js\";\nimport { RetryableError } from \"./provider.js\";\nimport type { ModelResponse, ContentBlock, TokenUsage } from \"../types.js\";\n\nexport interface ClusterSlot {\n model: string;\n role: \"planner\" | \"worker\" | \"reviewer\" | \"drafter\";\n baseURL?: string;\n maxTokens?: number;\n temperature?: number;\n}\n\nexport interface ClusterConfig {\n slots: ClusterSlot[];\n baseURL?: string;\n timeoutMs?: number;\n strategy?: \"auto\" | \"draft-verify\" | \"debate\" | \"majority\" | \"single\";\n draftCount?: number;\n debateRounds?: number;\n}\n\ninterface CallResult {\n content: string;\n usage: TokenUsage;\n stopReason: ModelResponse[\"stopReason\"];\n model: string;\n durationMs: number;\n}\n\ntype Complexity = \"simple\" | \"medium\" | \"complex\";\n\nconst DEFAULT_BASE = \"http://localhost:11434/v1\";\n\nfunction defaultCluster(baseURL?: string): ClusterSlot[] {\n const url = baseURL || DEFAULT_BASE;\n return [\n { model: \"gemma4:31b\", role: \"planner\", baseURL: url, temperature: 0.3 },\n { model: \"gemma4:26b\", role: \"worker\", baseURL: url, temperature: 0.3 },\n { model: \"gemma4:26b\", role: \"worker\", baseURL: url, temperature: 0.35 },\n { model: \"gemma4:26b\", role: \"reviewer\", baseURL: url, temperature: 0.3 },\n { model: \"gemma4:e4b\", role: \"drafter\", baseURL: url, temperature: 0.3 },\n ];\n}\n\nfunction classifyComplexity(messages: ChatMessage[], hasTools: boolean): Complexity {\n let totalTokens = 0;\n let turns = messages.length;\n let hasToolResults = false;\n let hasCode = false;\n let hasErrors = false;\n\n for (const m of messages) {\n const text = typeof m.content === \"string\" ? m.content : JSON.stringify(m.content);\n totalTokens += text.length / 4;\n if (m.role === \"tool\") hasToolResults = true;\n if (text.includes(\"```\") || text.includes(\"function \") || text.includes(\"class \")) hasCode = true;\n if (text.includes(\"error\") || text.includes(\"Error\") || text.includes(\"FAIL\")) hasErrors = true;\n }\n\n if (totalTokens > 10000 || (hasToolResults && hasErrors)) return \"complex\";\n if (totalTokens > 2000 || hasTools || hasCode || hasErrors || turns > 4) return \"medium\";\n return \"simple\";\n}\n\nfunction selectSlots(config: ClusterConfig, complexity: Complexity): { planner?: ClusterSlot; workers: ClusterSlot[]; reviewers: ClusterSlot[]; drafters?: ClusterSlot } {\n const planners = config.slots.filter(s => s.role === \"planner\");\n const workers = config.slots.filter(s => s.role === \"worker\");\n const reviewers = config.slots.filter(s => s.role === \"reviewer\");\n const drafters = config.slots.filter(s => s.role === \"drafter\");\n\n switch (complexity) {\n case \"complex\":\n return { planner: planners[0], workers, reviewers, drafters: drafters[0] };\n case \"medium\":\n return { planner: planners[0], workers: workers.slice(0, 1), reviewers: reviewers.slice(0, 1), drafters: drafters[0] };\n case \"simple\":\n default:\n return { planner: planners[0], workers: workers.slice(0, 1), reviewers: reviewers.slice(0, 1), drafters: drafters[0] };\n }\n}\n\nasync function callModel(slot: ClusterSlot, request: ChatRequest, baseURL: string, timeoutMs: number, extraOpts?: Record<string, unknown>): Promise<CallResult> {\n const url = (slot.baseURL || baseURL) + \"/chat/completions\";\n const messages: any[] = [];\n\n if (request.systemPrompt) {\n messages.push({ role: \"system\", content: request.systemPrompt });\n }\n\n for (const m of request.messages) {\n if (m.role === \"tool\") {\n messages.push({ role: \"tool\", tool_call_id: m.tool_use_id, content: m.content });\n continue;\n }\n if (m.role === \"assistant\" && Array.isArray(m.content)) {\n const textParts = (m.content as ContentBlock[]).filter(b => b.type === \"text\");\n const toolParts = (m.content as ContentBlock[]).filter(b => b.type === \"tool_use\");\n const msg: any = {};\n if (textParts.length) msg.content = textParts.map(p => (p as { text: string }).text).join(\"\");\n if (toolParts.length) {\n msg.tool_calls = toolParts.map(b => {\n const tb = b as { type: \"tool_use\"; id: string; name: string; input: Record<string, unknown> };\n return { id: tb.id, type: \"function\", function: { name: tb.name, arguments: JSON.stringify(tb.input) } };\n });\n }\n msg.role = \"assistant\";\n messages.push(msg);\n continue;\n }\n messages.push({ role: m.role, content: m.content });\n }\n\n const body: any = {\n model: slot.model,\n messages,\n stream: false,\n options: {\n num_predict: request.maxOutputTokens || slot.maxTokens || 4096,\n temperature: request.temperature ?? slot.temperature ?? 0.3,\n top_p: 0.95,\n top_k: 64,\n },\n ...extraOpts,\n };\n\n if (request.tools?.length) {\n body.tools = request.tools.map(t => ({\n type: \"function\",\n function: { name: t.name, description: t.description, parameters: t.input_schema },\n }));\n }\n\n const start = Date.now();\n let response;\n try {\n response = await fetch(url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(body),\n signal: AbortSignal.timeout(timeoutMs),\n });\n } catch (err) {\n if (err instanceof RetryableError) throw err;\n throw new RetryableError(`Cluster slot ${slot.model} connection failed: ${err instanceof Error ? err.message : String(err)}`);\n }\n\n if (!response.ok) {\n const text = await response.text();\n if (response.status === 429 || response.status === 503 || response.status === 529) {\n throw new RetryableError(`Cluster slot ${slot.model} rate limited: ${response.status}`);\n }\n throw new Error(`Cluster slot ${slot.model} error ${response.status}: ${text.slice(0, 200)}`);\n }\n\n const data = await response.json();\n const choice = data.choices?.[0];\n if (!choice) throw new Error(`Cluster slot ${slot.model} returned no choices`);\n\n let text = choice.message?.content || \"\";\n text = text.replace(/<think[^>]*>[\\s\\S]*?<\\/think>/gi, \"\").trim();\n text = text.replace(/<thinking>[\\s\\S]*?<\\/thinking>/gi, \"\").trim();\n text = text.replace(/<channel>thought[\\s\\S]*?<channel|>/gi, \"\").trim();\n text = text.replace(/\\[Thinking[^\\]]*\\]/gi, \"\").trim();\n\n return {\n content: text,\n usage: {\n inputTokens: data.usage?.prompt_tokens ?? 0,\n outputTokens: data.usage?.completion_tokens ?? 0,\n cacheReadTokens: 0,\n cacheWriteTokens: 0,\n },\n stopReason: choice.finish_reason === \"tool_calls\" ? \"tool_use\" : \"end_turn\",\n model: slot.model,\n durationMs: Date.now() - start,\n };\n}\n\nfunction mergeUsage(...usages: TokenUsage[]): TokenUsage {\n return {\n inputTokens: usages.reduce((s, u) => s + u.inputTokens, 0),\n outputTokens: usages.reduce((s, u) => s + u.outputTokens, 0),\n cacheReadTokens: usages.reduce((s, u) => s + (u.cacheReadTokens || 0), 0),\n cacheWriteTokens: usages.reduce((s, u) => s + (u.cacheWriteTokens || 0), 0),\n };\n}\n\nexport class ClusterProvider implements Provider {\n readonly model: string;\n private config: ClusterConfig;\n private stats: { calls: number; tokensIn: number; tokensOut: number; byModel: Record<string, number> };\n\n constructor(config?: Partial<ClusterConfig>) {\n this.config = {\n baseURL: DEFAULT_BASE,\n timeoutMs: 180_000,\n strategy: \"auto\",\n draftCount: 1,\n debateRounds: 1,\n slots: defaultCluster(config?.baseURL),\n ...config,\n };\n const models = [...new Set(this.config.slots.map(s => s.model))];\n this.model = `cluster[${models.join(\",\")}]`;\n this.stats = { calls: 0, tokensIn: 0, tokensOut: 0, byModel: {} };\n for (const m of models) this.stats.byModel[m] = 0;\n }\n\n getStats() { return { ...this.stats }; }\n\n async chat(request: ChatRequest): Promise<ModelResponse> {\n const strategy = this.config.strategy || \"auto\";\n const complexity = strategy === \"auto\" ? classifyComplexity(request.messages, !!request.tools?.length) : \"medium\";\n\n let result: CallResult;\n switch (strategy === \"auto\" ? complexity : \"simple\") {\n case \"simple\":\n result = await this.speculative(request);\n break;\n case \"complex\":\n result = await this.debate(request);\n break;\n default:\n result = await this.draftVerify(request);\n break;\n }\n\n const content: ContentBlock[] = [];\n if (result.content) {\n content.push({ type: \"text\", text: result.content });\n }\n\n return {\n content,\n stopReason: result.stopReason,\n usage: result.usage,\n };\n }\n\n private async speculative(request: ChatRequest): Promise<CallResult> {\n const slots = selectSlots(this.config, \"simple\");\n const drafter = slots.drafters;\n const worker = slots.workers[0];\n\n if (!drafter || !worker) {\n return this.fallback(request);\n }\n\n const draft = await this.safeCall(drafter, request, { num_predict: (request.maxOutputTokens || 4096) });\n\n if (!draft || draft.content.length < 20) {\n const fb = await this.safeCall(worker, request);\n return fb || this.fallback(request);\n }\n\n const verifyMessages: ChatMessage[] = [\n ...request.messages.slice(0, -1),\n { role: \"user\" as const, content: `${typeof request.messages[request.messages.length - 1].content === \"string\" ? request.messages[request.messages.length - 1].content : \"\"}\\n\\nHere is a draft response. Review it. If it is correct and complete, return exactly the same text. If it has errors, fix them. Return ONLY the final corrected text, nothing else.\\n\\nDRAFT:\\n${draft.content.slice(0, 8000)}` },\n ];\n\n const verifyRequest: ChatRequest = { ...request, messages: verifyMessages };\n const verified = await this.safeCall(worker, verifyRequest);\n\n if (!verified) return { ...draft, model: this.model };\n\n const similarity = jaccardSimilarity(draft.content, verified.content);\n if (similarity > 0.7) {\n return { ...draft, usage: mergeUsage(draft.usage) };\n }\n\n return { ...verified, usage: mergeUsage(draft.usage, verified.usage) };\n }\n\n private async draftVerify(request: ChatRequest): Promise<CallResult> {\n const slots = selectSlots(this.config, \"medium\");\n const worker = slots.workers[0];\n const reviewer = slots.reviewers[0];\n\n if (!worker) return this.fallback(request);\n\n const primary = await this.safeCall(worker, request);\n if (!primary) return this.fallback(request);\n\n if (!reviewer || primary.content.length < 50) {\n return primary;\n }\n\n const reviewMessages: ChatMessage[] = [\n { role: \"user\" as const, content: `Review this response for correctness. Fix any errors. Return ONLY the corrected text.\\n\\nORIGINAL REQUEST:\\n${typeof request.messages[request.messages.length - 1].content === \"string\" ? request.messages[request.messages.length - 1].content : \"\"}\\n\\nRESPONSE TO REVIEW:\\n${primary.content.slice(0, 6000)}` },\n ];\n\n const reviewed = await this.safeCall(reviewer, { ...request, messages: reviewMessages, maxOutputTokens: request.maxOutputTokens });\n if (!reviewed) return primary;\n\n return { ...reviewed, usage: mergeUsage(primary.usage, reviewed.usage) };\n }\n\n private async debate(request: ChatRequest): Promise<CallResult> {\n const slots = selectSlots(this.config, \"complex\");\n const workers = slots.workers;\n const planner = slots.planner;\n\n if (!workers.length) return this.fallback(request);\n\n const roundRounds = this.config.debateRounds || 1;\n let currentContent = \"\";\n\n for (let round = 0; round < roundRounds; round++) {\n const workerSlot = workers[round % workers.length];\n const implMessages: ChatMessage[] = round === 0\n ? request.messages\n : [\n ...request.messages.slice(0, -1),\n {\n role: \"user\" as const,\n content: `${typeof request.messages[request.messages.length - 1].content === \"string\" ? request.messages[request.messages.length - 1].content : \"\"}\\n\\nPREVIOUS ATTEMPT (Round ${round}):\\n${currentContent.slice(0, 4000)}\\n\\nImprove this. Fix any issues.`,\n },\n ];\n\n const impl = await this.safeCall(workerSlot, { ...request, messages: implMessages });\n if (!impl) continue;\n currentContent = impl.content;\n }\n\n if (!currentContent) return this.fallback(request);\n\n if (planner && workers.length > 1) {\n const candidates: CallResult[] = [];\n for (const w of workers) {\n const c = await this.safeCall(w, request);\n if (c && c.content.length > 30) candidates.push(c);\n }\n\n if (candidates.length > 1) {\n const best = candidates.sort((a, b) => b.content.length - a.content.length)[0];\n const arbMessages: ChatMessage[] = [\n {\n role: \"user\" as const,\n content: `Select the best response or synthesize a better one. Return ONLY the final text.\\n\\nTASK:\\n${typeof request.messages[request.messages.length - 1].content === \"string\" ? request.messages[request.messages.length - 1].content : \"\"}\\n\\nCANDIDATES:\\n${candidates.map((c, i) => `--- Candidate ${i + 1} (${c.model}) ---\\n${c.content.slice(0, 3000)}`).join(\"\\n\\n\")}`,\n },\n ];\n\n const arbitrated = await this.safeCall(planner, { ...request, messages: arbMessages, maxOutputTokens: request.maxOutputTokens });\n if (arbitrated && arbitrated.content.length > 20) {\n const allUsages = candidates.map(c => c.usage).concat(arbitrated.usage);\n return { ...arbitrated, usage: mergeUsage(...allUsages) };\n }\n }\n }\n\n return {\n content: currentContent,\n usage: { inputTokens: 0, outputTokens: 0 },\n stopReason: \"end_turn\",\n model: this.model,\n durationMs: 0,\n };\n }\n\n private async safeCall(slot: ClusterSlot, request: ChatRequest, extraOpts?: Record<string, unknown>): Promise<CallResult | null> {\n try {\n const result = await callModel(slot, request, this.config.baseURL || DEFAULT_BASE, this.config.timeoutMs || 180_000, extraOpts);\n this.stats.calls++;\n this.stats.tokensIn += result.usage.inputTokens;\n this.stats.tokensOut += result.usage.outputTokens;\n this.stats.byModel[slot.model] = (this.stats.byModel[slot.model] || 0) + 1;\n return result;\n } catch (e) {\n return null;\n }\n }\n\n private async fallback(request: ChatRequest): Promise<CallResult> {\n const anySlot = this.config.slots[0];\n const result = await callModel(anySlot, request, this.config.baseURL || DEFAULT_BASE, this.config.timeoutMs || 180_000);\n this.stats.calls++;\n this.stats.tokensIn += result.usage.inputTokens;\n this.stats.tokensOut += result.usage.outputTokens;\n this.stats.byModel[anySlot.model] = (this.stats.byModel[anySlot.model] || 0) + 1;\n return result;\n }\n}\n\nfunction jaccardSimilarity(a: string, b: string): number {\n const aWords = new Set(a.toLowerCase().split(/\\s+/).filter(w => w.length > 2));\n const bWords = new Set(b.toLowerCase().split(/\\s+/).filter(w => w.length > 2));\n if (aWords.size === 0 && bWords.size === 0) return 1;\n const intersection = [...aWords].filter(w => bWords.has(w)).length;\n const union = new Set([...aWords, ...bWords]).size;\n return union > 0 ? intersection / union : 0;\n}\n","import type { ModelResponse } from '../types.js';\nimport { BaseProvider, RetryableError } from './provider.js';\nimport type { Provider, ChatRequest, ChatMessage, APIToolDefinition } from './provider.js';\nimport { AnthropicProvider } from './anthropic.js';\nimport type { AnthropicProviderConfig } from './anthropic.js';\nimport { OpenAIProvider } from './openai.js';\nimport type { OpenAIProviderConfig } from './openai.js';\nimport { OllamaProvider } from './ollama.js';\nimport type { OllamaProviderConfig } from './ollama.js';\nimport { ClusterProvider } from './cluster.js';\nimport type { ClusterConfig, ClusterSlot } from './cluster.js';\n\nexport { BaseProvider, RetryableError } from './provider.js';\nexport type { Provider, ChatRequest, ChatMessage, APIToolDefinition } from './provider.js';\nexport { AnthropicProvider } from './anthropic.js';\nexport type { AnthropicProviderConfig } from './anthropic.js';\nexport { OpenAIProvider } from './openai.js';\nexport type { OpenAIProviderConfig } from './openai.js';\nexport { OllamaProvider } from './ollama.js';\nexport type { OllamaProviderConfig } from './ollama.js';\nexport { ClusterProvider } from './cluster.js';\nexport type { ClusterConfig, ClusterSlot } from './cluster.js';\n\nexport function anthropic(config: AnthropicProviderConfig): AnthropicProvider {\n return new AnthropicProvider(config);\n}\n\nexport function openai(config: OpenAIProviderConfig): OpenAIProvider {\n return new OpenAIProvider(config);\n}\n\nexport function ollama(config: OllamaProviderConfig): OllamaProvider {\n return new OllamaProvider(config);\n}\n\nexport function cluster(config?: Partial<ClusterConfig>): ClusterProvider {\n return new ClusterProvider(config);\n}\n\nexport interface CustomProviderConfig {\n provider: 'custom';\n model: string;\n chat: (request: ChatRequest) => Promise<ModelResponse>;\n}\n\nclass CustomProvider implements Provider {\n readonly model: string;\n private readonly chatFn: (request: ChatRequest) => Promise<ModelResponse>;\n\n constructor(config: CustomProviderConfig) {\n this.model = config.model;\n this.chatFn = config.chat;\n }\n\n chat(request: ChatRequest): Promise<ModelResponse> {\n return this.chatFn(request);\n }\n}\n\nexport type OllamaProviderConfigWithProvider = OllamaProviderConfig & { provider: 'ollama' };\n\nexport function createProvider(\n config:\n | (AnthropicProviderConfig & { provider: 'anthropic' })\n | (OpenAIProviderConfig & { provider: 'openai' })\n | OllamaProviderConfigWithProvider\n | CustomProviderConfig,\n): Provider {\n switch (config.provider) {\n case 'anthropic':\n return new AnthropicProvider(config);\n case 'openai':\n return new OpenAIProvider(config);\n case 'ollama':\n return new OllamaProvider(config);\n case 'custom':\n return new CustomProvider(config);\n }\n}\n"],"mappings":";AA0BO,IAAM,iBAAN,cAA6B,MAAM;AAAA,EAC/B;AAAA,EAET,YAAY,SAAiB,OAAe;AAC1C,UAAM,OAAO;AACb,SAAK,OAAO;AACZ,SAAK,QAAQ;AAAA,EACf;AACF;AAEO,IAAe,eAAf,MAAgD;AAAA,EAC5C;AAAA,EACA;AAAA,EACA;AAAA,EAET,YAAY,QAAwB;AAClC,SAAK,QAAQ,OAAO;AACpB,SAAK,kBAAkB,OAAO;AAC9B,SAAK,cAAc,OAAO;AAAA,EAC5B;AAAA,EAUU,cAAc,QAA6C;AACnE,YAAQ,QAAQ;AAAA,MACd,KAAK;AAAA,MACL,KAAK;AACH,eAAO;AAAA,MACT,KAAK;AAAA,MACL,KAAK;AACH,eAAO;AAAA,MACT,KAAK;AAAA,MACL,KAAK;AACH,eAAO;AAAA,MACT,KAAK;AACH,eAAO;AAAA,MACT;AACE,eAAO;AAAA,IACX;AAAA,EACF;AACF;;;AC7DO,IAAM,oBAAN,cAAgC,aAAa;AAAA,EACjC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACT,SAAc;AAAA,EAEtB,YAAY,QAAiC;AAC3C,UAAM,MAAM;AACZ,SAAK,SAAS,OAAO;AACrB,SAAK,UAAU,OAAO;AACtB,SAAK,sBAAsB,OAAO;AAClC,SAAK,gBAAgB,OAAO,iBAAiB;AAAA,EAC/C;AAAA,EAEA,MAAM,KAAK,SAA8C;AACvD,UAAM,gBAAgB,MAAM,OAAO,mBAAmB,GAAG;AAEzD,QAAI,CAAC,KAAK,QAAQ;AAChB,YAAM,OAAgC,EAAE,QAAQ,KAAK,OAAO;AAC5D,UAAI,KAAK,QAAS,MAAK,UAAU,KAAK;AACtC,UAAI,KAAK,oBAAqB,MAAK,sBAAsB;AACzD,WAAK,SAAS,IAAI,aAAa,IAAI;AAAA,IACrC;AAEA,UAAM,WAAW,KAAK,YAAY,QAAQ,QAAQ;AAClD,UAAM,QAAQ,KAAK,SAAS,QAAQ,KAAK;AACzC,UAAM,YAAY,QAAQ,mBAAmB,KAAK,mBAAmB;AACrE,UAAM,cAAc,QAAQ,eAAe,KAAK;AAEhD,UAAM,OAAgC;AAAA,MACpC,OAAO,KAAK;AAAA,MACZ,YAAY;AAAA,MACZ;AAAA,IACF;AAEA,QAAI,QAAQ,cAAc;AACxB,UAAI,KAAK,eAAe;AACtB,aAAK,SAAS;AAAA,UACZ,EAAE,MAAM,QAAQ,MAAM,QAAQ,cAAc,eAAe,EAAE,MAAM,YAAY,EAAE;AAAA,QACnF;AAAA,MACF,OAAO;AACL,aAAK,SAAS,QAAQ;AAAA,MACxB;AAAA,IACF;AACA,QAAI,MAAO,MAAK,QAAQ;AACxB,QAAI,gBAAgB,OAAW,MAAK,cAAc;AAElD,UAAM,aAAsC,CAAC;AAC7C,QAAI,QAAQ,YAAa,YAAW,SAAS,QAAQ;AAErD,QAAI;AACJ,QAAI;AACF,iBAAW,MAAM,KAAK,OAAO,SAAS,OAAO,MAAM,UAAU;AAAA,IAC/D,SAAS,KAAc;AACrB,YAAM,SAAU,KAAa;AAC7B,YAAM,OAAQ,KAAa;AAC3B,YAAM,YACJ,eAAe,aACd,OAAO,SAAS,YACf,CAAC,cAAc,gBAAgB,aAAa,WAAW,EAAE,SAAS,IAAI;AAE1E,UAAI,WAAW,OAAO,WAAW,OAAO,WAAW;AACjD,cAAM,IAAI;AAAA,UACR,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAAA,UAC/C,eAAe,QAAQ,MAAM;AAAA,QAC/B;AAAA,MACF;AACA,YAAM,IAAI;AAAA,QACR,wBAAwB,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,QACxE,eAAe,QAAQ,EAAE,OAAO,IAAI,IAAI;AAAA,MAC1C;AAAA,IACF;AAEA,UAAM,UAA0B,CAAC;AACjC,eAAW,SAAS,SAAS,SAAS;AACpC,UAAI,MAAM,SAAS,QAAQ;AACzB,gBAAQ,KAAK,EAAE,MAAM,QAAQ,MAAM,MAAM,KAAK,CAAc;AAAA,MAC9D,WAAW,MAAM,SAAS,YAAY;AACpC,gBAAQ,KAAK,EAAE,MAAM,YAAY,IAAI,MAAM,IAAI,MAAM,MAAM,MAAM,OAAO,MAAM,MAAM,CAAiB;AAAA,MACvG,WAAW,MAAM,SAAS,YAAY;AACpC,gBAAQ,KAAK,EAAE,MAAM,YAAY,UAAU,MAAM,SAAS,CAAkB;AAAA,MAC9E;AAAA,IACF;AAEA,WAAO;AAAA,MACL;AAAA,MACA,OAAO,KAAK,SAAS,SAAS,KAAK;AAAA,MACnC,YAAY,KAAK,cAAc,SAAS,WAAW;AAAA,IACrD;AAAA,EACF;AAAA,EAEU,YAAY,UAAoC;AACxD,WAAO,SAAS,IAAI,CAAC,QAAQ;AAC3B,UAAI,IAAI,SAAS,QAAQ;AACvB,cAAM,cACJ,OAAO,IAAI,YAAY,WACnB,IAAI,UACJ,IAAI,QACD,OAAO,CAAC,MAAsB,EAAE,SAAS,MAAM,EAC/C,IAAI,CAAC,MAAM,EAAE,IAAI,EACjB,KAAK,IAAI;AAElB,eAAO;AAAA,UACL,MAAM;AAAA,UACN,SAAS;AAAA,YACP;AAAA,cACE,MAAM;AAAA,cACN,aAAa,IAAI,eAAe;AAAA,cAChC,SAAS;AAAA,cACT,GAAI,IAAI,WAAW,EAAE,UAAU,KAAK,IAAI,CAAC;AAAA,YAC3C;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAEA,UAAI,IAAI,SAAS,aAAa;AAC5B,cAAM,UACJ,OAAO,IAAI,YAAY,WACnB,CAAC,EAAE,MAAM,QAAQ,MAAM,IAAI,QAAQ,CAAC,IACpC,IAAI,QAAQ,IAAI,CAAC,UAAU,KAAK,iBAAiB,KAAK,CAAC;AAC7D,eAAO,EAAE,MAAM,aAAa,QAAQ;AAAA,MACtC;AAEA,UAAI,OAAO,IAAI,YAAY,UAAU;AACnC,eAAO,EAAE,MAAM,QAAQ,SAAS,IAAI,QAAQ;AAAA,MAC9C;AAEA,aAAO;AAAA,QACL,MAAM;AAAA,QACN,SAAS,IAAI,QAAQ,IAAI,CAAC,UAAU,KAAK,iBAAiB,KAAK,CAAC;AAAA,MAClE;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEU,SAAS,OAAoD;AACrE,QAAI,CAAC,SAAS,MAAM,WAAW,EAAG,QAAO;AACzC,WAAO,MAAM,IAAI,CAAC,UAAU;AAAA,MAC1B,MAAM,KAAK;AAAA,MACX,aAAa,KAAK;AAAA,MAClB,cAAc,KAAK;AAAA,MACnB,MAAM;AAAA,IACR,EAAE;AAAA,EACJ;AAAA,EAEU,SAAS,eAAoC;AACrD,UAAM,IAAI;AAMV,WAAO;AAAA,MACL,aAAa,EAAE;AAAA,MACf,cAAc,EAAE;AAAA,MAChB,iBAAiB,EAAE;AAAA,MACnB,kBAAkB,EAAE;AAAA,IACtB;AAAA,EACF;AAAA,EAEQ,iBAAiB,OAA8C;AACrE,YAAQ,MAAM,MAAM;AAAA,MAClB,KAAK;AACH,eAAO,EAAE,MAAM,QAAQ,MAAM,MAAM,KAAK;AAAA,MAC1C,KAAK;AACH,eAAO,EAAE,MAAM,YAAY,IAAI,MAAM,IAAI,MAAM,MAAM,MAAM,OAAO,MAAM,MAAM;AAAA,MAChF,KAAK;AACH,eAAO,EAAE,MAAM,YAAY,UAAU,MAAM,SAAS;AAAA,MACtD;AACE,eAAO,EAAE,MAAM,QAAQ,MAAM,GAAG;AAAA,IACpC;AAAA,EACF;AACF;;;AC7KO,IAAM,iBAAN,cAA6B,aAAa;AAAA,EAC9B;AAAA,EACA;AAAA,EACA;AAAA,EACT,SAAc;AAAA,EAEtB,YAAY,QAA8B;AACxC,UAAM,MAAM;AACZ,SAAK,SAAS,OAAO;AACrB,SAAK,UAAU,OAAO;AACtB,SAAK,eAAe,OAAO;AAAA,EAC7B;AAAA,EAEA,MAAM,KAAK,SAA8C;AACvD,UAAM,UAAU,MAAM,OAAO,QAAQ,GAAG;AAExC,QAAI,CAAC,KAAK,QAAQ;AAChB,YAAM,OAAgC,EAAE,QAAQ,KAAK,OAAO;AAC5D,UAAI,KAAK,QAAS,MAAK,UAAU,KAAK;AACtC,UAAI,KAAK,aAAc,MAAK,eAAe,KAAK;AAChD,WAAK,SAAS,IAAI,OAAO,IAAI;AAAA,IAC/B;AAEA,UAAM,iBAAiB,KAAK,YAAY,QAAQ,QAAQ;AACxD,UAAM,WAAsB,CAAC;AAC7B,QAAI,QAAQ,cAAc;AACxB,eAAS,KAAK,EAAE,MAAM,UAAU,SAAS,QAAQ,aAAa,CAAC;AAAA,IACjE;AACA,aAAS,KAAK,GAAG,cAAc;AAE/B,UAAM,QAAQ,KAAK,SAAS,QAAQ,KAAK;AACzC,UAAM,YAAY,QAAQ,mBAAmB,KAAK;AAClD,UAAM,cAAc,QAAQ,eAAe,KAAK;AAEhD,UAAM,OAAgC;AAAA,MACpC,OAAO,KAAK;AAAA,MACZ;AAAA,MACA,QAAQ;AAAA,IACV;AAEA,QAAI,MAAO,MAAK,QAAQ;AACxB,QAAI,cAAc,OAAW,MAAK,aAAa;AAC/C,QAAI,gBAAgB,OAAW,MAAK,cAAc;AAElD,UAAM,aAAsC,CAAC;AAC7C,QAAI,QAAQ,YAAa,YAAW,SAAS,QAAQ;AAErD,QAAI;AACJ,QAAI;AACF,iBAAW,MAAM,KAAK,OAAO,KAAK,YAAY,OAAO,MAAM,UAAU;AAAA,IACvE,SAAS,KAAc;AACrB,YAAM,SAAU,KAAa;AAC7B,YAAM,OAAQ,KAAa;AAC3B,YAAM,YACJ,eAAe,aACd,OAAO,SAAS,YACf,CAAC,cAAc,gBAAgB,aAAa,WAAW,EAAE,SAAS,IAAI;AAE1E,UAAI,WAAW,OAAO,WAAW;AAC/B,cAAM,IAAI;AAAA,UACR,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAAA,UAC/C,eAAe,QAAQ,MAAM;AAAA,QAC/B;AAAA,MACF;AACA,YAAM,IAAI;AAAA,QACR,qBAAqB,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,QACrE,eAAe,QAAQ,EAAE,OAAO,IAAI,IAAI;AAAA,MAC1C;AAAA,IACF;AAEA,UAAM,SAAS,SAAS,QAAQ,CAAC;AACjC,UAAM,UAA0B,CAAC;AAEjC,QAAI,OAAO,QAAQ,SAAS;AAC1B,cAAQ,KAAK,EAAE,MAAM,QAAQ,MAAM,OAAO,QAAQ,QAAQ,CAAc;AAAA,IAC1E;AAEA,QAAI,OAAO,QAAQ,YAAY;AAC7B,iBAAW,MAAM,OAAO,QAAQ,YAAY;AAC1C,YAAI,QAAiC,CAAC;AACtC,YAAI;AACF,kBAAQ,KAAK,MAAM,GAAG,SAAS,SAAS;AAAA,QAC1C,QAAQ;AAAA,QAAC;AACT,gBAAQ,KAAK;AAAA,UACX,MAAM;AAAA,UACN,IAAI,GAAG;AAAA,UACP,MAAM,GAAG,SAAS;AAAA,UAClB;AAAA,QACF,CAAiB;AAAA,MACnB;AAAA,IACF;AAEA,WAAO;AAAA,MACL;AAAA,MACA,OAAO,KAAK,SAAS,SAAS,KAAK;AAAA,MACnC,YAAY,KAAK,cAAc,OAAO,aAAa;AAAA,IACrD;AAAA,EACF;AAAA,EAEU,YAAY,UAAoC;AACxD,WAAO,SAAS,IAAI,CAAC,QAAQ;AAC3B,UAAI,IAAI,SAAS,QAAQ;AACvB,eAAO;AAAA,UACL,MAAM;AAAA,UACN,cAAc,IAAI,eAAe;AAAA,UACjC,SACE,OAAO,IAAI,YAAY,WACnB,IAAI,UACJ,IAAI,QACD,OAAO,CAAC,MAAsB,EAAE,SAAS,MAAM,EAC/C,IAAI,CAAC,MAAM,EAAE,IAAI,EACjB,KAAK,IAAI;AAAA,QACpB;AAAA,MACF;AAEA,UAAI,IAAI,SAAS,aAAa;AAC5B,YAAI,OAAO,IAAI,YAAY,UAAU;AACnC,iBAAO,EAAE,MAAM,aAAa,SAAS,IAAI,QAAQ;AAAA,QACnD;AAEA,cAAM,YAAY,IAAI,QACnB,OAAO,CAAC,MAAsB,EAAE,SAAS,MAAM,EAC/C,IAAI,CAAC,MAAM,EAAE,IAAI,EACjB,KAAK,EAAE;AACV,cAAM,YAAY,IAAI,QACnB,OAAO,CAAC,MAAyB,EAAE,SAAS,UAAU,EACtD,IAAI,CAAC,OAAO;AAAA,UACX,IAAI,EAAE;AAAA,UACN,MAAM;AAAA,UACN,UAAU,EAAE,MAAM,EAAE,MAAM,WAAW,KAAK,UAAU,EAAE,KAAK,EAAE;AAAA,QAC/D,EAAE;AAEJ,eAAO;AAAA,UACL,MAAM;AAAA,UACN,SAAS,aAAa;AAAA,UACtB,GAAI,UAAU,SAAS,IAAI,EAAE,YAAY,UAAU,IAAI,CAAC;AAAA,QAC1D;AAAA,MACF;AAEA,aAAO;AAAA,QACL,MAAM;AAAA,QACN,SACE,OAAO,IAAI,YAAY,WACnB,IAAI,UACJ,IAAI,QACD,OAAO,CAAC,MAAsB,EAAE,SAAS,MAAM,EAC/C,IAAI,CAAC,MAAM,EAAE,IAAI,EACjB,KAAK,IAAI;AAAA,MACpB;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEU,SAAS,OAAoD;AACrE,QAAI,CAAC,SAAS,MAAM,WAAW,EAAG,QAAO;AACzC,WAAO,MAAM,IAAI,CAAC,UAAU;AAAA,MAC1B,MAAM;AAAA,MACN,UAAU;AAAA,QACR,MAAM,KAAK;AAAA,QACX,aAAa,KAAK;AAAA,QAClB,YAAY,KAAK;AAAA,MACnB;AAAA,IACF,EAAE;AAAA,EACJ;AAAA,EAEU,SAAS,eAAoC;AACrD,UAAM,IAAI;AAKV,WAAO;AAAA,MACL,aAAa,EAAE;AAAA,MACf,cAAc,EAAE;AAAA,MAChB,iBAAiB,EAAE,uBAAuB;AAAA,IAC5C;AAAA,EACF;AACF;;;AChLO,IAAM,iBAAN,MAAyC;AAAA,EACrC;AAAA,EACQ;AAAA,EAEjB,YAAY,QAA8B;AACxC,SAAK,QAAQ,OAAO;AACpB,SAAK,UAAU,OAAO,WAAW;AAAA,EACnC;AAAA,EAEA,MAAM,KAAK,SAA8C;AACvD,UAAM,WAAkB,CAAC;AAEzB,QAAI,QAAQ,cAAc;AACxB,eAAS,KAAK,EAAE,MAAM,UAAU,SAAS,QAAQ,aAAa,CAAC;AAAA,IACjE;AAEA,eAAW,KAAK,QAAQ,UAAU;AAChC,UAAI,EAAE,SAAS,QAAQ;AACrB,iBAAS,KAAK;AAAA,UACZ,MAAM;AAAA,UACN,cAAc,EAAE;AAAA,UAChB,SAAS,EAAE;AAAA,QACb,CAAC;AACD;AAAA,MACF;AACA,UAAI,EAAE,SAAS,eAAe,MAAM,QAAQ,EAAE,OAAO,GAAG;AACtD,cAAM,YAAa,EAAE,QAA2B,OAAO,OAAK,EAAE,SAAS,MAAM;AAC7E,cAAM,YAAa,EAAE,QAA2B,OAAO,OAAK,EAAE,SAAS,UAAU;AAEjF,cAAM,MAAW,CAAC;AAClB,YAAI,UAAU,SAAS,GAAG;AACxB,cAAI,UAAU,UAAU,IAAI,OAAM,EAAuB,IAAI,EAAE,KAAK,EAAE;AAAA,QACxE;AACA,YAAI,UAAU,SAAS,GAAG;AACxB,cAAI,aAAa,UAAU,IAAI,OAAK;AAClC,kBAAM,KAAK;AACX,mBAAO;AAAA,cACL,IAAI,GAAG;AAAA,cACP,MAAM;AAAA,cACN,UAAU,EAAE,MAAM,GAAG,MAAM,WAAW,KAAK,UAAU,GAAG,KAAK,EAAE;AAAA,YACjE;AAAA,UACF,CAAC;AAAA,QACH;AACA,YAAI,OAAO;AACX,iBAAS,KAAK,GAAG;AACjB;AAAA,MACF;AACA,eAAS,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,EAAE,QAAQ,CAAC;AAAA,IACpD;AAEA,UAAM,OAAY;AAAA,MAChB,OAAO,KAAK;AAAA,MACZ;AAAA,MACA,QAAQ;AAAA,IACV;AAEA,QAAI,QAAQ,iBAAiB;AAC3B,WAAK,aAAa,QAAQ;AAAA,IAC5B;AAEA,QAAI,QAAQ,OAAO,QAAQ;AACzB,WAAK,QAAQ,QAAQ,MAAM,IAAI,QAAM;AAAA,QACnC,MAAM;AAAA,QACN,UAAU;AAAA,UACR,MAAM,EAAE;AAAA,UACR,aAAa,EAAE;AAAA,UACf,YAAY,EAAE;AAAA,QAChB;AAAA,MACF,EAAE;AAAA,IACJ;AAEA,QAAI;AACJ,QAAI;AACF,iBAAW,MAAM,MAAM,GAAG,KAAK,OAAO,qBAAqB;AAAA,QACzD,QAAQ;AAAA,QACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,QAC9C,MAAM,KAAK,UAAU,IAAI;AAAA,QACzB,QAAQ,QAAQ;AAAA,MAClB,CAAC;AAAA,IACH,SAAS,KAAK;AACZ,UAAI,eAAe,eAAgB,OAAM;AACzC,YAAM,IAAI;AAAA,QACR,6BAA6B,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,MAC/E;AAAA,IACF;AAEA,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,OAAO,MAAM,SAAS,KAAK;AACjC,UAAI,SAAS,WAAW,OAAO,SAAS,WAAW,OAAO,SAAS,WAAW,KAAK;AACjF,cAAM,IAAI,eAAe,oBAAoB,SAAS,MAAM,KAAK,KAAK,MAAM,GAAG,GAAG,CAAC,EAAE;AAAA,MACvF;AACA,YAAM,IAAI,MAAM,oBAAoB,SAAS,MAAM,KAAK,KAAK,MAAM,GAAG,GAAG,CAAC,EAAE;AAAA,IAC9E;AAEA,UAAM,OAAO,MAAM,SAAS,KAAK;AACjC,UAAM,SAAS,KAAK,UAAU,CAAC;AAC/B,QAAI,CAAC,QAAQ;AACX,YAAM,IAAI,MAAM,4BAA4B;AAAA,IAC9C;AAEA,UAAM,UAAiB,CAAC;AACxB,QAAI,aAA0C;AAE9C,QAAI,OAAO,SAAS,SAAS;AAC3B,UAAI,OAAO,OAAO,QAAQ;AAC1B,aAAO,KAAK,QAAQ,mCAAmC,EAAE,EAAE,KAAK;AAChE,aAAO,KAAK,QAAQ,oCAAoC,EAAE,EAAE,KAAK;AACjE,aAAO,KAAK,QAAQ,wBAAwB,EAAE,EAAE,KAAK;AACrD,UAAI,KAAK,SAAS,GAAG;AACnB,gBAAQ,KAAK,EAAE,MAAM,QAAiB,KAAK,CAAC;AAAA,MAC9C;AAAA,IACF;AAEA,QAAI,OAAO,SAAS,YAAY,QAAQ;AACtC,mBAAa;AACb,iBAAW,MAAM,OAAO,QAAQ,YAAY;AAC1C,YAAI;AACJ,YAAI;AACF,kBAAQ,KAAK,MAAM,GAAG,SAAS,SAAS;AAAA,QAC1C,QAAQ;AACN,kBAAQ,CAAC;AAAA,QACX;AACA,gBAAQ,KAAK;AAAA,UACX,MAAM;AAAA,UACN,IAAI,GAAG;AAAA,UACP,MAAM,GAAG,SAAS;AAAA,UAClB;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF;AAEA,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA,OAAO;AAAA,QACL,aAAa,KAAK,OAAO,iBAAiB;AAAA,QAC1C,cAAc,KAAK,OAAO,qBAAqB;AAAA,QAC/C,iBAAiB;AAAA,QACjB,kBAAkB;AAAA,MACpB;AAAA,IACF;AAAA,EACF;AACF;;;ACzHA,IAAM,eAAe;AAErB,SAAS,eAAe,SAAiC;AACvD,QAAM,MAAM,WAAW;AACvB,SAAO;AAAA,IACL,EAAE,OAAO,cAAc,MAAM,WAAW,SAAS,KAAK,aAAa,IAAI;AAAA,IACvE,EAAE,OAAO,cAAc,MAAM,UAAU,SAAS,KAAK,aAAa,IAAI;AAAA,IACtE,EAAE,OAAO,cAAc,MAAM,UAAU,SAAS,KAAK,aAAa,KAAK;AAAA,IACvE,EAAE,OAAO,cAAc,MAAM,YAAY,SAAS,KAAK,aAAa,IAAI;AAAA,IACxE,EAAE,OAAO,cAAc,MAAM,WAAW,SAAS,KAAK,aAAa,IAAI;AAAA,EACzE;AACF;AAEA,SAAS,mBAAmB,UAAyB,UAA+B;AAClF,MAAI,cAAc;AAClB,MAAI,QAAQ,SAAS;AACrB,MAAI,iBAAiB;AACrB,MAAI,UAAU;AACd,MAAI,YAAY;AAEhB,aAAW,KAAK,UAAU;AACxB,UAAM,OAAO,OAAO,EAAE,YAAY,WAAW,EAAE,UAAU,KAAK,UAAU,EAAE,OAAO;AACjF,mBAAe,KAAK,SAAS;AAC7B,QAAI,EAAE,SAAS,OAAQ,kBAAiB;AACxC,QAAI,KAAK,SAAS,KAAK,KAAK,KAAK,SAAS,WAAW,KAAK,KAAK,SAAS,QAAQ,EAAG,WAAU;AAC7F,QAAI,KAAK,SAAS,OAAO,KAAK,KAAK,SAAS,OAAO,KAAK,KAAK,SAAS,MAAM,EAAG,aAAY;AAAA,EAC7F;AAEA,MAAI,cAAc,OAAU,kBAAkB,UAAY,QAAO;AACjE,MAAI,cAAc,OAAQ,YAAY,WAAW,aAAa,QAAQ,EAAG,QAAO;AAChF,SAAO;AACT;AAEA,SAAS,YAAY,QAAuB,YAA6H;AACvK,QAAM,WAAW,OAAO,MAAM,OAAO,OAAK,EAAE,SAAS,SAAS;AAC9D,QAAM,UAAU,OAAO,MAAM,OAAO,OAAK,EAAE,SAAS,QAAQ;AAC5D,QAAM,YAAY,OAAO,MAAM,OAAO,OAAK,EAAE,SAAS,UAAU;AAChE,QAAM,WAAW,OAAO,MAAM,OAAO,OAAK,EAAE,SAAS,SAAS;AAE9D,UAAQ,YAAY;AAAA,IAClB,KAAK;AACH,aAAO,EAAE,SAAS,SAAS,CAAC,GAAG,SAAS,WAAW,UAAU,SAAS,CAAC,EAAE;AAAA,IAC3E,KAAK;AACH,aAAO,EAAE,SAAS,SAAS,CAAC,GAAG,SAAS,QAAQ,MAAM,GAAG,CAAC,GAAG,WAAW,UAAU,MAAM,GAAG,CAAC,GAAG,UAAU,SAAS,CAAC,EAAE;AAAA,IACvH,KAAK;AAAA,IACL;AACE,aAAO,EAAE,SAAS,SAAS,CAAC,GAAG,SAAS,QAAQ,MAAM,GAAG,CAAC,GAAG,WAAW,UAAU,MAAM,GAAG,CAAC,GAAG,UAAU,SAAS,CAAC,EAAE;AAAA,EACzH;AACF;AAEA,eAAe,UAAU,MAAmB,SAAsB,SAAiB,WAAmB,WAA0D;AAC9J,QAAM,OAAO,KAAK,WAAW,WAAW;AACxC,QAAM,WAAkB,CAAC;AAEzB,MAAI,QAAQ,cAAc;AACxB,aAAS,KAAK,EAAE,MAAM,UAAU,SAAS,QAAQ,aAAa,CAAC;AAAA,EACjE;AAEA,aAAW,KAAK,QAAQ,UAAU;AAChC,QAAI,EAAE,SAAS,QAAQ;AACrB,eAAS,KAAK,EAAE,MAAM,QAAQ,cAAc,EAAE,aAAa,SAAS,EAAE,QAAQ,CAAC;AAC/E;AAAA,IACF;AACA,QAAI,EAAE,SAAS,eAAe,MAAM,QAAQ,EAAE,OAAO,GAAG;AACtD,YAAM,YAAa,EAAE,QAA2B,OAAO,OAAK,EAAE,SAAS,MAAM;AAC7E,YAAM,YAAa,EAAE,QAA2B,OAAO,OAAK,EAAE,SAAS,UAAU;AACjF,YAAM,MAAW,CAAC;AAClB,UAAI,UAAU,OAAQ,KAAI,UAAU,UAAU,IAAI,OAAM,EAAuB,IAAI,EAAE,KAAK,EAAE;AAC5F,UAAI,UAAU,QAAQ;AACpB,YAAI,aAAa,UAAU,IAAI,OAAK;AAClC,gBAAM,KAAK;AACX,iBAAO,EAAE,IAAI,GAAG,IAAI,MAAM,YAAY,UAAU,EAAE,MAAM,GAAG,MAAM,WAAW,KAAK,UAAU,GAAG,KAAK,EAAE,EAAE;AAAA,QACzG,CAAC;AAAA,MACH;AACA,UAAI,OAAO;AACX,eAAS,KAAK,GAAG;AACjB;AAAA,IACF;AACA,aAAS,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,EAAE,QAAQ,CAAC;AAAA,EACpD;AAEA,QAAM,OAAY;AAAA,IAChB,OAAO,KAAK;AAAA,IACZ;AAAA,IACA,QAAQ;AAAA,IACR,SAAS;AAAA,MACP,aAAa,QAAQ,mBAAmB,KAAK,aAAa;AAAA,MAC1D,aAAa,QAAQ,eAAe,KAAK,eAAe;AAAA,MACxD,OAAO;AAAA,MACP,OAAO;AAAA,IACT;AAAA,IACA,GAAG;AAAA,EACL;AAEA,MAAI,QAAQ,OAAO,QAAQ;AACzB,SAAK,QAAQ,QAAQ,MAAM,IAAI,QAAM;AAAA,MACnC,MAAM;AAAA,MACN,UAAU,EAAE,MAAM,EAAE,MAAM,aAAa,EAAE,aAAa,YAAY,EAAE,aAAa;AAAA,IACnF,EAAE;AAAA,EACJ;AAEA,QAAM,QAAQ,KAAK,IAAI;AACvB,MAAI;AACJ,MAAI;AACF,eAAW,MAAM,MAAM,KAAK;AAAA,MAC1B,QAAQ;AAAA,MACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,MAC9C,MAAM,KAAK,UAAU,IAAI;AAAA,MACzB,QAAQ,YAAY,QAAQ,SAAS;AAAA,IACvC,CAAC;AAAA,EACH,SAAS,KAAK;AACZ,QAAI,eAAe,eAAgB,OAAM;AACzC,UAAM,IAAI,eAAe,gBAAgB,KAAK,KAAK,uBAAuB,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC,EAAE;AAAA,EAC9H;AAEA,MAAI,CAAC,SAAS,IAAI;AAChB,UAAMA,QAAO,MAAM,SAAS,KAAK;AACjC,QAAI,SAAS,WAAW,OAAO,SAAS,WAAW,OAAO,SAAS,WAAW,KAAK;AACjF,YAAM,IAAI,eAAe,gBAAgB,KAAK,KAAK,kBAAkB,SAAS,MAAM,EAAE;AAAA,IACxF;AACA,UAAM,IAAI,MAAM,gBAAgB,KAAK,KAAK,UAAU,SAAS,MAAM,KAAKA,MAAK,MAAM,GAAG,GAAG,CAAC,EAAE;AAAA,EAC9F;AAEA,QAAM,OAAO,MAAM,SAAS,KAAK;AACjC,QAAM,SAAS,KAAK,UAAU,CAAC;AAC/B,MAAI,CAAC,OAAQ,OAAM,IAAI,MAAM,gBAAgB,KAAK,KAAK,sBAAsB;AAE7E,MAAI,OAAO,OAAO,SAAS,WAAW;AACtC,SAAO,KAAK,QAAQ,mCAAmC,EAAE,EAAE,KAAK;AAChE,SAAO,KAAK,QAAQ,oCAAoC,EAAE,EAAE,KAAK;AACjE,SAAO,KAAK,QAAQ,wCAAwC,EAAE,EAAE,KAAK;AACrE,SAAO,KAAK,QAAQ,wBAAwB,EAAE,EAAE,KAAK;AAErD,SAAO;AAAA,IACL,SAAS;AAAA,IACT,OAAO;AAAA,MACL,aAAa,KAAK,OAAO,iBAAiB;AAAA,MAC1C,cAAc,KAAK,OAAO,qBAAqB;AAAA,MAC/C,iBAAiB;AAAA,MACjB,kBAAkB;AAAA,IACpB;AAAA,IACA,YAAY,OAAO,kBAAkB,eAAe,aAAa;AAAA,IACjE,OAAO,KAAK;AAAA,IACZ,YAAY,KAAK,IAAI,IAAI;AAAA,EAC3B;AACF;AAEA,SAAS,cAAc,QAAkC;AACvD,SAAO;AAAA,IACL,aAAa,OAAO,OAAO,CAAC,GAAG,MAAM,IAAI,EAAE,aAAa,CAAC;AAAA,IACzD,cAAc,OAAO,OAAO,CAAC,GAAG,MAAM,IAAI,EAAE,cAAc,CAAC;AAAA,IAC3D,iBAAiB,OAAO,OAAO,CAAC,GAAG,MAAM,KAAK,EAAE,mBAAmB,IAAI,CAAC;AAAA,IACxE,kBAAkB,OAAO,OAAO,CAAC,GAAG,MAAM,KAAK,EAAE,oBAAoB,IAAI,CAAC;AAAA,EAC5E;AACF;AAEO,IAAM,kBAAN,MAA0C;AAAA,EACtC;AAAA,EACD;AAAA,EACA;AAAA,EAER,YAAY,QAAiC;AAC3C,SAAK,SAAS;AAAA,MACZ,SAAS;AAAA,MACT,WAAW;AAAA,MACX,UAAU;AAAA,MACV,YAAY;AAAA,MACZ,cAAc;AAAA,MACd,OAAO,eAAe,QAAQ,OAAO;AAAA,MACrC,GAAG;AAAA,IACL;AACA,UAAM,SAAS,CAAC,GAAG,IAAI,IAAI,KAAK,OAAO,MAAM,IAAI,OAAK,EAAE,KAAK,CAAC,CAAC;AAC/D,SAAK,QAAQ,WAAW,OAAO,KAAK,GAAG,CAAC;AACxC,SAAK,QAAQ,EAAE,OAAO,GAAG,UAAU,GAAG,WAAW,GAAG,SAAS,CAAC,EAAE;AAChE,eAAW,KAAK,OAAQ,MAAK,MAAM,QAAQ,CAAC,IAAI;AAAA,EAClD;AAAA,EAEA,WAAW;AAAE,WAAO,EAAE,GAAG,KAAK,MAAM;AAAA,EAAG;AAAA,EAEvC,MAAM,KAAK,SAA8C;AACvD,UAAM,WAAW,KAAK,OAAO,YAAY;AACzC,UAAM,aAAa,aAAa,SAAS,mBAAmB,QAAQ,UAAU,CAAC,CAAC,QAAQ,OAAO,MAAM,IAAI;AAEzG,QAAI;AACJ,YAAQ,aAAa,SAAS,aAAa,UAAU;AAAA,MACnD,KAAK;AACH,iBAAS,MAAM,KAAK,YAAY,OAAO;AACvC;AAAA,MACF,KAAK;AACH,iBAAS,MAAM,KAAK,OAAO,OAAO;AAClC;AAAA,MACF;AACE,iBAAS,MAAM,KAAK,YAAY,OAAO;AACvC;AAAA,IACJ;AAEA,UAAM,UAA0B,CAAC;AACjC,QAAI,OAAO,SAAS;AAClB,cAAQ,KAAK,EAAE,MAAM,QAAQ,MAAM,OAAO,QAAQ,CAAC;AAAA,IACrD;AAEA,WAAO;AAAA,MACL;AAAA,MACA,YAAY,OAAO;AAAA,MACnB,OAAO,OAAO;AAAA,IAChB;AAAA,EACF;AAAA,EAEA,MAAc,YAAY,SAA2C;AACnE,UAAM,QAAQ,YAAY,KAAK,QAAQ,QAAQ;AAC/C,UAAM,UAAU,MAAM;AACtB,UAAM,SAAS,MAAM,QAAQ,CAAC;AAE9B,QAAI,CAAC,WAAW,CAAC,QAAQ;AACvB,aAAO,KAAK,SAAS,OAAO;AAAA,IAC9B;AAEA,UAAM,QAAQ,MAAM,KAAK,SAAS,SAAS,SAAS,EAAE,aAAc,QAAQ,mBAAmB,KAAM,CAAC;AAEtG,QAAI,CAAC,SAAS,MAAM,QAAQ,SAAS,IAAI;AACvC,YAAM,KAAK,MAAM,KAAK,SAAS,QAAQ,OAAO;AAC9C,aAAO,MAAM,KAAK,SAAS,OAAO;AAAA,IACpC;AAEA,UAAM,iBAAgC;AAAA,MACpC,GAAG,QAAQ,SAAS,MAAM,GAAG,EAAE;AAAA,MAC/B,EAAE,MAAM,QAAiB,SAAS,GAAG,OAAO,QAAQ,SAAS,QAAQ,SAAS,SAAS,CAAC,EAAE,YAAY,WAAW,QAAQ,SAAS,QAAQ,SAAS,SAAS,CAAC,EAAE,UAAU,EAAE;AAAA;AAAA;AAAA;AAAA;AAAA,EAAoM,MAAM,QAAQ,MAAM,GAAG,GAAI,CAAC,GAAG;AAAA,IAChZ;AAEA,UAAM,gBAA6B,EAAE,GAAG,SAAS,UAAU,eAAe;AAC1E,UAAM,WAAW,MAAM,KAAK,SAAS,QAAQ,aAAa;AAE1D,QAAI,CAAC,SAAU,QAAO,EAAE,GAAG,OAAO,OAAO,KAAK,MAAM;AAEpD,UAAM,aAAa,kBAAkB,MAAM,SAAS,SAAS,OAAO;AACpE,QAAI,aAAa,KAAK;AACpB,aAAO,EAAE,GAAG,OAAO,OAAO,WAAW,MAAM,KAAK,EAAE;AAAA,IACpD;AAEA,WAAO,EAAE,GAAG,UAAU,OAAO,WAAW,MAAM,OAAO,SAAS,KAAK,EAAE;AAAA,EACvE;AAAA,EAEA,MAAc,YAAY,SAA2C;AACnE,UAAM,QAAQ,YAAY,KAAK,QAAQ,QAAQ;AAC/C,UAAM,SAAS,MAAM,QAAQ,CAAC;AAC9B,UAAM,WAAW,MAAM,UAAU,CAAC;AAElC,QAAI,CAAC,OAAQ,QAAO,KAAK,SAAS,OAAO;AAEzC,UAAM,UAAU,MAAM,KAAK,SAAS,QAAQ,OAAO;AACnD,QAAI,CAAC,QAAS,QAAO,KAAK,SAAS,OAAO;AAE1C,QAAI,CAAC,YAAY,QAAQ,QAAQ,SAAS,IAAI;AAC5C,aAAO;AAAA,IACT;AAEA,UAAM,iBAAgC;AAAA,MACpC,EAAE,MAAM,QAAiB,SAAS;AAAA;AAAA;AAAA,EAA+G,OAAO,QAAQ,SAAS,QAAQ,SAAS,SAAS,CAAC,EAAE,YAAY,WAAW,QAAQ,SAAS,QAAQ,SAAS,SAAS,CAAC,EAAE,UAAU,EAAE;AAAA;AAAA;AAAA,EAA4B,QAAQ,QAAQ,MAAM,GAAG,GAAI,CAAC,GAAG;AAAA,IACtV;AAEA,UAAM,WAAW,MAAM,KAAK,SAAS,UAAU,EAAE,GAAG,SAAS,UAAU,gBAAgB,iBAAiB,QAAQ,gBAAgB,CAAC;AACjI,QAAI,CAAC,SAAU,QAAO;AAEtB,WAAO,EAAE,GAAG,UAAU,OAAO,WAAW,QAAQ,OAAO,SAAS,KAAK,EAAE;AAAA,EACzE;AAAA,EAEA,MAAc,OAAO,SAA2C;AAC9D,UAAM,QAAQ,YAAY,KAAK,QAAQ,SAAS;AAChD,UAAM,UAAU,MAAM;AACtB,UAAM,UAAU,MAAM;AAEtB,QAAI,CAAC,QAAQ,OAAQ,QAAO,KAAK,SAAS,OAAO;AAEjD,UAAM,cAAc,KAAK,OAAO,gBAAgB;AAChD,QAAI,iBAAiB;AAErB,aAAS,QAAQ,GAAG,QAAQ,aAAa,SAAS;AAChD,YAAM,aAAa,QAAQ,QAAQ,QAAQ,MAAM;AACjD,YAAM,eAA8B,UAAU,IAC1C,QAAQ,WACR;AAAA,QACE,GAAG,QAAQ,SAAS,MAAM,GAAG,EAAE;AAAA,QAC/B;AAAA,UACE,MAAM;AAAA,UACN,SAAS,GAAG,OAAO,QAAQ,SAAS,QAAQ,SAAS,SAAS,CAAC,EAAE,YAAY,WAAW,QAAQ,SAAS,QAAQ,SAAS,SAAS,CAAC,EAAE,UAAU,EAAE;AAAA;AAAA,0BAA+B,KAAK;AAAA,EAAO,eAAe,MAAM,GAAG,GAAI,CAAC;AAAA;AAAA;AAAA,QAC5N;AAAA,MACF;AAEJ,YAAM,OAAO,MAAM,KAAK,SAAS,YAAY,EAAE,GAAG,SAAS,UAAU,aAAa,CAAC;AACnF,UAAI,CAAC,KAAM;AACX,uBAAiB,KAAK;AAAA,IACxB;AAEA,QAAI,CAAC,eAAgB,QAAO,KAAK,SAAS,OAAO;AAEjD,QAAI,WAAW,QAAQ,SAAS,GAAG;AACjC,YAAM,aAA2B,CAAC;AAClC,iBAAW,KAAK,SAAS;AACvB,cAAM,IAAI,MAAM,KAAK,SAAS,GAAG,OAAO;AACxC,YAAI,KAAK,EAAE,QAAQ,SAAS,GAAI,YAAW,KAAK,CAAC;AAAA,MACnD;AAEA,UAAI,WAAW,SAAS,GAAG;AACzB,cAAM,OAAO,WAAW,KAAK,CAAC,GAAG,MAAM,EAAE,QAAQ,SAAS,EAAE,QAAQ,MAAM,EAAE,CAAC;AAC7E,cAAM,cAA6B;AAAA,UACjC;AAAA,YACE,MAAM;AAAA,YACN,SAAS;AAAA;AAAA;AAAA,EAA8F,OAAO,QAAQ,SAAS,QAAQ,SAAS,SAAS,CAAC,EAAE,YAAY,WAAW,QAAQ,SAAS,QAAQ,SAAS,SAAS,CAAC,EAAE,UAAU,EAAE;AAAA;AAAA;AAAA,EAAoB,WAAW,IAAI,CAAC,GAAG,MAAM,iBAAiB,IAAI,CAAC,KAAK,EAAE,KAAK;AAAA,EAAU,EAAE,QAAQ,MAAM,GAAG,GAAI,CAAC,EAAE,EAAE,KAAK,MAAM,CAAC;AAAA,UAChX;AAAA,QACF;AAEA,cAAM,aAAa,MAAM,KAAK,SAAS,SAAS,EAAE,GAAG,SAAS,UAAU,aAAa,iBAAiB,QAAQ,gBAAgB,CAAC;AAC/H,YAAI,cAAc,WAAW,QAAQ,SAAS,IAAI;AAChD,gBAAM,YAAY,WAAW,IAAI,OAAK,EAAE,KAAK,EAAE,OAAO,WAAW,KAAK;AACtE,iBAAO,EAAE,GAAG,YAAY,OAAO,WAAW,GAAG,SAAS,EAAE;AAAA,QAC1D;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,MACL,SAAS;AAAA,MACT,OAAO,EAAE,aAAa,GAAG,cAAc,EAAE;AAAA,MACzC,YAAY;AAAA,MACZ,OAAO,KAAK;AAAA,MACZ,YAAY;AAAA,IACd;AAAA,EACF;AAAA,EAEA,MAAc,SAAS,MAAmB,SAAsB,WAAiE;AAC/H,QAAI;AACF,YAAM,SAAS,MAAM,UAAU,MAAM,SAAS,KAAK,OAAO,WAAW,cAAc,KAAK,OAAO,aAAa,MAAS,SAAS;AAC9H,WAAK,MAAM;AACX,WAAK,MAAM,YAAY,OAAO,MAAM;AACpC,WAAK,MAAM,aAAa,OAAO,MAAM;AACrC,WAAK,MAAM,QAAQ,KAAK,KAAK,KAAK,KAAK,MAAM,QAAQ,KAAK,KAAK,KAAK,KAAK;AACzE,aAAO;AAAA,IACT,SAAS,GAAG;AACV,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEA,MAAc,SAAS,SAA2C;AAChE,UAAM,UAAU,KAAK,OAAO,MAAM,CAAC;AACnC,UAAM,SAAS,MAAM,UAAU,SAAS,SAAS,KAAK,OAAO,WAAW,cAAc,KAAK,OAAO,aAAa,IAAO;AACtH,SAAK,MAAM;AACX,SAAK,MAAM,YAAY,OAAO,MAAM;AACpC,SAAK,MAAM,aAAa,OAAO,MAAM;AACrC,SAAK,MAAM,QAAQ,QAAQ,KAAK,KAAK,KAAK,MAAM,QAAQ,QAAQ,KAAK,KAAK,KAAK;AAC/E,WAAO;AAAA,EACT;AACF;AAEA,SAAS,kBAAkB,GAAW,GAAmB;AACvD,QAAM,SAAS,IAAI,IAAI,EAAE,YAAY,EAAE,MAAM,KAAK,EAAE,OAAO,OAAK,EAAE,SAAS,CAAC,CAAC;AAC7E,QAAM,SAAS,IAAI,IAAI,EAAE,YAAY,EAAE,MAAM,KAAK,EAAE,OAAO,OAAK,EAAE,SAAS,CAAC,CAAC;AAC7E,MAAI,OAAO,SAAS,KAAK,OAAO,SAAS,EAAG,QAAO;AACnD,QAAM,eAAe,CAAC,GAAG,MAAM,EAAE,OAAO,OAAK,OAAO,IAAI,CAAC,CAAC,EAAE;AAC5D,QAAM,SAAQ,oBAAI,IAAI,CAAC,GAAG,QAAQ,GAAG,MAAM,CAAC,GAAE;AAC9C,SAAO,QAAQ,IAAI,eAAe,QAAQ;AAC5C;;;AC/WO,SAAS,UAAU,QAAoD;AAC5E,SAAO,IAAI,kBAAkB,MAAM;AACrC;AAEO,SAAS,OAAO,QAA8C;AACnE,SAAO,IAAI,eAAe,MAAM;AAClC;AAEO,SAAS,OAAO,QAA8C;AACnE,SAAO,IAAI,eAAe,MAAM;AAClC;AAEO,SAAS,QAAQ,QAAkD;AACxE,SAAO,IAAI,gBAAgB,MAAM;AACnC;AAQA,IAAM,iBAAN,MAAyC;AAAA,EAC9B;AAAA,EACQ;AAAA,EAEjB,YAAY,QAA8B;AACxC,SAAK,QAAQ,OAAO;AACpB,SAAK,SAAS,OAAO;AAAA,EACvB;AAAA,EAEA,KAAK,SAA8C;AACjD,WAAO,KAAK,OAAO,OAAO;AAAA,EAC5B;AACF;AAIO,SAAS,eACd,QAKU;AACV,UAAQ,OAAO,UAAU;AAAA,IACvB,KAAK;AACH,aAAO,IAAI,kBAAkB,MAAM;AAAA,IACrC,KAAK;AACH,aAAO,IAAI,eAAe,MAAM;AAAA,IAClC,KAAK;AACH,aAAO,IAAI,eAAe,MAAM;AAAA,IAClC,KAAK;AACH,aAAO,IAAI,eAAe,MAAM;AAAA,EACpC;AACF;","names":["text"]}