@kenkaiiii/gg-ai 5.23.3 → 5.25.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 +91 -18
- 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 +90 -18
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
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;
|
|
@@ -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")) {
|
|
@@ -1922,7 +1961,9 @@ function streamOpenAI(options) {
|
|
|
1922
1961
|
async function* runStream2(options) {
|
|
1923
1962
|
const providerName = options.provider ?? "openai";
|
|
1924
1963
|
const useStreaming = options.streaming !== false;
|
|
1964
|
+
const endpointKey = reasoningFieldKey(providerName, options.baseUrl, options.model);
|
|
1925
1965
|
const client = createClient2(options);
|
|
1966
|
+
const isLocal = options.provider === "local";
|
|
1926
1967
|
const isKimiK3 = options.provider === "moonshot" && options.model === "kimi-k3";
|
|
1927
1968
|
const isManagedKimiK3 = isKimiK3 && options.baseUrl?.replace(/\/+$/, "").endsWith("/coding/v1") === true;
|
|
1928
1969
|
const k3Effort = options.thinking ? toKimiK3Effort(options.thinking) : void 0;
|
|
@@ -1945,7 +1986,8 @@ async function* runStream2(options) {
|
|
|
1945
1986
|
// disabled K3 must NOT carry placeholder reasoning_content (mirrors the
|
|
1946
1987
|
// official CLI: reasoning is preserved only while thinking is enabled).
|
|
1947
1988
|
thinking: isKimiK27 || !!options.thinking,
|
|
1948
|
-
supportsImages: options.supportsImages
|
|
1989
|
+
supportsImages: options.supportsImages,
|
|
1990
|
+
reasoningField: getReasoningField(endpointKey)
|
|
1949
1991
|
});
|
|
1950
1992
|
const defaultTemp = options.provider === "glm" ? 0.6 : void 0;
|
|
1951
1993
|
const effectiveTemp = options.temperature ?? defaultTemp;
|
|
@@ -1957,7 +1999,7 @@ async function* runStream2(options) {
|
|
|
1957
1999
|
...effectiveTemp != null && !options.thinking && !hasFixedKimiSampling ? { temperature: effectiveTemp } : {},
|
|
1958
2000
|
...options.topP != null && !hasFixedKimiSampling ? { top_p: options.topP } : {},
|
|
1959
2001
|
...options.stop ? { stop: options.stop } : {},
|
|
1960
|
-
...options.thinking && !usesThinkingParam && !isKimiK3 && !isKimiK27 ? { reasoning_effort: toOpenAIReasoningEffort(options.thinking, options.model) } : {},
|
|
2002
|
+
...options.thinking && !usesThinkingParam && !isKimiK3 && !isKimiK27 && !isLocal ? { reasoning_effort: toOpenAIReasoningEffort(options.thinking, options.model) } : {},
|
|
1961
2003
|
...options.tools?.length ? { tools: toOpenAITools(options.tools) } : {},
|
|
1962
2004
|
...options.toolChoice && options.tools?.length ? { tool_choice: toOpenAIToolChoice(options.toolChoice) } : {},
|
|
1963
2005
|
...useStreaming ? { stream_options: { include_usage: true } } : {}
|
|
@@ -1971,6 +2013,11 @@ async function* runStream2(options) {
|
|
|
1971
2013
|
paramsAny.prompt_cache_retention = "24h";
|
|
1972
2014
|
}
|
|
1973
2015
|
}
|
|
2016
|
+
if (isLocal && options.thinking) {
|
|
2017
|
+
params.reasoning_effort = toLocalReasoningEffort(
|
|
2018
|
+
options.thinking
|
|
2019
|
+
);
|
|
2020
|
+
}
|
|
1974
2021
|
if (options.provider === "openai" && options.serviceTier) {
|
|
1975
2022
|
params.service_tier = options.serviceTier;
|
|
1976
2023
|
}
|
|
@@ -2007,8 +2054,8 @@ async function* runStream2(options) {
|
|
|
2007
2054
|
const completion = await client.chat.completions.create(params, {
|
|
2008
2055
|
signal: options.signal ?? void 0
|
|
2009
2056
|
});
|
|
2010
|
-
yield* synthesizeEventsFromCompletion(completion, !!options.thinking);
|
|
2011
|
-
return completionToResponse(completion);
|
|
2057
|
+
yield* synthesizeEventsFromCompletion(completion, !!options.thinking, endpointKey);
|
|
2058
|
+
return completionToResponse(completion, endpointKey);
|
|
2012
2059
|
} catch (err) {
|
|
2013
2060
|
throw toError2(err, providerName);
|
|
2014
2061
|
}
|
|
@@ -2043,11 +2090,12 @@ async function* runStream2(options) {
|
|
|
2043
2090
|
finishReason = choice.finish_reason;
|
|
2044
2091
|
}
|
|
2045
2092
|
const delta = choice.delta;
|
|
2046
|
-
const
|
|
2047
|
-
if (
|
|
2048
|
-
|
|
2093
|
+
const reasoning = readReasoning(delta);
|
|
2094
|
+
if (reasoning) {
|
|
2095
|
+
rememberReasoningField(endpointKey, reasoning.field);
|
|
2096
|
+
thinkingAccum += reasoning.text;
|
|
2049
2097
|
if (options.thinking) {
|
|
2050
|
-
yield { type: "thinking_delta", text:
|
|
2098
|
+
yield { type: "thinking_delta", text: reasoning.text };
|
|
2051
2099
|
}
|
|
2052
2100
|
}
|
|
2053
2101
|
if (delta.content) {
|
|
@@ -2132,16 +2180,17 @@ async function* runStream2(options) {
|
|
|
2132
2180
|
yield { type: "done", stopReason };
|
|
2133
2181
|
return response;
|
|
2134
2182
|
}
|
|
2135
|
-
function* synthesizeEventsFromCompletion(completion, thinkingEnabled) {
|
|
2183
|
+
function* synthesizeEventsFromCompletion(completion, thinkingEnabled, endpointKey) {
|
|
2136
2184
|
const choice = completion.choices?.[0];
|
|
2137
2185
|
if (!choice) {
|
|
2138
2186
|
yield { type: "done", stopReason: normalizeOpenAIStopReason(null) };
|
|
2139
2187
|
return;
|
|
2140
2188
|
}
|
|
2141
2189
|
const msg = choice.message;
|
|
2142
|
-
const reasoning = msg
|
|
2143
|
-
if (
|
|
2144
|
-
|
|
2190
|
+
const reasoning = readReasoning(msg);
|
|
2191
|
+
if (reasoning) {
|
|
2192
|
+
rememberReasoningField(endpointKey, reasoning.field);
|
|
2193
|
+
if (thinkingEnabled) yield { type: "thinking_delta", text: reasoning.text };
|
|
2145
2194
|
}
|
|
2146
2195
|
if (typeof msg.content === "string" && msg.content) {
|
|
2147
2196
|
yield { type: "text_delta", text: msg.content };
|
|
@@ -2169,15 +2218,16 @@ function* synthesizeEventsFromCompletion(completion, thinkingEnabled) {
|
|
|
2169
2218
|
}
|
|
2170
2219
|
yield { type: "done", stopReason: normalizeOpenAIStopReason(choice.finish_reason ?? null) };
|
|
2171
2220
|
}
|
|
2172
|
-
function completionToResponse(completion) {
|
|
2221
|
+
function completionToResponse(completion, endpointKey) {
|
|
2173
2222
|
const choice = completion.choices?.[0];
|
|
2174
2223
|
const contentParts = [];
|
|
2175
2224
|
let textAccum = "";
|
|
2176
2225
|
if (choice) {
|
|
2177
2226
|
const msg = choice.message;
|
|
2178
|
-
const reasoning = msg
|
|
2179
|
-
if (
|
|
2180
|
-
|
|
2227
|
+
const reasoning = readReasoning(msg);
|
|
2228
|
+
if (reasoning) {
|
|
2229
|
+
rememberReasoningField(endpointKey, reasoning.field);
|
|
2230
|
+
contentParts.push({ type: "thinking", text: reasoning.text });
|
|
2181
2231
|
}
|
|
2182
2232
|
if (typeof msg.content === "string" && msg.content) {
|
|
2183
2233
|
textAccum = msg.content;
|
|
@@ -3529,6 +3579,28 @@ providerRegistry.register("minimax", {
|
|
|
3529
3579
|
serverTools: void 0
|
|
3530
3580
|
})
|
|
3531
3581
|
});
|
|
3582
|
+
function localWireModelId(id) {
|
|
3583
|
+
const match = /^local\/[^/]+\/(.+)$/.exec(id);
|
|
3584
|
+
return match?.[1] ?? id;
|
|
3585
|
+
}
|
|
3586
|
+
providerRegistry.register("local", {
|
|
3587
|
+
// Locally hosted OpenAI-compatible servers (Ollama, LM Studio, llama.cpp,
|
|
3588
|
+
// vLLM). There is no default endpoint: the baseUrl comes from the endpoint
|
|
3589
|
+
// credential the discovery layer wrote, so a missing one is a wiring bug, not
|
|
3590
|
+
// something to paper over with a guess at someone else's port.
|
|
3591
|
+
stream: (options) => {
|
|
3592
|
+
if (!options.baseUrl) {
|
|
3593
|
+
throw new GGAIError(
|
|
3594
|
+
"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."
|
|
3595
|
+
);
|
|
3596
|
+
}
|
|
3597
|
+
return streamOpenAI({
|
|
3598
|
+
...options,
|
|
3599
|
+
model: localWireModelId(options.model),
|
|
3600
|
+
webSearch: false
|
|
3601
|
+
});
|
|
3602
|
+
}
|
|
3603
|
+
});
|
|
3532
3604
|
function stream(options) {
|
|
3533
3605
|
const entry = providerRegistry.get(options.provider);
|
|
3534
3606
|
if (!entry) {
|
|
@@ -3933,6 +4005,7 @@ function registerPalsuProvider(config) {
|
|
|
3933
4005
|
formatErrorForDisplay,
|
|
3934
4006
|
isHardBillingMessage,
|
|
3935
4007
|
isUsageLimitError,
|
|
4008
|
+
localWireModelId,
|
|
3936
4009
|
palsuAssistantMessage,
|
|
3937
4010
|
palsuText,
|
|
3938
4011
|
palsuThinking,
|