github-router 0.3.273 → 0.3.275

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 (37) hide show
  1. package/dist/{attribution-settings-4nEQq_tn.js → attribution-settings-ZOaCUrYY.js} +4 -4
  2. package/dist/attribution-settings-ZOaCUrYY.js.map +1 -0
  3. package/dist/{auth-3so8RT91.js → auth-Q1tfmfCT.js} +2 -2
  4. package/dist/{auth-3so8RT91.js.map → auth-Q1tfmfCT.js.map} +1 -1
  5. package/dist/browser-ext/manifest.json +1 -1
  6. package/dist/{check-usage-goXyc3qS.js → check-usage-CHLz4tU_.js} +3 -3
  7. package/dist/{check-usage-goXyc3qS.js.map → check-usage-CHLz4tU_.js.map} +1 -1
  8. package/dist/{claude-BNZD-bQN.js → claude-Cl4gYoOZ.js} +7 -7
  9. package/dist/{claude-BNZD-bQN.js.map → claude-Cl4gYoOZ.js.map} +1 -1
  10. package/dist/{codex-C_MA9uy5.js → codex-D_IXUgKf.js} +5 -5
  11. package/dist/{codex-C_MA9uy5.js.map → codex-D_IXUgKf.js.map} +1 -1
  12. package/dist/engine-Drs3cxLW.js +2 -0
  13. package/dist/{gate-discovery-DvA4xObh.js → gate-discovery-Br448Md6.js} +2 -2
  14. package/dist/{gate-discovery-DvA4xObh.js.map → gate-discovery-Br448Md6.js.map} +1 -1
  15. package/dist/{get-copilot-usage-nZXbvSi8.js → get-copilot-usage-BRN18uMJ.js} +2 -2
  16. package/dist/{get-copilot-usage-nZXbvSi8.js.map → get-copilot-usage-BRN18uMJ.js.map} +1 -1
  17. package/dist/{internal-stop-hook-WVgnwt5U.js → internal-stop-hook-DMLQ8vRZ.js} +2 -2
  18. package/dist/{internal-stop-hook-WVgnwt5U.js.map → internal-stop-hook-DMLQ8vRZ.js.map} +1 -1
  19. package/dist/main.js +8 -8
  20. package/dist/{models-BmGGH6pP.js → models-d0gkuYGy.js} +2 -2
  21. package/dist/{models-BmGGH6pP.js.map → models-d0gkuYGy.js.map} +1 -1
  22. package/dist/{peer-mcp-personas-DAZU1OfN.js → peer-mcp-personas-TMOZJhfy.js} +566 -105
  23. package/dist/{peer-mcp-personas-DAZU1OfN.js.map → peer-mcp-personas-TMOZJhfy.js.map} +1 -1
  24. package/dist/{provision-C3UIA1Tf.js → provision-BJ5vUpmp.js} +2 -2
  25. package/dist/{provision-C3UIA1Tf.js.map → provision-BJ5vUpmp.js.map} +1 -1
  26. package/dist/{serve-DPgawWWq.js → serve-DMA82DFJ.js} +6 -6
  27. package/dist/{serve-DPgawWWq.js.map → serve-DMA82DFJ.js.map} +1 -1
  28. package/dist/{server-setup-I5KYkuxE.js → server-setup-CVfqSkh_.js} +6 -5
  29. package/dist/{server-setup-I5KYkuxE.js.map → server-setup-CVfqSkh_.js.map} +1 -1
  30. package/dist/{start-CWWqjjwm.js → start-BGze5TnZ.js} +3 -3
  31. package/dist/{start-CWWqjjwm.js.map → start-BGze5TnZ.js.map} +1 -1
  32. package/dist/{token-Bz7iN8US.js → token-Bz6HoH2H.js} +365 -46
  33. package/dist/token-Bz6HoH2H.js.map +1 -0
  34. package/package.json +1 -1
  35. package/dist/attribution-settings-4nEQq_tn.js.map +0 -1
  36. package/dist/engine-CHN8j6BV.js +0 -2
  37. package/dist/token-Bz7iN8US.js.map +0 -1
@@ -1,6 +1,6 @@
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-Bz7iN8US.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-Bz6HoH2H.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";
@@ -19052,14 +19052,42 @@ function currentInFlight() {
19052
19052
  //#endregion
19053
19053
  //#region src/lib/vision-preflight.ts
19054
19054
  /**
19055
- * Outbound vision preflight.
19055
+ * Outbound vision handling.
19056
19056
  *
19057
- * Converts what would otherwise be an opaque upstream `400` into a local,
19058
- * actionable rejection — the same trade `predictedWindowOverflow` in
19059
- * `src/routes/mcp/handler.ts` already makes for prompt tokens, and the reason
19060
- * this file exists at all: `capabilities.limits.vision` advertises three fields
19061
- * (`max_prompt_images`, `max_prompt_image_size`, `supported_media_types`) and
19062
- * until now the proxy read exactly one of them, in the `models` pretty-printer.
19057
+ * WHO DECIDES THE IMAGE LIMIT
19058
+ *
19059
+ * Copilot does, and this module no longer guesses. The catalog advertises a
19060
+ * `max_prompt_images` limit, and that field was measured against the live API
19061
+ * on 2026-08-10 across all 23 vision-capable models:
19062
+ *
19063
+ * - gemini-3.x catalog 10 → upstream enforces exactly 10
19064
+ * - gpt-5.6-sol catalog 1 → upstream enforces 50
19065
+ * - gpt-5.5 catalog 1 → accepted 120, no ceiling found
19066
+ * - claude-opus-5 catalog 1 → accepted 200, no ceiling found
19067
+ * - claude-sonnet/haiku catalog 5 → accepted 32+
19068
+ *
19069
+ * So the field is accurate for one family and understates the truth by 50x to
19070
+ * 200x everywhere else. Note the real ceiling is not even uniform WITHIN a
19071
+ * family: gpt-5.6-sol stops at 50 while gpt-5.5 took 120, which is the sharpest
19072
+ * argument against substituting one hardcoded number for another. A local cardinality reject built on it rejected at 2
19073
+ * what upstream serves at 50, and — because the count was taken over the whole
19074
+ * assembled payload including replayed history — the caller could not act on
19075
+ * the error, so every retry reproduced it and the session was finished.
19076
+ *
19077
+ * Upstream also enforces rules this module does not model at all (minimum pixel
19078
+ * dimensions on grok-4.5, per-model media-type support on gpt-4o), which is the
19079
+ * general argument: local pre-validation cannot be complete, and where it
19080
+ * guesses it is wrong.
19081
+ *
19082
+ * WHAT WE DO INSTEAD
19083
+ *
19084
+ * Send it, and recover from upstream's answer. Copilot's rejections name the
19085
+ * real number ("maximum allowed for model gemini-3.6-flash is 10, got 16",
19086
+ * "Exceeded maximum number of images (50) allowed in the request"), so
19087
+ * `parseUpstreamImageCeiling` reads it, `planOutboundImages` prunes to it, the
19088
+ * transport retries once, and `rememberImageCeiling` keeps it for the process
19089
+ * lifetime so the round trip is paid once per model per boot. The learned value
19090
+ * is an observation rather than a guess, and it self-heals if Copilot changes.
19063
19091
  *
19064
19092
  * WHY ONE CHOKEPOINT, NOT PER-ADAPTER CHECKS
19065
19093
  *
@@ -19067,38 +19095,82 @@ function currentInFlight() {
19067
19095
  * block, a block nested inside a `tool_result`, the synthetic follow-up user
19068
19096
  * message the shim emits because a tool-output item cannot carry images, images
19069
19097
  * already present in replayed conversation history, and peer-critic
19070
- * attachments. Validating in each adapter means each adapter has to
19098
+ * attachments. Handling this in each adapter means each adapter has to
19071
19099
  * rediscover every one of those shapes, and the ones it forgets fail silently.
19072
- * So validation runs ONCE, on the fully assembled payload, immediately before
19073
- * transport serialization `createResponses` and `createChatCompletions` and
19074
- * is therefore total by construction.
19100
+ * So it runs ONCE, on the fully assembled payload, immediately before transport
19101
+ * serialization, and is therefore total by construction.
19075
19102
  *
19076
- * POLICY ON MISSING METADATA
19103
+ * NOTHING HERE FAILS A REQUEST
19077
19104
  *
19078
- * Deliberately NOT fail-open. "We don't know the limit" is not "there is no
19079
- * limit"; treating it as the latter reproduces the exact opaque-400 this
19080
- * module exists to remove. The three cases are distinguished:
19105
+ * A defect that is fatal for a whole request is fatal forever once the image is
19106
+ * in replayed history, because the caller cannot edit history. So every defect
19107
+ * this module recognises drops that one image and replaces it IN PLACE with a
19108
+ * short text note the model can read and relay. In place, never deletion: a
19109
+ * turn whose only content was a screenshot would otherwise become an empty
19110
+ * content array, which upstream does reject.
19081
19111
  *
19082
- * - model absent from the catalog entirely ALLOW. We have no basis for a
19083
- * judgement, upstream remains authoritative, and blocking would break
19084
- * custom catalogs and offline tests. This mirrors `modelSupportsEndpoint`.
19085
- * - model present, `supports.vision` not true → REJECT, naming the model.
19086
- * - model present, vision supported, limits absent → CONSERVATIVE FLOOR
19087
- * (`FLOOR_MAX_IMAGES` / `FLOOR_MAX_IMAGE_BYTES`), and the message says so,
19088
- * so the caller can tell a real limit from an assumed one.
19089
- *
19090
- * Error strings are returned to callers and end up in front of a model, so they
19091
- * name the model, the numbers, and the fix — never a stack, a local path, or a
19092
- * raw catalog object.
19112
+ * Note text carries no ordinals and no running totals. Claude Code replays the
19113
+ * whole transcript every turn, so a note reading "image 1 of 2" would become
19114
+ * "image 1 of 3" on the next image and invalidate the prompt-cache prefix from
19115
+ * the earliest omission onward.
19093
19116
  */
19094
19117
  /**
19095
- * Floor applied when a model advertises vision but publishes no limits. Every
19096
- * vision-capable model in the live catalog reports at least 1 image and a
19097
- * 3 MiB ceiling, so this is the observed minimum rather than a guess.
19118
+ * Applied when a model advertises vision but publishes no size limit. Every
19119
+ * vision-capable model in the live catalog reports 3 MiB, so this is the
19120
+ * observed value rather than a guess. There is deliberately no image-COUNT
19121
+ * floor: that is the number upstream turned out to own.
19098
19122
  */
19099
- const FLOOR_MAX_IMAGES = 1;
19100
19123
  const FLOOR_MAX_IMAGE_BYTES = 3145728;
19101
19124
  /**
19125
+ * Ceilings observed from upstream rejections, keyed by model id. Process
19126
+ * lifetime only, and deliberately not persisted: a stale number on disk would
19127
+ * be exactly the catalog problem again, one indirection further away.
19128
+ */
19129
+ const learnedCeilings = /* @__PURE__ */ new Map();
19130
+ function learnedImageCeiling(modelId) {
19131
+ return learnedCeilings.get(modelId);
19132
+ }
19133
+ function rememberImageCeiling(modelId, ceiling) {
19134
+ if (!Number.isInteger(ceiling) || ceiling < 1) return;
19135
+ learnedCeilings.set(modelId, ceiling);
19136
+ }
19137
+ /** True when anything has been learned at all — a cheap pre-parse gate. */
19138
+ function hasLearnedImageCeilings() {
19139
+ return learnedCeilings.size > 0;
19140
+ }
19141
+ /**
19142
+ * Both rejection shapes Copilot was observed to emit carry the real ceiling:
19143
+ *
19144
+ * too many images: maximum allowed for model gemini-3.6-flash is 10, got 16
19145
+ * Exceeded maximum number of images (50) allowed in the request.
19146
+ *
19147
+ * Anything else returns `undefined`, and the caller forwards upstream's error
19148
+ * untouched. A parser that guesses would reintroduce the failure this module
19149
+ * was rewritten to remove.
19150
+ */
19151
+ const CEILING_PATTERNS = [/maximum allowed for model \S+ is (\d+)/i, /exceeded maximum number of images \((\d+)\)/i];
19152
+ function parseUpstreamImageCeiling(body) {
19153
+ if (!/image/i.test(body)) return void 0;
19154
+ for (const pattern of CEILING_PATTERNS) {
19155
+ const match = pattern.exec(body);
19156
+ if (!match) continue;
19157
+ const ceiling = Number(match[1]);
19158
+ if (Number.isInteger(ceiling) && ceiling >= 1 && ceiling <= 1e4) return ceiling;
19159
+ }
19160
+ }
19161
+ /**
19162
+ * Read an error body without consuming it, so the existing error path can still
19163
+ * report the same text downstream. Never throws: a body we cannot read simply
19164
+ * yields no ceiling and upstream's error is forwarded as it always was.
19165
+ */
19166
+ async function peekErrorBody(response) {
19167
+ try {
19168
+ return await response.clone().text();
19169
+ } catch {
19170
+ return "";
19171
+ }
19172
+ }
19173
+ /**
19102
19174
  * Split a `data:<mime>;base64,<payload>` URI. Returns `null` for any other URL
19103
19175
  * shape (including a plain remote `https://` reference, which the caller
19104
19176
  * handles separately because its bytes are not ours to inspect).
@@ -19111,45 +19183,162 @@ function parseDataUrl(url) {
19111
19183
  base64: match[2]
19112
19184
  };
19113
19185
  }
19114
- function reject(message) {
19186
+ /**
19187
+ * Judge one image on its own merits. Returns `undefined` when it is fine.
19188
+ *
19189
+ * Remote-URL images are never judged here: the bytes live on someone else's
19190
+ * server, so any local claim about them would be fiction.
19191
+ */
19192
+ function imageDefect(image, modelId, maxBytes, assumed, allowedTypes) {
19193
+ if (image.url !== void 0 && image.base64 === void 0) return void 0;
19194
+ if (image.declaredMimeType === void 0 || image.declaredMimeType.length === 0) return {
19195
+ reason: "no media type declared",
19196
+ note: "[image removed: no media type was declared, so it could not be sent]"
19197
+ };
19198
+ if (image.base64 === void 0) return void 0;
19199
+ const bytes = decodeBase64Strict(image.base64);
19200
+ if (!bytes) return {
19201
+ reason: "not valid base64",
19202
+ note: "[image removed: the image data was not valid base64]"
19203
+ };
19204
+ if (bytes.length > maxBytes) return {
19205
+ reason: `${bytes.length} bytes over model ${modelId}'s ${maxBytes}-byte limit${assumed}`,
19206
+ note: `[image removed: it is over this model's ${maxBytes}-byte limit; re-capture at a smaller scale or lower quality]`
19207
+ };
19208
+ const actual = detectImageMimeType(bytes);
19209
+ if (!actual) return {
19210
+ reason: `declared ${image.declaredMimeType} but the bytes are not a supported image`,
19211
+ note: `[image removed: it is declared ${image.declaredMimeType} but its bytes are not a supported image (jpeg, png, webp, gif, heic, heif)]`
19212
+ };
19213
+ if (actual !== image.declaredMimeType) return {
19214
+ reason: `declared ${image.declaredMimeType} but the bytes are ${actual}`,
19215
+ note: `[image removed: it is declared ${image.declaredMimeType} but its bytes are ${actual}; send the correct media type]`
19216
+ };
19217
+ if (allowedTypes && allowedTypes.length > 0 && !allowedTypes.includes(actual)) return {
19218
+ reason: `${actual} is not in model ${modelId}'s accepted media types`,
19219
+ note: `[image removed: ${actual} is not accepted by this model; it accepts ${allowedTypes.join(", ")}]`
19220
+ };
19221
+ }
19222
+ function keepAll(count) {
19115
19223
  return {
19116
- ok: false,
19117
- message
19224
+ verdicts: Array.from({ length: count }, () => ({ keep: true })),
19225
+ kept: count,
19226
+ dropped: 0
19118
19227
  };
19119
19228
  }
19120
19229
  /**
19121
- * Validate every image on an outbound request against the resolved model's
19122
- * advertised vision capability.
19230
+ * Decide, per image, what goes on the wire.
19123
19231
  *
19124
- * Remote-URL images are counted toward the cardinality limit but not size- or
19125
- * type-checked: the bytes live on someone else's server, so any local claim
19126
- * about them would be fiction. Upstream stays authoritative for those.
19232
+ * `maxImages` is the CARDINALITY budget, and it comes only from a ceiling
19233
+ * upstream actually stated never from the catalog, whose `max_prompt_images`
19234
+ * was measured wrong for 20 of 23 models. Omit it and no image is dropped for
19235
+ * being one too many.
19236
+ *
19237
+ * Validity is judged BEFORE the budget so a malformed image cannot consume a
19238
+ * slot and evict a good one, and the budget pass never rewrites a verdict the
19239
+ * validity pass already set — a malformed image must not be reported as a
19240
+ * cardinality eviction.
19127
19241
  */
19128
- function checkOutboundImages(modelId, images) {
19129
- if (images.length === 0) return { ok: true };
19242
+ function planOutboundImages(modelId, images, options) {
19243
+ if (images.length === 0) return {
19244
+ verdicts: [],
19245
+ kept: 0,
19246
+ dropped: 0
19247
+ };
19130
19248
  const model = state.models?.data.find((m) => m.id === modelId);
19131
- if (!model) return { ok: true };
19132
- if ((model.capabilities?.supports)?.vision !== true) return reject(`Model ${modelId} does not support image input. Send text only, or select a vision-capable model.`);
19133
- const limits = model.capabilities?.limits?.vision;
19134
- const maxImages = limits?.max_prompt_images ?? FLOOR_MAX_IMAGES;
19249
+ const maxImages = options?.maxImages;
19250
+ if (!model) {
19251
+ if (maxImages === void 0) return keepAll(images.length);
19252
+ }
19253
+ const supports = model?.capabilities?.supports;
19254
+ if (model && supports?.vision !== true) {
19255
+ const note = `[image removed: model ${modelId} does not accept image input; select a vision-capable model to send images]`;
19256
+ return {
19257
+ verdicts: images.map(() => ({
19258
+ keep: false,
19259
+ reason: `model ${modelId} does not support image input`,
19260
+ note
19261
+ })),
19262
+ kept: 0,
19263
+ dropped: images.length
19264
+ };
19265
+ }
19266
+ const limits = model?.capabilities?.limits?.vision;
19135
19267
  const maxBytes = limits?.max_prompt_image_size ?? FLOOR_MAX_IMAGE_BYTES;
19136
- const assumed = limits?.max_prompt_images === void 0 ? " (assumed; the model publishes no image limits)" : "";
19137
- if (images.length > maxImages) return reject(`Model ${modelId} accepts at most ${maxImages} image(s) per request${assumed}, but this request carries ${images.length}. Send fewer images, or use a model with a higher image limit.`);
19268
+ const assumed = limits?.max_prompt_image_size === void 0 ? " (assumed; the model publishes no image size limit)" : "";
19138
19269
  const allowedTypes = limits?.supported_media_types;
19139
- for (const [index, image] of images.entries()) {
19140
- if (image.url !== void 0 && image.base64 === void 0) continue;
19141
- const position = `image ${index + 1} of ${images.length}`;
19142
- if (image.declaredMimeType === void 0 || image.declaredMimeType.length === 0) return reject(`${position} has no media type. Anthropic's \`source.media_type\` (or a \`data:<mime>;base64,\` prefix) is required — it used to be defaulted, which silently asserted a type the model may not accept.`);
19143
- if (image.base64 === void 0) continue;
19144
- const bytes = decodeBase64Strict(image.base64);
19145
- if (!bytes) return reject(`${position} is not valid base64 and cannot be sent.`);
19146
- if (bytes.length > maxBytes) return reject(`${position} is ${bytes.length} bytes, over model ${modelId}'s ${maxBytes}-byte limit${assumed}. Re-capture at a smaller scale or lower quality.`);
19147
- const actual = detectImageMimeType(bytes);
19148
- if (!actual) return reject(`${position} is declared ${image.declaredMimeType} but its bytes are not a supported image (jpeg, png, webp, gif, heic, heif).`);
19149
- if (actual !== image.declaredMimeType) return reject(`${position} is declared ${image.declaredMimeType} but its bytes are ${actual}. Send the correct media type.`);
19150
- if (allowedTypes && allowedTypes.length > 0 && !allowedTypes.includes(actual)) return reject(`${position} is ${actual}, which model ${modelId} does not accept. Supported: ${allowedTypes.join(", ")}.`);
19270
+ const verdicts = images.map((image) => {
19271
+ const defect = model ? imageDefect(image, modelId, maxBytes, assumed, allowedTypes) : imageDefect(image, modelId, Number.POSITIVE_INFINITY, "", void 0);
19272
+ return defect ? {
19273
+ keep: false,
19274
+ reason: defect.reason,
19275
+ note: defect.note
19276
+ } : { keep: true };
19277
+ });
19278
+ if (maxImages !== void 0) {
19279
+ const overflowNote = `[image removed: this model accepts at most ${maxImages} image${maxImages === 1 ? "" : "s"} per request, so only the most recent were sent]`;
19280
+ let admitted = 0;
19281
+ for (let index = verdicts.length - 1; index >= 0; index--) {
19282
+ const verdict = verdicts[index];
19283
+ if (!verdict.keep) continue;
19284
+ if (admitted < maxImages) {
19285
+ admitted++;
19286
+ continue;
19287
+ }
19288
+ verdict.keep = false;
19289
+ verdict.reason = `over model ${modelId}'s ${maxImages}-image ceiling`;
19290
+ verdict.note = overflowNote;
19291
+ }
19151
19292
  }
19152
- return { ok: true };
19293
+ const kept = verdicts.filter((v) => v.keep).length;
19294
+ return {
19295
+ verdicts,
19296
+ kept,
19297
+ dropped: verdicts.length - kept
19298
+ };
19299
+ }
19300
+ /**
19301
+ * Emit one warn line per drop. Rewriting a request body on the hot path with no
19302
+ * record is not acceptable: the note is addressed to the model, and the model
19303
+ * may or may not relay it, so the operator needs their own channel.
19304
+ */
19305
+ function logImagePlan(modelId, plan) {
19306
+ if (plan.dropped === 0) return;
19307
+ const reasons = [...new Set(plan.verdicts.filter((v) => !v.keep).map((v) => v.reason))];
19308
+ consola.warn(`Dropped ${plan.dropped} of ${plan.verdicts.length} image(s) bound for ${modelId} (${plan.kept} kept): ${reasons.join("; ")}`);
19309
+ }
19310
+ function responsesImageUrl(part) {
19311
+ if (part === null || typeof part !== "object") return void 0;
19312
+ const p = part;
19313
+ if (p.type !== "input_image" || typeof p.image_url !== "string") return void 0;
19314
+ return p.image_url;
19315
+ }
19316
+ function chatImageUrl(part) {
19317
+ if (part === null || typeof part !== "object") return void 0;
19318
+ const p = part;
19319
+ if (p.type !== "image_url") return void 0;
19320
+ const url = p.image_url?.url;
19321
+ return typeof url === "string" ? url : void 0;
19322
+ }
19323
+ /** Anthropic-native `{type:"image", source:{type:"base64", media_type, data}}`. */
19324
+ function anthropicImage(part) {
19325
+ if (part === null || typeof part !== "object") return void 0;
19326
+ const p = part;
19327
+ if (p.type !== "image") return void 0;
19328
+ const source = p.source;
19329
+ if (!source) return void 0;
19330
+ if (typeof source.url === "string" && typeof source.data !== "string") return { url: source.url };
19331
+ return {
19332
+ base64: typeof source.data === "string" ? source.data : void 0,
19333
+ declaredMimeType: typeof source.media_type === "string" ? source.media_type : void 0
19334
+ };
19335
+ }
19336
+ function fromUrl(url) {
19337
+ const parsed = parseDataUrl(url);
19338
+ return parsed ? {
19339
+ base64: parsed.base64,
19340
+ declaredMimeType: parsed.mimeType
19341
+ } : { url };
19153
19342
  }
19154
19343
  /** Collect the images on an assembled Copilot `/responses` payload. */
19155
19344
  function imagesInResponsesPayload(input) {
@@ -19160,10 +19349,8 @@ function imagesInResponsesPayload(input) {
19160
19349
  const content = item.content;
19161
19350
  if (!Array.isArray(content)) continue;
19162
19351
  for (const part of content) {
19163
- if (part === null || typeof part !== "object") continue;
19164
- const p = part;
19165
- if (p.type !== "input_image" || typeof p.image_url !== "string") continue;
19166
- images.push(fromUrl(p.image_url));
19352
+ const url = responsesImageUrl(part);
19353
+ if (url !== void 0) images.push(fromUrl(url));
19167
19354
  }
19168
19355
  }
19169
19356
  return images;
@@ -19177,40 +19364,167 @@ function imagesInChatPayload(messages) {
19177
19364
  const content = message.content;
19178
19365
  if (!Array.isArray(content)) continue;
19179
19366
  for (const part of content) {
19180
- if (part === null || typeof part !== "object") continue;
19181
- const p = part;
19182
- if (p.type !== "image_url") continue;
19183
- const url = p.image_url?.url;
19184
- if (typeof url !== "string") continue;
19185
- images.push(fromUrl(url));
19367
+ const url = chatImageUrl(part);
19368
+ if (url !== void 0) images.push(fromUrl(url));
19186
19369
  }
19187
19370
  }
19188
19371
  return images;
19189
19372
  }
19190
- function fromUrl(url) {
19191
- const parsed = parseDataUrl(url);
19192
- return parsed ? {
19193
- base64: parsed.base64,
19194
- declaredMimeType: parsed.mimeType
19195
- } : { url };
19196
- }
19197
19373
  /**
19198
- * Run the preflight and throw a client-visible 400 when it fails.
19374
+ * Visit every Anthropic image part in order, descending into the nested
19375
+ * `content` a `tool_result` carries.
19199
19376
  *
19200
- * Shaped as an `HTTPError` carrying a synthetic `Response` so it flows through
19201
- * the existing `forwardError` path and reaches the client as a normal
19202
- * Anthropic-format `invalid_request_error` — the same envelope an upstream
19203
- * rejection would produce, except it names the actual problem and no upstream
19204
- * request was made. Tests assert that second property: a preflight failure must
19205
- * cost zero upstream calls.
19377
+ * The extractor and the pruner BOTH drive off this one walker, so their
19378
+ * traversal orders cannot drift apart which is the failure that would drop
19379
+ * the wrong image.
19206
19380
  */
19207
- function assertOutboundImagesOk(modelId, images) {
19208
- const verdict = checkOutboundImages(modelId, images);
19209
- if (verdict.ok) return;
19210
- throw new HTTPError(verdict.message, new Response(JSON.stringify({ error: { message: verdict.message } }), {
19211
- status: 400,
19212
- headers: { "content-type": "application/json" }
19213
- }));
19381
+ function walkAnthropicParts(part, visit) {
19382
+ const image = anthropicImage(part);
19383
+ if (image !== void 0) {
19384
+ visit(image);
19385
+ return;
19386
+ }
19387
+ if (part === null || typeof part !== "object") return;
19388
+ const nested = part.content;
19389
+ if (!Array.isArray(nested)) return;
19390
+ for (const inner of nested) walkAnthropicParts(inner, visit);
19391
+ }
19392
+ /** Collect the images on an Anthropic-native `/v1/messages` body. */
19393
+ function imagesInAnthropicMessages(messages) {
19394
+ const images = [];
19395
+ if (!Array.isArray(messages)) return images;
19396
+ for (const message of messages) {
19397
+ if (message === null || typeof message !== "object") continue;
19398
+ const content = message.content;
19399
+ if (!Array.isArray(content)) continue;
19400
+ for (const part of content) walkAnthropicParts(part, (image) => images.push(image));
19401
+ }
19402
+ return images;
19403
+ }
19404
+ /**
19405
+ * Thrown when the pruner's walk does not visit exactly as many images as the
19406
+ * planner judged. Fail loudly: defaulting an unjudged image to "keep" would
19407
+ * turn a traversal-drift bug into a silently leaked image.
19408
+ */
19409
+ var ImageIndexDriftError = class extends Error {};
19410
+ function assertConsumed(imageIndex, verdicts) {
19411
+ if (imageIndex !== verdicts.length) throw new ImageIndexDriftError(`image traversal drift: pruner visited ${imageIndex} image(s), planner judged ${verdicts.length}`);
19412
+ }
19413
+ /**
19414
+ * Replace each dropped image with a text part IN PLACE, preserving position.
19415
+ * Untouched items and parts keep their original object identity, so nothing is
19416
+ * needlessly copied and the caller's payload is never mutated.
19417
+ */
19418
+ function pruneImagesFromResponsesInput(input, verdicts) {
19419
+ if (!Array.isArray(input)) return input;
19420
+ let imageIndex = 0;
19421
+ const out = input.map((item) => {
19422
+ if (item === null || typeof item !== "object") return item;
19423
+ const content = item.content;
19424
+ if (!Array.isArray(content)) return item;
19425
+ let replaced = false;
19426
+ const parts = content.map((part) => {
19427
+ if (responsesImageUrl(part) === void 0) return part;
19428
+ const verdict = verdicts[imageIndex++];
19429
+ if (!verdict || verdict.keep) return part;
19430
+ replaced = true;
19431
+ return {
19432
+ type: "input_text",
19433
+ text: verdict.note
19434
+ };
19435
+ });
19436
+ return replaced ? {
19437
+ ...item,
19438
+ content: parts
19439
+ } : item;
19440
+ });
19441
+ assertConsumed(imageIndex, verdicts);
19442
+ return out;
19443
+ }
19444
+ function pruneImagesFromChatMessages(messages, verdicts) {
19445
+ if (!Array.isArray(messages)) return messages;
19446
+ let imageIndex = 0;
19447
+ const out = messages.map((message) => {
19448
+ if (message === null || typeof message !== "object") return message;
19449
+ const content = message.content;
19450
+ if (!Array.isArray(content)) return message;
19451
+ let replaced = false;
19452
+ const parts = content.map((part) => {
19453
+ if (chatImageUrl(part) === void 0) return part;
19454
+ const verdict = verdicts[imageIndex++];
19455
+ if (!verdict || verdict.keep) return part;
19456
+ replaced = true;
19457
+ return {
19458
+ type: "text",
19459
+ text: verdict.note
19460
+ };
19461
+ });
19462
+ return replaced ? {
19463
+ ...message,
19464
+ content: parts
19465
+ } : message;
19466
+ });
19467
+ assertConsumed(imageIndex, verdicts);
19468
+ return out;
19469
+ }
19470
+ function pruneImagesFromAnthropicMessages(messages, verdicts) {
19471
+ if (!Array.isArray(messages)) return messages;
19472
+ let imageIndex = 0;
19473
+ const replacePart = (part) => {
19474
+ if (anthropicImage(part) !== void 0) {
19475
+ const verdict = verdicts[imageIndex++];
19476
+ if (!verdict || verdict.keep) return {
19477
+ part,
19478
+ replaced: false
19479
+ };
19480
+ return {
19481
+ part: {
19482
+ type: "text",
19483
+ text: verdict.note
19484
+ },
19485
+ replaced: true
19486
+ };
19487
+ }
19488
+ if (part !== null && typeof part === "object") {
19489
+ const nested = part.content;
19490
+ if (Array.isArray(nested)) {
19491
+ let nestedReplaced = false;
19492
+ const inner = nested.map((innerPart) => {
19493
+ const result = replacePart(innerPart);
19494
+ if (result.replaced) nestedReplaced = true;
19495
+ return result.part;
19496
+ });
19497
+ if (nestedReplaced) return {
19498
+ part: {
19499
+ ...part,
19500
+ content: inner
19501
+ },
19502
+ replaced: true
19503
+ };
19504
+ }
19505
+ }
19506
+ return {
19507
+ part,
19508
+ replaced: false
19509
+ };
19510
+ };
19511
+ const out = messages.map((message) => {
19512
+ if (message === null || typeof message !== "object") return message;
19513
+ const content = message.content;
19514
+ if (!Array.isArray(content)) return message;
19515
+ let replaced = false;
19516
+ const parts = content.map((part) => {
19517
+ const result = replacePart(part);
19518
+ if (result.replaced) replaced = true;
19519
+ return result.part;
19520
+ });
19521
+ return replaced ? {
19522
+ ...message,
19523
+ content: parts
19524
+ } : message;
19525
+ });
19526
+ assertConsumed(imageIndex, verdicts);
19527
+ return out;
19214
19528
  }
19215
19529
  //#endregion
19216
19530
  //#region src/lib/diagnose-response.ts
@@ -19336,8 +19650,35 @@ async function readResponseBodyCapped(response, routePath, capBytes = MAX_RESPON
19336
19650
  */
19337
19651
  const createChatCompletions = async (payload, modelHeaders, callerSignal, retryTransient = false) => {
19338
19652
  if (!state.copilotToken) throw new Error("Copilot token not found");
19339
- const enableVision = payload.messages.some((x) => typeof x.content !== "string" && x.content?.some((x) => x.type === "image_url"));
19340
- if (enableVision) assertOutboundImagesOk(payload.model, imagesInChatPayload(payload.messages));
19653
+ const carriesImages = payload.messages.some((x) => typeof x.content !== "string" && x.content?.some((x) => x.type === "image_url"));
19654
+ let enableVision = carriesImages;
19655
+ /**
19656
+ * Apply a cardinality budget plus the per-image checks on the fully assembled
19657
+ * payload — the single outbound chokepoint, so every path that can introduce
19658
+ * an image (top-level block, nested tool_result, the shim's synthetic
19659
+ * follow-up user message, replayed history, peer attachments) is covered
19660
+ * without each of them re-deriving the rules.
19661
+ *
19662
+ * `enableVision` is recomputed: if nothing survives, sending
19663
+ * `copilot-vision-request: true` would trade one 400 for another.
19664
+ */
19665
+ const applyImagePlan = (maxImages) => {
19666
+ try {
19667
+ const plan = planOutboundImages(payload.model, imagesInChatPayload(payload.messages), maxImages === void 0 ? void 0 : { maxImages });
19668
+ if (plan.dropped === 0) return false;
19669
+ logImagePlan(payload.model, plan);
19670
+ payload = {
19671
+ ...payload,
19672
+ messages: pruneImagesFromChatMessages(payload.messages, plan.verdicts)
19673
+ };
19674
+ enableVision = plan.kept > 0;
19675
+ return true;
19676
+ } catch (error) {
19677
+ consola.warn(`Image pruning skipped for ${payload.model}: ${String(error)}`);
19678
+ return false;
19679
+ }
19680
+ };
19681
+ if (carriesImages) applyImagePlan(learnedImageCeiling(payload.model));
19341
19682
  const isAgentCall = payload.messages.some((msg) => ["assistant", "tool"].includes(msg.role));
19342
19683
  const url = `${copilotBaseUrl(state)}/chat/completions`;
19343
19684
  const doFetch = () => {
@@ -19358,10 +19699,21 @@ const createChatCompletions = async (payload, modelHeaders, callerSignal, retryT
19358
19699
  return fetch(url, fetchInit);
19359
19700
  };
19360
19701
  const withRefresh = () => tryRefreshAndRetry(doFetch, "/chat/completions");
19361
- const response = retryTransient ? await fetchWithTransientRetry(withRefresh, {
19702
+ const send = () => retryTransient ? fetchWithTransientRetry(withRefresh, {
19362
19703
  signal: callerSignal,
19363
19704
  label: "/chat/completions"
19364
- }) : await withRefresh();
19705
+ }) : withRefresh();
19706
+ let response = await send();
19707
+ if (!response.ok && carriesImages) {
19708
+ const ceiling = parseUpstreamImageCeiling(await peekErrorBody(response));
19709
+ if (ceiling !== void 0) {
19710
+ rememberImageCeiling(payload.model, ceiling);
19711
+ if (applyImagePlan(ceiling)) {
19712
+ response.body?.cancel();
19713
+ response = await send();
19714
+ }
19715
+ }
19716
+ }
19365
19717
  if (!response.ok) {
19366
19718
  let errorBody;
19367
19719
  try {
@@ -19400,8 +19752,32 @@ const createChatCompletions = async (payload, modelHeaders, callerSignal, retryT
19400
19752
  */
19401
19753
  const createResponses = async (payload, modelHeaders, callerSignal, retryTransient = false) => {
19402
19754
  if (!state.copilotToken) throw new Error("Copilot token not found");
19403
- const enableVision = detectVision(payload.input);
19404
- if (enableVision) assertOutboundImagesOk(payload.model, imagesInResponsesPayload(payload.input));
19755
+ const carriesImages = detectVision(payload.input);
19756
+ let enableVision = carriesImages;
19757
+ /**
19758
+ * Apply a cardinality budget plus the per-image checks, rewriting `payload`
19759
+ * in place of the caller's object. Returns whether anything changed.
19760
+ *
19761
+ * `enableVision` is recomputed here: if nothing survives, sending
19762
+ * `copilot-vision-request: true` would trade one 400 for another.
19763
+ */
19764
+ const applyImagePlan = (maxImages) => {
19765
+ try {
19766
+ const plan = planOutboundImages(payload.model, imagesInResponsesPayload(payload.input), maxImages === void 0 ? void 0 : { maxImages });
19767
+ if (plan.dropped === 0) return false;
19768
+ logImagePlan(payload.model, plan);
19769
+ payload = {
19770
+ ...payload,
19771
+ input: pruneImagesFromResponsesInput(payload.input, plan.verdicts)
19772
+ };
19773
+ enableVision = plan.kept > 0;
19774
+ return true;
19775
+ } catch (error) {
19776
+ consola.warn(`Image pruning skipped for ${payload.model}: ${String(error)}`);
19777
+ return false;
19778
+ }
19779
+ };
19780
+ if (carriesImages) applyImagePlan(learnedImageCeiling(payload.model));
19405
19781
  const isAgentCall = detectAgentCall(payload.input);
19406
19782
  const url = `${copilotBaseUrl(state)}/responses`;
19407
19783
  const doFetch = () => {
@@ -19422,10 +19798,21 @@ const createResponses = async (payload, modelHeaders, callerSignal, retryTransie
19422
19798
  return fetch(url, fetchInit);
19423
19799
  };
19424
19800
  const withRefresh = () => tryRefreshAndRetry(doFetch, "/responses");
19425
- const response = retryTransient ? await fetchWithTransientRetry(withRefresh, {
19801
+ const send = () => retryTransient ? fetchWithTransientRetry(withRefresh, {
19426
19802
  signal: callerSignal,
19427
19803
  label: "/responses"
19428
- }) : await withRefresh();
19804
+ }) : withRefresh();
19805
+ let response = await send();
19806
+ if (!response.ok && carriesImages) {
19807
+ const ceiling = parseUpstreamImageCeiling(await peekErrorBody(response));
19808
+ if (ceiling !== void 0) {
19809
+ rememberImageCeiling(payload.model, ceiling);
19810
+ if (applyImagePlan(ceiling)) {
19811
+ response.body?.cancel();
19812
+ response = await send();
19813
+ }
19814
+ }
19815
+ }
19429
19816
  if (!response.ok) {
19430
19817
  let bodyText;
19431
19818
  try {
@@ -25498,7 +25885,7 @@ function capToolResultText(content, capBytes) {
25498
25885
  * loaded into memory, let alone base64-expanded by a third.
25499
25886
  *
25500
25887
  * The per-model check still runs later at the transport boundary
25501
- * (`assertOutboundImagesOk`); this is the cheap guard, not the authority.
25888
+ * (`planOutboundImages`); this is the cheap guard, not the authority.
25502
25889
  */
25503
25890
  const MAX_ATTACHMENT_BYTES = 3145728;
25504
25891
  const MAX_TOTAL_ATTACHMENT_BYTES = 12582912;
@@ -25522,7 +25909,7 @@ const READ_FLAGS = typeof constants.O_NOFOLLOW === "number" ? constants.O_RDONLY
25522
25909
  async function loadPeerImages(paths, workspace) {
25523
25910
  if (paths.length > 10) return {
25524
25911
  ok: false,
25525
- error: `imagePaths: ${paths.length} paths exceeds the 10-image ceiling (the most any Copilot model accepts). Send fewer.`
25912
+ error: `imagePaths: ${paths.length} paths exceeds the 10-image per-call budget. Send fewer, or split across calls.`
25526
25913
  };
25527
25914
  let workspaceAbs;
25528
25915
  try {
@@ -25857,6 +26244,67 @@ function buildHeaders(extraHeaders) {
25857
26244
  };
25858
26245
  }
25859
26246
  /**
26247
+ * Prune the images in a parsed Anthropic request body down to `ceiling` and
26248
+ * re-serialize. Returns `undefined` when nothing needed dropping.
26249
+ *
26250
+ * Never throws. A latent traversal bug in the pruner must not convert an error
26251
+ * we could have forwarded into a proxy crash — the entire point of this change
26252
+ * is that an image problem stops being fatal.
26253
+ *
26254
+ * This is the one place the proxy re-serializes a `/v1/messages` body it would
26255
+ * otherwise forward byte-for-byte, so it inherits the usual JSON round-trip
26256
+ * caveat for integers beyond 2^53. It runs only when a ceiling is in hand:
26257
+ * either one upstream just stated, or one learned earlier in this process.
26258
+ */
26259
+ function applyCeiling(parsed, ceiling) {
26260
+ const model = typeof parsed.model === "string" ? parsed.model : "";
26261
+ try {
26262
+ const plan = planOutboundImages(model, imagesInAnthropicMessages(parsed.messages), { maxImages: ceiling });
26263
+ if (plan.dropped === 0) return void 0;
26264
+ logImagePlan(model, plan);
26265
+ return JSON.stringify({
26266
+ ...parsed,
26267
+ messages: pruneImagesFromAnthropicMessages(parsed.messages, plan.verdicts)
26268
+ });
26269
+ } catch (error) {
26270
+ consola.warn(`Image pruning skipped for ${model || "unknown model"}: ${String(error)}`);
26271
+ return;
26272
+ }
26273
+ }
26274
+ function parseBody(body) {
26275
+ try {
26276
+ return JSON.parse(body);
26277
+ } catch {
26278
+ return;
26279
+ }
26280
+ }
26281
+ /** Prune to a ceiling this process already learned for the body's own model. */
26282
+ function pruneToLearnedCeiling(body) {
26283
+ const parsed = parseBody(body);
26284
+ if (!parsed) return void 0;
26285
+ const model = typeof parsed.model === "string" ? parsed.model : "";
26286
+ if (model.length === 0) return void 0;
26287
+ const ceiling = learnedImageCeiling(model);
26288
+ return ceiling === void 0 ? void 0 : applyCeiling(parsed, ceiling);
26289
+ }
26290
+ /** Prune to a ceiling upstream just stated, and remember it for next time. */
26291
+ function pruneToStatedCeiling(body, ceiling) {
26292
+ const parsed = parseBody(body);
26293
+ if (!parsed) return void 0;
26294
+ const model = typeof parsed.model === "string" ? parsed.model : "";
26295
+ if (model.length > 0) rememberImageCeiling(model, ceiling);
26296
+ return applyCeiling(parsed, ceiling);
26297
+ }
26298
+ /**
26299
+ * Cheap pre-parse gate for the proactive path only. Whitespace-tolerant: a
26300
+ * client that pretty-prints its JSON still matches. Deliberately NOT used to
26301
+ * gate the recovery path — gating recovery on a string probe means a probe miss
26302
+ * silently restores the fatal 400 this whole mechanism removes.
26303
+ */
26304
+ function mayCarryImages(body) {
26305
+ return /"type"\s*:\s*"image"/.test(body);
26306
+ }
26307
+ /**
25860
26308
  * Forward an Anthropic Messages API request to Copilot's native /v1/messages endpoint.
25861
26309
  * Returns the raw Response so callers can handle streaming vs non-streaming.
25862
26310
  *
@@ -25879,6 +26327,7 @@ async function createMessages(body, extraHeaders, callerSignal, retryTransient =
25879
26327
  if (!state.copilotToken) throw new Error("Copilot token not found");
25880
26328
  const url = `${copilotBaseUrl(state)}/v1/messages?beta=true`;
25881
26329
  consola.debug(`Forwarding to ${url}`);
26330
+ if (hasLearnedImageCeilings() && mayCarryImages(body)) body = pruneToLearnedCeiling(body) ?? body;
25882
26331
  const doFetch = () => {
25883
26332
  const fetchInit = {
25884
26333
  method: "POST",
@@ -25893,10 +26342,22 @@ async function createMessages(body, extraHeaders, callerSignal, retryTransient =
25893
26342
  return fetch(url, fetchInit);
25894
26343
  };
25895
26344
  const withRefresh = () => tryRefreshAndRetry(doFetch, "/v1/messages");
25896
- const response = retryTransient ? await fetchWithTransientRetry(withRefresh, {
26345
+ const send = () => retryTransient ? fetchWithTransientRetry(withRefresh, {
25897
26346
  signal: callerSignal,
25898
26347
  label: "/v1/messages"
25899
- }) : await withRefresh();
26348
+ }) : withRefresh();
26349
+ let response = await send();
26350
+ if (!response.ok) {
26351
+ const ceiling = parseUpstreamImageCeiling(await peekErrorBody(response));
26352
+ if (ceiling !== void 0) {
26353
+ const pruned = pruneToStatedCeiling(body, ceiling);
26354
+ if (pruned !== void 0) {
26355
+ response.body?.cancel();
26356
+ body = pruned;
26357
+ response = await send();
26358
+ }
26359
+ }
26360
+ }
25900
26361
  if (!response.ok) {
25901
26362
  let errorBody;
25902
26363
  try {
@@ -26461,7 +26922,7 @@ function toolEntries(scope) {
26461
26922
  imagePaths: {
26462
26923
  type: "array",
26463
26924
  items: { type: "string" },
26464
- description: "Optional paths to image files (screenshots, diagrams, charts) INSIDE the workspace for the persona to LOOK AT. The proxy reads and encodes them, so no image data passes through your context. Content is identified by bytes, not extension; jpeg/png/webp/gif/heic/heif, 3 MiB each. Note paths are confined to the proxy's working directory. Note the per-model ceiling: the gemini-backed personas accept 10 images, the gpt- and opus-backed ones accept 1."
26925
+ description: "Optional paths to image files (screenshots, diagrams, charts) INSIDE the workspace for the persona to LOOK AT. The proxy reads and encodes them, so no image data passes through your context. Content is identified by bytes, not extension; jpeg/png/webp/gif/heic/heif, 3 MiB each and 12 MiB in total, up to 10 per call. Note paths are confined to the proxy's working directory."
26465
26926
  },
26466
26927
  effort: {
26467
26928
  type: "string",
@@ -34598,4 +35059,4 @@ function enumerateInjectedMcpToolNames(groupKeys, opts = {}) {
34598
35059
  //#endregion
34599
35060
  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 };
34600
35061
 
34601
- //# sourceMappingURL=peer-mcp-personas-DAZU1OfN.js.map
35062
+ //# sourceMappingURL=peer-mcp-personas-TMOZJhfy.js.map