pi-provider-litellm 2.0.2 → 2.0.3
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/discover.js +2 -0
- package/dist/index.js +85 -1
- package/package.json +1 -1
package/dist/discover.js
CHANGED
|
@@ -85,6 +85,8 @@ function catalogLookupIds(id) {
|
|
|
85
85
|
const match = /^(?:claude-)?(opus|sonnet|haiku)-(\d+)-(\d+)$/.exec(anthropicAlias);
|
|
86
86
|
if (match)
|
|
87
87
|
lookupIds.add(`claude-${match[1]}-${match[2]}-${match[3]}`);
|
|
88
|
+
if (anthropicAlias === "fable-5")
|
|
89
|
+
lookupIds.add("claude-fable-5");
|
|
88
90
|
return [...lookupIds];
|
|
89
91
|
}
|
|
90
92
|
function findCatalogModelInProvider(provider, lookupIds) {
|
package/dist/index.js
CHANGED
|
@@ -3,7 +3,7 @@ import { readFile } from "node:fs/promises";
|
|
|
3
3
|
import { join } from "node:path";
|
|
4
4
|
import { getAgentDir } from "@earendil-works/pi-coding-agent";
|
|
5
5
|
import { setupLiteLLMCostTracking } from "./cost.js";
|
|
6
|
-
import { discoverModels, isGpt55Model, normalizeBaseUrl, shouldSuppressReasoningContent } from "./discover.js";
|
|
6
|
+
import { discoverModels, isGpt55Model, isMoonshotModel, normalizeBaseUrl, shouldSuppressReasoningContent, } from "./discover.js";
|
|
7
7
|
import { getGcloudToken, getGcloudTokenCacheKey, getGcloudTokenCommand, isGcloudTokenAuthEnabled, } from "./gcloud-token.js";
|
|
8
8
|
import { getSessionIdFromFile } from "./litellm.js";
|
|
9
9
|
import { createMcpToolDefinitions } from "./mcp-tools.js";
|
|
@@ -579,6 +579,56 @@ function createProviderAuth(definition) {
|
|
|
579
579
|
function isReasoningItem(item) {
|
|
580
580
|
return typeof item === "object" && item !== null && item.type === "reasoning";
|
|
581
581
|
}
|
|
582
|
+
// Returns the original array reference when no normalization is needed.
|
|
583
|
+
function normalizeStrictToolMessages(messages) {
|
|
584
|
+
const normalized = [];
|
|
585
|
+
let imageParts = [];
|
|
586
|
+
let changed = false;
|
|
587
|
+
const flushImages = () => {
|
|
588
|
+
if (imageParts.length === 0)
|
|
589
|
+
return;
|
|
590
|
+
normalized.push({
|
|
591
|
+
role: "user",
|
|
592
|
+
content: [{ type: "text", text: "Attached image(s) from tool result:" }, ...imageParts],
|
|
593
|
+
});
|
|
594
|
+
imageParts = [];
|
|
595
|
+
};
|
|
596
|
+
for (const message of messages) {
|
|
597
|
+
if (message.role !== "tool")
|
|
598
|
+
flushImages();
|
|
599
|
+
if (message.role === "assistant" &&
|
|
600
|
+
Array.isArray(message.tool_calls) &&
|
|
601
|
+
message.tool_calls.length > 0 &&
|
|
602
|
+
message.content == null) {
|
|
603
|
+
normalized.push({ ...message, content: "" });
|
|
604
|
+
changed = true;
|
|
605
|
+
}
|
|
606
|
+
else if (message.role === "tool" && Array.isArray(message.content)) {
|
|
607
|
+
const previousImageCount = imageParts.length;
|
|
608
|
+
const content = message.content
|
|
609
|
+
.map((part) => {
|
|
610
|
+
if (typeof part === "string")
|
|
611
|
+
return part;
|
|
612
|
+
if (part?.type === "text")
|
|
613
|
+
return part.text || "";
|
|
614
|
+
if (part?.type === "image_url")
|
|
615
|
+
imageParts.push(part);
|
|
616
|
+
return "";
|
|
617
|
+
})
|
|
618
|
+
.join("");
|
|
619
|
+
normalized.push({
|
|
620
|
+
...message,
|
|
621
|
+
content: content || (imageParts.length > previousImageCount ? "(see attached image)" : "(no tool output)"),
|
|
622
|
+
});
|
|
623
|
+
changed = true;
|
|
624
|
+
}
|
|
625
|
+
else {
|
|
626
|
+
normalized.push(message);
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
flushImages();
|
|
630
|
+
return changed ? normalized : messages;
|
|
631
|
+
}
|
|
582
632
|
// Reasoning fields LiteLLM forwards to chat-completions providers. The Moonshot
|
|
583
633
|
// path defaults them off; the gpt-5.5 tool path strips them entirely.
|
|
584
634
|
const REASONING_SUPPRESSION_DEFAULTS = {
|
|
@@ -587,6 +637,7 @@ const REASONING_SUPPRESSION_DEFAULTS = {
|
|
|
587
637
|
merge_reasoning_content_in_choices: true,
|
|
588
638
|
thinking: { type: "disabled" },
|
|
589
639
|
};
|
|
640
|
+
const GEMINI_MODEL_PATTERN = /(?:^|[-_/.:])gemini(?=$|[-_/.:])/i;
|
|
590
641
|
function prepareLiteLLMRequestPayload(payload, modelId, api, sessionId) {
|
|
591
642
|
let next;
|
|
592
643
|
const update = (key, value) => {
|
|
@@ -632,6 +683,39 @@ function prepareLiteLLMRequestPayload(payload, modelId, api, sessionId) {
|
|
|
632
683
|
next.input = input.filter((item) => !isReasoningItem(item));
|
|
633
684
|
}
|
|
634
685
|
}
|
|
686
|
+
// Moonshot/Kimi applies strict OpenAI schema validation: assistant tool calls
|
|
687
|
+
// must carry string content, and tool results must be plain text.
|
|
688
|
+
if (modelId && isMoonshotModel(modelId)) {
|
|
689
|
+
const messages = (next ?? payload).messages;
|
|
690
|
+
if (Array.isArray(messages)) {
|
|
691
|
+
const normalized = normalizeStrictToolMessages(messages);
|
|
692
|
+
if (normalized !== messages) {
|
|
693
|
+
next ??= { ...payload };
|
|
694
|
+
next.messages = normalized;
|
|
695
|
+
}
|
|
696
|
+
}
|
|
697
|
+
}
|
|
698
|
+
if (modelId && GEMINI_MODEL_PATTERN.test(modelId)) {
|
|
699
|
+
const currentPayload = next ?? payload;
|
|
700
|
+
if (typeof currentPayload.reasoning_effort === "string") {
|
|
701
|
+
const lower = currentPayload.reasoning_effort.toLowerCase();
|
|
702
|
+
if (currentPayload.reasoning_effort !== lower) {
|
|
703
|
+
next ??= { ...payload };
|
|
704
|
+
next.reasoning_effort = lower;
|
|
705
|
+
}
|
|
706
|
+
}
|
|
707
|
+
const reasoningPayload = next ?? payload;
|
|
708
|
+
if (isPlainObject(reasoningPayload.reasoning) && typeof reasoningPayload.reasoning.effort === "string") {
|
|
709
|
+
const lower = reasoningPayload.reasoning.effort.toLowerCase();
|
|
710
|
+
if (reasoningPayload.reasoning.effort !== lower) {
|
|
711
|
+
next ??= { ...payload };
|
|
712
|
+
next.reasoning = {
|
|
713
|
+
...next.reasoning,
|
|
714
|
+
effort: lower,
|
|
715
|
+
};
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
}
|
|
635
719
|
if (sessionId) {
|
|
636
720
|
next ??= { ...payload };
|
|
637
721
|
next.litellm_session_id = sessionId;
|