github-router 0.3.177 → 0.3.202

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
- import { t as PATHS } from "./paths-BZPgxKUl.js";
2
- import { d as runCommandCapture, l as parseBoolEnv, n as isPidAlive, o as trackChild, p as runManagedExeCapture, r as registerColbertExitHandlers, t as getColbertInstanceUuid, u as resolveExecutable } from "./lifecycle-DrDEjx_c.js";
3
- import { i as registerExitHandlers, n as getInstanceUuid, r as recordWorkerRepo, t as WorktreeRegistry } from "./lifecycle-Dvr3pGGG.js";
1
+ import { t as PATHS } from "./paths-BO22pMUb.js";
2
+ import { d as runCommandCapture, l as parseBoolEnv, n as isPidAlive, o as trackChild, p as runManagedExeCapture, r as registerColbertExitHandlers, t as getColbertInstanceUuid, u as resolveExecutable } from "./lifecycle-D-1CYr1Y.js";
3
+ import { i as registerExitHandlers, n as getInstanceUuid, r as recordWorkerRepo, t as WorktreeRegistry } from "./lifecycle-bPdiXjYB.js";
4
4
  import { createRequire } from "node:module";
5
5
  import consola from "consola";
6
6
  import { createHash, randomBytes, randomUUID, timingSafeEqual } from "node:crypto";
@@ -623,6 +623,13 @@ function normalizeModelId$1(id) {
623
623
  * version pinning (a dated catalog id matched at Step 1) always wins.
624
624
  * 6. Return as-is with a warning
625
625
  */
626
+ /**
627
+ * `[1m]`-downgrade warnings we've already emitted this process. `resolveModel`
628
+ * is called many times per launch (env setup, model validation, the banner,
629
+ * and — under `serve` — on every model-picker `/models` poll), so the downgrade
630
+ * notice is deduped to once per model id to avoid log spam.
631
+ */
632
+ const warnedOneMDowngrade = /* @__PURE__ */ new Set();
626
633
  function resolveModel(modelId) {
627
634
  const models = state.models?.data;
628
635
  if (!models) return modelId;
@@ -630,7 +637,10 @@ function resolveModel(modelId) {
630
637
  if (oneMMatch) {
631
638
  const stripped = oneMMatch[1];
632
639
  const resolved = resolveModel(stripped);
633
- if (!/-1m(?:$|-)/.test(resolved)) consola.warn(`Model "${modelId}" requested 1M context but no -1m backend is in Copilot's catalog for this tier/family; downgrading upstream to "${resolved}" (200K). Claude Code's local context accounting will still assume 1M — expect premature auto-compact. Drop the [1m] suffix (or unset CLAUDE_CODE_DISABLE_1M_CONTEXT if you set it) to silence.`);
640
+ if (!/-1m(?:$|-)/.test(resolved) && !warnedOneMDowngrade.has(modelId)) {
641
+ warnedOneMDowngrade.add(modelId);
642
+ consola.warn(`Model "${modelId}" requested 1M context but no -1m backend is in Copilot's catalog for this tier/family; downgrading upstream to "${resolved}" (200K). Claude Code's local context accounting will still assume 1M — expect premature auto-compact. Drop the [1m] suffix (or unset CLAUDE_CODE_DISABLE_1M_CONTEXT if you set it) to silence.`);
643
+ }
634
644
  return resolved;
635
645
  }
636
646
  if (models.some((m) => m.id === modelId)) return modelId;
@@ -1145,6 +1155,25 @@ function collapsePathKeys(env) {
1145
1155
  return env;
1146
1156
  }
1147
1157
 
1158
+ //#endregion
1159
+ //#region src/lib/mcp-workspace-header.ts
1160
+ /** Header the per-session MCP headersHelper emits, carrying the calling Claude
1161
+ * session's working directory. The /mcp handler uses it as the default
1162
+ * `workspace` for repo-scoped tools so a machine-wide `serve` targets the
1163
+ * active repo, not the proxy launch cwd. */
1164
+ const MCP_WORKSPACE_HEADER = "X-GH-Workspace";
1165
+ /** stdout JSON the headersHelper prints; Claude merges it into the connection
1166
+ * headers. `cwd` is the helper's own process cwd = the session's project dir. */
1167
+ function buildWorkspaceHeaderJson(cwd) {
1168
+ return JSON.stringify({ [MCP_WORKSPACE_HEADER]: cwd });
1169
+ }
1170
+ /** Command string Claude runs as the headersHelper. Mirrors
1171
+ * buildPromptSubmitHookCommand's quoting (src/lib/orchestration/prompt-submit-hook.ts). */
1172
+ function buildWorkspaceHeaderHelperCommand(execPath, scriptPath) {
1173
+ const q = (s) => `"${s}"`;
1174
+ return scriptPath && scriptPath !== execPath ? `${q(execPath)} ${q(scriptPath)} internal-workspace-header` : `${q(execPath)} internal-workspace-header`;
1175
+ }
1176
+
1148
1177
  //#endregion
1149
1178
  //#region src/lib/insecure-tls.ts
1150
1179
  const IS_BUN$1 = typeof globalThis.Bun !== "undefined";
@@ -12076,6 +12105,14 @@ var TreeSitterPool = class {
12076
12105
  * entirely and force the in-process path, rather than churning spawn→crash
12077
12106
  * forever. */
12078
12107
  crashCount = 0;
12108
+ workersSpawned = 0;
12109
+ /** Test-only observability for crash/respawn assertions. */
12110
+ __workerLifecycleForTest() {
12111
+ return {
12112
+ crashes: this.crashCount,
12113
+ spawned: this.workersSpawned
12114
+ };
12115
+ }
12079
12116
  queue = [];
12080
12117
  inflight = /* @__PURE__ */ new Map();
12081
12118
  constructor() {
@@ -12123,6 +12160,7 @@ var TreeSitterPool = class {
12123
12160
  let worker;
12124
12161
  try {
12125
12162
  worker = new Worker(this.workerPath);
12163
+ this.workersSpawned += 1;
12126
12164
  } catch (err) {
12127
12165
  consola.debug(`[code_search] tree-sitter worker spawn failed: ${err.message}`);
12128
12166
  resolve(null);
@@ -12225,8 +12263,14 @@ var TreeSitterPool = class {
12225
12263
  if (!job) break;
12226
12264
  pw.busyJobId = job.id;
12227
12265
  this.inflight.set(job.id, job);
12266
+ const injectCrash = _testCrashOnceArmed;
12267
+ const reqToPost = injectCrash ? {
12268
+ ...job.req,
12269
+ testCrash: true
12270
+ } : job.req;
12228
12271
  try {
12229
- pw.worker.postMessage(job.req);
12272
+ pw.worker.postMessage(reqToPost);
12273
+ if (injectCrash) _testCrashOnceArmed = false;
12230
12274
  } catch (err) {
12231
12275
  consola.debug(`[code_search] tree-sitter worker postMessage failed: ${err.message}`);
12232
12276
  this.inflight.delete(job.id);
@@ -12398,6 +12442,7 @@ function resolveWorkerPath() {
12398
12442
  }
12399
12443
  let _pool = null;
12400
12444
  let _shutdownRegistered = false;
12445
+ let _testCrashOnceArmed = false;
12401
12446
  /**
12402
12447
  * The pool is ON by default for real (non-CI) runs and OFF under CI.
12403
12448
  *
@@ -12650,6 +12695,10 @@ const WALL_TIME_MS = 3e4;
12650
12695
  * comfortable headroom for ~5-10 files even on cold cache.
12651
12696
  */
12652
12697
  const STRUCTURAL_BUDGET_MS = 200;
12698
+ let _structuralBudgetTestOverride = null;
12699
+ function structuralBudgetMs() {
12700
+ return _structuralBudgetTestOverride ?? STRUCTURAL_BUDGET_MS;
12701
+ }
12653
12702
  const STRUCTURAL_TOPN_FULL = 50;
12654
12703
  const STRUCTURAL_TOPN_FAST = 10;
12655
12704
  /**
@@ -13957,7 +14006,7 @@ async function searchCode(rawInput, externalSignal) {
13957
14006
  })).filter((e) => e.index >= 0),
13958
14007
  workspaceRoot: ws.canonical,
13959
14008
  topN,
13960
- budgetMs: STRUCTURAL_BUDGET_MS,
14009
+ budgetMs: structuralBudgetMs(),
13961
14010
  signal: ac.signal
13962
14011
  });
13963
14012
  structuralOutlines = structural.outlinesByFile;
@@ -15562,6 +15611,7 @@ async function provisionAndIndexColbert(opts = {}) {
15562
15611
  return;
15563
15612
  }
15564
15613
  if (!provisioned) return;
15614
+ if (opts.skipCwdIndex) return;
15565
15615
  const cwd = opts.cwd ?? process$1.cwd();
15566
15616
  try {
15567
15617
  if ((await gitState(cwd)).isRepo && await startupKickAllowed(cwd)) kickBackgroundInit(cwd);
@@ -16881,7 +16931,7 @@ function logAudit$1(record) {
16881
16931
  try {
16882
16932
  const fs$2 = await import("node:fs/promises");
16883
16933
  const path$1 = await import("node:path");
16884
- const { PATHS: PATHS$1 } = await import("./paths-CDYvyApX.js");
16934
+ const { PATHS: PATHS$1 } = await import("./paths-B5k78n0d.js");
16885
16935
  const dir = path$1.join(PATHS$1.APP_DIR, "browser-mcp");
16886
16936
  await fs$2.mkdir(dir, { recursive: true });
16887
16937
  const line = JSON.stringify({
@@ -24084,9 +24134,9 @@ function jsonPathPreflightCap(body, scope) {
24084
24134
  const decision = typeof args.decision === "string" ? args.decision : "";
24085
24135
  const optionsRaw = Array.isArray(args.options) ? args.options : [];
24086
24136
  const standInContext = typeof args.context === "string" ? args.context : "";
24087
- if (!decision || optionsRaw.length === 0) return void 0;
24137
+ if (!decision || optionsRaw.length === 0 || !standInContext.trim()) return void 0;
24088
24138
  const briefBytes$1 = Buffer.byteLength(decision + JSON.stringify(optionsRaw) + standInContext, "utf8");
24089
- const STAND_IN_CAP_BYTES = 6 * 1024;
24139
+ const STAND_IN_CAP_BYTES = 32 * 1024;
24090
24140
  if (briefBytes$1 > STAND_IN_CAP_BYTES) return rpcResult(body.id, toolError(`pre-flight rejected: stand_in on a ${briefBytes$1}-byte input is predicted to exceed the JSON tools/call timeout (cap=${STAND_IN_CAP_BYTES} bytes). stand_in runs two sequential voting rounds across three frontier models — wall-clock is typically 2-3 minutes regardless of input size. Send Accept: text/event-stream to use the SSE path which bypasses this cap, or trim the decision/options/context.`));
24091
24141
  return;
24092
24142
  }
@@ -24213,7 +24263,13 @@ function logTelemetry(t) {
24213
24263
  if (t.errorMessage) parts.push(`error=${JSON.stringify(t.errorMessage)}`);
24214
24264
  process.stderr.write(parts.join(" ") + "\n");
24215
24265
  }
24216
- async function handleToolsCall(body, scope) {
24266
+ function toolAcceptsWorkspace(tool$1) {
24267
+ return tool$1.capability === "worker" || tool$1.toolNameHttp === "code" || tool$1.toolNameHttp === "run_workflow";
24268
+ }
24269
+ function applySessionWorkspace(args, sessionWorkspace, tool$1) {
24270
+ if ((!tool$1 || toolAcceptsWorkspace(tool$1)) && typeof sessionWorkspace === "string" && sessionWorkspace.length > 0 && nodePath.isAbsolute(sessionWorkspace) && (args.workspace === void 0 || args.workspace === "")) args.workspace = sessionWorkspace;
24271
+ }
24272
+ async function handleToolsCall(body, scope, sessionWorkspace) {
24217
24273
  const params = body.params ?? {};
24218
24274
  const name = typeof params.name === "string" ? params.name : "";
24219
24275
  const args = params.arguments ?? {};
@@ -24276,6 +24332,7 @@ async function handleToolsCall(body, scope) {
24276
24332
  const telemetryName = persona ? persona.agentName : nonPersonaTool.toolNameHttp;
24277
24333
  const telemetryModel = persona ? persona.model : "(non-persona)";
24278
24334
  try {
24335
+ if (nonPersonaTool) applySessionWorkspace(args, sessionWorkspace, nonPersonaTool);
24279
24336
  const result = persona ? await callPersona(persona, personaPrompt, personaContext, personaEffort, aborter?.signal) : await nonPersonaTool.handler(args, aborter?.signal);
24280
24337
  logTelemetry({
24281
24338
  name: telemetryName,
@@ -24321,7 +24378,7 @@ function handleCancelledNotification(body) {
24321
24378
  }
24322
24379
  cancelInflight(requestId, "client requested cancellation");
24323
24380
  }
24324
- async function handleRpc(_c, body, scope) {
24381
+ async function handleRpc(_c, body, scope, sessionWorkspace) {
24325
24382
  if (body === null || typeof body !== "object" || Array.isArray(body)) return {
24326
24383
  status: 200,
24327
24384
  body: rpcError(null, RPC_INVALID_REQUEST, "jsonrpc 2.0 envelope required")
@@ -24372,7 +24429,7 @@ async function handleRpc(_c, body, scope) {
24372
24429
  };
24373
24430
  return {
24374
24431
  status: 200,
24375
- body: await handleToolsCall(body, scope)
24432
+ body: await handleToolsCall(body, scope, sessionWorkspace)
24376
24433
  };
24377
24434
  case "resources/list":
24378
24435
  if (isNotification) return {
@@ -24463,17 +24520,18 @@ async function handleMcpPost(c, scopeArg = "all") {
24463
24520
  consola.debug("/mcp parse error:", err);
24464
24521
  return c.json(rpcError(null, RPC_PARSE_ERROR, "request body is not valid JSON"), 200);
24465
24522
  }
24523
+ const sessionWorkspace = c.req.header(MCP_WORKSPACE_HEADER);
24466
24524
  if (process.env.GH_ROUTER_LOG_PEER_MCP === "1" && typeof body === "object" && body !== null && !Array.isArray(body) && body.method === "tools/call") {
24467
24525
  const nm = typeof body.params?.name === "string" ? body.params.name : "?";
24468
24526
  process.stderr.write(`[peer-mcp] recv t=${Date.now()} name=${nm} scope=${scope} inflight=${currentInFlight()}\n`);
24469
24527
  }
24470
- if (typeof body === "object" && body !== null && !Array.isArray(body) && body.method === "tools/call" && acceptsEventStream(c.req.header("accept"))) return handleToolsCallSSE(body, scope);
24528
+ if (typeof body === "object" && body !== null && !Array.isArray(body) && body.method === "tools/call" && acceptsEventStream(c.req.header("accept"))) return handleToolsCallSSE(body, scope, sessionWorkspace);
24471
24529
  if (typeof body === "object" && body !== null && !Array.isArray(body) && body.method === "tools/call") {
24472
24530
  const preflight = jsonPathPreflightCap(body, scope);
24473
24531
  if (preflight) return c.json(preflight, 200);
24474
24532
  }
24475
24533
  try {
24476
- const { status, body: respBody } = await handleRpc(c, body, scope);
24534
+ const { status, body: respBody } = await handleRpc(c, body, scope, sessionWorkspace);
24477
24535
  if (respBody === null) return c.body(null, status);
24478
24536
  return c.json(respBody, status);
24479
24537
  } catch (err) {
@@ -24526,9 +24584,9 @@ function acceptsEventStream(accept) {
24526
24584
  * "Invalid state: Controller is already closed" race without warning.
24527
24585
  */
24528
24586
  const SSE_HEARTBEAT_INTERVAL_MS = 5e3;
24529
- async function handleToolsCallSSE(body, scope) {
24587
+ async function handleToolsCallSSE(body, scope, sessionWorkspace) {
24530
24588
  const encoder = new TextEncoder();
24531
- const callPromise = handleToolsCall(body, scope);
24589
+ const callPromise = handleToolsCall(body, scope, sessionWorkspace);
24532
24590
  let heartbeatHandle;
24533
24591
  const stream = new ReadableStream({
24534
24592
  async start(controller) {
@@ -28039,12 +28097,15 @@ Respond with ONLY a single JSON object — no prose, no markdown fences, no prea
28039
28097
  "choice": "<option.id>" | null,
28040
28098
  "confidence": <number between 0.0 and 1.0>,
28041
28099
  "reasoning": "<one short sentence>",
28042
- "need_more_info": "<what context is missing, if you cannot decide>"
28100
+ "need_more_info": "<what context is missing, if you cannot decide>",
28101
+ "alternative": "<a concrete unlisted option — ONLY if every provided option is inadequate>"
28043
28102
  }
28044
28103
 
28045
28104
  Calibration rules:
28046
28105
  - "confidence" reflects how sure you are this is the better option (not how confident you are in your prose). 0.5 = coin flip. 0.9 = clear winner. Be honestly calibrated; the orchestrator weighs your number directly.
28047
28106
  - If the question is genuinely under-specified — you'd need information you don't have to choose well — set "choice": null AND populate "need_more_info" with the specific gap. Do NOT guess.
28107
+ - The caller curated these options; default to choosing among them. Only if a provided option is actively harmful, or clearly dominated by an obvious unlisted option, set "choice": null AND put that concrete option in "alternative" (one sentence). This is distinct from "need_more_info" (which is about missing context, not a better option). Prefer choosing over proposing — do not invent an alternative to avoid committing.
28108
+ - On an abstention, populate at most ONE escape channel: "need_more_info" OR "alternative", never both. If both seem to apply, use "need_more_info" — missing context takes precedence, because you can't reliably judge the options inadequate without it.
28048
28109
  - One sentence of reasoning. Not a paragraph.
28049
28110
  - The other two models will vote independently and you will see their votes in round 2. There is no benefit to anticipating what they'll pick; vote on the merits.
28050
28111
 
@@ -28057,16 +28118,19 @@ Same JSON schema as round 1:
28057
28118
  "choice": "<option.id>" | null,
28058
28119
  "confidence": <number between 0.0 and 1.0>,
28059
28120
  "reasoning": "<one short sentence>",
28060
- "need_more_info": "<gap, if any>"
28121
+ "need_more_info": "<gap, if any>",
28122
+ "alternative": "<a concrete unlisted option, if every provided option is inadequate>"
28061
28123
  }
28062
28124
 
28063
28125
  Calibration rules:
28064
28126
  - You may keep your round-1 vote OR change it. Do NOT change just to agree — agreement is not the goal, the right answer is. Capitulating to peer pressure when you still believe your original choice is better is a failure mode, not a success.
28065
28127
  - If a peer's reasoning identifies a consideration you missed or weighed wrong, update freely. The blind round was the anti-anchor mechanism; this round is where genuine evidence can move you.
28066
28128
  - If round 1 left you genuinely uncertain and peer reasoning hasn't resolved it, "choice": null is still the honest answer.
28129
+ - Keep using "alternative" only when every provided option is inadequate (choice null); it is not a way to dodge a decision the options already support.
28130
+ - On an abstention, populate at most ONE escape channel: "need_more_info" OR "alternative", never both. If both seem to apply, use "need_more_info" (missing context takes precedence).
28067
28131
 
28068
28132
  Output ONLY the JSON object.`;
28069
- const RETRY_PROMPT_SUFFIX = `\n\nYour previous response was not valid JSON matching the schema. Respond with ONLY the JSON object — no preamble, no markdown fences, no closing remarks. Schema reminder: {"choice": "<id>" | null, "confidence": 0.0-1.0, "reasoning": "<one sentence>", "need_more_info": "<gap, if any>"}`;
28133
+ const RETRY_PROMPT_SUFFIX = `\n\nYour previous response was not valid JSON matching the schema. Respond with ONLY the JSON object — no preamble, no markdown fences, no closing remarks. Schema reminder: {"choice": "<id>" | null, "confidence": 0.0-1.0, "reasoning": "<one sentence>", "need_more_info": "<gap, if any>", "alternative": "<unlisted option, if any>"}`;
28070
28134
  /**
28071
28135
  * Run the two-round stand-in protocol. Returns a structured verdict
28072
28136
  * envelope. Throws only on systemic failure (e.g., all three upstream
@@ -28074,71 +28138,66 @@ const RETRY_PROMPT_SUFFIX = `\n\nYour previous response was not valid JSON match
28074
28138
  * `VoteFailure` entries in the result.
28075
28139
  */
28076
28140
  async function runStandIn(input, signal) {
28141
+ const validIds = new Set(input.options.map((o) => o.id));
28077
28142
  const r1UserText = buildRound1UserText(input);
28078
- const r1 = await Promise.all(STAND_IN_MODELS.map((cfg) => callAndParse(cfg, SYSTEM_PROMPT_R1, r1UserText, signal)));
28143
+ const r1 = await Promise.all(STAND_IN_MODELS.map((cfg) => callAndParse(cfg, SYSTEM_PROMPT_R1, r1UserText, validIds, signal)));
28079
28144
  const successfulR1 = r1.filter((r) => isVote(r.vote));
28080
- if (successfulR1.length === STAND_IN_MODELS.length && successfulR1.every((r) => r.vote.needMoreInfo && r.vote.choice === null)) {
28081
- const gaps = successfulR1.map((r) => `- ${r.key}: ${r.vote.needMoreInfo}`).join("\n");
28082
- return {
28083
- verdict: "need_more_info",
28084
- recommendation: null,
28085
- confidence: 0,
28086
- votes: voteRecord(r1, null),
28087
- notes: `All three models reported they need more context to decide:\n${gaps}`
28088
- };
28089
- }
28145
+ const nmiR1 = gapAbstainVerdict(successfulR1, r1, null);
28146
+ if (nmiR1) return nmiR1;
28090
28147
  const r1Decision = aggregateVotes(successfulR1);
28091
- if (r1Decision.verdict === "consensus" && r1Decision.meanConfidence >= .8) return {
28148
+ if (r1Decision.verdict === "consensus" && r1Decision.meanConfidence >= .8) return withDerivedNotes({
28092
28149
  verdict: "consensus",
28093
28150
  recommendation: r1Decision.winner,
28094
28151
  confidence: round2(r1Decision.meanConfidence),
28095
28152
  votes: voteRecord(r1, null),
28096
28153
  notes: `All three models picked ${r1Decision.winner} in round 1 with high confidence (skipped round 2).`
28097
- };
28098
- if (successfulR1.length < 2) return {
28154
+ }, r1, null);
28155
+ if (successfulR1.length < 2) return withDerivedNotes({
28099
28156
  verdict: "no_consensus",
28100
28157
  recommendation: null,
28101
28158
  confidence: 0,
28102
28159
  votes: voteRecord(r1, null),
28103
28160
  notes: `Only ${successfulR1.length} of 3 models returned a parseable round-1 vote; insufficient signal to run round 2.`
28104
- };
28161
+ }, r1, null);
28105
28162
  const r2UserTextBase = buildRound2UserTextBase(input, r1);
28106
- const r2 = await Promise.all(STAND_IN_MODELS.map((cfg) => callAndParse(cfg, SYSTEM_PROMPT_R2, r2UserTextBase + `\n\nYou are ${cfg.key}. Reconsider and vote.`, signal)));
28163
+ const r2 = await Promise.all(STAND_IN_MODELS.map((cfg) => callAndParse(cfg, SYSTEM_PROMPT_R2, r2UserTextBase + `\n\nYou are ${cfg.key}. Reconsider and vote.`, validIds, signal)));
28107
28164
  const successfulR2 = r2.filter((r) => isVote(r.vote));
28108
- if (successfulR2.length < 2) return {
28165
+ if (successfulR2.length < 2) return withDerivedNotes({
28109
28166
  verdict: "no_consensus",
28110
28167
  recommendation: null,
28111
28168
  confidence: 0,
28112
28169
  votes: voteRecord(r1, r2),
28113
28170
  notes: `Only ${successfulR2.length} of 3 models returned a parseable round-2 vote; deferring to user.`
28114
- };
28171
+ }, r1, r2);
28172
+ const nmiR2 = gapAbstainVerdict(successfulR2, r1, r2);
28173
+ if (nmiR2) return nmiR2;
28115
28174
  const r2Decision = aggregateVotes(successfulR2);
28116
- if (r2Decision.verdict === "consensus") return {
28175
+ if (r2Decision.verdict === "consensus") return withDerivedNotes({
28117
28176
  verdict: "consensus",
28118
28177
  recommendation: r2Decision.winner,
28119
28178
  confidence: round2(r2Decision.meanConfidence),
28120
28179
  votes: voteRecord(r1, r2),
28121
28180
  notes: `All three models picked ${r2Decision.winner} in round 2.`
28122
- };
28181
+ }, r1, r2);
28123
28182
  if (r2Decision.verdict === "majority") {
28124
28183
  const dissenters = successfulR2.filter((r) => r.vote.choice !== r2Decision.winner).map((r) => `${r.key} picked ${r.vote.choice ?? "abstain"} (${r.vote.reasoning})`).join("; ");
28125
- return {
28184
+ return withDerivedNotes({
28126
28185
  verdict: "majority",
28127
28186
  recommendation: r2Decision.winner,
28128
28187
  confidence: round2(r2Decision.meanConfidence),
28129
28188
  votes: voteRecord(r1, r2),
28130
28189
  notes: `Majority (2 of 3) picked ${r2Decision.winner}. Dissent: ${dissenters}.`
28131
- };
28190
+ }, r1, r2);
28132
28191
  }
28133
- return {
28192
+ return withDerivedNotes({
28134
28193
  verdict: "no_consensus",
28135
28194
  recommendation: null,
28136
28195
  confidence: 0,
28137
28196
  votes: voteRecord(r1, r2),
28138
28197
  notes: `Models did not converge in round 2 (votes split). Defer to user.`
28139
- };
28198
+ }, r1, r2);
28140
28199
  }
28141
- async function callAndParse(cfg, instructions, userText, signal) {
28200
+ async function callAndParse(cfg, instructions, userText, validIds, signal) {
28142
28201
  const model = cfg.key === "gpt-5.6-sol" ? resolveOpenAiFrontier() ?? cfg.model : cfg.model;
28143
28202
  let raw;
28144
28203
  try {
@@ -28159,7 +28218,7 @@ async function callAndParse(cfg, instructions, userText, signal) {
28159
28218
  }
28160
28219
  };
28161
28220
  }
28162
- const first = tryParseVote(raw);
28221
+ const first = tryParseVote(raw, validIds);
28163
28222
  if (first.ok) return {
28164
28223
  key: cfg.key,
28165
28224
  vote: first.vote
@@ -28183,7 +28242,7 @@ async function callAndParse(cfg, instructions, userText, signal) {
28183
28242
  }
28184
28243
  };
28185
28244
  }
28186
- const second = tryParseVote(retryRaw);
28245
+ const second = tryParseVote(retryRaw, validIds);
28187
28246
  if (second.ok) return {
28188
28247
  key: cfg.key,
28189
28248
  vote: second.vote
@@ -28197,7 +28256,7 @@ async function callAndParse(cfg, instructions, userText, signal) {
28197
28256
  }
28198
28257
  };
28199
28258
  }
28200
- function tryParseVote(raw) {
28259
+ function tryParseVote(raw, validIds) {
28201
28260
  if (!raw || !raw.trim()) return {
28202
28261
  ok: false,
28203
28262
  error: "empty response"
@@ -28225,11 +28284,16 @@ function tryParseVote(raw) {
28225
28284
  error: "parsed value is not an object"
28226
28285
  };
28227
28286
  const obj = parsed;
28228
- const choice = obj.choice === null ? null : typeof obj.choice === "string" && obj.choice.length > 0 ? obj.choice : void 0;
28229
- if (choice === void 0) return {
28287
+ const rawChoice = obj.choice === null ? null : typeof obj.choice === "string" && obj.choice.length > 0 ? obj.choice : void 0;
28288
+ if (rawChoice === void 0) return {
28230
28289
  ok: false,
28231
28290
  error: "missing or invalid 'choice' field (string or null required)"
28232
28291
  };
28292
+ if (rawChoice !== null && !validIds.has(rawChoice)) return {
28293
+ ok: false,
28294
+ error: "'choice' must be one of the provided option ids or null"
28295
+ };
28296
+ const choice = rawChoice;
28233
28297
  const confidenceRaw = obj.confidence;
28234
28298
  const confidence = typeof confidenceRaw === "number" && Number.isFinite(confidenceRaw) ? Math.max(0, Math.min(1, confidenceRaw)) : void 0;
28235
28299
  if (confidence === void 0) return {
@@ -28241,13 +28305,15 @@ function tryParseVote(raw) {
28241
28305
  ok: false,
28242
28306
  error: "missing or empty 'reasoning' field"
28243
28307
  };
28308
+ const needMoreInfo = choice === null && typeof obj.need_more_info === "string" && obj.need_more_info.trim().length > 0 ? obj.need_more_info.trim() : void 0;
28244
28309
  return {
28245
28310
  ok: true,
28246
28311
  vote: {
28247
28312
  choice,
28248
28313
  confidence,
28249
28314
  reasoning,
28250
- needMoreInfo: typeof obj.need_more_info === "string" && obj.need_more_info.length > 0 ? obj.need_more_info : void 0
28315
+ needMoreInfo,
28316
+ alternative: choice === null && !needMoreInfo && typeof obj.alternative === "string" && obj.alternative.trim().length > 0 ? obj.alternative.trim() : void 0
28251
28317
  }
28252
28318
  };
28253
28319
  }
@@ -28310,13 +28376,70 @@ function buildRound2UserTextBase(input, r1) {
28310
28376
  for (const r of r1) if (isVote(r.vote)) {
28311
28377
  const choiceText = r.vote.choice === null ? "abstain" : r.vote.choice;
28312
28378
  const gapText = r.vote.needMoreInfo ? ` (needs: ${r.vote.needMoreInfo})` : "";
28313
- summaries.push(`- ${r.key} picked ${choiceText}, confidence ${r.vote.confidence.toFixed(2)}, reasoning: ${r.vote.reasoning}${gapText}`);
28379
+ const altText = r.vote.alternative ? ` [proposed unlisted alternative: ${r.vote.alternative}]` : "";
28380
+ summaries.push(`- ${r.key} picked ${choiceText}, confidence ${r.vote.confidence.toFixed(2)}, reasoning: ${r.vote.reasoning}${gapText}${altText}`);
28314
28381
  } else summaries.push(`- ${r.key} did not return a valid round-1 vote (${r.vote.error}).`);
28315
28382
  return base + "\n" + summaries.join("\n");
28316
28383
  }
28317
28384
  function isVote(v) {
28318
28385
  return !("error" in v);
28319
28386
  }
28387
+ function gapAbstainVerdict(successful, r1, r2) {
28388
+ const gapVotes = successful.filter((r) => r.vote.choice === null && r.vote.needMoreInfo);
28389
+ if (gapVotes.length < 2) return null;
28390
+ const gaps = gapVotes.map((r) => `- ${r.key}: ${r.vote.needMoreInfo}`).join("\n");
28391
+ const header = gapVotes.length === STAND_IN_MODELS.length ? "All three models reported they need more context to decide:" : `${gapVotes.length} of 3 models reported they need more context to decide:`;
28392
+ return withDerivedNotes({
28393
+ verdict: "need_more_info",
28394
+ recommendation: null,
28395
+ confidence: 0,
28396
+ votes: voteRecord(r1, r2),
28397
+ notes: `${header}\n${gaps}`
28398
+ }, r1, r2);
28399
+ }
28400
+ /**
28401
+ * Freshest parsed vote per model (round 2 if it parsed, else round 1) — the
28402
+ * basis for deriving alternative / gap notes without double-counting a model
28403
+ * across rounds.
28404
+ */
28405
+ function freshestVotes(r1, r2) {
28406
+ const out = [];
28407
+ for (const cfg of STAND_IN_MODELS) {
28408
+ const r2Entry = r2?.find((r) => r.key === cfg.key);
28409
+ const r1Entry = r1.find((r) => r.key === cfg.key);
28410
+ const vote = r2Entry && isVote(r2Entry.vote) ? r2Entry.vote : r1Entry && isVote(r1Entry.vote) ? r1Entry.vote : null;
28411
+ if (vote) out.push({
28412
+ key: cfg.key,
28413
+ vote
28414
+ });
28415
+ }
28416
+ return out;
28417
+ }
28418
+ /**
28419
+ * Append derived notes to a verdict WITHOUT touching the verdict / tally:
28420
+ * - panel-proposed unlisted `alternative`s (surfaced on every verdict);
28421
+ * - partial missing-context gaps (surfaced only on no_consensus — the
28422
+ * dedicated need_more_info path already lists its own gaps).
28423
+ * Purely additive to `notes`; never changes verdict / recommendation / isError.
28424
+ * This is what lets the alternative + partial-gap signals ride along while the
28425
+ * abstain and blind-R1 invariants stay untouched.
28426
+ */
28427
+ function withDerivedNotes(result, r1, r2) {
28428
+ const fresh = freshestVotes(r1, r2);
28429
+ const extras = [];
28430
+ const alts = fresh.filter((v) => v.vote.alternative);
28431
+ if (alts.length > 0) extras.push("The panel also flagged unlisted option(s):\n" + alts.map((v) => `- ${v.key}: ${v.vote.alternative}`).join("\n"));
28432
+ if (result.verdict === "no_consensus") {
28433
+ const gaps = fresh.filter((v) => v.vote.choice === null && v.vote.needMoreInfo);
28434
+ if (gaps.length > 0) extras.push("Some models cited missing context:\n" + gaps.map((v) => `- ${v.key}: ${v.vote.needMoreInfo}`).join("\n"));
28435
+ }
28436
+ if (extras.length === 0) return result;
28437
+ const notes = [result.notes, ...extras].filter(Boolean).join("\n\n");
28438
+ return {
28439
+ ...result,
28440
+ notes
28441
+ };
28442
+ }
28320
28443
  function voteRecord(r1, r2) {
28321
28444
  const record = {};
28322
28445
  for (const cfg of STAND_IN_MODELS) {
@@ -31289,10 +31412,14 @@ const NON_PERSONA_MCP_TOOLS = Object.freeze([
31289
31412
  toolNameHttp: "stand_in",
31290
31413
  group: "decide",
31291
31414
  capability: "stand_in",
31292
- description: "Three-lab away-mode decision tiebreak advisor for moments when the user is unavailable and the agent is stuck between two or more concrete options. It polls gpt-5.6-sol, Opus 4.7, and gemini-3.1-pro-preview across blind and informed voting rounds, then returns a ranked-choice verdict such as consensus, majority, no_consensus, or need_more_info. Use when work would otherwise halt on a bounded choice the user would normally make. Not for code review, open-ended exploration, single-model second opinions, or bypassing confirmation on irreversible actions such as push, delete, drop, or deploy; use peer-review-coordinator or the individual critics for review and still ask the user for destructive actions.",
31415
+ description: "Three-lab away-mode decision tiebreak advisor for moments when the user is unavailable and the agent is stuck between two or more concrete options. It polls gpt-5.6-sol, Opus 4.7, and gemini-3.1-pro-preview across blind and informed voting rounds, then returns a ranked-choice verdict such as consensus, majority, no_consensus, or need_more_info. Use when work would otherwise halt on a bounded choice the user would normally make. If every provided option is inadequate, the panel may flag a concrete better unlisted option in `notes` so you can re-invoke with a revised set. The three panel models are cold-start — no repo, transcript, or memory access — and see only your decision, options, and context, so the `context` argument must carry all the background they need to judge. Not for code review, open-ended exploration, single-model second opinions, or bypassing confirmation on irreversible actions such as push, delete, drop, or deploy; use peer-review-coordinator or the individual critics for review and still ask the user for destructive actions.",
31293
31416
  inputSchema: {
31294
31417
  type: "object",
31295
- required: ["decision", "options"],
31418
+ required: [
31419
+ "decision",
31420
+ "options",
31421
+ "context"
31422
+ ],
31296
31423
  additionalProperties: false,
31297
31424
  properties: {
31298
31425
  decision: {
@@ -31303,7 +31430,7 @@ const NON_PERSONA_MCP_TOOLS = Object.freeze([
31303
31430
  type: "array",
31304
31431
  minItems: 2,
31305
31432
  maxItems: 6,
31306
- description: "2-6 concrete options for the panel to vote on. Caller-provided do NOT ask the panel to generate options. The verdict cites the chosen option by `id`.",
31433
+ description: "2-6 concrete options curated by the caller for the panel to vote on. The panel may surface a gated unlisted alternative in `notes`, but does not replace the caller's option set. The verdict cites the chosen option by `id`.",
31307
31434
  items: {
31308
31435
  type: "object",
31309
31436
  required: ["id", "summary"],
@@ -31326,7 +31453,7 @@ const NON_PERSONA_MCP_TOOLS = Object.freeze([
31326
31453
  },
31327
31454
  context: {
31328
31455
  type: "string",
31329
- description: "Task / code background that informs the decision. Keep tight the input is capped at ~6KB total across decision + options + context."
31456
+ description: "REQUIRED. The three panel models are cold-start: no access to your repository, prior transcript, or memory they see ONLY this decision + options + context. Include everything needed to decide well: the constraints that matter, the relevant code or excerpts, prior decisions not to relitigate, and what a good outcome looks like. Thin context yields a weak verdict. (On the JSON transport a ~32KB size guard applies; the SSE transport has no such limit.)"
31330
31457
  }
31331
31458
  }
31332
31459
  },
@@ -31370,8 +31497,9 @@ function assertMcpToolSurfaceConsistent() {
31370
31497
  /**
31371
31498
  * Shared closure body for the two worker MCP tools. Validates the
31372
31499
  * minimal arg shape (prompt required + optional knobs typed), then
31373
- * forwards to `runWorkerAgent`. `workspace` defaults to the proxy's
31374
- * launch cwd; callers can override via the optional `workspace` arg
31500
+ * forwards to `runWorkerAgent`. Outside serve mode, `workspace` defaults
31501
+ * to the proxy's launch cwd; serve mode requires an explicit/header-derived
31502
+ * workspace. Callers can override via the optional `workspace` arg
31375
31503
  * (absolute paths only — enforced here). The engine performs every
31376
31504
  * deeper validation (model existence, thinking clamp, worktree
31377
31505
  * provisioning, semaphore acquisition, workspace realpath +
@@ -31433,7 +31561,7 @@ async function runWorkerToolCall(call) {
31433
31561
  };
31434
31562
  worktree = args.worktree;
31435
31563
  }
31436
- let workspace = process.cwd();
31564
+ let workspace;
31437
31565
  if (args.workspace !== void 0) {
31438
31566
  if (typeof args.workspace !== "string" || args.workspace.length === 0) return {
31439
31567
  content: [{
@@ -31450,7 +31578,14 @@ async function runWorkerToolCall(call) {
31450
31578
  isError: true
31451
31579
  };
31452
31580
  workspace = args.workspace;
31453
- }
31581
+ } else if (state.serveMode) return {
31582
+ content: [{
31583
+ type: "text",
31584
+ text: `worker_${mode}: a workspace is required. This is a machine-wide github-router serve; pass the absolute path of the project you are working in as \`workspace\`.`
31585
+ }],
31586
+ isError: true
31587
+ };
31588
+ else workspace = process.cwd();
31454
31589
  let maxWallClockMs;
31455
31590
  let clampNote = "";
31456
31591
  if (args.maxWallClockMs !== void 0) {
@@ -31663,11 +31798,11 @@ async function runStandInToolCall(args, signal) {
31663
31798
  detail
31664
31799
  });
31665
31800
  }
31666
- const context = args.context === void 0 ? void 0 : typeof args.context === "string" ? args.context : null;
31667
- if (context === null) return {
31801
+ const context = typeof args.context === "string" ? args.context : "";
31802
+ if (!context.trim()) return {
31668
31803
  content: [{
31669
31804
  type: "text",
31670
- text: "stand_in: arguments.context must be a string when provided"
31805
+ text: "stand_in: arguments.context is required (non-empty string). The panel is cold-start and sees only decision + options + context; include the constraints, relevant code, and success criteria needed to decide."
31671
31806
  }],
31672
31807
  isError: true
31673
31808
  };
@@ -31681,7 +31816,34 @@ async function runStandInToolCall(args, signal) {
31681
31816
  text: JSON.stringify(result)
31682
31817
  }] };
31683
31818
  }
31819
+ /**
31820
+ * Every exact `mcp__<key>__<tool>` name github-router injects, for the given
31821
+ * resolved group keys (`peers`/`search`/… → their collision-resolved mcpServers
31822
+ * key). A SUPERSET — it ignores per-tool capability gates because an allow-list
31823
+ * entry for a tool that isn't actually served is inert, which keeps it correct
31824
+ * as gates change and as tools are added.
31825
+ *
31826
+ * Used to seed CloudCLI's `localStorage['claude-settings'].allowedTools` so its
31827
+ * Agent-SDK `canUseTool` auto-approves our MCP tools in PLAN mode. `canUseTool`
31828
+ * does EXACT tool-name matching (no `mcp__<server>` wildcard — see
31829
+ * `matchesToolPermission` in CloudCLI's `claude-sdk.js`), so bare `mcp__peers`
31830
+ * would NOT cover `mcp__peers__gemini_critic`; the exact names are required.
31831
+ * This is the ONLY lever for plan mode: bypass mode skips `canUseTool`, and the
31832
+ * mirror `settings.json permissions.allow` is NOT consulted by `canUseTool`
31833
+ * (which reads `sdkOptions.allowedTools`, seeded from this localStorage key).
31834
+ */
31835
+ function enumerateInjectedMcpToolNames(groupKeys, opts = {}) {
31836
+ const names = [];
31837
+ const peersKey = groupKeys.peers;
31838
+ if (peersKey) for (const p of [...PERSONAS_READ, ...PERSONAS_WRITE]) names.push(`mcp__${peersKey}__${p.toolNameHttp}`);
31839
+ for (const t of NON_PERSONA_MCP_TOOLS) {
31840
+ const key = groupKeys[t.group];
31841
+ if (key) names.push(`mcp__${key}__${t.toolNameHttp}`);
31842
+ }
31843
+ if (opts.codexCli) names.push("mcp__codex-cli__codex");
31844
+ return [...new Set(names)];
31845
+ }
31684
31846
 
31685
31847
  //#endregion
31686
- export { isAdvisorRequested as $, cacheCopilotVersion as $t, liveExec as A, provisionBrowserAssets as At, withNoOutputRetry as B, DEFAULT_CODEX_MODEL as Bt, fileReviewDebounce as C, resolveMcpToolTimeoutMs as Ct, stopGateEnabledForRepo as D, MAX_RESPONSE_BODY_BYTES as Dt, repoRoot as E, createChatCompletions as Et, IMPLEMENT_DEFAULT_MODEL as F, shouldUseInsecureTls as Ft, vscodeRipgrepPath as G, generateRandomPort as Gt, buildToolbeltAwareness as H, DEFAULT_PORT as Ht, PLAN_DEFAULT_MODEL as I, ArtifactClient as It, searchWeb as J, withInstallLock as Jt, TOOLBELT_TOOLS$1 as K, pickClaudeDefault as Kt, REVIEW_DEFAULT_MODEL as L, collapsePathKeys as Lt, BROWSE_DEFAULT_MODEL as M, provisionAndIndexColbert as Mt, DEFAULT_MODEL as N, extractTarGzMember as Nt, stopReviewStateDir as O, readResponseBodyCapped as Ot, EXPLORE_DEFAULT_MODEL as P, extractZipMember as Pt, injectAdvisorTool as Q, tryRefreshAndRetry as Qt, appendPlanReminder as R, toolbeltPathOverride as Rt, fileLastPromptStore as S, assembleResponsesPayload as St, repoFingerprint as T, createResponses as Tt, toolbeltEnabled as U, UPSTREAM_FETCH_TIMEOUT_MS as Ut, availableToolCommands as V, DEFAULT_CODEX_MODEL_FALLBACKS as Vt, toolbeltSkipSet as W, UPSTREAM_INACTIVITY_TIMEOUT_MS as Wt, ADVISOR_TOOL_INSTRUCTIONS as X, setupGitHubAgentToken as Xt, ADVISOR_INTERNAL_TOOL_NAME as Y, setupCopilotToken as Yt, buildAdvisorStream as Z, setupGitHubToken as Zt, stopGateId as _, workerToolsEnabled as _t, buildPeerAwarenessSnippet as a, resolveModel as an, relayAnthropicStream as at, fileBaselineStore as b, createMessages as bt, buildArtifactOpenHookCommand as c, fetchWithTransientRetry as cn, agentToolsEnabled as ct, captureLaunchBaseline as d, GITHUB_API_BASE_URL as dn, browserCompoundToolsEnabled as dt, cacheModels as en, buildAnthropicErrorEvent as et, decideStopHook as f, copilotBaseUrl as fn, browserToolsEnabled as ft, stopGateDisabled as g, standInToolEnabled as gt, launchBaselineKey as h, state as hn, nativeSubagentModel as ht, buildAgentPrompt as i, resolveCodexModel as in, readIteratorWithTimeout as it, resolveSealedGate as j, hasSupportedBrowserInstalled as jt, trustRepo as k, parseJsonOrDiagnose as kt, buildSessionBindHookCommand as l, HTTPError as ln, artifactToolsEnabled as lt, injectStopHookIntoSettingsFile as m, githubHeaders as mn, geminiAvailable as mt, MCP_GROUPS as n, filterBetaHeader as nn, isControllerClosedError as nt, buildPeerAwarenessSummary as o, sleep as on, handleMcpDelete as ot, fileBlockBudget as p, copilotHeaders as pn, fleetToolsEnabled as pt, assetFor as q, getPackageVersion as qt, assertMcpToolSurfaceConsistent as r, isNullish as rn, logStreamError as rt, personasFor as s, getModels as sn, handleMcpPost as st, GROUP_META as t, cacheVSCodeVersion as tn, buildOpenAIErrorEvent as tt, buildStopHookCommand as u, forwardError as un, browseAgentEnabled as ut, stopGatePlanMode as v, shimDefaultsToXhigh as vt, isSubagentContext as w, pickEndpoint as wt, fileFindingsStore as x, getTokenCount as xt, stopReviewEnabled as y, countTokens as yt, runWorkerAgent as z, DEFAULT_CLAUDE_MODEL_FALLBACKS as zt };
31687
- //# sourceMappingURL=peer-mcp-personas-BtQi-dF-.js.map
31848
+ export { buildAdvisorStream as $, setupCopilotToken as $t, trustRepo as A, readResponseBodyCapped as At, runWorkerAgent as B, buildWorkspaceHeaderJson as Bt, fileLastPromptStore as C, getTokenCount as Ct, repoRoot as D, createResponses as Dt, repoFingerprint as E, pickEndpoint as Et, EXPLORE_DEFAULT_MODEL as F, extractTarGzMember as Ft, toolbeltEnabled as G, DEFAULT_CODEX_MODEL_FALLBACKS as Gt, buildEnv as H, toolbeltPathOverride as Ht, IMPLEMENT_DEFAULT_MODEL as I, extractZipMember as It, TOOLBELT_TOOLS$1 as J, UPSTREAM_INACTIVITY_TIMEOUT_MS as Jt, toolbeltSkipSet as K, DEFAULT_PORT as Kt, PLAN_DEFAULT_MODEL as L, shouldUseInsecureTls as Lt, resolveSealedGate as M, provisionBrowserAssets as Mt, BROWSE_DEFAULT_MODEL as N, hasSupportedBrowserInstalled as Nt, stopGateEnabledForRepo as O, createChatCompletions as Ot, DEFAULT_MODEL as P, provisionAndIndexColbert as Pt, ADVISOR_TOOL_INSTRUCTIONS as Q, withInstallLock as Qt, REVIEW_DEFAULT_MODEL as R, ArtifactClient as Rt, fileFindingsStore as S, createMessages as St, isSubagentContext as T, resolveMcpToolTimeoutMs as Tt, availableToolCommands as U, DEFAULT_CLAUDE_MODEL_FALLBACKS as Ut, withNoOutputRetry as V, collapsePathKeys as Vt, buildToolbeltAwareness as W, DEFAULT_CODEX_MODEL as Wt, searchWeb as X, pickClaudeDefault as Xt, assetFor as Y, generateRandomPort as Yt, ADVISOR_INTERNAL_TOOL_NAME as Z, getPackageVersion as Zt, stopGateDisabled as _, copilotBaseUrl as _n, nativeSubagentModel as _t, buildPeerAwarenessSnippet as a, cacheVSCodeVersion as an, logStreamError as at, stopReviewEnabled as b, state as bn, shimDefaultsToXhigh as bt, personasFor as c, resolveCodexModel as cn, handleMcpDelete as ct, buildStopHookCommand as d, getModels as dn, artifactToolsEnabled as dt, setupGitHubAgentToken as en, injectAdvisorTool as et, captureLaunchBaseline as f, getGitHubUser as fn, browseAgentEnabled as ft, launchBaselineKey as g, GITHUB_API_BASE_URL as gn, geminiAvailable as gt, injectStopHookIntoSettingsFile as h, forwardError as hn, fleetToolsEnabled as ht, buildAgentPrompt as i, cacheModels as in, isControllerClosedError as it, liveExec as j, parseJsonOrDiagnose as jt, stopReviewStateDir as k, MAX_RESPONSE_BODY_BYTES as kt, buildArtifactOpenHookCommand as l, resolveModel as ln, handleMcpPost as lt, fileBlockBudget as m, HTTPError as mn, browserToolsEnabled as mt, MCP_GROUPS as n, tryRefreshAndRetry as nn, buildAnthropicErrorEvent as nt, buildPeerAwarenessSummary as o, filterBetaHeader as on, readIteratorWithTimeout as ot, decideStopHook as p, fetchWithTransientRetry as pn, browserCompoundToolsEnabled as pt, vscodeRipgrepPath as q, UPSTREAM_FETCH_TIMEOUT_MS as qt, assertMcpToolSurfaceConsistent as r, cacheCopilotVersion as rn, buildOpenAIErrorEvent as rt, enumerateInjectedMcpToolNames as s, isNullish as sn, relayAnthropicStream as st, GROUP_META as t, setupGitHubToken as tn, isAdvisorRequested as tt, buildSessionBindHookCommand as u, sleep as un, agentToolsEnabled as ut, stopGateId as v, copilotHeaders as vn, standInToolEnabled as vt, fileReviewDebounce as w, assembleResponsesPayload as wt, fileBaselineStore as x, countTokens as xt, stopGatePlanMode as y, githubHeaders as yn, workerToolsEnabled as yt, appendPlanReminder as z, buildWorkspaceHeaderHelperCommand as zt };
31849
+ //# sourceMappingURL=peer-mcp-personas-rik0SIrg.js.map