@jeffreycao/copilot-api 1.10.1 → 1.10.2

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.
@@ -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-C5ej0z8n.js";
3
- import { a as getConfig, c as getReasoningEffortForModel, d as isResponsesApiContextManagementModel, f as isResponsesApiWebSearchEnabled, i as getClaudeTokenMultiplier, l as getSmallModel, o as getExtraPromptForModel, p as isResponsesApiWebSocketEnabled, r as getAnthropicApiKey, s as getProviderConfig, t as getProxyEnvDispatcher, u as isMessagesApiEnabled } from "./proxy-De0Po8kG.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-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;
@@ -2905,14 +2944,23 @@ const MESSAGE_TYPE = "message";
2905
2944
  const COMPACTION_SIGNATURE_PREFIX = "cm1#";
2906
2945
  const COMPACTION_SIGNATURE_SEPARATOR = "@";
2907
2946
  const THINKING_TEXT = "Thinking...";
2908
- const translateAnthropicMessagesToResponsesPayload = (payload) => {
2947
+ const buildPromptCacheKey = (basePromptCacheKey, subagentAgentId) => {
2948
+ if (!basePromptCacheKey) return null;
2949
+ const normalizedSubagentAgentId = subagentAgentId?.trim() || null;
2950
+ if (!normalizedSubagentAgentId) return basePromptCacheKey;
2951
+ return `${basePromptCacheKey}:agent:${normalizedSubagentAgentId}`;
2952
+ };
2953
+ const translateAnthropicMessagesToResponsesPayload = (payload, subagentAgentId) => {
2909
2954
  const input = [];
2910
2955
  const applyPhase = shouldApplyPhase(payload.model);
2911
2956
  for (const message of payload.messages) input.push(...translateMessage(message, payload.model, applyPhase));
2957
+ const hasOriginalTools = Array.isArray(payload.tools) && payload.tools.length > 0;
2912
2958
  const translatedTools = convertAnthropicTools(payload.tools);
2913
2959
  const toolChoice = convertAnthropicToolChoice(payload.tool_choice);
2914
- const { sessionId: promptCacheKey } = parseUserIdMetadata(payload.metadata?.user_id);
2915
- return {
2960
+ const { sessionId: metadataPromptCacheKey } = parseUserIdMetadata(payload.metadata?.user_id);
2961
+ const sessionAffinity = requestContext.getStore()?.sessionAffinity?.trim() || null;
2962
+ const promptCacheKey = buildPromptCacheKey(metadataPromptCacheKey ?? sessionAffinity, subagentAgentId);
2963
+ const responsesPayload = {
2916
2964
  model: payload.model,
2917
2965
  input,
2918
2966
  instructions: translateSystemPrompt(payload.system, payload.model),
@@ -2922,7 +2970,6 @@ const translateAnthropicMessagesToResponsesPayload = (payload) => {
2922
2970
  tools: translatedTools,
2923
2971
  tool_choice: toolChoice,
2924
2972
  metadata: payload.metadata ? { ...payload.metadata } : null,
2925
- prompt_cache_key: promptCacheKey,
2926
2973
  stream: payload.stream ?? null,
2927
2974
  store: false,
2928
2975
  parallel_tool_calls: true,
@@ -2932,6 +2979,8 @@ const translateAnthropicMessagesToResponsesPayload = (payload) => {
2932
2979
  },
2933
2980
  include: ["reasoning.encrypted_content"]
2934
2981
  };
2982
+ if (hasOriginalTools) responsesPayload.prompt_cache_key = promptCacheKey;
2983
+ return responsesPayload;
2935
2984
  };
2936
2985
  const encodeCompactionCarrierSignature = (compaction) => {
2937
2986
  return `${COMPACTION_SIGNATURE_PREFIX}${compaction.encrypted_content}${COMPACTION_SIGNATURE_SEPARATOR}${compaction.id}`;
@@ -3047,8 +3096,8 @@ const resolveAssistantPhase = (_model, content, applyPhase) => {
3047
3096
  if (!content.some((block) => block.type === "text")) return;
3048
3097
  return content.some((block) => block.type === "tool_use") ? "commentary" : "final_answer";
3049
3098
  };
3050
- const shouldApplyPhase = (model) => {
3051
- return getExtraPromptForModel(model).includes("## Intermediary updates");
3099
+ const shouldApplyPhase = (_model) => {
3100
+ return true;
3052
3101
  };
3053
3102
  const createTextContent = (text) => ({
3054
3103
  type: "input_text",
@@ -4116,7 +4165,7 @@ const handleWithChatCompletions = async (c, anthropicPayload, options) => {
4116
4165
  };
4117
4166
  const handleWithResponsesApi = async (c, anthropicPayload, options) => {
4118
4167
  const { logger, selectedModel, ...requestOptions } = options;
4119
- const responsesPayload = translateAnthropicMessagesToResponsesPayload(anthropicPayload);
4168
+ const responsesPayload = translateAnthropicMessagesToResponsesPayload(anthropicPayload, requestOptions.subagentMarker?.agent_id);
4120
4169
  const recordUsage = createCopilotUsageRecorder({
4121
4170
  endpoint: "responses",
4122
4171
  fallbackSessionId: requestOptions.sessionId,
@@ -4322,6 +4371,9 @@ const messagesFlowHandlers = {
4322
4371
  };
4323
4372
  async function handleCompletion(c) {
4324
4373
  const anthropicPayload = await c.req.json();
4374
+ const requestedModel = anthropicPayload.model;
4375
+ anthropicPayload.model = resolveMappedModel(anthropicPayload.model);
4376
+ if (anthropicPayload.model !== requestedModel) logger$3.debug(`Resolved model mapping: ${requestedModel} -> ${anthropicPayload.model}`);
4325
4377
  const providerModelAlias = parseProviderModelAlias(anthropicPayload.model);
4326
4378
  if (providerModelAlias) {
4327
4379
  anthropicPayload.model = providerModelAlias.model;
@@ -4707,11 +4759,19 @@ const server = new Hono();
4707
4759
  server.use(traceIdMiddleware);
4708
4760
  server.use(logger());
4709
4761
  server.use(cors());
4710
- server.use("*", createAuthMiddleware({ allowUnauthenticatedPaths: [
4711
- "/",
4712
- "/usage-viewer",
4713
- "/usage-viewer/"
4714
- ] }));
4762
+ server.use("*", createAuthMiddleware({
4763
+ allowUnauthenticatedPaths: [
4764
+ "/",
4765
+ "/usage-viewer",
4766
+ "/usage-viewer/"
4767
+ ],
4768
+ shouldSkipPath: (path) => path.startsWith("/admin/")
4769
+ }));
4770
+ server.use("/admin/*", createAuthMiddleware({
4771
+ getApiKeys: getConfiguredAdminApiKeys,
4772
+ allowUnauthenticatedPaths: [],
4773
+ allowWhenNoApiKeys: false
4774
+ }));
4715
4775
  server.get("/", (c) => c.text("Server running"));
4716
4776
  server.get("/usage-viewer", (c) => {
4717
4777
  const usageViewerFileUrl = new URL("../pages/index.html", import.meta.url);
@@ -4719,6 +4779,7 @@ server.get("/usage-viewer", (c) => {
4719
4779
  });
4720
4780
  server.get("/usage-viewer/", (c) => c.redirect("/usage-viewer", 301));
4721
4781
  server.route("/chat/completions", completionRoutes);
4782
+ server.route("/admin/config", configRoutes);
4722
4783
  server.route("/models", modelRoutes);
4723
4784
  server.route("/embeddings", embeddingRoutes);
4724
4785
  server.route("/usage", usageRoute);
@@ -4735,4 +4796,4 @@ server.route("/:provider/v1/models", providerModelRoutes);
4735
4796
  //#endregion
4736
4797
  export { server };
4737
4798
 
4738
- //# sourceMappingURL=server-DpVPS3zt.js.map
4799
+ //# sourceMappingURL=server-csGHkK-m.js.map