@nick3/copilot-api 1.3.5 → 1.3.8

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,8 +1,8 @@
1
1
  import { PATHS } from "./paths-DoT4SZ8f.js";
2
2
  import { listAccountsFromRegistry } from "./accounts-registry-c7rs5Ed9.js";
3
- import { HTTPError, accountFromState, cacheModels, copilotBaseUrl, copilotHeaders, forwardError, generateRequestIdFromPayload, getCopilotUsage, getRootSessionId, getUUID, isNullish, prepareInteractionHeaders, sleep, state } from "./utils-BUJfM1V2.js";
4
- import "./get-copilot-token-BwP_PxV5.js";
5
- import { PROVIDER_TYPE_ANTHROPIC, accountsManager, getAliasTargetSet, getConfig, getExtraPromptForModel, getModelAliases, getModelAliasesInfo, getModelRefreshIntervalMs, getProviderConfig, getReasoningEffortForModel, getSmallModel, isForceAgentEnabled, isFreeModelLoadBalancingEnabled, isMessageStartInputTokensFallbackEnabled, isMessagesApiEnabled, isResponsesApiContextManagementModel, mergeConfigWithDefaults, shouldCompactUseSmallModel } from "./accounts-manager-DjGzZIcp.js";
3
+ import { HTTPError, accountFromState, cacheModels, copilotBaseUrl, copilotHeaders, forwardError, generateRequestIdFromPayload, getCopilotUsage, getRootSessionId, getUUID, isNullish, prepareForCompact, prepareInteractionHeaders, sleep, state } from "./utils-BaoXuYkx.js";
4
+ import "./get-copilot-token-CUT8hpgX.js";
5
+ import { PROVIDER_TYPE_ANTHROPIC, accountsManager, getAliasTargetSet, getConfig, getExtraPromptForModel, getModelAliases, getModelAliasesInfo, getModelRefreshIntervalMs, getProviderConfig, getReasoningEffortForModel, getSmallModel, isForceAgentEnabled, isFreeModelLoadBalancingEnabled, isMessageStartInputTokensFallbackEnabled, isMessagesApiEnabled, isResponsesApiContextManagementModel, mergeConfigWithDefaults, shouldCompactUseSmallModel } from "./accounts-manager-BGBtDChT.js";
6
6
  import consola from "consola";
7
7
  import fs, { readFile } from "node:fs/promises";
8
8
  import * as path$1 from "node:path";
@@ -12,6 +12,7 @@ import { Hono } from "hono";
12
12
  import { cors } from "hono/cors";
13
13
  import { logger } from "hono/logger";
14
14
  import fs$1, { existsSync } from "node:fs";
15
+ import { AsyncLocalStorage } from "node:async_hooks";
15
16
  import { Database } from "bun:sqlite";
16
17
  import { fileURLToPath } from "node:url";
17
18
  import { streamSSE } from "hono/streaming";
@@ -104,6 +105,40 @@ function createAuthMiddleware(options = {}) {
104
105
  };
105
106
  }
106
107
 
108
+ //#endregion
109
+ //#region src/lib/request-context.ts
110
+ const TRACE_ID_MAX_LENGTH = 64;
111
+ const TRACE_ID_PATTERN = /^\w[\w.-]*$/;
112
+ const asyncLocalStorage = new AsyncLocalStorage();
113
+ const requestContext = {
114
+ getStore: () => asyncLocalStorage.getStore(),
115
+ run: (context, callback) => asyncLocalStorage.run(context, callback)
116
+ };
117
+ function generateTraceId() {
118
+ const timestamp = Date.now().toString(36);
119
+ const random = Math.random().toString(36).slice(2, 8);
120
+ return `${timestamp}-${random}`;
121
+ }
122
+ function resolveTraceId(traceId) {
123
+ const candidate = traceId?.trim();
124
+ if (!candidate || candidate.length > TRACE_ID_MAX_LENGTH || !TRACE_ID_PATTERN.test(candidate)) return generateTraceId();
125
+ return candidate;
126
+ }
127
+
128
+ //#endregion
129
+ //#region src/lib/trace.ts
130
+ const traceIdMiddleware = async (c, next) => {
131
+ const traceId = resolveTraceId(c.req.header("x-trace-id"));
132
+ c.header("x-trace-id", traceId);
133
+ const context = {
134
+ traceId,
135
+ startTime: Date.now()
136
+ };
137
+ await requestContext.run(context, async () => {
138
+ await next();
139
+ });
140
+ };
141
+
107
142
  //#endregion
108
143
  //#region src/lib/admin-db.ts
109
144
  const DEFAULT_DB_PATH = path.join(PATHS.APP_DIR, "admin.sqlite");
@@ -2148,12 +2183,14 @@ const createHandlerLogger = (name) => {
2148
2183
  cleanupOldLogs();
2149
2184
  lastCleanup = Date.now();
2150
2185
  }
2186
+ const traceId = requestContext.getStore()?.traceId;
2151
2187
  const date = logObj.date;
2152
2188
  const dateKey = date.toLocaleDateString("sv-SE");
2153
2189
  const timestamp = date.toLocaleString("sv-SE", { hour12: false });
2154
2190
  const filePath = path.join(LOG_DIR, `${sanitizedName}-${dateKey}.log`);
2155
2191
  const message = formatArgs(logObj.args);
2156
- const line = `[${timestamp}] [${logObj.type}] [${logObj.tag || name}]${message ? ` ${message}` : ""}`;
2192
+ const traceIdStr = traceId ? ` [${traceId}]` : "";
2193
+ const line = `[${timestamp}] [${logObj.type}] [${logObj.tag || name}]${traceIdStr}${message ? ` ${message}` : ""}`;
2157
2194
  appendLine(filePath, line);
2158
2195
  } });
2159
2196
  return instance;
@@ -2403,7 +2440,7 @@ const getTokenCount = async (payload, model) => {
2403
2440
 
2404
2441
  //#endregion
2405
2442
  //#region src/services/copilot/create-responses.ts
2406
- const createResponses = async (payload, { vision, initiator, upstreamRequestId, subagentMarker, sessionId }, account) => {
2443
+ const createResponses = async (payload, { vision, initiator, upstreamRequestId, subagentMarker, sessionId, isCompact }, account) => {
2407
2444
  const ctx = account ?? accountFromState();
2408
2445
  if (!ctx.copilotToken) throw new Error("Copilot token not found");
2409
2446
  const headers = {
@@ -2411,6 +2448,7 @@ const createResponses = async (payload, { vision, initiator, upstreamRequestId,
2411
2448
  "x-initiator": initiator
2412
2449
  };
2413
2450
  prepareInteractionHeaders(sessionId, Boolean(subagentMarker), headers);
2451
+ prepareForCompact(headers, isCompact);
2414
2452
  payload.service_tier = null;
2415
2453
  const response = await fetch(`${copilotBaseUrl(ctx)}/responses`, {
2416
2454
  method: "POST",
@@ -2892,6 +2930,7 @@ const createChatCompletions = async (payload, account, options) => {
2892
2930
  };
2893
2931
  prepareInteractionHeaders(options?.sessionId, Boolean(options?.subagentMarker), headers);
2894
2932
  const upstreamPayload = applyDefaultReasoningEffort(payload);
2933
+ prepareForCompact(headers, options?.isCompact);
2895
2934
  const response = await fetch(`${copilotBaseUrl(ctx)}/chat/completions`, {
2896
2935
  method: "POST",
2897
2936
  headers,
@@ -4441,6 +4480,7 @@ const createMessages = async (payload, account, options) => {
4441
4480
  "x-initiator": options?.subagentMarker ? "agent" : initiator
4442
4481
  };
4443
4482
  prepareInteractionHeaders(options?.sessionId, Boolean(options?.subagentMarker), headers);
4483
+ prepareForCompact(headers, options?.isCompact);
4444
4484
  const anthropicBeta = buildAnthropicBetaHeader(options?.anthropicBetaHeader, payload.thinking);
4445
4485
  if (anthropicBeta) headers["anthropic-beta"] = anthropicBeta;
4446
4486
  const response = await fetch(`${copilotBaseUrl(ctx)}/v1/messages`, {
@@ -4887,7 +4927,8 @@ async function handleCompletion(c) {
4887
4927
  subagentMarker,
4888
4928
  sessionId,
4889
4929
  instr,
4890
- selectedModel
4930
+ selectedModel,
4931
+ isCompact
4891
4932
  });
4892
4933
  if (endpoint === RESPONSES_ENDPOINT$1) return await handleWithResponsesApi({
4893
4934
  c,
@@ -4897,7 +4938,8 @@ async function handleCompletion(c) {
4897
4938
  subagentMarker,
4898
4939
  sessionId,
4899
4940
  selectedModel,
4900
- instr
4941
+ instr,
4942
+ isCompact
4901
4943
  });
4902
4944
  return await handleWithChatCompletions({
4903
4945
  c,
@@ -4906,11 +4948,12 @@ async function handleCompletion(c) {
4906
4948
  subagentMarker,
4907
4949
  sessionId,
4908
4950
  selectedModel,
4909
- instr
4951
+ instr,
4952
+ isCompact
4910
4953
  });
4911
4954
  }
4912
4955
  const handleWithChatCompletions = async (params) => {
4913
- const { c, openAIPayload, initiatorOverride, subagentMarker, sessionId, selectedModel, instr } = params;
4956
+ const { c, openAIPayload, initiatorOverride, subagentMarker, sessionId, selectedModel, instr, isCompact } = params;
4914
4957
  logger$5.debug("Translated OpenAI request payload:", JSON.stringify(openAIPayload));
4915
4958
  const ctx = toAccountContext(instr.account);
4916
4959
  const initiator = initiatorOverride ?? getChatInitiator(openAIPayload.messages);
@@ -4921,7 +4964,8 @@ const handleWithChatCompletions = async (params) => {
4921
4964
  upstreamRequestId: instr.upstreamRequestId,
4922
4965
  initiator,
4923
4966
  subagentMarker,
4924
- sessionId
4967
+ sessionId,
4968
+ isCompact
4925
4969
  });
4926
4970
  } catch (error) {
4927
4971
  return await handleChatCompletionsCreateError({
@@ -4952,7 +4996,7 @@ const handleWithChatCompletions = async (params) => {
4952
4996
  }));
4953
4997
  };
4954
4998
  const handleWithResponsesApi = async (params) => {
4955
- const { c, anthropicPayload, openAIPayload, initiatorOverride, subagentMarker, sessionId, selectedModel, instr } = params;
4999
+ const { c, anthropicPayload, openAIPayload, initiatorOverride, subagentMarker, sessionId, selectedModel, instr, isCompact } = params;
4956
5000
  const responsesPayload = translateAnthropicMessagesToResponsesPayload(anthropicPayload, selectedModel.id);
4957
5001
  applyResponsesApiContextManagement(responsesPayload, selectedModel.capabilities.limits.max_prompt_tokens);
4958
5002
  compactInputByLatestCompaction(responsesPayload);
@@ -4968,7 +5012,8 @@ const handleWithResponsesApi = async (params) => {
4968
5012
  initiator: resolvedInitiator,
4969
5013
  upstreamRequestId: instr.upstreamRequestId,
4970
5014
  subagentMarker,
4971
- sessionId
5015
+ sessionId,
5016
+ isCompact
4972
5017
  }, ctx);
4973
5018
  } catch (error) {
4974
5019
  return await handleResponsesCreateError({
@@ -5419,7 +5464,7 @@ async function streamMessagesAndLog(params) {
5419
5464
  }
5420
5465
  }
5421
5466
  const handleWithMessagesApi = async (params) => {
5422
- const { c, anthropicPayload, anthropicBetaHeader, initiatorOverride, subagentMarker, sessionId, instr, selectedModel } = params;
5467
+ const { c, anthropicPayload, anthropicBetaHeader, initiatorOverride, subagentMarker, sessionId, instr, selectedModel, isCompact } = params;
5423
5468
  for (const msg of anthropicPayload.messages) if (msg.role === "assistant" && Array.isArray(msg.content)) msg.content = msg.content.filter((block) => {
5424
5469
  if (block.type !== "thinking") return true;
5425
5470
  return block.thinking && block.thinking !== "Thinking..." && block.signature && !block.signature.includes("@");
@@ -5443,7 +5488,8 @@ const handleWithMessagesApi = async (params) => {
5443
5488
  upstreamRequestId: instr.upstreamRequestId,
5444
5489
  initiator,
5445
5490
  subagentMarker,
5446
- sessionId
5491
+ sessionId,
5492
+ isCompact
5447
5493
  });
5448
5494
  } catch (error) {
5449
5495
  return await handleMessagesCreateError({
@@ -5665,14 +5711,37 @@ async function handleProviderMessages(c) {
5665
5711
  provider
5666
5712
  }));
5667
5713
  const upstreamResponse = await forwardProviderMessages(providerConfig, payload, c.req.raw.headers);
5714
+ if (!upstreamResponse.ok) {
5715
+ logger$3.error("Failed to create responses", upstreamResponse);
5716
+ throw new HTTPError("Failed to create responses", upstreamResponse);
5717
+ }
5668
5718
  const contentType = upstreamResponse.headers.get("content-type") ?? "";
5669
5719
  if (Boolean(payload.stream) && contentType.includes("text/event-stream")) {
5670
5720
  logger$3.debug("provider.messages.streaming");
5671
5721
  return streamSSE(c, async (stream) => {
5672
- for await (const event of events(upstreamResponse)) {
5673
- const eventName = event.event;
5674
- const data = event.data ?? "";
5675
- logger$3.debug("provider.messages.raw_stream_event", data);
5722
+ for await (const chunk of events(upstreamResponse)) {
5723
+ logger$3.debug("provider.messages.raw_stream_event:", chunk.data);
5724
+ const eventName = chunk.event;
5725
+ if (eventName === "ping") {
5726
+ await stream.writeSSE({
5727
+ event: "ping",
5728
+ data: "{\"type\":\"ping\"}"
5729
+ });
5730
+ continue;
5731
+ }
5732
+ let data = chunk.data;
5733
+ if (!data) continue;
5734
+ try {
5735
+ const parsed = JSON.parse(data);
5736
+ if (parsed.type === "message_start") adjustInputTokens(providerConfig, parsed.message.usage);
5737
+ else if (parsed.type === "message_delta") adjustInputTokens(providerConfig, parsed.usage);
5738
+ data = JSON.stringify(parsed);
5739
+ } catch (error) {
5740
+ logger$3.error("provider.messages.streaming.adjust_tokens_error", {
5741
+ error,
5742
+ originalData: data
5743
+ });
5744
+ }
5676
5745
  await stream.writeSSE({
5677
5746
  event: eventName,
5678
5747
  data
@@ -5680,7 +5749,10 @@ async function handleProviderMessages(c) {
5680
5749
  }
5681
5750
  });
5682
5751
  }
5683
- return createProviderProxyResponse(upstreamResponse);
5752
+ const jsonBody = await upstreamResponse.json();
5753
+ adjustInputTokens(providerConfig, jsonBody.usage);
5754
+ logger$3.debug("provider.messages.no_stream result:", JSON.stringify(jsonBody));
5755
+ return c.json(jsonBody);
5684
5756
  } catch (error) {
5685
5757
  logger$3.error("provider.messages.error", {
5686
5758
  provider,
@@ -5689,6 +5761,11 @@ async function handleProviderMessages(c) {
5689
5761
  throw error;
5690
5762
  }
5691
5763
  }
5764
+ const adjustInputTokens = (providerConfig, usage) => {
5765
+ if (!providerConfig.adjustInputTokens || !usage) return;
5766
+ usage.input_tokens = Math.max(0, (usage.input_tokens ?? 0) - (usage.cache_read_input_tokens ?? 0) - (usage.cache_creation_input_tokens ?? 0));
5767
+ logger$3.debug("provider.messages.adjusted_usage:", JSON.stringify(usage));
5768
+ };
5692
5769
 
5693
5770
  //#endregion
5694
5771
  //#region src/routes/provider/messages/route.ts
@@ -6295,6 +6372,7 @@ usageRoute.get("/:accountIndex", async (c) => {
6295
6372
  //#endregion
6296
6373
  //#region src/server.ts
6297
6374
  const server = new Hono();
6375
+ server.use(traceIdMiddleware);
6298
6376
  server.use(logger());
6299
6377
  server.use(cors());
6300
6378
  server.use("*", createAuthMiddleware({
@@ -6320,4 +6398,4 @@ server.route("/:provider/v1/models", providerModelRoutes);
6320
6398
 
6321
6399
  //#endregion
6322
6400
  export { server };
6323
- //# sourceMappingURL=server-CM_0PrbK.js.map
6401
+ //# sourceMappingURL=server-COWbIpDR.js.map