@prestyj/ai 5.9.0 → 5.10.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 +93 -20
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +14 -2
- package/dist/index.d.ts +14 -2
- package/dist/index.js +92 -20
- 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
|
@@ -42,6 +42,7 @@ __export(index_exports, {
|
|
|
42
42
|
formatErrorForDisplay: () => formatErrorForDisplay,
|
|
43
43
|
isHardBillingMessage: () => isHardBillingMessage,
|
|
44
44
|
isUsageLimitError: () => isUsageLimitError,
|
|
45
|
+
localWireModelId: () => localWireModelId,
|
|
45
46
|
palsuAssistantMessage: () => palsuAssistantMessage,
|
|
46
47
|
palsuText: () => palsuText,
|
|
47
48
|
palsuThinking: () => palsuThinking,
|
|
@@ -561,6 +562,39 @@ function normalizeRootForAnthropic(schema) {
|
|
|
561
562
|
return out;
|
|
562
563
|
}
|
|
563
564
|
|
|
565
|
+
// src/providers/reasoning-field.ts
|
|
566
|
+
var REASONING_FIELD_ALIASES = [
|
|
567
|
+
"reasoning_content",
|
|
568
|
+
"reasoning",
|
|
569
|
+
"reasoning_text"
|
|
570
|
+
];
|
|
571
|
+
var DEFAULT_REASONING_FIELD = REASONING_FIELD_ALIASES[0];
|
|
572
|
+
function readReasoning(obj) {
|
|
573
|
+
if (!obj) return void 0;
|
|
574
|
+
for (const field of REASONING_FIELD_ALIASES) {
|
|
575
|
+
const value = obj[field];
|
|
576
|
+
if (typeof value === "string" && value) return { field, text: value };
|
|
577
|
+
}
|
|
578
|
+
return void 0;
|
|
579
|
+
}
|
|
580
|
+
function reasoningFieldKey(provider, baseUrl, model) {
|
|
581
|
+
return `${provider}|${baseUrl ?? ""}|${model}`;
|
|
582
|
+
}
|
|
583
|
+
var MAX_REMEMBERED_ENDPOINTS = 64;
|
|
584
|
+
var detectedFields = /* @__PURE__ */ new Map();
|
|
585
|
+
function rememberReasoningField(key, field) {
|
|
586
|
+
if (detectedFields.get(key) === field) return;
|
|
587
|
+
detectedFields.set(key, field);
|
|
588
|
+
while (detectedFields.size > MAX_REMEMBERED_ENDPOINTS) {
|
|
589
|
+
const oldest = detectedFields.keys().next();
|
|
590
|
+
if (oldest.done) break;
|
|
591
|
+
detectedFields.delete(oldest.value);
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
function getReasoningField(key) {
|
|
595
|
+
return detectedFields.get(key) ?? DEFAULT_REASONING_FIELD;
|
|
596
|
+
}
|
|
597
|
+
|
|
564
598
|
// src/providers/transform.ts
|
|
565
599
|
function hasValidThinkingSignature(part) {
|
|
566
600
|
return typeof part.signature === "string" && part.signature.trim().length > 0;
|
|
@@ -945,12 +979,12 @@ function toAnthropicToolChoice(choice) {
|
|
|
945
979
|
return { type: "tool", name: choice.name };
|
|
946
980
|
}
|
|
947
981
|
function isAdaptiveThinkingModel(model) {
|
|
948
|
-
return /opus-4[-.]8|opus-4[-.]7|opus-4[-.]6|sonnet-5|fable-5|mythos-5/.test(model);
|
|
982
|
+
return /opus-5|opus-4[-.]8|opus-4[-.]7|opus-4[-.]6|sonnet-5|fable-5|mythos-5/.test(model);
|
|
949
983
|
}
|
|
950
984
|
function toAnthropicThinking(level, maxTokens, model) {
|
|
951
985
|
if (isAdaptiveThinkingModel(model)) {
|
|
952
986
|
let effort = level;
|
|
953
|
-
if (effort === "xhigh" && !/opus-4-8|opus-4-7/.test(model)) {
|
|
987
|
+
if (effort === "xhigh" && !/opus-5|opus-4-8|opus-4-7/.test(model)) {
|
|
954
988
|
effort = "high";
|
|
955
989
|
}
|
|
956
990
|
return {
|
|
@@ -981,6 +1015,7 @@ function remapToolCallId(id, idMap) {
|
|
|
981
1015
|
return mapped;
|
|
982
1016
|
}
|
|
983
1017
|
function toOpenAIMessages(messages, options) {
|
|
1018
|
+
const reasoningField = options?.reasoningField || DEFAULT_REASONING_FIELD;
|
|
984
1019
|
const out = [];
|
|
985
1020
|
const idMap = /* @__PURE__ */ new Map();
|
|
986
1021
|
const mergeToolResultText = options?.provider === "glm";
|
|
@@ -1047,9 +1082,9 @@ function toOpenAIMessages(messages, options) {
|
|
|
1047
1082
|
...hasToolCalls ? { tool_calls: toolCalls } : {}
|
|
1048
1083
|
};
|
|
1049
1084
|
if (thinkingParts) {
|
|
1050
|
-
assistantMsg
|
|
1085
|
+
assistantMsg[reasoningField] = thinkingParts;
|
|
1051
1086
|
} else if (options?.thinking && hasToolCalls && options.provider !== "glm") {
|
|
1052
|
-
assistantMsg
|
|
1087
|
+
assistantMsg[reasoningField] = " ";
|
|
1053
1088
|
}
|
|
1054
1089
|
out.push(assistantMsg);
|
|
1055
1090
|
continue;
|
|
@@ -1127,6 +1162,10 @@ function toOpenAIToolChoice(choice) {
|
|
|
1127
1162
|
if (choice === "required") return "required";
|
|
1128
1163
|
return { type: "function", function: { name: choice.name } };
|
|
1129
1164
|
}
|
|
1165
|
+
function toLocalReasoningEffort(level) {
|
|
1166
|
+
if (level === "max" || level === "ultra" || level === "xhigh") return "max";
|
|
1167
|
+
return level;
|
|
1168
|
+
}
|
|
1130
1169
|
function toOpenAIReasoningEffort(level, model) {
|
|
1131
1170
|
const effort = level === "max" || level === "ultra" ? "xhigh" : level;
|
|
1132
1171
|
if (model.startsWith("fugu") && (effort === "low" || effort === "medium")) {
|
|
@@ -1923,7 +1962,9 @@ function streamOpenAI(options) {
|
|
|
1923
1962
|
async function* runStream2(options) {
|
|
1924
1963
|
const providerName = options.provider ?? "openai";
|
|
1925
1964
|
const useStreaming = options.streaming !== false;
|
|
1965
|
+
const endpointKey = reasoningFieldKey(providerName, options.baseUrl, options.model);
|
|
1926
1966
|
const client = createClient2(options);
|
|
1967
|
+
const isLocal = options.provider === "local";
|
|
1927
1968
|
const isKimiK3 = options.provider === "moonshot" && options.model === "kimi-k3";
|
|
1928
1969
|
const isManagedKimiK3 = isKimiK3 && options.baseUrl?.replace(/\/+$/, "").endsWith("/coding/v1") === true;
|
|
1929
1970
|
const k3Effort = options.thinking ? toKimiK3Effort(options.thinking) : void 0;
|
|
@@ -1946,7 +1987,8 @@ async function* runStream2(options) {
|
|
|
1946
1987
|
// disabled K3 must NOT carry placeholder reasoning_content (mirrors the
|
|
1947
1988
|
// official CLI: reasoning is preserved only while thinking is enabled).
|
|
1948
1989
|
thinking: isKimiK27 || !!options.thinking,
|
|
1949
|
-
supportsImages: options.supportsImages
|
|
1990
|
+
supportsImages: options.supportsImages,
|
|
1991
|
+
reasoningField: getReasoningField(endpointKey)
|
|
1950
1992
|
});
|
|
1951
1993
|
const defaultTemp = options.provider === "glm" ? 0.6 : void 0;
|
|
1952
1994
|
const effectiveTemp = options.temperature ?? defaultTemp;
|
|
@@ -1958,7 +2000,7 @@ async function* runStream2(options) {
|
|
|
1958
2000
|
...effectiveTemp != null && !options.thinking && !hasFixedKimiSampling ? { temperature: effectiveTemp } : {},
|
|
1959
2001
|
...options.topP != null && !hasFixedKimiSampling ? { top_p: options.topP } : {},
|
|
1960
2002
|
...options.stop ? { stop: options.stop } : {},
|
|
1961
|
-
...options.thinking && !usesThinkingParam && !isKimiK3 && !isKimiK27 ? { reasoning_effort: toOpenAIReasoningEffort(options.thinking, options.model) } : {},
|
|
2003
|
+
...options.thinking && !usesThinkingParam && !isKimiK3 && !isKimiK27 && !isLocal ? { reasoning_effort: toOpenAIReasoningEffort(options.thinking, options.model) } : {},
|
|
1962
2004
|
...options.tools?.length ? { tools: toOpenAITools(options.tools) } : {},
|
|
1963
2005
|
...options.toolChoice && options.tools?.length ? { tool_choice: toOpenAIToolChoice(options.toolChoice) } : {},
|
|
1964
2006
|
...useStreaming ? { stream_options: { include_usage: true } } : {}
|
|
@@ -1972,6 +2014,11 @@ async function* runStream2(options) {
|
|
|
1972
2014
|
paramsAny.prompt_cache_retention = "24h";
|
|
1973
2015
|
}
|
|
1974
2016
|
}
|
|
2017
|
+
if (isLocal && options.thinking) {
|
|
2018
|
+
params.reasoning_effort = toLocalReasoningEffort(
|
|
2019
|
+
options.thinking
|
|
2020
|
+
);
|
|
2021
|
+
}
|
|
1975
2022
|
if (options.provider === "openai" && options.serviceTier) {
|
|
1976
2023
|
params.service_tier = options.serviceTier;
|
|
1977
2024
|
}
|
|
@@ -2008,8 +2055,8 @@ async function* runStream2(options) {
|
|
|
2008
2055
|
const completion = await client.chat.completions.create(params, {
|
|
2009
2056
|
signal: options.signal ?? void 0
|
|
2010
2057
|
});
|
|
2011
|
-
yield* synthesizeEventsFromCompletion(completion, !!options.thinking);
|
|
2012
|
-
return completionToResponse(completion);
|
|
2058
|
+
yield* synthesizeEventsFromCompletion(completion, !!options.thinking, endpointKey);
|
|
2059
|
+
return completionToResponse(completion, endpointKey);
|
|
2013
2060
|
} catch (err) {
|
|
2014
2061
|
throw toError2(err, providerName);
|
|
2015
2062
|
}
|
|
@@ -2044,11 +2091,12 @@ async function* runStream2(options) {
|
|
|
2044
2091
|
finishReason = choice.finish_reason;
|
|
2045
2092
|
}
|
|
2046
2093
|
const delta = choice.delta;
|
|
2047
|
-
const
|
|
2048
|
-
if (
|
|
2049
|
-
|
|
2094
|
+
const reasoning = readReasoning(delta);
|
|
2095
|
+
if (reasoning) {
|
|
2096
|
+
rememberReasoningField(endpointKey, reasoning.field);
|
|
2097
|
+
thinkingAccum += reasoning.text;
|
|
2050
2098
|
if (options.thinking) {
|
|
2051
|
-
yield { type: "thinking_delta", text:
|
|
2099
|
+
yield { type: "thinking_delta", text: reasoning.text };
|
|
2052
2100
|
}
|
|
2053
2101
|
}
|
|
2054
2102
|
if (delta.content) {
|
|
@@ -2133,16 +2181,17 @@ async function* runStream2(options) {
|
|
|
2133
2181
|
yield { type: "done", stopReason };
|
|
2134
2182
|
return response;
|
|
2135
2183
|
}
|
|
2136
|
-
function* synthesizeEventsFromCompletion(completion, thinkingEnabled) {
|
|
2184
|
+
function* synthesizeEventsFromCompletion(completion, thinkingEnabled, endpointKey) {
|
|
2137
2185
|
const choice = completion.choices?.[0];
|
|
2138
2186
|
if (!choice) {
|
|
2139
2187
|
yield { type: "done", stopReason: normalizeOpenAIStopReason(null) };
|
|
2140
2188
|
return;
|
|
2141
2189
|
}
|
|
2142
2190
|
const msg = choice.message;
|
|
2143
|
-
const reasoning = msg
|
|
2144
|
-
if (
|
|
2145
|
-
|
|
2191
|
+
const reasoning = readReasoning(msg);
|
|
2192
|
+
if (reasoning) {
|
|
2193
|
+
rememberReasoningField(endpointKey, reasoning.field);
|
|
2194
|
+
if (thinkingEnabled) yield { type: "thinking_delta", text: reasoning.text };
|
|
2146
2195
|
}
|
|
2147
2196
|
if (typeof msg.content === "string" && msg.content) {
|
|
2148
2197
|
yield { type: "text_delta", text: msg.content };
|
|
@@ -2170,15 +2219,16 @@ function* synthesizeEventsFromCompletion(completion, thinkingEnabled) {
|
|
|
2170
2219
|
}
|
|
2171
2220
|
yield { type: "done", stopReason: normalizeOpenAIStopReason(choice.finish_reason ?? null) };
|
|
2172
2221
|
}
|
|
2173
|
-
function completionToResponse(completion) {
|
|
2222
|
+
function completionToResponse(completion, endpointKey) {
|
|
2174
2223
|
const choice = completion.choices?.[0];
|
|
2175
2224
|
const contentParts = [];
|
|
2176
2225
|
let textAccum = "";
|
|
2177
2226
|
if (choice) {
|
|
2178
2227
|
const msg = choice.message;
|
|
2179
|
-
const reasoning = msg
|
|
2180
|
-
if (
|
|
2181
|
-
|
|
2228
|
+
const reasoning = readReasoning(msg);
|
|
2229
|
+
if (reasoning) {
|
|
2230
|
+
rememberReasoningField(endpointKey, reasoning.field);
|
|
2231
|
+
contentParts.push({ type: "thinking", text: reasoning.text });
|
|
2182
2232
|
}
|
|
2183
2233
|
if (typeof msg.content === "string" && msg.content) {
|
|
2184
2234
|
textAccum = msg.content;
|
|
@@ -3539,6 +3589,28 @@ providerRegistry.register("minimax", {
|
|
|
3539
3589
|
serverTools: void 0
|
|
3540
3590
|
})
|
|
3541
3591
|
});
|
|
3592
|
+
function localWireModelId(id) {
|
|
3593
|
+
const match = /^local\/[^/]+\/(.+)$/.exec(id);
|
|
3594
|
+
return match?.[1] ?? id;
|
|
3595
|
+
}
|
|
3596
|
+
providerRegistry.register("local", {
|
|
3597
|
+
// Locally hosted OpenAI-compatible servers (Ollama, LM Studio, llama.cpp,
|
|
3598
|
+
// vLLM). There is no default endpoint: the baseUrl comes from the endpoint
|
|
3599
|
+
// credential the discovery layer wrote, so a missing one is a wiring bug, not
|
|
3600
|
+
// something to paper over with a guess at someone else's port.
|
|
3601
|
+
stream: (options) => {
|
|
3602
|
+
if (!options.baseUrl) {
|
|
3603
|
+
throw new EZCoderAIError(
|
|
3604
|
+
"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."
|
|
3605
|
+
);
|
|
3606
|
+
}
|
|
3607
|
+
return streamOpenAI({
|
|
3608
|
+
...options,
|
|
3609
|
+
model: localWireModelId(options.model),
|
|
3610
|
+
webSearch: false
|
|
3611
|
+
});
|
|
3612
|
+
}
|
|
3613
|
+
});
|
|
3542
3614
|
function stream(options) {
|
|
3543
3615
|
const entry = providerRegistry.get(options.provider);
|
|
3544
3616
|
if (!entry) {
|
|
@@ -3943,6 +4015,7 @@ function registerPalsuProvider(config) {
|
|
|
3943
4015
|
formatErrorForDisplay,
|
|
3944
4016
|
isHardBillingMessage,
|
|
3945
4017
|
isUsageLimitError,
|
|
4018
|
+
localWireModelId,
|
|
3946
4019
|
palsuAssistantMessage,
|
|
3947
4020
|
palsuText,
|
|
3948
4021
|
palsuThinking,
|