@nick3/copilot-api 1.2.4 → 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 +47 -0
- package/dist/{accounts-manager-eec8Wj3_.js → accounts-manager-iJwqQUkM.js} +111 -8
- package/dist/accounts-manager-iJwqQUkM.js.map +1 -0
- package/dist/main.js +13 -9
- package/dist/main.js.map +1 -1
- package/dist/{server-Cxlbm6kJ.js → server-BgJ8vqcw.js} +226 -54
- package/dist/server-BgJ8vqcw.js.map +1 -0
- package/package.json +1 -1
- package/dist/accounts-manager-eec8Wj3_.js.map +0 -1
- package/dist/server-Cxlbm6kJ.js.map +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { HTTPError, PATHS, accountFromState, accountsManager, copilotBaseUrl, copilotHeaders, forwardError, generateRequestIdFromPayload, getAliasTargetSet, getConfig, getCopilotUsage, getExtraPromptForModel, getModelAliases, getModelAliasesInfo, getModelRefreshIntervalMs, getReasoningEffortForModel, getRootSessionId, getSmallModel, getUUID, isForceAgentEnabled, isFreeModelLoadBalancingEnabled, isMessageStartInputTokensFallbackEnabled, isNullish, isResponsesApiContextManagementModel, 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";
|
|
@@ -2234,11 +2234,7 @@ const createResponses = async (payload, { vision, initiator, upstreamRequestId,
|
|
|
2234
2234
|
...copilotHeaders(ctx, vision, upstreamRequestId),
|
|
2235
2235
|
"x-initiator": initiator
|
|
2236
2236
|
};
|
|
2237
|
-
|
|
2238
|
-
headers["x-initiator"] = "agent";
|
|
2239
|
-
headers["x-interaction-type"] = "conversation-subagent";
|
|
2240
|
-
}
|
|
2241
|
-
if (sessionId) headers["x-interaction-id"] = sessionId;
|
|
2237
|
+
prepareInteractionHeaders(sessionId, Boolean(subagentMarker), headers);
|
|
2242
2238
|
payload.service_tier = null;
|
|
2243
2239
|
const response = await fetch(`${copilotBaseUrl(ctx)}/responses`, {
|
|
2244
2240
|
method: "POST",
|
|
@@ -2718,8 +2714,7 @@ const createChatCompletions = async (payload, account, options) => {
|
|
|
2718
2714
|
...copilotHeaders(ctx, enableVision, options?.upstreamRequestId),
|
|
2719
2715
|
"x-initiator": options?.subagentMarker ? "agent" : initiator
|
|
2720
2716
|
};
|
|
2721
|
-
|
|
2722
|
-
if (options?.sessionId) headers["x-interaction-id"] = options.sessionId;
|
|
2717
|
+
prepareInteractionHeaders(options?.sessionId, Boolean(options?.subagentMarker), headers);
|
|
2723
2718
|
const upstreamPayload = applyDefaultReasoningEffort(payload);
|
|
2724
2719
|
const response = await fetch(`${copilotBaseUrl(ctx)}/chat/completions`, {
|
|
2725
2720
|
method: "POST",
|
|
@@ -2736,7 +2731,7 @@ const createChatCompletions = async (payload, account, options) => {
|
|
|
2736
2731
|
|
|
2737
2732
|
//#endregion
|
|
2738
2733
|
//#region src/routes/chat-completions/handler.ts
|
|
2739
|
-
const logger$
|
|
2734
|
+
const logger$6 = createHandlerLogger("chat-completions-handler");
|
|
2740
2735
|
const CHAT_COMPLETIONS_ENDPOINT$1 = "/chat/completions";
|
|
2741
2736
|
async function handleCompletion$1(c) {
|
|
2742
2737
|
await checkRateLimit(state);
|
|
@@ -2766,7 +2761,7 @@ async function handleCompletion$1(c) {
|
|
|
2766
2761
|
reason: "MODEL_NOT_SUPPORTED"
|
|
2767
2762
|
});
|
|
2768
2763
|
}
|
|
2769
|
-
logger$
|
|
2764
|
+
logger$6.debug("Request payload:", JSON.stringify(payload).slice(-400));
|
|
2770
2765
|
const selection = await accountsManager.selectAccountForRequest([{
|
|
2771
2766
|
modelId: clientModel,
|
|
2772
2767
|
endpoint: CHAT_COMPLETIONS_ENDPOINT$1
|
|
@@ -2885,9 +2880,9 @@ function selectionFailureResponse$2(c, params) {
|
|
|
2885
2880
|
async function logTokenCountForRequest(params) {
|
|
2886
2881
|
try {
|
|
2887
2882
|
const tokenCount = await getTokenCount(params.payload, params.selectedModel);
|
|
2888
|
-
logger$
|
|
2883
|
+
logger$6.info("Current token count:", tokenCount);
|
|
2889
2884
|
} catch (error) {
|
|
2890
|
-
logger$
|
|
2885
|
+
logger$6.warn("Failed to calculate token count:", error);
|
|
2891
2886
|
}
|
|
2892
2887
|
}
|
|
2893
2888
|
function applyDefaultMaxTokens(payload, selectedModel) {
|
|
@@ -2896,7 +2891,7 @@ function applyDefaultMaxTokens(payload, selectedModel) {
|
|
|
2896
2891
|
...payload,
|
|
2897
2892
|
max_tokens: selectedModel.capabilities.limits.max_output_tokens
|
|
2898
2893
|
};
|
|
2899
|
-
logger$
|
|
2894
|
+
logger$6.debug("Set max_tokens to:", JSON.stringify(updated.max_tokens));
|
|
2900
2895
|
return updated;
|
|
2901
2896
|
}
|
|
2902
2897
|
async function handleStreamingRequest(params) {
|
|
@@ -2928,7 +2923,7 @@ async function handleStreamingRequest(params) {
|
|
|
2928
2923
|
premiumUnlimitedBefore,
|
|
2929
2924
|
response
|
|
2930
2925
|
});
|
|
2931
|
-
logger$
|
|
2926
|
+
logger$6.debug("Streaming response");
|
|
2932
2927
|
return streamSSE(c, (stream) => streamChatCompletionsAndLog$1({
|
|
2933
2928
|
stream,
|
|
2934
2929
|
response,
|
|
@@ -2981,7 +2976,7 @@ async function handleNonStreamingUpstreamResponse(params) {
|
|
|
2981
2976
|
let errorMessage;
|
|
2982
2977
|
const finishedAtMs = Date.now();
|
|
2983
2978
|
try {
|
|
2984
|
-
logger$
|
|
2979
|
+
logger$6.debug("Non-streaming response:", JSON.stringify(response));
|
|
2985
2980
|
return c.json(response);
|
|
2986
2981
|
} catch (error) {
|
|
2987
2982
|
const details = extractErrorDetails(error);
|
|
@@ -3031,7 +3026,7 @@ async function streamChatCompletionsAndLog$1(params) {
|
|
|
3031
3026
|
if (ttfbMs === void 0) ttfbMs = Date.now() - request.startedAtMs;
|
|
3032
3027
|
const usage = await extractUsageFromChunk(chunk);
|
|
3033
3028
|
if (usage) lastUsage = usage;
|
|
3034
|
-
logger$
|
|
3029
|
+
logger$6.debug("Streaming chunk:", JSON.stringify(chunk));
|
|
3035
3030
|
await stream.writeSSE(chunk);
|
|
3036
3031
|
}
|
|
3037
3032
|
} catch (error) {
|
|
@@ -3039,7 +3034,7 @@ async function streamChatCompletionsAndLog$1(params) {
|
|
|
3039
3034
|
errorName = details.errorName;
|
|
3040
3035
|
errorStatus = details.errorStatus;
|
|
3041
3036
|
errorMessage = details.errorMessage;
|
|
3042
|
-
logger$
|
|
3037
|
+
logger$6.warn("Streaming error:", error);
|
|
3043
3038
|
} finally {
|
|
3044
3039
|
const finishedAtMs = Date.now();
|
|
3045
3040
|
await accountsManager.finalizeQuota(account, reservation);
|
|
@@ -3096,13 +3091,13 @@ async function handleNonStreamingRequest(params) {
|
|
|
3096
3091
|
});
|
|
3097
3092
|
finishedAtMs = Date.now();
|
|
3098
3093
|
if (!isNonStreaming$1(response)) {
|
|
3099
|
-
logger$
|
|
3094
|
+
logger$6.debug("Unexpected streaming response");
|
|
3100
3095
|
return streamSSE(c, async (stream) => {
|
|
3101
3096
|
for await (const chunk of response) await stream.writeSSE(chunk);
|
|
3102
3097
|
});
|
|
3103
3098
|
}
|
|
3104
3099
|
usage = normalizeChatCompletionsUsage(response.usage);
|
|
3105
|
-
logger$
|
|
3100
|
+
logger$6.debug("Non-streaming response:", JSON.stringify(response));
|
|
3106
3101
|
return c.json(response);
|
|
3107
3102
|
} catch (error) {
|
|
3108
3103
|
finishedAtMs = Date.now();
|
|
@@ -3374,11 +3369,11 @@ const mergeToolResultForClaude = (anthropicPayload) => {
|
|
|
3374
3369
|
msg.content = mergeToolResult(toolResults, textBlocks);
|
|
3375
3370
|
}
|
|
3376
3371
|
};
|
|
3377
|
-
const estimateInputTokens = async (payload, selectedModel, logger$
|
|
3372
|
+
const estimateInputTokens = async (payload, selectedModel, logger$7) => {
|
|
3378
3373
|
try {
|
|
3379
3374
|
return (await getTokenCount(payload, selectedModel)).input;
|
|
3380
3375
|
} catch (error) {
|
|
3381
|
-
logger$
|
|
3376
|
+
logger$7.warn("Failed to estimate input tokens for message_start", error);
|
|
3382
3377
|
return;
|
|
3383
3378
|
}
|
|
3384
3379
|
};
|
|
@@ -4246,8 +4241,7 @@ const createMessages = async (payload, account, options) => {
|
|
|
4246
4241
|
...copilotHeaders(ctx, enableVision, options?.upstreamRequestId),
|
|
4247
4242
|
"x-initiator": options?.subagentMarker ? "agent" : initiator
|
|
4248
4243
|
};
|
|
4249
|
-
|
|
4250
|
-
if (options?.sessionId) headers["x-interaction-id"] = options.sessionId;
|
|
4244
|
+
prepareInteractionHeaders(options?.sessionId, Boolean(options?.subagentMarker), headers);
|
|
4251
4245
|
const anthropicBeta = buildAnthropicBetaHeader(options?.anthropicBetaHeader, payload.thinking);
|
|
4252
4246
|
if (anthropicBeta) headers["anthropic-beta"] = anthropicBeta;
|
|
4253
4247
|
const response = await fetch(`${copilotBaseUrl(ctx)}/v1/messages`, {
|
|
@@ -4567,7 +4561,7 @@ const parseSubagentMarkerFromSystemReminder = (text) => {
|
|
|
4567
4561
|
|
|
4568
4562
|
//#endregion
|
|
4569
4563
|
//#region src/routes/messages/handler.ts
|
|
4570
|
-
const logger$
|
|
4564
|
+
const logger$5 = createHandlerLogger("messages-handler");
|
|
4571
4565
|
const CHAT_COMPLETIONS_ENDPOINT = "/chat/completions";
|
|
4572
4566
|
const RESPONSES_ENDPOINT$1 = "/responses";
|
|
4573
4567
|
const MESSAGES_ENDPOINT = "/v1/messages";
|
|
@@ -4582,21 +4576,21 @@ async function handleCompletion(c) {
|
|
|
4582
4576
|
const { ip: clientIp, source: clientIpSource } = getClientIpInfo(c);
|
|
4583
4577
|
const userAgent = c.req.header("user-agent") ?? void 0;
|
|
4584
4578
|
const anthropicPayload = await c.req.json();
|
|
4585
|
-
logger$
|
|
4579
|
+
logger$5.debug("Anthropic request payload:", JSON.stringify(anthropicPayload));
|
|
4586
4580
|
const subagentMarker = parseSubagentMarkerFromFirstUser(anthropicPayload);
|
|
4587
4581
|
const initiatorOverride = subagentMarker ? "agent" : void 0;
|
|
4588
|
-
if (subagentMarker) logger$
|
|
4582
|
+
if (subagentMarker) logger$5.debug("Detected Subagent marker:", JSON.stringify(subagentMarker));
|
|
4589
4583
|
const sessionId = getRootSessionId(anthropicPayload, c);
|
|
4590
|
-
logger$
|
|
4584
|
+
logger$5.debug("Extracted session ID:", sessionId);
|
|
4591
4585
|
const anthropicBeta = c.req.header("anthropic-beta");
|
|
4592
4586
|
const isCompact = isCompactRequest(anthropicPayload);
|
|
4593
4587
|
if (anthropicBeta && isWarmupProbeRequest(anthropicPayload)) anthropicPayload.model = getSmallModel();
|
|
4594
4588
|
if (isCompact) {
|
|
4595
|
-
logger$
|
|
4589
|
+
logger$5.debug("Is compact request:", isCompact);
|
|
4596
4590
|
if (shouldCompactUseSmallModel()) anthropicPayload.model = getSmallModel();
|
|
4597
4591
|
} else mergeToolResultForClaude(anthropicPayload);
|
|
4598
4592
|
const upstreamRequestId = generateRequestIdFromPayload(anthropicPayload, sessionId);
|
|
4599
|
-
logger$
|
|
4593
|
+
logger$5.debug("Generated request ID:", upstreamRequestId);
|
|
4600
4594
|
const clientModel = anthropicPayload.model;
|
|
4601
4595
|
const streamRequested = Boolean(anthropicPayload.stream);
|
|
4602
4596
|
const rawUserId = anthropicPayload.metadata?.user_id;
|
|
@@ -4716,7 +4710,7 @@ async function handleCompletion(c) {
|
|
|
4716
4710
|
}
|
|
4717
4711
|
const handleWithChatCompletions = async (params) => {
|
|
4718
4712
|
const { c, openAIPayload, initiatorOverride, subagentMarker, sessionId, selectedModel, instr } = params;
|
|
4719
|
-
logger$
|
|
4713
|
+
logger$5.debug("Translated OpenAI request payload:", JSON.stringify(openAIPayload));
|
|
4720
4714
|
const ctx = toAccountContext(instr.account);
|
|
4721
4715
|
const initiator = initiatorOverride ?? getChatInitiator(openAIPayload.messages);
|
|
4722
4716
|
instr.initiator = initiator;
|
|
@@ -4740,9 +4734,9 @@ const handleWithChatCompletions = async (params) => {
|
|
|
4740
4734
|
response,
|
|
4741
4735
|
instr
|
|
4742
4736
|
});
|
|
4743
|
-
logger$
|
|
4737
|
+
logger$5.debug("Streaming response from Copilot");
|
|
4744
4738
|
const fallbackEnabled = isMessageStartInputTokensFallbackEnabled();
|
|
4745
|
-
const estimatedInputTokens = fallbackEnabled ? await estimateInputTokens(openAIPayload, selectedModel, logger$
|
|
4739
|
+
const estimatedInputTokens = fallbackEnabled ? await estimateInputTokens(openAIPayload, selectedModel, logger$5) : void 0;
|
|
4746
4740
|
const historicalUsage = fallbackEnabled && instr.promptCacheKey && instr.safetyIdentifier ? instr.store.getLastCompletedUsageBySession({
|
|
4747
4741
|
promptCacheKey: instr.promptCacheKey,
|
|
4748
4742
|
safetyIdentifier: instr.safetyIdentifier,
|
|
@@ -4761,7 +4755,7 @@ const handleWithResponsesApi = async (params) => {
|
|
|
4761
4755
|
const responsesPayload = translateAnthropicMessagesToResponsesPayload(anthropicPayload, selectedModel.id);
|
|
4762
4756
|
applyResponsesApiContextManagement(responsesPayload, selectedModel.capabilities.limits.max_prompt_tokens);
|
|
4763
4757
|
compactInputByLatestCompaction(responsesPayload);
|
|
4764
|
-
logger$
|
|
4758
|
+
logger$5.debug("Translated Responses payload:", JSON.stringify(responsesPayload));
|
|
4765
4759
|
const { vision, initiator } = getResponsesRequestOptions(responsesPayload);
|
|
4766
4760
|
const resolvedInitiator = initiatorOverride ?? initiator;
|
|
4767
4761
|
const ctx = toAccountContext(instr.account);
|
|
@@ -4783,9 +4777,9 @@ const handleWithResponsesApi = async (params) => {
|
|
|
4783
4777
|
});
|
|
4784
4778
|
}
|
|
4785
4779
|
if (responsesPayload.stream && isAsyncIterable$1(response)) {
|
|
4786
|
-
logger$
|
|
4780
|
+
logger$5.debug("Streaming response from Copilot (Responses API)");
|
|
4787
4781
|
const fallbackEnabled = isMessageStartInputTokensFallbackEnabled();
|
|
4788
|
-
const estimatedInputTokens = fallbackEnabled ? await estimateInputTokens(openAIPayload, selectedModel, logger$
|
|
4782
|
+
const estimatedInputTokens = fallbackEnabled ? await estimateInputTokens(openAIPayload, selectedModel, logger$5) : void 0;
|
|
4789
4783
|
const historicalUsage = fallbackEnabled && instr.promptCacheKey && instr.safetyIdentifier ? instr.store.getLastCompletedUsageBySession({
|
|
4790
4784
|
promptCacheKey: instr.promptCacheKey,
|
|
4791
4785
|
safetyIdentifier: instr.safetyIdentifier,
|
|
@@ -4870,9 +4864,9 @@ async function handleChatCompletionsNonStreaming(params) {
|
|
|
4870
4864
|
let errorMessage;
|
|
4871
4865
|
const finishedAtMs = Date.now();
|
|
4872
4866
|
try {
|
|
4873
|
-
logger$
|
|
4867
|
+
logger$5.debug("Non-streaming response from Copilot:", JSON.stringify(response));
|
|
4874
4868
|
const anthropicResponse = translateToAnthropic(response);
|
|
4875
|
-
logger$
|
|
4869
|
+
logger$5.debug("Translated Anthropic response:", JSON.stringify(anthropicResponse));
|
|
4876
4870
|
return c.json(anthropicResponse);
|
|
4877
4871
|
} catch (error) {
|
|
4878
4872
|
const details = extractErrorDetails(error);
|
|
@@ -4920,7 +4914,7 @@ async function streamChatCompletionsAndLog(params) {
|
|
|
4920
4914
|
try {
|
|
4921
4915
|
for await (const rawEvent of response) {
|
|
4922
4916
|
if (ttfbMs === void 0) ttfbMs = Date.now() - instr.startedAtMs;
|
|
4923
|
-
logger$
|
|
4917
|
+
logger$5.debug("Copilot raw stream event:", JSON.stringify(rawEvent));
|
|
4924
4918
|
const { data: rawData } = rawEvent;
|
|
4925
4919
|
const data = typeof rawData === "string" ? rawData : await rawData;
|
|
4926
4920
|
if (data === "[DONE]") break;
|
|
@@ -4929,7 +4923,7 @@ async function streamChatCompletionsAndLog(params) {
|
|
|
4929
4923
|
if (chunk.usage) lastUsage = normalizeChatCompletionsUsage(chunk.usage);
|
|
4930
4924
|
const events$1 = translateChunkToAnthropicEvents(chunk, streamState);
|
|
4931
4925
|
for (const event of events$1) {
|
|
4932
|
-
logger$
|
|
4926
|
+
logger$5.debug("Translated Anthropic event:", JSON.stringify(event));
|
|
4933
4927
|
await stream.writeSSE({
|
|
4934
4928
|
event: event.type,
|
|
4935
4929
|
data: JSON.stringify(event)
|
|
@@ -4941,7 +4935,7 @@ async function streamChatCompletionsAndLog(params) {
|
|
|
4941
4935
|
errorName = details.errorName;
|
|
4942
4936
|
errorStatus = details.errorStatus;
|
|
4943
4937
|
errorMessage = details.errorMessage;
|
|
4944
|
-
logger$
|
|
4938
|
+
logger$5.warn("Streaming error:", error);
|
|
4945
4939
|
if (details.unauthorized) accountsManager.markAccountFailed(instr.account.id, "Unauthorized (401)");
|
|
4946
4940
|
} finally {
|
|
4947
4941
|
const finishedAtMs = Date.now();
|
|
@@ -4992,9 +4986,9 @@ async function handleResponsesNonStreaming(params) {
|
|
|
4992
4986
|
const finishedAtMs = Date.now();
|
|
4993
4987
|
try {
|
|
4994
4988
|
usage = extractResponsesUsageFromResult(result);
|
|
4995
|
-
logger$
|
|
4989
|
+
logger$5.debug("Non-streaming Responses result:", JSON.stringify(result).slice(-400));
|
|
4996
4990
|
const anthropicResponse = translateResponsesResultToAnthropic(result);
|
|
4997
|
-
logger$
|
|
4991
|
+
logger$5.debug("Translated Anthropic response:", JSON.stringify(anthropicResponse));
|
|
4998
4992
|
return c.json(anthropicResponse);
|
|
4999
4993
|
} catch (error) {
|
|
5000
4994
|
const details = extractErrorDetails(error);
|
|
@@ -5024,7 +5018,7 @@ async function handleResponsesNonStreaming(params) {
|
|
|
5024
5018
|
async function ensureResponsesStreamCompleted(params) {
|
|
5025
5019
|
const { stream, streamState, setStreamError } = params;
|
|
5026
5020
|
if (streamState.messageCompleted) return;
|
|
5027
|
-
logger$
|
|
5021
|
+
logger$5.warn("Responses stream ended without completion; sending error event");
|
|
5028
5022
|
const msg = "Responses stream ended without completion";
|
|
5029
5023
|
const errorEvent = buildErrorEvent(msg);
|
|
5030
5024
|
setStreamError("StreamIncomplete", msg);
|
|
@@ -5057,21 +5051,21 @@ async function streamResponsesAndLog$1(params) {
|
|
|
5057
5051
|
}
|
|
5058
5052
|
const data = chunk.data;
|
|
5059
5053
|
if (!data) continue;
|
|
5060
|
-
logger$
|
|
5054
|
+
logger$5.debug("Responses raw stream event:", data);
|
|
5061
5055
|
const parsed = JSON.parse(data);
|
|
5062
5056
|
const u = extractResponsesUsageFromStreamEvent(parsed);
|
|
5063
5057
|
if (u.usageJson) lastUsage = u;
|
|
5064
5058
|
const events$1 = translateResponsesStreamEvent(parsed, streamState);
|
|
5065
5059
|
for (const event of events$1) {
|
|
5066
5060
|
const eventData = JSON.stringify(event);
|
|
5067
|
-
logger$
|
|
5061
|
+
logger$5.debug("Translated Anthropic event:", eventData);
|
|
5068
5062
|
await stream.writeSSE({
|
|
5069
5063
|
event: event.type,
|
|
5070
5064
|
data: eventData
|
|
5071
5065
|
});
|
|
5072
5066
|
}
|
|
5073
5067
|
if (streamState.messageCompleted) {
|
|
5074
|
-
logger$
|
|
5068
|
+
logger$5.debug("Message completed, ending stream");
|
|
5075
5069
|
break;
|
|
5076
5070
|
}
|
|
5077
5071
|
}
|
|
@@ -5088,7 +5082,7 @@ async function streamResponsesAndLog$1(params) {
|
|
|
5088
5082
|
errorName = details.errorName;
|
|
5089
5083
|
errorStatus = details.errorStatus;
|
|
5090
5084
|
errorMessage = details.errorMessage;
|
|
5091
|
-
logger$
|
|
5085
|
+
logger$5.warn("Streaming error:", error);
|
|
5092
5086
|
if (details.unauthorized) accountsManager.markAccountFailed(instr.account.id, "Unauthorized (401)");
|
|
5093
5087
|
} finally {
|
|
5094
5088
|
const finishedAtMs = Date.now();
|
|
@@ -5138,7 +5132,7 @@ async function handleMessagesNonStreaming(params) {
|
|
|
5138
5132
|
let errorMessage;
|
|
5139
5133
|
const finishedAtMs = Date.now();
|
|
5140
5134
|
try {
|
|
5141
|
-
logger$
|
|
5135
|
+
logger$5.debug("Non-streaming Messages result:", JSON.stringify(response).slice(-400));
|
|
5142
5136
|
return c.json(response);
|
|
5143
5137
|
} catch (error) {
|
|
5144
5138
|
const details = extractErrorDetails(error);
|
|
@@ -5172,7 +5166,7 @@ const parseMessagesStreamUsage = (data) => {
|
|
|
5172
5166
|
if (parsed.type !== "message_delta" || !parsed.usage) return null;
|
|
5173
5167
|
return normalizeMessagesUsage(parsed.usage);
|
|
5174
5168
|
} catch (error) {
|
|
5175
|
-
logger$
|
|
5169
|
+
logger$5.warn("Failed to parse messages stream event", error);
|
|
5176
5170
|
return null;
|
|
5177
5171
|
}
|
|
5178
5172
|
};
|
|
@@ -5189,7 +5183,7 @@ async function streamMessagesAndLog(params) {
|
|
|
5189
5183
|
const eventNameRaw = rawEvent.event;
|
|
5190
5184
|
const eventName = typeof eventNameRaw === "string" && eventNameRaw.length > 0 ? eventNameRaw : "message";
|
|
5191
5185
|
const data = rawEvent.data ?? "";
|
|
5192
|
-
logger$
|
|
5186
|
+
logger$5.debug("Messages raw stream event:", data);
|
|
5193
5187
|
const usage = parseMessagesStreamUsage(data);
|
|
5194
5188
|
if (usage) lastUsage = usage;
|
|
5195
5189
|
await stream.writeSSE({
|
|
@@ -5202,7 +5196,7 @@ async function streamMessagesAndLog(params) {
|
|
|
5202
5196
|
errorName = details.errorName;
|
|
5203
5197
|
errorStatus = details.errorStatus;
|
|
5204
5198
|
errorMessage = details.errorMessage;
|
|
5205
|
-
logger$
|
|
5199
|
+
logger$5.warn("Streaming error:", error);
|
|
5206
5200
|
if (details.unauthorized) accountsManager.markAccountFailed(instr.account.id, "Unauthorized (401)");
|
|
5207
5201
|
} finally {
|
|
5208
5202
|
const finishedAtMs = Date.now();
|
|
@@ -5237,7 +5231,7 @@ const handleWithMessagesApi = async (params) => {
|
|
|
5237
5231
|
anthropicPayload.thinking = { type: "adaptive" };
|
|
5238
5232
|
anthropicPayload.output_config = { effort: getAnthropicEffortForModel(anthropicPayload.model) };
|
|
5239
5233
|
}
|
|
5240
|
-
logger$
|
|
5234
|
+
logger$5.debug("Translated Messages payload:", JSON.stringify(anthropicPayload));
|
|
5241
5235
|
const ctx = toAccountContext(instr.account);
|
|
5242
5236
|
const initiator = initiatorOverride ?? getMessagesInitiator(anthropicPayload);
|
|
5243
5237
|
instr.initiator = initiator;
|
|
@@ -5258,7 +5252,7 @@ const handleWithMessagesApi = async (params) => {
|
|
|
5258
5252
|
});
|
|
5259
5253
|
}
|
|
5260
5254
|
if (isAsyncIterable$1(response)) {
|
|
5261
|
-
logger$
|
|
5255
|
+
logger$5.debug("Streaming response from Copilot (Messages API)");
|
|
5262
5256
|
return streamSSE(c, (stream) => streamMessagesAndLog({
|
|
5263
5257
|
stream,
|
|
5264
5258
|
response,
|
|
@@ -5342,6 +5336,182 @@ modelRoutes.get("/", async (c) => {
|
|
|
5342
5336
|
}
|
|
5343
5337
|
});
|
|
5344
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
|
+
|
|
5345
5515
|
//#endregion
|
|
5346
5516
|
//#region src/routes/responses/stream-id-sync.ts
|
|
5347
5517
|
const createStreamIdTracker = () => ({ outputItems: /* @__PURE__ */ new Map() });
|
|
@@ -5922,7 +6092,9 @@ server.route("/v1/models", modelRoutes);
|
|
|
5922
6092
|
server.route("/v1/embeddings", embeddingRoutes);
|
|
5923
6093
|
server.route("/v1/responses", responsesRoutes);
|
|
5924
6094
|
server.route("/v1/messages", messageRoutes);
|
|
6095
|
+
server.route("/:provider/v1/messages", providerMessageRoutes);
|
|
6096
|
+
server.route("/:provider/v1/models", providerModelRoutes);
|
|
5925
6097
|
|
|
5926
6098
|
//#endregion
|
|
5927
6099
|
export { server };
|
|
5928
|
-
//# sourceMappingURL=server-
|
|
6100
|
+
//# sourceMappingURL=server-BgJ8vqcw.js.map
|