github-router 0.3.269 → 0.3.271

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 (38) hide show
  1. package/dist/{attribution-settings-B1txv_Lk.js → attribution-settings-DLRQEKpU.js} +3 -3
  2. package/dist/{attribution-settings-B1txv_Lk.js.map → attribution-settings-DLRQEKpU.js.map} +1 -1
  3. package/dist/{auth-r-my7efo.js → auth-DIFbHOu0.js} +2 -2
  4. package/dist/{auth-r-my7efo.js.map → auth-DIFbHOu0.js.map} +1 -1
  5. package/dist/browser-ext/manifest.json +1 -1
  6. package/dist/{check-usage-CZr2ZkG0.js → check-usage-DfnrR-d_.js} +3 -3
  7. package/dist/{check-usage-CZr2ZkG0.js.map → check-usage-DfnrR-d_.js.map} +1 -1
  8. package/dist/{claude-BjNY0J6e.js → claude-BpQVQE0T.js} +7 -7
  9. package/dist/{claude-BjNY0J6e.js.map → claude-BpQVQE0T.js.map} +1 -1
  10. package/dist/{codex-CoRWpkHL.js → codex-CGMiGJy1.js} +5 -5
  11. package/dist/{codex-CoRWpkHL.js.map → codex-CGMiGJy1.js.map} +1 -1
  12. package/dist/engine-DUJyXWZn.js +2 -0
  13. package/dist/{gate-discovery-D-7oua8b.js → gate-discovery-BBA7cV1D.js} +2 -2
  14. package/dist/{gate-discovery-D-7oua8b.js.map → gate-discovery-BBA7cV1D.js.map} +1 -1
  15. package/dist/{get-copilot-usage-CFEpeA7E.js → get-copilot-usage-Ds09xSmH.js} +2 -2
  16. package/dist/{get-copilot-usage-CFEpeA7E.js.map → get-copilot-usage-Ds09xSmH.js.map} +1 -1
  17. package/dist/{internal-stop-hook-Db5o9RcZ.js → internal-stop-hook-CO2NDmGL.js} +2 -2
  18. package/dist/{internal-stop-hook-Db5o9RcZ.js.map → internal-stop-hook-CO2NDmGL.js.map} +1 -1
  19. package/dist/main.js +8 -8
  20. package/dist/{models-CJLt4XjP.js → models-BFQUp0ov.js} +2 -2
  21. package/dist/{models-CJLt4XjP.js.map → models-BFQUp0ov.js.map} +1 -1
  22. package/dist/{peer-mcp-personas-DSbBlgFt.js → peer-mcp-personas-CN8xaXcV.js} +377 -101
  23. package/dist/peer-mcp-personas-CN8xaXcV.js.map +1 -0
  24. package/dist/{provision-CA-xwnFu.js → provision-CiPjSx7J.js} +2 -2
  25. package/dist/{provision-CA-xwnFu.js.map → provision-CiPjSx7J.js.map} +1 -1
  26. package/dist/{serve-DHny4ewF.js → serve-CpTMr5D9.js} +6 -6
  27. package/dist/{serve-DHny4ewF.js.map → serve-CpTMr5D9.js.map} +1 -1
  28. package/dist/{server-setup-Dd293T1O.js → server-setup-B02Myghc.js} +285 -99
  29. package/dist/server-setup-B02Myghc.js.map +1 -0
  30. package/dist/{start-P2rmHBkL.js → start-CIV9eXVb.js} +3 -3
  31. package/dist/{start-P2rmHBkL.js.map → start-CIV9eXVb.js.map} +1 -1
  32. package/dist/{token-C_q95GF7.js → token-iaSGp76k.js} +303 -143
  33. package/dist/token-iaSGp76k.js.map +1 -0
  34. package/package.json +1 -1
  35. package/dist/engine-DpVC7HRL.js +0 -2
  36. package/dist/peer-mcp-personas-DSbBlgFt.js.map +0 -1
  37. package/dist/server-setup-Dd293T1O.js.map +0 -1
  38. package/dist/token-C_q95GF7.js.map +0 -1
@@ -1,15 +1,15 @@
1
- import { A as searchWeb, B as readIteratorWithTimeout, Dt as toolbeltPathOverride, F as isAdvisorRequested, H as handleMcpDelete, I as buildAnthropicErrorEvent, It as withOneMSuffix, L as buildOpenAIErrorEvent, Lt as withInstallLock, M as ADVISOR_TOOL_INSTRUCTIONS, Mt as UPSTREAM_FETCH_TIMEOUT_MS, N as buildAdvisorStream, Nt as UPSTREAM_INACTIVITY_TIMEOUT_MS, P as injectAdvisorTool, Pt as generateRandomPort, R as isControllerClosedError, U as handleMcpPost, V as relayAnthropicStream, W as agentToolsEnabled, at as countTokens, ct as assembleResponsesPayload, dt as createResponses, ft as createChatCompletions, ht as parseJsonOrDiagnose, it as shimDefaultsToXhigh, j as ADVISOR_INTERNAL_TOOL_NAME, lt as resolveMcpToolTimeoutMs, mt as readResponseBodyCapped, ot as createMessages, pt as MAX_RESPONSE_BODY_BYTES, r as assertMcpToolSurfaceConsistent, st as getTokenCount, ut as pickEndpoint, w as toolbeltEnabled, z as logStreamError } from "./peer-mcp-personas-DSbBlgFt.js";
1
+ import { A as searchWeb, B as buildAnthropicErrorEvent, Bt as withOneMSuffix, F as isAdvisorRequested, G as relayAnthropicStream, H as isControllerClosedError, I as formatThinkingRepairDecline, It as UPSTREAM_FETCH_TIMEOUT_MS, J as agentToolsEnabled, K as handleMcpDelete, L as rememberThinkingHistoryRepair, Lt as UPSTREAM_INACTIVITY_TIMEOUT_MS, M as ADVISOR_TOOL_INSTRUCTIONS, N as buildAdvisorStream, P as injectAdvisorTool, R as repairKnownThinkingHistory, Rt as generateRandomPort, U as logStreamError, V as buildOpenAIErrorEvent, Vt as withInstallLock, W as readIteratorWithTimeout, _t as MAX_RESPONSE_BODY_BYTES, ct as shimDefaultsToXhigh, dt as getTokenCount, ft as assembleResponsesPayload, gt as createChatCompletions, ht as createResponses, j as ADVISOR_INTERNAL_TOOL_NAME, jt as toolbeltPathOverride, lt as countTokens, mt as pickEndpoint, pt as resolveMcpToolTimeoutMs, q as handleMcpPost, r as assertMcpToolSurfaceConsistent, ut as createMessages, vt as readResponseBodyCapped, w as toolbeltEnabled, yt as parseJsonOrDiagnose, z as repairRejectedThinkingHistory } from "./peer-mcp-personas-CN8xaXcV.js";
2
2
  import { t as getPackageVersion } from "./version-_Q1WpsQp.js";
3
3
  import { i as ensurePaths, t as PATHS } from "./paths-Bg1_DWhi.js";
4
- import { C as copilotHeaders, O as state, S as copilotBaseUrl, a as cacheCopilotVersion, c as filterBetaHeader, d as resolveModel, f as sleep, g as fetchWithTransientRetry, i as tryRefreshAndRetry, l as isNullish, n as setupGitHubAgentToken, o as cacheModels, r as setupGitHubToken, s as cacheVSCodeVersion, t as setupCopilotToken, v as HTTPError, y as forwardError } from "./token-C_q95GF7.js";
5
- import { t as getCopilotUsage } from "./get-copilot-usage-CFEpeA7E.js";
4
+ import { A as state, T as copilotHeaders, _ as forwardError, a as cacheCopilotVersion, c as filterBetaHeader, d as resolveModel, f as sleep, g as HTTPError, i as tryRefreshAndRetry, l as isNullish, n as setupGitHubAgentToken, o as cacheModels, r as setupGitHubToken, s as cacheVSCodeVersion, t as setupCopilotToken, w as copilotBaseUrl, y as fetchWithTransientRetry } from "./token-iaSGp76k.js";
5
+ import { t as getCopilotUsage } from "./get-copilot-usage-Ds09xSmH.js";
6
6
  import { a as resolveExecutable, n as killManagedTree, o as runCommandCapture, r as parseBoolEnv, s as runCommandVoid } from "./exec-y8C_MU8A.js";
7
7
  import consola from "consola";
8
8
  import * as fs$2 from "node:fs";
9
9
  import fs, { existsSync } from "node:fs";
10
10
  import * as nodePath from "node:path";
11
11
  import path from "node:path";
12
- import { randomUUID } from "node:crypto";
12
+ import { createHash, randomUUID } from "node:crypto";
13
13
  import fs$1 from "node:fs/promises";
14
14
  import os from "node:os";
15
15
  import process$1 from "node:process";
@@ -357,9 +357,12 @@ async function runSelfUpdate(opts) {
357
357
  //#region src/lib/file-log-reporter.ts
358
358
  const MAX_LOG_BYTES = 1048576;
359
359
  const DEDUP_MAX = 1e3;
360
+ const DEDUP_WINDOW_MS = 3e5;
360
361
  const ARG_MAX_LEN = 2048;
361
- const DEDUP_KEY_MAX_LEN = 200;
362
+ const ERROR_CAUSE_MAX_DEPTH = 4;
363
+ const ERROR_FIELD_MAX_LEN = 512;
362
364
  const CREDENTIAL_RE = /\b(eyJ[A-Za-z0-9_-]{20,}(?:\.[A-Za-z0-9_-]+){0,2}|gh[opsu]_[A-Za-z0-9_]{20,}|Bearer\s+\S{20,})\b/g;
365
+ const ERROR_BODY_RE = /\b(request\s+body|body)\s*[:=]\s*.*$/i;
363
366
  const ALLOWED_TYPES = /* @__PURE__ */ new Set([
364
367
  "fatal",
365
368
  "error",
@@ -368,25 +371,87 @@ const ALLOWED_TYPES = /* @__PURE__ */ new Set([
368
371
  function sanitize(line) {
369
372
  return line.replace(CREDENTIAL_RE, "[REDACTED]");
370
373
  }
374
+ function errorProperty(error, key) {
375
+ if (typeof error !== "object" && typeof error !== "function" || error === null) return;
376
+ try {
377
+ const value = error[key];
378
+ return typeof value === "string" ? value : void 0;
379
+ } catch {
380
+ return;
381
+ }
382
+ }
383
+ function errorCause(error) {
384
+ if (typeof error !== "object" && typeof error !== "function" || error === null) return;
385
+ try {
386
+ return error.cause;
387
+ } catch {
388
+ return;
389
+ }
390
+ }
391
+ function safeString(value) {
392
+ try {
393
+ return String(value);
394
+ } catch {
395
+ return "[unserializable]";
396
+ }
397
+ }
398
+ function boundErrorField(value) {
399
+ return value.length > ERROR_FIELD_MAX_LEN ? `${value.slice(0, ERROR_FIELD_MAX_LEN)}…` : value;
400
+ }
401
+ function sanitizeErrorMessage(value) {
402
+ return sanitize(value).replace(ERROR_BODY_RE, "$1=[REDACTED]");
403
+ }
404
+ function serializeError(error) {
405
+ const chain = [];
406
+ const seen = /* @__PURE__ */ new Set();
407
+ let current = error;
408
+ for (let depth = 0; current !== void 0 && depth <= ERROR_CAUSE_MAX_DEPTH; depth++) {
409
+ if ((typeof current === "object" || typeof current === "function") && current !== null) {
410
+ if (seen.has(current)) {
411
+ chain.push("[circular cause]");
412
+ break;
413
+ }
414
+ seen.add(current);
415
+ }
416
+ const name = boundErrorField(errorProperty(current, "name") ?? "Error");
417
+ const message = boundErrorField(sanitizeErrorMessage(errorProperty(current, "message") ?? (typeof current === "string" ? current : safeString(current))));
418
+ const rawCode = errorProperty(current, "code");
419
+ const code = rawCode ? boundErrorField(rawCode) : void 0;
420
+ chain.push(`${name}: ${message}${code ? ` code=${code}` : ""}`);
421
+ const cause = errorCause(current);
422
+ if (cause === void 0) break;
423
+ if (depth === ERROR_CAUSE_MAX_DEPTH) {
424
+ chain.push("[cause chain truncated]");
425
+ break;
426
+ }
427
+ current = cause;
428
+ }
429
+ return chain.join(" <- cause: ");
430
+ }
371
431
  function serializeArg(arg) {
372
432
  if (typeof arg === "string") return arg;
373
- if (arg instanceof Error) {
374
- const parts = [arg.message];
375
- if (arg.stack) parts.push(arg.stack);
376
- return parts.join("\n");
377
- }
378
- return String(arg);
433
+ if (arg instanceof Error) return serializeError(arg);
434
+ return safeString(arg);
435
+ }
436
+ function serializeArgs(logObj) {
437
+ return logObj.args.map((arg) => {
438
+ const serialized = sanitize(serializeArg(arg));
439
+ return serialized.length > ARG_MAX_LEN ? `${serialized.slice(0, ARG_MAX_LEN)}…` : serialized;
440
+ });
379
441
  }
380
- function formatLogLine(logObj) {
381
- return sanitize(`${logObj.date.toISOString()} [${(logObj.type ?? "error").toUpperCase()}] ${logObj.args.map((a) => {
382
- const s = serializeArg(a);
383
- return s.length > ARG_MAX_LEN ? s.slice(0, ARG_MAX_LEN) + "…" : s;
384
- }).join(" ").replace(/\r\n|\r|\n/g, "\\n")}\n`);
442
+ function formatLogLine(logObj, suppressed = 0) {
443
+ return `${logObj.date.toISOString()} [${(logObj.type ?? "error").toUpperCase()}] ${serializeArgs(logObj).join(" ").replace(/\r\n|\r|\n/g, "\\n")}${suppressed > 0 ? ` [${suppressed} identical occurrences suppressed]` : ""}\n`;
385
444
  }
386
445
  function makeDedupeKey(logObj) {
387
- const firstArg = logObj.args.length > 0 ? serializeArg(logObj.args[0]) : "";
388
- const key = `${logObj.type}:${firstArg}`;
389
- return key.length > DEDUP_KEY_MAX_LEN ? key.slice(0, DEDUP_KEY_MAX_LEN) : key;
446
+ const hash = createHash("sha256");
447
+ hash.update(logObj.type);
448
+ for (const arg of serializeArgs(logObj)) {
449
+ hash.update("\0");
450
+ hash.update(String(arg.length));
451
+ hash.update(":");
452
+ hash.update(arg);
453
+ }
454
+ return hash.digest("base64url");
390
455
  }
391
456
  /**
392
457
  * Construction-time rotation: rename the log aside if it's already over the
@@ -408,7 +473,7 @@ function rotateAtStartup(filePath) {
408
473
  }
409
474
  var FileLogReporter = class FileLogReporter {
410
475
  filePath;
411
- seen = /* @__PURE__ */ new Set();
476
+ seen = /* @__PURE__ */ new Map();
412
477
  bytesSinceCheck = 0;
413
478
  static ROTATE_CHECK_BYTES = MAX_LOG_BYTES / 2;
414
479
  fd;
@@ -466,10 +531,25 @@ var FileLogReporter = class FileLogReporter {
466
531
  log(logObj, _ctx) {
467
532
  if (!ALLOWED_TYPES.has(logObj.type)) return;
468
533
  const key = makeDedupeKey(logObj);
469
- if (this.seen.has(key)) return;
470
- if (this.seen.size >= DEDUP_MAX) this.seen.clear();
471
- this.seen.add(key);
472
- const line = formatLogLine(logObj);
534
+ const timestamp = logObj.date.getTime();
535
+ const previous = this.seen.get(key);
536
+ let suppressed = 0;
537
+ if (previous) {
538
+ if (timestamp - previous.lastWrittenAt < DEDUP_WINDOW_MS) {
539
+ previous.suppressed++;
540
+ return;
541
+ }
542
+ suppressed = previous.suppressed;
543
+ previous.lastWrittenAt = timestamp;
544
+ previous.suppressed = 0;
545
+ } else {
546
+ if (this.seen.size >= DEDUP_MAX) this.seen.clear();
547
+ this.seen.set(key, {
548
+ lastWrittenAt: timestamp,
549
+ suppressed: 0
550
+ });
551
+ }
552
+ const line = formatLogLine(logObj, suppressed);
473
553
  this.bytesSinceCheck += line.length;
474
554
  if (this.bytesSinceCheck >= FileLogReporter.ROTATE_CHECK_BYTES) {
475
555
  this.rotateIfNeeded();
@@ -1277,7 +1357,7 @@ function collectToolFieldKeys(body) {
1277
1357
  //#endregion
1278
1358
  //#region package.json
1279
1359
  var name = "github-router";
1280
- var version = "0.3.269";
1360
+ var version = "0.3.271";
1281
1361
  //#endregion
1282
1362
  //#region src/lib/approval.ts
1283
1363
  const awaitApproval = async () => {
@@ -1625,12 +1705,21 @@ mcpRoutes.delete("/:group", (c) => {
1625
1705
  * any other input shape, fall back to a synthesized `toolu_advisor_N`
1626
1706
  * id.
1627
1707
  */
1628
- function toCopilotToolUseId(srvId, fallbackIndex) {
1708
+ function toCopilotToolUseId(srvId) {
1629
1709
  if (srvId.startsWith("srvtoolu_")) {
1630
1710
  const suffix = srvId.slice(9);
1631
1711
  if (/^[a-zA-Z0-9_]+$/.test(suffix)) return `toolu_${suffix}`;
1632
1712
  }
1633
- return `toolu_advisor_${fallbackIndex}`;
1713
+ if (/^toolu_[a-zA-Z0-9_]+$/.test(srvId)) return srvId;
1714
+ }
1715
+ function invalidAdvisorHistory(message) {
1716
+ throw new HTTPError("Invalid advisor history", Response.json({
1717
+ type: "error",
1718
+ error: {
1719
+ type: "invalid_request_error",
1720
+ message: `Invalid advisor history: ${message}`
1721
+ }
1722
+ }, { status: 400 }));
1634
1723
  }
1635
1724
  /**
1636
1725
  * Fast-path detector: returns true if the raw body has any chance of
@@ -1645,85 +1734,148 @@ function bodyMightNeedSanitize(rawBody) {
1645
1734
  return rawBody.includes("\"server_tool_use\"") || rawBody.includes("\"advisor_tool_result\"") || /"type":"advisor_\d+"/.test(rawBody);
1646
1735
  }
1647
1736
  /**
1648
- * Translate one assistant turn's content array, splitting at advisor
1649
- * pairs into the multi-message structure Copilot accepts.
1650
- *
1651
- * Input shape (Claude Code stores everything in one assistant turn):
1652
- * [text*, server_tool_use{advisor}, advisor_tool_result, text*, ...]
1653
- *
1654
- * Output: array of {role, content[]} message objects, alternating
1655
- * assistant→user→assistant for each advisor pair encountered.
1737
+ * Translate one client-visible assistant turn into the internal messages
1738
+ * Copilot originally saw. Parallel advisor calls are replayed as one assistant
1739
+ * turn followed by one user turn containing every matching result. Sequential
1740
+ * advisor groups remain separate assistant/user pairs. When a client tool and
1741
+ * advisor coexist, the advisor results and the client's following tool results
1742
+ * are merged into the one immediate user message required by Anthropic.
1656
1743
  */
1657
- function splitAssistantTurnAtAdvisorPairs(originalContent, syntheticIndexRef) {
1744
+ function splitAssistantTurnAtAdvisorPairs(originalMessage, originalContent, followingMessage) {
1658
1745
  const messages = [];
1659
1746
  let currentAssistantContent = [];
1660
1747
  let translated = false;
1748
+ let emittedFirstAssistant = false;
1749
+ const pushAssistant = () => {
1750
+ if (currentAssistantContent.length === 0) invalidAdvisorHistory("advisor pair has no assistant content");
1751
+ messages.push(emittedFirstAssistant ? {
1752
+ role: "assistant",
1753
+ content: currentAssistantContent
1754
+ } : {
1755
+ ...originalMessage,
1756
+ content: currentAssistantContent
1757
+ });
1758
+ emittedFirstAssistant = true;
1759
+ };
1661
1760
  let i = 0;
1662
1761
  while (i < originalContent.length) {
1663
1762
  const block = originalContent[i];
1664
1763
  const b = typeof block === "object" && block !== null ? block : null;
1665
- if (b && b.type === "server_tool_use" && b.name === "__anthropic_advisor".replace(/^__anthropic_/, "")) {
1666
- const stuId = typeof b.id === "string" ? b.id : "";
1667
- const nextBlock = originalContent[i + 1];
1668
- const next = typeof nextBlock === "object" && nextBlock !== null ? nextBlock : null;
1669
- const copilotId = stuId.startsWith("srvtoolu_") ? toCopilotToolUseId(stuId, syntheticIndexRef.value++) : stuId.startsWith("toolu_") && /^toolu_[a-zA-Z0-9_]+$/.test(stuId) ? stuId : `toolu_advisor_${syntheticIndexRef.value++}`;
1670
- currentAssistantContent.push({
1671
- type: "tool_use",
1672
- id: copilotId,
1673
- name: ADVISOR_INTERNAL_TOOL_NAME,
1674
- input: {}
1675
- });
1676
- messages.push({
1677
- role: "assistant",
1678
- content: currentAssistantContent
1679
- });
1764
+ if (b?.type === "server_tool_use" && b.name === "__anthropic_advisor".replace(/^__anthropic_/, "")) {
1765
+ const uses = [];
1766
+ const results = /* @__PURE__ */ new Map();
1767
+ let readingResults = false;
1768
+ while (i < originalContent.length) {
1769
+ const candidate = originalContent[i];
1770
+ const record = typeof candidate === "object" && candidate !== null ? candidate : null;
1771
+ if (record?.type === "server_tool_use" && record.name === "__anthropic_advisor".replace(/^__anthropic_/, "")) {
1772
+ if (readingResults) {
1773
+ if (results.size === uses.length) break;
1774
+ invalidAdvisorHistory("advisor blocks overlap or are ambiguously nested");
1775
+ }
1776
+ const serverId = typeof record.id === "string" ? record.id : "";
1777
+ const copilotId = toCopilotToolUseId(serverId);
1778
+ if (!copilotId) invalidAdvisorHistory("advisor server_tool_use id is not round-trippable");
1779
+ if (uses.some((use) => use.serverId === serverId)) invalidAdvisorHistory("duplicate advisor server_tool_use id");
1780
+ uses.push({
1781
+ serverId,
1782
+ copilotId
1783
+ });
1784
+ currentAssistantContent.push({
1785
+ type: "tool_use",
1786
+ id: copilotId,
1787
+ name: ADVISOR_INTERNAL_TOOL_NAME,
1788
+ input: {}
1789
+ });
1790
+ i++;
1791
+ continue;
1792
+ }
1793
+ if (record?.type === "advisor_tool_result") {
1794
+ readingResults = true;
1795
+ const serverId = typeof record.tool_use_id === "string" ? record.tool_use_id : "";
1796
+ if (!uses.some((use) => use.serverId === serverId)) invalidAdvisorHistory("advisor_tool_result has no matching advisor server_tool_use");
1797
+ if (results.has(serverId)) invalidAdvisorHistory("duplicate advisor_tool_result");
1798
+ const resultContent = record.content;
1799
+ let resultText;
1800
+ if (typeof resultContent === "string") resultText = resultContent;
1801
+ else if (typeof resultContent === "object" && resultContent !== null) {
1802
+ const text = resultContent.text;
1803
+ if (typeof text === "string") resultText = text;
1804
+ }
1805
+ if (resultText === void 0) invalidAdvisorHistory("advisor_tool_result has no replayable text");
1806
+ results.set(serverId, resultText);
1807
+ i++;
1808
+ continue;
1809
+ }
1810
+ if (readingResults) {
1811
+ if (results.size !== uses.length) invalidAdvisorHistory("advisor server_tool_use has no matching advisor_tool_result in the same assistant turn");
1812
+ break;
1813
+ }
1814
+ currentAssistantContent.push(candidate);
1815
+ i++;
1816
+ }
1817
+ if (results.size !== uses.length) invalidAdvisorHistory("advisor server_tool_use has no matching advisor_tool_result in the same assistant turn");
1818
+ const ordinaryToolIds = currentAssistantContent.filter((entry) => typeof entry === "object" && entry !== null && entry.type === "tool_use" && entry.name !== "__anthropic_advisor").map((entry) => entry.id);
1819
+ if (ordinaryToolIds.some((id) => typeof id !== "string" || id.length === 0)) invalidAdvisorHistory("client tool_use has no matchable id");
1820
+ pushAssistant();
1680
1821
  translated = true;
1681
- let resultText = "";
1682
- if (next && next.type === "advisor_tool_result") {
1683
- const c = next.content;
1684
- if (typeof c === "string") resultText = c;
1685
- else if (typeof c === "object" && c !== null) {
1686
- const txt = c.text;
1687
- if (typeof txt === "string") resultText = txt;
1822
+ const advisorResults = uses.map((use) => ({
1823
+ type: "tool_result",
1824
+ tool_use_id: use.copilotId,
1825
+ content: results.get(use.serverId)
1826
+ }));
1827
+ if (ordinaryToolIds.length > 0) {
1828
+ if (i < originalContent.length) invalidAdvisorHistory("assistant continuation followed an unresolved client tool in an advisor turn");
1829
+ if (typeof followingMessage !== "object" || followingMessage === null || followingMessage.role !== "user" || !Array.isArray(followingMessage.content)) invalidAdvisorHistory("mixed advisor/client-tool turn has no immediate user tool results");
1830
+ const following = followingMessage;
1831
+ const followingContent = following.content;
1832
+ let sawNonResult = false;
1833
+ const resultIds = [];
1834
+ for (const entry of followingContent) {
1835
+ const record = typeof entry === "object" && entry !== null ? entry : null;
1836
+ if (record?.type === "tool_result") {
1837
+ if (sawNonResult) invalidAdvisorHistory("tool_result appears after user text/content");
1838
+ if (typeof record.tool_use_id !== "string") invalidAdvisorHistory("tool_result has no matchable tool_use_id");
1839
+ resultIds.push(record.tool_use_id);
1840
+ } else sawNonResult = true;
1688
1841
  }
1689
- i += 2;
1690
- } else {
1691
- resultText = "[Advisor result missing in conversation history.]";
1692
- i += 1;
1842
+ const expected = [...ordinaryToolIds].sort();
1843
+ const actual = [...resultIds].sort();
1844
+ if (expected.length !== actual.length || expected.some((id, index) => id !== actual[index])) invalidAdvisorHistory("mixed advisor/client-tool turn does not have exactly one result for every client tool");
1845
+ messages.push({
1846
+ ...following,
1847
+ content: [...advisorResults, ...followingContent]
1848
+ });
1849
+ return {
1850
+ messages,
1851
+ translated: true,
1852
+ consumedFollowingMessage: true
1853
+ };
1693
1854
  }
1694
1855
  messages.push({
1695
1856
  role: "user",
1696
- content: [{
1697
- type: "tool_result",
1698
- tool_use_id: copilotId,
1699
- content: resultText
1700
- }]
1857
+ content: advisorResults
1701
1858
  });
1702
1859
  currentAssistantContent = [];
1703
1860
  continue;
1704
1861
  }
1705
- if (b && b.type === "advisor_tool_result") {
1706
- translated = true;
1707
- i += 1;
1708
- continue;
1709
- }
1862
+ if (b?.type === "advisor_tool_result") invalidAdvisorHistory("advisor_tool_result has no immediately preceding advisor server_tool_use");
1710
1863
  currentAssistantContent.push(block);
1711
- i += 1;
1864
+ i++;
1712
1865
  }
1713
1866
  if (currentAssistantContent.length > 0) messages.push({
1714
1867
  role: "assistant",
1715
1868
  content: currentAssistantContent
1716
1869
  });
1717
1870
  if (!translated) return {
1718
- messages: [{
1719
- role: "assistant",
1720
- content: originalContent
1721
- }],
1722
- translated: false
1871
+ messages: [originalMessage],
1872
+ translated: false,
1873
+ consumedFollowingMessage: false
1723
1874
  };
1724
1875
  return {
1725
1876
  messages,
1726
- translated: true
1877
+ translated: true,
1878
+ consumedFollowingMessage: false
1727
1879
  };
1728
1880
  }
1729
1881
  function sanitizeAnthropicBody(rawBody) {
@@ -1752,8 +1904,8 @@ function sanitizeAnthropicBody(rawBody) {
1752
1904
  const original = parsed.messages;
1753
1905
  const rebuilt = [];
1754
1906
  let anyTranslated = false;
1755
- const syntheticIndexRef = { value: 0 };
1756
- for (const msg of original) {
1907
+ for (let messageIndex = 0; messageIndex < original.length; messageIndex++) {
1908
+ const msg = original[messageIndex];
1757
1909
  if (typeof msg !== "object" || msg === null || msg.role !== "assistant") {
1758
1910
  rebuilt.push(msg);
1759
1911
  continue;
@@ -1772,10 +1924,11 @@ function sanitizeAnthropicBody(rawBody) {
1772
1924
  rebuilt.push(msg);
1773
1925
  continue;
1774
1926
  }
1775
- const { messages: split, translated } = splitAssistantTurnAtAdvisorPairs(content, syntheticIndexRef);
1927
+ const { messages: split, translated, consumedFollowingMessage } = splitAssistantTurnAtAdvisorPairs(msg, content, original[messageIndex + 1]);
1776
1928
  if (translated) {
1777
1929
  anyTranslated = true;
1778
1930
  for (const m of split) rebuilt.push(m);
1931
+ if (consumedFollowingMessage) messageIndex++;
1779
1932
  } else rebuilt.push(msg);
1780
1933
  }
1781
1934
  if (anyTranslated) {
@@ -3502,6 +3655,7 @@ async function handleNonClaudeChat(c, opts) {
3502
3655
  }
3503
3656
  //#endregion
3504
3657
  //#region src/routes/messages/handler.ts
3658
+ const MAX_THINKING_REPAIR_ATTEMPTS = 5;
3505
3659
  const isWebSearchTool$1 = (tool) => !!tool && typeof tool === "object" && (typeof tool.type === "string" && tool.type.startsWith("web_search") || tool.name === "web_search");
3506
3660
  /**
3507
3661
  * Extract whitelisted beta headers from the incoming request to forward
@@ -3698,15 +3852,33 @@ async function handleCompletion(c) {
3698
3852
  if (modelId) logEndpointMismatch(modelId, "/v1/messages");
3699
3853
  const effectiveBetas = applyDefaultBetas(betaHeaders, resolvedModel ?? originalModel);
3700
3854
  const advisorAborter = advisorEnabled ? new AbortController() : void 0;
3855
+ const requestHeaders = {
3856
+ ...selectedModel?.requestHeaders,
3857
+ ...effectiveBetas
3858
+ };
3859
+ let nativeBody = resolvedBody;
3860
+ const knownThinkingRepair = repairKnownThinkingHistory(nativeBody);
3861
+ if (knownThinkingRepair) {
3862
+ nativeBody = knownThinkingRepair.body;
3863
+ consola.warn(`Reapplying proven thinking-history repair: message=${knownThinkingRepair.messageIndex} removed_blocks=${knownThinkingRepair.removedBlocks}`);
3864
+ }
3701
3865
  let response;
3702
- try {
3703
- response = await createMessages(resolvedBody, {
3704
- ...selectedModel?.requestHeaders,
3705
- ...effectiveBetas
3706
- }, advisorAborter?.signal, true);
3866
+ let acceptedRepair;
3867
+ const repairedMessageIndices = /* @__PURE__ */ new Set();
3868
+ for (let attempt = 0; response === void 0; attempt++) try {
3869
+ response = await createMessages(nativeBody, requestHeaders, advisorAborter?.signal, true);
3870
+ if (acceptedRepair) {
3871
+ rememberThinkingHistoryRepair(acceptedRepair.fingerprint);
3872
+ consola.warn(`Thinking-history repair succeeded: message=${acceptedRepair.messageIndex} removed_blocks=${acceptedRepair.removedBlocks} attempts=${attempt}`);
3873
+ }
3707
3874
  } catch (error) {
3708
- if (error instanceof HTTPError) {
3709
- const errorBody = await error.response.clone().text().catch(() => "");
3875
+ if (!(error instanceof HTTPError)) throw error;
3876
+ const errorBody = await error.response.clone().text().catch(() => "");
3877
+ const outcome = attempt < MAX_THINKING_REPAIR_ATTEMPTS ? repairRejectedThinkingHistory(nativeBody, errorBody) : void 0;
3878
+ const thinkingRepair = outcome?.ok ? outcome.repair : void 0;
3879
+ if (!thinkingRepair || repairedMessageIndices.has(thinkingRepair.messageIndex)) {
3880
+ if (outcome && !outcome.ok) consola.warn(`Thinking-history repair declined: ${formatThinkingRepairDecline(outcome.decline)}`);
3881
+ else if (thinkingRepair) consola.warn(`Thinking-history repair made no progress; upstream re-named message=${thinkingRepair.messageIndex} after it was already repaired`);
3710
3882
  logRequest({
3711
3883
  method: "POST",
3712
3884
  path: c.req.path,
@@ -3715,8 +3887,13 @@ async function handleCompletion(c) {
3715
3887
  status: error.response.status,
3716
3888
  errorBody
3717
3889
  }, selectedModel, startTime);
3890
+ throw error;
3718
3891
  }
3719
- throw error;
3892
+ if (acceptedRepair) rememberThinkingHistoryRepair(acceptedRepair.fingerprint);
3893
+ consola.warn(`Copilot rejected signed thinking history; retrying without rejected historical blocks: message=${thinkingRepair.messageIndex} removed_blocks=${thinkingRepair.removedBlocks} attempt=${attempt + 1}`);
3894
+ nativeBody = thinkingRepair.body;
3895
+ acceptedRepair = thinkingRepair;
3896
+ repairedMessageIndices.add(thinkingRepair.messageIndex);
3720
3897
  }
3721
3898
  const contentType = response.headers.get("content-type") ?? "";
3722
3899
  const clientAcceptsSSE = (c.req.header("accept") ?? "").includes("text/event-stream");
@@ -3751,17 +3928,14 @@ async function handleCompletion(c) {
3751
3928
  if (advisorEnabled && response.body) {
3752
3929
  let parsedBase = {};
3753
3930
  try {
3754
- parsedBase = JSON.parse(resolvedBody);
3931
+ parsedBase = JSON.parse(nativeBody);
3755
3932
  } catch {}
3756
3933
  const initialConversation = Array.isArray(parsedBase.messages) ? parsedBase.messages : [];
3757
3934
  return new Response(buildAdvisorStream({
3758
3935
  firstResponse: response,
3759
3936
  initialConversation,
3760
3937
  baseBody: parsedBase,
3761
- requestHeaders: {
3762
- ...selectedModel?.requestHeaders,
3763
- ...effectiveBetas
3764
- },
3938
+ requestHeaders,
3765
3939
  externalAborter: advisorAborter
3766
3940
  }), {
3767
3941
  status: response.status,
@@ -3821,7 +3995,7 @@ function resolveModelInBody$1(rawBody) {
3821
3995
  const selectedModel = resolvedModel ? state.models?.data.find((m) => m.id === resolvedModel) : void 0;
3822
3996
  if (translateThinking(parsed, selectedModel)) modified = true;
3823
3997
  if (clampOutputConfigEffortInPlace(parsed, selectedModel)) modified = true;
3824
- if (rawBody.includes("\"scope\"") && sanitizeCacheControl$1(parsed)) modified = true;
3998
+ if ((rawBody.includes("\"scope\"") || rawBody.includes("\"cache_control\"") && (rawBody.includes("\"thinking\"") || rawBody.includes("\"redacted_thinking\""))) && sanitizeCacheControl$1(parsed)) modified = true;
3825
3999
  if ((rawBody.includes("\"budget\"") || rawBody.includes("\"output_config\"") || rawBody.includes("\"betas\"") || rawBody.includes("\"eager_input_streaming\"")) && stripAnthropicOnlyFields$1(parsed)) modified = true;
3826
4000
  return {
3827
4001
  body: modified ? JSON.stringify(parsed) : rawBody,
@@ -3903,7 +4077,9 @@ function translateThinking(body, model) {
3903
4077
  return true;
3904
4078
  }
3905
4079
  /**
3906
- * Strip the `scope` field from all `cache_control` objects in the body.
4080
+ * Strip the `scope` field from ordinary `cache_control` objects. Copilot
4081
+ * rejects the entire cache_control object on signed thinking blocks, so remove
4082
+ * that unsigned transport metadata without touching thinking/signature/data.
3907
4083
  * Claude CLI 2.1.88+ sends {"type":"ephemeral","scope":"global"} which
3908
4084
  * Copilot rejects. Mutates the parsed object in place.
3909
4085
  *
@@ -3914,6 +4090,11 @@ function sanitizeCacheControl$1(body) {
3914
4090
  let stripped = false;
3915
4091
  function stripScope(block) {
3916
4092
  const cc = block.cache_control;
4093
+ if (cc && (block.type === "thinking" || block.type === "redacted_thinking")) {
4094
+ delete block.cache_control;
4095
+ stripped = true;
4096
+ return;
4097
+ }
3917
4098
  if (cc?.scope !== void 0) {
3918
4099
  delete cc.scope;
3919
4100
  if (Object.keys(cc).length === 0) delete block.cache_control;
@@ -4120,7 +4301,7 @@ function resolveModelInBody(rawBody) {
4120
4301
  modified = true;
4121
4302
  }
4122
4303
  }
4123
- if (rawBody.includes("\"scope\"") && sanitizeCacheControl(parsed)) modified = true;
4304
+ if ((rawBody.includes("\"scope\"") || rawBody.includes("\"cache_control\"") && (rawBody.includes("\"thinking\"") || rawBody.includes("\"redacted_thinking\""))) && sanitizeCacheControl(parsed)) modified = true;
4124
4305
  if ((rawBody.includes("\"budget\"") || rawBody.includes("\"output_config\"") || rawBody.includes("\"betas\"") || rawBody.includes("\"eager_input_streaming\"")) && stripAnthropicOnlyFields(parsed)) modified = true;
4125
4306
  const resolvedModel = typeof parsed.model === "string" ? parsed.model : originalModel;
4126
4307
  const selectedModel = resolvedModel ? state.models?.data.find((m) => m.id === resolvedModel) : void 0;
@@ -4134,6 +4315,11 @@ function resolveModelInBody(rawBody) {
4134
4315
  function sanitizeCacheControl(body) {
4135
4316
  let stripped = false;
4136
4317
  function stripScope(block) {
4318
+ if (block.cache_control && (block.type === "thinking" || block.type === "redacted_thinking")) {
4319
+ delete block.cache_control;
4320
+ stripped = true;
4321
+ return;
4322
+ }
4137
4323
  if (block.cache_control?.scope !== void 0) {
4138
4324
  delete block.cache_control.scope;
4139
4325
  if (Object.keys(block.cache_control).length === 0) delete block.cache_control;
@@ -5263,4 +5449,4 @@ function getCodexEnvVars(serverUrl) {
5263
5449
  //#endregion
5264
5450
  export { sharedServerArgs as a, listModelsForEndpoint as c, checkClaudeVersion as d, updateClaude as f, setupAndServe as i, enableFileLogging as l, getCodexEnvVars as n, startKeepAwake as o, parseSharedArgs as r, stopKeepAwake as s, getClaudeCodeEnvVars as t, runSelfUpdate as u };
5265
5451
 
5266
- //# sourceMappingURL=server-setup-Dd293T1O.js.map
5452
+ //# sourceMappingURL=server-setup-B02Myghc.js.map