@kenkaiiii/gg-ai 5.68.0 → 5.69.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +356 -25
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +85 -2
- package/dist/index.d.ts +85 -2
- package/dist/index.js +351 -24
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -35,14 +35,17 @@ __export(index_exports, {
|
|
|
35
35
|
ProviderError: () => ProviderError,
|
|
36
36
|
REDACTION_MARKER: () => REDACTED,
|
|
37
37
|
StreamResult: () => StreamResult,
|
|
38
|
+
TOOL_CALL_NAME_RULES: () => TOOL_CALL_NAME_RULES,
|
|
38
39
|
clampProviderContextImages: () => clampProviderContextImages,
|
|
39
40
|
classifyProviderError: () => classifyProviderError,
|
|
41
|
+
dropInvalidToolCalls: () => dropInvalidToolCalls,
|
|
40
42
|
environmentSecrets: () => environmentSecrets,
|
|
41
43
|
formatError: () => formatError,
|
|
42
44
|
formatErrorForDisplay: () => formatErrorForDisplay,
|
|
43
45
|
hasLoneSurrogate: () => hasLoneSurrogate,
|
|
44
46
|
isHardBillingMessage: () => isHardBillingMessage,
|
|
45
47
|
isUsageLimitError: () => isUsageLimitError,
|
|
48
|
+
isValidToolCallName: () => isValidToolCallName,
|
|
46
49
|
localWireModelId: () => localWireModelId,
|
|
47
50
|
palsuAssistantMessage: () => palsuAssistantMessage,
|
|
48
51
|
palsuText: () => palsuText,
|
|
@@ -61,7 +64,8 @@ __export(index_exports, {
|
|
|
61
64
|
stream: () => stream,
|
|
62
65
|
toAnthropicMessages: () => toAnthropicMessages,
|
|
63
66
|
toOpenAIMessages: () => toOpenAIMessages,
|
|
64
|
-
toWellFormedText: () => toWellFormedText
|
|
67
|
+
toWellFormedText: () => toWellFormedText,
|
|
68
|
+
toolCallNameRuleFor: () => toolCallNameRuleFor
|
|
65
69
|
});
|
|
66
70
|
module.exports = __toCommonJS(index_exports);
|
|
67
71
|
|
|
@@ -515,7 +519,11 @@ function zodToJsonSchema(schema) {
|
|
|
515
519
|
return normalized;
|
|
516
520
|
}
|
|
517
521
|
function resolveToolSchema(tool) {
|
|
518
|
-
|
|
522
|
+
const schema = tool.rawInputSchema ?? zodToJsonSchema(tool.parameters);
|
|
523
|
+
if (schema.type === "object" && schema.properties === void 0) {
|
|
524
|
+
return { ...schema, properties: {} };
|
|
525
|
+
}
|
|
526
|
+
return schema;
|
|
519
527
|
}
|
|
520
528
|
function normalizeRootForAnthropic(schema) {
|
|
521
529
|
const branches = schema.oneOf ?? schema.anyOf;
|
|
@@ -722,6 +730,10 @@ var ANTHROPIC_INPUT_BLOCK_TYPES = /* @__PURE__ */ new Set([
|
|
|
722
730
|
"connector_text",
|
|
723
731
|
"container_upload",
|
|
724
732
|
"document",
|
|
733
|
+
// Server-side refusal fallback marker. Only reaches the wire when the request
|
|
734
|
+
// carries the server-side-fallback beta; otherwise applyServerFallbackReplay
|
|
735
|
+
// strips it first (see toAnthropicMessages' `fallbackBlocks` option).
|
|
736
|
+
"fallback",
|
|
725
737
|
"image",
|
|
726
738
|
"mid_conv_system",
|
|
727
739
|
"redacted_thinking",
|
|
@@ -743,6 +755,42 @@ function isPositionSensitiveThinking(part) {
|
|
|
743
755
|
if (part.type === "thinking") return hasValidThinkingSignature(part);
|
|
744
756
|
return isRawThinking(part);
|
|
745
757
|
}
|
|
758
|
+
function isServerFallbackBlock(part) {
|
|
759
|
+
return part.type === "raw" && part.data.type === "fallback";
|
|
760
|
+
}
|
|
761
|
+
function applyServerFallbackReplay(content, keepMarkers, droppedToolCallIds) {
|
|
762
|
+
let lastFallbackIdx = -1;
|
|
763
|
+
content.forEach((part, idx) => {
|
|
764
|
+
if (isServerFallbackBlock(part)) lastFallbackIdx = idx;
|
|
765
|
+
});
|
|
766
|
+
if (lastFallbackIdx === -1) return content;
|
|
767
|
+
const resultIds = /* @__PURE__ */ new Set();
|
|
768
|
+
for (const part of content) {
|
|
769
|
+
if (part.type === "server_tool_result") resultIds.add(part.toolUseId);
|
|
770
|
+
else if (part.type === "raw" && typeof part.data.tool_use_id === "string")
|
|
771
|
+
resultIds.add(part.data.tool_use_id);
|
|
772
|
+
}
|
|
773
|
+
const out = [];
|
|
774
|
+
content.forEach((part, idx) => {
|
|
775
|
+
if (isServerFallbackBlock(part)) {
|
|
776
|
+
if (keepMarkers) out.push(part);
|
|
777
|
+
return;
|
|
778
|
+
}
|
|
779
|
+
if (idx < lastFallbackIdx) {
|
|
780
|
+
if (part.type === "thinking" || isRawThinking(part)) return;
|
|
781
|
+
if (part.type === "raw" && part.data.type === "connector_text") return;
|
|
782
|
+
if (part.type === "tool_call") {
|
|
783
|
+
droppedToolCallIds?.add(part.id);
|
|
784
|
+
return;
|
|
785
|
+
}
|
|
786
|
+
if (part.type === "server_tool_call" && !resultIds.has(part.id)) return;
|
|
787
|
+
if (part.type === "raw" && part.data.type === "server_tool_use" && !resultIds.has(String(part.data.id)))
|
|
788
|
+
return;
|
|
789
|
+
}
|
|
790
|
+
out.push(part);
|
|
791
|
+
});
|
|
792
|
+
return out.every(isServerFallbackBlock) ? [] : out;
|
|
793
|
+
}
|
|
746
794
|
function toAnthropicAssistantPart(part, idMap) {
|
|
747
795
|
if (part.type === "text") return { type: "text", text: part.text };
|
|
748
796
|
if (part.type === "thinking") {
|
|
@@ -810,10 +858,17 @@ function countContextImages(messages) {
|
|
|
810
858
|
}
|
|
811
859
|
return count;
|
|
812
860
|
}
|
|
861
|
+
var IMAGE_DROP_BATCH = 30;
|
|
862
|
+
function providerImageDropCount(imageCount2, budget) {
|
|
863
|
+
const overflow = imageCount2 - budget;
|
|
864
|
+
if (overflow <= 0) return 0;
|
|
865
|
+
const batch = Math.max(1, Math.min(IMAGE_DROP_BATCH, Math.floor(budget / 3)));
|
|
866
|
+
return Math.min(imageCount2, Math.ceil(overflow / batch) * batch);
|
|
867
|
+
}
|
|
813
868
|
function clampProviderContextImages(messages, provider, supportsImages) {
|
|
814
869
|
if (supportsImages === false) return messages;
|
|
815
870
|
const budget = PROVIDER_IMAGE_BUDGETS[provider] ?? 5;
|
|
816
|
-
let remainingToRemove = countContextImages(messages)
|
|
871
|
+
let remainingToRemove = providerImageDropCount(countContextImages(messages), budget);
|
|
817
872
|
if (remainingToRemove <= 0) return messages;
|
|
818
873
|
return messages.map((message) => {
|
|
819
874
|
if (message.role === "user" && Array.isArray(message.content)) {
|
|
@@ -847,6 +902,144 @@ function clampProviderContextImages(messages, provider, supportsImages) {
|
|
|
847
902
|
return message;
|
|
848
903
|
});
|
|
849
904
|
}
|
|
905
|
+
var TOOL_CALL_NAME_RULES = {
|
|
906
|
+
// Anthropic Messages API: tool / tool_use name `^[a-zA-Z0-9_-]{1,128}$`.
|
|
907
|
+
anthropic: { id: "anthropic", maxLength: 128, pattern: /^[a-zA-Z0-9_-]{1,128}$/ },
|
|
908
|
+
// OpenAI Chat Completions: function name a-z A-Z 0-9 _ -, max length 64.
|
|
909
|
+
"openai-chat": { id: "openai-chat", maxLength: 64, pattern: /^[a-zA-Z0-9_-]{1,64}$/ },
|
|
910
|
+
// OpenAI Responses (Codex): same charset; replayed `input[N].name` over 128
|
|
911
|
+
// chars is rejected with `string_above_max_length`.
|
|
912
|
+
"openai-responses": {
|
|
913
|
+
id: "openai-responses",
|
|
914
|
+
maxLength: 128,
|
|
915
|
+
pattern: /^[a-zA-Z0-9_-]{1,128}$/
|
|
916
|
+
},
|
|
917
|
+
// Gemini FunctionDeclaration name: starts with a letter or underscore, then
|
|
918
|
+
// a-z A-Z 0-9 _ . : -, max length 128.
|
|
919
|
+
gemini: { id: "gemini", maxLength: 128, pattern: /^[a-zA-Z_][a-zA-Z0-9_.:-]{0,127}$/ },
|
|
920
|
+
// OpenAI-compatible third parties (GLM, Kimi, DeepSeek, OpenRouter, xAI,
|
|
921
|
+
// local servers, MiniMax, …) don't share one documented charset, so only
|
|
922
|
+
// reject what no declared tool name can contain: blank, >128 chars, or any
|
|
923
|
+
// whitespace / control character (the signature of invocation text).
|
|
924
|
+
generic: { id: "generic", maxLength: 128 }
|
|
925
|
+
};
|
|
926
|
+
var TOOL_NAME_FORBIDDEN_CHARS = /[\s\p{Cc}]/u;
|
|
927
|
+
function isValidToolCallName(name, rule) {
|
|
928
|
+
if (typeof name !== "string" || name.trim().length === 0) return false;
|
|
929
|
+
if (name.length > rule.maxLength) return false;
|
|
930
|
+
if (TOOL_NAME_FORBIDDEN_CHARS.test(name)) return false;
|
|
931
|
+
return rule.pattern ? rule.pattern.test(name) : true;
|
|
932
|
+
}
|
|
933
|
+
function isDefaultOrHost(baseUrl, host) {
|
|
934
|
+
if (!baseUrl) return true;
|
|
935
|
+
try {
|
|
936
|
+
return new URL(baseUrl).hostname === host;
|
|
937
|
+
} catch {
|
|
938
|
+
return false;
|
|
939
|
+
}
|
|
940
|
+
}
|
|
941
|
+
function toolCallNameRuleFor(provider, options) {
|
|
942
|
+
switch (provider) {
|
|
943
|
+
case "anthropic":
|
|
944
|
+
return TOOL_CALL_NAME_RULES.anthropic;
|
|
945
|
+
case "openai":
|
|
946
|
+
if (options?.accountId) return TOOL_CALL_NAME_RULES["openai-responses"];
|
|
947
|
+
return isDefaultOrHost(options?.baseUrl, "api.openai.com") ? TOOL_CALL_NAME_RULES["openai-chat"] : TOOL_CALL_NAME_RULES.generic;
|
|
948
|
+
case "gemini":
|
|
949
|
+
return TOOL_CALL_NAME_RULES.gemini;
|
|
950
|
+
default:
|
|
951
|
+
return TOOL_CALL_NAME_RULES.generic;
|
|
952
|
+
}
|
|
953
|
+
}
|
|
954
|
+
function isValidToolCallId(id) {
|
|
955
|
+
return typeof id === "string" && id.trim().length > 0;
|
|
956
|
+
}
|
|
957
|
+
function isRawReasoning(part) {
|
|
958
|
+
return part.type === "raw" && part.data.type === "reasoning";
|
|
959
|
+
}
|
|
960
|
+
function isDanglingReasoning(parts, idx) {
|
|
961
|
+
for (let i = idx + 1; i < parts.length; i++) {
|
|
962
|
+
const next = parts[i];
|
|
963
|
+
if (isRawReasoning(next)) return true;
|
|
964
|
+
if (next.type === "text" || next.type === "tool_call") return false;
|
|
965
|
+
}
|
|
966
|
+
return true;
|
|
967
|
+
}
|
|
968
|
+
function hasReplayableAssistantContent(parts) {
|
|
969
|
+
return parts.some((part) => {
|
|
970
|
+
if (part.type === "text") return part.text.length > 0;
|
|
971
|
+
if (part.type === "thinking") return false;
|
|
972
|
+
if (part.type === "raw") {
|
|
973
|
+
const t = part.data.type;
|
|
974
|
+
return !(t === "thinking" || t === "redacted_thinking" || t === "reasoning" || t === "fallback");
|
|
975
|
+
}
|
|
976
|
+
return true;
|
|
977
|
+
});
|
|
978
|
+
}
|
|
979
|
+
function dropInvalidToolCalls(messages, rule) {
|
|
980
|
+
const isInvalid = (part) => part.type === "tool_call" && (!isValidToolCallName(part.name, rule) || !isValidToolCallId(part.id));
|
|
981
|
+
const hasInvalid = messages.some(
|
|
982
|
+
(m) => m.role === "assistant" && Array.isArray(m.content) && m.content.some(isInvalid)
|
|
983
|
+
);
|
|
984
|
+
if (!hasInvalid) return messages;
|
|
985
|
+
const out = [];
|
|
986
|
+
let pending = /* @__PURE__ */ new Map();
|
|
987
|
+
let prunedAssistant = null;
|
|
988
|
+
for (const msg of messages) {
|
|
989
|
+
if (msg.role === "user" || msg.role === "system") {
|
|
990
|
+
if (msg.role === "user") pending = /* @__PURE__ */ new Map();
|
|
991
|
+
out.push(msg);
|
|
992
|
+
continue;
|
|
993
|
+
}
|
|
994
|
+
if (msg.role === "assistant") {
|
|
995
|
+
pending = /* @__PURE__ */ new Map();
|
|
996
|
+
if (typeof msg.content === "string") {
|
|
997
|
+
out.push(msg);
|
|
998
|
+
continue;
|
|
999
|
+
}
|
|
1000
|
+
const original = msg.content;
|
|
1001
|
+
let dropped = false;
|
|
1002
|
+
const kept = [];
|
|
1003
|
+
for (const part of original) {
|
|
1004
|
+
if (part.type === "tool_call") {
|
|
1005
|
+
const keep = !isInvalid(part);
|
|
1006
|
+
const queue = pending.get(part.id) ?? [];
|
|
1007
|
+
queue.push(keep);
|
|
1008
|
+
pending.set(part.id, queue);
|
|
1009
|
+
if (!keep) {
|
|
1010
|
+
dropped = true;
|
|
1011
|
+
continue;
|
|
1012
|
+
}
|
|
1013
|
+
}
|
|
1014
|
+
kept.push(part);
|
|
1015
|
+
}
|
|
1016
|
+
if (!dropped) {
|
|
1017
|
+
out.push(msg);
|
|
1018
|
+
continue;
|
|
1019
|
+
}
|
|
1020
|
+
const content = kept.filter(
|
|
1021
|
+
(part, idx) => !isRawReasoning(part) || !isDanglingReasoning(kept, idx) || isDanglingReasoning(original, original.indexOf(part))
|
|
1022
|
+
);
|
|
1023
|
+
if (hasReplayableAssistantContent(content)) {
|
|
1024
|
+
const pruned = { ...msg, content };
|
|
1025
|
+
out.push(pruned);
|
|
1026
|
+
prunedAssistant = pruned;
|
|
1027
|
+
}
|
|
1028
|
+
continue;
|
|
1029
|
+
}
|
|
1030
|
+
let changed = false;
|
|
1031
|
+
const results = msg.content.filter((result) => {
|
|
1032
|
+
const queue = pending.get(result.toolCallId);
|
|
1033
|
+
const keep = queue && queue.length > 0 ? queue.shift() : true;
|
|
1034
|
+
if (!keep) changed = true;
|
|
1035
|
+
return keep;
|
|
1036
|
+
});
|
|
1037
|
+
if (!changed) out.push(msg);
|
|
1038
|
+
else if (results.length > 0) out.push({ ...msg, content: results });
|
|
1039
|
+
}
|
|
1040
|
+
if (prunedAssistant && out[out.length - 1] === prunedAssistant) out.pop();
|
|
1041
|
+
return out;
|
|
1042
|
+
}
|
|
850
1043
|
var NON_VISION_USER_IMAGE_PLACEHOLDER = "(image omitted: model does not support images)";
|
|
851
1044
|
var NON_VISION_TOOL_IMAGE_PLACEHOLDER = "(tool image omitted: model does not support images)";
|
|
852
1045
|
var NON_VIDEO_USER_PLACEHOLDER = "(video omitted: model does not support video)";
|
|
@@ -953,10 +1146,12 @@ function remapAnthropicToolCallId(id, idMap) {
|
|
|
953
1146
|
idMap.set(id, mapped);
|
|
954
1147
|
return mapped;
|
|
955
1148
|
}
|
|
956
|
-
function toAnthropicMessages(messages, cacheControl) {
|
|
1149
|
+
function toAnthropicMessages(messages, cacheControl, options) {
|
|
957
1150
|
let systemText;
|
|
958
1151
|
const out = [];
|
|
959
1152
|
const idMap = /* @__PURE__ */ new Map();
|
|
1153
|
+
const keepFallbackBlocks = options?.fallbackBlocks === true;
|
|
1154
|
+
const droppedToolCallIds = /* @__PURE__ */ new Set();
|
|
960
1155
|
const trajectoryStartIdx = messages.reduce(
|
|
961
1156
|
(last, m, i) => m.role === "user" ? i : last,
|
|
962
1157
|
-1
|
|
@@ -1002,17 +1197,23 @@ function toAnthropicMessages(messages, cacheControl) {
|
|
|
1002
1197
|
}
|
|
1003
1198
|
if (msg.role === "assistant") {
|
|
1004
1199
|
if (typeof msg.content === "string" && msg.content === "") continue;
|
|
1005
|
-
const content = typeof msg.content === "string" ? msg.content : toAnthropicAssistantContent(
|
|
1200
|
+
const content = typeof msg.content === "string" ? msg.content : toAnthropicAssistantContent(
|
|
1201
|
+
applyServerFallbackReplay(msg.content, keepFallbackBlocks, droppedToolCallIds),
|
|
1202
|
+
msgIdx > trajectoryStartIdx,
|
|
1203
|
+
idMap
|
|
1204
|
+
);
|
|
1006
1205
|
if (Array.isArray(content) && content.length === 0) continue;
|
|
1007
1206
|
out.push({ role: "assistant", content });
|
|
1008
1207
|
continue;
|
|
1009
1208
|
}
|
|
1010
1209
|
if (msg.role === "tool") {
|
|
1210
|
+
const results = droppedToolCallIds.size ? msg.content.filter((r) => !droppedToolCallIds.has(r.toolCallId)) : msg.content;
|
|
1211
|
+
if (results.length === 0) continue;
|
|
1011
1212
|
out.push({
|
|
1012
1213
|
role: "user",
|
|
1013
1214
|
// Cast covers the video block (used by the Anthropic-compatible MiniMax
|
|
1014
1215
|
// API), which isn't in the first-party Anthropic tool_result types.
|
|
1015
|
-
content:
|
|
1216
|
+
content: results.map((result) => ({
|
|
1016
1217
|
type: "tool_result",
|
|
1017
1218
|
tool_use_id: remapAnthropicToolCallId(result.toolCallId, idMap),
|
|
1018
1219
|
content: toAnthropicToolResultContent(result.content),
|
|
@@ -1352,6 +1553,48 @@ function fineGrainedToolStreamingEnabled() {
|
|
|
1352
1553
|
const v = raw.trim().toLowerCase();
|
|
1353
1554
|
return v === "1" || v === "true" || v === "yes" || v === "on";
|
|
1354
1555
|
}
|
|
1556
|
+
var SERVER_FALLBACK_BETA = "server-side-fallback-2026-07-01";
|
|
1557
|
+
var anthropicServerFallback = {
|
|
1558
|
+
disabled: /* @__PURE__ */ new Set(),
|
|
1559
|
+
reset() {
|
|
1560
|
+
this.disabled.clear();
|
|
1561
|
+
}
|
|
1562
|
+
};
|
|
1563
|
+
function serverFallbackKey(options) {
|
|
1564
|
+
const auth = options.apiKey?.startsWith("sk-ant-oat") ? "oauth" : "key";
|
|
1565
|
+
return `${options.baseUrl ?? process.env.ANTHROPIC_BASE_URL ?? ""}|${auth}`;
|
|
1566
|
+
}
|
|
1567
|
+
function isDirectAnthropicApi(baseUrl) {
|
|
1568
|
+
const effective = baseUrl ?? process.env.ANTHROPIC_BASE_URL;
|
|
1569
|
+
if (!effective) return true;
|
|
1570
|
+
try {
|
|
1571
|
+
const url = new URL(effective);
|
|
1572
|
+
return url.protocol === "https:" && url.hostname === "api.anthropic.com";
|
|
1573
|
+
} catch {
|
|
1574
|
+
return false;
|
|
1575
|
+
}
|
|
1576
|
+
}
|
|
1577
|
+
function isServerFallbackRejection(err) {
|
|
1578
|
+
const status = err?.status;
|
|
1579
|
+
if (status !== 400) return false;
|
|
1580
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
1581
|
+
return /fallbacks|server-side-fallback/i.test(message);
|
|
1582
|
+
}
|
|
1583
|
+
function sumUsageIterations(usage) {
|
|
1584
|
+
const iterations = usage?.iterations;
|
|
1585
|
+
if (!Array.isArray(iterations) || iterations.length === 0) return null;
|
|
1586
|
+
const num = (v) => typeof v === "number" && Number.isFinite(v) ? v : 0;
|
|
1587
|
+
const totals = { inputTokens: 0, outputTokens: 0, cacheRead: 0, cacheWrite: 0 };
|
|
1588
|
+
for (const it of iterations) {
|
|
1589
|
+
if (!it || typeof it !== "object") continue;
|
|
1590
|
+
const rec = it;
|
|
1591
|
+
totals.inputTokens += num(rec.input_tokens);
|
|
1592
|
+
totals.outputTokens += num(rec.output_tokens);
|
|
1593
|
+
totals.cacheRead += num(rec.cache_read_input_tokens);
|
|
1594
|
+
totals.cacheWrite += num(rec.cache_creation_input_tokens);
|
|
1595
|
+
}
|
|
1596
|
+
return totals;
|
|
1597
|
+
}
|
|
1355
1598
|
function createClient(options) {
|
|
1356
1599
|
const isOAuth = options.apiKey?.startsWith("sk-ant-oat");
|
|
1357
1600
|
const userAgent = isOAuth ? options.userAgent ?? "claude-cli/2.1.75 (external, cli)" : "";
|
|
@@ -1448,7 +1691,11 @@ async function* runStream(options) {
|
|
|
1448
1691
|
const supportsFirstPartyToolExtras = !options.baseUrl || options.baseUrl.includes("api.anthropic.com");
|
|
1449
1692
|
const downgradedImages = downgradeUnsupportedImages(options.messages, options.supportsImages);
|
|
1450
1693
|
const downgradedMessages = downgradeUnsupportedVideos(downgradedImages, options.supportsVideo);
|
|
1451
|
-
const
|
|
1694
|
+
const fallbackKey = serverFallbackKey(options);
|
|
1695
|
+
const useServerFallback = options.provider !== "minimax" && isDirectAnthropicApi(options.baseUrl) && !anthropicServerFallback.disabled.has(fallbackKey);
|
|
1696
|
+
const { system: rawSystem, messages } = toAnthropicMessages(downgradedMessages, cacheControl, {
|
|
1697
|
+
fallbackBlocks: useServerFallback
|
|
1698
|
+
});
|
|
1452
1699
|
const system = isOAuth ? [
|
|
1453
1700
|
{
|
|
1454
1701
|
type: "text",
|
|
@@ -1518,6 +1765,7 @@ async function* runStream(options) {
|
|
|
1518
1765
|
];
|
|
1519
1766
|
return contextEdits.length ? { context_management: { edits: contextEdits } } : {};
|
|
1520
1767
|
})(),
|
|
1768
|
+
...useServerFallback ? { fallbacks: "default" } : {},
|
|
1521
1769
|
stream: useStreaming
|
|
1522
1770
|
};
|
|
1523
1771
|
const hasAdaptiveThinking = isAdaptiveThinkingModel(options.model);
|
|
@@ -1534,20 +1782,41 @@ async function* runStream(options) {
|
|
|
1534
1782
|
// it Anthropic silently ignores ttl:"1h" and falls back to the 5-min default,
|
|
1535
1783
|
// so a pre-warmed cache expires before the user's first turn. cacheControl.ttl
|
|
1536
1784
|
// is only "1h" on the first-party endpoint (see toAnthropicCacheControl).
|
|
1537
|
-
...cacheControl?.ttl === "1h" ? ["extended-cache-ttl-2025-04-11"] : []
|
|
1785
|
+
...cacheControl?.ttl === "1h" ? ["extended-cache-ttl-2025-04-11"] : [],
|
|
1786
|
+
...useServerFallback ? [SERVER_FALLBACK_BETA] : []
|
|
1538
1787
|
];
|
|
1539
|
-
const
|
|
1788
|
+
const toRequestOptions = (betas) => ({
|
|
1540
1789
|
signal: options.signal ?? void 0,
|
|
1541
|
-
...
|
|
1790
|
+
...betas.length ? { headers: { "anthropic-beta": betas.join(",") } } : {}
|
|
1791
|
+
});
|
|
1792
|
+
const requestOptions = toRequestOptions(betaHeaders);
|
|
1793
|
+
const send = async (create) => {
|
|
1794
|
+
try {
|
|
1795
|
+
return await create(params, requestOptions);
|
|
1796
|
+
} catch (err) {
|
|
1797
|
+
if (!useServerFallback || !isServerFallbackRejection(err)) throw err;
|
|
1798
|
+
anthropicServerFallback.disabled.add(fallbackKey);
|
|
1799
|
+
const { fallbacks: _dropped, ...rest } = params;
|
|
1800
|
+
const retryParams = {
|
|
1801
|
+
...rest,
|
|
1802
|
+
messages: toAnthropicMessages(downgradedMessages, cacheControl, { fallbackBlocks: false }).messages
|
|
1803
|
+
};
|
|
1804
|
+
return create(
|
|
1805
|
+
retryParams,
|
|
1806
|
+
toRequestOptions(betaHeaders.filter((b) => b !== SERVER_FALLBACK_BETA))
|
|
1807
|
+
);
|
|
1808
|
+
}
|
|
1542
1809
|
};
|
|
1543
1810
|
if (!useStreaming) {
|
|
1544
1811
|
try {
|
|
1545
1812
|
const nonStreamingClient = client.withOptions({
|
|
1546
1813
|
timeout: NON_STREAMING_REQUEST_TIMEOUT_MS
|
|
1547
1814
|
});
|
|
1548
|
-
const message = await
|
|
1549
|
-
|
|
1550
|
-
|
|
1815
|
+
const message = await send(
|
|
1816
|
+
(p, o) => nonStreamingClient.messages.create(
|
|
1817
|
+
{ ...p, stream: false },
|
|
1818
|
+
o
|
|
1819
|
+
)
|
|
1551
1820
|
);
|
|
1552
1821
|
yield* synthesizeEventsFromMessage(message);
|
|
1553
1822
|
return messageToResponse(message);
|
|
@@ -1565,9 +1834,8 @@ async function* runStream(options) {
|
|
|
1565
1834
|
const keepalive = { type: "keepalive" };
|
|
1566
1835
|
let receivedAnyEvent = false;
|
|
1567
1836
|
try {
|
|
1568
|
-
const stream2 = await
|
|
1569
|
-
|
|
1570
|
-
requestOptions
|
|
1837
|
+
const stream2 = await send(
|
|
1838
|
+
(p, o) => client.messages.create(p, o)
|
|
1571
1839
|
);
|
|
1572
1840
|
for await (const event of stream2) {
|
|
1573
1841
|
receivedAnyEvent = true;
|
|
@@ -1745,6 +2013,13 @@ async function* runStream(options) {
|
|
|
1745
2013
|
if (usage?.output_tokens != null) {
|
|
1746
2014
|
outputTokens = usage.output_tokens;
|
|
1747
2015
|
}
|
|
2016
|
+
const totals = sumUsageIterations(usage);
|
|
2017
|
+
if (totals) {
|
|
2018
|
+
inputTokens = totals.inputTokens;
|
|
2019
|
+
outputTokens = totals.outputTokens;
|
|
2020
|
+
cacheRead = totals.cacheRead;
|
|
2021
|
+
cacheWrite = totals.cacheWrite;
|
|
2022
|
+
}
|
|
1748
2023
|
yield keepalive;
|
|
1749
2024
|
break;
|
|
1750
2025
|
}
|
|
@@ -1874,10 +2149,11 @@ function messageToResponse(message) {
|
|
|
1874
2149
|
}
|
|
1875
2150
|
}
|
|
1876
2151
|
const usage = message.usage;
|
|
1877
|
-
const
|
|
1878
|
-
const
|
|
1879
|
-
const
|
|
1880
|
-
const
|
|
2152
|
+
const totals = sumUsageIterations(usage);
|
|
2153
|
+
const inputTokens = totals?.inputTokens ?? usage.input_tokens ?? 0;
|
|
2154
|
+
const outputTokens = totals?.outputTokens ?? usage.output_tokens ?? 0;
|
|
2155
|
+
const cacheRead = totals?.cacheRead ?? usage.cache_read_input_tokens;
|
|
2156
|
+
const cacheWrite = totals?.cacheWrite ?? usage.cache_creation_input_tokens;
|
|
1881
2157
|
return {
|
|
1882
2158
|
message: {
|
|
1883
2159
|
role: "assistant",
|
|
@@ -3908,6 +4184,41 @@ function sanitizeMessagesForWire(messages) {
|
|
|
3908
4184
|
return sanitized ?? messages;
|
|
3909
4185
|
}
|
|
3910
4186
|
|
|
4187
|
+
// src/utils/context-observation.ts
|
|
4188
|
+
function imageCount(message) {
|
|
4189
|
+
if (!message || !Array.isArray(message.content)) return 0;
|
|
4190
|
+
if (message.role === "user")
|
|
4191
|
+
return message.content.filter((part) => part.type === "image").length;
|
|
4192
|
+
if (message.role !== "tool") return 0;
|
|
4193
|
+
return message.content.reduce(
|
|
4194
|
+
(count, result) => count + (Array.isArray(result.content) ? result.content.filter((part) => part.type === "image").length : 0),
|
|
4195
|
+
0
|
|
4196
|
+
);
|
|
4197
|
+
}
|
|
4198
|
+
function observePreparedContext(before, after, tools) {
|
|
4199
|
+
let imagesBefore = 0;
|
|
4200
|
+
let imagesAfter = 0;
|
|
4201
|
+
let firstImageDropMessage = null;
|
|
4202
|
+
for (let index = 0; index < before.length; index++) {
|
|
4203
|
+
const oldCount = imageCount(before[index]);
|
|
4204
|
+
const newCount = imageCount(after[index]);
|
|
4205
|
+
imagesBefore += oldCount;
|
|
4206
|
+
imagesAfter += newCount;
|
|
4207
|
+
if (firstImageDropMessage === null && newCount < oldCount) firstImageDropMessage = index;
|
|
4208
|
+
}
|
|
4209
|
+
return {
|
|
4210
|
+
messages: after,
|
|
4211
|
+
tools: tools.map((tool) => ({
|
|
4212
|
+
name: tool.name,
|
|
4213
|
+
description: tool.description,
|
|
4214
|
+
parameters: resolveToolSchema(tool)
|
|
4215
|
+
})),
|
|
4216
|
+
imagesBefore,
|
|
4217
|
+
imagesAfter,
|
|
4218
|
+
firstImageDropMessage
|
|
4219
|
+
};
|
|
4220
|
+
}
|
|
4221
|
+
|
|
3911
4222
|
// src/stream.ts
|
|
3912
4223
|
var GLM_CODING_BASE_URL = "https://api.z.ai/api/coding/paas/v4";
|
|
3913
4224
|
var KIMI_CODE_USER_AGENT = `kimi-code-cli/${process.env.KIMI_CODE_VERSION ?? "1.0.11"}`;
|
|
@@ -4050,11 +4361,27 @@ function stream(options) {
|
|
|
4050
4361
|
throw new VideoUnsupportedError();
|
|
4051
4362
|
}
|
|
4052
4363
|
const wireMessages = stripMessageProvenance(options.messages);
|
|
4053
|
-
const
|
|
4054
|
-
|
|
4055
|
-
|
|
4056
|
-
options.
|
|
4364
|
+
const sanitized = sanitizeMessagesForWire(wireMessages);
|
|
4365
|
+
const replayable = dropInvalidToolCalls(
|
|
4366
|
+
sanitized,
|
|
4367
|
+
toolCallNameRuleFor(options.provider, {
|
|
4368
|
+
accountId: options.accountId,
|
|
4369
|
+
baseUrl: options.baseUrl
|
|
4370
|
+
})
|
|
4057
4371
|
);
|
|
4372
|
+
const messages = clampProviderContextImages(replayable, options.provider, options.supportsImages);
|
|
4373
|
+
if (options.onContextPrepared) {
|
|
4374
|
+
try {
|
|
4375
|
+
options.onContextPrepared(
|
|
4376
|
+
observePreparedContext(
|
|
4377
|
+
replayable === sanitized ? wireMessages : replayable,
|
|
4378
|
+
messages,
|
|
4379
|
+
options.tools ?? []
|
|
4380
|
+
)
|
|
4381
|
+
);
|
|
4382
|
+
} catch {
|
|
4383
|
+
}
|
|
4384
|
+
}
|
|
4058
4385
|
return entry.stream(messages === options.messages ? options : { ...options, messages });
|
|
4059
4386
|
}
|
|
4060
4387
|
function stripMessageProvenance(messages) {
|
|
@@ -4466,14 +4793,17 @@ function registerPalsuProvider(config) {
|
|
|
4466
4793
|
ProviderError,
|
|
4467
4794
|
REDACTION_MARKER,
|
|
4468
4795
|
StreamResult,
|
|
4796
|
+
TOOL_CALL_NAME_RULES,
|
|
4469
4797
|
clampProviderContextImages,
|
|
4470
4798
|
classifyProviderError,
|
|
4799
|
+
dropInvalidToolCalls,
|
|
4471
4800
|
environmentSecrets,
|
|
4472
4801
|
formatError,
|
|
4473
4802
|
formatErrorForDisplay,
|
|
4474
4803
|
hasLoneSurrogate,
|
|
4475
4804
|
isHardBillingMessage,
|
|
4476
4805
|
isUsageLimitError,
|
|
4806
|
+
isValidToolCallName,
|
|
4477
4807
|
localWireModelId,
|
|
4478
4808
|
palsuAssistantMessage,
|
|
4479
4809
|
palsuText,
|
|
@@ -4492,6 +4822,7 @@ function registerPalsuProvider(config) {
|
|
|
4492
4822
|
stream,
|
|
4493
4823
|
toAnthropicMessages,
|
|
4494
4824
|
toOpenAIMessages,
|
|
4495
|
-
toWellFormedText
|
|
4825
|
+
toWellFormedText,
|
|
4826
|
+
toolCallNameRuleFor
|
|
4496
4827
|
});
|
|
4497
4828
|
//# sourceMappingURL=index.cjs.map
|