@avasis-ai/synthcode 1.0.7 → 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.
- package/dist/{chunk-F34HO4RA.js → chunk-KPJDLUMB.js} +338 -1
- package/dist/chunk-KPJDLUMB.js.map +1 -0
- package/dist/index.cjs +339 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +5 -1
- package/dist/index.js.map +1 -1
- package/dist/llm/index.cjs +339 -0
- package/dist/llm/index.cjs.map +1 -1
- package/dist/llm/index.d.cts +36 -1
- package/dist/llm/index.d.ts +36 -1
- package/dist/llm/index.js +5 -1
- package/package.json +1 -1
- package/dist/chunk-F34HO4RA.js.map +0 -1
package/dist/llm/index.cjs
CHANGED
|
@@ -32,10 +32,12 @@ var llm_exports = {};
|
|
|
32
32
|
__export(llm_exports, {
|
|
33
33
|
AnthropicProvider: () => AnthropicProvider,
|
|
34
34
|
BaseProvider: () => BaseProvider,
|
|
35
|
+
ClusterProvider: () => ClusterProvider,
|
|
35
36
|
OllamaProvider: () => OllamaProvider,
|
|
36
37
|
OpenAIProvider: () => OpenAIProvider,
|
|
37
38
|
RetryableError: () => RetryableError,
|
|
38
39
|
anthropic: () => anthropic,
|
|
40
|
+
cluster: () => cluster,
|
|
39
41
|
createProvider: () => createProvider,
|
|
40
42
|
ollama: () => ollama,
|
|
41
43
|
openai: () => openai
|
|
@@ -483,6 +485,338 @@ var OllamaProvider = class {
|
|
|
483
485
|
}
|
|
484
486
|
};
|
|
485
487
|
|
|
488
|
+
// src/llm/cluster.ts
|
|
489
|
+
var DEFAULT_BASE = "http://localhost:11434/v1";
|
|
490
|
+
function defaultCluster(baseURL) {
|
|
491
|
+
const url = baseURL || DEFAULT_BASE;
|
|
492
|
+
return [
|
|
493
|
+
{ model: "gemma4:31b", role: "planner", baseURL: url, temperature: 0.3 },
|
|
494
|
+
{ model: "gemma4:26b", role: "worker", baseURL: url, temperature: 0.3 },
|
|
495
|
+
{ model: "gemma4:26b", role: "worker", baseURL: url, temperature: 0.35 },
|
|
496
|
+
{ model: "gemma4:26b", role: "reviewer", baseURL: url, temperature: 0.3 },
|
|
497
|
+
{ model: "gemma4:e4b", role: "drafter", baseURL: url, temperature: 0.3 }
|
|
498
|
+
];
|
|
499
|
+
}
|
|
500
|
+
function classifyComplexity(messages, hasTools) {
|
|
501
|
+
let totalTokens = 0;
|
|
502
|
+
let turns = messages.length;
|
|
503
|
+
let hasToolResults = false;
|
|
504
|
+
let hasCode = false;
|
|
505
|
+
let hasErrors = false;
|
|
506
|
+
for (const m of messages) {
|
|
507
|
+
const text = typeof m.content === "string" ? m.content : JSON.stringify(m.content);
|
|
508
|
+
totalTokens += text.length / 4;
|
|
509
|
+
if (m.role === "tool") hasToolResults = true;
|
|
510
|
+
if (text.includes("```") || text.includes("function ") || text.includes("class ")) hasCode = true;
|
|
511
|
+
if (text.includes("error") || text.includes("Error") || text.includes("FAIL")) hasErrors = true;
|
|
512
|
+
}
|
|
513
|
+
if (totalTokens > 1e4 || hasToolResults && hasErrors) return "complex";
|
|
514
|
+
if (totalTokens > 2e3 || hasTools || hasCode || hasErrors || turns > 4) return "medium";
|
|
515
|
+
return "simple";
|
|
516
|
+
}
|
|
517
|
+
function selectSlots(config, complexity) {
|
|
518
|
+
const planners = config.slots.filter((s) => s.role === "planner");
|
|
519
|
+
const workers = config.slots.filter((s) => s.role === "worker");
|
|
520
|
+
const reviewers = config.slots.filter((s) => s.role === "reviewer");
|
|
521
|
+
const drafters = config.slots.filter((s) => s.role === "drafter");
|
|
522
|
+
switch (complexity) {
|
|
523
|
+
case "complex":
|
|
524
|
+
return { planner: planners[0], workers, reviewers, drafters: drafters[0] };
|
|
525
|
+
case "medium":
|
|
526
|
+
return { planner: planners[0], workers: workers.slice(0, 1), reviewers: reviewers.slice(0, 1), drafters: drafters[0] };
|
|
527
|
+
case "simple":
|
|
528
|
+
default:
|
|
529
|
+
return { planner: planners[0], workers: workers.slice(0, 1), reviewers: reviewers.slice(0, 1), drafters: drafters[0] };
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
async function callModel(slot, request, baseURL, timeoutMs, extraOpts) {
|
|
533
|
+
const url = (slot.baseURL || baseURL) + "/chat/completions";
|
|
534
|
+
const messages = [];
|
|
535
|
+
if (request.systemPrompt) {
|
|
536
|
+
messages.push({ role: "system", content: request.systemPrompt });
|
|
537
|
+
}
|
|
538
|
+
for (const m of request.messages) {
|
|
539
|
+
if (m.role === "tool") {
|
|
540
|
+
messages.push({ role: "tool", tool_call_id: m.tool_use_id, content: m.content });
|
|
541
|
+
continue;
|
|
542
|
+
}
|
|
543
|
+
if (m.role === "assistant" && Array.isArray(m.content)) {
|
|
544
|
+
const textParts = m.content.filter((b) => b.type === "text");
|
|
545
|
+
const toolParts = m.content.filter((b) => b.type === "tool_use");
|
|
546
|
+
const msg = {};
|
|
547
|
+
if (textParts.length) msg.content = textParts.map((p) => p.text).join("");
|
|
548
|
+
if (toolParts.length) {
|
|
549
|
+
msg.tool_calls = toolParts.map((b) => {
|
|
550
|
+
const tb = b;
|
|
551
|
+
return { id: tb.id, type: "function", function: { name: tb.name, arguments: JSON.stringify(tb.input) } };
|
|
552
|
+
});
|
|
553
|
+
}
|
|
554
|
+
msg.role = "assistant";
|
|
555
|
+
messages.push(msg);
|
|
556
|
+
continue;
|
|
557
|
+
}
|
|
558
|
+
messages.push({ role: m.role, content: m.content });
|
|
559
|
+
}
|
|
560
|
+
const body = {
|
|
561
|
+
model: slot.model,
|
|
562
|
+
messages,
|
|
563
|
+
stream: false,
|
|
564
|
+
options: {
|
|
565
|
+
num_predict: request.maxOutputTokens || slot.maxTokens || 4096,
|
|
566
|
+
temperature: request.temperature ?? slot.temperature ?? 0.3,
|
|
567
|
+
top_p: 0.95,
|
|
568
|
+
top_k: 64
|
|
569
|
+
},
|
|
570
|
+
...extraOpts
|
|
571
|
+
};
|
|
572
|
+
if (request.tools?.length) {
|
|
573
|
+
body.tools = request.tools.map((t) => ({
|
|
574
|
+
type: "function",
|
|
575
|
+
function: { name: t.name, description: t.description, parameters: t.input_schema }
|
|
576
|
+
}));
|
|
577
|
+
}
|
|
578
|
+
const start = Date.now();
|
|
579
|
+
let response;
|
|
580
|
+
try {
|
|
581
|
+
response = await fetch(url, {
|
|
582
|
+
method: "POST",
|
|
583
|
+
headers: { "Content-Type": "application/json" },
|
|
584
|
+
body: JSON.stringify(body),
|
|
585
|
+
signal: AbortSignal.timeout(timeoutMs)
|
|
586
|
+
});
|
|
587
|
+
} catch (err) {
|
|
588
|
+
if (err instanceof RetryableError) throw err;
|
|
589
|
+
throw new RetryableError(`Cluster slot ${slot.model} connection failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
590
|
+
}
|
|
591
|
+
if (!response.ok) {
|
|
592
|
+
const text2 = await response.text();
|
|
593
|
+
if (response.status === 429 || response.status === 503 || response.status === 529) {
|
|
594
|
+
throw new RetryableError(`Cluster slot ${slot.model} rate limited: ${response.status}`);
|
|
595
|
+
}
|
|
596
|
+
throw new Error(`Cluster slot ${slot.model} error ${response.status}: ${text2.slice(0, 200)}`);
|
|
597
|
+
}
|
|
598
|
+
const data = await response.json();
|
|
599
|
+
const choice = data.choices?.[0];
|
|
600
|
+
if (!choice) throw new Error(`Cluster slot ${slot.model} returned no choices`);
|
|
601
|
+
let text = choice.message?.content || "";
|
|
602
|
+
text = text.replace(/<think[^>]*>[\s\S]*?<\/think>/gi, "").trim();
|
|
603
|
+
text = text.replace(/<thinking>[\s\S]*?<\/thinking>/gi, "").trim();
|
|
604
|
+
text = text.replace(/<channel>thought[\s\S]*?<channel|>/gi, "").trim();
|
|
605
|
+
text = text.replace(/\[Thinking[^\]]*\]/gi, "").trim();
|
|
606
|
+
return {
|
|
607
|
+
content: text,
|
|
608
|
+
usage: {
|
|
609
|
+
inputTokens: data.usage?.prompt_tokens ?? 0,
|
|
610
|
+
outputTokens: data.usage?.completion_tokens ?? 0,
|
|
611
|
+
cacheReadTokens: 0,
|
|
612
|
+
cacheWriteTokens: 0
|
|
613
|
+
},
|
|
614
|
+
stopReason: choice.finish_reason === "tool_calls" ? "tool_use" : "end_turn",
|
|
615
|
+
model: slot.model,
|
|
616
|
+
durationMs: Date.now() - start
|
|
617
|
+
};
|
|
618
|
+
}
|
|
619
|
+
function mergeUsage(...usages) {
|
|
620
|
+
return {
|
|
621
|
+
inputTokens: usages.reduce((s, u) => s + u.inputTokens, 0),
|
|
622
|
+
outputTokens: usages.reduce((s, u) => s + u.outputTokens, 0),
|
|
623
|
+
cacheReadTokens: usages.reduce((s, u) => s + (u.cacheReadTokens || 0), 0),
|
|
624
|
+
cacheWriteTokens: usages.reduce((s, u) => s + (u.cacheWriteTokens || 0), 0)
|
|
625
|
+
};
|
|
626
|
+
}
|
|
627
|
+
var ClusterProvider = class {
|
|
628
|
+
model;
|
|
629
|
+
config;
|
|
630
|
+
stats;
|
|
631
|
+
constructor(config) {
|
|
632
|
+
this.config = {
|
|
633
|
+
baseURL: DEFAULT_BASE,
|
|
634
|
+
timeoutMs: 18e4,
|
|
635
|
+
strategy: "auto",
|
|
636
|
+
draftCount: 1,
|
|
637
|
+
debateRounds: 1,
|
|
638
|
+
slots: defaultCluster(config?.baseURL),
|
|
639
|
+
...config
|
|
640
|
+
};
|
|
641
|
+
const models = [...new Set(this.config.slots.map((s) => s.model))];
|
|
642
|
+
this.model = `cluster[${models.join(",")}]`;
|
|
643
|
+
this.stats = { calls: 0, tokensIn: 0, tokensOut: 0, byModel: {} };
|
|
644
|
+
for (const m of models) this.stats.byModel[m] = 0;
|
|
645
|
+
}
|
|
646
|
+
getStats() {
|
|
647
|
+
return { ...this.stats };
|
|
648
|
+
}
|
|
649
|
+
async chat(request) {
|
|
650
|
+
const strategy = this.config.strategy || "auto";
|
|
651
|
+
const complexity = strategy === "auto" ? classifyComplexity(request.messages, !!request.tools?.length) : "medium";
|
|
652
|
+
let result;
|
|
653
|
+
switch (strategy === "auto" ? complexity : "simple") {
|
|
654
|
+
case "simple":
|
|
655
|
+
result = await this.speculative(request);
|
|
656
|
+
break;
|
|
657
|
+
case "complex":
|
|
658
|
+
result = await this.debate(request);
|
|
659
|
+
break;
|
|
660
|
+
default:
|
|
661
|
+
result = await this.draftVerify(request);
|
|
662
|
+
break;
|
|
663
|
+
}
|
|
664
|
+
const content = [];
|
|
665
|
+
if (result.content) {
|
|
666
|
+
content.push({ type: "text", text: result.content });
|
|
667
|
+
}
|
|
668
|
+
return {
|
|
669
|
+
content,
|
|
670
|
+
stopReason: result.stopReason,
|
|
671
|
+
usage: result.usage
|
|
672
|
+
};
|
|
673
|
+
}
|
|
674
|
+
async speculative(request) {
|
|
675
|
+
const slots = selectSlots(this.config, "simple");
|
|
676
|
+
const drafter = slots.drafters;
|
|
677
|
+
const worker = slots.workers[0];
|
|
678
|
+
if (!drafter || !worker) {
|
|
679
|
+
return this.fallback(request);
|
|
680
|
+
}
|
|
681
|
+
const draft = await this.safeCall(drafter, request, { num_predict: request.maxOutputTokens || 4096 });
|
|
682
|
+
if (!draft || draft.content.length < 20) {
|
|
683
|
+
const fb = await this.safeCall(worker, request);
|
|
684
|
+
return fb || this.fallback(request);
|
|
685
|
+
}
|
|
686
|
+
const verifyMessages = [
|
|
687
|
+
...request.messages.slice(0, -1),
|
|
688
|
+
{ role: "user", content: `${typeof request.messages[request.messages.length - 1].content === "string" ? request.messages[request.messages.length - 1].content : ""}
|
|
689
|
+
|
|
690
|
+
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.
|
|
691
|
+
|
|
692
|
+
DRAFT:
|
|
693
|
+
${draft.content.slice(0, 8e3)}` }
|
|
694
|
+
];
|
|
695
|
+
const verifyRequest = { ...request, messages: verifyMessages };
|
|
696
|
+
const verified = await this.safeCall(worker, verifyRequest);
|
|
697
|
+
if (!verified) return { ...draft, model: this.model };
|
|
698
|
+
const similarity = jaccardSimilarity(draft.content, verified.content);
|
|
699
|
+
if (similarity > 0.7) {
|
|
700
|
+
return { ...draft, usage: mergeUsage(draft.usage) };
|
|
701
|
+
}
|
|
702
|
+
return { ...verified, usage: mergeUsage(draft.usage, verified.usage) };
|
|
703
|
+
}
|
|
704
|
+
async draftVerify(request) {
|
|
705
|
+
const slots = selectSlots(this.config, "medium");
|
|
706
|
+
const worker = slots.workers[0];
|
|
707
|
+
const reviewer = slots.reviewers[0];
|
|
708
|
+
if (!worker) return this.fallback(request);
|
|
709
|
+
const primary = await this.safeCall(worker, request);
|
|
710
|
+
if (!primary) return this.fallback(request);
|
|
711
|
+
if (!reviewer || primary.content.length < 50) {
|
|
712
|
+
return primary;
|
|
713
|
+
}
|
|
714
|
+
const reviewMessages = [
|
|
715
|
+
{ role: "user", content: `Review this response for correctness. Fix any errors. Return ONLY the corrected text.
|
|
716
|
+
|
|
717
|
+
ORIGINAL REQUEST:
|
|
718
|
+
${typeof request.messages[request.messages.length - 1].content === "string" ? request.messages[request.messages.length - 1].content : ""}
|
|
719
|
+
|
|
720
|
+
RESPONSE TO REVIEW:
|
|
721
|
+
${primary.content.slice(0, 6e3)}` }
|
|
722
|
+
];
|
|
723
|
+
const reviewed = await this.safeCall(reviewer, { ...request, messages: reviewMessages, maxOutputTokens: request.maxOutputTokens });
|
|
724
|
+
if (!reviewed) return primary;
|
|
725
|
+
return { ...reviewed, usage: mergeUsage(primary.usage, reviewed.usage) };
|
|
726
|
+
}
|
|
727
|
+
async debate(request) {
|
|
728
|
+
const slots = selectSlots(this.config, "complex");
|
|
729
|
+
const workers = slots.workers;
|
|
730
|
+
const planner = slots.planner;
|
|
731
|
+
if (!workers.length) return this.fallback(request);
|
|
732
|
+
const roundRounds = this.config.debateRounds || 1;
|
|
733
|
+
let currentContent = "";
|
|
734
|
+
for (let round = 0; round < roundRounds; round++) {
|
|
735
|
+
const workerSlot = workers[round % workers.length];
|
|
736
|
+
const implMessages = round === 0 ? request.messages : [
|
|
737
|
+
...request.messages.slice(0, -1),
|
|
738
|
+
{
|
|
739
|
+
role: "user",
|
|
740
|
+
content: `${typeof request.messages[request.messages.length - 1].content === "string" ? request.messages[request.messages.length - 1].content : ""}
|
|
741
|
+
|
|
742
|
+
PREVIOUS ATTEMPT (Round ${round}):
|
|
743
|
+
${currentContent.slice(0, 4e3)}
|
|
744
|
+
|
|
745
|
+
Improve this. Fix any issues.`
|
|
746
|
+
}
|
|
747
|
+
];
|
|
748
|
+
const impl = await this.safeCall(workerSlot, { ...request, messages: implMessages });
|
|
749
|
+
if (!impl) continue;
|
|
750
|
+
currentContent = impl.content;
|
|
751
|
+
}
|
|
752
|
+
if (!currentContent) return this.fallback(request);
|
|
753
|
+
if (planner && workers.length > 1) {
|
|
754
|
+
const candidates = [];
|
|
755
|
+
for (const w of workers) {
|
|
756
|
+
const c = await this.safeCall(w, request);
|
|
757
|
+
if (c && c.content.length > 30) candidates.push(c);
|
|
758
|
+
}
|
|
759
|
+
if (candidates.length > 1) {
|
|
760
|
+
const best = candidates.sort((a, b) => b.content.length - a.content.length)[0];
|
|
761
|
+
const arbMessages = [
|
|
762
|
+
{
|
|
763
|
+
role: "user",
|
|
764
|
+
content: `Select the best response or synthesize a better one. Return ONLY the final text.
|
|
765
|
+
|
|
766
|
+
TASK:
|
|
767
|
+
${typeof request.messages[request.messages.length - 1].content === "string" ? request.messages[request.messages.length - 1].content : ""}
|
|
768
|
+
|
|
769
|
+
CANDIDATES:
|
|
770
|
+
${candidates.map((c, i) => `--- Candidate ${i + 1} (${c.model}) ---
|
|
771
|
+
${c.content.slice(0, 3e3)}`).join("\n\n")}`
|
|
772
|
+
}
|
|
773
|
+
];
|
|
774
|
+
const arbitrated = await this.safeCall(planner, { ...request, messages: arbMessages, maxOutputTokens: request.maxOutputTokens });
|
|
775
|
+
if (arbitrated && arbitrated.content.length > 20) {
|
|
776
|
+
const allUsages = candidates.map((c) => c.usage).concat(arbitrated.usage);
|
|
777
|
+
return { ...arbitrated, usage: mergeUsage(...allUsages) };
|
|
778
|
+
}
|
|
779
|
+
}
|
|
780
|
+
}
|
|
781
|
+
return {
|
|
782
|
+
content: currentContent,
|
|
783
|
+
usage: { inputTokens: 0, outputTokens: 0 },
|
|
784
|
+
stopReason: "end_turn",
|
|
785
|
+
model: this.model,
|
|
786
|
+
durationMs: 0
|
|
787
|
+
};
|
|
788
|
+
}
|
|
789
|
+
async safeCall(slot, request, extraOpts) {
|
|
790
|
+
try {
|
|
791
|
+
const result = await callModel(slot, request, this.config.baseURL || DEFAULT_BASE, this.config.timeoutMs || 18e4, extraOpts);
|
|
792
|
+
this.stats.calls++;
|
|
793
|
+
this.stats.tokensIn += result.usage.inputTokens;
|
|
794
|
+
this.stats.tokensOut += result.usage.outputTokens;
|
|
795
|
+
this.stats.byModel[slot.model] = (this.stats.byModel[slot.model] || 0) + 1;
|
|
796
|
+
return result;
|
|
797
|
+
} catch (e) {
|
|
798
|
+
return null;
|
|
799
|
+
}
|
|
800
|
+
}
|
|
801
|
+
async fallback(request) {
|
|
802
|
+
const anySlot = this.config.slots[0];
|
|
803
|
+
const result = await callModel(anySlot, request, this.config.baseURL || DEFAULT_BASE, this.config.timeoutMs || 18e4);
|
|
804
|
+
this.stats.calls++;
|
|
805
|
+
this.stats.tokensIn += result.usage.inputTokens;
|
|
806
|
+
this.stats.tokensOut += result.usage.outputTokens;
|
|
807
|
+
this.stats.byModel[anySlot.model] = (this.stats.byModel[anySlot.model] || 0) + 1;
|
|
808
|
+
return result;
|
|
809
|
+
}
|
|
810
|
+
};
|
|
811
|
+
function jaccardSimilarity(a, b) {
|
|
812
|
+
const aWords = new Set(a.toLowerCase().split(/\s+/).filter((w) => w.length > 2));
|
|
813
|
+
const bWords = new Set(b.toLowerCase().split(/\s+/).filter((w) => w.length > 2));
|
|
814
|
+
if (aWords.size === 0 && bWords.size === 0) return 1;
|
|
815
|
+
const intersection = [...aWords].filter((w) => bWords.has(w)).length;
|
|
816
|
+
const union = (/* @__PURE__ */ new Set([...aWords, ...bWords])).size;
|
|
817
|
+
return union > 0 ? intersection / union : 0;
|
|
818
|
+
}
|
|
819
|
+
|
|
486
820
|
// src/llm/index.ts
|
|
487
821
|
function anthropic(config) {
|
|
488
822
|
return new AnthropicProvider(config);
|
|
@@ -493,6 +827,9 @@ function openai(config) {
|
|
|
493
827
|
function ollama(config) {
|
|
494
828
|
return new OllamaProvider(config);
|
|
495
829
|
}
|
|
830
|
+
function cluster(config) {
|
|
831
|
+
return new ClusterProvider(config);
|
|
832
|
+
}
|
|
496
833
|
var CustomProvider = class {
|
|
497
834
|
model;
|
|
498
835
|
chatFn;
|
|
@@ -520,10 +857,12 @@ function createProvider(config) {
|
|
|
520
857
|
0 && (module.exports = {
|
|
521
858
|
AnthropicProvider,
|
|
522
859
|
BaseProvider,
|
|
860
|
+
ClusterProvider,
|
|
523
861
|
OllamaProvider,
|
|
524
862
|
OpenAIProvider,
|
|
525
863
|
RetryableError,
|
|
526
864
|
anthropic,
|
|
865
|
+
cluster,
|
|
527
866
|
createProvider,
|
|
528
867
|
ollama,
|
|
529
868
|
openai
|
package/dist/llm/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/llm/index.ts","../../src/llm/provider.ts","../../src/llm/anthropic.ts","../../src/llm/openai.ts","../../src/llm/ollama.ts"],"sourcesContent":["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';\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';\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 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","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"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/llm/index.ts","../../src/llm/provider.ts","../../src/llm/anthropic.ts","../../src/llm/openai.ts","../../src/llm/ollama.ts","../../src/llm/cluster.ts"],"sourcesContent":["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","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"],"mappings":"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","names":["text"]}
|
package/dist/llm/index.d.cts
CHANGED
|
@@ -50,9 +50,44 @@ declare class OllamaProvider implements Provider {
|
|
|
50
50
|
chat(request: ChatRequest): Promise<ModelResponse>;
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
+
interface ClusterSlot {
|
|
54
|
+
model: string;
|
|
55
|
+
role: "planner" | "worker" | "reviewer" | "drafter";
|
|
56
|
+
baseURL?: string;
|
|
57
|
+
maxTokens?: number;
|
|
58
|
+
temperature?: number;
|
|
59
|
+
}
|
|
60
|
+
interface ClusterConfig {
|
|
61
|
+
slots: ClusterSlot[];
|
|
62
|
+
baseURL?: string;
|
|
63
|
+
timeoutMs?: number;
|
|
64
|
+
strategy?: "auto" | "draft-verify" | "debate" | "majority" | "single";
|
|
65
|
+
draftCount?: number;
|
|
66
|
+
debateRounds?: number;
|
|
67
|
+
}
|
|
68
|
+
declare class ClusterProvider implements Provider {
|
|
69
|
+
readonly model: string;
|
|
70
|
+
private config;
|
|
71
|
+
private stats;
|
|
72
|
+
constructor(config?: Partial<ClusterConfig>);
|
|
73
|
+
getStats(): {
|
|
74
|
+
calls: number;
|
|
75
|
+
tokensIn: number;
|
|
76
|
+
tokensOut: number;
|
|
77
|
+
byModel: Record<string, number>;
|
|
78
|
+
};
|
|
79
|
+
chat(request: ChatRequest): Promise<ModelResponse>;
|
|
80
|
+
private speculative;
|
|
81
|
+
private draftVerify;
|
|
82
|
+
private debate;
|
|
83
|
+
private safeCall;
|
|
84
|
+
private fallback;
|
|
85
|
+
}
|
|
86
|
+
|
|
53
87
|
declare function anthropic(config: AnthropicProviderConfig): AnthropicProvider;
|
|
54
88
|
declare function openai(config: OpenAIProviderConfig): OpenAIProvider;
|
|
55
89
|
declare function ollama(config: OllamaProviderConfig): OllamaProvider;
|
|
90
|
+
declare function cluster(config?: Partial<ClusterConfig>): ClusterProvider;
|
|
56
91
|
interface CustomProviderConfig {
|
|
57
92
|
provider: 'custom';
|
|
58
93
|
model: string;
|
|
@@ -67,4 +102,4 @@ declare function createProvider(config: (AnthropicProviderConfig & {
|
|
|
67
102
|
provider: 'openai';
|
|
68
103
|
}) | OllamaProviderConfigWithProvider | CustomProviderConfig): Provider;
|
|
69
104
|
|
|
70
|
-
export { APIToolDefinition, AnthropicProvider, type AnthropicProviderConfig, BaseProvider, ChatMessage, ChatRequest, type CustomProviderConfig, OllamaProvider, type OllamaProviderConfig, type OllamaProviderConfigWithProvider, OpenAIProvider, type OpenAIProviderConfig, Provider, anthropic, createProvider, ollama, openai };
|
|
105
|
+
export { APIToolDefinition, AnthropicProvider, type AnthropicProviderConfig, BaseProvider, ChatMessage, ChatRequest, type ClusterConfig, ClusterProvider, type ClusterSlot, type CustomProviderConfig, OllamaProvider, type OllamaProviderConfig, type OllamaProviderConfigWithProvider, OpenAIProvider, type OpenAIProviderConfig, Provider, anthropic, cluster, createProvider, ollama, openai };
|