@jeffreycao/copilot-api 1.10.1 → 1.10.3
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 +28 -5
- package/README.zh-CN.md +28 -5
- package/dist/{auth-D7YCTWpx.js → auth-BHa2OHXf.js} +3 -3
- package/dist/{auth-D7YCTWpx.js.map → auth-BHa2OHXf.js.map} +1 -1
- package/dist/{check-usage-Dgg0nNEw.js → check-usage-BdXGp1Wr.js} +3 -3
- package/dist/{check-usage-Dgg0nNEw.js.map → check-usage-BdXGp1Wr.js.map} +1 -1
- package/dist/main.js +3 -3
- package/dist/{proxy-De0Po8kG.js → proxy-DQLzdeq3.js} +106 -6
- package/dist/proxy-DQLzdeq3.js.map +1 -0
- package/dist/{server-DpVPS3zt.js → server-UsHsMP_2.js} +87 -20
- package/dist/server-UsHsMP_2.js.map +1 -0
- package/dist/{start-DDII-0ML.js → start-C7_M_42Q.js} +5 -5
- package/dist/{start-DDII-0ML.js.map → start-C7_M_42Q.js.map} +1 -1
- package/dist/{token-BQlDdqtI.js → token-Dj8XsAxn.js} +2 -2
- package/dist/{token-BQlDdqtI.js.map → token-Dj8XsAxn.js.map} +1 -1
- package/dist/{utils-C5ej0z8n.js → utils-jHLgqAq2.js} +3 -3
- package/dist/{utils-C5ej0z8n.js.map → utils-jHLgqAq2.js.map} +1 -1
- package/package.json +1 -1
- package/dist/proxy-De0Po8kG.js.map +0 -1
- package/dist/server-DpVPS3zt.js.map +0 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { t as PATHS } from "./paths-DC-mqCY3.js";
|
|
2
|
-
import { D as generateTraceId, E as prepareMessageProxyHeaders, I as state, M as compactMessageSections, O as requestContext, P as compactSystemPromptStarts, T as prepareInteractionHeaders, _ as copilotWebSocketHeaders, c as getUUID, d as sleep, f as getCopilotUsage, g as copilotHeaders, h as copilotBaseUrl, j as compactAutoContinuePromptStarts, k as resolveTraceId$1, l as isNullish, m as forwardError, n as cacheModels, o as generateRequestIdFromPayload, p as HTTPError, s as getRootSessionId, u as parseUserIdMetadata, w as prepareForCompact } from "./utils-
|
|
3
|
-
import { a as getConfig, c as
|
|
2
|
+
import { D as generateTraceId, E as prepareMessageProxyHeaders, I as state, M as compactMessageSections, O as requestContext, P as compactSystemPromptStarts, T as prepareInteractionHeaders, _ as copilotWebSocketHeaders, c as getUUID, d as sleep, f as getCopilotUsage, g as copilotHeaders, h as copilotBaseUrl, j as compactAutoContinuePromptStarts, k as resolveTraceId$1, l as isNullish, m as forwardError, n as cacheModels, o as generateRequestIdFromPayload, p as HTTPError, s as getRootSessionId, u as parseUserIdMetadata, w as prepareForCompact } from "./utils-jHLgqAq2.js";
|
|
3
|
+
import { _ as setModelMappings, a as getConfig, c as getProviderConfig, d as isMessagesApiEnabled, f as isResponsesApiContextManagementModel, g as resolveMappedModel, i as getClaudeTokenMultiplier, l as getReasoningEffortForModel, m as isResponsesApiWebSocketEnabled, o as getExtraPromptForModel, p as isResponsesApiWebSearchEnabled, r as getAnthropicApiKey, s as getModelMappings, t as getProxyEnvDispatcher, u as getSmallModel } from "./proxy-DQLzdeq3.js";
|
|
4
4
|
import consola from "consola";
|
|
5
5
|
import fs from "node:fs/promises";
|
|
6
6
|
import path from "node:path";
|
|
@@ -12,6 +12,7 @@ import fs$1, { readFileSync } from "node:fs";
|
|
|
12
12
|
import { streamSSE } from "hono/streaming";
|
|
13
13
|
import util from "node:util";
|
|
14
14
|
import { events } from "fetch-event-stream";
|
|
15
|
+
import { z } from "zod";
|
|
15
16
|
import { WebSocket } from "undici";
|
|
16
17
|
//#region src/lib/request-auth.ts
|
|
17
18
|
function normalizeApiKeys(apiKeys) {
|
|
@@ -26,6 +27,14 @@ function normalizeApiKeys(apiKeys) {
|
|
|
26
27
|
function getConfiguredApiKeys() {
|
|
27
28
|
return normalizeApiKeys(getConfig().auth?.apiKeys);
|
|
28
29
|
}
|
|
30
|
+
function normalizeApiKey(apiKey) {
|
|
31
|
+
if (typeof apiKey !== "string") return null;
|
|
32
|
+
return apiKey.trim() || null;
|
|
33
|
+
}
|
|
34
|
+
function getConfiguredAdminApiKeys() {
|
|
35
|
+
const adminApiKey = normalizeApiKey(getConfig().auth?.adminApiKey);
|
|
36
|
+
return adminApiKey ? [adminApiKey] : [];
|
|
37
|
+
}
|
|
29
38
|
function extractRequestApiKey(c) {
|
|
30
39
|
const xApiKey = c.req.header("x-api-key")?.trim();
|
|
31
40
|
if (xApiKey) return xApiKey;
|
|
@@ -46,11 +55,14 @@ function createAuthMiddleware(options = {}) {
|
|
|
46
55
|
const getApiKeys = options.getApiKeys ?? getConfiguredApiKeys;
|
|
47
56
|
const allowUnauthenticatedPaths = options.allowUnauthenticatedPaths ?? ["/"];
|
|
48
57
|
const allowOptionsBypass = options.allowOptionsBypass ?? true;
|
|
58
|
+
const allowWhenNoApiKeys = options.allowWhenNoApiKeys ?? true;
|
|
59
|
+
const shouldSkipPath = options.shouldSkipPath ?? (() => false);
|
|
49
60
|
return async (c, next) => {
|
|
50
61
|
if (allowOptionsBypass && c.req.method === "OPTIONS") return next();
|
|
62
|
+
if (shouldSkipPath(c.req.path)) return next();
|
|
51
63
|
if (allowUnauthenticatedPaths.includes(c.req.path)) return next();
|
|
52
64
|
const apiKeys = getApiKeys();
|
|
53
|
-
if (apiKeys.length === 0) return next();
|
|
65
|
+
if (apiKeys.length === 0) return allowWhenNoApiKeys ? next() : createUnauthorizedResponse(c);
|
|
54
66
|
const requestApiKey = extractRequestApiKey(c);
|
|
55
67
|
if (!requestApiKey || !apiKeys.includes(requestApiKey)) return createUnauthorizedResponse(c);
|
|
56
68
|
return next();
|
|
@@ -1085,6 +1097,32 @@ completionRoutes.post("/", async (c) => {
|
|
|
1085
1097
|
}
|
|
1086
1098
|
});
|
|
1087
1099
|
//#endregion
|
|
1100
|
+
//#region src/routes/admin/config/route.ts
|
|
1101
|
+
const configRoutes = new Hono();
|
|
1102
|
+
const modelMappingsRequestSchema = z.object({ modelMappings: z.record(z.string(), z.string()) });
|
|
1103
|
+
configRoutes.get("/model-mappings", (c) => {
|
|
1104
|
+
return c.json({
|
|
1105
|
+
configPath: PATHS.CONFIG_PATH,
|
|
1106
|
+
modelMappings: getModelMappings()
|
|
1107
|
+
});
|
|
1108
|
+
});
|
|
1109
|
+
configRoutes.post("/model-mappings", async (c) => {
|
|
1110
|
+
try {
|
|
1111
|
+
const parseResult = modelMappingsRequestSchema.safeParse(await c.req.json());
|
|
1112
|
+
if (!parseResult.success) return c.json({ error: {
|
|
1113
|
+
message: parseResult.error.issues[0]?.message ?? "Invalid request body.",
|
|
1114
|
+
type: "invalid_request_error"
|
|
1115
|
+
} }, 400);
|
|
1116
|
+
const updatedModelMappings = setModelMappings(parseResult.data.modelMappings);
|
|
1117
|
+
return c.json({
|
|
1118
|
+
configPath: PATHS.CONFIG_PATH,
|
|
1119
|
+
modelMappings: updatedModelMappings
|
|
1120
|
+
});
|
|
1121
|
+
} catch (error) {
|
|
1122
|
+
return await forwardError(c, error);
|
|
1123
|
+
}
|
|
1124
|
+
});
|
|
1125
|
+
//#endregion
|
|
1088
1126
|
//#region src/services/copilot/create-embeddings.ts
|
|
1089
1127
|
const createEmbeddings = async (payload) => {
|
|
1090
1128
|
if (!state.copilotToken) throw new Error("Copilot token not found");
|
|
@@ -1819,6 +1857,7 @@ async function countTokensViaAnthropic(c, payload) {
|
|
|
1819
1857
|
*/
|
|
1820
1858
|
async function handleCountTokens(c) {
|
|
1821
1859
|
const anthropicPayload = await c.req.json();
|
|
1860
|
+
anthropicPayload.model = resolveMappedModel(anthropicPayload.model);
|
|
1822
1861
|
const providerModelAlias = parseProviderModelAlias(anthropicPayload.model);
|
|
1823
1862
|
if (providerModelAlias) {
|
|
1824
1863
|
anthropicPayload.model = providerModelAlias.model;
|
|
@@ -2777,6 +2816,12 @@ const removeResponsesWebSocketPoolEntry = (poolKey, entry) => {
|
|
|
2777
2816
|
const unrefTimer = (timer) => {
|
|
2778
2817
|
if (typeof timer === "object" && "unref" in timer && typeof timer.unref === "function") timer.unref();
|
|
2779
2818
|
};
|
|
2819
|
+
const createResponsesWebSocketError = (message, event) => {
|
|
2820
|
+
const reason = event?.error ?? event?.message;
|
|
2821
|
+
if (reason === void 0 || reason === "") return new Error(message);
|
|
2822
|
+
const cause = toError(reason);
|
|
2823
|
+
return new Error(`${message}: ${cause.message}`, { cause });
|
|
2824
|
+
};
|
|
2780
2825
|
const openResponsesWebSocket = async ({ headers, url }) => await new Promise((resolve, reject) => {
|
|
2781
2826
|
const dispatcher = getProxyEnvDispatcher();
|
|
2782
2827
|
const websocket = new WebSocket(url, dispatcher ? {
|
|
@@ -2791,9 +2836,9 @@ const openResponsesWebSocket = async ({ headers, url }) => await new Promise((re
|
|
|
2791
2836
|
cleanup();
|
|
2792
2837
|
resolve(websocket);
|
|
2793
2838
|
};
|
|
2794
|
-
const onError = () => {
|
|
2839
|
+
const onError = (event) => {
|
|
2795
2840
|
cleanup();
|
|
2796
|
-
reject(
|
|
2841
|
+
reject(createResponsesWebSocketError("Failed to create responses websocket", event));
|
|
2797
2842
|
};
|
|
2798
2843
|
websocket.addEventListener("open", onOpen);
|
|
2799
2844
|
websocket.addEventListener("error", onError);
|
|
@@ -2815,8 +2860,8 @@ const createWebSocketMessageStream = async function* (websocket) {
|
|
|
2815
2860
|
closed = true;
|
|
2816
2861
|
wake();
|
|
2817
2862
|
};
|
|
2818
|
-
const onError = () => {
|
|
2819
|
-
error =
|
|
2863
|
+
const onError = (event) => {
|
|
2864
|
+
error = createResponsesWebSocketError("Responses websocket stream error", event);
|
|
2820
2865
|
wake();
|
|
2821
2866
|
};
|
|
2822
2867
|
websocket.addEventListener("message", onMessage);
|
|
@@ -2905,14 +2950,23 @@ const MESSAGE_TYPE = "message";
|
|
|
2905
2950
|
const COMPACTION_SIGNATURE_PREFIX = "cm1#";
|
|
2906
2951
|
const COMPACTION_SIGNATURE_SEPARATOR = "@";
|
|
2907
2952
|
const THINKING_TEXT = "Thinking...";
|
|
2908
|
-
const
|
|
2953
|
+
const buildPromptCacheKey = (basePromptCacheKey, subagentAgentId) => {
|
|
2954
|
+
if (!basePromptCacheKey) return null;
|
|
2955
|
+
const normalizedSubagentAgentId = subagentAgentId?.trim() || null;
|
|
2956
|
+
if (!normalizedSubagentAgentId) return basePromptCacheKey;
|
|
2957
|
+
return `${basePromptCacheKey}:agent:${normalizedSubagentAgentId}`;
|
|
2958
|
+
};
|
|
2959
|
+
const translateAnthropicMessagesToResponsesPayload = (payload, subagentAgentId) => {
|
|
2909
2960
|
const input = [];
|
|
2910
2961
|
const applyPhase = shouldApplyPhase(payload.model);
|
|
2911
2962
|
for (const message of payload.messages) input.push(...translateMessage(message, payload.model, applyPhase));
|
|
2963
|
+
const hasOriginalTools = Array.isArray(payload.tools) && payload.tools.length > 0;
|
|
2912
2964
|
const translatedTools = convertAnthropicTools(payload.tools);
|
|
2913
2965
|
const toolChoice = convertAnthropicToolChoice(payload.tool_choice);
|
|
2914
|
-
const { sessionId:
|
|
2915
|
-
|
|
2966
|
+
const { sessionId: metadataPromptCacheKey } = parseUserIdMetadata(payload.metadata?.user_id);
|
|
2967
|
+
const sessionAffinity = requestContext.getStore()?.sessionAffinity?.trim() || null;
|
|
2968
|
+
const promptCacheKey = buildPromptCacheKey(metadataPromptCacheKey ?? sessionAffinity, subagentAgentId);
|
|
2969
|
+
const responsesPayload = {
|
|
2916
2970
|
model: payload.model,
|
|
2917
2971
|
input,
|
|
2918
2972
|
instructions: translateSystemPrompt(payload.system, payload.model),
|
|
@@ -2922,7 +2976,6 @@ const translateAnthropicMessagesToResponsesPayload = (payload) => {
|
|
|
2922
2976
|
tools: translatedTools,
|
|
2923
2977
|
tool_choice: toolChoice,
|
|
2924
2978
|
metadata: payload.metadata ? { ...payload.metadata } : null,
|
|
2925
|
-
prompt_cache_key: promptCacheKey,
|
|
2926
2979
|
stream: payload.stream ?? null,
|
|
2927
2980
|
store: false,
|
|
2928
2981
|
parallel_tool_calls: true,
|
|
@@ -2932,6 +2985,8 @@ const translateAnthropicMessagesToResponsesPayload = (payload) => {
|
|
|
2932
2985
|
},
|
|
2933
2986
|
include: ["reasoning.encrypted_content"]
|
|
2934
2987
|
};
|
|
2988
|
+
if (hasOriginalTools) responsesPayload.prompt_cache_key = promptCacheKey;
|
|
2989
|
+
return responsesPayload;
|
|
2935
2990
|
};
|
|
2936
2991
|
const encodeCompactionCarrierSignature = (compaction) => {
|
|
2937
2992
|
return `${COMPACTION_SIGNATURE_PREFIX}${compaction.encrypted_content}${COMPACTION_SIGNATURE_SEPARATOR}${compaction.id}`;
|
|
@@ -3047,8 +3102,8 @@ const resolveAssistantPhase = (_model, content, applyPhase) => {
|
|
|
3047
3102
|
if (!content.some((block) => block.type === "text")) return;
|
|
3048
3103
|
return content.some((block) => block.type === "tool_use") ? "commentary" : "final_answer";
|
|
3049
3104
|
};
|
|
3050
|
-
const shouldApplyPhase = (
|
|
3051
|
-
return
|
|
3105
|
+
const shouldApplyPhase = (_model) => {
|
|
3106
|
+
return true;
|
|
3052
3107
|
};
|
|
3053
3108
|
const createTextContent = (text) => ({
|
|
3054
3109
|
type: "input_text",
|
|
@@ -4116,7 +4171,7 @@ const handleWithChatCompletions = async (c, anthropicPayload, options) => {
|
|
|
4116
4171
|
};
|
|
4117
4172
|
const handleWithResponsesApi = async (c, anthropicPayload, options) => {
|
|
4118
4173
|
const { logger, selectedModel, ...requestOptions } = options;
|
|
4119
|
-
const responsesPayload = translateAnthropicMessagesToResponsesPayload(anthropicPayload);
|
|
4174
|
+
const responsesPayload = translateAnthropicMessagesToResponsesPayload(anthropicPayload, requestOptions.subagentMarker?.agent_id);
|
|
4120
4175
|
const recordUsage = createCopilotUsageRecorder({
|
|
4121
4176
|
endpoint: "responses",
|
|
4122
4177
|
fallbackSessionId: requestOptions.sessionId,
|
|
@@ -4322,6 +4377,9 @@ const messagesFlowHandlers = {
|
|
|
4322
4377
|
};
|
|
4323
4378
|
async function handleCompletion(c) {
|
|
4324
4379
|
const anthropicPayload = await c.req.json();
|
|
4380
|
+
const requestedModel = anthropicPayload.model;
|
|
4381
|
+
anthropicPayload.model = resolveMappedModel(anthropicPayload.model);
|
|
4382
|
+
if (anthropicPayload.model !== requestedModel) logger$3.debug(`Resolved model mapping: ${requestedModel} -> ${anthropicPayload.model}`);
|
|
4325
4383
|
const providerModelAlias = parseProviderModelAlias(anthropicPayload.model);
|
|
4326
4384
|
if (providerModelAlias) {
|
|
4327
4385
|
anthropicPayload.model = providerModelAlias.model;
|
|
@@ -4707,11 +4765,19 @@ const server = new Hono();
|
|
|
4707
4765
|
server.use(traceIdMiddleware);
|
|
4708
4766
|
server.use(logger());
|
|
4709
4767
|
server.use(cors());
|
|
4710
|
-
server.use("*", createAuthMiddleware({
|
|
4711
|
-
|
|
4712
|
-
|
|
4713
|
-
|
|
4714
|
-
|
|
4768
|
+
server.use("*", createAuthMiddleware({
|
|
4769
|
+
allowUnauthenticatedPaths: [
|
|
4770
|
+
"/",
|
|
4771
|
+
"/usage-viewer",
|
|
4772
|
+
"/usage-viewer/"
|
|
4773
|
+
],
|
|
4774
|
+
shouldSkipPath: (path) => path.startsWith("/admin/")
|
|
4775
|
+
}));
|
|
4776
|
+
server.use("/admin/*", createAuthMiddleware({
|
|
4777
|
+
getApiKeys: getConfiguredAdminApiKeys,
|
|
4778
|
+
allowUnauthenticatedPaths: [],
|
|
4779
|
+
allowWhenNoApiKeys: false
|
|
4780
|
+
}));
|
|
4715
4781
|
server.get("/", (c) => c.text("Server running"));
|
|
4716
4782
|
server.get("/usage-viewer", (c) => {
|
|
4717
4783
|
const usageViewerFileUrl = new URL("../pages/index.html", import.meta.url);
|
|
@@ -4719,6 +4785,7 @@ server.get("/usage-viewer", (c) => {
|
|
|
4719
4785
|
});
|
|
4720
4786
|
server.get("/usage-viewer/", (c) => c.redirect("/usage-viewer", 301));
|
|
4721
4787
|
server.route("/chat/completions", completionRoutes);
|
|
4788
|
+
server.route("/admin/config", configRoutes);
|
|
4722
4789
|
server.route("/models", modelRoutes);
|
|
4723
4790
|
server.route("/embeddings", embeddingRoutes);
|
|
4724
4791
|
server.route("/usage", usageRoute);
|
|
@@ -4735,4 +4802,4 @@ server.route("/:provider/v1/models", providerModelRoutes);
|
|
|
4735
4802
|
//#endregion
|
|
4736
4803
|
export { server };
|
|
4737
4804
|
|
|
4738
|
-
//# sourceMappingURL=server-
|
|
4805
|
+
//# sourceMappingURL=server-UsHsMP_2.js.map
|