@jeffreycao/copilot-api 1.10.3 → 1.10.5
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 +53 -6
- package/README.zh-CN.md +52 -5
- package/dist/main.js +4 -2
- package/dist/main.js.map +1 -1
- package/dist/mcp-cZ7TLr1M.js +37 -0
- package/dist/mcp-cZ7TLr1M.js.map +1 -0
- package/dist/{proxy-DQLzdeq3.js → proxy-CSO5SLia.js} +1 -1
- package/dist/{proxy-DQLzdeq3.js.map → proxy-CSO5SLia.js.map} +1 -1
- package/dist/{server-UsHsMP_2.js → server-DsfYz_GE.js} +279 -62
- package/dist/server-DsfYz_GE.js.map +1 -0
- package/dist/{start-C7_M_42Q.js → start-BkG22v1Z.js} +3 -3
- package/dist/{start-C7_M_42Q.js.map → start-BkG22v1Z.js.map} +1 -1
- package/dist/tool-search-CKe6hqnv.js +110 -0
- package/dist/tool-search-CKe6hqnv.js.map +1 -0
- package/package.json +2 -1
- package/dist/server-UsHsMP_2.js.map +0 -1
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { t as PATHS } from "./paths-DC-mqCY3.js";
|
|
2
2
|
import { D as generateTraceId, E as prepareMessageProxyHeaders, I as state, M as compactMessageSections, O as requestContext, P as compactSystemPromptStarts, T as prepareInteractionHeaders, _ as copilotWebSocketHeaders, c as getUUID, d as sleep, f as getCopilotUsage, g as copilotHeaders, h as copilotBaseUrl, j as compactAutoContinuePromptStarts, k as resolveTraceId$1, l as isNullish, m as forwardError, n as cacheModels, o as generateRequestIdFromPayload, p as HTTPError, s as getRootSessionId, u as parseUserIdMetadata, w as prepareForCompact } from "./utils-jHLgqAq2.js";
|
|
3
|
-
import {
|
|
3
|
+
import { a as isDeferredToolName, c as parseMcpToolSearchSentinel, d as shouldEnableResponsesToolSearch, i as isBridgeToolSearchName, l as resolveBridgeToolSearchName, o as listDeferredToolNames, r as formatToolSearchBridgeArguments, s as normalizeToolSearchBridgeArguments, t as BRIDGE_TOOL_SEARCH_NAME, u as selectDeferredToolsByNames } from "./tool-search-CKe6hqnv.js";
|
|
4
|
+
import { _ as setModelMappings, a as getConfig, c as getProviderConfig, d as isMessagesApiEnabled, f as isResponsesApiContextManagementModel, g as resolveMappedModel, i as getClaudeTokenMultiplier, l as getReasoningEffortForModel, m as isResponsesApiWebSocketEnabled, o as getExtraPromptForModel, p as isResponsesApiWebSearchEnabled, r as getAnthropicApiKey, s as getModelMappings, t as getProxyEnvDispatcher, u as getSmallModel } from "./proxy-CSO5SLia.js";
|
|
4
5
|
import consola from "consola";
|
|
5
6
|
import fs from "node:fs/promises";
|
|
6
7
|
import path from "node:path";
|
|
7
8
|
import { createHash } from "node:crypto";
|
|
9
|
+
import { z } from "zod";
|
|
8
10
|
import { Hono } from "hono";
|
|
9
11
|
import { cors } from "hono/cors";
|
|
10
12
|
import { logger } from "hono/logger";
|
|
@@ -12,7 +14,6 @@ import fs$1, { readFileSync } from "node:fs";
|
|
|
12
14
|
import { streamSSE } from "hono/streaming";
|
|
13
15
|
import util from "node:util";
|
|
14
16
|
import { events } from "fetch-event-stream";
|
|
15
|
-
import { z } from "zod";
|
|
16
17
|
import { WebSocket } from "undici";
|
|
17
18
|
//#region src/lib/request-auth.ts
|
|
18
19
|
function normalizeApiKeys(apiKeys) {
|
|
@@ -2705,7 +2706,7 @@ const buildResponsesWebSocketPoolKey = (payload, { requestId, subagentMarker })
|
|
|
2705
2706
|
const getResponsesWebSocketInitiator = (preparedHeaders) => {
|
|
2706
2707
|
return getHeaderValue(preparedHeaders, "x-initiator")?.toLowerCase() === "agent" ? "agent" : "user";
|
|
2707
2708
|
};
|
|
2708
|
-
const createPooledResponsesWebSocketStream = (request) =>
|
|
2709
|
+
const createPooledResponsesWebSocketStream = (request) => runResponsesWebSocketRequest(request);
|
|
2709
2710
|
const buildResponsesWebSocketPayload = (payload, initiator) => {
|
|
2710
2711
|
const websocketPayload = {
|
|
2711
2712
|
...payload,
|
|
@@ -2724,11 +2725,12 @@ const buildResponsesWebSocketUrl = (baseUrl) => {
|
|
|
2724
2725
|
return url.toString();
|
|
2725
2726
|
};
|
|
2726
2727
|
const responsesWebSocketPool = /* @__PURE__ */ new Map();
|
|
2727
|
-
const
|
|
2728
|
-
|
|
2729
|
-
const
|
|
2728
|
+
const responsesWebSocketActiveRequests = /* @__PURE__ */ new Map();
|
|
2729
|
+
const runResponsesWebSocketRequest = async function* (request) {
|
|
2730
|
+
const { entry, pooled } = getResponsesWebSocketRequestTarget(request);
|
|
2731
|
+
const release = acquireResponsesWebSocketEntry(request.poolKey, entry, pooled);
|
|
2730
2732
|
try {
|
|
2731
|
-
const websocket = await entry
|
|
2733
|
+
const websocket = await getReadyResponsesWebSocket(request.poolKey, entry, pooled);
|
|
2732
2734
|
websocket.send(JSON.stringify(request.payload));
|
|
2733
2735
|
for await (const data of createWebSocketMessageStream(websocket)) {
|
|
2734
2736
|
const chunk = createResponsesWebSocketStreamChunk(data);
|
|
@@ -2744,21 +2746,31 @@ const runResponsesWebSocketPoolRequest = async function* (request) {
|
|
|
2744
2746
|
release();
|
|
2745
2747
|
}
|
|
2746
2748
|
};
|
|
2747
|
-
const
|
|
2749
|
+
const getResponsesWebSocketRequestTarget = (request) => {
|
|
2750
|
+
if (getResponsesWebSocketActiveRequestCount(request.poolKey) > 0) return {
|
|
2751
|
+
entry: createResponsesWebSocketEntry(request),
|
|
2752
|
+
pooled: false
|
|
2753
|
+
};
|
|
2748
2754
|
const existing = responsesWebSocketPool.get(request.poolKey);
|
|
2749
2755
|
if (existing && !existing.closed) {
|
|
2750
2756
|
clearResponsesWebSocketIdleTimer(existing);
|
|
2751
|
-
return
|
|
2757
|
+
return {
|
|
2758
|
+
entry: existing,
|
|
2759
|
+
pooled: true
|
|
2760
|
+
};
|
|
2752
2761
|
}
|
|
2753
|
-
const entry =
|
|
2762
|
+
const entry = createResponsesWebSocketEntry(request);
|
|
2754
2763
|
responsesWebSocketPool.set(request.poolKey, entry);
|
|
2755
|
-
return
|
|
2764
|
+
return {
|
|
2765
|
+
entry,
|
|
2766
|
+
pooled: true
|
|
2767
|
+
};
|
|
2756
2768
|
};
|
|
2757
|
-
const
|
|
2769
|
+
const createResponsesWebSocketEntry = (request) => {
|
|
2758
2770
|
const entry = {
|
|
2759
2771
|
closed: false,
|
|
2760
2772
|
idleTimer: null,
|
|
2761
|
-
|
|
2773
|
+
requestCount: 0,
|
|
2762
2774
|
websocketPromise: openResponsesWebSocket({
|
|
2763
2775
|
headers: request.headers,
|
|
2764
2776
|
url: buildResponsesWebSocketUrl(copilotBaseUrl(state))
|
|
@@ -2776,23 +2788,34 @@ const createResponsesWebSocketPoolEntry = (request) => {
|
|
|
2776
2788
|
});
|
|
2777
2789
|
return entry;
|
|
2778
2790
|
};
|
|
2779
|
-
const
|
|
2780
|
-
clearResponsesWebSocketIdleTimer(entry);
|
|
2781
|
-
let releaseCurrent;
|
|
2782
|
-
const previousLock = entry.lock;
|
|
2783
|
-
entry.lock = new Promise((resolve) => {
|
|
2784
|
-
releaseCurrent = resolve;
|
|
2785
|
-
});
|
|
2786
|
-
await previousLock;
|
|
2791
|
+
const acquireResponsesWebSocketEntry = (poolKey, entry, pooled) => {
|
|
2787
2792
|
clearResponsesWebSocketIdleTimer(entry);
|
|
2793
|
+
incrementResponsesWebSocketActiveRequestCount(poolKey);
|
|
2794
|
+
entry.requestCount += 1;
|
|
2788
2795
|
let released = false;
|
|
2789
2796
|
return () => {
|
|
2790
2797
|
if (released) return;
|
|
2791
2798
|
released = true;
|
|
2792
|
-
|
|
2793
|
-
|
|
2799
|
+
entry.requestCount -= 1;
|
|
2800
|
+
decrementResponsesWebSocketActiveRequestCount(poolKey);
|
|
2801
|
+
if (entry.closed || entry.requestCount > 0) return;
|
|
2802
|
+
if (pooled && responsesWebSocketPool.get(poolKey) === entry) {
|
|
2803
|
+
scheduleResponsesWebSocketIdleClose(poolKey, entry);
|
|
2804
|
+
return;
|
|
2805
|
+
}
|
|
2806
|
+
removeResponsesWebSocketPoolEntry(poolKey, entry);
|
|
2794
2807
|
};
|
|
2795
2808
|
};
|
|
2809
|
+
const getReadyResponsesWebSocket = async (poolKey, entry, pooled) => {
|
|
2810
|
+
if (entry.closed) throw new Error("Responses websocket became unavailable before the request started");
|
|
2811
|
+
const websocket = await entry.websocketPromise;
|
|
2812
|
+
if (entry.closed || pooled && responsesWebSocketPool.get(poolKey) !== entry) throw new Error("Responses websocket became unavailable before the request started");
|
|
2813
|
+
if (websocket.readyState !== WebSocket.OPEN) {
|
|
2814
|
+
removeResponsesWebSocketPoolEntry(poolKey, entry);
|
|
2815
|
+
throw new Error("Responses websocket became unavailable before the request started");
|
|
2816
|
+
}
|
|
2817
|
+
return websocket;
|
|
2818
|
+
};
|
|
2796
2819
|
const scheduleResponsesWebSocketIdleClose = (poolKey, entry) => {
|
|
2797
2820
|
clearResponsesWebSocketIdleTimer(entry);
|
|
2798
2821
|
entry.idleTimer = setTimeout(() => {
|
|
@@ -2806,9 +2829,21 @@ const clearResponsesWebSocketIdleTimer = (entry) => {
|
|
|
2806
2829
|
entry.idleTimer = null;
|
|
2807
2830
|
}
|
|
2808
2831
|
};
|
|
2832
|
+
const getResponsesWebSocketActiveRequestCount = (poolKey) => responsesWebSocketActiveRequests.get(poolKey) ?? 0;
|
|
2833
|
+
const incrementResponsesWebSocketActiveRequestCount = (poolKey) => {
|
|
2834
|
+
responsesWebSocketActiveRequests.set(poolKey, getResponsesWebSocketActiveRequestCount(poolKey) + 1);
|
|
2835
|
+
};
|
|
2836
|
+
const decrementResponsesWebSocketActiveRequestCount = (poolKey) => {
|
|
2837
|
+
const nextCount = getResponsesWebSocketActiveRequestCount(poolKey) - 1;
|
|
2838
|
+
if (nextCount <= 0) {
|
|
2839
|
+
responsesWebSocketActiveRequests.delete(poolKey);
|
|
2840
|
+
return;
|
|
2841
|
+
}
|
|
2842
|
+
responsesWebSocketActiveRequests.set(poolKey, nextCount);
|
|
2843
|
+
};
|
|
2809
2844
|
const removeResponsesWebSocketPoolEntry = (poolKey, entry) => {
|
|
2810
|
-
if (responsesWebSocketPool.get(poolKey)
|
|
2811
|
-
|
|
2845
|
+
if (responsesWebSocketPool.get(poolKey) === entry) responsesWebSocketPool.delete(poolKey);
|
|
2846
|
+
if (entry.closed) return;
|
|
2812
2847
|
entry.closed = true;
|
|
2813
2848
|
clearResponsesWebSocketIdleTimer(entry);
|
|
2814
2849
|
entry.websocketPromise.then(closeResponsesWebSocket).catch(() => {});
|
|
@@ -2959,10 +2994,19 @@ const buildPromptCacheKey = (basePromptCacheKey, subagentAgentId) => {
|
|
|
2959
2994
|
const translateAnthropicMessagesToResponsesPayload = (payload, subagentAgentId) => {
|
|
2960
2995
|
const input = [];
|
|
2961
2996
|
const applyPhase = shouldApplyPhase(payload.model);
|
|
2962
|
-
|
|
2997
|
+
const toolSearchEnabled = shouldEnableResponsesToolSearch({
|
|
2998
|
+
model: payload.model,
|
|
2999
|
+
tools: payload.tools
|
|
3000
|
+
});
|
|
3001
|
+
const translationState = {
|
|
3002
|
+
originalTools: payload.tools ?? [],
|
|
3003
|
+
toolSearchEnabled,
|
|
3004
|
+
toolUseNameById: /* @__PURE__ */ new Map()
|
|
3005
|
+
};
|
|
3006
|
+
for (const message of payload.messages) input.push(...translateMessage(message, payload.model, applyPhase, translationState));
|
|
2963
3007
|
const hasOriginalTools = Array.isArray(payload.tools) && payload.tools.length > 0;
|
|
2964
|
-
const translatedTools = convertAnthropicTools(payload.tools);
|
|
2965
|
-
const toolChoice = convertAnthropicToolChoice(payload.tool_choice);
|
|
3008
|
+
const translatedTools = convertAnthropicTools(payload.tools, toolSearchEnabled);
|
|
3009
|
+
const toolChoice = convertAnthropicToolChoice(payload.tool_choice, toolSearchEnabled);
|
|
2966
3010
|
const { sessionId: metadataPromptCacheKey } = parseUserIdMetadata(payload.metadata?.user_id);
|
|
2967
3011
|
const sessionAffinity = requestContext.getStore()?.sessionAffinity?.trim() || null;
|
|
2968
3012
|
const promptCacheKey = buildPromptCacheKey(metadataPromptCacheKey ?? sessionAffinity, subagentAgentId);
|
|
@@ -3005,11 +3049,11 @@ const decodeCompactionCarrierSignature = (signature) => {
|
|
|
3005
3049
|
};
|
|
3006
3050
|
}
|
|
3007
3051
|
};
|
|
3008
|
-
const translateMessage = (message, model, applyPhase) => {
|
|
3009
|
-
if (message.role === "user") return translateUserMessage(message);
|
|
3010
|
-
return translateAssistantMessage(message, model, applyPhase);
|
|
3052
|
+
const translateMessage = (message, model, applyPhase, state) => {
|
|
3053
|
+
if (message.role === "user") return translateUserMessage(message, state);
|
|
3054
|
+
return translateAssistantMessage(message, model, applyPhase, state);
|
|
3011
3055
|
};
|
|
3012
|
-
const translateUserMessage = (message) => {
|
|
3056
|
+
const translateUserMessage = (message, state) => {
|
|
3013
3057
|
if (typeof message.content === "string") return [createMessage("user", message.content)];
|
|
3014
3058
|
if (!Array.isArray(message.content)) return [];
|
|
3015
3059
|
const items = [];
|
|
@@ -3017,7 +3061,7 @@ const translateUserMessage = (message) => {
|
|
|
3017
3061
|
for (const block of message.content) {
|
|
3018
3062
|
if (block.type === "tool_result") {
|
|
3019
3063
|
flushPendingContent(pendingContent, items, { role: "user" });
|
|
3020
|
-
items.push(
|
|
3064
|
+
items.push(createToolCallOutput(block, state));
|
|
3021
3065
|
continue;
|
|
3022
3066
|
}
|
|
3023
3067
|
const converted = translateUserContentBlock(block);
|
|
@@ -3026,7 +3070,7 @@ const translateUserMessage = (message) => {
|
|
|
3026
3070
|
flushPendingContent(pendingContent, items, { role: "user" });
|
|
3027
3071
|
return items;
|
|
3028
3072
|
};
|
|
3029
|
-
const translateAssistantMessage = (message, model, applyPhase) => {
|
|
3073
|
+
const translateAssistantMessage = (message, model, applyPhase, state) => {
|
|
3030
3074
|
const assistantPhase = resolveAssistantPhase(model, message.content, applyPhase);
|
|
3031
3075
|
if (typeof message.content === "string") return [createMessage("assistant", message.content, assistantPhase)];
|
|
3032
3076
|
if (!Array.isArray(message.content)) return [];
|
|
@@ -3034,11 +3078,12 @@ const translateAssistantMessage = (message, model, applyPhase) => {
|
|
|
3034
3078
|
const pendingContent = [];
|
|
3035
3079
|
for (const block of message.content) {
|
|
3036
3080
|
if (block.type === "tool_use") {
|
|
3081
|
+
state.toolUseNameById.set(block.id, block.name);
|
|
3037
3082
|
flushPendingContent(pendingContent, items, {
|
|
3038
3083
|
role: "assistant",
|
|
3039
3084
|
phase: assistantPhase
|
|
3040
3085
|
});
|
|
3041
|
-
items.push(
|
|
3086
|
+
items.push(createToolCall(block, state));
|
|
3042
3087
|
continue;
|
|
3043
3088
|
}
|
|
3044
3089
|
if (block.type === "thinking" && block.signature) {
|
|
@@ -3156,19 +3201,79 @@ const parseReasoningSignature = (signature) => {
|
|
|
3156
3201
|
id: signature.slice(splitIndex + 1)
|
|
3157
3202
|
};
|
|
3158
3203
|
};
|
|
3159
|
-
const createFunctionToolCall = (block) => ({
|
|
3204
|
+
const createFunctionToolCall = (block, state) => ({
|
|
3160
3205
|
type: "function_call",
|
|
3161
3206
|
call_id: block.id,
|
|
3162
3207
|
name: block.name,
|
|
3163
3208
|
arguments: JSON.stringify(block.input),
|
|
3209
|
+
status: "completed",
|
|
3210
|
+
...state.toolSearchEnabled && isDeferredToolName(block.name) ? { namespace: block.name } : {}
|
|
3211
|
+
});
|
|
3212
|
+
const createToolSearchCall = (block) => ({
|
|
3213
|
+
type: "tool_search_call",
|
|
3214
|
+
call_id: block.id,
|
|
3215
|
+
arguments: normalizeToolSearchBridgeArguments(block.input),
|
|
3216
|
+
execution: "client",
|
|
3164
3217
|
status: "completed"
|
|
3165
3218
|
});
|
|
3219
|
+
const createToolCall = (block, state) => {
|
|
3220
|
+
if (state.toolSearchEnabled && isBridgeToolSearchName(block.name)) return createToolSearchCall(block);
|
|
3221
|
+
return createFunctionToolCall(block, state);
|
|
3222
|
+
};
|
|
3166
3223
|
const createFunctionCallOutput = (block) => ({
|
|
3167
3224
|
type: "function_call_output",
|
|
3168
3225
|
call_id: block.tool_use_id,
|
|
3169
3226
|
output: convertToolResultContent(block.content),
|
|
3170
3227
|
status: block.is_error ? "incomplete" : "completed"
|
|
3171
3228
|
});
|
|
3229
|
+
const createToolCallOutput = (block, state) => {
|
|
3230
|
+
const toolUseName = state.toolUseNameById.get(block.tool_use_id);
|
|
3231
|
+
if (state.toolSearchEnabled && isBridgeToolSearchName(toolUseName ?? "")) return createToolSearchOutput(block, state.originalTools);
|
|
3232
|
+
return createFunctionCallOutput(block);
|
|
3233
|
+
};
|
|
3234
|
+
const createToolSearchOutput = (block, originalTools) => {
|
|
3235
|
+
const referencedToolNames = resolveToolSearchReferencedToolNames(block.content, originalTools);
|
|
3236
|
+
return {
|
|
3237
|
+
type: "tool_search_output",
|
|
3238
|
+
call_id: block.tool_use_id,
|
|
3239
|
+
tools: referencedToolNames.map((toolName) => convertDeferredToolToNamespace(resolveDeferredTool(toolName, originalTools))),
|
|
3240
|
+
execution: "client",
|
|
3241
|
+
status: block.is_error ? "incomplete" : "completed"
|
|
3242
|
+
};
|
|
3243
|
+
};
|
|
3244
|
+
const resolveToolSearchReferencedToolNames = (content, originalTools) => {
|
|
3245
|
+
const explicitReferences = extractToolReferenceNames(content);
|
|
3246
|
+
if (explicitReferences.length > 0) return uniqueToolNames(explicitReferences);
|
|
3247
|
+
const sentinel = extractMcpToolSearchSentinel(content);
|
|
3248
|
+
if (sentinel) return selectDeferredToolsByNames(sentinel.names, originalTools).map((tool) => tool.name);
|
|
3249
|
+
return [];
|
|
3250
|
+
};
|
|
3251
|
+
const extractToolReferenceNames = (content) => {
|
|
3252
|
+
if (!Array.isArray(content)) return [];
|
|
3253
|
+
return content.flatMap((block) => block.type === "tool_reference" ? [block.tool_name] : []);
|
|
3254
|
+
};
|
|
3255
|
+
const extractMcpToolSearchSentinel = (content) => {
|
|
3256
|
+
if (typeof content === "string") return parseMcpToolSearchSentinel(content);
|
|
3257
|
+
for (const block of content) {
|
|
3258
|
+
if (block.type !== "text") continue;
|
|
3259
|
+
const sentinel = parseMcpToolSearchSentinel(block.text);
|
|
3260
|
+
if (sentinel) return sentinel;
|
|
3261
|
+
}
|
|
3262
|
+
return null;
|
|
3263
|
+
};
|
|
3264
|
+
const resolveDeferredTool = (toolName, originalTools) => {
|
|
3265
|
+
const tool = originalTools.find((candidate) => candidate.name === toolName);
|
|
3266
|
+
if (tool && isDeferredToolName(tool.name)) return tool;
|
|
3267
|
+
throw createInvalidRequestError(`Tool reference '${toolName}' has no corresponding deferred tool definition`);
|
|
3268
|
+
};
|
|
3269
|
+
const uniqueToolNames = (toolNames) => [...new Set(toolNames)];
|
|
3270
|
+
const createInvalidRequestError = (message) => new HTTPError(message, new Response(JSON.stringify({ error: {
|
|
3271
|
+
message,
|
|
3272
|
+
type: "invalid_request_error"
|
|
3273
|
+
} }), {
|
|
3274
|
+
status: 400,
|
|
3275
|
+
headers: { "content-type": "application/json" }
|
|
3276
|
+
}));
|
|
3172
3277
|
const translateSystemPrompt = (system, model) => {
|
|
3173
3278
|
if (!system) return null;
|
|
3174
3279
|
const extraPrompt = getExtraPromptForModel(model);
|
|
@@ -3179,31 +3284,83 @@ const translateSystemPrompt = (system, model) => {
|
|
|
3179
3284
|
}).join(" ");
|
|
3180
3285
|
return text.length > 0 ? text : null;
|
|
3181
3286
|
};
|
|
3182
|
-
const convertAnthropicTools = (tools) => {
|
|
3287
|
+
const convertAnthropicTools = (tools, toolSearchEnabled) => {
|
|
3183
3288
|
if (!tools || tools.length === 0) return null;
|
|
3184
|
-
|
|
3289
|
+
const converted = [];
|
|
3290
|
+
let addedToolSearch = false;
|
|
3291
|
+
const searchableToolNames = toolSearchEnabled ? listDeferredToolNames(tools) : [];
|
|
3292
|
+
for (const tool of tools) {
|
|
3293
|
+
if (isBridgeToolSearchName(tool.name)) {
|
|
3294
|
+
if (toolSearchEnabled && !addedToolSearch) {
|
|
3295
|
+
converted.push(createResponsesToolSearchDefinition(searchableToolNames));
|
|
3296
|
+
addedToolSearch = true;
|
|
3297
|
+
}
|
|
3298
|
+
continue;
|
|
3299
|
+
}
|
|
3300
|
+
if (toolSearchEnabled && isDeferredToolName(tool.name)) {
|
|
3301
|
+
converted.push(convertDeferredToolToNamespace(tool));
|
|
3302
|
+
continue;
|
|
3303
|
+
}
|
|
3304
|
+
converted.push(convertToolToFunction(tool));
|
|
3305
|
+
}
|
|
3306
|
+
return converted;
|
|
3307
|
+
};
|
|
3308
|
+
const createResponsesToolSearchDefinition = (searchableToolNames) => ({
|
|
3309
|
+
type: "tool_search",
|
|
3310
|
+
execution: "client",
|
|
3311
|
+
description: "Load deferred tools by exact name before using them. Return only the searchable tool names you need for the next step.",
|
|
3312
|
+
parameters: {
|
|
3313
|
+
type: "object",
|
|
3314
|
+
properties: { names: {
|
|
3315
|
+
type: "array",
|
|
3316
|
+
description: "Exact deferred tool names to load.",
|
|
3317
|
+
items: {
|
|
3318
|
+
type: "string",
|
|
3319
|
+
enum: searchableToolNames
|
|
3320
|
+
},
|
|
3321
|
+
minItems: 1
|
|
3322
|
+
} },
|
|
3323
|
+
required: ["names"],
|
|
3324
|
+
additionalProperties: false
|
|
3325
|
+
}
|
|
3326
|
+
});
|
|
3327
|
+
const convertToolToFunction = (tool) => ({
|
|
3328
|
+
type: "function",
|
|
3329
|
+
name: tool.name,
|
|
3330
|
+
parameters: normalizeToolSchema(tool.input_schema),
|
|
3331
|
+
strict: false,
|
|
3332
|
+
...tool.description ? { description: tool.description } : {}
|
|
3333
|
+
});
|
|
3334
|
+
const convertDeferredToolToNamespace = (tool) => ({
|
|
3335
|
+
type: "namespace",
|
|
3336
|
+
name: tool.name,
|
|
3337
|
+
...tool.description ? { description: tool.description } : {},
|
|
3338
|
+
tools: [{
|
|
3185
3339
|
type: "function",
|
|
3186
3340
|
name: tool.name,
|
|
3187
3341
|
parameters: normalizeToolSchema(tool.input_schema),
|
|
3188
3342
|
strict: false,
|
|
3343
|
+
defer_loading: true,
|
|
3189
3344
|
...tool.description ? { description: tool.description } : {}
|
|
3190
|
-
}
|
|
3191
|
-
};
|
|
3192
|
-
const convertAnthropicToolChoice = (choice) => {
|
|
3345
|
+
}]
|
|
3346
|
+
});
|
|
3347
|
+
const convertAnthropicToolChoice = (choice, toolSearchEnabled) => {
|
|
3193
3348
|
if (!choice) return "auto";
|
|
3194
3349
|
switch (choice.type) {
|
|
3195
3350
|
case "auto": return "auto";
|
|
3196
3351
|
case "any": return "required";
|
|
3197
|
-
case "tool":
|
|
3198
|
-
|
|
3199
|
-
|
|
3200
|
-
|
|
3352
|
+
case "tool":
|
|
3353
|
+
if (toolSearchEnabled && choice.name && isBridgeToolSearchName(choice.name)) return "auto";
|
|
3354
|
+
return choice.name ? {
|
|
3355
|
+
type: "function",
|
|
3356
|
+
name: choice.name
|
|
3357
|
+
} : "auto";
|
|
3201
3358
|
case "none": return "none";
|
|
3202
3359
|
default: return "auto";
|
|
3203
3360
|
}
|
|
3204
3361
|
};
|
|
3205
|
-
const translateResponsesResultToAnthropic = (response) => {
|
|
3206
|
-
const contentBlocks = mapOutputToAnthropicContent(response.output);
|
|
3362
|
+
const translateResponsesResultToAnthropic = (response, options) => {
|
|
3363
|
+
const contentBlocks = mapOutputToAnthropicContent(response.output, options);
|
|
3207
3364
|
const usage = mapResponsesUsage(response);
|
|
3208
3365
|
let anthropicContent = fallbackContentBlocks(response.output_text);
|
|
3209
3366
|
if (contentBlocks.length > 0) anthropicContent = contentBlocks;
|
|
@@ -3219,7 +3376,7 @@ const translateResponsesResultToAnthropic = (response) => {
|
|
|
3219
3376
|
usage
|
|
3220
3377
|
};
|
|
3221
3378
|
};
|
|
3222
|
-
const mapOutputToAnthropicContent = (output) => {
|
|
3379
|
+
const mapOutputToAnthropicContent = (output, options) => {
|
|
3223
3380
|
const contentBlocks = [];
|
|
3224
3381
|
for (const item of output) switch (item.type) {
|
|
3225
3382
|
case "reasoning": {
|
|
@@ -3236,6 +3393,12 @@ const mapOutputToAnthropicContent = (output) => {
|
|
|
3236
3393
|
if (toolUseBlock) contentBlocks.push(toolUseBlock);
|
|
3237
3394
|
break;
|
|
3238
3395
|
}
|
|
3396
|
+
case "tool_search_call": {
|
|
3397
|
+
const toolUseBlock = createToolSearchUseContentBlock(item, options?.toolSearchName);
|
|
3398
|
+
if (toolUseBlock) contentBlocks.push(toolUseBlock);
|
|
3399
|
+
break;
|
|
3400
|
+
}
|
|
3401
|
+
case "tool_search_output": break;
|
|
3239
3402
|
case "message": {
|
|
3240
3403
|
const combinedText = combineMessageTextContent(item.content);
|
|
3241
3404
|
if (combinedText.length > 0) contentBlocks.push({
|
|
@@ -3297,15 +3460,29 @@ const extractReasoningText = (item) => {
|
|
|
3297
3460
|
};
|
|
3298
3461
|
const createToolUseContentBlock = (call) => {
|
|
3299
3462
|
const toolId = call.call_id;
|
|
3300
|
-
|
|
3301
|
-
|
|
3463
|
+
const toolName = resolveToolUseName(call);
|
|
3464
|
+
if (!toolName || !toolId) return null;
|
|
3465
|
+
return {
|
|
3466
|
+
type: "tool_use",
|
|
3467
|
+
id: toolId,
|
|
3468
|
+
name: toolName,
|
|
3469
|
+
input: parseFunctionCallArguments(call.arguments)
|
|
3470
|
+
};
|
|
3471
|
+
};
|
|
3472
|
+
const createToolSearchUseContentBlock = (call, toolSearchName = BRIDGE_TOOL_SEARCH_NAME) => {
|
|
3473
|
+
const toolId = call.call_id;
|
|
3474
|
+
if (!toolId) return null;
|
|
3302
3475
|
return {
|
|
3303
3476
|
type: "tool_use",
|
|
3304
3477
|
id: toolId,
|
|
3305
|
-
name:
|
|
3306
|
-
input
|
|
3478
|
+
name: toolSearchName,
|
|
3479
|
+
input: parseToolSearchArguments(call.arguments)
|
|
3307
3480
|
};
|
|
3308
3481
|
};
|
|
3482
|
+
const resolveToolUseName = (call) => {
|
|
3483
|
+
if (typeof call.namespace === "string" && call.namespace.length > 0) return call.namespace;
|
|
3484
|
+
return call.name;
|
|
3485
|
+
};
|
|
3309
3486
|
const createCompactionThinkingBlock = (item) => {
|
|
3310
3487
|
if (!item.id || !item.encrypted_content) return null;
|
|
3311
3488
|
return {
|
|
@@ -3331,6 +3508,9 @@ const parseFunctionCallArguments = (rawArguments) => {
|
|
|
3331
3508
|
}
|
|
3332
3509
|
return { raw_arguments: rawArguments };
|
|
3333
3510
|
};
|
|
3511
|
+
const parseToolSearchArguments = (argumentsValue) => {
|
|
3512
|
+
return formatToolSearchBridgeArguments(argumentsValue);
|
|
3513
|
+
};
|
|
3334
3514
|
const fallbackContentBlocks = (outputText) => {
|
|
3335
3515
|
if (!outputText) return [];
|
|
3336
3516
|
return [{
|
|
@@ -3341,7 +3521,7 @@ const fallbackContentBlocks = (outputText) => {
|
|
|
3341
3521
|
const mapResponsesStopReason = (response) => {
|
|
3342
3522
|
const { status, incomplete_details: incompleteDetails } = response;
|
|
3343
3523
|
if (status === "completed") {
|
|
3344
|
-
if (response.output.some((item) => item.type === "function_call")) return "tool_use";
|
|
3524
|
+
if (response.output.some((item) => item.type === "function_call" || item.type === "tool_search_call")) return "tool_use";
|
|
3345
3525
|
return "end_turn";
|
|
3346
3526
|
}
|
|
3347
3527
|
if (status === "incomplete") {
|
|
@@ -3412,14 +3592,15 @@ const updateWhitespaceRunState = (previousCount, chunk) => {
|
|
|
3412
3592
|
exceeded: false
|
|
3413
3593
|
};
|
|
3414
3594
|
};
|
|
3415
|
-
const createResponsesStreamState = () => ({
|
|
3595
|
+
const createResponsesStreamState = (options) => ({
|
|
3416
3596
|
messageStartSent: false,
|
|
3417
3597
|
messageCompleted: false,
|
|
3418
3598
|
nextContentBlockIndex: 0,
|
|
3419
3599
|
blockIndexByKey: /* @__PURE__ */ new Map(),
|
|
3420
3600
|
openBlocks: /* @__PURE__ */ new Set(),
|
|
3421
3601
|
blockHasDelta: /* @__PURE__ */ new Set(),
|
|
3422
|
-
functionCallStateByOutputIndex: /* @__PURE__ */ new Map()
|
|
3602
|
+
functionCallStateByOutputIndex: /* @__PURE__ */ new Map(),
|
|
3603
|
+
toolSearchName: options?.toolSearchName ?? "mcp__tool_search__search"
|
|
3423
3604
|
});
|
|
3424
3605
|
const translateResponsesStreamEvent = (rawEvent, state) => {
|
|
3425
3606
|
switch (rawEvent.type) {
|
|
@@ -3444,7 +3625,7 @@ const handleResponseCreated = (rawEvent, state) => {
|
|
|
3444
3625
|
};
|
|
3445
3626
|
const handleOutputItemAdded$1 = (rawEvent, state) => {
|
|
3446
3627
|
const events = new Array();
|
|
3447
|
-
const functionCallDetails = extractFunctionCallDetails(rawEvent);
|
|
3628
|
+
const functionCallDetails = extractFunctionCallDetails(rawEvent, state);
|
|
3448
3629
|
if (!functionCallDetails) return events;
|
|
3449
3630
|
const { outputIndex, toolCallId, name, initialArguments } = functionCallDetails;
|
|
3450
3631
|
const blockIndex = openFunctionCallBlock(state, {
|
|
@@ -3471,6 +3652,28 @@ const handleOutputItemDone$1 = (rawEvent, state) => {
|
|
|
3471
3652
|
const item = rawEvent.item;
|
|
3472
3653
|
const itemType = item.type;
|
|
3473
3654
|
const outputIndex = rawEvent.output_index;
|
|
3655
|
+
if (itemType === "tool_search_call") {
|
|
3656
|
+
const blockIndex = openFunctionCallBlock(state, {
|
|
3657
|
+
outputIndex,
|
|
3658
|
+
toolCallId: item.call_id,
|
|
3659
|
+
name: state.toolSearchName,
|
|
3660
|
+
events
|
|
3661
|
+
});
|
|
3662
|
+
const finalArguments = stringifyToolSearchArguments(item.arguments);
|
|
3663
|
+
if (!state.blockHasDelta.has(blockIndex) && finalArguments) {
|
|
3664
|
+
events.push({
|
|
3665
|
+
type: "content_block_delta",
|
|
3666
|
+
index: blockIndex,
|
|
3667
|
+
delta: {
|
|
3668
|
+
type: "input_json_delta",
|
|
3669
|
+
partial_json: finalArguments
|
|
3670
|
+
}
|
|
3671
|
+
});
|
|
3672
|
+
state.blockHasDelta.add(blockIndex);
|
|
3673
|
+
}
|
|
3674
|
+
state.functionCallStateByOutputIndex.delete(outputIndex);
|
|
3675
|
+
return events;
|
|
3676
|
+
}
|
|
3474
3677
|
if (itemType === "compaction") {
|
|
3475
3678
|
if (!item.id || !item.encrypted_content) return events;
|
|
3476
3679
|
const blockIndex = openThinkingBlockIfNeeded(state, outputIndex, events);
|
|
@@ -3799,16 +4002,30 @@ const openFunctionCallBlock = (state, params) => {
|
|
|
3799
4002
|
}
|
|
3800
4003
|
return blockIndex;
|
|
3801
4004
|
};
|
|
3802
|
-
const extractFunctionCallDetails = (rawEvent) => {
|
|
4005
|
+
const extractFunctionCallDetails = (rawEvent, state) => {
|
|
3803
4006
|
const item = rawEvent.item;
|
|
3804
|
-
|
|
4007
|
+
const itemType = item.type;
|
|
4008
|
+
if (itemType === "tool_search_call") return {
|
|
4009
|
+
outputIndex: rawEvent.output_index,
|
|
4010
|
+
toolCallId: item.call_id,
|
|
4011
|
+
name: state.toolSearchName,
|
|
4012
|
+
initialArguments: ""
|
|
4013
|
+
};
|
|
4014
|
+
if (itemType !== "function_call") return;
|
|
3805
4015
|
return {
|
|
3806
4016
|
outputIndex: rawEvent.output_index,
|
|
3807
4017
|
toolCallId: item.call_id,
|
|
3808
|
-
name: item
|
|
4018
|
+
name: resolveToolUseName(item),
|
|
3809
4019
|
initialArguments: item.arguments
|
|
3810
4020
|
};
|
|
3811
4021
|
};
|
|
4022
|
+
const stringifyToolSearchArguments = (argumentsValue) => {
|
|
4023
|
+
try {
|
|
4024
|
+
return JSON.stringify(formatToolSearchBridgeArguments(argumentsValue));
|
|
4025
|
+
} catch {
|
|
4026
|
+
return;
|
|
4027
|
+
}
|
|
4028
|
+
};
|
|
3812
4029
|
//#endregion
|
|
3813
4030
|
//#region src/services/copilot/create-messages.ts
|
|
3814
4031
|
const INTERLEAVED_THINKING_BETA = "interleaved-thinking-2025-05-14";
|
|
@@ -4192,7 +4409,7 @@ const handleWithResponsesApi = async (c, anthropicPayload, options) => {
|
|
|
4192
4409
|
if (responsesPayload.stream && isAsyncIterable$1(response)) {
|
|
4193
4410
|
logger.debug("Streaming response from Copilot (Responses API)");
|
|
4194
4411
|
return streamSSE(c, async (stream) => {
|
|
4195
|
-
const streamState = createResponsesStreamState();
|
|
4412
|
+
const streamState = createResponsesStreamState({ toolSearchName: resolveBridgeToolSearchName(anthropicPayload.tools) });
|
|
4196
4413
|
let usage = {};
|
|
4197
4414
|
for await (const chunk of response) {
|
|
4198
4415
|
if (chunk.event === "ping") {
|
|
@@ -4236,7 +4453,7 @@ const handleWithResponsesApi = async (c, anthropicPayload, options) => {
|
|
|
4236
4453
|
value: response,
|
|
4237
4454
|
tailLength: 400
|
|
4238
4455
|
});
|
|
4239
|
-
const anthropicResponse = translateResponsesResultToAnthropic(response);
|
|
4456
|
+
const anthropicResponse = translateResponsesResultToAnthropic(response, { toolSearchName: resolveBridgeToolSearchName(anthropicPayload.tools) });
|
|
4240
4457
|
recordUsage(normalizeResponsesUsage(response.usage));
|
|
4241
4458
|
debugJson(logger, "Translated Anthropic response:", anthropicResponse);
|
|
4242
4459
|
return c.json(anthropicResponse);
|
|
@@ -4802,4 +5019,4 @@ server.route("/:provider/v1/models", providerModelRoutes);
|
|
|
4802
5019
|
//#endregion
|
|
4803
5020
|
export { server };
|
|
4804
5021
|
|
|
4805
|
-
//# sourceMappingURL=server-
|
|
5022
|
+
//# sourceMappingURL=server-DsfYz_GE.js.map
|