@prestyj/ai 5.9.0 → 5.11.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/README.md +1 -1
- package/dist/index.cjs +258 -25
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +48 -6
- package/dist/index.d.ts +48 -6
- package/dist/index.js +251 -24
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -40,7 +40,7 @@ Tool parameters are Zod schemas. Converted to JSON Schema at the provider bounda
|
|
|
40
40
|
|
|
41
41
|
| Provider | Models | Notes |
|
|
42
42
|
|---|---|---|
|
|
43
|
-
| `anthropic` | Claude Opus
|
|
43
|
+
| `anthropic` | Claude Opus 5, Sonnet 5, Haiku 4.5 | Extended thinking, prompt caching, server-side compaction |
|
|
44
44
|
| `openai` | GPT-4.1, o3, o4-mini | Supports OAuth (codex endpoint) and API keys |
|
|
45
45
|
| `glm` | GLM-5.1, GLM-4.7 | Z.AI platform, OpenAI-compatible |
|
|
46
46
|
| `moonshot` | Kimi K3, Kimi K2.7 Code | Moonshot platform, OpenAI-compatible |
|
package/dist/index.cjs
CHANGED
|
@@ -40,8 +40,10 @@ __export(index_exports, {
|
|
|
40
40
|
environmentSecrets: () => environmentSecrets,
|
|
41
41
|
formatError: () => formatError,
|
|
42
42
|
formatErrorForDisplay: () => formatErrorForDisplay,
|
|
43
|
+
hasLoneSurrogate: () => hasLoneSurrogate,
|
|
43
44
|
isHardBillingMessage: () => isHardBillingMessage,
|
|
44
45
|
isUsageLimitError: () => isUsageLimitError,
|
|
46
|
+
localWireModelId: () => localWireModelId,
|
|
45
47
|
palsuAssistantMessage: () => palsuAssistantMessage,
|
|
46
48
|
palsuText: () => palsuText,
|
|
47
49
|
palsuThinking: () => palsuThinking,
|
|
@@ -51,10 +53,14 @@ __export(index_exports, {
|
|
|
51
53
|
redactText: () => redactText,
|
|
52
54
|
redactValue: () => redactValue,
|
|
53
55
|
registerPalsuProvider: () => registerPalsuProvider,
|
|
56
|
+
sanitizeMessagesForWire: () => sanitizeMessagesForWire,
|
|
54
57
|
setProviderDiagnostic: () => setProviderDiagnostic,
|
|
58
|
+
sliceHead: () => sliceHead,
|
|
59
|
+
sliceTail: () => sliceTail,
|
|
55
60
|
stream: () => stream,
|
|
56
61
|
toAnthropicMessages: () => toAnthropicMessages,
|
|
57
|
-
toOpenAIMessages: () => toOpenAIMessages
|
|
62
|
+
toOpenAIMessages: () => toOpenAIMessages,
|
|
63
|
+
toWellFormedText: () => toWellFormedText
|
|
58
64
|
});
|
|
59
65
|
module.exports = __toCommonJS(index_exports);
|
|
60
66
|
|
|
@@ -561,6 +567,39 @@ function normalizeRootForAnthropic(schema) {
|
|
|
561
567
|
return out;
|
|
562
568
|
}
|
|
563
569
|
|
|
570
|
+
// src/providers/reasoning-field.ts
|
|
571
|
+
var REASONING_FIELD_ALIASES = [
|
|
572
|
+
"reasoning_content",
|
|
573
|
+
"reasoning",
|
|
574
|
+
"reasoning_text"
|
|
575
|
+
];
|
|
576
|
+
var DEFAULT_REASONING_FIELD = REASONING_FIELD_ALIASES[0];
|
|
577
|
+
function readReasoning(obj) {
|
|
578
|
+
if (!obj) return void 0;
|
|
579
|
+
for (const field of REASONING_FIELD_ALIASES) {
|
|
580
|
+
const value = obj[field];
|
|
581
|
+
if (typeof value === "string" && value) return { field, text: value };
|
|
582
|
+
}
|
|
583
|
+
return void 0;
|
|
584
|
+
}
|
|
585
|
+
function reasoningFieldKey(provider, baseUrl, model) {
|
|
586
|
+
return `${provider}|${baseUrl ?? ""}|${model}`;
|
|
587
|
+
}
|
|
588
|
+
var MAX_REMEMBERED_ENDPOINTS = 64;
|
|
589
|
+
var detectedFields = /* @__PURE__ */ new Map();
|
|
590
|
+
function rememberReasoningField(key, field) {
|
|
591
|
+
if (detectedFields.get(key) === field) return;
|
|
592
|
+
detectedFields.set(key, field);
|
|
593
|
+
while (detectedFields.size > MAX_REMEMBERED_ENDPOINTS) {
|
|
594
|
+
const oldest = detectedFields.keys().next();
|
|
595
|
+
if (oldest.done) break;
|
|
596
|
+
detectedFields.delete(oldest.value);
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
function getReasoningField(key) {
|
|
600
|
+
return detectedFields.get(key) ?? DEFAULT_REASONING_FIELD;
|
|
601
|
+
}
|
|
602
|
+
|
|
564
603
|
// src/providers/transform.ts
|
|
565
604
|
function hasValidThinkingSignature(part) {
|
|
566
605
|
return typeof part.signature === "string" && part.signature.trim().length > 0;
|
|
@@ -945,12 +984,12 @@ function toAnthropicToolChoice(choice) {
|
|
|
945
984
|
return { type: "tool", name: choice.name };
|
|
946
985
|
}
|
|
947
986
|
function isAdaptiveThinkingModel(model) {
|
|
948
|
-
return /opus-4[-.]8|opus-4[-.]7|opus-4[-.]6|sonnet-5|fable-5|mythos-5/.test(model);
|
|
987
|
+
return /opus-5|opus-4[-.]8|opus-4[-.]7|opus-4[-.]6|sonnet-5|fable-5|mythos-5/.test(model);
|
|
949
988
|
}
|
|
950
989
|
function toAnthropicThinking(level, maxTokens, model) {
|
|
951
990
|
if (isAdaptiveThinkingModel(model)) {
|
|
952
991
|
let effort = level;
|
|
953
|
-
if (effort === "xhigh" && !/opus-4-8|opus-4-7/.test(model)) {
|
|
992
|
+
if (effort === "xhigh" && !/opus-5|opus-4-8|opus-4-7/.test(model)) {
|
|
954
993
|
effort = "high";
|
|
955
994
|
}
|
|
956
995
|
return {
|
|
@@ -981,6 +1020,7 @@ function remapToolCallId(id, idMap) {
|
|
|
981
1020
|
return mapped;
|
|
982
1021
|
}
|
|
983
1022
|
function toOpenAIMessages(messages, options) {
|
|
1023
|
+
const reasoningField = options?.reasoningField || DEFAULT_REASONING_FIELD;
|
|
984
1024
|
const out = [];
|
|
985
1025
|
const idMap = /* @__PURE__ */ new Map();
|
|
986
1026
|
const mergeToolResultText = options?.provider === "glm";
|
|
@@ -1047,9 +1087,9 @@ function toOpenAIMessages(messages, options) {
|
|
|
1047
1087
|
...hasToolCalls ? { tool_calls: toolCalls } : {}
|
|
1048
1088
|
};
|
|
1049
1089
|
if (thinkingParts) {
|
|
1050
|
-
assistantMsg
|
|
1090
|
+
assistantMsg[reasoningField] = thinkingParts;
|
|
1051
1091
|
} else if (options?.thinking && hasToolCalls && options.provider !== "glm") {
|
|
1052
|
-
assistantMsg
|
|
1092
|
+
assistantMsg[reasoningField] = " ";
|
|
1053
1093
|
}
|
|
1054
1094
|
out.push(assistantMsg);
|
|
1055
1095
|
continue;
|
|
@@ -1127,6 +1167,10 @@ function toOpenAIToolChoice(choice) {
|
|
|
1127
1167
|
if (choice === "required") return "required";
|
|
1128
1168
|
return { type: "function", function: { name: choice.name } };
|
|
1129
1169
|
}
|
|
1170
|
+
function toLocalReasoningEffort(level) {
|
|
1171
|
+
if (level === "max" || level === "ultra" || level === "xhigh") return "max";
|
|
1172
|
+
return level;
|
|
1173
|
+
}
|
|
1130
1174
|
function toOpenAIReasoningEffort(level, model) {
|
|
1131
1175
|
const effort = level === "max" || level === "ultra" ? "xhigh" : level;
|
|
1132
1176
|
if (model.startsWith("fugu") && (effort === "low" || effort === "medium")) {
|
|
@@ -1923,7 +1967,9 @@ function streamOpenAI(options) {
|
|
|
1923
1967
|
async function* runStream2(options) {
|
|
1924
1968
|
const providerName = options.provider ?? "openai";
|
|
1925
1969
|
const useStreaming = options.streaming !== false;
|
|
1970
|
+
const endpointKey = reasoningFieldKey(providerName, options.baseUrl, options.model);
|
|
1926
1971
|
const client = createClient2(options);
|
|
1972
|
+
const isLocal = options.provider === "local";
|
|
1927
1973
|
const isKimiK3 = options.provider === "moonshot" && options.model === "kimi-k3";
|
|
1928
1974
|
const isManagedKimiK3 = isKimiK3 && options.baseUrl?.replace(/\/+$/, "").endsWith("/coding/v1") === true;
|
|
1929
1975
|
const k3Effort = options.thinking ? toKimiK3Effort(options.thinking) : void 0;
|
|
@@ -1946,7 +1992,8 @@ async function* runStream2(options) {
|
|
|
1946
1992
|
// disabled K3 must NOT carry placeholder reasoning_content (mirrors the
|
|
1947
1993
|
// official CLI: reasoning is preserved only while thinking is enabled).
|
|
1948
1994
|
thinking: isKimiK27 || !!options.thinking,
|
|
1949
|
-
supportsImages: options.supportsImages
|
|
1995
|
+
supportsImages: options.supportsImages,
|
|
1996
|
+
reasoningField: getReasoningField(endpointKey)
|
|
1950
1997
|
});
|
|
1951
1998
|
const defaultTemp = options.provider === "glm" ? 0.6 : void 0;
|
|
1952
1999
|
const effectiveTemp = options.temperature ?? defaultTemp;
|
|
@@ -1958,7 +2005,7 @@ async function* runStream2(options) {
|
|
|
1958
2005
|
...effectiveTemp != null && !options.thinking && !hasFixedKimiSampling ? { temperature: effectiveTemp } : {},
|
|
1959
2006
|
...options.topP != null && !hasFixedKimiSampling ? { top_p: options.topP } : {},
|
|
1960
2007
|
...options.stop ? { stop: options.stop } : {},
|
|
1961
|
-
...options.thinking && !usesThinkingParam && !isKimiK3 && !isKimiK27 ? { reasoning_effort: toOpenAIReasoningEffort(options.thinking, options.model) } : {},
|
|
2008
|
+
...options.thinking && !usesThinkingParam && !isKimiK3 && !isKimiK27 && !isLocal ? { reasoning_effort: toOpenAIReasoningEffort(options.thinking, options.model) } : {},
|
|
1962
2009
|
...options.tools?.length ? { tools: toOpenAITools(options.tools) } : {},
|
|
1963
2010
|
...options.toolChoice && options.tools?.length ? { tool_choice: toOpenAIToolChoice(options.toolChoice) } : {},
|
|
1964
2011
|
...useStreaming ? { stream_options: { include_usage: true } } : {}
|
|
@@ -1972,6 +2019,11 @@ async function* runStream2(options) {
|
|
|
1972
2019
|
paramsAny.prompt_cache_retention = "24h";
|
|
1973
2020
|
}
|
|
1974
2021
|
}
|
|
2022
|
+
if (isLocal && options.thinking) {
|
|
2023
|
+
params.reasoning_effort = toLocalReasoningEffort(
|
|
2024
|
+
options.thinking
|
|
2025
|
+
);
|
|
2026
|
+
}
|
|
1975
2027
|
if (options.provider === "openai" && options.serviceTier) {
|
|
1976
2028
|
params.service_tier = options.serviceTier;
|
|
1977
2029
|
}
|
|
@@ -2008,8 +2060,8 @@ async function* runStream2(options) {
|
|
|
2008
2060
|
const completion = await client.chat.completions.create(params, {
|
|
2009
2061
|
signal: options.signal ?? void 0
|
|
2010
2062
|
});
|
|
2011
|
-
yield* synthesizeEventsFromCompletion(completion, !!options.thinking);
|
|
2012
|
-
return completionToResponse(completion);
|
|
2063
|
+
yield* synthesizeEventsFromCompletion(completion, !!options.thinking, endpointKey);
|
|
2064
|
+
return completionToResponse(completion, endpointKey);
|
|
2013
2065
|
} catch (err) {
|
|
2014
2066
|
throw toError2(err, providerName);
|
|
2015
2067
|
}
|
|
@@ -2044,11 +2096,12 @@ async function* runStream2(options) {
|
|
|
2044
2096
|
finishReason = choice.finish_reason;
|
|
2045
2097
|
}
|
|
2046
2098
|
const delta = choice.delta;
|
|
2047
|
-
const
|
|
2048
|
-
if (
|
|
2049
|
-
|
|
2099
|
+
const reasoning = readReasoning(delta);
|
|
2100
|
+
if (reasoning) {
|
|
2101
|
+
rememberReasoningField(endpointKey, reasoning.field);
|
|
2102
|
+
thinkingAccum += reasoning.text;
|
|
2050
2103
|
if (options.thinking) {
|
|
2051
|
-
yield { type: "thinking_delta", text:
|
|
2104
|
+
yield { type: "thinking_delta", text: reasoning.text };
|
|
2052
2105
|
}
|
|
2053
2106
|
}
|
|
2054
2107
|
if (delta.content) {
|
|
@@ -2133,16 +2186,17 @@ async function* runStream2(options) {
|
|
|
2133
2186
|
yield { type: "done", stopReason };
|
|
2134
2187
|
return response;
|
|
2135
2188
|
}
|
|
2136
|
-
function* synthesizeEventsFromCompletion(completion, thinkingEnabled) {
|
|
2189
|
+
function* synthesizeEventsFromCompletion(completion, thinkingEnabled, endpointKey) {
|
|
2137
2190
|
const choice = completion.choices?.[0];
|
|
2138
2191
|
if (!choice) {
|
|
2139
2192
|
yield { type: "done", stopReason: normalizeOpenAIStopReason(null) };
|
|
2140
2193
|
return;
|
|
2141
2194
|
}
|
|
2142
2195
|
const msg = choice.message;
|
|
2143
|
-
const reasoning = msg
|
|
2144
|
-
if (
|
|
2145
|
-
|
|
2196
|
+
const reasoning = readReasoning(msg);
|
|
2197
|
+
if (reasoning) {
|
|
2198
|
+
rememberReasoningField(endpointKey, reasoning.field);
|
|
2199
|
+
if (thinkingEnabled) yield { type: "thinking_delta", text: reasoning.text };
|
|
2146
2200
|
}
|
|
2147
2201
|
if (typeof msg.content === "string" && msg.content) {
|
|
2148
2202
|
yield { type: "text_delta", text: msg.content };
|
|
@@ -2170,15 +2224,16 @@ function* synthesizeEventsFromCompletion(completion, thinkingEnabled) {
|
|
|
2170
2224
|
}
|
|
2171
2225
|
yield { type: "done", stopReason: normalizeOpenAIStopReason(choice.finish_reason ?? null) };
|
|
2172
2226
|
}
|
|
2173
|
-
function completionToResponse(completion) {
|
|
2227
|
+
function completionToResponse(completion, endpointKey) {
|
|
2174
2228
|
const choice = completion.choices?.[0];
|
|
2175
2229
|
const contentParts = [];
|
|
2176
2230
|
let textAccum = "";
|
|
2177
2231
|
if (choice) {
|
|
2178
2232
|
const msg = choice.message;
|
|
2179
|
-
const reasoning = msg
|
|
2180
|
-
if (
|
|
2181
|
-
|
|
2233
|
+
const reasoning = readReasoning(msg);
|
|
2234
|
+
if (reasoning) {
|
|
2235
|
+
rememberReasoningField(endpointKey, reasoning.field);
|
|
2236
|
+
contentParts.push({ type: "thinking", text: reasoning.text });
|
|
2182
2237
|
}
|
|
2183
2238
|
if (typeof msg.content === "string" && msg.content) {
|
|
2184
2239
|
textAccum = msg.content;
|
|
@@ -3330,14 +3385,16 @@ async function* runStream4(options) {
|
|
|
3330
3385
|
let thinkingAccum = "";
|
|
3331
3386
|
let stopReason = "end_turn";
|
|
3332
3387
|
let inputTokens = 0;
|
|
3333
|
-
let
|
|
3388
|
+
let candidateTokens = 0;
|
|
3389
|
+
let reasoningTokens = 0;
|
|
3334
3390
|
let cacheRead = 0;
|
|
3335
3391
|
let toolIndex = 0;
|
|
3336
3392
|
const handleResponse = function* (chunk) {
|
|
3337
3393
|
const usage = usageFromResponse(chunk);
|
|
3338
3394
|
if (usage) {
|
|
3339
3395
|
inputTokens = usage.promptTokenCount ?? inputTokens;
|
|
3340
|
-
|
|
3396
|
+
candidateTokens = usage.candidatesTokenCount ?? candidateTokens;
|
|
3397
|
+
reasoningTokens = usage.thoughtsTokenCount ?? reasoningTokens;
|
|
3341
3398
|
cacheRead = usage.cachedContentTokenCount ?? cacheRead;
|
|
3342
3399
|
}
|
|
3343
3400
|
const reason = finishReasonFromResponse(chunk);
|
|
@@ -3393,6 +3450,7 @@ async function* runStream4(options) {
|
|
|
3393
3450
|
}
|
|
3394
3451
|
if (pendingToolCalls.length > 0) stopReason = "tool_use";
|
|
3395
3452
|
const adjustedInputTokens = Math.max(0, inputTokens - cacheRead);
|
|
3453
|
+
const outputTokens = candidateTokens + reasoningTokens;
|
|
3396
3454
|
const streamResponse = {
|
|
3397
3455
|
message: {
|
|
3398
3456
|
role: "assistant",
|
|
@@ -3402,6 +3460,7 @@ async function* runStream4(options) {
|
|
|
3402
3460
|
usage: {
|
|
3403
3461
|
inputTokens: adjustedInputTokens,
|
|
3404
3462
|
outputTokens,
|
|
3463
|
+
...reasoningTokens > 0 ? { reasoningTokens } : {},
|
|
3405
3464
|
...cacheRead > 0 ? { cacheRead } : {}
|
|
3406
3465
|
}
|
|
3407
3466
|
};
|
|
@@ -3450,6 +3509,140 @@ var ProviderRegistryImpl = class {
|
|
|
3450
3509
|
};
|
|
3451
3510
|
var providerRegistry = new ProviderRegistryImpl();
|
|
3452
3511
|
|
|
3512
|
+
// src/utils/well-formed.ts
|
|
3513
|
+
var LONE_SURROGATE = /[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?<![\uD800-\uDBFF])[\uDC00-\uDFFF]/;
|
|
3514
|
+
var LONE_SURROGATE_GLOBAL = new RegExp(LONE_SURROGATE, "g");
|
|
3515
|
+
var REPLACEMENT = "\uFFFD";
|
|
3516
|
+
function hasLoneSurrogate(text) {
|
|
3517
|
+
const isWellFormed = text.isWellFormed;
|
|
3518
|
+
if (typeof isWellFormed === "function") return !isWellFormed.call(text);
|
|
3519
|
+
return LONE_SURROGATE.test(text);
|
|
3520
|
+
}
|
|
3521
|
+
function toWellFormedText(text) {
|
|
3522
|
+
if (!hasLoneSurrogate(text)) return text;
|
|
3523
|
+
const toWellFormed = text.toWellFormed;
|
|
3524
|
+
if (typeof toWellFormed === "function") return toWellFormed.call(text);
|
|
3525
|
+
return text.replace(LONE_SURROGATE_GLOBAL, REPLACEMENT);
|
|
3526
|
+
}
|
|
3527
|
+
function isHighSurrogate(code) {
|
|
3528
|
+
return code !== void 0 && code >= 55296 && code <= 56319;
|
|
3529
|
+
}
|
|
3530
|
+
function isLowSurrogate(code) {
|
|
3531
|
+
return code !== void 0 && code >= 56320 && code <= 57343;
|
|
3532
|
+
}
|
|
3533
|
+
function sliceHead(text, chars) {
|
|
3534
|
+
if (chars <= 0) return "";
|
|
3535
|
+
if (chars >= text.length) return text;
|
|
3536
|
+
const end = isHighSurrogate(text.charCodeAt(chars - 1)) ? chars - 1 : chars;
|
|
3537
|
+
return text.slice(0, end);
|
|
3538
|
+
}
|
|
3539
|
+
function sliceTail(text, chars) {
|
|
3540
|
+
if (chars <= 0) return "";
|
|
3541
|
+
if (chars >= text.length) return text;
|
|
3542
|
+
const start = text.length - chars;
|
|
3543
|
+
return text.slice(isLowSurrogate(text.charCodeAt(start)) ? start + 1 : start);
|
|
3544
|
+
}
|
|
3545
|
+
function sanitizeJsonValue(value) {
|
|
3546
|
+
if (typeof value === "string") return toWellFormedText(value);
|
|
3547
|
+
if (Array.isArray(value)) {
|
|
3548
|
+
let changed = false;
|
|
3549
|
+
const next = value.map((item) => {
|
|
3550
|
+
const sanitized = sanitizeJsonValue(item);
|
|
3551
|
+
if (sanitized !== item) changed = true;
|
|
3552
|
+
return sanitized;
|
|
3553
|
+
});
|
|
3554
|
+
return changed ? next : value;
|
|
3555
|
+
}
|
|
3556
|
+
if (value !== null && typeof value === "object") {
|
|
3557
|
+
let changed = false;
|
|
3558
|
+
const next = {};
|
|
3559
|
+
for (const [key, item] of Object.entries(value)) {
|
|
3560
|
+
const sanitizedKey = toWellFormedText(key);
|
|
3561
|
+
const sanitized = sanitizeJsonValue(item);
|
|
3562
|
+
if (sanitizedKey !== key || sanitized !== item) changed = true;
|
|
3563
|
+
next[sanitizedKey] = sanitized;
|
|
3564
|
+
}
|
|
3565
|
+
return changed ? next : value;
|
|
3566
|
+
}
|
|
3567
|
+
return value;
|
|
3568
|
+
}
|
|
3569
|
+
function sanitizeRecord(value) {
|
|
3570
|
+
return sanitizeJsonValue(value);
|
|
3571
|
+
}
|
|
3572
|
+
function sanitizePart(part) {
|
|
3573
|
+
switch (part.type) {
|
|
3574
|
+
case "text":
|
|
3575
|
+
case "thinking": {
|
|
3576
|
+
const text = toWellFormedText(part.text);
|
|
3577
|
+
return text === part.text ? part : { ...part, text };
|
|
3578
|
+
}
|
|
3579
|
+
case "tool_call": {
|
|
3580
|
+
const args = sanitizeRecord(part.args);
|
|
3581
|
+
return args === part.args ? part : { ...part, args };
|
|
3582
|
+
}
|
|
3583
|
+
case "server_tool_call": {
|
|
3584
|
+
const input = sanitizeJsonValue(part.input);
|
|
3585
|
+
return input === part.input ? part : { ...part, input };
|
|
3586
|
+
}
|
|
3587
|
+
case "server_tool_result": {
|
|
3588
|
+
const data = sanitizeJsonValue(part.data);
|
|
3589
|
+
return data === part.data ? part : { ...part, data };
|
|
3590
|
+
}
|
|
3591
|
+
case "raw": {
|
|
3592
|
+
const data = sanitizeRecord(part.data);
|
|
3593
|
+
return data === part.data ? part : { ...part, data };
|
|
3594
|
+
}
|
|
3595
|
+
default:
|
|
3596
|
+
return part;
|
|
3597
|
+
}
|
|
3598
|
+
}
|
|
3599
|
+
function sanitizeParts(parts) {
|
|
3600
|
+
let changed = false;
|
|
3601
|
+
const next = parts.map((part) => {
|
|
3602
|
+
const sanitized = sanitizePart(part);
|
|
3603
|
+
if (sanitized !== part) changed = true;
|
|
3604
|
+
return sanitized;
|
|
3605
|
+
});
|
|
3606
|
+
return changed ? next : parts;
|
|
3607
|
+
}
|
|
3608
|
+
function sanitizeToolResultContent(content) {
|
|
3609
|
+
if (typeof content === "string") return toWellFormedText(content);
|
|
3610
|
+
return sanitizeParts(content);
|
|
3611
|
+
}
|
|
3612
|
+
function sanitizeToolResults(results) {
|
|
3613
|
+
let changed = false;
|
|
3614
|
+
const next = results.map((result) => {
|
|
3615
|
+
const content = sanitizeToolResultContent(result.content);
|
|
3616
|
+
if (content === result.content) return result;
|
|
3617
|
+
changed = true;
|
|
3618
|
+
return { ...result, content };
|
|
3619
|
+
});
|
|
3620
|
+
return changed ? next : results;
|
|
3621
|
+
}
|
|
3622
|
+
function sanitizeMessage(message) {
|
|
3623
|
+
if (message.role === "tool") {
|
|
3624
|
+
const content2 = sanitizeToolResults(message.content);
|
|
3625
|
+
return content2 === message.content ? message : { ...message, content: content2 };
|
|
3626
|
+
}
|
|
3627
|
+
if (typeof message.content === "string") {
|
|
3628
|
+
const content2 = toWellFormedText(message.content);
|
|
3629
|
+
return content2 === message.content ? message : { ...message, content: content2 };
|
|
3630
|
+
}
|
|
3631
|
+
const content = sanitizeParts(message.content);
|
|
3632
|
+
return content === message.content ? message : { ...message, content };
|
|
3633
|
+
}
|
|
3634
|
+
function sanitizeMessagesForWire(messages) {
|
|
3635
|
+
let sanitized;
|
|
3636
|
+
for (let index = 0; index < messages.length; index++) {
|
|
3637
|
+
const message = messages[index];
|
|
3638
|
+
const next = sanitizeMessage(message);
|
|
3639
|
+
if (next === message) continue;
|
|
3640
|
+
sanitized ??= messages.slice();
|
|
3641
|
+
sanitized[index] = next;
|
|
3642
|
+
}
|
|
3643
|
+
return sanitized ?? messages;
|
|
3644
|
+
}
|
|
3645
|
+
|
|
3453
3646
|
// src/stream.ts
|
|
3454
3647
|
var GLM_CODING_BASE_URL = "https://api.z.ai/api/coding/paas/v4";
|
|
3455
3648
|
var KIMI_CODE_USER_AGENT = `kimi-code-cli/${process.env.KIMI_CODE_VERSION ?? "1.0.11"}`;
|
|
@@ -3539,6 +3732,28 @@ providerRegistry.register("minimax", {
|
|
|
3539
3732
|
serverTools: void 0
|
|
3540
3733
|
})
|
|
3541
3734
|
});
|
|
3735
|
+
function localWireModelId(id) {
|
|
3736
|
+
const match = /^local\/[^/]+\/(.+)$/.exec(id);
|
|
3737
|
+
return match?.[1] ?? id;
|
|
3738
|
+
}
|
|
3739
|
+
providerRegistry.register("local", {
|
|
3740
|
+
// Locally hosted OpenAI-compatible servers (Ollama, LM Studio, llama.cpp,
|
|
3741
|
+
// vLLM). There is no default endpoint: the baseUrl comes from the endpoint
|
|
3742
|
+
// credential the discovery layer wrote, so a missing one is a wiring bug, not
|
|
3743
|
+
// something to paper over with a guess at someone else's port.
|
|
3744
|
+
stream: (options) => {
|
|
3745
|
+
if (!options.baseUrl) {
|
|
3746
|
+
throw new EZCoderAIError(
|
|
3747
|
+
"Local provider requires a baseUrl (e.g. http://127.0.0.1:11434/v1). No local endpoint was resolved for this model \u2014 re-scan for local models."
|
|
3748
|
+
);
|
|
3749
|
+
}
|
|
3750
|
+
return streamOpenAI({
|
|
3751
|
+
...options,
|
|
3752
|
+
model: localWireModelId(options.model),
|
|
3753
|
+
webSearch: false
|
|
3754
|
+
});
|
|
3755
|
+
}
|
|
3756
|
+
});
|
|
3542
3757
|
function stream(options) {
|
|
3543
3758
|
const entry = providerRegistry.get(options.provider);
|
|
3544
3759
|
if (!entry) {
|
|
@@ -3549,13 +3764,25 @@ function stream(options) {
|
|
|
3549
3764
|
if (options.supportsVideo !== true && messagesContainVideo(options.messages)) {
|
|
3550
3765
|
throw new VideoUnsupportedError();
|
|
3551
3766
|
}
|
|
3767
|
+
const wireMessages = stripMessageProvenance(options.messages);
|
|
3552
3768
|
const messages = clampProviderContextImages(
|
|
3553
|
-
|
|
3769
|
+
sanitizeMessagesForWire(wireMessages),
|
|
3554
3770
|
options.provider,
|
|
3555
3771
|
options.supportsImages
|
|
3556
3772
|
);
|
|
3557
3773
|
return entry.stream(messages === options.messages ? options : { ...options, messages });
|
|
3558
3774
|
}
|
|
3775
|
+
function stripMessageProvenance(messages) {
|
|
3776
|
+
let stripped;
|
|
3777
|
+
for (let index = 0; index < messages.length; index++) {
|
|
3778
|
+
const message = messages[index];
|
|
3779
|
+
if (!message.provenance) continue;
|
|
3780
|
+
stripped ??= messages.slice();
|
|
3781
|
+
const { provenance: _provenance, ...wireMessage } = message;
|
|
3782
|
+
stripped[index] = wireMessage;
|
|
3783
|
+
}
|
|
3784
|
+
return stripped ?? messages;
|
|
3785
|
+
}
|
|
3559
3786
|
function messagesContainVideo(messages) {
|
|
3560
3787
|
for (const msg of messages) {
|
|
3561
3788
|
if (typeof msg.content === "string" || !Array.isArray(msg.content)) continue;
|
|
@@ -3941,8 +4168,10 @@ function registerPalsuProvider(config) {
|
|
|
3941
4168
|
environmentSecrets,
|
|
3942
4169
|
formatError,
|
|
3943
4170
|
formatErrorForDisplay,
|
|
4171
|
+
hasLoneSurrogate,
|
|
3944
4172
|
isHardBillingMessage,
|
|
3945
4173
|
isUsageLimitError,
|
|
4174
|
+
localWireModelId,
|
|
3946
4175
|
palsuAssistantMessage,
|
|
3947
4176
|
palsuText,
|
|
3948
4177
|
palsuThinking,
|
|
@@ -3952,9 +4181,13 @@ function registerPalsuProvider(config) {
|
|
|
3952
4181
|
redactText,
|
|
3953
4182
|
redactValue,
|
|
3954
4183
|
registerPalsuProvider,
|
|
4184
|
+
sanitizeMessagesForWire,
|
|
3955
4185
|
setProviderDiagnostic,
|
|
4186
|
+
sliceHead,
|
|
4187
|
+
sliceTail,
|
|
3956
4188
|
stream,
|
|
3957
4189
|
toAnthropicMessages,
|
|
3958
|
-
toOpenAIMessages
|
|
4190
|
+
toOpenAIMessages,
|
|
4191
|
+
toWellFormedText
|
|
3959
4192
|
});
|
|
3960
4193
|
//# sourceMappingURL=index.cjs.map
|