@nick3/copilot-api 1.5.2 → 1.5.5

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.
Files changed (39) hide show
  1. package/README.md +5 -3
  2. package/dist/account-AacnHem5.js +362 -0
  3. package/dist/account-AacnHem5.js.map +1 -0
  4. package/dist/{accounts-manager-DhwGrhHF.js → accounts-manager-BevCBoaF.js} +96 -7
  5. package/dist/accounts-manager-BevCBoaF.js.map +1 -0
  6. package/dist/admin/assets/index-519a65q_.js +66 -0
  7. package/dist/admin/assets/index-ChMaMig2.css +1 -0
  8. package/dist/admin/index.html +2 -2
  9. package/dist/{auth-BtUQnU2m.js → auth-B7x3wjry.js} +6 -12
  10. package/dist/auth-B7x3wjry.js.map +1 -0
  11. package/dist/{check-usage-DiomC9Dl.js → check-usage-B1cbDEOI.js} +4 -5
  12. package/dist/{check-usage-DiomC9Dl.js.map → check-usage-B1cbDEOI.js.map} +1 -1
  13. package/dist/{debug-BzR5ZQUk.js → debug-BJfZVBB7.js} +2 -2
  14. package/dist/{debug-BzR5ZQUk.js.map → debug-BJfZVBB7.js.map} +1 -1
  15. package/dist/{get-copilot-token-DN1P6qll.js → get-copilot-token-cha9rQwA.js} +2 -2
  16. package/dist/{get-copilot-token-DN1P6qll.js.map → get-copilot-token-cha9rQwA.js.map} +1 -1
  17. package/dist/main.js +4 -4
  18. package/dist/{paths-Cvzy-eLX.js → paths-DGlr310R.js} +2 -2
  19. package/dist/{paths-Cvzy-eLX.js.map → paths-DGlr310R.js.map} +1 -1
  20. package/dist/{utils-53JWve7i.js → poll-access-token-DFooFWhY.js} +339 -46
  21. package/dist/poll-access-token-DFooFWhY.js.map +1 -0
  22. package/dist/{server-D9M_wFyO.js → server-CuXJhEMC.js} +495 -140
  23. package/dist/server-CuXJhEMC.js.map +1 -0
  24. package/dist/{start-D3yEfZnW.js → start-D6O1XcfI.js} +26 -15
  25. package/dist/start-D6O1XcfI.js.map +1 -0
  26. package/package.json +1 -1
  27. package/dist/account-CipKmikF.js +0 -17
  28. package/dist/account-CipKmikF.js.map +0 -1
  29. package/dist/accounts-manager-DhwGrhHF.js.map +0 -1
  30. package/dist/accounts-registry-CQYvRe65.js +0 -180
  31. package/dist/accounts-registry-CQYvRe65.js.map +0 -1
  32. package/dist/admin/assets/index-B-G_GrPI.js +0 -57
  33. package/dist/admin/assets/index-CsAeel_7.css +0 -1
  34. package/dist/auth-BtUQnU2m.js.map +0 -1
  35. package/dist/poll-access-token-BrRUFB1F.js +0 -52
  36. package/dist/poll-access-token-BrRUFB1F.js.map +0 -1
  37. package/dist/server-D9M_wFyO.js.map +0 -1
  38. package/dist/start-D3yEfZnW.js.map +0 -1
  39. package/dist/utils-53JWve7i.js.map +0 -1
@@ -1,13 +1,13 @@
1
- import { t as PATHS } from "./paths-Cvzy-eLX.js";
2
- import { i as listAccountsFromRegistry } from "./accounts-registry-CQYvRe65.js";
3
- import { C as prepareInteractionHeaders, D as state, E as accountFromState, S as prepareForCompact, T as resolveTraceId, _ as copilotHeaders, a as generateRequestIdFromPayload, c as isNullish, g as copilotBaseUrl, h as forwardError, l as parseUserIdMetadata, m as HTTPError, n as cacheModels, o as getRootSessionId, p as getCopilotUsage, s as getUUID, u as sleep, w as requestContext } from "./utils-53JWve7i.js";
4
- import "./get-copilot-token-DN1P6qll.js";
5
- import { _ as isMessagesApiEnabled, a as getClaudeTokenMultiplier, b as mergeConfigWithDefaults, c as getModelAliases, d as getProviderConfig, f as getReasoningEffortForModel, g as isMessageStartInputTokensFallbackEnabled, h as isForceAgentEnabled, i as getAnthropicApiKey, l as getModelAliasesInfo, m as isAccountAffinityEnabled, n as PROVIDER_TYPE_ANTHROPIC, o as getConfig, p as getSmallModel, r as getAliasTargetSet, s as getExtraPromptForModel, t as accountsManager, u as getModelRefreshIntervalMs, v as isResponsesApiContextManagementModel, x as shouldCompactUseSmallModel, y as isResponsesApiWebSearchEnabled } from "./accounts-manager-DhwGrhHF.js";
1
+ import { A as resolveTraceId, C as normalizeDomain, D as accountFromState, E as prepareMessageProxyHeaders, O as state, T as prepareInteractionHeaders, _ as HTTPError, b as copilotHeaders, c as getRootSessionId, d as parseUserIdMetadata, f as sleep, g as getCopilotUsage, h as getDeviceCode, k as requestContext, l as getUUID, m as getGitHubUser, r as cacheModels, s as generateRequestIdFromPayload, t as pollAccessToken, u as isNullish, v as forwardError, w as prepareForCompact, y as copilotBaseUrl } from "./poll-access-token-DFooFWhY.js";
2
+ import { a as getAccountClientIdentityByLoginAndApp, c as listAccountsFromRegistry, f as removeAccountFromRegistry, g as DEFAULT_IDENTITY_ENTERPRISE_DOMAIN, h as saveRegistry, m as saveAccountToken, p as removeAccountToken, r as addAccountToRegistry, t as isAccountType, u as loadRegistry, y as getCurrentIdentityEnvironment } from "./account-AacnHem5.js";
3
+ import { r as ensurePaths, t as PATHS } from "./paths-DGlr310R.js";
4
+ import "./get-copilot-token-cha9rQwA.js";
5
+ import { _ as isMessagesApiEnabled, a as getClaudeTokenMultiplier, b as mergeConfigWithDefaults, c as getModelAliases, d as getProviderConfig, f as getReasoningEffortForModel, g as isMessageStartInputTokensFallbackEnabled, h as isForceAgentEnabled, i as getAnthropicApiKey, l as getModelAliasesInfo, m as isAccountAffinityEnabled, n as PROVIDER_TYPE_ANTHROPIC, o as getConfig, p as getSmallModel, r as getAliasTargetSet, s as getExtraPromptForModel, t as accountsManager, u as getModelRefreshIntervalMs, v as isResponsesApiContextManagementModel, x as shouldCompactUseSmallModel, y as isResponsesApiWebSearchEnabled } from "./accounts-manager-BevCBoaF.js";
6
6
  import consola from "consola";
7
7
  import fs, { readFile } from "node:fs/promises";
8
+ import { randomUUID, timingSafeEqual } from "node:crypto";
8
9
  import * as path$1 from "node:path";
9
10
  import path from "node:path";
10
- import { randomUUID, timingSafeEqual } from "node:crypto";
11
11
  import { Hono } from "hono";
12
12
  import { cors } from "hono/cors";
13
13
  import { logger } from "hono/logger";
@@ -112,7 +112,9 @@ const traceIdMiddleware = async (c, next) => {
112
112
  const context = {
113
113
  traceId,
114
114
  startTime: Date.now(),
115
- userAgent: c.req.header("user-agent") || ""
115
+ userAgent: c.req.header("user-agent") || "",
116
+ sessionAffinity: c.req.header("x-session-affinity"),
117
+ parentSessionId: c.req.header("x-parent-session-id")
116
118
  };
117
119
  await requestContext.run(context, async () => {
118
120
  await next();
@@ -690,6 +692,162 @@ function extractResponsesUsageFromResult(result) {
690
692
  return normalizeResponsesUsage(result.usage);
691
693
  }
692
694
 
695
+ //#endregion
696
+ //#region src/routes/admin-api/auth-sessions.ts
697
+ function buildOauthUrls(enterpriseDomain) {
698
+ if (!enterpriseDomain) return void 0;
699
+ const domain = normalizeDomain(enterpriseDomain);
700
+ if (!domain) return void 0;
701
+ return {
702
+ deviceCodeUrl: `https://${domain}/login/device/code`,
703
+ accessTokenUrl: `https://${domain}/login/oauth/access_token`
704
+ };
705
+ }
706
+ const CLEANUP_INTERVAL_MS$1 = 6e4;
707
+ var AuthSessionManager = class {
708
+ sessions = /* @__PURE__ */ new Map();
709
+ cleanupTimer = null;
710
+ start() {
711
+ if (this.cleanupTimer) return;
712
+ this.cleanupTimer = setInterval(() => this.cleanupExpired(), CLEANUP_INTERVAL_MS$1);
713
+ }
714
+ stop() {
715
+ if (this.cleanupTimer) {
716
+ clearInterval(this.cleanupTimer);
717
+ this.cleanupTimer = null;
718
+ }
719
+ for (const session of this.sessions.values()) session.abortController.abort();
720
+ this.sessions.clear();
721
+ }
722
+ async startAuth(params) {
723
+ const enterpriseDomain = params.enterpriseDomain ? normalizeDomain(params.enterpriseDomain) : null;
724
+ const overrideUrls = buildOauthUrls(enterpriseDomain);
725
+ await ensurePaths();
726
+ const deviceResponse = await getDeviceCode({ overrideUrls });
727
+ const sessionId = randomUUID();
728
+ const abortController = new AbortController();
729
+ const expiresAt = Date.now() + deviceResponse.expires_in * 1e3;
730
+ const session = {
731
+ sessionId,
732
+ accountType: params.accountType,
733
+ enterpriseDomain,
734
+ status: "pending",
735
+ userCode: deviceResponse.user_code,
736
+ verificationUri: deviceResponse.verification_uri,
737
+ expiresAt,
738
+ interval: deviceResponse.interval,
739
+ abortController,
740
+ reauthAccountId: params.reauthAccountId ?? null
741
+ };
742
+ this.sessions.set(sessionId, session);
743
+ this.runAuthFlow(session, deviceResponse, overrideUrls);
744
+ return {
745
+ sessionId,
746
+ userCode: deviceResponse.user_code,
747
+ verificationUri: deviceResponse.verification_uri,
748
+ expiresIn: deviceResponse.expires_in,
749
+ interval: deviceResponse.interval
750
+ };
751
+ }
752
+ getStatus(sessionId) {
753
+ const session = this.sessions.get(sessionId);
754
+ if (!session) return null;
755
+ if (session.status === "pending" && Date.now() >= session.expiresAt) {
756
+ session.status = "expired";
757
+ session.abortController.abort();
758
+ }
759
+ return {
760
+ status: session.status,
761
+ accountId: session.accountId,
762
+ error: session.error
763
+ };
764
+ }
765
+ cancel(sessionId) {
766
+ const session = this.sessions.get(sessionId);
767
+ if (!session) return false;
768
+ session.abortController.abort();
769
+ this.sessions.delete(sessionId);
770
+ return true;
771
+ }
772
+ getLiveSession(sessionId) {
773
+ const session = this.sessions.get(sessionId);
774
+ if (!session || session.abortController.signal.aborted) return null;
775
+ return session;
776
+ }
777
+ async runAuthFlow(session, deviceResponse, overrideUrls) {
778
+ try {
779
+ const sessionId = session.sessionId;
780
+ const signal = session.abortController.signal;
781
+ const token = await pollAccessToken(deviceResponse, {
782
+ overrideUrls,
783
+ signal
784
+ });
785
+ if (!this.getLiveSession(sessionId)) return;
786
+ const user = await getGitHubUser({
787
+ githubToken: token,
788
+ accountType: session.accountType
789
+ });
790
+ if (!this.getLiveSession(sessionId)) return;
791
+ const accountId = user.login;
792
+ if (session.reauthAccountId && session.reauthAccountId !== accountId) {
793
+ this.failSession(sessionId, `Authenticated as "${accountId}" but expected "${session.reauthAccountId}". Use "Add Account" to add a different account.`);
794
+ return;
795
+ }
796
+ if (!this.getLiveSession(sessionId)) return;
797
+ await saveAccountToken(accountId, token);
798
+ if (!this.getLiveSession(sessionId)) return;
799
+ if (!this.getLiveSession(sessionId)) return;
800
+ const existingAccounts = await listAccountsFromRegistry();
801
+ if (!this.getLiveSession(sessionId)) return;
802
+ if (existingAccounts.some((acc) => acc.id === accountId)) {
803
+ const registry = await loadRegistry();
804
+ if (!this.getLiveSession(sessionId)) return;
805
+ await saveRegistry(registry);
806
+ } else {
807
+ if (!this.getLiveSession(sessionId)) return;
808
+ await addAccountToRegistry({
809
+ id: accountId,
810
+ accountType: session.accountType,
811
+ addedAt: Date.now()
812
+ });
813
+ }
814
+ if (!this.getLiveSession(sessionId)) return;
815
+ this.completeSession(sessionId, accountId);
816
+ } catch (error) {
817
+ if (session.abortController.signal.aborted) return;
818
+ this.failSession(session.sessionId, error instanceof Error ? error.message : String(error));
819
+ consola.error(`Auth session ${session.sessionId} failed:`, error);
820
+ }
821
+ }
822
+ completeSession(sessionId, accountId) {
823
+ const session = this.sessions.get(sessionId);
824
+ if (!session || session.abortController.signal.aborted) return;
825
+ session.status = "completed";
826
+ session.accountId = accountId;
827
+ }
828
+ failSession(sessionId, error) {
829
+ const session = this.sessions.get(sessionId);
830
+ if (!session || session.abortController.signal.aborted) return;
831
+ session.status = "failed";
832
+ session.error = error;
833
+ }
834
+ cleanupExpired() {
835
+ const now = Date.now();
836
+ const cleanupThreshold = 5 * 6e4;
837
+ for (const [id, session] of this.sessions) {
838
+ if (session.status !== "pending" && now - session.expiresAt > cleanupThreshold) {
839
+ session.abortController.abort();
840
+ this.sessions.delete(id);
841
+ }
842
+ if (session.status === "pending" && now >= session.expiresAt) {
843
+ session.status = "expired";
844
+ session.abortController.abort();
845
+ }
846
+ }
847
+ }
848
+ };
849
+ const authSessionManager = new AuthSessionManager();
850
+
693
851
  //#endregion
694
852
  //#region src/routes/admin-api/route.ts
695
853
  const ADMIN_TOKEN = process.env.ADMIN_TOKEN?.trim() || void 0;
@@ -1166,6 +1324,7 @@ adminApiRoutes.use("*", async (c, next) => {
1166
1324
  } }, decision.status);
1167
1325
  await next();
1168
1326
  });
1327
+ authSessionManager.start();
1169
1328
  adminApiRoutes.get("/meta", (c) => {
1170
1329
  const store = getRequestHistoryStore();
1171
1330
  return c.json(store.meta());
@@ -1395,6 +1554,115 @@ adminApiRoutes.get("/requests/:requestId", (c) => {
1395
1554
  const item = getRequestHistoryStore().getByRequestId(requestId);
1396
1555
  return c.json({ item });
1397
1556
  });
1557
+ adminApiRoutes.post("/accounts/auth/start", async (c) => {
1558
+ let payload;
1559
+ try {
1560
+ payload = await c.req.json();
1561
+ } catch {
1562
+ return jsonError(c, 400, {
1563
+ message: "Request body must be valid JSON.",
1564
+ type: "bad_request"
1565
+ });
1566
+ }
1567
+ if (!isPlainObject(payload)) return jsonError(c, 400, {
1568
+ message: "Request body must be an object.",
1569
+ type: "bad_request"
1570
+ });
1571
+ const accountType = payload.accountType;
1572
+ if (!isAccountType(accountType)) return jsonError(c, 400, {
1573
+ message: "accountType must be one of: individual, business, enterprise",
1574
+ type: "bad_request"
1575
+ });
1576
+ const enterpriseDomainRaw = payload.enterpriseDomain;
1577
+ let enterpriseDomain;
1578
+ if (accountType === "enterprise" && typeof enterpriseDomainRaw === "string") enterpriseDomain = enterpriseDomainRaw.trim();
1579
+ if (accountType === "enterprise" && !enterpriseDomain) return jsonError(c, 400, {
1580
+ message: "enterpriseDomain is required for enterprise accounts.",
1581
+ type: "bad_request"
1582
+ });
1583
+ try {
1584
+ const result = await authSessionManager.startAuth({
1585
+ accountType,
1586
+ enterpriseDomain
1587
+ });
1588
+ return c.json(result);
1589
+ } catch (error) {
1590
+ return jsonError(c, 500, {
1591
+ message: `Failed to start auth: ${error instanceof Error ? error.message : String(error)}`,
1592
+ type: "internal_error"
1593
+ });
1594
+ }
1595
+ });
1596
+ adminApiRoutes.get("/accounts/auth/status/:sessionId", (c) => {
1597
+ const sessionId = c.req.param("sessionId");
1598
+ const status = authSessionManager.getStatus(sessionId);
1599
+ if (!status) return jsonError(c, 404, {
1600
+ message: "Session not found.",
1601
+ type: "not_found"
1602
+ });
1603
+ return c.json(status);
1604
+ });
1605
+ adminApiRoutes.post("/accounts/auth/cancel/:sessionId", (c) => {
1606
+ const sessionId = c.req.param("sessionId");
1607
+ if (!authSessionManager.cancel(sessionId)) return jsonError(c, 404, {
1608
+ message: "Session not found.",
1609
+ type: "not_found"
1610
+ });
1611
+ return c.json({ cancelled: true });
1612
+ });
1613
+ adminApiRoutes.delete("/accounts/:id", async (c) => {
1614
+ const accountId = c.req.param("id");
1615
+ try {
1616
+ if (!(await listAccountsFromRegistry()).some((a) => a.id === accountId)) return jsonError(c, 404, {
1617
+ message: "Account not found.",
1618
+ type: "not_found"
1619
+ });
1620
+ await removeAccountFromRegistry(accountId);
1621
+ try {
1622
+ await removeAccountToken(accountId);
1623
+ } catch (error) {
1624
+ console.error(`Account ${accountId} deleted but token cleanup failed.`, error);
1625
+ }
1626
+ return c.json({
1627
+ deleted: true,
1628
+ accountId
1629
+ });
1630
+ } catch (error) {
1631
+ return jsonError(c, 500, {
1632
+ message: `Failed to delete account: ${error instanceof Error ? error.message : String(error)}`,
1633
+ type: "internal_error"
1634
+ });
1635
+ }
1636
+ });
1637
+ adminApiRoutes.post("/accounts/:id/reauth", async (c) => {
1638
+ const accountId = c.req.param("id");
1639
+ try {
1640
+ const account = (await listAccountsFromRegistry()).find((a) => a.id === accountId);
1641
+ if (!account) return jsonError(c, 404, {
1642
+ message: "Account not found.",
1643
+ type: "not_found"
1644
+ });
1645
+ const { oauthApp } = getCurrentIdentityEnvironment();
1646
+ const resolvedEnterpriseDomain = (await getAccountClientIdentityByLoginAndApp(accountId, oauthApp))?.enterpriseDomain;
1647
+ let enterpriseDomain;
1648
+ if (resolvedEnterpriseDomain && resolvedEnterpriseDomain !== DEFAULT_IDENTITY_ENTERPRISE_DOMAIN) enterpriseDomain = resolvedEnterpriseDomain;
1649
+ if (account.accountType === "enterprise" && !enterpriseDomain) return jsonError(c, 400, {
1650
+ message: "Cannot re-authenticate enterprise account: enterprise domain could not be resolved from stored identity.",
1651
+ type: "bad_request"
1652
+ });
1653
+ const result = await authSessionManager.startAuth({
1654
+ accountType: account.accountType,
1655
+ enterpriseDomain,
1656
+ reauthAccountId: accountId
1657
+ });
1658
+ return c.json(result);
1659
+ } catch (error) {
1660
+ return jsonError(c, 500, {
1661
+ message: `Failed to start reauth: ${error instanceof Error ? error.message : String(error)}`,
1662
+ type: "internal_error"
1663
+ });
1664
+ }
1665
+ });
1398
1666
 
1399
1667
  //#endregion
1400
1668
  //#region src/routes/admin/route.ts
@@ -2053,11 +2321,15 @@ function computeDiff(before, after) {
2053
2321
  }
2054
2322
  function toAccountContext(account) {
2055
2323
  return {
2324
+ accountLogin: account.accountLogin,
2056
2325
  githubToken: account.githubToken,
2057
2326
  copilotToken: account.copilotToken,
2058
2327
  ...account.copilotApiUrl !== void 0 ? { copilotApiUrl: account.copilotApiUrl } : {},
2059
2328
  accountType: account.accountType,
2060
- vsCodeVersion: account.vsCodeVersion
2329
+ vsCodeVersion: account.vsCodeVersion,
2330
+ clientDeviceId: account.clientDeviceId,
2331
+ clientMachineId: account.clientMachineId,
2332
+ clientSessionId: account.clientSessionId
2061
2333
  };
2062
2334
  }
2063
2335
  function extractErrorDetails(error) {
@@ -2082,6 +2354,9 @@ const FLUSH_INTERVAL_MS = 1e3;
2082
2354
  const MAX_BUFFER_SIZE = 100;
2083
2355
  const logStreams = /* @__PURE__ */ new Map();
2084
2356
  const logBuffers = /* @__PURE__ */ new Map();
2357
+ let runtimeInitialized = false;
2358
+ let flushInterval;
2359
+ let cleanupInterval;
2085
2360
  const ensureLogDirectory = () => {
2086
2361
  if (!fs$1.existsSync(LOG_DIR)) fs$1.mkdirSync(LOG_DIR, { recursive: true });
2087
2362
  };
@@ -2112,17 +2387,8 @@ const sanitizeName = (name) => {
2112
2387
  const normalized = name.toLowerCase().replaceAll(/[^a-z0-9]+/g, "-").replaceAll(/^-+|-+$/g, "");
2113
2388
  return normalized === "" ? "handler" : normalized;
2114
2389
  };
2115
- const getLogStream = (filePath) => {
2116
- let stream = logStreams.get(filePath);
2117
- if (!stream || stream.destroyed) {
2118
- stream = fs$1.createWriteStream(filePath, { flags: "a" });
2119
- logStreams.set(filePath, stream);
2120
- stream.on("error", (error) => {
2121
- console.warn("Log stream error", error);
2122
- logStreams.delete(filePath);
2123
- });
2124
- }
2125
- return stream;
2390
+ const maybeUnref = (timer) => {
2391
+ timer.unref();
2126
2392
  };
2127
2393
  const flushBuffer = (filePath) => {
2128
2394
  const buffer = logBuffers.get(filePath);
@@ -2137,6 +2403,52 @@ const flushBuffer = (filePath) => {
2137
2403
  const flushAllBuffers = () => {
2138
2404
  for (const filePath of logBuffers.keys()) flushBuffer(filePath);
2139
2405
  };
2406
+ const cleanup = () => {
2407
+ if (flushInterval) {
2408
+ clearInterval(flushInterval);
2409
+ flushInterval = void 0;
2410
+ }
2411
+ if (cleanupInterval) {
2412
+ clearInterval(cleanupInterval);
2413
+ cleanupInterval = void 0;
2414
+ }
2415
+ flushAllBuffers();
2416
+ for (const stream of logStreams.values()) stream.end();
2417
+ logStreams.clear();
2418
+ logBuffers.clear();
2419
+ };
2420
+ const initializeLoggerRuntime = () => {
2421
+ if (runtimeInitialized) return;
2422
+ runtimeInitialized = true;
2423
+ ensureLogDirectory();
2424
+ cleanupOldLogs();
2425
+ flushInterval = setInterval(flushAllBuffers, FLUSH_INTERVAL_MS);
2426
+ maybeUnref(flushInterval);
2427
+ cleanupInterval = setInterval(cleanupOldLogs, CLEANUP_INTERVAL_MS);
2428
+ maybeUnref(cleanupInterval);
2429
+ process.once("exit", cleanup);
2430
+ process.once("SIGINT", () => {
2431
+ cleanup();
2432
+ process.exit(0);
2433
+ });
2434
+ process.once("SIGTERM", () => {
2435
+ cleanup();
2436
+ process.exit(0);
2437
+ });
2438
+ };
2439
+ const getLogStream = (filePath) => {
2440
+ initializeLoggerRuntime();
2441
+ let stream = logStreams.get(filePath);
2442
+ if (!stream || stream.destroyed) {
2443
+ stream = fs$1.createWriteStream(filePath, { flags: "a" });
2444
+ logStreams.set(filePath, stream);
2445
+ stream.on("error", (error) => {
2446
+ console.warn("Log stream error", error);
2447
+ logStreams.delete(filePath);
2448
+ });
2449
+ }
2450
+ return stream;
2451
+ };
2140
2452
  const appendLine = (filePath, line) => {
2141
2453
  let buffer = logBuffers.get(filePath);
2142
2454
  if (!buffer) {
@@ -2146,35 +2458,23 @@ const appendLine = (filePath, line) => {
2146
2458
  buffer.push(line);
2147
2459
  if (buffer.length >= MAX_BUFFER_SIZE) flushBuffer(filePath);
2148
2460
  };
2149
- setInterval(flushAllBuffers, FLUSH_INTERVAL_MS);
2150
- const cleanup = () => {
2151
- flushAllBuffers();
2152
- for (const stream of logStreams.values()) stream.end();
2153
- logStreams.clear();
2154
- logBuffers.clear();
2461
+ const debugLazy = (logger$7, factory) => {
2462
+ if (!state.verbose) return;
2463
+ logger$7.debug(...factory());
2464
+ };
2465
+ const debugJson = (logger$7, label, value) => {
2466
+ debugLazy(logger$7, () => [label, JSON.stringify(value)]);
2467
+ };
2468
+ const debugJsonTail = (logger$7, label, { value, tailLength = 400 }) => {
2469
+ debugLazy(logger$7, () => [label, JSON.stringify(value).slice(-tailLength)]);
2155
2470
  };
2156
- process.on("exit", cleanup);
2157
- process.on("SIGINT", () => {
2158
- cleanup();
2159
- process.exit(0);
2160
- });
2161
- process.on("SIGTERM", () => {
2162
- cleanup();
2163
- process.exit(0);
2164
- });
2165
- let lastCleanup = 0;
2166
2471
  const createHandlerLogger = (name) => {
2167
- ensureLogDirectory();
2168
2472
  const sanitizedName = sanitizeName(name);
2169
2473
  const instance = consola.withTag(name);
2170
2474
  if (state.verbose) instance.level = 5;
2171
2475
  instance.setReporters([]);
2172
2476
  instance.addReporter({ log(logObj) {
2173
- ensureLogDirectory();
2174
- if (Date.now() - lastCleanup > CLEANUP_INTERVAL_MS) {
2175
- cleanupOldLogs();
2176
- lastCleanup = Date.now();
2177
- }
2477
+ initializeLoggerRuntime();
2178
2478
  const traceId = requestContext.getStore()?.traceId;
2179
2479
  const date = logObj.date;
2180
2480
  const dateKey = date.toLocaleDateString("sv-SE");
@@ -2504,7 +2804,10 @@ async function handleCompletion$1(c) {
2504
2804
  reason: "MODEL_NOT_SUPPORTED"
2505
2805
  });
2506
2806
  }
2507
- logger$6.debug("Request payload:", JSON.stringify(payload).slice(-400));
2807
+ debugJsonTail(logger$6, "Request payload:", {
2808
+ value: payload,
2809
+ tailLength: 400
2810
+ });
2508
2811
  const upstreamRequestId = generateRequestIdFromPayload(payload, normalizedPromptCacheKey);
2509
2812
  const selection = await accountsManager.selectAccountForRequest([{
2510
2813
  modelId: clientModel,
@@ -2637,7 +2940,7 @@ function applyDefaultMaxTokens(payload, selectedModel) {
2637
2940
  ...payload,
2638
2941
  max_tokens: selectedModel.capabilities.limits.max_output_tokens
2639
2942
  };
2640
- logger$6.debug("Set max_tokens to:", JSON.stringify(updated.max_tokens));
2943
+ debugJson(logger$6, "Set max_tokens to:", updated.max_tokens);
2641
2944
  return updated;
2642
2945
  }
2643
2946
  async function handleStreamingRequest(params) {
@@ -2723,7 +3026,7 @@ async function handleNonStreamingUpstreamResponse(params) {
2723
3026
  let errorMessage;
2724
3027
  const finishedAtMs = Date.now();
2725
3028
  try {
2726
- logger$6.debug("Non-streaming response:", JSON.stringify(response));
3029
+ debugJson(logger$6, "Non-streaming response:", response);
2727
3030
  return c.json(response);
2728
3031
  } catch (error) {
2729
3032
  const details = extractErrorDetails(error);
@@ -2773,7 +3076,7 @@ async function streamChatCompletionsAndLog$1(params) {
2773
3076
  if (ttfbMs === void 0) ttfbMs = Date.now() - request.startedAtMs;
2774
3077
  const usage = await extractUsageFromChunk(chunk);
2775
3078
  if (usage) lastUsage = usage;
2776
- logger$6.debug("Streaming chunk:", JSON.stringify(chunk));
3079
+ debugJson(logger$6, "Streaming chunk:", chunk);
2777
3080
  await stream.writeSSE(chunk);
2778
3081
  }
2779
3082
  } catch (error) {
@@ -2845,7 +3148,7 @@ async function handleNonStreamingRequest(params) {
2845
3148
  });
2846
3149
  }
2847
3150
  usage = normalizeChatCompletionsUsage(response.usage);
2848
- logger$6.debug("Non-streaming response:", JSON.stringify(response));
3151
+ debugJson(logger$6, "Non-streaming response:", response);
2849
3152
  return c.json(response);
2850
3153
  } catch (error) {
2851
3154
  finishedAtMs = Date.now();
@@ -3111,43 +3414,72 @@ const _normalizeSdkModelId = (sdkModelId) => {
3111
3414
  };
3112
3415
 
3113
3416
  //#endregion
3114
- //#region src/routes/messages/utils.ts
3115
- function mapOpenAIStopReasonToAnthropic(finishReason) {
3116
- if (finishReason === null) return null;
3117
- return {
3118
- stop: "end_turn",
3119
- length: "max_tokens",
3120
- tool_calls: "tool_use",
3121
- content_filter: "end_turn"
3122
- }[finishReason];
3123
- }
3124
- const mergeContentWithText = (toolResult, textBlock) => {
3125
- if (typeof toolResult.content === "string") return {
3126
- ...toolResult,
3127
- content: `${toolResult.content}\n\n${textBlock.text}`
3417
+ //#region src/routes/messages/preprocess.ts
3418
+ const compactSystemPromptStart = "You are a helpful AI assistant tasked with summarizing conversations";
3419
+ const compactTextOnlyGuard = "CRITICAL: Respond with TEXT ONLY. Do NOT call any tools.";
3420
+ const compactSummaryPromptStart = "Your task is to create a detailed summary of the conversation so far";
3421
+ const compactMessageSections = ["Pending Tasks:", "Current Work:"];
3422
+ const TOOL_REFERENCE_TURN_BOUNDARY = "Tool loaded.";
3423
+ const getAnthropicEffortForModel = (model) => {
3424
+ const reasoningEffort = getReasoningEffortForModel(model);
3425
+ if (reasoningEffort === "xhigh") return "max";
3426
+ if (reasoningEffort === "none" || reasoningEffort === "minimal") return "low";
3427
+ return reasoningEffort;
3428
+ };
3429
+ const getCompactCandidateText = (message) => {
3430
+ if (message.role !== "user") return "";
3431
+ if (typeof message.content === "string") return message.content;
3432
+ return message.content.filter((block) => block.type === "text").map((block) => block.text.startsWith("<system-reminder>") ? "" : block.text).filter((text) => text.length > 0).join("\n\n");
3433
+ };
3434
+ const isCompactMessage = (lastMessage) => {
3435
+ const text = getCompactCandidateText(lastMessage);
3436
+ if (!text) return false;
3437
+ return text.includes(compactTextOnlyGuard) && text.includes(compactSummaryPromptStart) && compactMessageSections.some((section) => text.includes(section));
3438
+ };
3439
+ const isCompactRequest = (anthropicPayload) => {
3440
+ const lastMessage = anthropicPayload.messages.at(-1);
3441
+ if (lastMessage && isCompactMessage(lastMessage)) return true;
3442
+ const system = anthropicPayload.system;
3443
+ if (typeof system === "string") return system.startsWith(compactSystemPromptStart);
3444
+ if (!Array.isArray(system)) return false;
3445
+ return system.some((msg) => typeof msg.text === "string" && msg.text.startsWith(compactSystemPromptStart));
3446
+ };
3447
+ const mergeContentWithText = (tr, textBlock) => {
3448
+ if (typeof tr.content === "string") return {
3449
+ ...tr,
3450
+ content: `${tr.content}\n\n${textBlock.text}`
3128
3451
  };
3452
+ if (hasToolRef(tr)) return tr;
3129
3453
  return {
3130
- ...toolResult,
3131
- content: [...toolResult.content, textBlock]
3454
+ ...tr,
3455
+ content: [...tr.content, textBlock]
3132
3456
  };
3133
3457
  };
3134
- const mergeContentWithTexts = (toolResult, textBlocks) => {
3135
- if (typeof toolResult.content === "string") {
3458
+ const mergeContentWithTexts = (tr, textBlocks) => {
3459
+ if (typeof tr.content === "string") {
3136
3460
  const appendedTexts = textBlocks.map((tb) => tb.text).join("\n\n");
3137
3461
  return {
3138
- ...toolResult,
3139
- content: `${toolResult.content}\n\n${appendedTexts}`
3462
+ ...tr,
3463
+ content: `${tr.content}\n\n${appendedTexts}`
3140
3464
  };
3141
3465
  }
3466
+ if (hasToolRef(tr)) return tr;
3142
3467
  return {
3143
- ...toolResult,
3144
- content: [...toolResult.content, ...textBlocks]
3468
+ ...tr,
3469
+ content: [...tr.content, ...textBlocks]
3145
3470
  };
3146
3471
  };
3147
3472
  const mergeToolResult = (toolResults, textBlocks) => {
3148
- if (toolResults.length === textBlocks.length) return toolResults.map((toolResult, index) => mergeContentWithText(toolResult, textBlocks[index]));
3473
+ if (toolResults.length === textBlocks.length) return toolResults.map((tr, i) => mergeContentWithText(tr, textBlocks[i]));
3149
3474
  const lastIndex = toolResults.length - 1;
3150
- return toolResults.map((toolResult, index) => index === lastIndex ? mergeContentWithTexts(toolResult, textBlocks) : toolResult);
3475
+ return toolResults.map((tr, i) => i === lastIndex ? mergeContentWithTexts(tr, textBlocks) : tr);
3476
+ };
3477
+ const stripToolReferenceTurnBoundary = (anthropicPayload) => {
3478
+ for (const msg of anthropicPayload.messages) {
3479
+ if (msg.role !== "user" || !Array.isArray(msg.content)) continue;
3480
+ if (!msg.content.some((block) => block.type === "tool_result" && hasToolRef(block))) continue;
3481
+ msg.content = msg.content.filter((block) => block.type !== "text" || block.text.trim() !== TOOL_REFERENCE_TURN_BOUNDARY);
3482
+ }
3151
3483
  };
3152
3484
  const mergeToolResultForClaude = (anthropicPayload) => {
3153
3485
  for (const msg of anthropicPayload.messages) {
@@ -3165,6 +3497,9 @@ const mergeToolResultForClaude = (anthropicPayload) => {
3165
3497
  msg.content = mergeToolResult(toolResults, textBlocks);
3166
3498
  }
3167
3499
  };
3500
+ const hasToolRef = (block) => {
3501
+ return Array.isArray(block.content) && block.content.some((c) => c.type === "tool_reference");
3502
+ };
3168
3503
  const stripUnsupportedCacheControl = (block) => {
3169
3504
  const cacheControl = block.cache_control;
3170
3505
  if (!cacheControl || typeof cacheControl !== "object" || Array.isArray(cacheControl)) return;
@@ -3181,9 +3516,9 @@ const stripTextBlockCacheControl = (block) => {
3181
3516
  if (record.type !== "text") return;
3182
3517
  stripUnsupportedCacheControl(record);
3183
3518
  };
3184
- const stripCacheControl = (anthropicPayload) => {
3185
- if (Array.isArray(anthropicPayload.system)) for (const block of anthropicPayload.system) stripTextBlockCacheControl(block);
3186
- for (const msg of anthropicPayload.messages) {
3519
+ const stripCacheControl = (payload) => {
3520
+ if (Array.isArray(payload.system)) for (const block of payload.system) stripTextBlockCacheControl(block);
3521
+ for (const msg of payload.messages) {
3187
3522
  if (!Array.isArray(msg.content)) continue;
3188
3523
  for (const block of msg.content) {
3189
3524
  stripTextBlockCacheControl(block);
@@ -3191,6 +3526,34 @@ const stripCacheControl = (anthropicPayload) => {
3191
3526
  }
3192
3527
  }
3193
3528
  };
3529
+ const filterAssistantThinkingBlocks = (payload) => {
3530
+ for (const msg of payload.messages) if (msg.role === "assistant" && Array.isArray(msg.content)) msg.content = msg.content.filter((block) => {
3531
+ if (block.type !== "thinking") return true;
3532
+ return block.thinking && block.thinking !== "Thinking..." && block.signature && !block.signature.includes("@");
3533
+ });
3534
+ };
3535
+ const prepareMessagesApiPayload = (payload, selectedModel) => {
3536
+ stripCacheControl(payload);
3537
+ filterAssistantThinkingBlocks(payload);
3538
+ const toolChoice = payload.tool_choice;
3539
+ const disableThink = toolChoice?.type === "any" || toolChoice?.type === "tool";
3540
+ if (selectedModel?.capabilities.supports.adaptive_thinking && !disableThink) {
3541
+ payload.thinking = { type: "adaptive" };
3542
+ payload.output_config = { effort: getAnthropicEffortForModel(payload.model) };
3543
+ }
3544
+ };
3545
+
3546
+ //#endregion
3547
+ //#region src/routes/messages/utils.ts
3548
+ function mapOpenAIStopReasonToAnthropic(finishReason) {
3549
+ if (finishReason === null) return null;
3550
+ return {
3551
+ stop: "end_turn",
3552
+ length: "max_tokens",
3553
+ tool_calls: "tool_use",
3554
+ content_filter: "end_turn"
3555
+ }[finishReason];
3556
+ }
3194
3557
  const estimateInputTokens = async (payload, selectedModel, logger$7) => {
3195
3558
  try {
3196
3559
  return (await getTokenCount(payload, selectedModel)).input;
@@ -3255,28 +3618,6 @@ const maybeBlockOriginalModelName = (context) => {
3255
3618
  }
3256
3619
  });
3257
3620
  };
3258
- const compactSystemPromptStart = "You are a helpful AI assistant tasked with summarizing conversations";
3259
- const compactTextOnlyGuard = "CRITICAL: Respond with TEXT ONLY. Do NOT call any tools.";
3260
- const compactSummaryPromptStart = "Your task is to create a detailed summary of the conversation so far";
3261
- const compactMessageSections = ["Pending Tasks:", "Current Work:"];
3262
- const getCompactCandidateText = (message) => {
3263
- if (message.role !== "user") return "";
3264
- if (typeof message.content === "string") return message.content;
3265
- return message.content.filter((block) => block.type === "text").map((block) => block.text.startsWith("<system-reminder>") ? "" : block.text).filter((text) => text.length > 0).join("\n\n");
3266
- };
3267
- const isCompactMessage = (lastMessage) => {
3268
- const text = getCompactCandidateText(lastMessage);
3269
- if (!text) return false;
3270
- return text.includes(compactTextOnlyGuard) && text.includes(compactSummaryPromptStart) && compactMessageSections.some((section) => text.includes(section));
3271
- };
3272
- const isCompactRequest = (anthropicPayload) => {
3273
- const lastMessage = anthropicPayload.messages.at(-1);
3274
- if (lastMessage && isCompactMessage(lastMessage)) return true;
3275
- const system = anthropicPayload.system;
3276
- if (typeof system === "string" && system.startsWith(compactSystemPromptStart)) return true;
3277
- if (Array.isArray(system) && system.some((msg) => typeof msg.text === "string" && msg.text.startsWith(compactSystemPromptStart))) return true;
3278
- return false;
3279
- };
3280
3621
 
3281
3622
  //#endregion
3282
3623
  //#region src/routes/messages/non-stream-translation.ts
@@ -3382,7 +3723,6 @@ function handleAssistantMessage(message, modelId) {
3382
3723
  function mapContent(content) {
3383
3724
  if (typeof content === "string") return content;
3384
3725
  if (!Array.isArray(content)) return null;
3385
- if (!content.some((block) => block.type === "image")) return content.filter((block) => block.type === "text").map((block) => block.text).join("\n\n");
3386
3726
  const contentParts = [];
3387
3727
  for (const block of content) switch (block.type) {
3388
3728
  case "text":
@@ -3397,6 +3737,12 @@ function mapContent(content) {
3397
3737
  image_url: { url: `data:${block.source.media_type};base64,${block.source.data}` }
3398
3738
  });
3399
3739
  break;
3740
+ case "tool_reference":
3741
+ contentParts.push({
3742
+ type: "text",
3743
+ text: `Tool ${block.tool_name} loaded`
3744
+ });
3745
+ break;
3400
3746
  }
3401
3747
  return contentParts;
3402
3748
  }
@@ -4009,6 +4355,9 @@ const convertToolResultContent = (content) => {
4009
4355
  case "image":
4010
4356
  result.push(createImageContent(block));
4011
4357
  break;
4358
+ case "tool_reference":
4359
+ result.push(createTextContent(`Tool ${block.tool_name} loaded`));
4360
+ break;
4012
4361
  default: break;
4013
4362
  }
4014
4363
  return result;
@@ -4450,7 +4799,7 @@ const extractFunctionCallDetails = (rawEvent) => {
4450
4799
  //#region src/routes/responses/utils.ts
4451
4800
  const getResponsesRequestOptions = (payload) => {
4452
4801
  return {
4453
- vision: hasVisionInput(payload),
4802
+ vision: hasVisionInput$1(payload),
4454
4803
  initiator: hasAgentInitiator(payload) ? "agent" : "user"
4455
4804
  };
4456
4805
  };
@@ -4465,7 +4814,7 @@ const isAgentRole = (item) => {
4465
4814
  if (!("role" in item) || !item.role) return true;
4466
4815
  return (typeof item.role === "string" ? item.role.toLowerCase() : "") === "assistant";
4467
4816
  };
4468
- const hasVisionInput = (payload) => {
4817
+ const hasVisionInput$1 = (payload) => {
4469
4818
  return getPayloadItems(payload).some((item) => containsVisionContent(item));
4470
4819
  };
4471
4820
  const resolveResponsesCompactThreshold = (maxPromptTokens) => {
@@ -4542,19 +4891,33 @@ const buildAnthropicBetaHeader = (anthropicBetaHeader, thinking) => {
4542
4891
  }
4543
4892
  if (thinking?.budget_tokens && !isAdaptiveThinking) return INTERLEAVED_THINKING_BETA;
4544
4893
  };
4545
- const createMessages = async (payload, account, options) => {
4546
- const ctx = account ?? accountFromState();
4547
- if (!ctx.copilotToken) throw new Error("Copilot token not found");
4548
- const enableVision = payload.messages.some((message) => Array.isArray(message.content) && message.content.some((block) => block.type === "image"));
4549
- const initiator = options?.initiator ?? getMessagesInitiator(payload);
4894
+ const hasVisionInput = (payload) => payload.messages.some((message) => Array.isArray(message.content) && message.content.some((block) => block.type === "image" || block.type === "tool_result" && Array.isArray(block.content) && block.content.some((inner) => inner.type === "image")));
4895
+ const shouldUseMessageProxyHeaders = (payload) => {
4896
+ const { safetyIdentifier, sessionId } = parseUserIdMetadata(payload.metadata?.user_id);
4897
+ return Boolean(safetyIdentifier && sessionId);
4898
+ };
4899
+ const buildMessagesHeaders = ({ ctx, enableVision, initiator, options, payload }) => {
4550
4900
  const headers = {
4551
4901
  ...copilotHeaders(ctx, enableVision, options?.upstreamRequestId),
4552
4902
  "x-initiator": options?.subagentMarker ? "agent" : initiator
4553
4903
  };
4554
4904
  prepareInteractionHeaders(options?.sessionId, Boolean(options?.subagentMarker), headers);
4555
4905
  prepareForCompact(headers, options?.isCompact);
4906
+ if (shouldUseMessageProxyHeaders(payload)) prepareMessageProxyHeaders(headers);
4556
4907
  const anthropicBeta = buildAnthropicBetaHeader(options?.anthropicBetaHeader, payload.thinking);
4557
4908
  if (anthropicBeta) headers["anthropic-beta"] = anthropicBeta;
4909
+ return headers;
4910
+ };
4911
+ const createMessages = async (payload, account, options) => {
4912
+ const ctx = account ?? accountFromState();
4913
+ if (!ctx.copilotToken) throw new Error("Copilot token not found");
4914
+ const headers = buildMessagesHeaders({
4915
+ ctx,
4916
+ enableVision: hasVisionInput(payload),
4917
+ initiator: options?.initiator ?? getMessagesInitiator(payload),
4918
+ options,
4919
+ payload
4920
+ });
4558
4921
  const response = await fetch(`${copilotBaseUrl(ctx)}/v1/messages`, {
4559
4922
  method: "POST",
4560
4923
  headers,
@@ -4829,7 +5192,7 @@ function closeThinkingBlockIfOpen(state$1, events$1) {
4829
5192
  //#region src/routes/messages/subagent-marker.ts
4830
5193
  const subagentMarkerPrefix = "__SUBAGENT_MARKER__";
4831
5194
  const parseSubagentMarkerFromFirstUser = (payload) => {
4832
- const firstUserMessage = payload.messages.find((msg) => msg.role === "user");
5195
+ const firstUserMessage = payload.messages.find((msg) => msg.role === "user" && Array.isArray(msg.content));
4833
5196
  if (!firstUserMessage || !Array.isArray(firstUserMessage.content)) return null;
4834
5197
  for (const block of firstUserMessage.content) {
4835
5198
  if (block.type !== "text") continue;
@@ -4886,10 +5249,10 @@ async function handleCompletion(c) {
4886
5249
  const { ip: clientIp, source: clientIpSource } = getClientIpInfo(c);
4887
5250
  const userAgent = c.req.header("user-agent") ?? void 0;
4888
5251
  const anthropicPayload = await c.req.json();
4889
- logger$5.debug("Anthropic request payload:", JSON.stringify(anthropicPayload));
5252
+ debugJson(logger$5, "Anthropic request payload:", anthropicPayload);
4890
5253
  const subagentMarker = parseSubagentMarkerFromFirstUser(anthropicPayload);
4891
5254
  const initiatorOverride = subagentMarker ? "agent" : void 0;
4892
- if (subagentMarker) logger$5.debug("Detected Subagent marker:", JSON.stringify(subagentMarker));
5255
+ if (subagentMarker) debugJson(logger$5, "Detected Subagent marker:", subagentMarker);
4893
5256
  const sessionId = getRootSessionId(anthropicPayload, c);
4894
5257
  logger$5.debug("Extracted session ID:", sessionId);
4895
5258
  const anthropicBeta = c.req.header("anthropic-beta");
@@ -4898,7 +5261,10 @@ async function handleCompletion(c) {
4898
5261
  if (isCompact) {
4899
5262
  logger$5.debug("Is compact request:", isCompact);
4900
5263
  if (shouldCompactUseSmallModel()) anthropicPayload.model = getSmallModel();
4901
- } else mergeToolResultForClaude(anthropicPayload);
5264
+ } else {
5265
+ stripToolReferenceTurnBoundary(anthropicPayload);
5266
+ mergeToolResultForClaude(anthropicPayload);
5267
+ }
4902
5268
  const upstreamRequestId = generateRequestIdFromPayload(anthropicPayload, sessionId);
4903
5269
  logger$5.debug("Generated request ID:", upstreamRequestId);
4904
5270
  const clientModel = anthropicPayload.model;
@@ -5028,7 +5394,7 @@ async function handleCompletion(c) {
5028
5394
  }
5029
5395
  const handleWithChatCompletions = async (params) => {
5030
5396
  const { c, openAIPayload, initiatorOverride, subagentMarker, sessionId, selectedModel, instr, isCompact } = params;
5031
- logger$5.debug("Translated OpenAI request payload:", JSON.stringify(openAIPayload));
5397
+ debugJson(logger$5, "Translated OpenAI request payload:", openAIPayload);
5032
5398
  const ctx = toAccountContext(instr.account);
5033
5399
  const initiator = initiatorOverride ?? getChatInitiator(openAIPayload.messages);
5034
5400
  instr.initiator = initiator;
@@ -5075,7 +5441,7 @@ const handleWithResponsesApi = async (params) => {
5075
5441
  const responsesPayload = translateAnthropicMessagesToResponsesPayload(anthropicPayload, selectedModel.id);
5076
5442
  applyResponsesApiContextManagement(responsesPayload, selectedModel.capabilities.limits.max_prompt_tokens);
5077
5443
  compactInputByLatestCompaction(responsesPayload);
5078
- logger$5.debug("Translated Responses payload:", JSON.stringify(responsesPayload));
5444
+ debugJson(logger$5, "Translated Responses payload:", responsesPayload);
5079
5445
  const { vision, initiator } = getResponsesRequestOptions(responsesPayload);
5080
5446
  const resolvedInitiator = initiatorOverride ?? initiator;
5081
5447
  const ctx = toAccountContext(instr.account);
@@ -5189,7 +5555,7 @@ async function handleChatCompletionsNonStreaming(params) {
5189
5555
  try {
5190
5556
  logger$5.debug("Non-streaming response from Copilot:", JSON.stringify(response));
5191
5557
  const anthropicResponse = translateToAnthropic(response);
5192
- logger$5.debug("Translated Anthropic response:", JSON.stringify(anthropicResponse));
5558
+ debugJson(logger$5, "Translated Anthropic response:", anthropicResponse);
5193
5559
  return c.json(anthropicResponse);
5194
5560
  } catch (error) {
5195
5561
  const details = extractErrorDetails(error);
@@ -5311,7 +5677,7 @@ async function handleResponsesNonStreaming(params) {
5311
5677
  usage = extractResponsesUsageFromResult(result);
5312
5678
  logger$5.debug("Non-streaming Responses result:", JSON.stringify(result).slice(-400));
5313
5679
  const anthropicResponse = translateResponsesResultToAnthropic(result);
5314
- logger$5.debug("Translated Anthropic response:", JSON.stringify(anthropicResponse));
5680
+ debugJson(logger$5, "Translated Anthropic response:", anthropicResponse);
5315
5681
  return c.json(anthropicResponse);
5316
5682
  } catch (error) {
5317
5683
  const details = extractErrorDetails(error);
@@ -5542,20 +5908,8 @@ async function streamMessagesAndLog(params) {
5542
5908
  }
5543
5909
  const handleWithMessagesApi = async (params) => {
5544
5910
  const { c, anthropicPayload, anthropicBetaHeader, initiatorOverride, subagentMarker, sessionId, instr, selectedModel, isCompact } = params;
5545
- stripCacheControl(anthropicPayload);
5546
- for (const msg of anthropicPayload.messages) if (msg.role === "assistant" && Array.isArray(msg.content)) msg.content = msg.content.filter((block) => {
5547
- if (block.type !== "thinking") return true;
5548
- return block.thinking && block.thinking !== "Thinking..." && block.signature && !block.signature.includes("@");
5549
- });
5550
- const toolChoice = anthropicPayload.tool_choice;
5551
- if (toolChoice?.type === "any" || toolChoice?.type === "tool") {
5552
- delete anthropicPayload.thinking;
5553
- delete anthropicPayload.output_config;
5554
- } else if (selectedModel.capabilities.supports.adaptive_thinking) {
5555
- anthropicPayload.thinking = { type: "adaptive" };
5556
- anthropicPayload.output_config = { effort: getAnthropicEffortForModel(anthropicPayload.model) };
5557
- }
5558
- logger$5.debug("Translated Messages payload:", JSON.stringify(anthropicPayload));
5911
+ prepareMessagesApiPayload(anthropicPayload, selectedModel);
5912
+ debugJson(logger$5, "Translated Messages payload:", anthropicPayload);
5559
5913
  const ctx = toAccountContext(instr.account);
5560
5914
  const initiator = initiatorOverride ?? getMessagesInitiator(anthropicPayload);
5561
5915
  instr.initiator = initiator;
@@ -5593,12 +5947,6 @@ const handleWithMessagesApi = async (params) => {
5593
5947
  };
5594
5948
  const isNonStreaming = (response) => Object.hasOwn(response, "choices");
5595
5949
  const isAsyncIterable$1 = (value) => Boolean(value) && typeof value[Symbol.asyncIterator] === "function";
5596
- const getAnthropicEffortForModel = (model) => {
5597
- const reasoningEffort = getReasoningEffortForModel(model);
5598
- if (reasoningEffort === "xhigh") return "max";
5599
- if (reasoningEffort === "none" || reasoningEffort === "minimal") return "low";
5600
- return reasoningEffort;
5601
- };
5602
5950
 
5603
5951
  //#endregion
5604
5952
  //#region src/routes/messages/route.ts
@@ -5779,10 +6127,10 @@ async function handleProviderMessages(c) {
5779
6127
  payload.temperature ??= modelConfig?.temperature;
5780
6128
  payload.top_p ??= modelConfig?.topP;
5781
6129
  payload.top_k ??= modelConfig?.topK;
5782
- logger$3.debug("provider.messages.request", JSON.stringify({
6130
+ debugJson(logger$3, "provider.messages.request", {
5783
6131
  payload,
5784
6132
  provider
5785
- }));
6133
+ });
5786
6134
  const upstreamResponse = await forwardProviderMessages(providerConfig, payload, c.req.raw.headers);
5787
6135
  if (!upstreamResponse.ok) {
5788
6136
  logger$3.error("Failed to create responses", upstreamResponse);
@@ -5825,7 +6173,7 @@ async function handleProviderMessages(c) {
5825
6173
  }
5826
6174
  const jsonBody = await upstreamResponse.json();
5827
6175
  adjustInputTokens(providerConfig, jsonBody.usage);
5828
- logger$3.debug("provider.messages.no_stream result:", JSON.stringify(jsonBody));
6176
+ debugJson(logger$3, "provider.messages.no_stream result:", jsonBody);
5829
6177
  return c.json(jsonBody);
5830
6178
  } catch (error) {
5831
6179
  logger$3.error("provider.messages.error", {
@@ -5838,7 +6186,7 @@ async function handleProviderMessages(c) {
5838
6186
  const adjustInputTokens = (providerConfig, usage) => {
5839
6187
  if (!providerConfig.adjustInputTokens || !usage) return;
5840
6188
  usage.input_tokens = Math.max(0, (usage.input_tokens ?? 0) - (usage.cache_read_input_tokens ?? 0) - (usage.cache_creation_input_tokens ?? 0));
5841
- logger$3.debug("provider.messages.adjusted_usage:", JSON.stringify(usage));
6189
+ debugJson(logger$3, "provider.messages.adjusted_usage:", usage);
5842
6190
  };
5843
6191
 
5844
6192
  //#endregion
@@ -5933,7 +6281,7 @@ const handleResponses = async (c) => {
5933
6281
  const request = buildRequestContext(c);
5934
6282
  const payload = await c.req.json();
5935
6283
  const clientModel = payload.model;
5936
- logger$1.debug("Responses request payload:", JSON.stringify(payload));
6284
+ debugJson(logger$1, "Responses request payload:", payload);
5937
6285
  if (!isResponsesApiWebSearchEnabled()) removeWebSearchTool(payload);
5938
6286
  compactInputByLatestCompaction(payload);
5939
6287
  const streamRequested = Boolean(payload.stream);
@@ -6181,7 +6529,10 @@ async function handleNonStreamingUpstreamResult(params) {
6181
6529
  let errorMessage;
6182
6530
  const finishedAtMs = Date.now();
6183
6531
  try {
6184
- logger$1.debug("Forwarding native Responses result:", JSON.stringify(result).slice(-400));
6532
+ debugJsonTail(logger$1, "Forwarding native Responses result:", {
6533
+ value: result,
6534
+ tailLength: 400
6535
+ });
6185
6536
  return c.json(result);
6186
6537
  } catch (error) {
6187
6538
  const details = extractErrorDetails(error);
@@ -6233,7 +6584,7 @@ async function streamResponsesAndLog(params) {
6233
6584
  const processedData = fixStreamIds(data ?? "", event, idTracker);
6234
6585
  const usage = extractUsageFromChunkData(processedData);
6235
6586
  if (usage) lastUsage = usage;
6236
- logger$1.debug("Responses stream chunk:", JSON.stringify(chunk));
6587
+ debugJson(logger$1, "Responses stream chunk:", chunk);
6237
6588
  await stream.writeSSE({
6238
6589
  id,
6239
6590
  event,
@@ -6297,7 +6648,10 @@ async function handleNonStreamingResponses(params) {
6297
6648
  if (streamResponse) return streamResponse;
6298
6649
  const result = response;
6299
6650
  usage = extractResponsesUsageFromResult(result);
6300
- logger$1.debug("Forwarding native Responses result:", JSON.stringify(result).slice(-400));
6651
+ debugJsonTail(logger$1, "Forwarding native Responses result:", {
6652
+ value: result,
6653
+ tailLength: 400
6654
+ });
6301
6655
  return c.json(result);
6302
6656
  } catch (error) {
6303
6657
  finishedAtMs = Date.now();
@@ -6344,6 +6698,7 @@ function handleUnexpectedResponsesStream(c, response) {
6344
6698
  for await (const chunk of response) {
6345
6699
  const { id, event, data } = getStreamChunkFields(chunk);
6346
6700
  const processedData = fixStreamIds(data ?? "", event, idTracker);
6701
+ debugJson(logger$1, "Responses stream chunk:", chunk);
6347
6702
  await stream.writeSSE({
6348
6703
  id,
6349
6704
  event,
@@ -6476,4 +6831,4 @@ server.route("/:provider/v1/models", providerModelRoutes);
6476
6831
 
6477
6832
  //#endregion
6478
6833
  export { server };
6479
- //# sourceMappingURL=server-D9M_wFyO.js.map
6834
+ //# sourceMappingURL=server-CuXJhEMC.js.map