github-router 0.3.270 → 0.3.273
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{attribution-settings-of5gJM5a.js → attribution-settings-4nEQq_tn.js} +3 -3
- package/dist/{attribution-settings-of5gJM5a.js.map → attribution-settings-4nEQq_tn.js.map} +1 -1
- package/dist/{auth-DIFbHOu0.js → auth-3so8RT91.js} +2 -2
- package/dist/{auth-DIFbHOu0.js.map → auth-3so8RT91.js.map} +1 -1
- package/dist/browser-ext/manifest.json +1 -1
- package/dist/{check-usage-DfnrR-d_.js → check-usage-goXyc3qS.js} +3 -3
- package/dist/{check-usage-DfnrR-d_.js.map → check-usage-goXyc3qS.js.map} +1 -1
- package/dist/{claude-BlzCUbVq.js → claude-BNZD-bQN.js} +7 -7
- package/dist/{claude-BlzCUbVq.js.map → claude-BNZD-bQN.js.map} +1 -1
- package/dist/{codex-BaFcXOyg.js → codex-C_MA9uy5.js} +5 -5
- package/dist/{codex-BaFcXOyg.js.map → codex-C_MA9uy5.js.map} +1 -1
- package/dist/engine-CHN8j6BV.js +2 -0
- package/dist/{gate-discovery-AUAjqSpV.js → gate-discovery-DvA4xObh.js} +2 -2
- package/dist/{gate-discovery-AUAjqSpV.js.map → gate-discovery-DvA4xObh.js.map} +1 -1
- package/dist/{get-copilot-usage-Ds09xSmH.js → get-copilot-usage-nZXbvSi8.js} +2 -2
- package/dist/{get-copilot-usage-Ds09xSmH.js.map → get-copilot-usage-nZXbvSi8.js.map} +1 -1
- package/dist/{internal-stop-hook-B1MIwmTR.js → internal-stop-hook-WVgnwt5U.js} +2 -2
- package/dist/{internal-stop-hook-B1MIwmTR.js.map → internal-stop-hook-WVgnwt5U.js.map} +1 -1
- package/dist/main.js +8 -8
- package/dist/{models-BFQUp0ov.js → models-BmGGH6pP.js} +2 -2
- package/dist/{models-BFQUp0ov.js.map → models-BmGGH6pP.js.map} +1 -1
- package/dist/{peer-mcp-personas-pWP3Eyt7.js → peer-mcp-personas-DAZU1OfN.js} +331 -20
- package/dist/peer-mcp-personas-DAZU1OfN.js.map +1 -0
- package/dist/{provision-CsYUVdMT.js → provision-C3UIA1Tf.js} +2 -2
- package/dist/{provision-CsYUVdMT.js.map → provision-C3UIA1Tf.js.map} +1 -1
- package/dist/{serve--c9n9hk4.js → serve-DPgawWWq.js} +6 -6
- package/dist/{serve--c9n9hk4.js.map → serve-DPgawWWq.js.map} +1 -1
- package/dist/{server-setup-BmyWS4WU.js → server-setup-I5KYkuxE.js} +570 -121
- package/dist/server-setup-I5KYkuxE.js.map +1 -0
- package/dist/{start-CXnLBouJ.js → start-CWWqjjwm.js} +3 -3
- package/dist/{start-CXnLBouJ.js.map → start-CWWqjjwm.js.map} +1 -1
- package/dist/{token-iaSGp76k.js → token-Bz7iN8US.js} +74 -6
- package/dist/token-Bz7iN8US.js.map +1 -0
- package/package.json +2 -1
- package/dist/engine-mwIgHJoi.js +0 -2
- package/dist/peer-mcp-personas-pWP3Eyt7.js.map +0 -1
- package/dist/server-setup-BmyWS4WU.js.map +0 -1
- package/dist/token-iaSGp76k.js.map +0 -1
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { t as getPackageVersion } from "./version-_Q1WpsQp.js";
|
|
2
2
|
import { t as PATHS } from "./paths-Bg1_DWhi.js";
|
|
3
|
-
import { A as state, C as GITHUB_GRAPHQL_URL, D as githubAgentGraphQLHeaders, E as copilotVersion, O as githubAgentHeaders, S as GITHUB_API_BASE_URL, T as copilotHeaders, b as sanitizeTransportText, d as resolveModel, f as sleep$2, g as HTTPError, h as isAllowedCopilotHost, i as tryRefreshAndRetry, v as classifyTransportError, w as copilotBaseUrl, x as withTransientRetry, y as fetchWithTransientRetry } from "./token-
|
|
3
|
+
import { A as state, C as GITHUB_GRAPHQL_URL, D as githubAgentGraphQLHeaders, E as copilotVersion, O as githubAgentHeaders, S as GITHUB_API_BASE_URL, T as copilotHeaders, b as sanitizeTransportText, d as resolveModel, f as sleep$2, g as HTTPError, h as isAllowedCopilotHost, i as tryRefreshAndRetry, v as classifyTransportError, w as copilotBaseUrl, x as withTransientRetry, y as fetchWithTransientRetry } from "./token-Bz7iN8US.js";
|
|
4
4
|
import { a as resolveExecutable, c as runManagedExeCapture, i as parseIntEnv, l as spawnTaskkillBestEffort, r as parseBoolEnv } from "./exec-y8C_MU8A.js";
|
|
5
5
|
import { i as registerExitHandlers$1, n as getInstanceUuid, r as recordWorkerRepo, t as WorktreeRegistry } from "./lifecycle-0XrazT05.js";
|
|
6
6
|
import { t as MCP_WORKSPACE_HEADER } from "./mcp-workspace-header-CGJbNeHb.js";
|
|
7
7
|
import { n as ArtifactError, r as applyInsecureTls, t as ArtifactClient } from "./client-CQMfroGV.js";
|
|
8
|
-
import { n as isPidAlive, r as registerColbertExitHandlers, s as trackChild, t as getColbertInstanceUuid } from "./lifecycle-AgNOtFRv.js";
|
|
8
|
+
import { n as isPidAlive$1, r as registerColbertExitHandlers, s as trackChild, t as getColbertInstanceUuid } from "./lifecycle-AgNOtFRv.js";
|
|
9
9
|
import { h as runGateChecks, m as sealedGateIds, p as resolveSealedGate } from "./stop-gate-hook-BqpumJtl.js";
|
|
10
10
|
import { t as liveExec } from "./orchestration-B_Q3ncXI.js";
|
|
11
11
|
import { createRequire } from "node:module";
|
|
@@ -272,6 +272,12 @@ function envInt$1(key, fallback) {
|
|
|
272
272
|
}
|
|
273
273
|
const UPSTREAM_FETCH_TIMEOUT_MS = envInt$1("UPSTREAM_FETCH_TIMEOUT_MS", 0);
|
|
274
274
|
const UPSTREAM_INACTIVITY_TIMEOUT_MS = envInt$1("UPSTREAM_INACTIVITY_TIMEOUT_MS", 3e5);
|
|
275
|
+
function upstreamAllowH2() {
|
|
276
|
+
return process.env.GH_ROUTER_UPSTREAM_ALLOW_H2 === "1";
|
|
277
|
+
}
|
|
278
|
+
function upstreamMaxConnections() {
|
|
279
|
+
return envInt$1("GH_ROUTER_UPSTREAM_MAX_CONNECTIONS", 256);
|
|
280
|
+
}
|
|
275
281
|
//#endregion
|
|
276
282
|
//#region src/lib/toolbelt/path-inject.ts
|
|
277
283
|
/**
|
|
@@ -4966,19 +4972,19 @@ function resolveTierModel(tier) {
|
|
|
4966
4972
|
}
|
|
4967
4973
|
//#endregion
|
|
4968
4974
|
//#region src/lib/first-mate/classifier.ts
|
|
4969
|
-
function isRecord$
|
|
4975
|
+
function isRecord$2(value) {
|
|
4970
4976
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
4971
4977
|
}
|
|
4972
4978
|
function firstMessageContent$1(value) {
|
|
4973
|
-
if (!isRecord$
|
|
4979
|
+
if (!isRecord$2(value) || !Array.isArray(value.choices)) return null;
|
|
4974
4980
|
const first = value.choices[0];
|
|
4975
|
-
if (!isRecord$
|
|
4981
|
+
if (!isRecord$2(first) || !isRecord$2(first.message)) return null;
|
|
4976
4982
|
return typeof first.message.content === "string" ? first.message.content : null;
|
|
4977
4983
|
}
|
|
4978
4984
|
function parseJsonObject(value) {
|
|
4979
4985
|
try {
|
|
4980
4986
|
const parsed = JSON.parse(value);
|
|
4981
|
-
return isRecord$
|
|
4987
|
+
return isRecord$2(parsed) ? parsed : null;
|
|
4982
4988
|
} catch {
|
|
4983
4989
|
return null;
|
|
4984
4990
|
}
|
|
@@ -5048,7 +5054,7 @@ async function classifyPlanReady(logExcerpt) {
|
|
|
5048
5054
|
schemaHint: "{\"planReady\":boolean,\"planExcerpt\":\"<=1200 chars from the completed plan, or empty\",\"confidence\":number}",
|
|
5049
5055
|
maxTokens: 500,
|
|
5050
5056
|
validate(value) {
|
|
5051
|
-
if (!isRecord$
|
|
5057
|
+
if (!isRecord$2(value)) return null;
|
|
5052
5058
|
const planReady = booleanValue$1(value.planReady);
|
|
5053
5059
|
const planExcerpt = stringValue$1(value.planExcerpt);
|
|
5054
5060
|
if (planReady === null || planExcerpt === null) return null;
|
|
@@ -5065,7 +5071,7 @@ async function classifyQuestionAnswerable(question, acceptanceCriteria) {
|
|
|
5065
5071
|
user: `Acceptance criteria:\n${acceptanceCriteria}\n\nAgent question:\n${question}`,
|
|
5066
5072
|
schemaHint: "{\"answerable\":boolean,\"answer\":\"present only when answerable\",\"confidence\":number}",
|
|
5067
5073
|
validate(value) {
|
|
5068
|
-
if (!isRecord$
|
|
5074
|
+
if (!isRecord$2(value)) return null;
|
|
5069
5075
|
const answerable = booleanValue$1(value.answerable);
|
|
5070
5076
|
if (answerable === null) return null;
|
|
5071
5077
|
const answer = stringValue$1(value.answer);
|
|
@@ -5083,7 +5089,7 @@ async function classifyFixAddressed(failureSummary, latestLogExcerpt) {
|
|
|
5083
5089
|
user: `Failure summary:\n${failureSummary}\n\nLatest log excerpt:\n${latestLogExcerpt}`,
|
|
5084
5090
|
schemaHint: "{\"addressed\":boolean,\"confidence\":number}",
|
|
5085
5091
|
validate(value) {
|
|
5086
|
-
if (!isRecord$
|
|
5092
|
+
if (!isRecord$2(value)) return null;
|
|
5087
5093
|
const addressed = booleanValue$1(value.addressed);
|
|
5088
5094
|
return addressed === null ? null : { addressed };
|
|
5089
5095
|
}
|
|
@@ -5095,7 +5101,7 @@ async function classifyStuck(logExcerpt) {
|
|
|
5095
5101
|
user: `Log excerpt:\n${logExcerpt}`,
|
|
5096
5102
|
schemaHint: "{\"stuck\":boolean,\"confidence\":number}",
|
|
5097
5103
|
validate(value) {
|
|
5098
|
-
if (!isRecord$
|
|
5104
|
+
if (!isRecord$2(value)) return null;
|
|
5099
5105
|
const stuck = booleanValue$1(value.stuck);
|
|
5100
5106
|
return stuck === null ? null : { stuck };
|
|
5101
5107
|
}
|
|
@@ -9975,6 +9981,40 @@ const WIN_RENAME_TRANSIENT = /* @__PURE__ */ new Set([
|
|
|
9975
9981
|
"EBUSY"
|
|
9976
9982
|
]);
|
|
9977
9983
|
/**
|
|
9984
|
+
* Owner pid embedded in a `.draining.<pid>.<rand>` or `.claim.<pid>.<rand>`
|
|
9985
|
+
* segment. A file can carry both (a claimed orphan keeps the drain segment), so
|
|
9986
|
+
* the LAST match is the current owner.
|
|
9987
|
+
*/
|
|
9988
|
+
const OWNER_SEGMENT_RE = /\.(?:draining|claim)\.(\d+)\./g;
|
|
9989
|
+
/**
|
|
9990
|
+
* Claims held by a live drainer in THIS process, across instances. Per-instance
|
|
9991
|
+
* `inflight` cannot see a peer instance's claim, and both share our pid, so pid
|
|
9992
|
+
* liveness cannot separate them either. A claim abandoned on a read error is
|
|
9993
|
+
* never added here, which is what keeps it replayable (R3 #4).
|
|
9994
|
+
*/
|
|
9995
|
+
const heldClaims = /* @__PURE__ */ new Set();
|
|
9996
|
+
function ownerPidOf(name) {
|
|
9997
|
+
let pid;
|
|
9998
|
+
for (const match of name.matchAll(OWNER_SEGMENT_RE)) pid = Number(match[1]);
|
|
9999
|
+
return pid !== void 0 && Number.isInteger(pid) && pid > 0 ? pid : void 0;
|
|
10000
|
+
}
|
|
10001
|
+
/**
|
|
10002
|
+
* `process.kill(pid, 0)` probes existence without signalling; `EPERM` means the
|
|
10003
|
+
* process exists but is owned by another user (still alive). Mirrors the copies
|
|
10004
|
+
* in `lib/paths.ts`, `lib/colbert/lifecycle.ts`, and `lib/worker-agent/
|
|
10005
|
+
* lifecycle.ts` — kept local so first-mate takes no dependency on those modules.
|
|
10006
|
+
*/
|
|
10007
|
+
function isPidAlive(pid) {
|
|
10008
|
+
if (!Number.isInteger(pid) || pid <= 0) return false;
|
|
10009
|
+
try {
|
|
10010
|
+
process.kill(pid, 0);
|
|
10011
|
+
return true;
|
|
10012
|
+
} catch (err) {
|
|
10013
|
+
if (err.code === "EPERM") return true;
|
|
10014
|
+
return false;
|
|
10015
|
+
}
|
|
10016
|
+
}
|
|
10017
|
+
/**
|
|
9978
10018
|
* Atomically claim `from` by renaming it to the process-unique `to`.
|
|
9979
10019
|
* Returns `true` if THIS caller won the claim, `false` if a peer already took it
|
|
9980
10020
|
* (source gone). Retries transient Windows sharing violations so two concurrent
|
|
@@ -10070,6 +10110,9 @@ var AnswerInbox = class {
|
|
|
10070
10110
|
if (!name.startsWith(`${base}.draining.`)) continue;
|
|
10071
10111
|
const orphan = path.join(dir, name);
|
|
10072
10112
|
if (this.inflight.has(orphan)) continue;
|
|
10113
|
+
if (heldClaims.has(orphan)) continue;
|
|
10114
|
+
const owner = ownerPidOf(name);
|
|
10115
|
+
if (owner !== void 0 && owner !== process.pid && isPidAlive(owner)) continue;
|
|
10073
10116
|
const claim = `${orphan}.claim.${process.pid}.${randomBytes(4).toString("hex")}`;
|
|
10074
10117
|
if (!await claimByRename(orphan, claim)) continue;
|
|
10075
10118
|
try {
|
|
@@ -10086,11 +10129,15 @@ var AnswerInbox = class {
|
|
|
10086
10129
|
} catch (err) {
|
|
10087
10130
|
if (err.code !== "ENOENT") consola.warn(`first-mate: deferring unreadable inbox claim ${target} for retry:`, err);
|
|
10088
10131
|
}
|
|
10089
|
-
for (const p of claimed)
|
|
10132
|
+
for (const p of claimed) {
|
|
10133
|
+
this.inflight.add(p);
|
|
10134
|
+
heldClaims.add(p);
|
|
10135
|
+
}
|
|
10090
10136
|
const ack = async () => {
|
|
10091
10137
|
for (const p of claimed) {
|
|
10092
10138
|
await fs$1.unlink(p).catch(() => {});
|
|
10093
10139
|
this.inflight.delete(p);
|
|
10140
|
+
heldClaims.delete(p);
|
|
10094
10141
|
}
|
|
10095
10142
|
};
|
|
10096
10143
|
return {
|
|
@@ -11499,7 +11546,7 @@ function parsePackageJson(text) {
|
|
|
11499
11546
|
if (text === void 0) return void 0;
|
|
11500
11547
|
try {
|
|
11501
11548
|
const parsed = JSON.parse(text);
|
|
11502
|
-
if (!isRecord(parsed)) return void 0;
|
|
11549
|
+
if (!isRecord$1(parsed)) return void 0;
|
|
11503
11550
|
return {
|
|
11504
11551
|
scripts: stringRecord(parsed.scripts),
|
|
11505
11552
|
dependencies: stringRecord(parsed.dependencies),
|
|
@@ -11699,11 +11746,11 @@ function buildScaffoldPrBody(reports) {
|
|
|
11699
11746
|
"No factory protocol files are seeded; orchestration remains external to the repository."
|
|
11700
11747
|
].join("\n");
|
|
11701
11748
|
}
|
|
11702
|
-
function isRecord(value) {
|
|
11749
|
+
function isRecord$1(value) {
|
|
11703
11750
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
11704
11751
|
}
|
|
11705
11752
|
function stringRecord(value) {
|
|
11706
|
-
if (!isRecord(value)) return {};
|
|
11753
|
+
if (!isRecord$1(value)) return {};
|
|
11707
11754
|
const result = {};
|
|
11708
11755
|
for (const [key, entry] of Object.entries(value)) if (typeof entry === "string") result[key] = entry;
|
|
11709
11756
|
return result;
|
|
@@ -15779,7 +15826,7 @@ async function freshnessVerdict(workspace) {
|
|
|
15779
15826
|
};
|
|
15780
15827
|
if (meta.status === "building") {
|
|
15781
15828
|
const pid = typeof meta.buildPid === "number" ? meta.buildPid : 0;
|
|
15782
|
-
if (isInitInFlight(workspace) || pid > 0 && isPidAlive(pid)) return {
|
|
15829
|
+
if (isInitInFlight(workspace) || pid > 0 && isPidAlive$1(pid)) return {
|
|
15783
15830
|
verdict: "building",
|
|
15784
15831
|
meta
|
|
15785
15832
|
};
|
|
@@ -27358,7 +27405,6 @@ function classifyNamedStreamError(errName, errMessage) {
|
|
|
27358
27405
|
}
|
|
27359
27406
|
function classifyStreamError(details) {
|
|
27360
27407
|
if (details.name === "AbortError" || details.name === "InactivityTimeout" || details.name === "TimeoutError" || details.name === "timeout_error") return "timeout_error";
|
|
27361
|
-
if (details.classification === "transient") return "overloaded_error";
|
|
27362
27408
|
return "api_error";
|
|
27363
27409
|
}
|
|
27364
27410
|
function formatStreamErrorMessage(details) {
|
|
@@ -27384,6 +27430,255 @@ function logStreamError(routePath, error, bytesRelayed) {
|
|
|
27384
27430
|
};
|
|
27385
27431
|
}
|
|
27386
27432
|
//#endregion
|
|
27433
|
+
//#region src/lib/thinking-history-repair.ts
|
|
27434
|
+
const THINKING_INTEGRITY_ERROR_RES = [/messages\.(\d+)\.content\.(\d+):\s*`thinking` or `redacted_thinking` blocks in the latest assistant message cannot be modified/, /messages\.(\d+)\.content\.(\d+):\s*Invalid `signature` in `thinking` block/];
|
|
27435
|
+
const MAX_REMEMBERED_REPAIRS = 1e3;
|
|
27436
|
+
const OMITTED_THINKING_PLACEHOLDER = "[prior reasoning omitted]";
|
|
27437
|
+
const repairSalt = randomBytes(32);
|
|
27438
|
+
const rememberedRepairs = /* @__PURE__ */ new Set();
|
|
27439
|
+
function declined(reason, detail = {}) {
|
|
27440
|
+
return {
|
|
27441
|
+
ok: false,
|
|
27442
|
+
decline: {
|
|
27443
|
+
reason,
|
|
27444
|
+
...detail
|
|
27445
|
+
}
|
|
27446
|
+
};
|
|
27447
|
+
}
|
|
27448
|
+
/** Render a decline as a single log-safe `key=value` line. */
|
|
27449
|
+
function formatThinkingRepairDecline(decline) {
|
|
27450
|
+
return Object.entries(decline).filter(([, value]) => value !== void 0).map(([key, value]) => `${key}=${String(value)}`).join(" ");
|
|
27451
|
+
}
|
|
27452
|
+
function isRecord(value) {
|
|
27453
|
+
return typeof value === "object" && value !== null;
|
|
27454
|
+
}
|
|
27455
|
+
/** Count signed blocks without hashing — used only to explain a decline. */
|
|
27456
|
+
function countSignedBlocks(content) {
|
|
27457
|
+
return content.filter((block) => isRecord(block) && (block.type === "thinking" || block.type === "redacted_thinking")).length;
|
|
27458
|
+
}
|
|
27459
|
+
function signedBlockFingerprint(_messageIndex, content) {
|
|
27460
|
+
const hash = createHash("sha256");
|
|
27461
|
+
hash.update(repairSalt);
|
|
27462
|
+
let signedBlocks = 0;
|
|
27463
|
+
for (let index = 0; index < content.length; index++) {
|
|
27464
|
+
const block = content[index];
|
|
27465
|
+
if (!isRecord(block)) continue;
|
|
27466
|
+
if (block.type !== "thinking" && block.type !== "redacted_thinking") continue;
|
|
27467
|
+
signedBlocks++;
|
|
27468
|
+
hash.update(String(index));
|
|
27469
|
+
hash.update(String(block.type));
|
|
27470
|
+
if (typeof block.signature === "string") hash.update(block.signature);
|
|
27471
|
+
if (typeof block.data === "string") hash.update(block.data);
|
|
27472
|
+
}
|
|
27473
|
+
return signedBlocks > 0 ? hash.digest("hex") : void 0;
|
|
27474
|
+
}
|
|
27475
|
+
function repairAtArrayIndex(parsed, messageIndex) {
|
|
27476
|
+
if (!Array.isArray(parsed.messages)) return declined("no-messages-array", { messageIndex });
|
|
27477
|
+
const messages = [...parsed.messages];
|
|
27478
|
+
const detail = {
|
|
27479
|
+
messageIndex,
|
|
27480
|
+
messageCount: messages.length
|
|
27481
|
+
};
|
|
27482
|
+
const message = messages[messageIndex];
|
|
27483
|
+
if (!isRecord(message)) return declined("message-missing", detail);
|
|
27484
|
+
if (message.role !== "assistant") return declined("message-not-assistant", {
|
|
27485
|
+
...detail,
|
|
27486
|
+
roleAtIndex: typeof message.role === "string" ? message.role : "unknown"
|
|
27487
|
+
});
|
|
27488
|
+
if (!Array.isArray(message.content)) return declined("content-not-array", {
|
|
27489
|
+
...detail,
|
|
27490
|
+
roleAtIndex: "assistant"
|
|
27491
|
+
});
|
|
27492
|
+
const shape = {
|
|
27493
|
+
...detail,
|
|
27494
|
+
roleAtIndex: "assistant",
|
|
27495
|
+
blocksAtIndex: message.content.length,
|
|
27496
|
+
signedBlocksAtIndex: countSignedBlocks(message.content)
|
|
27497
|
+
};
|
|
27498
|
+
const fingerprint = signedBlockFingerprint(messageIndex, message.content);
|
|
27499
|
+
if (!fingerprint) return declined("no-signed-blocks", shape);
|
|
27500
|
+
const repairedContent = message.content.filter((block) => !isRecord(block) || block.type !== "thinking" && block.type !== "redacted_thinking");
|
|
27501
|
+
const removedBlocks = message.content.length - repairedContent.length;
|
|
27502
|
+
if (removedBlocks === 0) return declined("no-blocks-removed", shape);
|
|
27503
|
+
if (repairedContent.length === 0) repairedContent.push({
|
|
27504
|
+
type: "text",
|
|
27505
|
+
text: OMITTED_THINKING_PLACEHOLDER
|
|
27506
|
+
});
|
|
27507
|
+
messages[messageIndex] = {
|
|
27508
|
+
...message,
|
|
27509
|
+
content: repairedContent
|
|
27510
|
+
};
|
|
27511
|
+
parsed.messages = messages;
|
|
27512
|
+
return {
|
|
27513
|
+
ok: true,
|
|
27514
|
+
repair: {
|
|
27515
|
+
body: JSON.stringify(parsed),
|
|
27516
|
+
fingerprint,
|
|
27517
|
+
messageIndex,
|
|
27518
|
+
removedBlocks
|
|
27519
|
+
}
|
|
27520
|
+
};
|
|
27521
|
+
}
|
|
27522
|
+
/** Roles in order, for a decline log. Roles only, so it carries no content. */
|
|
27523
|
+
function roleSequenceOf(messages) {
|
|
27524
|
+
return messages.map((message) => isRecord(message) && typeof message.role === "string" ? message.role : "unknown").join(",");
|
|
27525
|
+
}
|
|
27526
|
+
/** Elements upstream would not count as a conversation turn. */
|
|
27527
|
+
function isHoistedElement(message) {
|
|
27528
|
+
if (!isRecord(message)) return false;
|
|
27529
|
+
return message.role !== "user" && message.role !== "assistant";
|
|
27530
|
+
}
|
|
27531
|
+
/**
|
|
27532
|
+
* Translate an upstream-reported message index into an index in THIS array,
|
|
27533
|
+
* skipping elements upstream would not have counted.
|
|
27534
|
+
*
|
|
27535
|
+
* Anthropic's Messages schema has no in-array `system` role, yet clients do
|
|
27536
|
+
* send one, and upstream evidently accepts it and drops it before validating —
|
|
27537
|
+
* which shifts every index after it. Returns undefined when nothing is hoisted
|
|
27538
|
+
* (the mapping would be the identity) or when the target does not exist.
|
|
27539
|
+
*/
|
|
27540
|
+
function hoistAdjustedIndex(messages, reportedIndex) {
|
|
27541
|
+
let retained = 0;
|
|
27542
|
+
for (let index = 0; index < messages.length; index++) {
|
|
27543
|
+
if (isHoistedElement(messages[index])) continue;
|
|
27544
|
+
if (retained === reportedIndex) return index === reportedIndex ? void 0 : index;
|
|
27545
|
+
retained++;
|
|
27546
|
+
}
|
|
27547
|
+
}
|
|
27548
|
+
/** True when `content[contentIndex]` is a signed thinking block. */
|
|
27549
|
+
function hasSignedBlockAt(content, contentIndex) {
|
|
27550
|
+
if (!Array.isArray(content)) return false;
|
|
27551
|
+
const block = content[contentIndex];
|
|
27552
|
+
if (!isRecord(block)) return false;
|
|
27553
|
+
return block.type === "thinking" || block.type === "redacted_thinking";
|
|
27554
|
+
}
|
|
27555
|
+
/**
|
|
27556
|
+
* Resolve the message upstream named, then repair it.
|
|
27557
|
+
*
|
|
27558
|
+
* DIRECT INDEX FIRST, hoist-adjusted index only as a fallback. The ordering is
|
|
27559
|
+
* the whole safety argument: every request that repairs correctly today takes
|
|
27560
|
+
* the direct path untouched, and the adjusted path runs only where the code
|
|
27561
|
+
* would otherwise have declined outright. Mapping first would REGRESS a working
|
|
27562
|
+
* case — with `[user, system, assistant]` and upstream naming `messages.2`, the
|
|
27563
|
+
* direct lookup repairs the assistant turn correctly while a retained-role
|
|
27564
|
+
* mapping yields only `[user, assistant]` and runs off the end.
|
|
27565
|
+
*
|
|
27566
|
+
* The fallback is self-validating rather than trusted: it is accepted only if
|
|
27567
|
+
* the block upstream actually named is a signed thinking block at the adjusted
|
|
27568
|
+
* position. If the index shift has some other cause, that check fails and the
|
|
27569
|
+
* original decline stands, so a wrong hypothesis fails closed instead of
|
|
27570
|
+
* stripping blocks from an innocent turn.
|
|
27571
|
+
*/
|
|
27572
|
+
/** True when `index` names an assistant carrying the block upstream reported. */
|
|
27573
|
+
function namesReportedBlock(messages, index, contentIndex) {
|
|
27574
|
+
const message = messages[index];
|
|
27575
|
+
if (!isRecord(message) || message.role !== "assistant") return false;
|
|
27576
|
+
return hasSignedBlockAt(message.content, contentIndex);
|
|
27577
|
+
}
|
|
27578
|
+
/**
|
|
27579
|
+
* Resolve the message upstream named, then repair it.
|
|
27580
|
+
*
|
|
27581
|
+
* When nothing is hoisted, this array and upstream's are indexed alike, so the
|
|
27582
|
+
* reported index is used directly — the identity case, and the overwhelming
|
|
27583
|
+
* majority of traffic, whose behaviour is unchanged.
|
|
27584
|
+
*
|
|
27585
|
+
* When something IS hoisted, the two arrays provably disagree and the reported
|
|
27586
|
+
* index alone cannot say which turn was meant. Both the raw index and the
|
|
27587
|
+
* hoist-adjusted one can land on a signed assistant, and picking the raw one
|
|
27588
|
+
* blind would strip a healthy turn while leaving the corrupt one in place. So
|
|
27589
|
+
* the block index upstream reported is used as the tiebreak: whichever
|
|
27590
|
+
* candidate actually carries a signed block THERE is the one repaired. If both
|
|
27591
|
+
* do, the request is genuinely ambiguous and we decline — the client sees the
|
|
27592
|
+
* same 400 it would have seen anyway, with no innocent turn rewritten.
|
|
27593
|
+
*/
|
|
27594
|
+
function repairMessageAt(parsed, messageIndex, contentIndex) {
|
|
27595
|
+
if (!Array.isArray(parsed.messages)) return repairAtArrayIndex(parsed, messageIndex);
|
|
27596
|
+
const messages = parsed.messages;
|
|
27597
|
+
const hoistedCount = messages.filter((m) => isHoistedElement(m)).length;
|
|
27598
|
+
const mapped = hoistedCount === 0 ? void 0 : hoistAdjustedIndex(messages, messageIndex);
|
|
27599
|
+
const annotate = (outcome, extra = {}) => outcome.ok ? outcome : declined(outcome.decline.reason, {
|
|
27600
|
+
...outcome.decline,
|
|
27601
|
+
hoistedCount,
|
|
27602
|
+
roleSequence: roleSequenceOf(messages),
|
|
27603
|
+
...extra
|
|
27604
|
+
});
|
|
27605
|
+
if (hoistedCount === 0 || contentIndex === void 0 || mapped === void 0) return annotate(repairAtArrayIndex(parsed, messageIndex));
|
|
27606
|
+
const directNames = namesReportedBlock(messages, messageIndex, contentIndex);
|
|
27607
|
+
const mappedNames = namesReportedBlock(messages, mapped, contentIndex);
|
|
27608
|
+
if (directNames && mappedNames) return declined("ambiguous-index", {
|
|
27609
|
+
messageIndex,
|
|
27610
|
+
messageCount: messages.length,
|
|
27611
|
+
hoistedCount,
|
|
27612
|
+
roleSequence: roleSequenceOf(messages),
|
|
27613
|
+
mappedIndex: mapped
|
|
27614
|
+
});
|
|
27615
|
+
if (mappedNames) return annotate(repairAtArrayIndex(parsed, mapped), { mappedIndex: mapped });
|
|
27616
|
+
return annotate(repairAtArrayIndex(parsed, messageIndex), { mappedIndex: mapped });
|
|
27617
|
+
}
|
|
27618
|
+
/**
|
|
27619
|
+
* Build a one-shot repair only for Copilot's known signed-thinking integrity
|
|
27620
|
+
* rejections. The upstream error is the oracle: valid omitted-display thinking
|
|
27621
|
+
* also has an empty `thinking` string, so request shape alone cannot identify a
|
|
27622
|
+
* corrupt signature safely.
|
|
27623
|
+
*
|
|
27624
|
+
* Returns a discriminated outcome so a caller can report WHY a repair was not
|
|
27625
|
+
* applied; a silent decline is what made the original incident undiagnosable.
|
|
27626
|
+
*/
|
|
27627
|
+
function repairRejectedThinkingHistory(rawBody, upstreamErrorText) {
|
|
27628
|
+
const match = THINKING_INTEGRITY_ERROR_RES.map((pattern) => pattern.exec(upstreamErrorText)).find((candidate) => candidate !== null);
|
|
27629
|
+
if (!match) return declined("error-not-recognized");
|
|
27630
|
+
const messageIndex = Number(match[1]);
|
|
27631
|
+
if (!Number.isSafeInteger(messageIndex) || messageIndex < 0) return declined("message-index-invalid", { messageIndex });
|
|
27632
|
+
const parsedContentIndex = Number(match[2]);
|
|
27633
|
+
const contentIndex = Number.isSafeInteger(parsedContentIndex) && parsedContentIndex >= 0 ? parsedContentIndex : void 0;
|
|
27634
|
+
let parsed;
|
|
27635
|
+
try {
|
|
27636
|
+
parsed = JSON.parse(rawBody);
|
|
27637
|
+
} catch {
|
|
27638
|
+
return declined("body-not-json", { messageIndex });
|
|
27639
|
+
}
|
|
27640
|
+
return repairMessageAt(parsed, messageIndex, contentIndex);
|
|
27641
|
+
}
|
|
27642
|
+
/**
|
|
27643
|
+
* Reapply a repair already proven successful in this process. Only salted
|
|
27644
|
+
* digests are retained; no message, thinking, signature, or tool content is
|
|
27645
|
+
* stored.
|
|
27646
|
+
*/
|
|
27647
|
+
function repairKnownThinkingHistory(rawBody) {
|
|
27648
|
+
if (rememberedRepairs.size === 0) return void 0;
|
|
27649
|
+
let parsed;
|
|
27650
|
+
try {
|
|
27651
|
+
parsed = JSON.parse(rawBody);
|
|
27652
|
+
} catch {
|
|
27653
|
+
return;
|
|
27654
|
+
}
|
|
27655
|
+
if (!Array.isArray(parsed.messages)) return void 0;
|
|
27656
|
+
let repaired;
|
|
27657
|
+
let totalRemovedBlocks = 0;
|
|
27658
|
+
for (let index = parsed.messages.length - 1; index >= 0; index--) {
|
|
27659
|
+
const message = parsed.messages[index];
|
|
27660
|
+
if (!isRecord(message) || !Array.isArray(message.content)) continue;
|
|
27661
|
+
const fingerprint = signedBlockFingerprint(index, message.content);
|
|
27662
|
+
if (!fingerprint || !rememberedRepairs.has(fingerprint)) continue;
|
|
27663
|
+
const attempt = repairAtArrayIndex(parsed, index);
|
|
27664
|
+
if (!attempt.ok) continue;
|
|
27665
|
+
totalRemovedBlocks += attempt.repair.removedBlocks;
|
|
27666
|
+
repaired = {
|
|
27667
|
+
...attempt.repair,
|
|
27668
|
+
removedBlocks: totalRemovedBlocks
|
|
27669
|
+
};
|
|
27670
|
+
}
|
|
27671
|
+
return repaired;
|
|
27672
|
+
}
|
|
27673
|
+
function rememberThinkingHistoryRepair(fingerprint) {
|
|
27674
|
+
if (rememberedRepairs.has(fingerprint)) return;
|
|
27675
|
+
if (rememberedRepairs.size >= MAX_REMEMBERED_REPAIRS) {
|
|
27676
|
+
const oldest = rememberedRepairs.values().next().value;
|
|
27677
|
+
if (typeof oldest === "string") rememberedRepairs.delete(oldest);
|
|
27678
|
+
}
|
|
27679
|
+
rememberedRepairs.add(fingerprint);
|
|
27680
|
+
}
|
|
27681
|
+
//#endregion
|
|
27387
27682
|
//#region src/services/advisor/advisor.ts
|
|
27388
27683
|
/**
|
|
27389
27684
|
* Phase I: ADVISOR proxy-side translation.
|
|
@@ -28062,11 +28357,27 @@ function buildAdvisorStream(opts) {
|
|
|
28062
28357
|
}))
|
|
28063
28358
|
});
|
|
28064
28359
|
if (aborter.signal.aborted) return;
|
|
28065
|
-
|
|
28360
|
+
let continuationSend = JSON.stringify({
|
|
28066
28361
|
...opts.baseBody,
|
|
28067
28362
|
messages: conversation,
|
|
28068
28363
|
stream: true
|
|
28069
|
-
})
|
|
28364
|
+
});
|
|
28365
|
+
const knownRepair = repairKnownThinkingHistory(continuationSend);
|
|
28366
|
+
if (knownRepair) continuationSend = knownRepair.body;
|
|
28367
|
+
try {
|
|
28368
|
+
response = await createMessages(continuationSend, opts.requestHeaders, aborter.signal, true);
|
|
28369
|
+
} catch (continuationError) {
|
|
28370
|
+
if (!(continuationError instanceof HTTPError)) throw continuationError;
|
|
28371
|
+
const errorBody = await continuationError.response.clone().text().catch(() => "");
|
|
28372
|
+
const outcome = repairRejectedThinkingHistory(continuationSend, errorBody);
|
|
28373
|
+
if (!outcome.ok) {
|
|
28374
|
+
consola.warn(`Advisor continuation thinking-history repair declined: ${formatThinkingRepairDecline(outcome.decline)}`);
|
|
28375
|
+
throw continuationError;
|
|
28376
|
+
}
|
|
28377
|
+
consola.warn(`Advisor continuation: retrying without rejected thinking blocks: message=${outcome.repair.messageIndex} removed_blocks=${outcome.repair.removedBlocks}`);
|
|
28378
|
+
response = await createMessages(outcome.repair.body, opts.requestHeaders, aborter.signal, true);
|
|
28379
|
+
rememberThinkingHistoryRepair(outcome.repair.fingerprint);
|
|
28380
|
+
}
|
|
28070
28381
|
}
|
|
28071
28382
|
if (aborter.signal.aborted) return;
|
|
28072
28383
|
const finalIndex = nextSyntheticIndex++;
|
|
@@ -34285,6 +34596,6 @@ function enumerateInjectedMcpToolNames(groupKeys, opts = {}) {
|
|
|
34285
34596
|
return [...new Set(names)];
|
|
34286
34597
|
}
|
|
34287
34598
|
//#endregion
|
|
34288
|
-
export {
|
|
34599
|
+
export { browserToolsEnabled as $, searchWeb as A, collapsePathKeys as At, buildAnthropicErrorEvent as B, upstreamAllowH2 as Bt, buildToolbeltAwareness as C, provisionAndIndexColbert as Ct, TOOLBELT_TOOLS$1 as D, CONDENSED_OPERATING_SEQUENCE as Dt, vscodeRipgrepPath as E, warmTreeSitterPool as Et, isAdvisorRequested as F, DEFAULT_PORT as Ft, relayAnthropicStream as G, isControllerClosedError as H, withOneMSuffix as Ht, formatThinkingRepairDecline as I, UPSTREAM_FETCH_TIMEOUT_MS as It, agentToolsEnabled as J, handleMcpDelete as K, rememberThinkingHistoryRepair as L, UPSTREAM_INACTIVITY_TIMEOUT_MS as Lt, ADVISOR_TOOL_INSTRUCTIONS as M, DEFAULT_CLAUDE_MODEL_FALLBACKS as Mt, buildAdvisorStream as N, DEFAULT_CODEX_MODEL as Nt, assetFor as O, DEFINITION_OF_GREATNESS as Ot, injectAdvisorTool as P, DEFAULT_CODEX_MODEL_FALLBACKS as Pt, browserCompoundToolsEnabled as Q, repairKnownThinkingHistory as R, generateRandomPort as Rt, availableToolCommands as S, colbertDegradedWarning as St, toolbeltSkipSet as T, extractZipMember as Tt, logStreamError as U, withInstallLock as Ut, buildOpenAIErrorEvent as V, upstreamMaxConnections as Vt, readIteratorWithTimeout as W, brainstormModel as X, artifactToolsEnabled as Y, browseAgentEnabled as Z, appendPlanReminder as _, MAX_RESPONSE_BODY_BYTES as _t, buildPeerAwarenessSnippet as a, scribeModel as at, runWorkerAgent as b, provisionBrowserAssets as bt, personasFor as c, shimDefaultsToXhigh as ct, EXPLORE_DEFAULT_MODEL as d, getTokenCount as dt, fleetToolsEnabled as et, EXPLORE_DEFAULT_THINKING as f, assembleResponsesPayload as ft, TEST_DEFAULT_MODEL as g, createChatCompletions as gt, REVIEW_DEFAULT_MODEL as h, createResponses as ht, buildAgentPrompt as i, scoutModel as it, ADVISOR_INTERNAL_TOOL_NAME as j, toolbeltPathOverride as jt, satisfiesMinVersion as k, shouldUseInsecureTls as kt, BROWSE_DEFAULT_MODEL as l, countTokens as lt, PLAN_DEFAULT_MODEL as m, pickEndpoint as mt, MCP_GROUPS as n, nativeSubagentModel as nt, buildPeerAwarenessSummary as o, standInToolEnabled as ot, IMPLEMENT_DEFAULT_MODEL as p, resolveMcpToolTimeoutMs as pt, handleMcpPost as q, assertMcpToolSurfaceConsistent as r, reviewerModel as rt, enumerateInjectedMcpToolNames as s, workerToolsEnabled as st, GROUP_META as t, geminiAvailable as tt, DEFAULT_MODEL as u, createMessages as ut, resolveModeDefaults as v, readResponseBodyCapped as vt, toolbeltEnabled as w, extractTarGzMember as wt, buildEnv as x, hasSupportedBrowserInstalled as xt, resolveWorkerRunOpts as y, parseJsonOrDiagnose as yt, repairRejectedThinkingHistory as z, pickClaudeDefault as zt };
|
|
34289
34600
|
|
|
34290
|
-
//# sourceMappingURL=peer-mcp-personas-
|
|
34601
|
+
//# sourceMappingURL=peer-mcp-personas-DAZU1OfN.js.map
|