@absolutejs/ai 0.2.3 → 0.2.4
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/CHANGELOG.md +6 -0
- package/changelog.json +21 -0
- package/dist/ai/index.js +154 -15
- package/dist/ai/index.js.map +8 -7
- package/dist/ai/models/index.js +70 -2
- package/dist/ai/models/index.js.map +5 -4
- package/dist/ai/providers/anthropic.js +111 -5
- package/dist/ai/providers/anthropic.js.map +6 -5
- package/dist/ai/providers/gemini.js +210 -3
- package/dist/ai/providers/gemini.js.map +6 -4
- package/dist/ai/providers/openai.js +144 -10
- package/dist/ai/providers/openai.js.map +6 -5
- package/dist/ai/providers/openaiCompatible.js +146 -12
- package/dist/ai/providers/openaiCompatible.js.map +6 -5
- package/dist/ai/providers/openaiResponses.js +108 -4
- package/dist/ai/providers/openaiResponses.js.map +5 -4
- package/dist/ai/providers/openrouter.js +147 -11
- package/dist/ai/providers/openrouter.js.map +7 -6
- package/dist/src/ai/models/index.d.ts +1 -0
- package/dist/src/ai/models/reasoning.d.ts +15 -0
- package/dist/src/ai/providers/reasoning.d.ts +3 -0
- package/dist/types/ai.d.ts +1 -1
- package/package.json +1 -1
|
@@ -582,17 +582,70 @@ async function* tapStream(source, params, providerName) {
|
|
|
582
582
|
}
|
|
583
583
|
}
|
|
584
584
|
|
|
585
|
+
// src/ai/models/reasoning.ts
|
|
586
|
+
var profile = (kind, efforts, description, source) => ({ kind, efforts, description, source });
|
|
587
|
+
var claude = profile("effort", ["low", "medium", "high", "xhigh", "max"], "More thinking for harder problems; higher settings can take longer and use more credits.", "https://platform.claude.com/docs/en/build-with-claude/effort");
|
|
588
|
+
var claude46 = {
|
|
589
|
+
...claude,
|
|
590
|
+
efforts: ["low", "medium", "high", "max"]
|
|
591
|
+
};
|
|
592
|
+
var haiku = profile("budget", ["none", "low", "medium", "high"], "Thinking-token budget: Low 2,048; Medium 8,192; High 16,384. Actual usage can be lower.", "https://platform.claude.com/docs/en/build-with-claude/extended-thinking");
|
|
593
|
+
var gpt = profile("effort", ["none", "low", "medium", "high", "xhigh", "max"], claude.description, "https://developers.openai.com/api/docs/models/gpt-5.6-sol");
|
|
594
|
+
var gemini = profile("effort", ["low", "medium", "high"], claude.description, "https://ai.google.dev/gemini-api/docs/openai");
|
|
595
|
+
var deepseek = profile("effort", ["none", "low", "high", "max"], claude.description, "https://api-docs.deepseek.com/guides/thinking_mode/");
|
|
596
|
+
var mistral = profile("effort", ["none", "high"], "Minimal thinking or full reasoning. This model does not offer intermediate effort levels.", "https://docs.mistral.ai/studio/conversations/reasoning");
|
|
597
|
+
var qwen = profile("budget", ["none", "low", "medium", "high"], haiku.description, "https://help.aliyun.com/en/model-studio/deep-thinking");
|
|
598
|
+
var MODEL_REASONING = {
|
|
599
|
+
"anthropic:claude-fable-5-1": claude,
|
|
600
|
+
"anthropic:claude-opus-5": claude,
|
|
601
|
+
"anthropic:claude-sonnet-5": claude,
|
|
602
|
+
"anthropic:claude-sonnet-4-6": claude46,
|
|
603
|
+
"anthropic:claude-opus-4-6": claude46,
|
|
604
|
+
"anthropic:claude-haiku-4-5": haiku,
|
|
605
|
+
"openai:gpt-6-astra": {
|
|
606
|
+
...gpt,
|
|
607
|
+
efforts: ["low", "medium", "high", "xhigh", "max"],
|
|
608
|
+
source: "https://developers.openai.com/api/docs/models/gpt-6-astra"
|
|
609
|
+
},
|
|
610
|
+
"openai:gpt-5.6-sol": gpt,
|
|
611
|
+
"openai:gpt-5.6-terra": gpt,
|
|
612
|
+
"openai:gpt-5.6-luna": gpt,
|
|
613
|
+
"google:gemini-3.8-flash": gemini,
|
|
614
|
+
"google:gemini-3.1-pro-preview": gemini,
|
|
615
|
+
"google:gemini-2.5-flash": profile("budget", ["none", "low", "medium", "high"], "Thinking-token budget: Low 1,024; Medium 8,192; High 24,576.", gemini.source),
|
|
616
|
+
"xai:grok-4.6": profile("effort", ["low", "medium", "high", "xhigh"], "Always reasons. Choose how much thinking it should do.", "https://docs.x.ai/developers/model-capabilities/text/reasoning"),
|
|
617
|
+
"deepseek:deepseek-flash": deepseek,
|
|
618
|
+
"deepseek:deepseek-v4-pro": deepseek,
|
|
619
|
+
"mistral:mistral-medium-3-5": mistral,
|
|
620
|
+
"mistral:mistral-small-latest": mistral,
|
|
621
|
+
"alibaba:qwen3.8-max": qwen,
|
|
622
|
+
"alibaba:qwen3.7-plus": qwen,
|
|
623
|
+
"moonshot:kimi-k3": profile("effort", ["low", "high", "max"], "Always reasons. Choose how much thinking it should do.", "https://platform.kimi.ai/docs/guide/kimi-k3-quickstart"),
|
|
624
|
+
"moonshot:kimi-k2.7-code": profile("fixed", [], "Thinking is always enabled; this model has no documented adjustable effort control.", "https://www.kimi.ai/resources/kimi-k2-7-code")
|
|
625
|
+
};
|
|
626
|
+
var getModelReasoning = (provider, model) => MODEL_REASONING[`${provider}:${model}`];
|
|
627
|
+
|
|
585
628
|
// src/ai/providers/reasoning.ts
|
|
586
629
|
var EFFORT_ORDER = [
|
|
630
|
+
"none",
|
|
587
631
|
"minimal",
|
|
588
632
|
"low",
|
|
589
633
|
"medium",
|
|
590
634
|
"high",
|
|
635
|
+
"xhigh",
|
|
591
636
|
"max"
|
|
592
637
|
];
|
|
593
|
-
var ANTHROPIC_EFFORT = [
|
|
638
|
+
var ANTHROPIC_EFFORT = [
|
|
639
|
+
/opus-4-[5-8]/,
|
|
640
|
+
/sonnet-4-6/,
|
|
641
|
+
/fable-5/,
|
|
642
|
+
/mythos-5/,
|
|
643
|
+
/opus-5/,
|
|
644
|
+
/sonnet-5/
|
|
645
|
+
];
|
|
594
646
|
var ANTHROPIC_ADAPTIVE_ONLY = [];
|
|
595
647
|
var ANTHROPIC_LEGACY_THINKING = [
|
|
648
|
+
/haiku-4-5/,
|
|
596
649
|
/sonnet-4-5/,
|
|
597
650
|
/sonnet-4-0/,
|
|
598
651
|
/sonnet-4-2025/,
|
|
@@ -601,14 +654,20 @@ var ANTHROPIC_LEGACY_THINKING = [
|
|
|
601
654
|
/opus-4-2025/,
|
|
602
655
|
/3-7-sonnet/
|
|
603
656
|
];
|
|
604
|
-
var ANTHROPIC_NO_SAMPLING = [
|
|
657
|
+
var ANTHROPIC_NO_SAMPLING = [
|
|
658
|
+
/opus-4-[78]/,
|
|
659
|
+
/fable-5/,
|
|
660
|
+
/mythos-5/,
|
|
661
|
+
/opus-5/,
|
|
662
|
+
/sonnet-5/
|
|
663
|
+
];
|
|
605
664
|
var ANTHROPIC_MAX_EFFORT = [
|
|
606
665
|
/opus-4-[678]/,
|
|
607
666
|
/sonnet-4-6/,
|
|
608
667
|
/fable-5/,
|
|
609
668
|
/mythos-5/
|
|
610
669
|
];
|
|
611
|
-
var OPENAI_REASONING = [/(^|[^a-z])o[1345](-|$)/, /gpt-
|
|
670
|
+
var OPENAI_REASONING = [/(^|[^a-z])o[1345](-|$)/, /gpt-[56]/];
|
|
612
671
|
var OPENAI_MINIMAL_EFFORT = [/gpt-5/];
|
|
613
672
|
var matches = (model, patterns) => patterns.some((pattern) => pattern.test(model));
|
|
614
673
|
var anthropicReasoningMode = (model) => {
|
|
@@ -623,6 +682,8 @@ var anthropicReasoningMode = (model) => {
|
|
|
623
682
|
var anthropicSupportsSampling = (model) => !matches(model, ANTHROPIC_NO_SAMPLING);
|
|
624
683
|
var isOpenAIReasoningModel = (model) => matches(model, OPENAI_REASONING);
|
|
625
684
|
var EFFORT_BUDGET = {
|
|
685
|
+
none: 0,
|
|
686
|
+
xhigh: 24576,
|
|
626
687
|
high: 16384,
|
|
627
688
|
low: 2048,
|
|
628
689
|
max: 32768,
|
|
@@ -668,6 +729,9 @@ var anthropicEffortValue = (model, reasoning) => {
|
|
|
668
729
|
const effort = resolveEffort(reasoning);
|
|
669
730
|
if (!effort)
|
|
670
731
|
return null;
|
|
732
|
+
const known = getModelReasoning("anthropic", model);
|
|
733
|
+
if (known?.kind === "effort")
|
|
734
|
+
return clampEffort(effort, [...known.efforts]);
|
|
671
735
|
const allowed = matches(model, ANTHROPIC_MAX_EFFORT) ? ["low", "medium", "high", "max"] : ["low", "medium", "high"];
|
|
672
736
|
return clampEffort(effort, allowed);
|
|
673
737
|
};
|
|
@@ -677,10 +741,50 @@ var openaiEffortValue = (model, reasoning) => {
|
|
|
677
741
|
const effort = resolveEffort(reasoning);
|
|
678
742
|
if (!effort)
|
|
679
743
|
return null;
|
|
744
|
+
const known = getModelReasoning("openai", model);
|
|
745
|
+
if (known)
|
|
746
|
+
return clampEffort(effort, [...known.efforts]);
|
|
680
747
|
const allowed = matches(model, OPENAI_MINIMAL_EFFORT) ? ["minimal", "low", "medium", "high"] : ["low", "medium", "high"];
|
|
681
748
|
const requested = effort === "max" ? "high" : effort;
|
|
682
749
|
return clampEffort(requested, allowed);
|
|
683
750
|
};
|
|
751
|
+
var compatibleReasoningBody = (provider, model, reasoning) => {
|
|
752
|
+
if (!reasoning)
|
|
753
|
+
return {};
|
|
754
|
+
const known = getModelReasoning(provider, model);
|
|
755
|
+
const effort = resolveEffort(reasoning);
|
|
756
|
+
if (!known || !effort)
|
|
757
|
+
return {};
|
|
758
|
+
if (!known.efforts.includes(effort))
|
|
759
|
+
throw new Error(`Unsupported reasoning effort ${effort} for ${provider}:${model}`);
|
|
760
|
+
if (provider === "alibaba")
|
|
761
|
+
return effort === "none" ? { enable_thinking: false } : {
|
|
762
|
+
enable_thinking: true,
|
|
763
|
+
thinking_budget: resolveBudgetTokens(reasoning)
|
|
764
|
+
};
|
|
765
|
+
if (provider === "deepseek")
|
|
766
|
+
return effort === "none" ? { thinking: { type: "disabled" } } : { thinking: { type: "enabled" }, reasoning_effort: effort };
|
|
767
|
+
return { reasoning_effort: effort };
|
|
768
|
+
};
|
|
769
|
+
var geminiThinkingConfig = (model, reasoning) => {
|
|
770
|
+
if (!reasoning)
|
|
771
|
+
return;
|
|
772
|
+
const profile2 = getModelReasoning("google", model);
|
|
773
|
+
const effort = resolveEffort(reasoning);
|
|
774
|
+
if (!profile2 || !effort)
|
|
775
|
+
return;
|
|
776
|
+
if (!profile2.efforts.includes(effort))
|
|
777
|
+
throw new Error(`Unsupported reasoning effort ${effort} for ${model}`);
|
|
778
|
+
if (profile2.kind === "effort")
|
|
779
|
+
return { thinkingLevel: effort };
|
|
780
|
+
const budgets = {
|
|
781
|
+
none: 0,
|
|
782
|
+
low: 1024,
|
|
783
|
+
medium: 8192,
|
|
784
|
+
high: 24576
|
|
785
|
+
};
|
|
786
|
+
return { thinkingBudget: reasoning.budgetTokens ?? budgets[effort] };
|
|
787
|
+
};
|
|
684
788
|
|
|
685
789
|
// src/ai/providers/openaiResponses.ts
|
|
686
790
|
var h2IfHttps = (url) => url.startsWith("https://") ? { protocol: "http2" } : {};
|
|
@@ -1314,15 +1418,28 @@ var mapOpenAIContent = (msg) => {
|
|
|
1314
1418
|
}
|
|
1315
1419
|
const hasMedia = msg.content.some((block) => block.type === "image" || block.type === "document" || block.type === "audio" || block.type === "video");
|
|
1316
1420
|
if (!hasMedia) {
|
|
1317
|
-
return null;
|
|
1421
|
+
return msg.content.filter((block) => block.type === "text").map((block) => block.content).join("") || null;
|
|
1318
1422
|
}
|
|
1319
1423
|
return msg.content.map(mapContentBlockToOpenAI).filter((mapped) => mapped !== null);
|
|
1320
1424
|
};
|
|
1321
|
-
var buildRequestBody = (params, capabilityModel = params.model) => {
|
|
1425
|
+
var buildRequestBody = (params, capabilityModel = params.model, providerName = "openai") => {
|
|
1322
1426
|
const messages = params.messages.flatMap((msg) => {
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1427
|
+
const mapped = hasArrayContent(msg) && msg.content.some((block) => block.type === "tool_use" || block.type === "tool_result") ? buildToolMessages(msg.content) : [{ content: mapOpenAIContent(msg), role: msg.role }];
|
|
1428
|
+
if (hasArrayContent(msg) && msg.role === "assistant") {
|
|
1429
|
+
const assistant = mapped.find((message) => message.role === "assistant");
|
|
1430
|
+
if (assistant) {
|
|
1431
|
+
assistant.content = mapOpenAIContent(msg);
|
|
1432
|
+
const thinking = msg.content.filter((block) => block.type === "thinking").map((block) => block.thinking).join("");
|
|
1433
|
+
if (thinking && ["deepseek", "moonshot", "alibaba"].includes(providerName))
|
|
1434
|
+
assistant.reasoning_content = thinking;
|
|
1435
|
+
if (thinking && providerName === "mistral")
|
|
1436
|
+
assistant.content = [
|
|
1437
|
+
{ type: "thinking", thinking: [{ type: "text", text: thinking }] },
|
|
1438
|
+
...typeof assistant.content === "string" && assistant.content ? [{ type: "text", text: assistant.content }] : []
|
|
1439
|
+
];
|
|
1440
|
+
}
|
|
1441
|
+
}
|
|
1442
|
+
return mapped;
|
|
1326
1443
|
});
|
|
1327
1444
|
if (params.systemPrompt) {
|
|
1328
1445
|
messages.unshift({ content: params.systemPrompt, role: "system" });
|
|
@@ -1365,6 +1482,8 @@ var buildRequestBody = (params, capabilityModel = params.model) => {
|
|
|
1365
1482
|
if (typeof params.maxTokens === "number")
|
|
1366
1483
|
body.max_tokens = params.maxTokens;
|
|
1367
1484
|
}
|
|
1485
|
+
if (providerName !== "openai")
|
|
1486
|
+
Object.assign(body, compatibleReasoningBody(providerName, params.model, params.reasoning));
|
|
1368
1487
|
if (params.stopSequences && params.stopSequences.length > 0)
|
|
1369
1488
|
body.stop = params.stopSequences;
|
|
1370
1489
|
if (typeof params.seed === "number")
|
|
@@ -1468,6 +1587,21 @@ var processToolCallDeltas = (toolCalls, pendingToolCalls) => {
|
|
|
1468
1587
|
}
|
|
1469
1588
|
};
|
|
1470
1589
|
var processDelta = function* (delta, pendingToolCalls) {
|
|
1590
|
+
if (typeof delta.reasoning_content === "string")
|
|
1591
|
+
yield { type: "thinking", content: delta.reasoning_content };
|
|
1592
|
+
if (Array.isArray(delta.content)) {
|
|
1593
|
+
for (const part of delta.content) {
|
|
1594
|
+
if (!isRecord2(part))
|
|
1595
|
+
continue;
|
|
1596
|
+
if (part.type === "text" && typeof part.text === "string")
|
|
1597
|
+
yield { type: "text", content: part.text };
|
|
1598
|
+
if (part.type === "thinking" && Array.isArray(part.thinking)) {
|
|
1599
|
+
for (const thought of part.thinking)
|
|
1600
|
+
if (isRecord2(thought) && typeof thought.text === "string")
|
|
1601
|
+
yield { type: "thinking", content: thought.text };
|
|
1602
|
+
}
|
|
1603
|
+
}
|
|
1604
|
+
}
|
|
1471
1605
|
if (typeof delta.content === "string") {
|
|
1472
1606
|
yield { content: delta.content, type: "text" };
|
|
1473
1607
|
}
|
|
@@ -1730,7 +1864,7 @@ var openai = (config2) => {
|
|
|
1730
1864
|
body: (params) => buildResponsesRequestBody(params, false, config2.modelForCapabilities?.(params.model) ?? params.model)
|
|
1731
1865
|
}),
|
|
1732
1866
|
stream: (params) => {
|
|
1733
|
-
const openaiBody = buildRequestBody(params, config2.modelForCapabilities?.(params.model) ?? params.model);
|
|
1867
|
+
const openaiBody = buildRequestBody(params, config2.modelForCapabilities?.(params.model) ?? params.model, providerName);
|
|
1734
1868
|
const body = config2.transformRequestBody ? config2.transformRequestBody(openaiBody, params) : openaiBody;
|
|
1735
1869
|
return async function* () {
|
|
1736
1870
|
const [apiKey, headers] = await Promise.all([
|
|
@@ -1746,5 +1880,5 @@ export {
|
|
|
1746
1880
|
openai
|
|
1747
1881
|
};
|
|
1748
1882
|
|
|
1749
|
-
//# debugId=
|
|
1883
|
+
//# debugId=298140ED666CAD9C64756E2164756E21
|
|
1750
1884
|
//# sourceMappingURL=openai.js.map
|