@kenkaiiii/gg-ai 5.89.0 → 5.91.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 +107 -34
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -1
- package/dist/index.d.ts +5 -1
- package/dist/index.js +105 -34
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.cjs
CHANGED
|
@@ -35,6 +35,7 @@ __export(index_exports, {
|
|
|
35
35
|
EventStream: () => EventStream,
|
|
36
36
|
FAST_MODE_SUFFIX: () => FAST_MODE_SUFFIX,
|
|
37
37
|
GGAIError: () => GGAIError,
|
|
38
|
+
LOCAL_NO_API_KEY: () => LOCAL_NO_API_KEY,
|
|
38
39
|
PRECONNECT_INTERVAL_MS: () => PRECONNECT_INTERVAL_MS,
|
|
39
40
|
ProviderError: () => ProviderError,
|
|
40
41
|
REDACTION_MARKER: () => REDACTED,
|
|
@@ -57,6 +58,7 @@ __export(index_exports, {
|
|
|
57
58
|
isHardBillingMessage: () => isHardBillingMessage,
|
|
58
59
|
isUsageLimitError: () => isUsageLimitError,
|
|
59
60
|
isValidToolCallName: () => isValidToolCallName,
|
|
61
|
+
localBearerKey: () => localBearerKey,
|
|
60
62
|
localWireModelId: () => localWireModelId,
|
|
61
63
|
opensTurn: () => opensTurn,
|
|
62
64
|
palsuAssistantMessage: () => palsuAssistantMessage,
|
|
@@ -333,6 +335,8 @@ function formatError(err) {
|
|
|
333
335
|
guidance: fastRejection.guidance
|
|
334
336
|
};
|
|
335
337
|
}
|
|
338
|
+
const miniMax = err.provider === "minimax" ? formatMiniMaxError(err, cleanMessage) : void 0;
|
|
339
|
+
if (miniMax) return miniMax;
|
|
336
340
|
if (isUsageLimitError(err)) {
|
|
337
341
|
const resetClause = err.resetsAt ? ` It resets at ${formatResetTime(err.resetsAt)}.` : "";
|
|
338
342
|
return {
|
|
@@ -439,6 +443,38 @@ function inferSource(err) {
|
|
|
439
443
|
}
|
|
440
444
|
return "ggcoder";
|
|
441
445
|
}
|
|
446
|
+
function formatMiniMaxError(err, cleanMessage) {
|
|
447
|
+
const code = /\((\d{4,5})\)/.exec(err.message)?.[1];
|
|
448
|
+
const base = {
|
|
449
|
+
source: "provider",
|
|
450
|
+
message: cleanMessage,
|
|
451
|
+
provider: err.provider,
|
|
452
|
+
statusCode: err.statusCode,
|
|
453
|
+
...err.requestId ? { requestId: err.requestId } : {}
|
|
454
|
+
};
|
|
455
|
+
if (code === "2049" || code === "1004") {
|
|
456
|
+
return {
|
|
457
|
+
...base,
|
|
458
|
+
headline: "MiniMax didn't accept this API key.",
|
|
459
|
+
guidance: "A MiniMax key only works in the region that issued it (Global: platform.minimax.io, Mainland China: platform.minimaxi.com). Connect MiniMax again with the key so GG Coder can detect its region, and check the key is active."
|
|
460
|
+
};
|
|
461
|
+
}
|
|
462
|
+
if (code === "2061") {
|
|
463
|
+
return {
|
|
464
|
+
...base,
|
|
465
|
+
headline: "Your MiniMax plan doesn't include this model.",
|
|
466
|
+
guidance: "Switch to MiniMax M3.1 Flash in the model selector \u2014 it's the model M Plan and Token Plan cover. MiniMax M3 needs a pay-as-you-go key."
|
|
467
|
+
};
|
|
468
|
+
}
|
|
469
|
+
if (code === "1008") {
|
|
470
|
+
return {
|
|
471
|
+
...base,
|
|
472
|
+
headline: "MiniMax has no balance for this request.",
|
|
473
|
+
guidance: "Check this key's plan is active, or its pay-as-you-go balance, at platform.minimax.io (platform.minimaxi.com for Mainland China keys). Plan keys only cover MiniMax M3.1 Flash. Not a GG Coder issue."
|
|
474
|
+
};
|
|
475
|
+
}
|
|
476
|
+
return void 0;
|
|
477
|
+
}
|
|
442
478
|
function providerGuidance(provider, message, statusCode) {
|
|
443
479
|
const name = provider ? providerDisplayName(provider) : "the provider";
|
|
444
480
|
const status = provider ? PROVIDER_STATUS_URL[provider] : void 0;
|
|
@@ -1656,10 +1692,22 @@ function toAnthropicMessages(messages, cacheControl, options) {
|
|
|
1656
1692
|
(name) => toolReferences.has(name) && !referencedTools.has(name)
|
|
1657
1693
|
) : [];
|
|
1658
1694
|
if (refs.length === 0) {
|
|
1695
|
+
const content = toAnthropicToolResultContent(result.content);
|
|
1696
|
+
if (result.isError && typeof content !== "string" && content.some((part) => part.type !== "text")) {
|
|
1697
|
+
const text = content.filter((part) => part.type === "text" && part.text !== "");
|
|
1698
|
+
trailing.push({ type: "text", text: `Attachments from tool call ${toolUseId}:` });
|
|
1699
|
+
for (const part of content) if (part.type !== "text") trailing.push(part);
|
|
1700
|
+
return {
|
|
1701
|
+
type: "tool_result",
|
|
1702
|
+
tool_use_id: toolUseId,
|
|
1703
|
+
content: text.length > 0 ? text : "Tool call failed; its attachments follow.",
|
|
1704
|
+
is_error: true
|
|
1705
|
+
};
|
|
1706
|
+
}
|
|
1659
1707
|
return {
|
|
1660
1708
|
type: "tool_result",
|
|
1661
1709
|
tool_use_id: toolUseId,
|
|
1662
|
-
content
|
|
1710
|
+
content,
|
|
1663
1711
|
is_error: result.isError
|
|
1664
1712
|
};
|
|
1665
1713
|
}
|
|
@@ -1678,7 +1726,8 @@ ${part.text}` } : part
|
|
|
1678
1726
|
type: "tool_result",
|
|
1679
1727
|
tool_use_id: toolUseId,
|
|
1680
1728
|
content: refs.map((name) => ({ type: "tool_reference", tool_name: name })),
|
|
1681
|
-
is_error
|
|
1729
|
+
// tool_reference isn't text, so is_error would 400; the error text trails.
|
|
1730
|
+
is_error: void 0
|
|
1682
1731
|
};
|
|
1683
1732
|
});
|
|
1684
1733
|
out.push({
|
|
@@ -1701,8 +1750,8 @@ ${part.text}` } : part
|
|
|
1701
1750
|
markAnthropicCacheBreakpoint(out, tail, cacheControl);
|
|
1702
1751
|
} else {
|
|
1703
1752
|
if (anchor !== void 0) markAnthropicCacheBreakpoint(out, anchor, cacheControl);
|
|
1704
|
-
const
|
|
1705
|
-
markAnthropicCacheBreakpoint(out, tail,
|
|
1753
|
+
const blocking = calledBlockingTool(messages, trajectoryStartIdx);
|
|
1754
|
+
markAnthropicCacheBreakpoint(out, tail, blocking ? cacheControl : { type: "ephemeral" });
|
|
1706
1755
|
}
|
|
1707
1756
|
} else {
|
|
1708
1757
|
markAnthropicCacheBreakpoint(out, tail, cacheControl);
|
|
@@ -1738,19 +1787,13 @@ var BLOCKING_TOOL_NAMES = /* @__PURE__ */ new Set([
|
|
|
1738
1787
|
"subagent",
|
|
1739
1788
|
"ask_user"
|
|
1740
1789
|
]);
|
|
1741
|
-
|
|
1742
|
-
function isLongToolRun(messages, trajectoryStartIdx) {
|
|
1743
|
-
let rounds = 0;
|
|
1790
|
+
function calledBlockingTool(messages, trajectoryStartIdx) {
|
|
1744
1791
|
for (let i = Math.max(0, trajectoryStartIdx + 1); i < messages.length; i++) {
|
|
1745
1792
|
const m = messages[i];
|
|
1746
1793
|
if (m?.role !== "assistant" || typeof m.content === "string") continue;
|
|
1747
|
-
let called = false;
|
|
1748
1794
|
for (const part of m.content) {
|
|
1749
|
-
if (part.type
|
|
1750
|
-
called = true;
|
|
1751
|
-
if (BLOCKING_TOOL_NAMES.has(part.name)) return true;
|
|
1795
|
+
if (part.type === "tool_call" && BLOCKING_TOOL_NAMES.has(part.name)) return true;
|
|
1752
1796
|
}
|
|
1753
|
-
if (called && ++rounds >= LONG_RUN_ROUNDS) return true;
|
|
1754
1797
|
}
|
|
1755
1798
|
return false;
|
|
1756
1799
|
}
|
|
@@ -1809,6 +1852,13 @@ function isAdaptiveThinkingModel(model) {
|
|
|
1809
1852
|
return /opus-5|opus-4[-.]8|opus-4[-.]7|opus-4[-.]6|sonnet-5|haiku-5|fable-5|mythos-5/.test(model);
|
|
1810
1853
|
}
|
|
1811
1854
|
function toAnthropicThinking(level, maxTokens, model) {
|
|
1855
|
+
if (model.startsWith("MiniMax-M3.1")) {
|
|
1856
|
+
return {
|
|
1857
|
+
thinking: { type: "adaptive" },
|
|
1858
|
+
maxTokens,
|
|
1859
|
+
outputConfig: { effort: level === "ultra" ? "max" : level }
|
|
1860
|
+
};
|
|
1861
|
+
}
|
|
1812
1862
|
if (isAdaptiveThinkingModel(model)) {
|
|
1813
1863
|
let effort = level;
|
|
1814
1864
|
if (effort === "xhigh" && !/fable-5|mythos-5|opus-5|opus-4-8|opus-4-7|sonnet-5[-.]5|haiku-5[-.]5/.test(model)) {
|
|
@@ -2330,8 +2380,7 @@ async function* runStream(options) {
|
|
|
2330
2380
|
...system ? { system } : {},
|
|
2331
2381
|
...thinking ? { thinking } : {},
|
|
2332
2382
|
...outputConfig ? { output_config: outputConfig } : {},
|
|
2333
|
-
|
|
2334
|
-
...options.topP != null ? { top_p: options.topP } : {},
|
|
2383
|
+
// API version 2026-10-21 (SDK 1.x) rejects temperature/top_p/top_k with a 400.
|
|
2335
2384
|
...options.stop ? { stop_sequences: options.stop } : {},
|
|
2336
2385
|
...(deferredPlan?.live ?? options.tools)?.length || options.serverTools?.length || options.webSearch ? (() => {
|
|
2337
2386
|
const reservedServerNames = /* @__PURE__ */ new Set();
|
|
@@ -2432,7 +2481,7 @@ async function* runStream(options) {
|
|
|
2432
2481
|
yield* synthesizeEventsFromMessage(message);
|
|
2433
2482
|
return messageToResponse(message);
|
|
2434
2483
|
} catch (err) {
|
|
2435
|
-
throw toError(err, { fastMode: useFastMode });
|
|
2484
|
+
throw toError(err, { fastMode: useFastMode, provider: options.provider });
|
|
2436
2485
|
}
|
|
2437
2486
|
}
|
|
2438
2487
|
const contentParts = [];
|
|
@@ -2548,7 +2597,7 @@ async function* runStream(options) {
|
|
|
2548
2597
|
const rawPartial = accum.argsJson;
|
|
2549
2598
|
const snippet = rawPartial.length > 200 ? `${rawPartial.slice(0, 200)}\u2026` : rawPartial;
|
|
2550
2599
|
throw new ProviderError(
|
|
2551
|
-
|
|
2600
|
+
options.provider,
|
|
2552
2601
|
`Tool "${accum.toolName}" input JSON was truncated in the stream (${rawPartial.length} bytes): ${snippet}; ${parseErr.message}`,
|
|
2553
2602
|
{ cause: parseErr }
|
|
2554
2603
|
);
|
|
@@ -2651,15 +2700,15 @@ async function* runStream(options) {
|
|
|
2651
2700
|
}
|
|
2652
2701
|
}
|
|
2653
2702
|
} catch (err) {
|
|
2654
|
-
throw toError(err, { fastMode: useFastMode });
|
|
2703
|
+
throw toError(err, { fastMode: useFastMode, provider: options.provider });
|
|
2655
2704
|
}
|
|
2656
2705
|
if (!receivedAnyEvent) {
|
|
2657
|
-
throw new ProviderError(
|
|
2706
|
+
throw new ProviderError(options.provider, "Stream ended without producing any events.", {
|
|
2658
2707
|
statusCode: 504
|
|
2659
2708
|
});
|
|
2660
2709
|
}
|
|
2661
2710
|
if (stopReason === null) {
|
|
2662
|
-
throw new ProviderError(
|
|
2711
|
+
throw new ProviderError(options.provider, "Stream ended before completion (no stop_reason).", {
|
|
2663
2712
|
statusCode: 504,
|
|
2664
2713
|
cause: { partialContent: contentParts, outputTokens }
|
|
2665
2714
|
});
|
|
@@ -2801,6 +2850,7 @@ function readUnifiedRateLimit(headers) {
|
|
|
2801
2850
|
return { rejected: status === "rejected", ...resetsAt ? { resetsAt } : {} };
|
|
2802
2851
|
}
|
|
2803
2852
|
function toError(err, context) {
|
|
2853
|
+
const provider = context?.provider ?? "anthropic";
|
|
2804
2854
|
if (err instanceof ProviderError) return err;
|
|
2805
2855
|
if (err instanceof import_sdk.default.APIError) {
|
|
2806
2856
|
const errorBody = err.error;
|
|
@@ -2834,22 +2884,22 @@ function toError(err, context) {
|
|
|
2834
2884
|
}
|
|
2835
2885
|
if (isHardBillingMessage(message)) {
|
|
2836
2886
|
const usageMessage = /usage limit reached/i.test(message) ? message : `usage limit reached: ${message}`;
|
|
2837
|
-
return new ProviderError(
|
|
2887
|
+
return new ProviderError(provider, usageMessage, {
|
|
2838
2888
|
statusCode: err.status,
|
|
2839
2889
|
...requestId ? { requestId } : {},
|
|
2840
2890
|
cause: err
|
|
2841
2891
|
});
|
|
2842
2892
|
}
|
|
2843
|
-
return new ProviderError(
|
|
2893
|
+
return new ProviderError(provider, message, {
|
|
2844
2894
|
statusCode: err.status,
|
|
2845
2895
|
...requestId ? { requestId } : {},
|
|
2846
2896
|
cause: err
|
|
2847
2897
|
});
|
|
2848
2898
|
}
|
|
2849
2899
|
if (err instanceof Error) {
|
|
2850
|
-
return new ProviderError(
|
|
2900
|
+
return new ProviderError(provider, err.message, { cause: err });
|
|
2851
2901
|
}
|
|
2852
|
-
return new ProviderError(
|
|
2902
|
+
return new ProviderError(provider, String(err));
|
|
2853
2903
|
}
|
|
2854
2904
|
|
|
2855
2905
|
// src/providers/openai.ts
|
|
@@ -2937,6 +2987,12 @@ function getEnvironment() {
|
|
|
2937
2987
|
return globalThis.process?.env;
|
|
2938
2988
|
}
|
|
2939
2989
|
|
|
2990
|
+
// src/local-api-key.ts
|
|
2991
|
+
var LOCAL_NO_API_KEY = "local";
|
|
2992
|
+
function localBearerKey(apiKey) {
|
|
2993
|
+
return apiKey && apiKey !== LOCAL_NO_API_KEY ? apiKey : void 0;
|
|
2994
|
+
}
|
|
2995
|
+
|
|
2940
2996
|
// src/providers/openai.ts
|
|
2941
2997
|
function toKimiK3Effort(level) {
|
|
2942
2998
|
switch (level) {
|
|
@@ -2981,6 +3037,8 @@ function createClient2(options) {
|
|
|
2981
3037
|
const cached = openaiClientCache.get(cacheKey);
|
|
2982
3038
|
if (cached) return cached;
|
|
2983
3039
|
}
|
|
3040
|
+
const omitAuth = options.provider === "local" && localBearerKey(options.apiKey) === void 0;
|
|
3041
|
+
const defaultHeaders = omitAuth ? { ...options.defaultHeaders, Authorization: null } : options.defaultHeaders;
|
|
2984
3042
|
const client = new import_openai.default({
|
|
2985
3043
|
apiKey: options.apiKey,
|
|
2986
3044
|
...options.baseUrl ? { baseURL: options.baseUrl } : {},
|
|
@@ -2990,7 +3048,7 @@ function createClient2(options) {
|
|
|
2990
3048
|
// events). The SDK default of 2 silent retries stacked under it: one 5xx
|
|
2991
3049
|
// cost up to 3 hidden requests plus SDK sleeps before the loop even saw it.
|
|
2992
3050
|
maxRetries: 0,
|
|
2993
|
-
...
|
|
3051
|
+
...defaultHeaders ? { defaultHeaders } : {}
|
|
2994
3052
|
});
|
|
2995
3053
|
if (!options.fetch) {
|
|
2996
3054
|
if (openaiClientCache.size >= 8) {
|
|
@@ -5747,19 +5805,25 @@ providerRegistry.register("local", {
|
|
|
5747
5805
|
}),
|
|
5748
5806
|
// Every supported local server exposes OpenAI-compatible `/v1/embeddings`
|
|
5749
5807
|
// (the model must be an embedding model). None has an input-type parameter.
|
|
5750
|
-
embed: (request) => embedOpenAICompatible(
|
|
5751
|
-
|
|
5752
|
-
|
|
5753
|
-
|
|
5754
|
-
|
|
5808
|
+
embed: (request) => embedOpenAICompatible(
|
|
5809
|
+
{ ...request, apiKey: localBearerKey(request.apiKey) },
|
|
5810
|
+
{
|
|
5811
|
+
provider: "local",
|
|
5812
|
+
baseUrl: requireLocalBaseUrl(request.baseUrl),
|
|
5813
|
+
wireModel: localWireModelId(request.model)
|
|
5814
|
+
}
|
|
5815
|
+
),
|
|
5755
5816
|
embedBatchSize: LOCAL_EMBED_BATCH_SIZE,
|
|
5756
5817
|
// llama.cpp (`llama-server --rerank`) and vLLM serve `/v1/rerank`; Ollama and
|
|
5757
5818
|
// LM Studio don't, and answer with a 404 ProviderError.
|
|
5758
|
-
rerank: (request) => rerankCohereCompatible(
|
|
5759
|
-
|
|
5760
|
-
|
|
5761
|
-
|
|
5762
|
-
|
|
5819
|
+
rerank: (request) => rerankCohereCompatible(
|
|
5820
|
+
{ ...request, apiKey: localBearerKey(request.apiKey) },
|
|
5821
|
+
{
|
|
5822
|
+
provider: "local",
|
|
5823
|
+
baseUrl: requireLocalBaseUrl(request.baseUrl),
|
|
5824
|
+
wireModel: localWireModelId(request.model)
|
|
5825
|
+
}
|
|
5826
|
+
)
|
|
5763
5827
|
});
|
|
5764
5828
|
function requireLocalBaseUrl(baseUrl) {
|
|
5765
5829
|
if (!baseUrl) {
|
|
@@ -6133,6 +6197,13 @@ function formatChatError(error) {
|
|
|
6133
6197
|
"Check your connection before trying again."
|
|
6134
6198
|
);
|
|
6135
6199
|
}
|
|
6200
|
+
if (base.provider === "local" && (base.source === "auth" || base.statusCode === 401)) {
|
|
6201
|
+
return present(
|
|
6202
|
+
"auth",
|
|
6203
|
+
"The local server rejected its key",
|
|
6204
|
+
"Check the endpoint's key under Local models in AI Providers settings."
|
|
6205
|
+
);
|
|
6206
|
+
}
|
|
6136
6207
|
if (base.source === "auth" || base.statusCode === 401) {
|
|
6137
6208
|
return present(
|
|
6138
6209
|
"auth",
|
|
@@ -6506,6 +6577,7 @@ function palsuRerankScore(query, document) {
|
|
|
6506
6577
|
EventStream,
|
|
6507
6578
|
FAST_MODE_SUFFIX,
|
|
6508
6579
|
GGAIError,
|
|
6580
|
+
LOCAL_NO_API_KEY,
|
|
6509
6581
|
PRECONNECT_INTERVAL_MS,
|
|
6510
6582
|
ProviderError,
|
|
6511
6583
|
REDACTION_MARKER,
|
|
@@ -6528,6 +6600,7 @@ function palsuRerankScore(query, document) {
|
|
|
6528
6600
|
isHardBillingMessage,
|
|
6529
6601
|
isUsageLimitError,
|
|
6530
6602
|
isValidToolCallName,
|
|
6603
|
+
localBearerKey,
|
|
6531
6604
|
localWireModelId,
|
|
6532
6605
|
opensTurn,
|
|
6533
6606
|
palsuAssistantMessage,
|