@nick3/copilot-api 1.2.2 → 1.2.7
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 +68 -5
- package/dist/{accounts-manager-DellX80M.js → accounts-manager-iJwqQUkM.js} +221 -13
- package/dist/accounts-manager-iJwqQUkM.js.map +1 -0
- package/dist/main.js +15 -9
- package/dist/main.js.map +1 -1
- package/dist/{server-dAi_n8ee.js → server-BgJ8vqcw.js} +410 -80
- package/dist/server-BgJ8vqcw.js.map +1 -0
- package/package.json +1 -1
- package/dist/accounts-manager-DellX80M.js.map +0 -1
- package/dist/server-dAi_n8ee.js.map +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { HTTPError, PATHS, accountFromState, accountsManager, copilotBaseUrl, copilotHeaders, forwardError, getAliasTargetSet, getConfig, getCopilotUsage, getExtraPromptForModel, getModelAliases, getModelAliasesInfo, getModelRefreshIntervalMs, getReasoningEffortForModel, getSmallModel, isForceAgentEnabled, isFreeModelLoadBalancingEnabled, isMessageStartInputTokensFallbackEnabled, isNullish, listAccountsFromRegistry, mergeConfigWithDefaults, shouldCompactUseSmallModel, sleep, state } from "./accounts-manager-
|
|
1
|
+
import { HTTPError, PATHS, accountFromState, accountsManager, copilotBaseUrl, copilotHeaders, forwardError, generateRequestIdFromPayload, getAliasTargetSet, getConfig, getCopilotUsage, getExtraPromptForModel, getModelAliases, getModelAliasesInfo, getModelRefreshIntervalMs, getProviderConfig, getReasoningEffortForModel, getRootSessionId, getSmallModel, getUUID, isForceAgentEnabled, isFreeModelLoadBalancingEnabled, isMessageStartInputTokensFallbackEnabled, isNullish, isResponsesApiContextManagementModel, listAccountsFromRegistry, mergeConfigWithDefaults, prepareInteractionHeaders, shouldCompactUseSmallModel, sleep, state } from "./accounts-manager-iJwqQUkM.js";
|
|
2
2
|
import consola from "consola";
|
|
3
3
|
import fs, { readFile } from "node:fs/promises";
|
|
4
4
|
import * as path$1 from "node:path";
|
|
@@ -2227,13 +2227,14 @@ const getTokenCount = async (payload, model) => {
|
|
|
2227
2227
|
|
|
2228
2228
|
//#endregion
|
|
2229
2229
|
//#region src/services/copilot/create-responses.ts
|
|
2230
|
-
const createResponses = async (payload, { vision, initiator, upstreamRequestId }, account) => {
|
|
2230
|
+
const createResponses = async (payload, { vision, initiator, upstreamRequestId, subagentMarker, sessionId }, account) => {
|
|
2231
2231
|
const ctx = account ?? accountFromState();
|
|
2232
2232
|
if (!ctx.copilotToken) throw new Error("Copilot token not found");
|
|
2233
2233
|
const headers = {
|
|
2234
2234
|
...copilotHeaders(ctx, vision, upstreamRequestId),
|
|
2235
|
-
"
|
|
2235
|
+
"x-initiator": initiator
|
|
2236
2236
|
};
|
|
2237
|
+
prepareInteractionHeaders(sessionId, Boolean(subagentMarker), headers);
|
|
2237
2238
|
payload.service_tier = null;
|
|
2238
2239
|
const response = await fetch(`${copilotBaseUrl(ctx)}/responses`, {
|
|
2239
2240
|
method: "POST",
|
|
@@ -2251,6 +2252,8 @@ const createResponses = async (payload, { vision, initiator, upstreamRequestId }
|
|
|
2251
2252
|
//#endregion
|
|
2252
2253
|
//#region src/routes/messages/responses-translation.ts
|
|
2253
2254
|
const MESSAGE_TYPE = "message";
|
|
2255
|
+
const COMPACTION_SIGNATURE_PREFIX = "cm1#";
|
|
2256
|
+
const COMPACTION_SIGNATURE_SEPARATOR = "@";
|
|
2254
2257
|
const THINKING_TEXT$1 = "Thinking...";
|
|
2255
2258
|
const translateAnthropicMessagesToResponsesPayload = (payload, modelOverride) => {
|
|
2256
2259
|
const model = modelOverride ?? payload.model;
|
|
@@ -2282,6 +2285,23 @@ const translateAnthropicMessagesToResponsesPayload = (payload, modelOverride) =>
|
|
|
2282
2285
|
include: ["reasoning.encrypted_content"]
|
|
2283
2286
|
};
|
|
2284
2287
|
};
|
|
2288
|
+
const encodeCompactionCarrierSignature = (compaction) => {
|
|
2289
|
+
return `${COMPACTION_SIGNATURE_PREFIX}${compaction.encrypted_content}${COMPACTION_SIGNATURE_SEPARATOR}${compaction.id}`;
|
|
2290
|
+
};
|
|
2291
|
+
const decodeCompactionCarrierSignature = (signature) => {
|
|
2292
|
+
if (signature.startsWith(COMPACTION_SIGNATURE_PREFIX)) {
|
|
2293
|
+
const raw = signature.slice(4);
|
|
2294
|
+
const separatorIndex = raw.indexOf(COMPACTION_SIGNATURE_SEPARATOR);
|
|
2295
|
+
if (separatorIndex <= 0 || separatorIndex === raw.length - 1) return;
|
|
2296
|
+
const encrypted_content = raw.slice(0, separatorIndex);
|
|
2297
|
+
const id = raw.slice(separatorIndex + 1);
|
|
2298
|
+
if (!encrypted_content) return;
|
|
2299
|
+
return {
|
|
2300
|
+
id,
|
|
2301
|
+
encrypted_content
|
|
2302
|
+
};
|
|
2303
|
+
}
|
|
2304
|
+
};
|
|
2285
2305
|
const translateMessage = (message, model, applyPhase) => {
|
|
2286
2306
|
if (message.role === "user") return translateUserMessage(message);
|
|
2287
2307
|
return translateAssistantMessage(message, model, applyPhase);
|
|
@@ -2318,13 +2338,24 @@ const translateAssistantMessage = (message, model, applyPhase) => {
|
|
|
2318
2338
|
items.push(createFunctionToolCall(block));
|
|
2319
2339
|
continue;
|
|
2320
2340
|
}
|
|
2321
|
-
if (block.type === "thinking" && block.signature
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
|
|
2341
|
+
if (block.type === "thinking" && block.signature) {
|
|
2342
|
+
const compactionContent = createCompactionContent(block);
|
|
2343
|
+
if (compactionContent) {
|
|
2344
|
+
flushPendingContent(pendingContent, items, {
|
|
2345
|
+
role: "assistant",
|
|
2346
|
+
phase: assistantPhase
|
|
2347
|
+
});
|
|
2348
|
+
items.push(compactionContent);
|
|
2349
|
+
continue;
|
|
2350
|
+
}
|
|
2351
|
+
if (block.signature.includes("@")) {
|
|
2352
|
+
flushPendingContent(pendingContent, items, {
|
|
2353
|
+
role: "assistant",
|
|
2354
|
+
phase: assistantPhase
|
|
2355
|
+
});
|
|
2356
|
+
items.push(createReasoningContent(block));
|
|
2357
|
+
continue;
|
|
2358
|
+
}
|
|
2328
2359
|
}
|
|
2329
2360
|
const converted = translateAssistantContentBlock(block);
|
|
2330
2361
|
if (converted) pendingContent.push(converted);
|
|
@@ -2384,9 +2415,7 @@ const createImageContent = (block) => ({
|
|
|
2384
2415
|
detail: "auto"
|
|
2385
2416
|
});
|
|
2386
2417
|
const createReasoningContent = (block) => {
|
|
2387
|
-
const
|
|
2388
|
-
const signature = array[0];
|
|
2389
|
-
const id = array[1];
|
|
2418
|
+
const { encryptedContent, id } = parseReasoningSignature(block.signature);
|
|
2390
2419
|
const thinking = block.thinking === THINKING_TEXT$1 ? "" : block.thinking;
|
|
2391
2420
|
return {
|
|
2392
2421
|
id,
|
|
@@ -2395,7 +2424,27 @@ const createReasoningContent = (block) => {
|
|
|
2395
2424
|
type: "summary_text",
|
|
2396
2425
|
text: thinking
|
|
2397
2426
|
}] : [],
|
|
2398
|
-
encrypted_content:
|
|
2427
|
+
encrypted_content: encryptedContent
|
|
2428
|
+
};
|
|
2429
|
+
};
|
|
2430
|
+
const createCompactionContent = (block) => {
|
|
2431
|
+
const compaction = decodeCompactionCarrierSignature(block.signature);
|
|
2432
|
+
if (!compaction) return;
|
|
2433
|
+
return {
|
|
2434
|
+
id: compaction.id,
|
|
2435
|
+
type: "compaction",
|
|
2436
|
+
encrypted_content: compaction.encrypted_content
|
|
2437
|
+
};
|
|
2438
|
+
};
|
|
2439
|
+
const parseReasoningSignature = (signature) => {
|
|
2440
|
+
const splitIndex = signature.lastIndexOf("@");
|
|
2441
|
+
if (splitIndex <= 0 || splitIndex === signature.length - 1) return {
|
|
2442
|
+
encryptedContent: signature,
|
|
2443
|
+
id: ""
|
|
2444
|
+
};
|
|
2445
|
+
return {
|
|
2446
|
+
encryptedContent: signature.slice(0, splitIndex),
|
|
2447
|
+
id: signature.slice(splitIndex + 1)
|
|
2399
2448
|
};
|
|
2400
2449
|
};
|
|
2401
2450
|
const createFunctionToolCall = (block) => ({
|
|
@@ -2486,6 +2535,11 @@ const mapOutputToAnthropicContent = (output) => {
|
|
|
2486
2535
|
});
|
|
2487
2536
|
break;
|
|
2488
2537
|
}
|
|
2538
|
+
case "compaction": {
|
|
2539
|
+
const compactionBlock = createCompactionThinkingBlock(item);
|
|
2540
|
+
if (compactionBlock) contentBlocks.push(compactionBlock);
|
|
2541
|
+
break;
|
|
2542
|
+
}
|
|
2489
2543
|
default: {
|
|
2490
2544
|
const combinedText = combineMessageTextContent(item.content);
|
|
2491
2545
|
if (combinedText.length > 0) contentBlocks.push({
|
|
@@ -2543,6 +2597,17 @@ const createToolUseContentBlock = (call) => {
|
|
|
2543
2597
|
input
|
|
2544
2598
|
};
|
|
2545
2599
|
};
|
|
2600
|
+
const createCompactionThinkingBlock = (item) => {
|
|
2601
|
+
if (!item.id || !item.encrypted_content) return null;
|
|
2602
|
+
return {
|
|
2603
|
+
type: "thinking",
|
|
2604
|
+
thinking: THINKING_TEXT$1,
|
|
2605
|
+
signature: encodeCompactionCarrierSignature({
|
|
2606
|
+
id: item.id,
|
|
2607
|
+
encrypted_content: item.encrypted_content
|
|
2608
|
+
})
|
|
2609
|
+
};
|
|
2610
|
+
};
|
|
2546
2611
|
const parseFunctionCallArguments = (rawArguments) => {
|
|
2547
2612
|
if (typeof rawArguments !== "string" || rawArguments.trim().length === 0) return {};
|
|
2548
2613
|
try {
|
|
@@ -2647,8 +2712,9 @@ const createChatCompletions = async (payload, account, options) => {
|
|
|
2647
2712
|
const initiator = options?.initiator ?? getChatInitiator(payload.messages);
|
|
2648
2713
|
const headers = {
|
|
2649
2714
|
...copilotHeaders(ctx, enableVision, options?.upstreamRequestId),
|
|
2650
|
-
"
|
|
2715
|
+
"x-initiator": options?.subagentMarker ? "agent" : initiator
|
|
2651
2716
|
};
|
|
2717
|
+
prepareInteractionHeaders(options?.sessionId, Boolean(options?.subagentMarker), headers);
|
|
2652
2718
|
const upstreamPayload = applyDefaultReasoningEffort(payload);
|
|
2653
2719
|
const response = await fetch(`${copilotBaseUrl(ctx)}/chat/completions`, {
|
|
2654
2720
|
method: "POST",
|
|
@@ -2665,7 +2731,7 @@ const createChatCompletions = async (payload, account, options) => {
|
|
|
2665
2731
|
|
|
2666
2732
|
//#endregion
|
|
2667
2733
|
//#region src/routes/chat-completions/handler.ts
|
|
2668
|
-
const logger$
|
|
2734
|
+
const logger$6 = createHandlerLogger("chat-completions-handler");
|
|
2669
2735
|
const CHAT_COMPLETIONS_ENDPOINT$1 = "/chat/completions";
|
|
2670
2736
|
async function handleCompletion$1(c) {
|
|
2671
2737
|
await checkRateLimit(state);
|
|
@@ -2695,7 +2761,7 @@ async function handleCompletion$1(c) {
|
|
|
2695
2761
|
reason: "MODEL_NOT_SUPPORTED"
|
|
2696
2762
|
});
|
|
2697
2763
|
}
|
|
2698
|
-
logger$
|
|
2764
|
+
logger$6.debug("Request payload:", JSON.stringify(payload).slice(-400));
|
|
2699
2765
|
const selection = await accountsManager.selectAccountForRequest([{
|
|
2700
2766
|
modelId: clientModel,
|
|
2701
2767
|
endpoint: CHAT_COMPLETIONS_ENDPOINT$1
|
|
@@ -2726,7 +2792,10 @@ async function handleCompletion$1(c) {
|
|
|
2726
2792
|
if (state.manualApprove) await awaitApproval();
|
|
2727
2793
|
const payloadWithMaxTokens = applyDefaultMaxTokens(upstreamPayload, selectedModel);
|
|
2728
2794
|
const accountCtx = toAccountContext(account);
|
|
2729
|
-
|
|
2795
|
+
const upstreamRequestId = generateRequestIdFromPayload(payloadWithMaxTokens);
|
|
2796
|
+
const upstreamSessionId = getUUID(upstreamRequestId);
|
|
2797
|
+
request.upstreamRequestId = upstreamRequestId;
|
|
2798
|
+
request.upstreamSessionId = upstreamSessionId;
|
|
2730
2799
|
if (streamRequested) return handleStreamingRequest({
|
|
2731
2800
|
c,
|
|
2732
2801
|
store,
|
|
@@ -2811,9 +2880,9 @@ function selectionFailureResponse$2(c, params) {
|
|
|
2811
2880
|
async function logTokenCountForRequest(params) {
|
|
2812
2881
|
try {
|
|
2813
2882
|
const tokenCount = await getTokenCount(params.payload, params.selectedModel);
|
|
2814
|
-
logger$
|
|
2883
|
+
logger$6.info("Current token count:", tokenCount);
|
|
2815
2884
|
} catch (error) {
|
|
2816
|
-
logger$
|
|
2885
|
+
logger$6.warn("Failed to calculate token count:", error);
|
|
2817
2886
|
}
|
|
2818
2887
|
}
|
|
2819
2888
|
function applyDefaultMaxTokens(payload, selectedModel) {
|
|
@@ -2822,14 +2891,17 @@ function applyDefaultMaxTokens(payload, selectedModel) {
|
|
|
2822
2891
|
...payload,
|
|
2823
2892
|
max_tokens: selectedModel.capabilities.limits.max_output_tokens
|
|
2824
2893
|
};
|
|
2825
|
-
logger$
|
|
2894
|
+
logger$6.debug("Set max_tokens to:", JSON.stringify(updated.max_tokens));
|
|
2826
2895
|
return updated;
|
|
2827
2896
|
}
|
|
2828
2897
|
async function handleStreamingRequest(params) {
|
|
2829
2898
|
const { c, store, request, payload, selection, accountCtx, clientModel, premiumRemainingBefore, premiumUnlimitedBefore } = params;
|
|
2830
2899
|
let response;
|
|
2831
2900
|
try {
|
|
2832
|
-
response = await createChatCompletions(payload, accountCtx, {
|
|
2901
|
+
response = await createChatCompletions(payload, accountCtx, {
|
|
2902
|
+
upstreamRequestId: request.upstreamRequestId,
|
|
2903
|
+
sessionId: request.upstreamSessionId
|
|
2904
|
+
});
|
|
2833
2905
|
} catch (error) {
|
|
2834
2906
|
return handleUpstreamCreateError$1({
|
|
2835
2907
|
store,
|
|
@@ -2851,7 +2923,7 @@ async function handleStreamingRequest(params) {
|
|
|
2851
2923
|
premiumUnlimitedBefore,
|
|
2852
2924
|
response
|
|
2853
2925
|
});
|
|
2854
|
-
logger$
|
|
2926
|
+
logger$6.debug("Streaming response");
|
|
2855
2927
|
return streamSSE(c, (stream) => streamChatCompletionsAndLog$1({
|
|
2856
2928
|
stream,
|
|
2857
2929
|
response,
|
|
@@ -2904,7 +2976,7 @@ async function handleNonStreamingUpstreamResponse(params) {
|
|
|
2904
2976
|
let errorMessage;
|
|
2905
2977
|
const finishedAtMs = Date.now();
|
|
2906
2978
|
try {
|
|
2907
|
-
logger$
|
|
2979
|
+
logger$6.debug("Non-streaming response:", JSON.stringify(response));
|
|
2908
2980
|
return c.json(response);
|
|
2909
2981
|
} catch (error) {
|
|
2910
2982
|
const details = extractErrorDetails(error);
|
|
@@ -2954,7 +3026,7 @@ async function streamChatCompletionsAndLog$1(params) {
|
|
|
2954
3026
|
if (ttfbMs === void 0) ttfbMs = Date.now() - request.startedAtMs;
|
|
2955
3027
|
const usage = await extractUsageFromChunk(chunk);
|
|
2956
3028
|
if (usage) lastUsage = usage;
|
|
2957
|
-
logger$
|
|
3029
|
+
logger$6.debug("Streaming chunk:", JSON.stringify(chunk));
|
|
2958
3030
|
await stream.writeSSE(chunk);
|
|
2959
3031
|
}
|
|
2960
3032
|
} catch (error) {
|
|
@@ -2962,7 +3034,7 @@ async function streamChatCompletionsAndLog$1(params) {
|
|
|
2962
3034
|
errorName = details.errorName;
|
|
2963
3035
|
errorStatus = details.errorStatus;
|
|
2964
3036
|
errorMessage = details.errorMessage;
|
|
2965
|
-
logger$
|
|
3037
|
+
logger$6.warn("Streaming error:", error);
|
|
2966
3038
|
} finally {
|
|
2967
3039
|
const finishedAtMs = Date.now();
|
|
2968
3040
|
await accountsManager.finalizeQuota(account, reservation);
|
|
@@ -3013,16 +3085,19 @@ async function handleNonStreamingRequest(params) {
|
|
|
3013
3085
|
let errorMessage;
|
|
3014
3086
|
let finishedAtMs;
|
|
3015
3087
|
try {
|
|
3016
|
-
const response = await createChatCompletions(payload, accountCtx, {
|
|
3088
|
+
const response = await createChatCompletions(payload, accountCtx, {
|
|
3089
|
+
upstreamRequestId: request.upstreamRequestId,
|
|
3090
|
+
sessionId: request.upstreamSessionId
|
|
3091
|
+
});
|
|
3017
3092
|
finishedAtMs = Date.now();
|
|
3018
3093
|
if (!isNonStreaming$1(response)) {
|
|
3019
|
-
logger$
|
|
3094
|
+
logger$6.debug("Unexpected streaming response");
|
|
3020
3095
|
return streamSSE(c, async (stream) => {
|
|
3021
3096
|
for await (const chunk of response) await stream.writeSSE(chunk);
|
|
3022
3097
|
});
|
|
3023
3098
|
}
|
|
3024
3099
|
usage = normalizeChatCompletionsUsage(response.usage);
|
|
3025
|
-
logger$
|
|
3100
|
+
logger$6.debug("Non-streaming response:", JSON.stringify(response));
|
|
3026
3101
|
return c.json(response);
|
|
3027
3102
|
} catch (error) {
|
|
3028
3103
|
finishedAtMs = Date.now();
|
|
@@ -3294,11 +3369,11 @@ const mergeToolResultForClaude = (anthropicPayload) => {
|
|
|
3294
3369
|
msg.content = mergeToolResult(toolResults, textBlocks);
|
|
3295
3370
|
}
|
|
3296
3371
|
};
|
|
3297
|
-
const estimateInputTokens = async (payload, selectedModel, logger$
|
|
3372
|
+
const estimateInputTokens = async (payload, selectedModel, logger$7) => {
|
|
3298
3373
|
try {
|
|
3299
3374
|
return (await getTokenCount(payload, selectedModel)).input;
|
|
3300
3375
|
} catch (error) {
|
|
3301
|
-
logger$
|
|
3376
|
+
logger$7.warn("Failed to estimate input tokens for message_start", error);
|
|
3302
3377
|
return;
|
|
3303
3378
|
}
|
|
3304
3379
|
};
|
|
@@ -3716,8 +3791,34 @@ const handleOutputItemAdded$1 = (rawEvent, state$1) => {
|
|
|
3716
3791
|
const handleOutputItemDone$1 = (rawEvent, state$1) => {
|
|
3717
3792
|
const events$1 = new Array();
|
|
3718
3793
|
const item = rawEvent.item;
|
|
3719
|
-
|
|
3794
|
+
const itemType = item.type;
|
|
3720
3795
|
const outputIndex = rawEvent.output_index;
|
|
3796
|
+
if (itemType === "compaction") {
|
|
3797
|
+
if (!item.id || !item.encrypted_content) return events$1;
|
|
3798
|
+
const blockIndex$1 = openThinkingBlockIfNeeded(state$1, outputIndex, events$1);
|
|
3799
|
+
if (!state$1.blockHasDelta.has(blockIndex$1)) events$1.push({
|
|
3800
|
+
type: "content_block_delta",
|
|
3801
|
+
index: blockIndex$1,
|
|
3802
|
+
delta: {
|
|
3803
|
+
type: "thinking_delta",
|
|
3804
|
+
thinking: THINKING_TEXT$1
|
|
3805
|
+
}
|
|
3806
|
+
});
|
|
3807
|
+
events$1.push({
|
|
3808
|
+
type: "content_block_delta",
|
|
3809
|
+
index: blockIndex$1,
|
|
3810
|
+
delta: {
|
|
3811
|
+
type: "signature_delta",
|
|
3812
|
+
signature: encodeCompactionCarrierSignature({
|
|
3813
|
+
id: item.id,
|
|
3814
|
+
encrypted_content: item.encrypted_content
|
|
3815
|
+
})
|
|
3816
|
+
}
|
|
3817
|
+
});
|
|
3818
|
+
state$1.blockHasDelta.add(blockIndex$1);
|
|
3819
|
+
return events$1;
|
|
3820
|
+
}
|
|
3821
|
+
if (itemType !== "reasoning") return events$1;
|
|
3721
3822
|
const blockIndex = openThinkingBlockIfNeeded(state$1, outputIndex, events$1);
|
|
3722
3823
|
const signature = (item.encrypted_content ?? "") + "@" + item.id;
|
|
3723
3824
|
if (signature) {
|
|
@@ -4065,6 +4166,31 @@ const isAgentRole = (item) => {
|
|
|
4065
4166
|
const hasVisionInput = (payload) => {
|
|
4066
4167
|
return getPayloadItems(payload).some((item) => containsVisionContent(item));
|
|
4067
4168
|
};
|
|
4169
|
+
const resolveResponsesCompactThreshold = (maxPromptTokens) => {
|
|
4170
|
+
if (typeof maxPromptTokens === "number" && maxPromptTokens > 0) return Math.floor(maxPromptTokens * .9);
|
|
4171
|
+
return 5e4;
|
|
4172
|
+
};
|
|
4173
|
+
const createCompactionContextManagement = (compactThreshold) => [{
|
|
4174
|
+
type: "compaction",
|
|
4175
|
+
compact_threshold: compactThreshold
|
|
4176
|
+
}];
|
|
4177
|
+
const applyResponsesApiContextManagement = (payload, maxPromptTokens) => {
|
|
4178
|
+
if (payload.context_management !== void 0) return;
|
|
4179
|
+
if (!isResponsesApiContextManagementModel(payload.model)) return;
|
|
4180
|
+
payload.context_management = createCompactionContextManagement(resolveResponsesCompactThreshold(maxPromptTokens));
|
|
4181
|
+
};
|
|
4182
|
+
const compactInputByLatestCompaction = (payload) => {
|
|
4183
|
+
if (!Array.isArray(payload.input) || payload.input.length === 0) return;
|
|
4184
|
+
const latestCompactionMessageIndex = getLatestCompactionMessageIndex(payload.input);
|
|
4185
|
+
if (latestCompactionMessageIndex === void 0) return;
|
|
4186
|
+
payload.input = payload.input.slice(latestCompactionMessageIndex);
|
|
4187
|
+
};
|
|
4188
|
+
const getLatestCompactionMessageIndex = (input) => {
|
|
4189
|
+
for (let index = input.length - 1; index >= 0; index -= 1) if (isCompactionInputItem(input[index])) return index;
|
|
4190
|
+
};
|
|
4191
|
+
const isCompactionInputItem = (value) => {
|
|
4192
|
+
return "type" in value && typeof value.type === "string" && value.type === "compaction";
|
|
4193
|
+
};
|
|
4068
4194
|
const getPayloadItems = (payload) => {
|
|
4069
4195
|
const result = [];
|
|
4070
4196
|
const { input } = payload;
|
|
@@ -4113,8 +4239,9 @@ const createMessages = async (payload, account, options) => {
|
|
|
4113
4239
|
const initiator = options?.initiator ?? getMessagesInitiator(payload);
|
|
4114
4240
|
const headers = {
|
|
4115
4241
|
...copilotHeaders(ctx, enableVision, options?.upstreamRequestId),
|
|
4116
|
-
"
|
|
4242
|
+
"x-initiator": options?.subagentMarker ? "agent" : initiator
|
|
4117
4243
|
};
|
|
4244
|
+
prepareInteractionHeaders(options?.sessionId, Boolean(options?.subagentMarker), headers);
|
|
4118
4245
|
const anthropicBeta = buildAnthropicBetaHeader(options?.anthropicBetaHeader, payload.thinking);
|
|
4119
4246
|
if (anthropicBeta) headers["anthropic-beta"] = anthropicBeta;
|
|
4120
4247
|
const response = await fetch(`${copilotBaseUrl(ctx)}/v1/messages`, {
|
|
@@ -4434,7 +4561,7 @@ const parseSubagentMarkerFromSystemReminder = (text) => {
|
|
|
4434
4561
|
|
|
4435
4562
|
//#endregion
|
|
4436
4563
|
//#region src/routes/messages/handler.ts
|
|
4437
|
-
const logger$
|
|
4564
|
+
const logger$5 = createHandlerLogger("messages-handler");
|
|
4438
4565
|
const CHAT_COMPLETIONS_ENDPOINT = "/chat/completions";
|
|
4439
4566
|
const RESPONSES_ENDPOINT$1 = "/responses";
|
|
4440
4567
|
const MESSAGES_ENDPOINT = "/v1/messages";
|
|
@@ -4449,17 +4576,21 @@ async function handleCompletion(c) {
|
|
|
4449
4576
|
const { ip: clientIp, source: clientIpSource } = getClientIpInfo(c);
|
|
4450
4577
|
const userAgent = c.req.header("user-agent") ?? void 0;
|
|
4451
4578
|
const anthropicPayload = await c.req.json();
|
|
4452
|
-
logger$
|
|
4579
|
+
logger$5.debug("Anthropic request payload:", JSON.stringify(anthropicPayload));
|
|
4453
4580
|
const subagentMarker = parseSubagentMarkerFromFirstUser(anthropicPayload);
|
|
4454
4581
|
const initiatorOverride = subagentMarker ? "agent" : void 0;
|
|
4455
|
-
if (subagentMarker) logger$
|
|
4582
|
+
if (subagentMarker) logger$5.debug("Detected Subagent marker:", JSON.stringify(subagentMarker));
|
|
4583
|
+
const sessionId = getRootSessionId(anthropicPayload, c);
|
|
4584
|
+
logger$5.debug("Extracted session ID:", sessionId);
|
|
4456
4585
|
const anthropicBeta = c.req.header("anthropic-beta");
|
|
4457
4586
|
const isCompact = isCompactRequest(anthropicPayload);
|
|
4458
4587
|
if (anthropicBeta && isWarmupProbeRequest(anthropicPayload)) anthropicPayload.model = getSmallModel();
|
|
4459
4588
|
if (isCompact) {
|
|
4460
|
-
logger$
|
|
4589
|
+
logger$5.debug("Is compact request:", isCompact);
|
|
4461
4590
|
if (shouldCompactUseSmallModel()) anthropicPayload.model = getSmallModel();
|
|
4462
4591
|
} else mergeToolResultForClaude(anthropicPayload);
|
|
4592
|
+
const upstreamRequestId = generateRequestIdFromPayload(anthropicPayload, sessionId);
|
|
4593
|
+
logger$5.debug("Generated request ID:", upstreamRequestId);
|
|
4463
4594
|
const clientModel = anthropicPayload.model;
|
|
4464
4595
|
const streamRequested = Boolean(anthropicPayload.stream);
|
|
4465
4596
|
const rawUserId = anthropicPayload.metadata?.user_id;
|
|
@@ -4543,6 +4674,7 @@ async function handleCompletion(c) {
|
|
|
4543
4674
|
upstreamEndpoint: endpoint,
|
|
4544
4675
|
upstreamModel: selectedModel.id,
|
|
4545
4676
|
costUnits,
|
|
4677
|
+
upstreamRequestId,
|
|
4546
4678
|
premiumRemainingBefore,
|
|
4547
4679
|
premiumUnlimitedBefore
|
|
4548
4680
|
};
|
|
@@ -4551,6 +4683,8 @@ async function handleCompletion(c) {
|
|
|
4551
4683
|
anthropicPayload,
|
|
4552
4684
|
anthropicBetaHeader: anthropicBeta ?? void 0,
|
|
4553
4685
|
initiatorOverride,
|
|
4686
|
+
subagentMarker,
|
|
4687
|
+
sessionId,
|
|
4554
4688
|
instr,
|
|
4555
4689
|
selectedModel
|
|
4556
4690
|
});
|
|
@@ -4559,6 +4693,8 @@ async function handleCompletion(c) {
|
|
|
4559
4693
|
anthropicPayload,
|
|
4560
4694
|
openAIPayload,
|
|
4561
4695
|
initiatorOverride,
|
|
4696
|
+
subagentMarker,
|
|
4697
|
+
sessionId,
|
|
4562
4698
|
selectedModel,
|
|
4563
4699
|
instr
|
|
4564
4700
|
});
|
|
@@ -4566,23 +4702,25 @@ async function handleCompletion(c) {
|
|
|
4566
4702
|
c,
|
|
4567
4703
|
openAIPayload,
|
|
4568
4704
|
initiatorOverride,
|
|
4705
|
+
subagentMarker,
|
|
4706
|
+
sessionId,
|
|
4569
4707
|
selectedModel,
|
|
4570
4708
|
instr
|
|
4571
4709
|
});
|
|
4572
4710
|
}
|
|
4573
4711
|
const handleWithChatCompletions = async (params) => {
|
|
4574
|
-
const { c, openAIPayload, initiatorOverride, selectedModel, instr } = params;
|
|
4575
|
-
logger$
|
|
4712
|
+
const { c, openAIPayload, initiatorOverride, subagentMarker, sessionId, selectedModel, instr } = params;
|
|
4713
|
+
logger$5.debug("Translated OpenAI request payload:", JSON.stringify(openAIPayload));
|
|
4576
4714
|
const ctx = toAccountContext(instr.account);
|
|
4577
4715
|
const initiator = initiatorOverride ?? getChatInitiator(openAIPayload.messages);
|
|
4578
|
-
const upstreamRequestId = randomUUID();
|
|
4579
4716
|
instr.initiator = initiator;
|
|
4580
|
-
instr.upstreamRequestId = upstreamRequestId;
|
|
4581
4717
|
let response;
|
|
4582
4718
|
try {
|
|
4583
4719
|
response = await createChatCompletions(openAIPayload, ctx, {
|
|
4584
|
-
upstreamRequestId,
|
|
4585
|
-
initiator
|
|
4720
|
+
upstreamRequestId: instr.upstreamRequestId,
|
|
4721
|
+
initiator,
|
|
4722
|
+
subagentMarker,
|
|
4723
|
+
sessionId
|
|
4586
4724
|
});
|
|
4587
4725
|
} catch (error) {
|
|
4588
4726
|
return await handleChatCompletionsCreateError({
|
|
@@ -4596,9 +4734,9 @@ const handleWithChatCompletions = async (params) => {
|
|
|
4596
4734
|
response,
|
|
4597
4735
|
instr
|
|
4598
4736
|
});
|
|
4599
|
-
logger$
|
|
4737
|
+
logger$5.debug("Streaming response from Copilot");
|
|
4600
4738
|
const fallbackEnabled = isMessageStartInputTokensFallbackEnabled();
|
|
4601
|
-
const estimatedInputTokens = fallbackEnabled ? await estimateInputTokens(openAIPayload, selectedModel, logger$
|
|
4739
|
+
const estimatedInputTokens = fallbackEnabled ? await estimateInputTokens(openAIPayload, selectedModel, logger$5) : void 0;
|
|
4602
4740
|
const historicalUsage = fallbackEnabled && instr.promptCacheKey && instr.safetyIdentifier ? instr.store.getLastCompletedUsageBySession({
|
|
4603
4741
|
promptCacheKey: instr.promptCacheKey,
|
|
4604
4742
|
safetyIdentifier: instr.safetyIdentifier,
|
|
@@ -4613,21 +4751,23 @@ const handleWithChatCompletions = async (params) => {
|
|
|
4613
4751
|
}));
|
|
4614
4752
|
};
|
|
4615
4753
|
const handleWithResponsesApi = async (params) => {
|
|
4616
|
-
const { c, anthropicPayload, openAIPayload, initiatorOverride, selectedModel, instr } = params;
|
|
4754
|
+
const { c, anthropicPayload, openAIPayload, initiatorOverride, subagentMarker, sessionId, selectedModel, instr } = params;
|
|
4617
4755
|
const responsesPayload = translateAnthropicMessagesToResponsesPayload(anthropicPayload, selectedModel.id);
|
|
4618
|
-
|
|
4756
|
+
applyResponsesApiContextManagement(responsesPayload, selectedModel.capabilities.limits.max_prompt_tokens);
|
|
4757
|
+
compactInputByLatestCompaction(responsesPayload);
|
|
4758
|
+
logger$5.debug("Translated Responses payload:", JSON.stringify(responsesPayload));
|
|
4619
4759
|
const { vision, initiator } = getResponsesRequestOptions(responsesPayload);
|
|
4620
4760
|
const resolvedInitiator = initiatorOverride ?? initiator;
|
|
4621
4761
|
const ctx = toAccountContext(instr.account);
|
|
4622
|
-
const upstreamRequestId = randomUUID();
|
|
4623
4762
|
instr.initiator = resolvedInitiator;
|
|
4624
|
-
instr.upstreamRequestId = upstreamRequestId;
|
|
4625
4763
|
let response;
|
|
4626
4764
|
try {
|
|
4627
4765
|
response = await createResponses(responsesPayload, {
|
|
4628
4766
|
vision,
|
|
4629
4767
|
initiator: resolvedInitiator,
|
|
4630
|
-
upstreamRequestId
|
|
4768
|
+
upstreamRequestId: instr.upstreamRequestId,
|
|
4769
|
+
subagentMarker,
|
|
4770
|
+
sessionId
|
|
4631
4771
|
}, ctx);
|
|
4632
4772
|
} catch (error) {
|
|
4633
4773
|
return await handleResponsesCreateError({
|
|
@@ -4637,9 +4777,9 @@ const handleWithResponsesApi = async (params) => {
|
|
|
4637
4777
|
});
|
|
4638
4778
|
}
|
|
4639
4779
|
if (responsesPayload.stream && isAsyncIterable$1(response)) {
|
|
4640
|
-
logger$
|
|
4780
|
+
logger$5.debug("Streaming response from Copilot (Responses API)");
|
|
4641
4781
|
const fallbackEnabled = isMessageStartInputTokensFallbackEnabled();
|
|
4642
|
-
const estimatedInputTokens = fallbackEnabled ? await estimateInputTokens(openAIPayload, selectedModel, logger$
|
|
4782
|
+
const estimatedInputTokens = fallbackEnabled ? await estimateInputTokens(openAIPayload, selectedModel, logger$5) : void 0;
|
|
4643
4783
|
const historicalUsage = fallbackEnabled && instr.promptCacheKey && instr.safetyIdentifier ? instr.store.getLastCompletedUsageBySession({
|
|
4644
4784
|
promptCacheKey: instr.promptCacheKey,
|
|
4645
4785
|
safetyIdentifier: instr.safetyIdentifier,
|
|
@@ -4724,9 +4864,9 @@ async function handleChatCompletionsNonStreaming(params) {
|
|
|
4724
4864
|
let errorMessage;
|
|
4725
4865
|
const finishedAtMs = Date.now();
|
|
4726
4866
|
try {
|
|
4727
|
-
logger$
|
|
4867
|
+
logger$5.debug("Non-streaming response from Copilot:", JSON.stringify(response));
|
|
4728
4868
|
const anthropicResponse = translateToAnthropic(response);
|
|
4729
|
-
logger$
|
|
4869
|
+
logger$5.debug("Translated Anthropic response:", JSON.stringify(anthropicResponse));
|
|
4730
4870
|
return c.json(anthropicResponse);
|
|
4731
4871
|
} catch (error) {
|
|
4732
4872
|
const details = extractErrorDetails(error);
|
|
@@ -4774,7 +4914,7 @@ async function streamChatCompletionsAndLog(params) {
|
|
|
4774
4914
|
try {
|
|
4775
4915
|
for await (const rawEvent of response) {
|
|
4776
4916
|
if (ttfbMs === void 0) ttfbMs = Date.now() - instr.startedAtMs;
|
|
4777
|
-
logger$
|
|
4917
|
+
logger$5.debug("Copilot raw stream event:", JSON.stringify(rawEvent));
|
|
4778
4918
|
const { data: rawData } = rawEvent;
|
|
4779
4919
|
const data = typeof rawData === "string" ? rawData : await rawData;
|
|
4780
4920
|
if (data === "[DONE]") break;
|
|
@@ -4783,7 +4923,7 @@ async function streamChatCompletionsAndLog(params) {
|
|
|
4783
4923
|
if (chunk.usage) lastUsage = normalizeChatCompletionsUsage(chunk.usage);
|
|
4784
4924
|
const events$1 = translateChunkToAnthropicEvents(chunk, streamState);
|
|
4785
4925
|
for (const event of events$1) {
|
|
4786
|
-
logger$
|
|
4926
|
+
logger$5.debug("Translated Anthropic event:", JSON.stringify(event));
|
|
4787
4927
|
await stream.writeSSE({
|
|
4788
4928
|
event: event.type,
|
|
4789
4929
|
data: JSON.stringify(event)
|
|
@@ -4795,7 +4935,7 @@ async function streamChatCompletionsAndLog(params) {
|
|
|
4795
4935
|
errorName = details.errorName;
|
|
4796
4936
|
errorStatus = details.errorStatus;
|
|
4797
4937
|
errorMessage = details.errorMessage;
|
|
4798
|
-
logger$
|
|
4938
|
+
logger$5.warn("Streaming error:", error);
|
|
4799
4939
|
if (details.unauthorized) accountsManager.markAccountFailed(instr.account.id, "Unauthorized (401)");
|
|
4800
4940
|
} finally {
|
|
4801
4941
|
const finishedAtMs = Date.now();
|
|
@@ -4846,9 +4986,9 @@ async function handleResponsesNonStreaming(params) {
|
|
|
4846
4986
|
const finishedAtMs = Date.now();
|
|
4847
4987
|
try {
|
|
4848
4988
|
usage = extractResponsesUsageFromResult(result);
|
|
4849
|
-
logger$
|
|
4989
|
+
logger$5.debug("Non-streaming Responses result:", JSON.stringify(result).slice(-400));
|
|
4850
4990
|
const anthropicResponse = translateResponsesResultToAnthropic(result);
|
|
4851
|
-
logger$
|
|
4991
|
+
logger$5.debug("Translated Anthropic response:", JSON.stringify(anthropicResponse));
|
|
4852
4992
|
return c.json(anthropicResponse);
|
|
4853
4993
|
} catch (error) {
|
|
4854
4994
|
const details = extractErrorDetails(error);
|
|
@@ -4878,7 +5018,7 @@ async function handleResponsesNonStreaming(params) {
|
|
|
4878
5018
|
async function ensureResponsesStreamCompleted(params) {
|
|
4879
5019
|
const { stream, streamState, setStreamError } = params;
|
|
4880
5020
|
if (streamState.messageCompleted) return;
|
|
4881
|
-
logger$
|
|
5021
|
+
logger$5.warn("Responses stream ended without completion; sending error event");
|
|
4882
5022
|
const msg = "Responses stream ended without completion";
|
|
4883
5023
|
const errorEvent = buildErrorEvent(msg);
|
|
4884
5024
|
setStreamError("StreamIncomplete", msg);
|
|
@@ -4911,21 +5051,21 @@ async function streamResponsesAndLog$1(params) {
|
|
|
4911
5051
|
}
|
|
4912
5052
|
const data = chunk.data;
|
|
4913
5053
|
if (!data) continue;
|
|
4914
|
-
logger$
|
|
5054
|
+
logger$5.debug("Responses raw stream event:", data);
|
|
4915
5055
|
const parsed = JSON.parse(data);
|
|
4916
5056
|
const u = extractResponsesUsageFromStreamEvent(parsed);
|
|
4917
5057
|
if (u.usageJson) lastUsage = u;
|
|
4918
5058
|
const events$1 = translateResponsesStreamEvent(parsed, streamState);
|
|
4919
5059
|
for (const event of events$1) {
|
|
4920
5060
|
const eventData = JSON.stringify(event);
|
|
4921
|
-
logger$
|
|
5061
|
+
logger$5.debug("Translated Anthropic event:", eventData);
|
|
4922
5062
|
await stream.writeSSE({
|
|
4923
5063
|
event: event.type,
|
|
4924
5064
|
data: eventData
|
|
4925
5065
|
});
|
|
4926
5066
|
}
|
|
4927
5067
|
if (streamState.messageCompleted) {
|
|
4928
|
-
logger$
|
|
5068
|
+
logger$5.debug("Message completed, ending stream");
|
|
4929
5069
|
break;
|
|
4930
5070
|
}
|
|
4931
5071
|
}
|
|
@@ -4942,7 +5082,7 @@ async function streamResponsesAndLog$1(params) {
|
|
|
4942
5082
|
errorName = details.errorName;
|
|
4943
5083
|
errorStatus = details.errorStatus;
|
|
4944
5084
|
errorMessage = details.errorMessage;
|
|
4945
|
-
logger$
|
|
5085
|
+
logger$5.warn("Streaming error:", error);
|
|
4946
5086
|
if (details.unauthorized) accountsManager.markAccountFailed(instr.account.id, "Unauthorized (401)");
|
|
4947
5087
|
} finally {
|
|
4948
5088
|
const finishedAtMs = Date.now();
|
|
@@ -4992,7 +5132,7 @@ async function handleMessagesNonStreaming(params) {
|
|
|
4992
5132
|
let errorMessage;
|
|
4993
5133
|
const finishedAtMs = Date.now();
|
|
4994
5134
|
try {
|
|
4995
|
-
logger$
|
|
5135
|
+
logger$5.debug("Non-streaming Messages result:", JSON.stringify(response).slice(-400));
|
|
4996
5136
|
return c.json(response);
|
|
4997
5137
|
} catch (error) {
|
|
4998
5138
|
const details = extractErrorDetails(error);
|
|
@@ -5026,7 +5166,7 @@ const parseMessagesStreamUsage = (data) => {
|
|
|
5026
5166
|
if (parsed.type !== "message_delta" || !parsed.usage) return null;
|
|
5027
5167
|
return normalizeMessagesUsage(parsed.usage);
|
|
5028
5168
|
} catch (error) {
|
|
5029
|
-
logger$
|
|
5169
|
+
logger$5.warn("Failed to parse messages stream event", error);
|
|
5030
5170
|
return null;
|
|
5031
5171
|
}
|
|
5032
5172
|
};
|
|
@@ -5043,7 +5183,7 @@ async function streamMessagesAndLog(params) {
|
|
|
5043
5183
|
const eventNameRaw = rawEvent.event;
|
|
5044
5184
|
const eventName = typeof eventNameRaw === "string" && eventNameRaw.length > 0 ? eventNameRaw : "message";
|
|
5045
5185
|
const data = rawEvent.data ?? "";
|
|
5046
|
-
logger$
|
|
5186
|
+
logger$5.debug("Messages raw stream event:", data);
|
|
5047
5187
|
const usage = parseMessagesStreamUsage(data);
|
|
5048
5188
|
if (usage) lastUsage = usage;
|
|
5049
5189
|
await stream.writeSSE({
|
|
@@ -5056,7 +5196,7 @@ async function streamMessagesAndLog(params) {
|
|
|
5056
5196
|
errorName = details.errorName;
|
|
5057
5197
|
errorStatus = details.errorStatus;
|
|
5058
5198
|
errorMessage = details.errorMessage;
|
|
5059
|
-
logger$
|
|
5199
|
+
logger$5.warn("Streaming error:", error);
|
|
5060
5200
|
if (details.unauthorized) accountsManager.markAccountFailed(instr.account.id, "Unauthorized (401)");
|
|
5061
5201
|
} finally {
|
|
5062
5202
|
const finishedAtMs = Date.now();
|
|
@@ -5078,27 +5218,31 @@ async function streamMessagesAndLog(params) {
|
|
|
5078
5218
|
}
|
|
5079
5219
|
}
|
|
5080
5220
|
const handleWithMessagesApi = async (params) => {
|
|
5081
|
-
const { c, anthropicPayload, anthropicBetaHeader, initiatorOverride, instr, selectedModel } = params;
|
|
5221
|
+
const { c, anthropicPayload, anthropicBetaHeader, initiatorOverride, subagentMarker, sessionId, instr, selectedModel } = params;
|
|
5082
5222
|
for (const msg of anthropicPayload.messages) if (msg.role === "assistant" && Array.isArray(msg.content)) msg.content = msg.content.filter((block) => {
|
|
5083
5223
|
if (block.type !== "thinking") return true;
|
|
5084
5224
|
return block.thinking && block.thinking !== "Thinking..." && block.signature && !block.signature.includes("@");
|
|
5085
5225
|
});
|
|
5086
|
-
|
|
5226
|
+
const toolChoice = anthropicPayload.tool_choice;
|
|
5227
|
+
if (toolChoice?.type === "any" || toolChoice?.type === "tool") {
|
|
5228
|
+
delete anthropicPayload.thinking;
|
|
5229
|
+
delete anthropicPayload.output_config;
|
|
5230
|
+
} else if (selectedModel.capabilities.supports.adaptive_thinking) {
|
|
5087
5231
|
anthropicPayload.thinking = { type: "adaptive" };
|
|
5088
5232
|
anthropicPayload.output_config = { effort: getAnthropicEffortForModel(anthropicPayload.model) };
|
|
5089
5233
|
}
|
|
5090
|
-
logger$
|
|
5234
|
+
logger$5.debug("Translated Messages payload:", JSON.stringify(anthropicPayload));
|
|
5091
5235
|
const ctx = toAccountContext(instr.account);
|
|
5092
|
-
const upstreamRequestId = randomUUID();
|
|
5093
5236
|
const initiator = initiatorOverride ?? getMessagesInitiator(anthropicPayload);
|
|
5094
5237
|
instr.initiator = initiator;
|
|
5095
|
-
instr.upstreamRequestId = upstreamRequestId;
|
|
5096
5238
|
let response;
|
|
5097
5239
|
try {
|
|
5098
5240
|
response = await createMessages(anthropicPayload, ctx, {
|
|
5099
5241
|
anthropicBetaHeader,
|
|
5100
|
-
upstreamRequestId,
|
|
5101
|
-
initiator
|
|
5242
|
+
upstreamRequestId: instr.upstreamRequestId,
|
|
5243
|
+
initiator,
|
|
5244
|
+
subagentMarker,
|
|
5245
|
+
sessionId
|
|
5102
5246
|
});
|
|
5103
5247
|
} catch (error) {
|
|
5104
5248
|
return await handleMessagesCreateError({
|
|
@@ -5108,7 +5252,7 @@ const handleWithMessagesApi = async (params) => {
|
|
|
5108
5252
|
});
|
|
5109
5253
|
}
|
|
5110
5254
|
if (isAsyncIterable$1(response)) {
|
|
5111
|
-
logger$
|
|
5255
|
+
logger$5.debug("Streaming response from Copilot (Messages API)");
|
|
5112
5256
|
return streamSSE(c, (stream) => streamMessagesAndLog({
|
|
5113
5257
|
stream,
|
|
5114
5258
|
response,
|
|
@@ -5192,6 +5336,182 @@ modelRoutes.get("/", async (c) => {
|
|
|
5192
5336
|
}
|
|
5193
5337
|
});
|
|
5194
5338
|
|
|
5339
|
+
//#endregion
|
|
5340
|
+
//#region src/routes/provider/messages/count-tokens-handler.ts
|
|
5341
|
+
const logger$4 = createHandlerLogger("provider-count-tokens-handler");
|
|
5342
|
+
const createFallbackModel = (modelId) => ({
|
|
5343
|
+
capabilities: {
|
|
5344
|
+
family: "provider",
|
|
5345
|
+
limits: {},
|
|
5346
|
+
object: "model_capabilities",
|
|
5347
|
+
supports: {},
|
|
5348
|
+
tokenizer: "o200k_base",
|
|
5349
|
+
type: "chat"
|
|
5350
|
+
},
|
|
5351
|
+
id: modelId,
|
|
5352
|
+
model_picker_enabled: false,
|
|
5353
|
+
name: modelId,
|
|
5354
|
+
object: "model",
|
|
5355
|
+
preview: false,
|
|
5356
|
+
vendor: "provider",
|
|
5357
|
+
version: "unknown"
|
|
5358
|
+
});
|
|
5359
|
+
async function handleProviderCountTokens(c) {
|
|
5360
|
+
const provider = c.req.param("provider");
|
|
5361
|
+
try {
|
|
5362
|
+
const anthropicPayload = await c.req.json();
|
|
5363
|
+
const openAIPayload = translateToOpenAI(anthropicPayload);
|
|
5364
|
+
const modelId = anthropicPayload.model.trim();
|
|
5365
|
+
let selectedModel = state.models?.data.find((model) => model.id === modelId);
|
|
5366
|
+
if (!selectedModel && modelId) selectedModel = createFallbackModel(modelId);
|
|
5367
|
+
if (!selectedModel) {
|
|
5368
|
+
logger$4.warn("provider.count_tokens.model_not_found", {
|
|
5369
|
+
provider,
|
|
5370
|
+
model: anthropicPayload.model
|
|
5371
|
+
});
|
|
5372
|
+
return c.json({ input_tokens: 1 });
|
|
5373
|
+
}
|
|
5374
|
+
const tokenCount = await getTokenCount(openAIPayload, selectedModel);
|
|
5375
|
+
const finalTokenCount = tokenCount.input + tokenCount.output;
|
|
5376
|
+
logger$4.debug("provider.count_tokens.success", {
|
|
5377
|
+
provider,
|
|
5378
|
+
model: anthropicPayload.model,
|
|
5379
|
+
input_tokens: finalTokenCount
|
|
5380
|
+
});
|
|
5381
|
+
return c.json({ input_tokens: finalTokenCount });
|
|
5382
|
+
} catch (error) {
|
|
5383
|
+
logger$4.error("provider.count_tokens.error", {
|
|
5384
|
+
provider,
|
|
5385
|
+
error
|
|
5386
|
+
});
|
|
5387
|
+
return c.json({ input_tokens: 1 });
|
|
5388
|
+
}
|
|
5389
|
+
}
|
|
5390
|
+
|
|
5391
|
+
//#endregion
|
|
5392
|
+
//#region src/services/providers/anthropic-proxy.ts
|
|
5393
|
+
const FORWARDABLE_HEADERS = [
|
|
5394
|
+
"anthropic-version",
|
|
5395
|
+
"anthropic-beta",
|
|
5396
|
+
"accept",
|
|
5397
|
+
"user-agent"
|
|
5398
|
+
];
|
|
5399
|
+
function buildProviderUpstreamHeaders(providerConfig, requestHeaders) {
|
|
5400
|
+
const headers = {
|
|
5401
|
+
"content-type": "application/json",
|
|
5402
|
+
accept: "application/json",
|
|
5403
|
+
"x-api-key": providerConfig.apiKey
|
|
5404
|
+
};
|
|
5405
|
+
for (const headerName of FORWARDABLE_HEADERS) {
|
|
5406
|
+
const headerValue = requestHeaders.get(headerName);
|
|
5407
|
+
if (headerValue) headers[headerName] = headerValue;
|
|
5408
|
+
}
|
|
5409
|
+
return headers;
|
|
5410
|
+
}
|
|
5411
|
+
async function forwardProviderMessages(providerConfig, payload, requestHeaders) {
|
|
5412
|
+
return await fetch(`${providerConfig.baseUrl}/v1/messages`, {
|
|
5413
|
+
method: "POST",
|
|
5414
|
+
headers: buildProviderUpstreamHeaders(providerConfig, requestHeaders),
|
|
5415
|
+
body: JSON.stringify(payload)
|
|
5416
|
+
});
|
|
5417
|
+
}
|
|
5418
|
+
async function forwardProviderModels(providerConfig, requestHeaders) {
|
|
5419
|
+
return await fetch(`${providerConfig.baseUrl}/v1/models`, {
|
|
5420
|
+
method: "GET",
|
|
5421
|
+
headers: buildProviderUpstreamHeaders(providerConfig, requestHeaders)
|
|
5422
|
+
});
|
|
5423
|
+
}
|
|
5424
|
+
|
|
5425
|
+
//#endregion
|
|
5426
|
+
//#region src/routes/provider/messages/handler.ts
|
|
5427
|
+
const logger$3 = createHandlerLogger("provider-messages-handler");
|
|
5428
|
+
async function handleProviderMessages(c) {
|
|
5429
|
+
const provider = c.req.param("provider");
|
|
5430
|
+
const providerConfig = getProviderConfig(provider);
|
|
5431
|
+
if (!providerConfig) return c.json({ error: {
|
|
5432
|
+
message: `Provider '${provider}' not found or disabled`,
|
|
5433
|
+
type: "invalid_request_error"
|
|
5434
|
+
} }, 404);
|
|
5435
|
+
try {
|
|
5436
|
+
const payload = await c.req.json();
|
|
5437
|
+
payload.temperature ??= providerConfig.defaultTemperature;
|
|
5438
|
+
payload.top_p ??= providerConfig.defaultTopP;
|
|
5439
|
+
payload.top_k ??= providerConfig.defaultTopK;
|
|
5440
|
+
logger$3.debug("provider.messages.request", JSON.stringify({
|
|
5441
|
+
payload,
|
|
5442
|
+
provider
|
|
5443
|
+
}));
|
|
5444
|
+
const upstreamResponse = await forwardProviderMessages(providerConfig, payload, c.req.raw.headers);
|
|
5445
|
+
const contentType = upstreamResponse.headers.get("content-type") ?? "";
|
|
5446
|
+
if (Boolean(payload.stream) && contentType.includes("text/event-stream")) {
|
|
5447
|
+
logger$3.debug("provider.messages.streaming");
|
|
5448
|
+
return streamSSE(c, async (stream) => {
|
|
5449
|
+
for await (const event of events(upstreamResponse)) {
|
|
5450
|
+
const eventName = event.event;
|
|
5451
|
+
const data = event.data ?? "";
|
|
5452
|
+
logger$3.debug("provider.messages.raw_stream_event", data);
|
|
5453
|
+
await stream.writeSSE({
|
|
5454
|
+
event: eventName,
|
|
5455
|
+
data
|
|
5456
|
+
});
|
|
5457
|
+
}
|
|
5458
|
+
});
|
|
5459
|
+
}
|
|
5460
|
+
return upstreamResponse;
|
|
5461
|
+
} catch (error) {
|
|
5462
|
+
logger$3.error("provider.messages.error", {
|
|
5463
|
+
provider,
|
|
5464
|
+
error
|
|
5465
|
+
});
|
|
5466
|
+
throw error;
|
|
5467
|
+
}
|
|
5468
|
+
}
|
|
5469
|
+
|
|
5470
|
+
//#endregion
|
|
5471
|
+
//#region src/routes/provider/messages/route.ts
|
|
5472
|
+
const providerMessageRoutes = new Hono();
|
|
5473
|
+
providerMessageRoutes.post("/", async (c) => {
|
|
5474
|
+
try {
|
|
5475
|
+
return await handleProviderMessages(c);
|
|
5476
|
+
} catch (error) {
|
|
5477
|
+
return await forwardError(c, error);
|
|
5478
|
+
}
|
|
5479
|
+
});
|
|
5480
|
+
providerMessageRoutes.post("/count_tokens", async (c) => {
|
|
5481
|
+
try {
|
|
5482
|
+
return await handleProviderCountTokens(c);
|
|
5483
|
+
} catch (error) {
|
|
5484
|
+
return await forwardError(c, error);
|
|
5485
|
+
}
|
|
5486
|
+
});
|
|
5487
|
+
|
|
5488
|
+
//#endregion
|
|
5489
|
+
//#region src/routes/provider/models/route.ts
|
|
5490
|
+
const logger$2 = createHandlerLogger("provider-models-handler");
|
|
5491
|
+
const providerModelRoutes = new Hono();
|
|
5492
|
+
providerModelRoutes.get("/", async (c) => {
|
|
5493
|
+
const provider = c.req.param("provider") ?? "";
|
|
5494
|
+
try {
|
|
5495
|
+
const providerConfig = getProviderConfig(provider);
|
|
5496
|
+
if (!providerConfig) return c.json({ error: {
|
|
5497
|
+
message: `Provider '${provider}' not found or disabled`,
|
|
5498
|
+
type: "invalid_request_error"
|
|
5499
|
+
} }, 404);
|
|
5500
|
+
const upstreamResponse = await forwardProviderModels(providerConfig, c.req.raw.headers);
|
|
5501
|
+
logger$2.debug("provider.models.response", {
|
|
5502
|
+
provider,
|
|
5503
|
+
statusCode: upstreamResponse.status
|
|
5504
|
+
});
|
|
5505
|
+
return upstreamResponse;
|
|
5506
|
+
} catch (error) {
|
|
5507
|
+
logger$2.error("provider.models.error", {
|
|
5508
|
+
provider,
|
|
5509
|
+
error
|
|
5510
|
+
});
|
|
5511
|
+
return await forwardError(c, error);
|
|
5512
|
+
}
|
|
5513
|
+
});
|
|
5514
|
+
|
|
5195
5515
|
//#endregion
|
|
5196
5516
|
//#region src/routes/responses/stream-id-sync.ts
|
|
5197
5517
|
const createStreamIdTracker = () => ({ outputItems: /* @__PURE__ */ new Map() });
|
|
@@ -5241,6 +5561,7 @@ const handleResponses = async (c) => {
|
|
|
5241
5561
|
const clientModel = payload.model;
|
|
5242
5562
|
logger$1.debug("Responses request payload:", JSON.stringify(payload));
|
|
5243
5563
|
removeWebSearchTool(payload);
|
|
5564
|
+
compactInputByLatestCompaction(payload);
|
|
5244
5565
|
const streamRequested = Boolean(payload.stream);
|
|
5245
5566
|
const { initiator: initialInitiator } = getResponsesRequestOptions(payload);
|
|
5246
5567
|
const userId = payload.metadata?.user_id;
|
|
@@ -5282,13 +5603,18 @@ const handleResponses = async (c) => {
|
|
|
5282
5603
|
model: selectedModel.id
|
|
5283
5604
|
};
|
|
5284
5605
|
useFunctionApplyPatch(upstreamPayload);
|
|
5606
|
+
applyResponsesApiContextManagement(upstreamPayload, selectedModel.capabilities.limits.max_prompt_tokens);
|
|
5607
|
+
compactInputByLatestCompaction(upstreamPayload);
|
|
5285
5608
|
const premiumRemainingBefore = account.premiumRemaining;
|
|
5286
5609
|
const premiumUnlimitedBefore = account.unlimited;
|
|
5287
5610
|
const { vision, initiator } = getResponsesRequestOptions(upstreamPayload);
|
|
5288
5611
|
request.initiator = initiator;
|
|
5289
5612
|
if (state.manualApprove) await awaitApproval();
|
|
5290
5613
|
const accountCtx = toAccountContext(account);
|
|
5291
|
-
|
|
5614
|
+
const upstreamRequestId = generateRequestIdFromPayload({ messages: upstreamPayload.input });
|
|
5615
|
+
const upstreamSessionId = getUUID(upstreamRequestId);
|
|
5616
|
+
request.upstreamRequestId = upstreamRequestId;
|
|
5617
|
+
request.upstreamSessionId = upstreamSessionId;
|
|
5292
5618
|
if (streamRequested) return handleStreamingResponses({
|
|
5293
5619
|
c,
|
|
5294
5620
|
store,
|
|
@@ -5399,7 +5725,8 @@ async function handleStreamingResponses(params) {
|
|
|
5399
5725
|
response = await createResponses(payload, {
|
|
5400
5726
|
vision,
|
|
5401
5727
|
initiator,
|
|
5402
|
-
upstreamRequestId: request.upstreamRequestId
|
|
5728
|
+
upstreamRequestId: request.upstreamRequestId,
|
|
5729
|
+
sessionId: request.upstreamSessionId
|
|
5403
5730
|
}, accountCtx);
|
|
5404
5731
|
} catch (error) {
|
|
5405
5732
|
return handleUpstreamCreateError({
|
|
@@ -5584,7 +5911,8 @@ async function handleNonStreamingResponses(params) {
|
|
|
5584
5911
|
const response = await createResponses(payload, {
|
|
5585
5912
|
vision,
|
|
5586
5913
|
initiator,
|
|
5587
|
-
upstreamRequestId: request.upstreamRequestId
|
|
5914
|
+
upstreamRequestId: request.upstreamRequestId,
|
|
5915
|
+
sessionId: request.upstreamSessionId
|
|
5588
5916
|
}, accountCtx);
|
|
5589
5917
|
finishedAtMs = Date.now();
|
|
5590
5918
|
const streamResponse = handleUnexpectedResponsesStream(c, response);
|
|
@@ -5764,7 +6092,9 @@ server.route("/v1/models", modelRoutes);
|
|
|
5764
6092
|
server.route("/v1/embeddings", embeddingRoutes);
|
|
5765
6093
|
server.route("/v1/responses", responsesRoutes);
|
|
5766
6094
|
server.route("/v1/messages", messageRoutes);
|
|
6095
|
+
server.route("/:provider/v1/messages", providerMessageRoutes);
|
|
6096
|
+
server.route("/:provider/v1/models", providerModelRoutes);
|
|
5767
6097
|
|
|
5768
6098
|
//#endregion
|
|
5769
6099
|
export { server };
|
|
5770
|
-
//# sourceMappingURL=server-
|
|
6100
|
+
//# sourceMappingURL=server-BgJ8vqcw.js.map
|