@nick3/copilot-api 1.10.30 → 1.10.34
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 +41 -9
- package/README.zh-CN.md +39 -7
- package/dist/admin/assets/index-Cl_ViIW_.js +110 -0
- package/dist/admin/index.html +1 -1
- package/dist/{auth-CnwhQOu6.js → auth-Cc11G9V9.js} +2 -2
- package/dist/{auth-CnwhQOu6.js.map → auth-Cc11G9V9.js.map} +1 -1
- package/dist/{check-usage-CseltoFJ.js → check-usage-C2QE6R93.js} +2 -2
- package/dist/{check-usage-CseltoFJ.js.map → check-usage-C2QE6R93.js.map} +1 -1
- package/dist/{config-XZv75uoU.js → config-BaU_aWgi.js} +22 -4
- package/dist/config-BaU_aWgi.js.map +1 -0
- package/dist/{debug-D8xHblDV.js → debug-BKqoXB_p.js} +2 -2
- package/dist/{debug-D8xHblDV.js.map → debug-BKqoXB_p.js.map} +1 -1
- package/dist/main.js +4 -4
- package/dist/{responses-bridge-registry-JjUvTCST.js → responses-bridge-registry-DqCoY6Ex.js} +2 -2
- package/dist/{responses-bridge-registry-JjUvTCST.js.map → responses-bridge-registry-DqCoY6Ex.js.map} +1 -1
- package/dist/{server-BYKxAFro.js → server-C7pCkArb.js} +315 -147
- package/dist/server-C7pCkArb.js.map +1 -0
- package/dist/{start-DVlCJ0Ma.js → start-CdLbBkRA.js} +4 -4
- package/dist/{start-DVlCJ0Ma.js.map → start-CdLbBkRA.js.map} +1 -1
- package/dist/{token-9O2KJcF5.js → token-671YFxgv.js} +3 -2
- package/dist/token-671YFxgv.js.map +1 -0
- package/package.json +1 -1
- package/dist/admin/assets/index-BGmG-ckX.js +0 -110
- package/dist/config-XZv75uoU.js.map +0 -1
- package/dist/server-BYKxAFro.js.map +0 -1
- package/dist/token-9O2KJcF5.js.map +0 -1
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { A as accountFromState, B as compactSystemPromptStarts, C as copilotHeaders, D as prepareForCompact, E as normalizeDomain, F as resolveTraceId, L as compactAutoContinuePromptStarts, M as captureOutboundHeadersSnapshot, O as prepareInteractionHeaders, P as requestContext, R as compactMessageSections, S as copilotBaseUrl, T as copilotWebSocketHeaders, b as HTTPError, c as getUUID, d as parseUserIdMetadata, f as resolveAffinityKey, g as getCopilotUsage, h as getDeviceCode, j as state, k as prepareMessageProxyHeaders, l as isNullish, m as getGitHubUser, o as generateRequestIdFromPayload, p as sleep, s as getRootSessionId, t as pollAccessToken, u as normalizeStableSessionId, v as getProxyEnvDispatcher, x as forwardError } from "./poll-access-token-GzVkiTH8.js";
|
|
2
2
|
import { a as getAccountClientIdentityByLoginAndApp, b as getCurrentIdentityEnvironment, d as loadRegistry, g as saveRegistry, h as saveAccountToken, l as listAccountsFromRegistry, m as removeAccountToken, p as removeAccountFromRegistry, r as addAccountToRegistry, t as isAccountType } from "./account-DpW8RaT6.js";
|
|
3
3
|
import { r as ensurePaths, t as PATHS } from "./paths-Bpsb62LK.js";
|
|
4
|
-
import { C as
|
|
5
|
-
import { a as forwardCodexResponses, n as setupCodexToken } from "./token-
|
|
4
|
+
import { A as shouldCompactUseSmallModel, C as isResponsesApiWebSearchEnabled, D as resolveMappedModel, E as mergeConfigWithDefaults, O as resolveModelAlias, S as isResponsesApiContextManagementEnabled, _ as getSmallModel, a as getConfig, b as isMessageStartInputTokensFallbackEnabled, c as getModelAliases, d as getModelResponsesApiCompactThreshold$1, f as getProviderConfig, h as getReasoningEffortForModel, i as getClaudeTokenMultiplier, l as getModelAliasesInfo, m as getRawProviderConfig, n as getAliasTargetSet, o as getExtraPromptForModel, r as getAnthropicApiKey, s as getLogLevel, t as PROVIDER_TYPE_ANTHROPIC, u as getModelRefreshIntervalMs, v as isAccountAffinityEnabled, w as isResponsesApiWebSocketEnabled, x as isMessagesApiEnabled, y as isForceAgentEnabled } from "./config-BaU_aWgi.js";
|
|
5
|
+
import { a as forwardCodexResponses, n as setupCodexToken } from "./token-671YFxgv.js";
|
|
6
6
|
import { i as getRequestOutboundStore, r as getRedactedHeaderKeys } from "./request-outbound-DZTxxtcx.js";
|
|
7
7
|
import { i as isMcpHttpEnabledFromEnv, n as DEFAULT_MCP_HTTP_PATH } from "./mcp-http-config-DMdUDz1D.js";
|
|
8
8
|
import { a as isDeferredToolName, c as parseMcpToolSearchSentinel, i as isBridgeToolSearchName, l as selectDeferredToolsByNames, n as BRIDGE_TOOL_SEARCH_NAME, o as listDeferredToolNames, r as formatToolSearchBridgeArguments, s as normalizeToolSearchBridgeArguments, u as shouldEnableResponsesToolSearch } from "./mcp-server-DEqHrXFq.js";
|
|
9
9
|
import { n as handleStreamableHttpMcpRequest, r as mcpHttpCorsOptions } from "./mcp-http-DI4Vz01p.js";
|
|
10
|
-
import { C as createAuthMiddleware, S as isDevModeEnabled, _ as normalizeMessagesUsage, b as copilotFetch, c as accountsManager, d as extractResponsesUsageFromStreamEvent, f as getClientIpInfo, g as normalizeEmbeddingsUsage, h as normalizeChatCompletionsUsage, l as applySharedSessionAffinityRetention, m as getStatsStore, p as getRequestHistoryStore, s as updateQuotaRefreshSchedulerFromConfig, t as closeResponsesBridge, u as extractResponsesUsageFromResult, v as normalizeResponsesUsage, x as flushPendingCapture, y as toLocalDateString } from "./responses-bridge-registry-
|
|
10
|
+
import { C as createAuthMiddleware, S as isDevModeEnabled, _ as normalizeMessagesUsage, b as copilotFetch, c as accountsManager, d as extractResponsesUsageFromStreamEvent, f as getClientIpInfo, g as normalizeEmbeddingsUsage, h as normalizeChatCompletionsUsage, l as applySharedSessionAffinityRetention, m as getStatsStore, p as getRequestHistoryStore, s as updateQuotaRefreshSchedulerFromConfig, t as closeResponsesBridge, u as extractResponsesUsageFromResult, v as normalizeResponsesUsage, x as flushPendingCapture, y as toLocalDateString } from "./responses-bridge-registry-DqCoY6Ex.js";
|
|
11
11
|
import consola from "consola";
|
|
12
12
|
import fs, { readFile } from "node:fs/promises";
|
|
13
13
|
import { createHash, randomUUID } from "node:crypto";
|
|
@@ -954,6 +954,44 @@ const stripCacheControl = (payload) => {
|
|
|
954
954
|
}
|
|
955
955
|
}
|
|
956
956
|
};
|
|
957
|
+
const normalizeCacheControl = (cacheControl) => {
|
|
958
|
+
if (!cacheControl || typeof cacheControl !== "object" || Array.isArray(cacheControl)) return;
|
|
959
|
+
const type = cacheControl.type;
|
|
960
|
+
return type === "ephemeral" ? { type } : void 0;
|
|
961
|
+
};
|
|
962
|
+
const applyTopLevelCacheControl = (payload) => {
|
|
963
|
+
const topLevel = normalizeCacheControl(payload.cache_control);
|
|
964
|
+
if (!topLevel) {
|
|
965
|
+
if (payload.cache_control !== void 0) delete payload.cache_control;
|
|
966
|
+
return;
|
|
967
|
+
}
|
|
968
|
+
delete payload.cache_control;
|
|
969
|
+
for (let m = payload.messages.length - 1; m >= 0; m--) {
|
|
970
|
+
const message = payload.messages[m];
|
|
971
|
+
if (typeof message.content === "string") {
|
|
972
|
+
message.content = [{
|
|
973
|
+
type: "text",
|
|
974
|
+
text: message.content,
|
|
975
|
+
cache_control: { ...topLevel }
|
|
976
|
+
}];
|
|
977
|
+
return;
|
|
978
|
+
}
|
|
979
|
+
if (!Array.isArray(message.content)) continue;
|
|
980
|
+
for (let b = message.content.length - 1; b >= 0; b--) {
|
|
981
|
+
const block = message.content[b];
|
|
982
|
+
if (block.type !== "text" && block.type !== "image" && block.type !== "tool_use" && block.type !== "tool_result") continue;
|
|
983
|
+
block.cache_control ??= { ...topLevel };
|
|
984
|
+
return;
|
|
985
|
+
}
|
|
986
|
+
}
|
|
987
|
+
};
|
|
988
|
+
const stripToolEagerInputStreaming = (payload) => {
|
|
989
|
+
if (!payload.tools || payload.tools.length === 0) return;
|
|
990
|
+
for (const tool of payload.tools) {
|
|
991
|
+
const extended = tool;
|
|
992
|
+
if ("eager_input_streaming" in extended) delete extended.eager_input_streaming;
|
|
993
|
+
}
|
|
994
|
+
};
|
|
957
995
|
const filterAssistantThinkingBlocks = (payload) => {
|
|
958
996
|
for (const msg of payload.messages) if (msg.role === "assistant" && Array.isArray(msg.content)) msg.content = msg.content.filter((block) => {
|
|
959
997
|
if (block.type !== "thinking") return true;
|
|
@@ -962,6 +1000,8 @@ const filterAssistantThinkingBlocks = (payload) => {
|
|
|
962
1000
|
};
|
|
963
1001
|
const prepareMessagesApiPayload = (payload, selectedModel) => {
|
|
964
1002
|
stripCacheControl(payload);
|
|
1003
|
+
applyTopLevelCacheControl(payload);
|
|
1004
|
+
stripToolEagerInputStreaming(payload);
|
|
965
1005
|
filterAssistantThinkingBlocks(payload);
|
|
966
1006
|
const hasThinking = Boolean(payload.thinking);
|
|
967
1007
|
const toolChoice = payload.tool_choice;
|
|
@@ -3746,6 +3786,41 @@ const createHandlerLogger = (name) => {
|
|
|
3746
3786
|
return instance;
|
|
3747
3787
|
};
|
|
3748
3788
|
//#endregion
|
|
3789
|
+
//#region src/lib/provider-model.ts
|
|
3790
|
+
const parseProviderModelAlias = (model) => {
|
|
3791
|
+
const separatorIndex = model.indexOf("/");
|
|
3792
|
+
if (separatorIndex <= 0 || separatorIndex === model.length - 1) return null;
|
|
3793
|
+
const provider = model.slice(0, separatorIndex).trim();
|
|
3794
|
+
const providerModel = model.slice(separatorIndex + 1).trim();
|
|
3795
|
+
if (!provider || !providerModel) return null;
|
|
3796
|
+
return {
|
|
3797
|
+
model: providerModel,
|
|
3798
|
+
provider
|
|
3799
|
+
};
|
|
3800
|
+
};
|
|
3801
|
+
const resolveExistingProviderModelAlias = (model, resolveProvider) => {
|
|
3802
|
+
const alias = parseProviderModelAlias(model);
|
|
3803
|
+
if (!alias) return null;
|
|
3804
|
+
return resolveProvider(alias.provider) ? alias : null;
|
|
3805
|
+
};
|
|
3806
|
+
const createFallbackModel = (modelId) => ({
|
|
3807
|
+
capabilities: {
|
|
3808
|
+
family: "provider",
|
|
3809
|
+
limits: {},
|
|
3810
|
+
object: "model_capabilities",
|
|
3811
|
+
supports: {},
|
|
3812
|
+
tokenizer: "o200k_base",
|
|
3813
|
+
type: "chat"
|
|
3814
|
+
},
|
|
3815
|
+
id: modelId,
|
|
3816
|
+
model_picker_enabled: false,
|
|
3817
|
+
name: modelId,
|
|
3818
|
+
object: "model",
|
|
3819
|
+
preview: false,
|
|
3820
|
+
vendor: "provider",
|
|
3821
|
+
version: "unknown"
|
|
3822
|
+
});
|
|
3823
|
+
//#endregion
|
|
3749
3824
|
//#region src/lib/rate-limit.ts
|
|
3750
3825
|
async function checkRateLimit(state) {
|
|
3751
3826
|
if (state.rateLimitSeconds === void 0) return;
|
|
@@ -3771,6 +3846,210 @@ async function checkRateLimit(state) {
|
|
|
3771
3846
|
consola.info("Rate limit wait completed, proceeding with request");
|
|
3772
3847
|
}
|
|
3773
3848
|
//#endregion
|
|
3849
|
+
//#region src/lib/provider-resolver.ts
|
|
3850
|
+
function isMissingCodexCredentialsError(error) {
|
|
3851
|
+
return error instanceof Error && error.message === "Codex credentials not found. Run `copilot-api auth login --provider codex` first.";
|
|
3852
|
+
}
|
|
3853
|
+
async function resolveProviderConfig$3(providerName) {
|
|
3854
|
+
const normalizedProviderName = providerName.trim();
|
|
3855
|
+
if (!normalizedProviderName) return null;
|
|
3856
|
+
if (normalizedProviderName === "codex") {
|
|
3857
|
+
if (getRawProviderConfig(normalizedProviderName)?.enabled === false) return null;
|
|
3858
|
+
try {
|
|
3859
|
+
await setupCodexToken();
|
|
3860
|
+
} catch (error) {
|
|
3861
|
+
if (isMissingCodexCredentialsError(error)) return null;
|
|
3862
|
+
throw error;
|
|
3863
|
+
}
|
|
3864
|
+
const providerConfig = getProviderConfig(normalizedProviderName);
|
|
3865
|
+
if (!providerConfig) return null;
|
|
3866
|
+
return {
|
|
3867
|
+
...providerConfig,
|
|
3868
|
+
apiKey: state.codexAccessToken ?? providerConfig.apiKey
|
|
3869
|
+
};
|
|
3870
|
+
}
|
|
3871
|
+
return getProviderConfig(normalizedProviderName);
|
|
3872
|
+
}
|
|
3873
|
+
//#endregion
|
|
3874
|
+
//#region src/lib/token-usage.ts
|
|
3875
|
+
function normalizeOpenAIUsage$1(usage) {
|
|
3876
|
+
const cacheCreationInputTokens = usage?.prompt_tokens_details?.cache_creation_input_tokens;
|
|
3877
|
+
const cacheReadInputTokens = usage?.prompt_tokens_details?.cached_tokens;
|
|
3878
|
+
return {
|
|
3879
|
+
inputTokens: usage?.prompt_tokens === void 0 ? void 0 : Math.max(0, usage.prompt_tokens - (cacheCreationInputTokens ?? 0) - (cacheReadInputTokens ?? 0)),
|
|
3880
|
+
outputTokens: usage?.completion_tokens,
|
|
3881
|
+
cacheCreationInputTokens,
|
|
3882
|
+
cacheReadInputTokens
|
|
3883
|
+
};
|
|
3884
|
+
}
|
|
3885
|
+
function createProviderTokenUsageRecorder(options) {
|
|
3886
|
+
const logger = createHandlerLogger(`provider-${options.providerName}`);
|
|
3887
|
+
return (usage) => {
|
|
3888
|
+
logger.debug(`${options.endpoint} usage`, {
|
|
3889
|
+
model: options.model,
|
|
3890
|
+
provider: options.providerName,
|
|
3891
|
+
...usage
|
|
3892
|
+
});
|
|
3893
|
+
};
|
|
3894
|
+
}
|
|
3895
|
+
//#endregion
|
|
3896
|
+
//#region src/services/providers/provider-proxy.ts
|
|
3897
|
+
const SHARED_FORWARDABLE_HEADERS = ["accept", "user-agent"];
|
|
3898
|
+
const ANTHROPIC_FORWARDABLE_HEADERS = ["anthropic-version", "anthropic-beta"];
|
|
3899
|
+
const STRIPPED_RESPONSE_HEADERS = [
|
|
3900
|
+
"connection",
|
|
3901
|
+
"content-encoding",
|
|
3902
|
+
"content-length",
|
|
3903
|
+
"keep-alive",
|
|
3904
|
+
"proxy-authenticate",
|
|
3905
|
+
"proxy-authorization",
|
|
3906
|
+
"te",
|
|
3907
|
+
"trailer",
|
|
3908
|
+
"transfer-encoding",
|
|
3909
|
+
"upgrade"
|
|
3910
|
+
];
|
|
3911
|
+
function buildProviderUpstreamHeaders(providerConfig, requestHeaders) {
|
|
3912
|
+
const authHeaders = {};
|
|
3913
|
+
if (providerConfig.authType === "x-api-key") authHeaders["x-api-key"] = providerConfig.apiKey;
|
|
3914
|
+
else authHeaders.authorization = `Bearer ${providerConfig.apiKey}`;
|
|
3915
|
+
const headers = {
|
|
3916
|
+
"content-type": "application/json",
|
|
3917
|
+
accept: "application/json",
|
|
3918
|
+
...authHeaders
|
|
3919
|
+
};
|
|
3920
|
+
for (const headerName of SHARED_FORWARDABLE_HEADERS) {
|
|
3921
|
+
const headerValue = requestHeaders.get(headerName);
|
|
3922
|
+
if (headerValue) headers[headerName] = headerValue;
|
|
3923
|
+
}
|
|
3924
|
+
if (providerConfig.type !== "anthropic") return headers;
|
|
3925
|
+
for (const headerName of ANTHROPIC_FORWARDABLE_HEADERS) {
|
|
3926
|
+
const headerValue = requestHeaders.get(headerName);
|
|
3927
|
+
if (headerValue) headers[headerName] = headerValue;
|
|
3928
|
+
}
|
|
3929
|
+
return headers;
|
|
3930
|
+
}
|
|
3931
|
+
function createProviderProxyResponse(upstreamResponse, body) {
|
|
3932
|
+
const headers = new Headers(upstreamResponse.headers);
|
|
3933
|
+
for (const headerName of STRIPPED_RESPONSE_HEADERS) headers.delete(headerName);
|
|
3934
|
+
return new Response(body ?? upstreamResponse.body, {
|
|
3935
|
+
headers,
|
|
3936
|
+
status: upstreamResponse.status,
|
|
3937
|
+
statusText: upstreamResponse.statusText
|
|
3938
|
+
});
|
|
3939
|
+
}
|
|
3940
|
+
async function forwardProviderMessages(providerConfig, payload, requestHeaders, fetchImpl = fetch) {
|
|
3941
|
+
return await fetchImpl(`${providerConfig.baseUrl}/v1/messages`, {
|
|
3942
|
+
method: "POST",
|
|
3943
|
+
headers: buildProviderUpstreamHeaders(providerConfig, requestHeaders),
|
|
3944
|
+
body: JSON.stringify(payload)
|
|
3945
|
+
});
|
|
3946
|
+
}
|
|
3947
|
+
async function forwardProviderChatCompletions(providerConfig, payload, requestHeaders, fetchImpl = fetch) {
|
|
3948
|
+
return await fetchImpl(`${providerConfig.baseUrl}/v1/chat/completions`, {
|
|
3949
|
+
method: "POST",
|
|
3950
|
+
headers: buildProviderUpstreamHeaders(providerConfig, requestHeaders),
|
|
3951
|
+
body: JSON.stringify(payload)
|
|
3952
|
+
});
|
|
3953
|
+
}
|
|
3954
|
+
async function forwardProviderResponses(providerConfig, payload, requestHeaders) {
|
|
3955
|
+
return await fetch(`${providerConfig.baseUrl}/v1/responses`, {
|
|
3956
|
+
method: "POST",
|
|
3957
|
+
headers: buildProviderUpstreamHeaders(providerConfig, requestHeaders),
|
|
3958
|
+
body: JSON.stringify(payload)
|
|
3959
|
+
});
|
|
3960
|
+
}
|
|
3961
|
+
async function forwardProviderModels(providerConfig, requestHeaders, fetchImpl = fetch) {
|
|
3962
|
+
return await fetchImpl(`${providerConfig.baseUrl}/v1/models`, {
|
|
3963
|
+
method: "GET",
|
|
3964
|
+
headers: buildProviderUpstreamHeaders(providerConfig, requestHeaders)
|
|
3965
|
+
});
|
|
3966
|
+
}
|
|
3967
|
+
//#endregion
|
|
3968
|
+
//#region src/routes/provider/chat-completions/handler.ts
|
|
3969
|
+
const logger$8 = createHandlerLogger("provider-chat-completions-handler");
|
|
3970
|
+
async function handleProviderChatCompletionsForProvider(c, options) {
|
|
3971
|
+
const { payload, provider } = options;
|
|
3972
|
+
const providerConfig = await (c.get("providerConfigResolver") ?? resolveProviderConfig$3)(provider);
|
|
3973
|
+
if (providerConfig?.type !== "openai-compatible") return c.json({ error: {
|
|
3974
|
+
message: `Provider '${provider}' does not support the /v1/chat/completions endpoint`,
|
|
3975
|
+
type: "invalid_request_error"
|
|
3976
|
+
} }, 400);
|
|
3977
|
+
const modelConfig = providerConfig.models?.[payload.model];
|
|
3978
|
+
applyProviderModelDefaults(payload, modelConfig);
|
|
3979
|
+
applyMissingExtraBody$1(payload, { extraBody: modelConfig?.extraBody });
|
|
3980
|
+
applyProviderStreamOptions(payload);
|
|
3981
|
+
debugJson(logger$8, "provider.chat_completions.request", {
|
|
3982
|
+
payload,
|
|
3983
|
+
provider
|
|
3984
|
+
});
|
|
3985
|
+
const upstreamResponse = await forwardProviderChatCompletions(providerConfig, payload, c.req.raw.headers);
|
|
3986
|
+
if (!upstreamResponse.ok) {
|
|
3987
|
+
logger$8.error("Failed to create provider chat completions", {
|
|
3988
|
+
provider,
|
|
3989
|
+
statusCode: upstreamResponse.status
|
|
3990
|
+
});
|
|
3991
|
+
throw new HTTPError(`Failed to create ${provider} chat completions`, upstreamResponse);
|
|
3992
|
+
}
|
|
3993
|
+
const recordUsage = createProviderChatCompletionsUsageRecorder(payload, provider);
|
|
3994
|
+
const contentType = upstreamResponse.headers.get("content-type") ?? "";
|
|
3995
|
+
if (Boolean(payload.stream) && contentType.includes("text/event-stream")) return streamProviderChatCompletions(c, upstreamResponse, {
|
|
3996
|
+
provider,
|
|
3997
|
+
recordUsage
|
|
3998
|
+
});
|
|
3999
|
+
const responseBody = await upstreamResponse.clone().json();
|
|
4000
|
+
recordUsage(normalizeOpenAIUsage$1(responseBody.usage));
|
|
4001
|
+
debugJson(logger$8, "provider.chat_completions.response", responseBody);
|
|
4002
|
+
return createProviderProxyResponse(upstreamResponse);
|
|
4003
|
+
}
|
|
4004
|
+
const applyProviderModelDefaults = (payload, modelConfig) => {
|
|
4005
|
+
payload.temperature ??= modelConfig?.temperature;
|
|
4006
|
+
payload.top_p ??= modelConfig?.topP;
|
|
4007
|
+
payload.top_k ??= modelConfig?.topK;
|
|
4008
|
+
};
|
|
4009
|
+
const applyMissingExtraBody$1 = (payload, options) => {
|
|
4010
|
+
for (const [key, value] of Object.entries(options.extraBody ?? {})) if (!Object.hasOwn(payload, key)) payload[key] = value;
|
|
4011
|
+
};
|
|
4012
|
+
const applyProviderStreamOptions = (payload) => {
|
|
4013
|
+
if (!payload.stream) return;
|
|
4014
|
+
payload.stream_options = {
|
|
4015
|
+
...payload.stream_options ?? {},
|
|
4016
|
+
include_usage: true
|
|
4017
|
+
};
|
|
4018
|
+
};
|
|
4019
|
+
const createProviderChatCompletionsUsageRecorder = (payload, provider) => createProviderTokenUsageRecorder({
|
|
4020
|
+
endpoint: "chat_completions",
|
|
4021
|
+
model: payload.model,
|
|
4022
|
+
providerName: provider
|
|
4023
|
+
});
|
|
4024
|
+
const streamProviderChatCompletions = (c, upstreamResponse, options) => {
|
|
4025
|
+
logger$8.debug("provider.chat_completions.streaming", { provider: options.provider });
|
|
4026
|
+
return streamSSE(c, async (stream) => {
|
|
4027
|
+
let usage = {};
|
|
4028
|
+
try {
|
|
4029
|
+
for await (const chunk of events(upstreamResponse)) {
|
|
4030
|
+
debugJson(logger$8, "provider.chat_completions.stream_chunk", chunk);
|
|
4031
|
+
if (chunk.data && chunk.data !== "[DONE]") {
|
|
4032
|
+
const parsedChunk = parseChatCompletionChunkData(chunk.data);
|
|
4033
|
+
if (parsedChunk?.usage) usage = normalizeOpenAIUsage$1(parsedChunk.usage);
|
|
4034
|
+
}
|
|
4035
|
+
await stream.writeSSE({
|
|
4036
|
+
event: chunk.event,
|
|
4037
|
+
data: chunk.data ?? ""
|
|
4038
|
+
});
|
|
4039
|
+
}
|
|
4040
|
+
} finally {
|
|
4041
|
+
options.recordUsage(usage);
|
|
4042
|
+
}
|
|
4043
|
+
});
|
|
4044
|
+
};
|
|
4045
|
+
const parseChatCompletionChunkData = (data) => {
|
|
4046
|
+
try {
|
|
4047
|
+
return JSON.parse(data);
|
|
4048
|
+
} catch {
|
|
4049
|
+
return null;
|
|
4050
|
+
}
|
|
4051
|
+
};
|
|
4052
|
+
//#endregion
|
|
3774
4053
|
//#region src/routes/chat-completions/support.ts
|
|
3775
4054
|
const CHAT_COMPLETIONS_ENDPOINT$1 = "/chat/completions";
|
|
3776
4055
|
const GPT_5_4_MODEL_ID = "gpt-5.4";
|
|
@@ -3915,10 +4194,21 @@ function maybeRejectChatCompletionsClientModel(c, store, params) {
|
|
|
3915
4194
|
return null;
|
|
3916
4195
|
}
|
|
3917
4196
|
async function handleCompletion$1(c) {
|
|
4197
|
+
const payload = await c.req.json();
|
|
4198
|
+
const mappedModelResolver = c.get("resolveMappedModel") ?? resolveMappedModel;
|
|
4199
|
+
const providerConfigResolver = c.get("providerConfigResolver") ?? getProviderConfig;
|
|
4200
|
+
payload.model = mappedModelResolver(payload.model);
|
|
4201
|
+
const providerModelAlias = resolveExistingProviderModelAlias(payload.model, providerConfigResolver);
|
|
4202
|
+
if (providerModelAlias) {
|
|
4203
|
+
payload.model = providerModelAlias.model;
|
|
4204
|
+
return await handleProviderChatCompletionsForProvider(c, {
|
|
4205
|
+
payload,
|
|
4206
|
+
provider: providerModelAlias.provider
|
|
4207
|
+
});
|
|
4208
|
+
}
|
|
3918
4209
|
await checkRateLimit(state);
|
|
3919
4210
|
const store = getRequestHistoryStore();
|
|
3920
4211
|
const request = buildRequestContext$1(c);
|
|
3921
|
-
const payload = await c.req.json();
|
|
3922
4212
|
const clientModel = payload.model;
|
|
3923
4213
|
const streamRequested = Boolean(payload.stream);
|
|
3924
4214
|
const normalizedPromptCacheKey = applyChatRequestMetadata(request, payload, getChatInitiator(payload.messages));
|
|
@@ -4515,44 +4805,9 @@ async function runEmbeddingsWithAccount({ c, store, ctx, payload, clientModel, s
|
|
|
4515
4805
|
}
|
|
4516
4806
|
}
|
|
4517
4807
|
//#endregion
|
|
4518
|
-
//#region src/lib/provider-model.ts
|
|
4519
|
-
const parseProviderModelAlias = (model) => {
|
|
4520
|
-
const separatorIndex = model.indexOf("/");
|
|
4521
|
-
if (separatorIndex <= 0 || separatorIndex === model.length - 1) return null;
|
|
4522
|
-
const provider = model.slice(0, separatorIndex).trim();
|
|
4523
|
-
const providerModel = model.slice(separatorIndex + 1).trim();
|
|
4524
|
-
if (!provider || !providerModel) return null;
|
|
4525
|
-
return {
|
|
4526
|
-
model: providerModel,
|
|
4527
|
-
provider
|
|
4528
|
-
};
|
|
4529
|
-
};
|
|
4530
|
-
const resolveExistingProviderModelAlias = (model, resolveProvider) => {
|
|
4531
|
-
const alias = parseProviderModelAlias(model);
|
|
4532
|
-
if (!alias) return null;
|
|
4533
|
-
return resolveProvider(alias.provider) ? alias : null;
|
|
4534
|
-
};
|
|
4535
|
-
const createFallbackModel = (modelId) => ({
|
|
4536
|
-
capabilities: {
|
|
4537
|
-
family: "provider",
|
|
4538
|
-
limits: {},
|
|
4539
|
-
object: "model_capabilities",
|
|
4540
|
-
supports: {},
|
|
4541
|
-
tokenizer: "o200k_base",
|
|
4542
|
-
type: "chat"
|
|
4543
|
-
},
|
|
4544
|
-
id: modelId,
|
|
4545
|
-
model_picker_enabled: false,
|
|
4546
|
-
name: modelId,
|
|
4547
|
-
object: "model",
|
|
4548
|
-
preview: false,
|
|
4549
|
-
vendor: "provider",
|
|
4550
|
-
version: "unknown"
|
|
4551
|
-
});
|
|
4552
|
-
//#endregion
|
|
4553
4808
|
//#region src/routes/provider/messages/count-tokens-handler.ts
|
|
4554
4809
|
const logger$6 = createHandlerLogger("provider-count-tokens-handler");
|
|
4555
|
-
const resolveProviderConfig$
|
|
4810
|
+
const resolveProviderConfig$2 = (c, provider) => {
|
|
4556
4811
|
return (c.get("providerConfigResolver") ?? getProviderConfig)(provider);
|
|
4557
4812
|
};
|
|
4558
4813
|
async function handleProviderCountTokens(c) {
|
|
@@ -4565,7 +4820,7 @@ async function handleProviderCountTokens(c) {
|
|
|
4565
4820
|
async function handleProviderCountTokensForProvider(c, options) {
|
|
4566
4821
|
const { payload: anthropicPayload, provider } = options;
|
|
4567
4822
|
normalizeSystemMessages(anthropicPayload);
|
|
4568
|
-
const providerConfig = resolveProviderConfig$
|
|
4823
|
+
const providerConfig = resolveProviderConfig$2(c, provider);
|
|
4569
4824
|
if (!providerConfig) return c.json({ error: {
|
|
4570
4825
|
message: `Provider '${provider}' not found or disabled`,
|
|
4571
4826
|
type: "invalid_request_error"
|
|
@@ -5045,7 +5300,11 @@ const consumeResponsesWebSocketStream = async (stream) => {
|
|
|
5045
5300
|
for await (const chunk of stream) {
|
|
5046
5301
|
if (!chunk.data || chunk.data === "[DONE]") continue;
|
|
5047
5302
|
const event = JSON.parse(chunk.data);
|
|
5048
|
-
if (event.type === "error")
|
|
5303
|
+
if (event.type === "error") {
|
|
5304
|
+
const status = typeof event.code === "string" ? parseInt(event.code, 10) : NaN;
|
|
5305
|
+
const httpStatus = Number.isFinite(status) && status >= 100 && status < 600 ? status : 500;
|
|
5306
|
+
throw new HTTPError(event.message, new Response(JSON.stringify({ error: { message: event.message } }), { status: httpStatus }));
|
|
5307
|
+
}
|
|
5049
5308
|
if (event.type === "response.completed" || event.type === "response.failed" || event.type === "response.incomplete") return event.response;
|
|
5050
5309
|
}
|
|
5051
5310
|
throw new Error("Responses websocket ended without a terminal response");
|
|
@@ -6025,82 +6284,10 @@ function closeThinkingBlockIfOpen(state, events) {
|
|
|
6025
6284
|
}
|
|
6026
6285
|
}
|
|
6027
6286
|
//#endregion
|
|
6028
|
-
//#region src/services/providers/provider-proxy.ts
|
|
6029
|
-
const SHARED_FORWARDABLE_HEADERS = ["accept", "user-agent"];
|
|
6030
|
-
const ANTHROPIC_FORWARDABLE_HEADERS = ["anthropic-version", "anthropic-beta"];
|
|
6031
|
-
const STRIPPED_RESPONSE_HEADERS = [
|
|
6032
|
-
"connection",
|
|
6033
|
-
"content-encoding",
|
|
6034
|
-
"content-length",
|
|
6035
|
-
"keep-alive",
|
|
6036
|
-
"proxy-authenticate",
|
|
6037
|
-
"proxy-authorization",
|
|
6038
|
-
"te",
|
|
6039
|
-
"trailer",
|
|
6040
|
-
"transfer-encoding",
|
|
6041
|
-
"upgrade"
|
|
6042
|
-
];
|
|
6043
|
-
function buildProviderUpstreamHeaders(providerConfig, requestHeaders) {
|
|
6044
|
-
const authHeaders = {};
|
|
6045
|
-
if (providerConfig.authType === "x-api-key") authHeaders["x-api-key"] = providerConfig.apiKey;
|
|
6046
|
-
else authHeaders.authorization = `Bearer ${providerConfig.apiKey}`;
|
|
6047
|
-
const headers = {
|
|
6048
|
-
"content-type": "application/json",
|
|
6049
|
-
accept: "application/json",
|
|
6050
|
-
...authHeaders
|
|
6051
|
-
};
|
|
6052
|
-
for (const headerName of SHARED_FORWARDABLE_HEADERS) {
|
|
6053
|
-
const headerValue = requestHeaders.get(headerName);
|
|
6054
|
-
if (headerValue) headers[headerName] = headerValue;
|
|
6055
|
-
}
|
|
6056
|
-
if (providerConfig.type !== "anthropic") return headers;
|
|
6057
|
-
for (const headerName of ANTHROPIC_FORWARDABLE_HEADERS) {
|
|
6058
|
-
const headerValue = requestHeaders.get(headerName);
|
|
6059
|
-
if (headerValue) headers[headerName] = headerValue;
|
|
6060
|
-
}
|
|
6061
|
-
return headers;
|
|
6062
|
-
}
|
|
6063
|
-
function createProviderProxyResponse(upstreamResponse, body) {
|
|
6064
|
-
const headers = new Headers(upstreamResponse.headers);
|
|
6065
|
-
for (const headerName of STRIPPED_RESPONSE_HEADERS) headers.delete(headerName);
|
|
6066
|
-
return new Response(body ?? upstreamResponse.body, {
|
|
6067
|
-
headers,
|
|
6068
|
-
status: upstreamResponse.status,
|
|
6069
|
-
statusText: upstreamResponse.statusText
|
|
6070
|
-
});
|
|
6071
|
-
}
|
|
6072
|
-
async function forwardProviderMessages(providerConfig, payload, requestHeaders, fetchImpl = fetch) {
|
|
6073
|
-
return await fetchImpl(`${providerConfig.baseUrl}/v1/messages`, {
|
|
6074
|
-
method: "POST",
|
|
6075
|
-
headers: buildProviderUpstreamHeaders(providerConfig, requestHeaders),
|
|
6076
|
-
body: JSON.stringify(payload)
|
|
6077
|
-
});
|
|
6078
|
-
}
|
|
6079
|
-
async function forwardProviderChatCompletions(providerConfig, payload, requestHeaders, fetchImpl = fetch) {
|
|
6080
|
-
return await fetchImpl(`${providerConfig.baseUrl}/v1/chat/completions`, {
|
|
6081
|
-
method: "POST",
|
|
6082
|
-
headers: buildProviderUpstreamHeaders(providerConfig, requestHeaders),
|
|
6083
|
-
body: JSON.stringify(payload)
|
|
6084
|
-
});
|
|
6085
|
-
}
|
|
6086
|
-
async function forwardProviderResponses(providerConfig, payload, requestHeaders) {
|
|
6087
|
-
return await fetch(`${providerConfig.baseUrl}/v1/responses`, {
|
|
6088
|
-
method: "POST",
|
|
6089
|
-
headers: buildProviderUpstreamHeaders(providerConfig, requestHeaders),
|
|
6090
|
-
body: JSON.stringify(payload)
|
|
6091
|
-
});
|
|
6092
|
-
}
|
|
6093
|
-
async function forwardProviderModels(providerConfig, requestHeaders, fetchImpl = fetch) {
|
|
6094
|
-
return await fetchImpl(`${providerConfig.baseUrl}/v1/models`, {
|
|
6095
|
-
method: "GET",
|
|
6096
|
-
headers: buildProviderUpstreamHeaders(providerConfig, requestHeaders)
|
|
6097
|
-
});
|
|
6098
|
-
}
|
|
6099
|
-
//#endregion
|
|
6100
6287
|
//#region src/routes/provider/messages/handler.ts
|
|
6101
6288
|
const logger$5 = createHandlerLogger("provider-messages-handler");
|
|
6102
6289
|
const getProviderFetch$1 = (c) => c.get("providerFetch") ?? fetch;
|
|
6103
|
-
const resolveProviderConfig$
|
|
6290
|
+
const resolveProviderConfig$1 = (c, provider) => {
|
|
6104
6291
|
return (c.get("providerConfigResolver") ?? getProviderConfig)(provider);
|
|
6105
6292
|
};
|
|
6106
6293
|
const OPENAI_COMPATIBLE_CONTEXT_CACHE_MARKER_LIMIT = 4;
|
|
@@ -6136,7 +6323,7 @@ async function handleProviderMessages(c) {
|
|
|
6136
6323
|
}
|
|
6137
6324
|
async function handleProviderMessagesForProvider(c, options) {
|
|
6138
6325
|
const { instrumentation, payload, provider } = options;
|
|
6139
|
-
const providerConfig = resolveProviderConfig$
|
|
6326
|
+
const providerConfig = resolveProviderConfig$1(c, provider);
|
|
6140
6327
|
if (!providerConfig) {
|
|
6141
6328
|
const message = `Provider '${provider}' not found or disabled`;
|
|
6142
6329
|
instrumentation?.onError?.({
|
|
@@ -7008,6 +7195,7 @@ const stringifyToolSearchArguments = (argumentsValue) => {
|
|
|
7008
7195
|
};
|
|
7009
7196
|
const DEFAULT_RESPONSES_COMPACT_THRESHOLD_RATIO = .9;
|
|
7010
7197
|
const responsesUtilsDependencies = {
|
|
7198
|
+
getModelResponsesApiCompactThreshold: getModelResponsesApiCompactThreshold$1,
|
|
7011
7199
|
isResponsesApiContextManagementEnabled,
|
|
7012
7200
|
isResponsesApiWebSocketEnabled
|
|
7013
7201
|
};
|
|
@@ -7116,6 +7304,11 @@ const resolveResponsesCompactThreshold = (maxPromptTokens, compactThresholdRatio
|
|
|
7116
7304
|
if (typeof maxPromptTokens === "number" && maxPromptTokens > 0) return Math.floor(maxPromptTokens * compactThresholdRatio);
|
|
7117
7305
|
return 2e5 * compactThresholdRatio;
|
|
7118
7306
|
};
|
|
7307
|
+
const getModelResponsesApiCompactThreshold = (model) => {
|
|
7308
|
+
const threshold = responsesUtilsDependencies.getModelResponsesApiCompactThreshold(model);
|
|
7309
|
+
if (typeof threshold !== "number" || !Number.isFinite(threshold) || threshold <= 0) return;
|
|
7310
|
+
return threshold;
|
|
7311
|
+
};
|
|
7119
7312
|
const createCompactionContextManagement = (compactThreshold) => [{
|
|
7120
7313
|
type: "compaction",
|
|
7121
7314
|
compact_threshold: compactThreshold
|
|
@@ -7123,7 +7316,7 @@ const createCompactionContextManagement = (compactThreshold) => [{
|
|
|
7123
7316
|
const applyResponsesApiContextManagement = (payload, maxPromptTokens, compactThresholdRatio = DEFAULT_RESPONSES_COMPACT_THRESHOLD_RATIO) => {
|
|
7124
7317
|
if (payload.context_management !== void 0) return;
|
|
7125
7318
|
if (!responsesUtilsDependencies.isResponsesApiContextManagementEnabled()) return;
|
|
7126
|
-
payload.context_management = createCompactionContextManagement(resolveResponsesCompactThreshold(maxPromptTokens, compactThresholdRatio));
|
|
7319
|
+
payload.context_management = createCompactionContextManagement(getModelResponsesApiCompactThreshold(payload.model) ?? resolveResponsesCompactThreshold(maxPromptTokens, compactThresholdRatio));
|
|
7127
7320
|
};
|
|
7128
7321
|
const compactInputByLatestCompaction = (payload) => {
|
|
7129
7322
|
if (!Array.isArray(payload.input) || payload.input.length === 0) return;
|
|
@@ -8492,14 +8685,14 @@ function getModels() {
|
|
|
8492
8685
|
//#region src/routes/provider/models/route.ts
|
|
8493
8686
|
const logger$3 = createHandlerLogger("provider-models-handler");
|
|
8494
8687
|
const getProviderFetch = (c) => c.get("providerFetch") ?? fetch;
|
|
8495
|
-
const resolveProviderConfig
|
|
8688
|
+
const resolveProviderConfig = (c, provider) => {
|
|
8496
8689
|
return (c.get("providerConfigResolver") ?? getProviderConfig)(provider);
|
|
8497
8690
|
};
|
|
8498
8691
|
const providerModelRoutes = new Hono();
|
|
8499
8692
|
providerModelRoutes.get("/", async (c) => {
|
|
8500
8693
|
const provider = c.req.param("provider") ?? "";
|
|
8501
8694
|
try {
|
|
8502
|
-
const providerConfig = resolveProviderConfig
|
|
8695
|
+
const providerConfig = resolveProviderConfig(c, provider);
|
|
8503
8696
|
if (!providerConfig) return c.json({ error: {
|
|
8504
8697
|
message: `Provider '${provider}' not found or disabled`,
|
|
8505
8698
|
type: "invalid_request_error"
|
|
@@ -8560,31 +8753,6 @@ const isCodexRateLimitWindow = (value) => {
|
|
|
8560
8753
|
return typeof record.reset_after_seconds === "number" && typeof record.reset_at === "number" && typeof record.used_percent === "number" && typeof record.window_minutes === "number";
|
|
8561
8754
|
};
|
|
8562
8755
|
//#endregion
|
|
8563
|
-
//#region src/lib/provider-resolver.ts
|
|
8564
|
-
function isMissingCodexCredentialsError(error) {
|
|
8565
|
-
return error instanceof Error && error.message === "Codex credentials not found. Run `copilot-api auth login --provider codex` first.";
|
|
8566
|
-
}
|
|
8567
|
-
async function resolveProviderConfig(providerName) {
|
|
8568
|
-
const normalizedProviderName = providerName.trim();
|
|
8569
|
-
if (!normalizedProviderName) return null;
|
|
8570
|
-
if (normalizedProviderName === "codex") {
|
|
8571
|
-
if (getRawProviderConfig(normalizedProviderName)?.enabled === false) return null;
|
|
8572
|
-
try {
|
|
8573
|
-
await setupCodexToken();
|
|
8574
|
-
} catch (error) {
|
|
8575
|
-
if (isMissingCodexCredentialsError(error)) return null;
|
|
8576
|
-
throw error;
|
|
8577
|
-
}
|
|
8578
|
-
const providerConfig = getProviderConfig(normalizedProviderName);
|
|
8579
|
-
if (!providerConfig) return null;
|
|
8580
|
-
return {
|
|
8581
|
-
...providerConfig,
|
|
8582
|
-
apiKey: state.codexAccessToken ?? providerConfig.apiKey
|
|
8583
|
-
};
|
|
8584
|
-
}
|
|
8585
|
-
return getProviderConfig(normalizedProviderName);
|
|
8586
|
-
}
|
|
8587
|
-
//#endregion
|
|
8588
8756
|
//#region src/routes/provider/responses/handler.ts
|
|
8589
8757
|
const logger$2 = createHandlerLogger("provider-responses-handler");
|
|
8590
8758
|
async function handleProviderResponsesForProvider(c, options) {
|
|
@@ -8593,7 +8761,7 @@ async function handleProviderResponsesForProvider(c, options) {
|
|
|
8593
8761
|
payload,
|
|
8594
8762
|
provider
|
|
8595
8763
|
});
|
|
8596
|
-
const providerConfig = await resolveProviderConfig(provider);
|
|
8764
|
+
const providerConfig = await resolveProviderConfig$3(provider);
|
|
8597
8765
|
if (providerConfig?.type !== "openai-responses") return c.json({ error: {
|
|
8598
8766
|
message: `Provider '${provider}' does not support the /v1/responses endpoint`,
|
|
8599
8767
|
type: "invalid_request_error"
|
|
@@ -8731,7 +8899,7 @@ const handleResponses = async (c) => {
|
|
|
8731
8899
|
debugJson(logger$1, "Responses request payload:", payload);
|
|
8732
8900
|
const requestedModel = payload.model;
|
|
8733
8901
|
payload.model = resolveMappedModel(payload.model);
|
|
8734
|
-
if (payload.model !== requestedModel)
|
|
8902
|
+
if (payload.model !== requestedModel) consola.debug(`Resolved model mapping: ${requestedModel} -> ${payload.model}`);
|
|
8735
8903
|
const providerModelAlias = parseProviderModelAlias(payload.model);
|
|
8736
8904
|
if (providerModelAlias) {
|
|
8737
8905
|
payload.model = providerModelAlias.model;
|
|
@@ -9360,4 +9528,4 @@ createServer();
|
|
|
9360
9528
|
//#endregion
|
|
9361
9529
|
export { createServer };
|
|
9362
9530
|
|
|
9363
|
-
//# sourceMappingURL=server-
|
|
9531
|
+
//# sourceMappingURL=server-C7pCkArb.js.map
|