@kenkaiiii/gg-ai 5.87.3 → 5.88.1
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 +302 -24
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +49 -1
- package/dist/index.d.ts +49 -1
- package/dist/index.js +299 -24
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
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
|
+
PRECONNECT_INTERVAL_MS: () => PRECONNECT_INTERVAL_MS,
|
|
38
39
|
ProviderError: () => ProviderError,
|
|
39
40
|
REDACTION_MARKER: () => REDACTED,
|
|
40
41
|
ResponseStalledError: () => ResponseStalledError,
|
|
@@ -66,6 +67,8 @@ __export(index_exports, {
|
|
|
66
67
|
palsuToolCall: () => palsuToolCall,
|
|
67
68
|
parseFastModeRejection: () => parseFastModeRejection,
|
|
68
69
|
pendingClaudeCodeVersionRefresh: () => pendingClaudeCodeVersionRefresh,
|
|
70
|
+
preconnectOrigin: () => preconnectOrigin,
|
|
71
|
+
preconnectProvider: () => preconnectProvider,
|
|
69
72
|
prewarmAnthropicCache: () => prewarmAnthropicCache,
|
|
70
73
|
providerRegistry: () => providerRegistry,
|
|
71
74
|
redactText: () => redactText,
|
|
@@ -488,6 +491,26 @@ function providerGuidance(provider, message, statusCode) {
|
|
|
488
491
|
// src/providers/anthropic.ts
|
|
489
492
|
var import_sdk = __toESM(require("@anthropic-ai/sdk"), 1);
|
|
490
493
|
|
|
494
|
+
// src/providers/cache-minimums.ts
|
|
495
|
+
var ANTHROPIC_MIN_CACHEABLE_TOKENS = [
|
|
496
|
+
[/haiku-4-5|opus-4-[56]/, 4096],
|
|
497
|
+
[/haiku-3-5|haiku-3\b/, 2048],
|
|
498
|
+
[/[a-z]-(?:[5-9]|\d{2})(?:-|$)/, 512],
|
|
499
|
+
// 5.x and later families (family name, then major)
|
|
500
|
+
[/sonnet-4|opus-4|sonnet-3-7/, 1024]
|
|
501
|
+
];
|
|
502
|
+
function anthropicMinCacheableTokens(model) {
|
|
503
|
+
for (const [pattern, min] of ANTHROPIC_MIN_CACHEABLE_TOKENS) {
|
|
504
|
+
if (pattern.test(model)) return min;
|
|
505
|
+
}
|
|
506
|
+
return 1024;
|
|
507
|
+
}
|
|
508
|
+
function estimatePrefixTokens(...parts) {
|
|
509
|
+
let chars = 0;
|
|
510
|
+
for (const part of parts) if (part !== void 0) chars += JSON.stringify(part).length;
|
|
511
|
+
return Math.ceil(chars / 3.5);
|
|
512
|
+
}
|
|
513
|
+
|
|
491
514
|
// src/utils/event-stream.ts
|
|
492
515
|
var EventStream = class {
|
|
493
516
|
queue = [];
|
|
@@ -1485,6 +1508,41 @@ function toolResultVideos(content) {
|
|
|
1485
1508
|
if (typeof content === "string") return [];
|
|
1486
1509
|
return content.filter((b) => b.type === "video");
|
|
1487
1510
|
}
|
|
1511
|
+
function planDeferredTools(tools, catalog, messages) {
|
|
1512
|
+
if (!catalog?.length) return void 0;
|
|
1513
|
+
const byName = /* @__PURE__ */ new Map();
|
|
1514
|
+
for (const tool of catalog) if (!byName.has(tool.name)) byName.set(tool.name, tool);
|
|
1515
|
+
const loaded = /* @__PURE__ */ new Set();
|
|
1516
|
+
for (const message of messages) {
|
|
1517
|
+
if (message.role !== "tool") continue;
|
|
1518
|
+
for (const result of message.content) {
|
|
1519
|
+
for (const name of result.loadedTools ?? []) if (byName.has(name)) loaded.add(name);
|
|
1520
|
+
}
|
|
1521
|
+
}
|
|
1522
|
+
const live = (tools ?? []).filter((tool) => !(byName.has(tool.name) && loaded.has(tool.name)));
|
|
1523
|
+
if (live.length === 0) return void 0;
|
|
1524
|
+
const liveNames = new Set(live.map((tool) => tool.name));
|
|
1525
|
+
const deferred = [...byName.values()].filter((tool) => !liveNames.has(tool.name));
|
|
1526
|
+
return { live, deferred, loaded, byName };
|
|
1527
|
+
}
|
|
1528
|
+
function supportsAnthropicDeferredTools(model) {
|
|
1529
|
+
return /opus-4[-.][5-9]|sonnet-4[-.][5-9]|haiku-4[-.]5|opus-5|sonnet-5|haiku-5|fable-5|mythos-5/.test(
|
|
1530
|
+
model
|
|
1531
|
+
);
|
|
1532
|
+
}
|
|
1533
|
+
function supportsResponsesToolSearch(model) {
|
|
1534
|
+
return /^gpt-(5\.[4-9]|[6-9])/.test(model);
|
|
1535
|
+
}
|
|
1536
|
+
function usesDeferredToolLoading(options) {
|
|
1537
|
+
if (options.provider === "anthropic") {
|
|
1538
|
+
const firstParty = !options.baseUrl || options.baseUrl.includes("api.anthropic.com");
|
|
1539
|
+
return firstParty && supportsAnthropicDeferredTools(options.model);
|
|
1540
|
+
}
|
|
1541
|
+
if (options.provider === "openai" && options.accountId) {
|
|
1542
|
+
return supportsResponsesToolSearch(options.model);
|
|
1543
|
+
}
|
|
1544
|
+
return false;
|
|
1545
|
+
}
|
|
1488
1546
|
function toAnthropicCacheControl(retention, baseUrl) {
|
|
1489
1547
|
const resolved = retention ?? "short";
|
|
1490
1548
|
if (resolved === "none") return void 0;
|
|
@@ -1527,6 +1585,8 @@ function toAnthropicMessages(messages, cacheControl, options) {
|
|
|
1527
1585
|
const keepFallbackBlocks = options?.fallbackBlocks === true;
|
|
1528
1586
|
const droppedToolCallIds = /* @__PURE__ */ new Set();
|
|
1529
1587
|
const unresolvedServerToolIds = unresolvedServerToolUseIds(messages);
|
|
1588
|
+
const toolReferences = options?.toolReferences;
|
|
1589
|
+
const referencedTools = /* @__PURE__ */ new Set();
|
|
1530
1590
|
const trajectoryStartIdx = messages.reduce(
|
|
1531
1591
|
(last, m, i) => opensTurn(m) ? i : last,
|
|
1532
1592
|
-1
|
|
@@ -1589,16 +1649,43 @@ function toAnthropicMessages(messages, cacheControl, options) {
|
|
|
1589
1649
|
if (msg.role === "tool") {
|
|
1590
1650
|
const results = droppedToolCallIds.size ? msg.content.filter((r) => !droppedToolCallIds.has(r.toolCallId)) : msg.content;
|
|
1591
1651
|
if (results.length === 0) continue;
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1652
|
+
const trailing = [];
|
|
1653
|
+
const blocks = results.map((result) => {
|
|
1654
|
+
const toolUseId = remapAnthropicToolCallId(result.toolCallId, idMap);
|
|
1655
|
+
const refs = toolReferences ? (result.loadedTools ?? []).filter(
|
|
1656
|
+
(name) => toolReferences.has(name) && !referencedTools.has(name)
|
|
1657
|
+
) : [];
|
|
1658
|
+
if (refs.length === 0) {
|
|
1659
|
+
return {
|
|
1660
|
+
type: "tool_result",
|
|
1661
|
+
tool_use_id: toolUseId,
|
|
1662
|
+
content: toAnthropicToolResultContent(result.content),
|
|
1663
|
+
is_error: result.isError
|
|
1664
|
+
};
|
|
1665
|
+
}
|
|
1666
|
+
for (const name of refs) referencedTools.add(name);
|
|
1667
|
+
const original = toAnthropicToolResultContent(result.content);
|
|
1668
|
+
const parts = typeof original === "string" ? [{ type: "text", text: original }] : original;
|
|
1669
|
+
const first = parts.findIndex((part) => part.type === "text" && part.text !== "");
|
|
1670
|
+
parts.forEach((part, index) => {
|
|
1671
|
+
if (part.type === "text" && part.text === "") return;
|
|
1672
|
+
trailing.push(
|
|
1673
|
+
index === first && part.type === "text" ? { type: "text", text: `Result of tool call ${toolUseId}:
|
|
1674
|
+
${part.text}` } : part
|
|
1675
|
+
);
|
|
1676
|
+
});
|
|
1677
|
+
return {
|
|
1597
1678
|
type: "tool_result",
|
|
1598
|
-
tool_use_id:
|
|
1599
|
-
content:
|
|
1679
|
+
tool_use_id: toolUseId,
|
|
1680
|
+
content: refs.map((name) => ({ type: "tool_reference", tool_name: name })),
|
|
1600
1681
|
is_error: result.isError
|
|
1601
|
-
}
|
|
1682
|
+
};
|
|
1683
|
+
});
|
|
1684
|
+
out.push({
|
|
1685
|
+
role: "user",
|
|
1686
|
+
// Cast covers the video and tool_reference blocks, which aren't in this
|
|
1687
|
+
// SDK's first-party tool_result types.
|
|
1688
|
+
content: [...blocks, ...trailing]
|
|
1602
1689
|
});
|
|
1603
1690
|
}
|
|
1604
1691
|
}
|
|
@@ -1614,7 +1701,8 @@ function toAnthropicMessages(messages, cacheControl, options) {
|
|
|
1614
1701
|
markAnthropicCacheBreakpoint(out, tail, cacheControl);
|
|
1615
1702
|
} else {
|
|
1616
1703
|
if (anchor !== void 0) markAnthropicCacheBreakpoint(out, anchor, cacheControl);
|
|
1617
|
-
|
|
1704
|
+
const longRun = isLongToolRun(messages, trajectoryStartIdx);
|
|
1705
|
+
markAnthropicCacheBreakpoint(out, tail, longRun ? cacheControl : { type: "ephemeral" });
|
|
1618
1706
|
}
|
|
1619
1707
|
} else {
|
|
1620
1708
|
markAnthropicCacheBreakpoint(out, tail, cacheControl);
|
|
@@ -1644,6 +1732,28 @@ function toAnthropicMessages(messages, cacheControl, options) {
|
|
|
1644
1732
|
}
|
|
1645
1733
|
return { system, messages: out };
|
|
1646
1734
|
}
|
|
1735
|
+
var BLOCKING_TOOL_NAMES = /* @__PURE__ */ new Set([
|
|
1736
|
+
"wait_agent",
|
|
1737
|
+
"task_output",
|
|
1738
|
+
"subagent",
|
|
1739
|
+
"ask_user"
|
|
1740
|
+
]);
|
|
1741
|
+
var LONG_RUN_ROUNDS = 6;
|
|
1742
|
+
function isLongToolRun(messages, trajectoryStartIdx) {
|
|
1743
|
+
let rounds = 0;
|
|
1744
|
+
for (let i = Math.max(0, trajectoryStartIdx + 1); i < messages.length; i++) {
|
|
1745
|
+
const m = messages[i];
|
|
1746
|
+
if (m?.role !== "assistant" || typeof m.content === "string") continue;
|
|
1747
|
+
let called = false;
|
|
1748
|
+
for (const part of m.content) {
|
|
1749
|
+
if (part.type !== "tool_call") continue;
|
|
1750
|
+
called = true;
|
|
1751
|
+
if (BLOCKING_TOOL_NAMES.has(part.name)) return true;
|
|
1752
|
+
}
|
|
1753
|
+
if (called && ++rounds >= LONG_RUN_ROUNDS) return true;
|
|
1754
|
+
}
|
|
1755
|
+
return false;
|
|
1756
|
+
}
|
|
1647
1757
|
function markAnthropicCacheBreakpoint(out, index, cacheControl) {
|
|
1648
1758
|
const message = out[index];
|
|
1649
1759
|
if (!message) return;
|
|
@@ -1664,6 +1774,18 @@ function markAnthropicCacheBreakpoint(out, index, cacheControl) {
|
|
|
1664
1774
|
}
|
|
1665
1775
|
}
|
|
1666
1776
|
function toAnthropicTools(tools, options) {
|
|
1777
|
+
const deferred = (options?.deferred ?? []).map(
|
|
1778
|
+
(tool) => ({
|
|
1779
|
+
name: tool.name,
|
|
1780
|
+
description: tool.description,
|
|
1781
|
+
input_schema: tool.rawInputSchema ?? zodToJsonSchema(tool.parameters),
|
|
1782
|
+
...options?.enableFineGrainedToolStreaming ? { eager_input_streaming: true } : {},
|
|
1783
|
+
defer_loading: true
|
|
1784
|
+
})
|
|
1785
|
+
);
|
|
1786
|
+
return [...toAnthropicLiveTools(tools, options), ...deferred];
|
|
1787
|
+
}
|
|
1788
|
+
function toAnthropicLiveTools(tools, options) {
|
|
1667
1789
|
return tools.map((tool, index) => {
|
|
1668
1790
|
const anthropicTool = {
|
|
1669
1791
|
name: tool.name,
|
|
@@ -1950,6 +2072,7 @@ function parseToolArguments(argsJson) {
|
|
|
1950
2072
|
// src/utils/provider-fetch.ts
|
|
1951
2073
|
var import_undici = require("undici");
|
|
1952
2074
|
var PROVIDER_TRANSPORT_TIMEOUT_MS = 45 * 6e4;
|
|
2075
|
+
var PROVIDER_KEEP_ALIVE_TIMEOUT_MS = 3e4;
|
|
1953
2076
|
function nodeUsesEnvProxy({
|
|
1954
2077
|
env = process.env,
|
|
1955
2078
|
execArgv = process.execArgv,
|
|
@@ -1962,7 +2085,11 @@ function nodeUsesEnvProxy({
|
|
|
1962
2085
|
return major >= 24 || major === 22 && minor >= 21;
|
|
1963
2086
|
}
|
|
1964
2087
|
function createProviderFetch(timeoutMs, { useEnvProxy = nodeUsesEnvProxy() } = {}) {
|
|
1965
|
-
const timeouts = {
|
|
2088
|
+
const timeouts = {
|
|
2089
|
+
headersTimeout: timeoutMs,
|
|
2090
|
+
bodyTimeout: timeoutMs,
|
|
2091
|
+
keepAliveTimeout: PROVIDER_KEEP_ALIVE_TIMEOUT_MS
|
|
2092
|
+
};
|
|
1966
2093
|
const dispatcher = useEnvProxy ? new import_undici.EnvHttpProxyAgent(timeouts) : new import_undici.Agent(timeouts);
|
|
1967
2094
|
const builtinFetch = globalThis.fetch;
|
|
1968
2095
|
const providerFetch2 = async (input, init2) => {
|
|
@@ -2117,6 +2244,9 @@ async function prewarmAnthropicCache(options) {
|
|
|
2117
2244
|
// prewarmed prompt cache actually hits — both are gated by the flag.
|
|
2118
2245
|
enableFineGrainedToolStreaming: fineGrainedToolStreamingEnabled()
|
|
2119
2246
|
}) : void 0;
|
|
2247
|
+
if (estimatePrefixTokens(fullSystem, tools) < anthropicMinCacheableTokens(options.model)) {
|
|
2248
|
+
return;
|
|
2249
|
+
}
|
|
2120
2250
|
await client.messages.create(
|
|
2121
2251
|
{
|
|
2122
2252
|
model: options.model,
|
|
@@ -2157,8 +2287,11 @@ async function* runStream(options) {
|
|
|
2157
2287
|
const downgradedMessages = downgradeUnsupportedVideos(downgradedImages, options.supportsVideo);
|
|
2158
2288
|
const fallbackKey = serverFallbackKey(options);
|
|
2159
2289
|
const useServerFallback = options.provider !== "minimax" && isDirectAnthropicApi(options.baseUrl) && !anthropicServerFallback.disabled.has(fallbackKey);
|
|
2290
|
+
const deferredPlan = options.provider === "anthropic" && isDirectAnthropicApi(options.baseUrl) && supportsAnthropicDeferredTools(options.model) ? planDeferredTools(options.tools, options.deferredTools, downgradedMessages) : void 0;
|
|
2291
|
+
const toolReferences = deferredPlan?.loaded;
|
|
2160
2292
|
const { system: rawSystem, messages } = toAnthropicMessages(downgradedMessages, cacheControl, {
|
|
2161
|
-
fallbackBlocks: useServerFallback
|
|
2293
|
+
fallbackBlocks: useServerFallback,
|
|
2294
|
+
toolReferences
|
|
2162
2295
|
});
|
|
2163
2296
|
const useFastMode = options.speed === "fast" && options.provider === "anthropic" && isDirectAnthropicApi(options.baseUrl);
|
|
2164
2297
|
const system = isOAuth ? [
|
|
@@ -2200,20 +2333,20 @@ async function* runStream(options) {
|
|
|
2200
2333
|
...options.temperature != null && !thinking ? { temperature: options.temperature } : {},
|
|
2201
2334
|
...options.topP != null ? { top_p: options.topP } : {},
|
|
2202
2335
|
...options.stop ? { stop_sequences: options.stop } : {},
|
|
2203
|
-
...options.tools?.length || options.serverTools?.length || options.webSearch ? (() => {
|
|
2336
|
+
...(deferredPlan?.live ?? options.tools)?.length || options.serverTools?.length || options.webSearch ? (() => {
|
|
2204
2337
|
const reservedServerNames = /* @__PURE__ */ new Set();
|
|
2205
2338
|
if (options.webSearch) reservedServerNames.add("web_search");
|
|
2206
2339
|
for (const t of options.serverTools ?? []) {
|
|
2207
2340
|
const name = t.name;
|
|
2208
2341
|
if (name) reservedServerNames.add(name);
|
|
2209
2342
|
}
|
|
2210
|
-
const
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
}
|
|
2216
|
-
) : [];
|
|
2343
|
+
const notReserved = (t) => !reservedServerNames.has(t.name);
|
|
2344
|
+
const liveTools = deferredPlan?.live ?? options.tools ?? [];
|
|
2345
|
+
const clientTools = liveTools.length ? toAnthropicTools(liveTools.filter(notReserved), {
|
|
2346
|
+
...supportsFirstPartyToolExtras && cacheControl ? { cacheControl } : {},
|
|
2347
|
+
...supportsFirstPartyToolExtras && fineGrainedToolStreamingEnabled() ? { enableFineGrainedToolStreaming: true } : {},
|
|
2348
|
+
...deferredPlan ? { deferred: deferredPlan.deferred.filter(notReserved) } : {}
|
|
2349
|
+
}) : [];
|
|
2217
2350
|
return {
|
|
2218
2351
|
tools: [
|
|
2219
2352
|
...clientTools,
|
|
@@ -2234,6 +2367,13 @@ async function* runStream(options) {
|
|
|
2234
2367
|
...useFastMode ? { speed: "fast" } : {},
|
|
2235
2368
|
stream: useStreaming
|
|
2236
2369
|
};
|
|
2370
|
+
if (options.prewarm && estimatePrefixTokens(baseParams.system, baseParams.tools) < anthropicMinCacheableTokens(options.model)) {
|
|
2371
|
+
return {
|
|
2372
|
+
message: { role: "assistant", content: [] },
|
|
2373
|
+
stopReason: "end_turn",
|
|
2374
|
+
usage: { inputTokens: 0, outputTokens: 0 }
|
|
2375
|
+
};
|
|
2376
|
+
}
|
|
2237
2377
|
const params = mergeProviderOptions(baseParams, options.providerOptions);
|
|
2238
2378
|
const hasAdaptiveThinking = isAdaptiveThinkingModel(options.model);
|
|
2239
2379
|
const betaHeaders = [
|
|
@@ -2267,7 +2407,10 @@ async function* runStream(options) {
|
|
|
2267
2407
|
const { fallbacks: _dropped, ...rest } = params;
|
|
2268
2408
|
const retryParams = {
|
|
2269
2409
|
...rest,
|
|
2270
|
-
messages: toAnthropicMessages(downgradedMessages, cacheControl, {
|
|
2410
|
+
messages: toAnthropicMessages(downgradedMessages, cacheControl, {
|
|
2411
|
+
fallbackBlocks: false,
|
|
2412
|
+
toolReferences
|
|
2413
|
+
}).messages
|
|
2271
2414
|
};
|
|
2272
2415
|
return create(
|
|
2273
2416
|
retryParams,
|
|
@@ -2843,6 +2986,10 @@ function createClient2(options) {
|
|
|
2843
2986
|
...options.baseUrl ? { baseURL: options.baseUrl } : {},
|
|
2844
2987
|
// Default transport lifts undici's 300s header/body caps (see provider-fetch.ts).
|
|
2845
2988
|
fetch: options.fetch ?? providerFetch,
|
|
2989
|
+
// The agent loop owns retries (classified backoff, Retry-After, UI retry
|
|
2990
|
+
// events). The SDK default of 2 silent retries stacked under it: one 5xx
|
|
2991
|
+
// cost up to 3 hidden requests plus SDK sleeps before the loop even saw it.
|
|
2992
|
+
maxRetries: 0,
|
|
2846
2993
|
...options.defaultHeaders ? { defaultHeaders: options.defaultHeaders } : {}
|
|
2847
2994
|
});
|
|
2848
2995
|
if (!options.fetch) {
|
|
@@ -3617,6 +3764,15 @@ async function* consumeResponsesEvents(events, ctx) {
|
|
|
3617
3764
|
droppedToolCalls
|
|
3618
3765
|
});
|
|
3619
3766
|
}
|
|
3767
|
+
const addedOrder = [...toolCalls.keys()];
|
|
3768
|
+
const toolSlots = orderedItems.flatMap((e, i) => e.kind === "tool" ? [i] : []);
|
|
3769
|
+
const sortedTools = toolSlots.map((i) => orderedItems[i]).sort(
|
|
3770
|
+
(a, b) => a?.kind === "tool" && b?.kind === "tool" ? addedOrder.indexOf(a.id) - addedOrder.indexOf(b.id) : 0
|
|
3771
|
+
);
|
|
3772
|
+
toolSlots.forEach((slot, k) => {
|
|
3773
|
+
const entry = sortedTools[k];
|
|
3774
|
+
if (entry) orderedItems[slot] = entry;
|
|
3775
|
+
});
|
|
3620
3776
|
const seenTool = /* @__PURE__ */ new Set();
|
|
3621
3777
|
let textInserted = false;
|
|
3622
3778
|
for (const entry of orderedItems) {
|
|
@@ -3693,6 +3849,8 @@ function toResponsesInput(messages, options) {
|
|
|
3693
3849
|
let system;
|
|
3694
3850
|
const input = [];
|
|
3695
3851
|
const idMap = /* @__PURE__ */ new Map();
|
|
3852
|
+
const loadedTools = /* @__PURE__ */ new Set();
|
|
3853
|
+
let toolLoads = 0;
|
|
3696
3854
|
for (const msg of messages) {
|
|
3697
3855
|
if (msg.role === "system") {
|
|
3698
3856
|
system = msg.content;
|
|
@@ -3746,6 +3904,28 @@ function toResponsesInput(messages, options) {
|
|
|
3746
3904
|
call_id: mapId(callId, idMap),
|
|
3747
3905
|
output: text.length > 0 ? text : "(see attached image)"
|
|
3748
3906
|
});
|
|
3907
|
+
const loads = options.toolSearchLoads;
|
|
3908
|
+
const names = loads ? (result.loadedTools ?? []).filter((name) => loads.has(name) && !loadedTools.has(name)) : [];
|
|
3909
|
+
if (loads && names.length > 0) {
|
|
3910
|
+
for (const name of names) loadedTools.add(name);
|
|
3911
|
+
const loadId = `gg_tool_load_${++toolLoads}`;
|
|
3912
|
+
input.push(
|
|
3913
|
+
{
|
|
3914
|
+
type: "tool_search_call",
|
|
3915
|
+
call_id: loadId,
|
|
3916
|
+
execution: "client",
|
|
3917
|
+
status: "completed",
|
|
3918
|
+
arguments: { query: names.join(" "), limit: names.length }
|
|
3919
|
+
},
|
|
3920
|
+
{
|
|
3921
|
+
type: "tool_search_output",
|
|
3922
|
+
call_id: loadId,
|
|
3923
|
+
execution: "client",
|
|
3924
|
+
status: "completed",
|
|
3925
|
+
tools: names.map((name) => loads.get(name))
|
|
3926
|
+
}
|
|
3927
|
+
);
|
|
3928
|
+
}
|
|
3749
3929
|
if (options.supportsImages !== false && Array.isArray(result.content)) {
|
|
3750
3930
|
for (const block of result.content) {
|
|
3751
3931
|
if (block.type === "image") toolImages.push(block);
|
|
@@ -3844,8 +4024,19 @@ async function* runStream3(options, retriedWithoutReasoning = false) {
|
|
|
3844
4024
|
const url = `${baseUrl}/codex/responses`;
|
|
3845
4025
|
const downgradedImages = downgradeUnsupportedImages(options.messages, options.supportsImages);
|
|
3846
4026
|
const downgraded = downgradeUnsupportedVideos(downgradedImages, options.supportsVideo);
|
|
4027
|
+
const deferredPlan = supportsResponsesToolSearch(options.model) ? planDeferredTools(options.tools, options.deferredTools, downgraded) : void 0;
|
|
4028
|
+
const strictTools = options.strictTools ?? true;
|
|
4029
|
+
const toolSearchLoads = deferredPlan ? new Map(
|
|
4030
|
+
[...deferredPlan.loaded].map((name) => {
|
|
4031
|
+
const tool = deferredPlan.byName.get(name);
|
|
4032
|
+
const [wire] = tool ? toCodexTools([tool], strictTools) : [];
|
|
4033
|
+
return [name, { ...wire, defer_loading: true }];
|
|
4034
|
+
})
|
|
4035
|
+
) : void 0;
|
|
4036
|
+
const liveTools = deferredPlan?.live ?? options.tools;
|
|
3847
4037
|
const { system, input } = toResponsesInput(downgraded, {
|
|
3848
4038
|
supportsImages: options.supportsImages,
|
|
4039
|
+
toolSearchLoads,
|
|
3849
4040
|
mapId: remapCodexId,
|
|
3850
4041
|
// Stamped reasoning belongs to another transport (e.g. Grok's) and would
|
|
3851
4042
|
// be rejected here; Codex's own items are never stamped.
|
|
@@ -3859,12 +4050,12 @@ async function* runStream3(options, retriedWithoutReasoning = false) {
|
|
|
3859
4050
|
stream: true,
|
|
3860
4051
|
instructions: system,
|
|
3861
4052
|
input,
|
|
3862
|
-
tool_choice: toCodexToolChoice(options.toolChoice,
|
|
4053
|
+
tool_choice: toCodexToolChoice(options.toolChoice, liveTools),
|
|
3863
4054
|
parallel_tool_calls: !liteShape,
|
|
3864
4055
|
include: ["reasoning.encrypted_content"]
|
|
3865
4056
|
};
|
|
3866
|
-
if (
|
|
3867
|
-
body.tools = toCodexTools(
|
|
4057
|
+
if (liveTools?.length) {
|
|
4058
|
+
body.tools = toCodexTools(liveTools, strictTools);
|
|
3868
4059
|
}
|
|
3869
4060
|
body.prompt_cache_key = normalizePromptCacheKey(options.promptCacheKey ?? "ggcoder");
|
|
3870
4061
|
if (options.temperature != null && !options.thinking) {
|
|
@@ -5606,7 +5797,7 @@ function stream(requested) {
|
|
|
5606
5797
|
observePreparedContext(
|
|
5607
5798
|
replayable === sanitized ? wireMessages : replayable,
|
|
5608
5799
|
messages,
|
|
5609
|
-
options
|
|
5800
|
+
observedTools(options, messages)
|
|
5610
5801
|
)
|
|
5611
5802
|
);
|
|
5612
5803
|
} catch {
|
|
@@ -5614,6 +5805,11 @@ function stream(requested) {
|
|
|
5614
5805
|
}
|
|
5615
5806
|
return entry.stream(messages === options.messages ? options : { ...options, messages });
|
|
5616
5807
|
}
|
|
5808
|
+
function observedTools(options, messages) {
|
|
5809
|
+
if (!usesDeferredToolLoading(options)) return options.tools ?? [];
|
|
5810
|
+
const plan = planDeferredTools(options.tools, options.deferredTools, messages);
|
|
5811
|
+
return plan ? [...plan.live, ...plan.deferred] : options.tools ?? [];
|
|
5812
|
+
}
|
|
5617
5813
|
function stripMessageProvenance(messages) {
|
|
5618
5814
|
let stripped;
|
|
5619
5815
|
for (let index = 0; index < messages.length; index++) {
|
|
@@ -5753,6 +5949,85 @@ function l2Normalize(vector) {
|
|
|
5753
5949
|
return vector.map((value) => value / norm);
|
|
5754
5950
|
}
|
|
5755
5951
|
|
|
5952
|
+
// src/utils/preconnect.ts
|
|
5953
|
+
var PRECONNECT_INTERVAL_MS = 3e4;
|
|
5954
|
+
function defaultBaseUrl(provider, accountId) {
|
|
5955
|
+
switch (provider) {
|
|
5956
|
+
case "anthropic":
|
|
5957
|
+
return "https://api.anthropic.com";
|
|
5958
|
+
case "openai":
|
|
5959
|
+
return accountId ? "https://chatgpt.com/backend-api" : "https://api.openai.com/v1";
|
|
5960
|
+
case "gemini":
|
|
5961
|
+
return "https://cloudcode-pa.googleapis.com";
|
|
5962
|
+
case "glm":
|
|
5963
|
+
return "https://api.z.ai/api/coding/paas/v4";
|
|
5964
|
+
case "moonshot":
|
|
5965
|
+
return "https://api.moonshot.ai/v1";
|
|
5966
|
+
case "deepseek":
|
|
5967
|
+
return "https://api.deepseek.com/v1";
|
|
5968
|
+
case "openrouter":
|
|
5969
|
+
return "https://openrouter.ai/api/v1";
|
|
5970
|
+
case "xiaomi":
|
|
5971
|
+
return "https://token-plan-sgp.xiaomimimo.com/v1";
|
|
5972
|
+
case "minimax":
|
|
5973
|
+
return "https://api.minimax.io/anthropic";
|
|
5974
|
+
case "xai":
|
|
5975
|
+
return "https://api.x.ai/v1";
|
|
5976
|
+
case "huggingface":
|
|
5977
|
+
return "https://router.huggingface.co/v1";
|
|
5978
|
+
case "sakana":
|
|
5979
|
+
return "https://api.sakana.ai/v1";
|
|
5980
|
+
case "local":
|
|
5981
|
+
case "palsu":
|
|
5982
|
+
return void 0;
|
|
5983
|
+
}
|
|
5984
|
+
}
|
|
5985
|
+
function isLocalHost(hostname) {
|
|
5986
|
+
const host = hostname.replace(/^\[|\]$/g, "").toLowerCase();
|
|
5987
|
+
if (host === "localhost" || host.endsWith(".localhost") || host.endsWith(".local")) return true;
|
|
5988
|
+
if (host === "::1" || host === "0.0.0.0") return true;
|
|
5989
|
+
if (host.includes(":")) return /^(f[cd]|fe[89ab])/.test(host);
|
|
5990
|
+
const octets = host.split(".").map(Number);
|
|
5991
|
+
if (octets.length !== 4 || octets.some((n) => !Number.isInteger(n))) return false;
|
|
5992
|
+
const [a = 0, b = 0] = octets;
|
|
5993
|
+
return a === 127 || a === 10 || a === 192 && b === 168 || a === 172 && b >= 16 && b <= 31;
|
|
5994
|
+
}
|
|
5995
|
+
function preconnectTarget(options) {
|
|
5996
|
+
const raw = options.baseUrl ?? defaultBaseUrl(options.provider, options.accountId);
|
|
5997
|
+
if (!raw || options.provider === "local" || options.provider === "palsu") return void 0;
|
|
5998
|
+
let url;
|
|
5999
|
+
try {
|
|
6000
|
+
url = new URL(raw);
|
|
6001
|
+
} catch {
|
|
6002
|
+
return void 0;
|
|
6003
|
+
}
|
|
6004
|
+
if (url.protocol !== "https:" || isLocalHost(url.hostname)) return void 0;
|
|
6005
|
+
url.pathname = url.pathname.replace(/\/+$/, "") || "/";
|
|
6006
|
+
url.search = "";
|
|
6007
|
+
url.hash = "";
|
|
6008
|
+
return url;
|
|
6009
|
+
}
|
|
6010
|
+
function preconnectOrigin(options) {
|
|
6011
|
+
return preconnectTarget(options)?.origin;
|
|
6012
|
+
}
|
|
6013
|
+
function preconnectProvider(options) {
|
|
6014
|
+
const target = preconnectTarget(options);
|
|
6015
|
+
if (!target) return void 0;
|
|
6016
|
+
const origin = target.origin;
|
|
6017
|
+
const now = options.now ?? Date.now();
|
|
6018
|
+
const last = options.warmedAt.get(origin);
|
|
6019
|
+
if (last !== void 0 && now - last < PRECONNECT_INTERVAL_MS) return void 0;
|
|
6020
|
+
options.warmedAt.set(origin, now);
|
|
6021
|
+
const fetchImpl = options.fetch ?? providerFetch;
|
|
6022
|
+
void fetchImpl(target.href, {
|
|
6023
|
+
method: "HEAD",
|
|
6024
|
+
redirect: "manual",
|
|
6025
|
+
signal: AbortSignal.timeout(1e4)
|
|
6026
|
+
}).then((response) => response.body?.cancel()).catch(() => {
|
|
6027
|
+
});
|
|
6028
|
+
return origin;
|
|
6029
|
+
}
|
|
6030
|
+
|
|
5756
6031
|
// src/chat-error.ts
|
|
5757
6032
|
function causeCode(error) {
|
|
5758
6033
|
if (!(error instanceof Error) || !error.cause || typeof error.cause !== "object") return "";
|
|
@@ -6231,6 +6506,7 @@ function palsuRerankScore(query, document) {
|
|
|
6231
6506
|
EventStream,
|
|
6232
6507
|
FAST_MODE_SUFFIX,
|
|
6233
6508
|
GGAIError,
|
|
6509
|
+
PRECONNECT_INTERVAL_MS,
|
|
6234
6510
|
ProviderError,
|
|
6235
6511
|
REDACTION_MARKER,
|
|
6236
6512
|
ResponseStalledError,
|
|
@@ -6262,6 +6538,8 @@ function palsuRerankScore(query, document) {
|
|
|
6262
6538
|
palsuToolCall,
|
|
6263
6539
|
parseFastModeRejection,
|
|
6264
6540
|
pendingClaudeCodeVersionRefresh,
|
|
6541
|
+
preconnectOrigin,
|
|
6542
|
+
preconnectProvider,
|
|
6265
6543
|
prewarmAnthropicCache,
|
|
6266
6544
|
providerRegistry,
|
|
6267
6545
|
redactText,
|