@eddyskywalker/dsh-chatgpt-subscription 0.61.0 → 0.63.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/index.js CHANGED
@@ -14,7 +14,7 @@ import path, { basename, dirname, extname, isAbsolute, join, relative, resolve,
14
14
  import os, { homedir, platform, userInfo } from "node:os";
15
15
  import { constants, createCipheriv, createDecipheriv, createHash, createHmac, publicEncrypt, randomBytes, randomUUID } from "node:crypto";
16
16
  import { isDeepStrictEqual } from "node:util";
17
- import { execSync, spawn } from "node:child_process";
17
+ import { execFileSync, spawn } from "node:child_process";
18
18
  import fs$1, { appendFileSync, constants as constants$1, copyFileSync, existsSync, mkdirSync, readFileSync, readdirSync, realpathSync, rmSync, statSync, utimesSync, writeFileSync } from "node:fs";
19
19
  import http, { createServer } from "node:http";
20
20
  import { WebError } from "@deepseek-ai/dsh-web";
@@ -808,7 +808,7 @@ const ROUTE_PREFIX$5 = "/api/dsh-chatgpt-subscription";
808
808
  * `test/responses-client.test.ts` asserts the two agree, so a release that
809
809
  * forgets this constant fails the suite instead of shipping quietly.
810
810
  */
811
- const PLUGIN_VERSION = "0.61.0";
811
+ const PLUGIN_VERSION = "0.63.0";
812
812
  const CODEX_CHATGPT_PROVIDER_ID = "codex-chatgpt";
813
813
  const CODEX_API_BASE = "https://chatgpt.com/backend-api/codex";
814
814
  const CODEX_RESPONSES_URL = `${CODEX_API_BASE}/responses`;
@@ -11378,20 +11378,36 @@ function shouldBypassProxy(target, noProxyList = "") {
11378
11378
  return noProxyBypasses(url.hostname, url.port || defaultPortFor(url.protocol), noProxyList);
11379
11379
  }
11380
11380
  /**
11381
+ * Run one system probe with no console window and no shell layer.
11382
+ *
11383
+ * `windowsHide` is not cosmetic here. `execSync` runs through `cmd.exe /d /s /c`,
11384
+ * and a host that has no console of its own (a detached `dsh web` host on Windows,
11385
+ * or any GUI-launched parent) gets a NEW VISIBLE console allocated for that
11386
+ * short-lived shell — the black window that flashed on every re-detection, because
11387
+ * the proxy cache TTL is only 5 seconds (#19, #91). `execFileSync` additionally
11388
+ * drops the shell hop, so one probe is one process instead of two and its argument
11389
+ * needs no quoting. `windowsHide` is a no-op on macOS and Linux, but it states the
11390
+ * intent once for every platform.
11391
+ */
11392
+ function runSystemProbe(file, args) {
11393
+ return execFileSync(file, args, {
11394
+ timeout: 1500,
11395
+ encoding: "utf-8",
11396
+ windowsHide: true,
11397
+ stdio: [
11398
+ "ignore",
11399
+ "pipe",
11400
+ "ignore"
11401
+ ]
11402
+ });
11403
+ }
11404
+ /**
11381
11405
  * Read one GNOME proxy setting; `null` when `gsettings` is absent or the key is
11382
11406
  * unreadable (headless box, no dconf session).
11383
11407
  */
11384
11408
  function readGsettings(key) {
11385
11409
  try {
11386
- return execSync(`gsettings get ${key}`, {
11387
- timeout: 1500,
11388
- encoding: "utf-8",
11389
- stdio: [
11390
- "ignore",
11391
- "pipe",
11392
- "ignore"
11393
- ]
11394
- }).trim();
11410
+ return runSystemProbe("gsettings", ["get", key]).trim();
11395
11411
  } catch {
11396
11412
  return null;
11397
11413
  }
@@ -11421,26 +11437,10 @@ function parseLinuxSystemProxy(read) {
11421
11437
  function detectSystemProxy(platform = process.platform, env = process.env, readSettings = readGsettings) {
11422
11438
  try {
11423
11439
  if (platform === "win32") {
11424
- const detected = parseWindowsProxyRegistry(execSync("reg query \"HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\"", {
11425
- timeout: 1500,
11426
- encoding: "utf-8",
11427
- stdio: [
11428
- "ignore",
11429
- "pipe",
11430
- "ignore"
11431
- ]
11432
- }));
11440
+ const detected = parseWindowsProxyRegistry(runSystemProbe("reg.exe", ["query", "HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"]));
11433
11441
  if (detected) return detected;
11434
11442
  } else if (platform === "darwin") {
11435
- const detected = parseMacOsScutilProxy(execSync("scutil --proxy", {
11436
- timeout: 1500,
11437
- encoding: "utf-8",
11438
- stdio: [
11439
- "ignore",
11440
- "pipe",
11441
- "ignore"
11442
- ]
11443
- }));
11443
+ const detected = parseMacOsScutilProxy(runSystemProbe("scutil", ["--proxy"]));
11444
11444
  if (detected) return detected;
11445
11445
  } else if (platform === "linux") {
11446
11446
  const detected = parseLinuxSystemProxy(readSettings);
@@ -28188,7 +28188,11 @@ function isWarmupHitReport(report, previous) {
28188
28188
  if (cached < CACHE_WARMUP_DEFAULTS.retainedPrefixMinCachedTokens) return false;
28189
28189
  if (prevCached < CACHE_WARMUP_DEFAULTS.retainedPrefixMinCachedTokens) return false;
28190
28190
  if (cached < prevCached) return false;
28191
- return fresh <= CACHE_WARMUP_DEFAULTS.retainedPrefixMaxFreshTokens;
28191
+ if (fresh <= CACHE_WARMUP_DEFAULTS.retainedPrefixMaxFreshTokens) return true;
28192
+ const prevFresh = finiteCount(previous.inputTokens);
28193
+ const prevAlignedTotal = Math.floor((prevCached + prevFresh) / 256) * 256;
28194
+ if (prevCached >= 4096 && cached > prevCached && cached >= prevAlignedTotal) return true;
28195
+ return false;
28192
28196
  }
28193
28197
  function consecutiveWarmupHits(reports) {
28194
28198
  try {
@@ -28666,7 +28670,7 @@ function isBareFilePathLine(trimmed) {
28666
28670
  */
28667
28671
  function isMixedEvidenceOutput(text) {
28668
28672
  if (text.includes("[cache-warmup preview]")) return true;
28669
- if (/^(?:===|---)\s+.+?(?:\s+(?:===|---))?$/m.test(text) || /^###\s+\S/m.test(text) || /^--\s+.+\s+--$/m.test(text)) return true;
28673
+ if (/^(?:===\s+.+?(?:\s+===)?|---\s+(?!a\/\S).+?(?:\s+---)?)$/m.test(text) || /^###\s+\S/m.test(text) || /^--\s+.+\s+--$/m.test(text)) return true;
28670
28674
  const lines = text.split("\n");
28671
28675
  let inspectStringConcat = 0;
28672
28676
  let jsonPropertyLines = 0;
@@ -29034,22 +29038,48 @@ function looksLikeContract(text) {
29034
29038
  return false;
29035
29039
  }
29036
29040
  /**
29041
+ * 判断包含 `diff --git` 的文本是否为构建/测试脚本输出中内嵌的局部 diff,而非纯粹的代码补丁。
29042
+ *
29043
+ * 真实会话中(如 `npm run checks && npm run verify`),脚本前段可能打印一段快照 `diff --git`,
29044
+ * 紧接着运行测试或以 `[exit code: 1]` 退出。若一刀切将所有含 `diff --git` 的输出当作源码,
29045
+ * 会导致 25KB+ 的构建/测试失败日志无法投影。
29046
+ */
29047
+ function isEmbeddedDiffInBuildOrTestLog(text) {
29048
+ const firstNonEmpty = text.split("\n").map((line) => line.trim()).find((line) => line !== "");
29049
+ if (firstNonEmpty === void 0) return false;
29050
+ if (firstNonEmpty.startsWith("diff --git ") || firstNonEmpty.startsWith("--- a/") || firstNonEmpty.startsWith("+++ b/") || firstNonEmpty.startsWith("@@ ") || /^(?:commit\s+)?[0-9a-f]{7,40}\b/.test(firstNonEmpty)) return false;
29051
+ const hasTestSummary = extractTestEvidence(text) !== void 0;
29052
+ const hasExitCode = /\[exit code: -?\d+\]/i.test(text) || /(?:exit code|exited with code|process exited with code)[:=\s]+-?\d+/i.test(text);
29053
+ const hasNpmScriptHeader = /^>\s+\S+@\S+\s+\S+/m.test(text);
29054
+ return hasTestSummary || hasExitCode && hasNpmScriptHeader;
29055
+ }
29056
+ /**
29037
29057
  * 源码或混合证据判定:
29038
29058
  * - 含多处 markdown 代码围栏;
29039
- * - 含 `git diff` 补丁块(`diff --git` / `@@ -x,y +x,y @@`);
29059
+ * - 含 `git diff` 补丁块(`diff --git` / `@@ -x,y +x,y @@`),除非是带测试汇总/脚本退出码的构建日志;
29040
29060
  * - 含至少 5 行带行号的源码切片(`1: ...` 或 `1\t...`),说明是单文件或多文件混合读取输出;
29041
29061
  * - 代码行占比 >= 45%。
29042
29062
  */
29043
29063
  function looksLikeSourceCode(text) {
29044
- if (/^diff --git\s+/m.test(text) || /^@@ -\d+(?:,\d+)? \+\d+(?:,\d+)? @@/m.test(text)) return true;
29064
+ const hasDiff = /^diff --git\s+/m.test(text) || /^@@ -\d+(?:,\d+)? \+\d+(?:,\d+)? @@/m.test(text);
29065
+ if (hasDiff && !isEmbeddedDiffInBuildOrTestLog(text)) return true;
29045
29066
  let fences = 0;
29046
29067
  for (const line of text.split("\n").slice(0, 600)) if (stripLineNumberPrefix(line).trim().startsWith("```")) fences += 1;
29047
29068
  if (fences >= 4) return true;
29048
29069
  let code = 0;
29049
29070
  let numbered = 0;
29050
29071
  let nonEmpty = 0;
29072
+ let inEmbeddedDiffHunk = false;
29051
29073
  for (const raw of text.split("\n").slice(0, 600)) {
29052
29074
  if (raw.trim() === "") continue;
29075
+ if (hasDiff) {
29076
+ if (raw.startsWith("diff --git ") || raw.startsWith("--- a/") || raw.startsWith("+++ b/") || raw.startsWith("@@ ")) {
29077
+ inEmbeddedDiffHunk = true;
29078
+ continue;
29079
+ }
29080
+ if (inEmbeddedDiffHunk && (raw.startsWith("+") || raw.startsWith("-") || raw.startsWith(" "))) continue;
29081
+ inEmbeddedDiffHunk = false;
29082
+ }
29053
29083
  if (LINE_NUMBER_PREFIX.test(raw)) numbered += 1;
29054
29084
  const trimmed = stripLineNumberPrefix(raw).trim();
29055
29085
  if (trimmed === "") continue;
@@ -33807,7 +33837,159 @@ function leadingSystemText$6(options) {
33807
33837
  return parts.length === 0 ? void 0 : parts.join("\n\n");
33808
33838
  }
33809
33839
  function nonSystemMessages$6(options) {
33810
- return options.messages.filter((message) => message.role !== "system");
33840
+ return orderStaticPrefixMessages(options.messages.filter((message) => message.role !== "system"));
33841
+ }
33842
+ /**
33843
+ * Stability tier for an initial bootstrap reminder message (`1` = most static, `4` = session-scoped).
33844
+ *
33845
+ * The harness appends bootstrap reminders (`agent-instructions`, `runtime-context`,
33846
+ * `progress-updates-language`, `skill-catalog`) AFTER the first user prompt (or
33847
+ * after the retained tail following a compaction checkpoint). Because Kimi's
33848
+ * prefix cache matches strictly from byte 0, leaving the dynamic user prompt at
33849
+ * index 0 prevents subagents, forked sessions, and post-compaction turns from
33850
+ * sharing the ~8,300-token `AGENTS.md` + `skill-catalog` prefix.
33851
+ *
33852
+ * Mid-conversation delta reminders (`Updated instructions from:`, `Additional
33853
+ * instructions from:`, `Instructions removed:`, `The available skill catalog changed.`)
33854
+ * return `null` so they stay anchored at the exact history position where they
33855
+ * arrived (append-only in-history).
33856
+ */
33857
+ function classifyBootstrapUserMessage(message) {
33858
+ if (message.role !== "user" || isToolResultMessage$7(message)) return null;
33859
+ const source = isRecord$53(message.source) ? message.source : void 0;
33860
+ const kind = source !== void 0 ? asString$21(source.kind) : void 0;
33861
+ const text = firstTextOf(message.content)?.trimStart() ?? "";
33862
+ if (kind === "progress-updates-language" || text.startsWith("Progress update output language override:")) return 1;
33863
+ if (text.startsWith("<system-reminder>\nThe following workspace instructions") || kind === "agent-instructions" && !text.startsWith("<system-reminder>\nUpdated instructions") && !text.startsWith("<system-reminder>\nAdditional instructions") && !text.startsWith("<system-reminder>\nInstructions removed")) return 2;
33864
+ if (text.startsWith("<system-reminder>\nA skill is a reusable set of task-specific instructions.") || kind === "skill-catalog" && !text.startsWith("<system-reminder>\nThe available skill catalog changed.")) return 3;
33865
+ if (kind === "runtime-context" || text.startsWith("Current runtime context. This snapshot supersedes")) return 4;
33866
+ return null;
33867
+ }
33868
+ function isCompactCheckpointMessage(message) {
33869
+ if (message === void 0 || message.role !== "user" || isToolResultMessage$7(message)) return false;
33870
+ const source = isRecord$53(message.source) ? message.source : void 0;
33871
+ if (source !== void 0 && asString$21(source.kind) === "compact-checkpoint") return true;
33872
+ return (firstTextOf(message.content)?.trimStart() ?? "").startsWith("This is an automatically generated checkpoint condensing");
33873
+ }
33874
+ /**
33875
+ * Normalize `agent-instructions` text so global `~/.dsh/` instructions precede
33876
+ * workspace-local `AGENTS.md` instructions when both appear in the same block.
33877
+ */
33878
+ function normalizeAgentInstructionsMessage(message) {
33879
+ if (!Array.isArray(message.content) || message.content.length !== 1) return message;
33880
+ const first = message.content[0];
33881
+ if (!isRecord$53(first) || first.type !== "text" || typeof first.text !== "string") return message;
33882
+ const raw = first.text;
33883
+ const firstIdx = raw.indexOf("\n\nInstructions from: ");
33884
+ if (firstIdx < 0) return message;
33885
+ const closeIdx = raw.lastIndexOf("\n</system-reminder>");
33886
+ if (closeIdx <= firstIdx) return message;
33887
+ const header = raw.slice(0, firstIdx);
33888
+ const body = raw.slice(firstIdx + 2, closeIdx);
33889
+ const tail = raw.slice(closeIdx);
33890
+ const sections = body.split("\n\nInstructions from: ");
33891
+ if (sections.length < 2) return message;
33892
+ const tagged = sections.map((sec, idx) => {
33893
+ const firstLineEnd = sec.indexOf("\n");
33894
+ const sourcePath = (firstLineEnd < 0 ? sec : sec.slice(0, firstLineEnd)).trim();
33895
+ return {
33896
+ sec,
33897
+ idx,
33898
+ rank: sourcePath.startsWith("~/") || sourcePath.startsWith("~\\") || sourcePath.includes("/.dsh/") || sourcePath.includes("\\.dsh\\") ? 0 : 1
33899
+ };
33900
+ });
33901
+ if (!tagged.some((item, i) => i > 0 && item.rank < tagged[i - 1].rank)) return message;
33902
+ tagged.sort((a, b) => a.rank - b.rank || a.idx - b.idx);
33903
+ const rebuilt = `${header}\n\nInstructions from: ${tagged.map((t) => t.sec).join("\n\nInstructions from: ")}${tail}`;
33904
+ return {
33905
+ ...message,
33906
+ content: [{
33907
+ ...first,
33908
+ text: rebuilt
33909
+ }]
33910
+ };
33911
+ }
33912
+ /**
33913
+ * Deterministic entropy-sorted ordering for leading bootstrap reminders.
33914
+ *
33915
+ * 1. Within the leading pre-assistant `user` message run, orders the first
33916
+ * occurrence of each bootstrap tier (`1: progress-updates-language` ->
33917
+ * `2: agent-instructions` -> `3: skill-catalog` -> `4: runtime-context`)
33918
+ * ahead of the dynamic `user` prompt (`5`).
33919
+ * 2. When the surface starts with a `compact-checkpoint` that shadowed the
33920
+ * original bootstrap run and the harness re-injected Tier 1/2/3 reminders
33921
+ * after the retained tail, hoists the first occurrence of Tier 1/2/3 ahead
33922
+ * of `compact-checkpoint` so the ~21k static prefix stays intact across
33923
+ * compaction boundaries and every step after compaction.
33924
+ */
33925
+ function orderStaticPrefixMessages(messages) {
33926
+ try {
33927
+ if (messages.length <= 1) return [...messages];
33928
+ let leadEnd = 0;
33929
+ while (leadEnd < messages.length && messages[leadEnd].role === "user" && !isToolResultMessage$7(messages[leadEnd])) leadEnd += 1;
33930
+ if (leadEnd > 0 && isCompactCheckpointMessage(messages[0])) {
33931
+ const seenInLead = /* @__PURE__ */ new Set();
33932
+ for (let i = 0; i < leadEnd; i++) {
33933
+ const tier = classifyBootstrapUserMessage(messages[i]);
33934
+ if (tier !== null) seenInLead.add(tier);
33935
+ }
33936
+ if (!seenInLead.has(1) && !seenInLead.has(2)) {
33937
+ const hoistedByTier = /* @__PURE__ */ new Map();
33938
+ for (let i = leadEnd; i < messages.length; i++) {
33939
+ const msg = messages[i];
33940
+ const tier = classifyBootstrapUserMessage(msg);
33941
+ if ((tier === 1 || tier === 2 || tier === 3) && !hoistedByTier.has(tier)) hoistedByTier.set(tier, {
33942
+ index: i,
33943
+ message: tier === 2 ? normalizeAgentInstructionsMessage(msg) : msg
33944
+ });
33945
+ }
33946
+ if (hoistedByTier.size > 0) {
33947
+ const hoistedIndices = /* @__PURE__ */ new Set();
33948
+ const prefix = [];
33949
+ for (const tier of [
33950
+ 1,
33951
+ 2,
33952
+ 3
33953
+ ]) {
33954
+ const entry = hoistedByTier.get(tier);
33955
+ if (entry !== void 0) {
33956
+ hoistedIndices.add(entry.index);
33957
+ prefix.push(entry.message);
33958
+ }
33959
+ }
33960
+ const rest = messages.filter((_, idx) => !hoistedIndices.has(idx));
33961
+ return [...prefix, ...rest];
33962
+ }
33963
+ }
33964
+ }
33965
+ if (leadEnd <= 1) return [...messages];
33966
+ const seenTiers = /* @__PURE__ */ new Set();
33967
+ const leadTagged = [];
33968
+ let hasBootstrap = false;
33969
+ for (let i = 0; i < leadEnd; i++) {
33970
+ const rawMsg = messages[i];
33971
+ const tier = classifyBootstrapUserMessage(rawMsg);
33972
+ if (tier !== null && !seenTiers.has(tier)) {
33973
+ seenTiers.add(tier);
33974
+ hasBootstrap = true;
33975
+ leadTagged.push({
33976
+ message: tier === 2 ? normalizeAgentInstructionsMessage(rawMsg) : rawMsg,
33977
+ rank: tier,
33978
+ index: i
33979
+ });
33980
+ } else leadTagged.push({
33981
+ message: rawMsg,
33982
+ rank: 5,
33983
+ index: i
33984
+ });
33985
+ }
33986
+ if (!hasBootstrap) return [...messages];
33987
+ if (!leadTagged.some((item, i) => i > 0 && item.rank < leadTagged[i - 1].rank || item.message !== messages[i])) return [...messages];
33988
+ leadTagged.sort((a, b) => a.rank - b.rank || a.index - b.index);
33989
+ return [...leadTagged.map((item) => item.message), ...messages.slice(leadEnd)];
33990
+ } catch {
33991
+ return [...messages];
33992
+ }
33811
33993
  }
33812
33994
  const NO_REASONING = {
33813
33995
  fields: [],
@@ -35374,21 +35556,43 @@ function rememberScoped(store, key, value) {
35374
35556
  */
35375
35557
  const prefixSnapshots = /* @__PURE__ */ new Map();
35376
35558
  /**
35559
+ * Extract the concatenated text of leading workspace-static bootstrap reminders
35560
+ * (Tiers 1–3: `progress-updates-language`, initial `agent-instructions`, initial
35561
+ * `skill-catalog`) after static-prefix ordering.
35562
+ */
35563
+ function leadingStaticBootstrapText(options) {
35564
+ const ordered = nonSystemMessages$6(options);
35565
+ const parts = [];
35566
+ for (const message of ordered) {
35567
+ const tier = classifyBootstrapUserMessage(message);
35568
+ if (tier === 1 || tier === 2 || tier === 3) {
35569
+ const text = textOf$7(message.content);
35570
+ if (text !== "") parts.push(text);
35571
+ continue;
35572
+ }
35573
+ break;
35574
+ }
35575
+ return parts.join("\n\n");
35576
+ }
35577
+ /**
35377
35578
  * Hash the prefix-breaking inputs of one request.
35378
35579
  *
35379
35580
  * @param options - The request about to be built.
35380
- * @returns The hashes of its system prompt and its tool list.
35581
+ * @returns The hashes of its system prompt, tool list, and optional static bootstrap prefix.
35381
35582
  */
35382
35583
  function prefixFingerprints(options) {
35383
35584
  const systemText = leadingSystemText$6(options) ?? "";
35384
35585
  const tools = options.tools ?? [];
35586
+ const staticBootstrap = leadingStaticBootstrapText(options);
35587
+ const staticPrefixHash = staticBootstrap === "" ? null : fingerprint(staticBootstrap);
35385
35588
  return {
35386
35589
  systemPromptHash: systemText === "" ? null : fingerprint(systemText),
35387
35590
  toolsHash: tools.length === 0 ? null : fingerprint(JSON.stringify(tools.map((tool) => [
35388
35591
  tool.name,
35389
35592
  tool.description ?? "",
35390
35593
  tool.parameters ?? {}
35391
- ])))
35594
+ ]))),
35595
+ ...staticPrefixHash === null ? {} : { staticPrefixHash }
35392
35596
  };
35393
35597
  }
35394
35598
  /**
@@ -37122,6 +37326,19 @@ const inFlightColdLeaderStartedAt = /* @__PURE__ */ new Map();
37122
37326
  * from the outside.
37123
37327
  */
37124
37328
  const coldLeaderReleases = /* @__PURE__ */ new Map();
37329
+ /**
37330
+ * In-flight main-session requests waiting for their HTTP response headers,
37331
+ * keyed by sessionId. Used so a concurrent `session-title-first-prompt-llm`
37332
+ * side-channel request yields to the main turn's prefill instead of competing
37333
+ * on the same account during cold start.
37334
+ */
37335
+ const inFlightMainSessionHeaders = /* @__PURE__ */ new Map();
37336
+ const mainSessionHeaderReleases = /* @__PURE__ */ new Map();
37337
+ /**
37338
+ * Per-account/model first-turn prefill pacing chain for concurrent subagent bursts.
37339
+ */
37340
+ const inFlightSubagentBurstLeaders = /* @__PURE__ */ new Map();
37341
+ const subagentBurstReleases = /* @__PURE__ */ new Map();
37125
37342
  /** The gate of a request that neither waits for nor leads a cold start. */
37126
37343
  const NO_COLD_START_GATE = {
37127
37344
  isLeader: false,
@@ -37132,9 +37349,9 @@ const NO_COLD_START_GATE = {
37132
37349
  * The group of requests that address the same cached prefix.
37133
37350
  *
37134
37351
  * The service derives its cache from the request content, so two requests with
37135
- * the same model, the same system prompt and the same tool list hit the same
37136
- * entry. The region is part of the key because each region is a separate
37137
- * service with a cache of its own.
37352
+ * the same model, the same system prompt, the same tool list and the same
37353
+ * leading static bootstrap reminders hit the same entry. The region is part of
37354
+ * the key because each region is a separate service with a cache of its own.
37138
37355
  *
37139
37356
  * A request with no system prompt has no prefix worth warming, and gets no
37140
37357
  * group at all.
@@ -37144,18 +37361,18 @@ const NO_COLD_START_GATE = {
37144
37361
  * @returns The group key, or undefined when the request has no prefix.
37145
37362
  */
37146
37363
  function coldStartGroupKey(region, options) {
37147
- const { systemPromptHash, toolsHash } = prefixFingerprints(options);
37364
+ const { systemPromptHash, toolsHash, staticPrefixHash } = prefixFingerprints(options);
37148
37365
  if (systemPromptHash === null) return void 0;
37149
- return `${region}:${options.model}:${systemPromptHash}:${toolsHash ?? "none"}`;
37366
+ return `${region}:${options.model}:${systemPromptHash}:${toolsHash ?? "none"}${staticPrefixHash ? ":" + staticPrefixHash : ""}`;
37150
37367
  }
37151
37368
  /**
37152
37369
  * Remember that a prefix group is warm.
37153
37370
  *
37154
37371
  * @param groupKey - The group that was just warmed.
37155
37372
  */
37156
- function rememberWarmPrefix(groupKey) {
37373
+ function rememberWarmPrefix(groupKey, now = Date.now()) {
37157
37374
  warmPrefixTimestamps.delete(groupKey);
37158
- warmPrefixTimestamps.set(groupKey, Date.now());
37375
+ warmPrefixTimestamps.set(groupKey, now);
37159
37376
  while (warmPrefixTimestamps.size > MAX_WARM_PREFIX_GROUPS) {
37160
37377
  const oldest = warmPrefixTimestamps.keys().next();
37161
37378
  if (oldest.done === true) break;
@@ -37163,6 +37380,83 @@ function rememberWarmPrefix(groupKey) {
37163
37380
  }
37164
37381
  }
37165
37382
  /**
37383
+ * Register an in-flight main-session request until its HTTP response headers arrive.
37384
+ */
37385
+ function registerInFlightMainSessionHeader(sessionId) {
37386
+ const key = sessionId.trim();
37387
+ if (key === "") return () => void 0;
37388
+ mainSessionHeaderReleases.get(key)?.();
37389
+ let resolveHeader;
37390
+ const promise = new Promise((resolve) => {
37391
+ resolveHeader = resolve;
37392
+ });
37393
+ inFlightMainSessionHeaders.set(key, promise);
37394
+ let released = false;
37395
+ const release = () => {
37396
+ if (released) return;
37397
+ released = true;
37398
+ resolveHeader();
37399
+ if (mainSessionHeaderReleases.get(key) === release) {
37400
+ mainSessionHeaderReleases.delete(key);
37401
+ inFlightMainSessionHeaders.delete(key);
37402
+ }
37403
+ };
37404
+ mainSessionHeaderReleases.set(key, release);
37405
+ return release;
37406
+ }
37407
+ /**
37408
+ * Whether a first-turn request carries a subagent mandate or large uncached
37409
+ * dynamic payload that should stagger behind an already in-flight sibling burst.
37410
+ */
37411
+ function isSubagentBurstCandidate(options) {
37412
+ let dynamicChars = 0;
37413
+ for (const message of options.messages) {
37414
+ if (message.role !== "user") continue;
37415
+ const tier = classifyBootstrapUserMessage(message);
37416
+ if (tier === 1 || tier === 2 || tier === 3) continue;
37417
+ if (!Array.isArray(message.content)) continue;
37418
+ for (const block of message.content) if (typeof block === "object" && block !== null && block.type === "text") {
37419
+ const text = typeof block.text === "string" ? block.text : "";
37420
+ if (text.includes("dsh-mandate-v2")) return true;
37421
+ dynamicChars += text.length;
37422
+ }
37423
+ }
37424
+ return dynamicChars >= 1200;
37425
+ }
37426
+ /**
37427
+ * Stagger concurrent subagent first-turn requests on the same account/model
37428
+ * so they do not stampede prefill in the same millisecond.
37429
+ */
37430
+ async function acquireSubagentBurstPacing(pacingKey, signal) {
37431
+ while (true) {
37432
+ const existing = inFlightSubagentBurstLeaders.get(pacingKey);
37433
+ if (existing === void 0) break;
37434
+ await raceColdStartLeader(existing, signal);
37435
+ if (signal.aborted) return () => void 0;
37436
+ if (inFlightSubagentBurstLeaders.get(pacingKey) === existing) {
37437
+ subagentBurstReleases.get(pacingKey)?.();
37438
+ break;
37439
+ }
37440
+ }
37441
+ let resolvePacing;
37442
+ const promise = new Promise((resolve) => {
37443
+ resolvePacing = resolve;
37444
+ });
37445
+ inFlightSubagentBurstLeaders.set(pacingKey, promise);
37446
+ let settled = false;
37447
+ const release = () => {
37448
+ if (settled) return;
37449
+ settled = true;
37450
+ resolvePacing();
37451
+ if (subagentBurstReleases.get(pacingKey) === release) {
37452
+ subagentBurstReleases.delete(pacingKey);
37453
+ inFlightSubagentBurstLeaders.delete(pacingKey);
37454
+ }
37455
+ };
37456
+ subagentBurstReleases.set(pacingKey, release);
37457
+ return release;
37458
+ }
37459
+ /**
37166
37460
  * Wait for the leader of a prefix group, for the wait budget, or for an abort.
37167
37461
  *
37168
37462
  * The timer and the abort listener are removed whichever way the race ends, so
@@ -37506,322 +37800,338 @@ var KimiCodeAdapter = class extends LlmAdapter {
37506
37800
  }
37507
37801
  async *requestStream(options, signal, activity) {
37508
37802
  const fetchFn = this.options.fetchFn ?? fetch;
37509
- const catalog = await this.catalog().catch(() => []);
37510
- const wire = wireForCatalogEntry(options.model, catalog);
37511
- const entry = catalog.find((model) => model.id === options.model);
37512
37803
  const normalized = normalizeGenerateOptions(options);
37513
37804
  const sideChannel = isSideChannelTitleRequest(normalized);
37514
- const images = await resolveRequestImages$2(normalized, this.options.attachments, signal, KIMI_CODE_REQUEST_IMAGE_MAX_EDGE);
37515
- const priorDroppedKeys = getSessionDroppedImageKeys(options.sessionId, options.sessionId === void 0 ? void 0 : sessionCacheState.read(options.sessionId)?.budgetDropped);
37516
- const stickyOffload = offloadRequestImagesWithStickyBudget(normalized, maxRequestImageBytes$1(), lowRequestImageBytes(), images, priorDroppedKeys);
37517
- const imageTrimmed = stickyOffload.options;
37518
- if (!sideChannel) markPendingImageOffload(options.sessionId, stickyOffload.newlyDroppedKeys.length);
37519
- const gatedEffort = coerceThinkingEffort(options.model, mapReasoningEffort(options.reasoningEffort === void 0 || options.reasoningEffort === null ? void 0 : String(options.reasoningEffort)));
37520
- if (gatedEffort.coercedFrom !== null) recordThinkingCoercion({
37521
- model: options.model,
37522
- wire,
37523
- from: gatedEffort.coercedFrom,
37524
- to: gatedEffort.effort
37525
- }, options.sessionId);
37526
- const videoTrimmed = offloadOldestRequestVideos(imageTrimmed, MAX_REQUEST_VIDEO_BYTES$1);
37527
- const requestOptions = gatedEffort.effort === void 0 ? videoTrimmed : {
37528
- ...videoTrimmed,
37529
- reasoningEffort: ReasoningEffortId(gatedEffort.effort)
37530
- };
37531
- const videos = await resolveRequestVideos(requestOptions, this.options.videos, signal);
37532
- const settings = await this.settings();
37533
- const modalities = inputModalitiesForEntry(options.model, catalog);
37534
- /**
37535
- * Everything every attempt shares: the media reads and the capability gates.
37536
- *
37537
- * Account-specific references are merged on top of this per attempt, so the
37538
- * gate is applied once and a reference can never be cited for a modality the
37539
- * model does not declare.
37540
- */
37541
- const baseMedia = {
37542
- videos,
37543
- videoAccepted: modalities.includes("video"),
37544
- messageTools: dynamicToolsForEntry(options.model, catalog)
37545
- };
37546
- /**
37547
- * Which readable occurrences the reference path would cover.
37548
- *
37549
- * Decided here so the body-fit guard can measure the body that will actually
37550
- * be sent; nothing is uploaded, and no network is touched, until that guard
37551
- * has accepted the request (see the rotation loop).
37552
- */
37553
- const planned = planMediaReferences({
37554
- wire,
37555
- imageAccepted: modalities.includes("image"),
37556
- videoAccepted: baseMedia.videoAccepted === true,
37557
- images,
37558
- videos
37559
- });
37560
- const contextWindow = this.contextWindowFor(options.model, entry, settings.contextWindowOverrides);
37561
- const requestedMax = options.maxTokens ?? maxOutputTokensFor$4(options.model, contextWindow);
37562
- const inputCap = maxInputTokensForEntry(options.model, catalog);
37563
- const promptLimit = inputCap === void 0 ? contextWindow : Math.min(contextWindow, inputCap);
37564
- const boundedOptions = {
37565
- ...requestOptions,
37566
- maxTokens: clampOutputToContext$1(requestedMax, promptLimit, estimatedInputTokens(requestOptions))
37567
- };
37568
- const carriesVideo = requestHasVideo(requestOptions);
37569
- const bodyLimit = carriesVideo ? MAX_VIDEO_MESSAGE_BODY_BYTES : maxRequestBodyBytesFor(kimiCodeModelDef(entry?.id ?? options.model), process.env);
37570
- /**
37571
- * Run the greedy body-fit loop for ONE set of media references.
37572
- *
37573
- * A function rather than a loop in place because the same loop now serves
37574
- * every build of one request: the pre-upload MEASUREMENT (placeholder
37575
- * references), the real reference build after the upload, and the all-inline
37576
- * rebuild the missing-resource fallback re-sends.
37577
- *
37578
- * Every call restarts from `boundedOptions`. That is load bearing rather than
37579
- * tidy: the inline fallback has to re-fit the inline body from scratch and
37580
- * stay inside the same ceiling instead of inheriting an omission the
37581
- * reference path made to fit a different, much smaller body.
37582
- */
37583
- const buildBodyWithinLimit = (media) => {
37584
- let buildOptions = boundedOptions;
37585
- for (let attempt = 0;; attempt++) {
37586
- const built = buildRequest(buildOptions, wire, images, void 0, media);
37587
- const body = JSON.stringify(built);
37588
- const bytes = Buffer.byteLength(body, "utf8");
37589
- if (bytes <= bodyLimit) return {
37590
- body,
37591
- options: buildOptions
37592
- };
37593
- const context = () => ({
37594
- droppedImages: countOmitted(buildOptions, requestOptions, images),
37595
- sendableImagesRemaining: requestImagePayloadLengths(buildOptions, images).length,
37596
- excessBytes: bytes - bodyLimit
37597
- });
37598
- if (attempt > MAX_BODY_FIT_ATTEMPTS || !requestHasSendableImage(buildOptions, images)) {
37599
- assertRequestBodyFits$1(built, carriesVideo, context(), bodyLimit);
37600
- throw new Error("unreachable: assertRequestBodyFits returns or throws");
37601
- }
37602
- const drop = dropOldestImagesUntilFits(buildOptions, images, bytes - bodyLimit, requestOptions);
37603
- if (drop.dropped === 0) {
37604
- assertRequestBodyFits$1(built, carriesVideo, context(), bodyLimit);
37605
- throw new Error("unreachable: assertRequestBodyFits returns or throws");
37606
- }
37607
- buildOptions = drop.options;
37608
- }
37609
- };
37610
- /**
37611
- * The measured build for the reference path, done at most once.
37612
- *
37613
- * Held across rotation attempts because it is account-independent: it decides
37614
- * whether this request can be sent at all, and that answer cannot change
37615
- * because a different account answered.
37616
- *
37617
- * The OPTIONS travel with the body because they, not the plan, name the media
37618
- * this request still carries: see {@link mediaAttachmentIdsIn}.
37619
- */
37620
- let measured;
37621
- let sentBuild;
37622
- const pool = this.accountPool;
37623
- const tried = /* @__PURE__ */ new Set();
37624
- let servedByAccountId;
37625
- let response;
37626
- while (true) {
37627
- let apiCredentials;
37628
- let accountId;
37629
- if (pool === null) try {
37630
- apiCredentials = await ensureAccessToken$1(this.store, {
37631
- fetchFn,
37632
- signal,
37633
- maxAttempts: MODEL_REFRESH_MAX_ATTEMPTS
37634
- });
37635
- } catch (error) {
37636
- throw credentialFailure(error, signal);
37637
- }
37638
- else {
37639
- let effective;
37640
- try {
37641
- effective = await pool.getEffectiveCredential(tried, fetchFn, { maxAttempts: MODEL_REFRESH_MAX_ATTEMPTS });
37642
- } catch (error) {
37643
- throw credentialFailure(error, signal);
37644
- }
37645
- accountId = effective.account.id;
37646
- servedByAccountId = accountId;
37647
- tried.add(accountId);
37648
- apiCredentials = effective.credentials;
37649
- }
37650
- const region = apiCredentials.region ?? await resolveRegion();
37651
- const base = (apiCredentials.baseUrl ?? codingBaseUrl(region)).replace(/\/+$/, "");
37652
- const endpoint = wire === "anthropic" ? `${base}/v1/messages?beta=true` : `${base}/v1/chat/completions`;
37653
- const headers = await modelRequestHeaders$1(apiCredentials.accessToken, wire);
37805
+ const sessionKey = typeof options.sessionId === "string" ? options.sessionId.trim() : "";
37806
+ const mainHeaderRelease = !sideChannel && sessionKey !== "" ? registerInFlightMainSessionHeader(sessionKey) : () => void 0;
37807
+ try {
37808
+ const catalog = await this.catalog().catch(() => []);
37809
+ const wire = wireForCatalogEntry(options.model, catalog);
37810
+ const entry = catalog.find((model) => model.id === options.model);
37811
+ const images = await resolveRequestImages$2(normalized, this.options.attachments, signal, KIMI_CODE_REQUEST_IMAGE_MAX_EDGE);
37812
+ const priorDroppedKeys = getSessionDroppedImageKeys(options.sessionId, options.sessionId === void 0 ? void 0 : sessionCacheState.read(options.sessionId)?.budgetDropped);
37813
+ const stickyOffload = offloadRequestImagesWithStickyBudget(normalized, maxRequestImageBytes$1(), lowRequestImageBytes(), images, priorDroppedKeys);
37814
+ const imageTrimmed = stickyOffload.options;
37815
+ if (!sideChannel) markPendingImageOffload(options.sessionId, stickyOffload.newlyDroppedKeys.length);
37816
+ const gatedEffort = coerceThinkingEffort(options.model, mapReasoningEffort(options.reasoningEffort === void 0 || options.reasoningEffort === null ? void 0 : String(options.reasoningEffort)));
37817
+ if (gatedEffort.coercedFrom !== null) recordThinkingCoercion({
37818
+ model: options.model,
37819
+ wire,
37820
+ from: gatedEffort.coercedFrom,
37821
+ to: gatedEffort.effort
37822
+ }, options.sessionId);
37823
+ const videoTrimmed = offloadOldestRequestVideos(imageTrimmed, MAX_REQUEST_VIDEO_BYTES$1);
37824
+ const requestOptions = gatedEffort.effort === void 0 ? videoTrimmed : {
37825
+ ...videoTrimmed,
37826
+ reasoningEffort: ReasoningEffortId(gatedEffort.effort)
37827
+ };
37828
+ const videos = await resolveRequestVideos(requestOptions, this.options.videos, signal);
37829
+ const settings = await this.settings();
37830
+ const modalities = inputModalitiesForEntry(options.model, catalog);
37654
37831
  /**
37655
- * Which account's file store this attempt writes to and cites from.
37832
+ * Everything every attempt shares: the media reads and the capability gates.
37656
37833
  *
37657
- * A pooled account's own id, because that is the only identity a reference
37658
- * may be cached under; a single stored credential uses the user id its
37659
- * sign-in reported, or a constant when it reported none. The access token is
37660
- * never used, here or anywhere a cache key is built.
37834
+ * Account-specific references are merged on top of this per attempt, so the
37835
+ * gate is applied once and a reference can never be cited for a modality the
37836
+ * model does not declare.
37661
37837
  */
37662
- const accountScope = accountId ?? legacyAccountScope(apiCredentials);
37663
- if (measured === void 0) measured = buildBodyWithinLimit(planned.length === 0 ? baseMedia : {
37664
- ...baseMedia,
37665
- ...plannedReferenceMaps(planned)
37666
- });
37667
- const stillSent = mediaAttachmentIdsIn(measured.options);
37668
- const uploadable = planned.filter((item) => stillSent.has(item.attachmentId));
37669
- const uploads = uploadable.length === 0 ? void 0 : await this.uploadPlannedReferences({
37670
- planned: uploadable,
37671
- accessToken: apiCredentials.accessToken,
37672
- baseUrl: base,
37673
- accountScope,
37674
- signal
37675
- });
37676
- let finalBuild = uploads === void 0 ? planned.length === 0 ? measured : buildBodyWithinLimit(baseMedia) : buildBodyWithinLimit({
37677
- ...baseMedia,
37678
- imageReferences: uploads.imageReferences,
37679
- videoReferences: uploads.videoReferences
37838
+ const baseMedia = {
37839
+ videos,
37840
+ videoAccepted: modalities.includes("video"),
37841
+ messageTools: dynamicToolsForEntry(options.model, catalog)
37842
+ };
37843
+ /**
37844
+ * Which readable occurrences the reference path would cover.
37845
+ *
37846
+ * Decided here so the body-fit guard can measure the body that will actually
37847
+ * be sent; nothing is uploaded, and no network is touched, until that guard
37848
+ * has accepted the request (see the rotation loop).
37849
+ */
37850
+ const planned = planMediaReferences({
37851
+ wire,
37852
+ imageAccepted: modalities.includes("image"),
37853
+ videoAccepted: baseMedia.videoAccepted === true,
37854
+ images,
37855
+ videos
37680
37856
  });
37681
- sentBuild = finalBuild;
37682
- let body = finalBuild.body;
37683
- const post = async (payload) => {
37684
- try {
37685
- const response = await fetchWithContextBudgetRecovery(fetchFn)(endpoint, {
37686
- method: "POST",
37687
- headers,
37688
- body: payload,
37689
- signal
37857
+ const contextWindow = this.contextWindowFor(options.model, entry, settings.contextWindowOverrides);
37858
+ const requestedMax = options.maxTokens ?? maxOutputTokensFor$4(options.model, contextWindow);
37859
+ const inputCap = maxInputTokensForEntry(options.model, catalog);
37860
+ const promptLimit = inputCap === void 0 ? contextWindow : Math.min(contextWindow, inputCap);
37861
+ const boundedOptions = {
37862
+ ...requestOptions,
37863
+ maxTokens: clampOutputToContext$1(requestedMax, promptLimit, estimatedInputTokens(requestOptions))
37864
+ };
37865
+ const carriesVideo = requestHasVideo(requestOptions);
37866
+ const bodyLimit = carriesVideo ? MAX_VIDEO_MESSAGE_BODY_BYTES : maxRequestBodyBytesFor(kimiCodeModelDef(entry?.id ?? options.model), process.env);
37867
+ /**
37868
+ * Run the greedy body-fit loop for ONE set of media references.
37869
+ *
37870
+ * A function rather than a loop in place because the same loop now serves
37871
+ * every build of one request: the pre-upload MEASUREMENT (placeholder
37872
+ * references), the real reference build after the upload, and the all-inline
37873
+ * rebuild the missing-resource fallback re-sends.
37874
+ *
37875
+ * Every call restarts from `boundedOptions`. That is load bearing rather than
37876
+ * tidy: the inline fallback has to re-fit the inline body from scratch and
37877
+ * stay inside the same ceiling instead of inheriting an omission the
37878
+ * reference path made to fit a different, much smaller body.
37879
+ */
37880
+ const buildBodyWithinLimit = (media) => {
37881
+ let buildOptions = boundedOptions;
37882
+ for (let attempt = 0;; attempt++) {
37883
+ const built = buildRequest(buildOptions, wire, images, void 0, media);
37884
+ const body = JSON.stringify(built);
37885
+ const bytes = Buffer.byteLength(body, "utf8");
37886
+ if (bytes <= bodyLimit) return {
37887
+ body,
37888
+ options: buildOptions
37889
+ };
37890
+ const context = () => ({
37891
+ droppedImages: countOmitted(buildOptions, requestOptions, images),
37892
+ sendableImagesRemaining: requestImagePayloadLengths(buildOptions, images).length,
37893
+ excessBytes: bytes - bodyLimit
37690
37894
  });
37691
- activity?.pulse();
37692
- return response;
37693
- } catch (error) {
37694
- if (signal.aborted) throw new LlmError("Kimi Code request aborted", "ABORTED", { cause: error });
37695
- throw new LlmError(`Kimi Code request failed: ${error instanceof Error ? error.message : String(error)}`, "TRANSPORT", { cause: error });
37895
+ if (attempt > MAX_BODY_FIT_ATTEMPTS || !requestHasSendableImage(buildOptions, images)) {
37896
+ assertRequestBodyFits$1(built, carriesVideo, context(), bodyLimit);
37897
+ throw new Error("unreachable: assertRequestBodyFits returns or throws");
37898
+ }
37899
+ const drop = dropOldestImagesUntilFits(buildOptions, images, bytes - bodyLimit, requestOptions);
37900
+ if (drop.dropped === 0) {
37901
+ assertRequestBodyFits$1(built, carriesVideo, context(), bodyLimit);
37902
+ throw new Error("unreachable: assertRequestBodyFits returns or throws");
37903
+ }
37904
+ buildOptions = drop.options;
37696
37905
  }
37697
37906
  };
37698
- const coldGroupKey = sideChannel ? void 0 : coldStartGroupKey(region, requestOptions);
37699
- const coldGate = coldGroupKey === void 0 ? void 0 : await acquireColdStartWarmup(coldGroupKey, signal);
37700
- let coldGateSettled = false;
37701
- const settleColdGate = (warm) => {
37702
- if (coldGateSettled) return;
37703
- coldGateSettled = true;
37704
- coldGate?.release();
37705
- if (warm) coldGate?.markWarm();
37706
- };
37707
- response = await post(body).then((value) => {
37708
- settleColdGate(value.ok);
37709
- return value;
37710
- }, (error) => {
37711
- settleColdGate(false);
37712
- throw error;
37713
- });
37714
- let detail = response.ok ? "" : (await response.text().catch(() => "")).slice(0, 2e3);
37715
- if (response.status === 404 && uploads !== void 0 && uploads.cited.length > 0 && isMissingResourceBody(detail)) {
37716
- const uploader = this.mediaFiles();
37717
- for (const item of uploads.cited) uploader.forget({
37907
+ /**
37908
+ * The measured build for the reference path, done at most once.
37909
+ *
37910
+ * Held across rotation attempts because it is account-independent: it decides
37911
+ * whether this request can be sent at all, and that answer cannot change
37912
+ * because a different account answered.
37913
+ *
37914
+ * The OPTIONS travel with the body because they, not the plan, name the media
37915
+ * this request still carries: see {@link mediaAttachmentIdsIn}.
37916
+ */
37917
+ let measured;
37918
+ let sentBuild;
37919
+ const pool = this.accountPool;
37920
+ const tried = /* @__PURE__ */ new Set();
37921
+ let servedByAccountId;
37922
+ let response;
37923
+ while (true) {
37924
+ let apiCredentials;
37925
+ let accountId;
37926
+ if (pool === null) try {
37927
+ apiCredentials = await ensureAccessToken$1(this.store, {
37928
+ fetchFn,
37929
+ signal,
37930
+ maxAttempts: MODEL_REFRESH_MAX_ATTEMPTS
37931
+ });
37932
+ } catch (error) {
37933
+ throw credentialFailure(error, signal);
37934
+ }
37935
+ else {
37936
+ let effective;
37937
+ try {
37938
+ effective = await pool.getEffectiveCredential(tried, fetchFn, { maxAttempts: MODEL_REFRESH_MAX_ATTEMPTS });
37939
+ } catch (error) {
37940
+ throw credentialFailure(error, signal);
37941
+ }
37942
+ accountId = effective.account.id;
37943
+ servedByAccountId = accountId;
37944
+ tried.add(accountId);
37945
+ apiCredentials = effective.credentials;
37946
+ }
37947
+ const region = apiCredentials.region ?? await resolveRegion();
37948
+ const base = (apiCredentials.baseUrl ?? codingBaseUrl(region)).replace(/\/+$/, "");
37949
+ const endpoint = wire === "anthropic" ? `${base}/v1/messages?beta=true` : `${base}/v1/chat/completions`;
37950
+ const headers = await modelRequestHeaders$1(apiCredentials.accessToken, wire);
37951
+ /**
37952
+ * Which account's file store this attempt writes to and cites from.
37953
+ *
37954
+ * A pooled account's own id, because that is the only identity a reference
37955
+ * may be cached under; a single stored credential uses the user id its
37956
+ * sign-in reported, or a constant when it reported none. The access token is
37957
+ * never used, here or anywhere a cache key is built.
37958
+ */
37959
+ const accountScope = accountId ?? legacyAccountScope(apiCredentials);
37960
+ if (measured === void 0) measured = buildBodyWithinLimit(planned.length === 0 ? baseMedia : {
37961
+ ...baseMedia,
37962
+ ...plannedReferenceMaps(planned)
37963
+ });
37964
+ const stillSent = mediaAttachmentIdsIn(measured.options);
37965
+ const uploadable = planned.filter((item) => stillSent.has(item.attachmentId));
37966
+ const uploads = uploadable.length === 0 ? void 0 : await this.uploadPlannedReferences({
37967
+ planned: uploadable,
37968
+ accessToken: apiCredentials.accessToken,
37718
37969
  baseUrl: base,
37719
37970
  accountScope,
37720
- mediaType: item.mediaType,
37721
- data: item.data
37971
+ signal
37722
37972
  });
37723
- let inlineBuild;
37724
- try {
37725
- inlineBuild = buildBodyWithinLimit(baseMedia);
37726
- } catch {
37727
- inlineBuild = void 0;
37973
+ let finalBuild = uploads === void 0 ? planned.length === 0 ? measured : buildBodyWithinLimit(baseMedia) : buildBodyWithinLimit({
37974
+ ...baseMedia,
37975
+ imageReferences: uploads.imageReferences,
37976
+ videoReferences: uploads.videoReferences
37977
+ });
37978
+ sentBuild = finalBuild;
37979
+ let body = finalBuild.body;
37980
+ const post = async (payload) => {
37981
+ try {
37982
+ const response = await fetchWithContextBudgetRecovery(fetchFn)(endpoint, {
37983
+ method: "POST",
37984
+ headers,
37985
+ body: payload,
37986
+ signal
37987
+ });
37988
+ activity?.pulse();
37989
+ return response;
37990
+ } catch (error) {
37991
+ if (signal.aborted) throw new LlmError("Kimi Code request aborted", "ABORTED", { cause: error });
37992
+ throw new LlmError(`Kimi Code request failed: ${error instanceof Error ? error.message : String(error)}`, "TRANSPORT", { cause: error });
37993
+ }
37994
+ };
37995
+ if (sideChannel && sessionKey !== "") {
37996
+ const pendingMain = inFlightMainSessionHeaders.get(sessionKey);
37997
+ if (pendingMain !== void 0) {
37998
+ await raceColdStartLeader(pendingMain, signal);
37999
+ if (signal.aborted) throw new LlmError("Kimi Code request aborted", "ABORTED");
38000
+ }
37728
38001
  }
37729
- if (inlineBuild !== void 0) {
37730
- finalBuild = inlineBuild;
37731
- sentBuild = inlineBuild;
37732
- body = inlineBuild.body;
37733
- response = await post(body);
37734
- detail = response.ok ? "" : (await response.text().catch(() => "")).slice(0, 2e3);
38002
+ const coldGroupKey = sideChannel ? void 0 : coldStartGroupKey(region, requestOptions);
38003
+ const coldGate = coldGroupKey === void 0 ? void 0 : await acquireColdStartWarmup(coldGroupKey, signal);
38004
+ const burstPacingRelease = !sideChannel && sessionKey !== "" && getCacheStats(sessionKey).requests === 0 && isSubagentBurstCandidate(requestOptions) ? await acquireSubagentBurstPacing(`${accountScope}:${options.model}`, signal) : () => void 0;
38005
+ let coldGateSettled = false;
38006
+ const settleColdGate = (warm) => {
38007
+ if (coldGateSettled) return;
38008
+ coldGateSettled = true;
38009
+ coldGate?.release();
38010
+ burstPacingRelease();
38011
+ mainHeaderRelease();
38012
+ if (warm) coldGate?.markWarm();
38013
+ };
38014
+ response = await post(body).then((value) => {
38015
+ settleColdGate(value.ok);
38016
+ return value;
38017
+ }, (error) => {
38018
+ settleColdGate(false);
38019
+ throw error;
38020
+ });
38021
+ let detail = response.ok ? "" : (await response.text().catch(() => "")).slice(0, 2e3);
38022
+ if (response.status === 404 && uploads !== void 0 && uploads.cited.length > 0 && isMissingResourceBody(detail)) {
38023
+ const uploader = this.mediaFiles();
38024
+ for (const item of uploads.cited) uploader.forget({
38025
+ baseUrl: base,
38026
+ accountScope,
38027
+ mediaType: item.mediaType,
38028
+ data: item.data
38029
+ });
38030
+ let inlineBuild;
38031
+ try {
38032
+ inlineBuild = buildBodyWithinLimit(baseMedia);
38033
+ } catch {
38034
+ inlineBuild = void 0;
38035
+ }
38036
+ if (inlineBuild !== void 0) {
38037
+ finalBuild = inlineBuild;
38038
+ sentBuild = inlineBuild;
38039
+ body = inlineBuild.body;
38040
+ response = await post(body);
38041
+ detail = response.ok ? "" : (await response.text().catch(() => "")).slice(0, 2e3);
38042
+ }
37735
38043
  }
37736
- }
37737
- if (response.ok) break;
37738
- const failure = classifyKimiFailure(response.status, detail);
37739
- const after = response.status === 429 ? retryAfterMs$1(response.headers) : void 0;
37740
- if (pool !== null && accountId !== void 0) {
37741
- const planScoped = response.status === 429 && matchesAny$1(detail, ENTITLEMENT_PATTERNS);
37742
- if (response.status === 429 && !planScoped && !failure.upstreamOverload) {
37743
- const cooldownMs = failure.accountScoped ? accountLimitCooldownMs(detail) : after ?? POOL_COOLDOWN_MS$5;
37744
- await pool.markCooldown(accountId, cooldownMs, `${PROVIDER_NAME$8} 429`).catch(() => void 0);
37745
- if (await pool.hasAnotherAvailableAccount(tried)) continue;
37746
- } else if (failure.code === "INVALID_CREDENTIAL") {
37747
- await pool.markAuthFailed(accountId, failure.message).catch(() => void 0);
37748
- if (await pool.hasAnotherAvailableAccount(tried)) continue;
37749
- } else if (failure.accountScoped) {
37750
- await pool.markCooldown(accountId, accountLimitCooldownMs(detail), `${PROVIDER_NAME$8} 403`).catch(() => void 0);
37751
- if (await pool.hasAnotherAvailableAccount(tried)) continue;
38044
+ if (response.ok) break;
38045
+ const failure = classifyKimiFailure(response.status, detail);
38046
+ const after = response.status === 429 ? retryAfterMs$1(response.headers) : void 0;
38047
+ if (pool !== null && accountId !== void 0) {
38048
+ const planScoped = response.status === 429 && matchesAny$1(detail, ENTITLEMENT_PATTERNS);
38049
+ if (response.status === 429 && !planScoped && !failure.upstreamOverload) {
38050
+ const cooldownMs = failure.accountScoped ? accountLimitCooldownMs(detail) : after ?? POOL_COOLDOWN_MS$5;
38051
+ await pool.markCooldown(accountId, cooldownMs, `${PROVIDER_NAME$8} 429`).catch(() => void 0);
38052
+ if (await pool.hasAnotherAvailableAccount(tried)) continue;
38053
+ } else if (failure.code === "INVALID_CREDENTIAL") {
38054
+ await pool.markAuthFailed(accountId, failure.message).catch(() => void 0);
38055
+ if (await pool.hasAnotherAvailableAccount(tried)) continue;
38056
+ } else if (failure.accountScoped) {
38057
+ await pool.markCooldown(accountId, accountLimitCooldownMs(detail), `${PROVIDER_NAME$8} 403`).catch(() => void 0);
38058
+ if (await pool.hasAnotherAvailableAccount(tried)) continue;
38059
+ }
37752
38060
  }
38061
+ throw new LlmError(failure.message, failure.code, {
38062
+ status: response.status,
38063
+ ...after === void 0 ? {} : { providerRetryAfterMs: after }
38064
+ });
37753
38065
  }
37754
- throw new LlmError(failure.message, failure.code, {
37755
- status: response.status,
37756
- ...after === void 0 ? {} : { providerRetryAfterMs: after }
37757
- });
37758
- }
37759
- if (sentBuild !== void 0 && !sideChannel) {
37760
- const requestImageBytes = requestImagePayloadLengths(sentBuild.options, images).reduce((sum, bytes) => sum + bytes, 0);
37761
- const trimmedKeys = new Set(collectRemainingImageKeys(imageTrimmed, images));
37762
- const sentKeys = new Set(collectRemainingImageKeys(sentBuild.options, images));
37763
- const bodyFitDroppedKeys = [...trimmedKeys].filter((key) => !sentKeys.has(key));
37764
- const allDroppedKeys = /* @__PURE__ */ new Set([...stickyOffload.allDroppedKeys, ...bodyFitDroppedKeys]);
37765
- recordSessionImageBudget(options.sessionId, {
37766
- allDroppedKeys,
37767
- newlyDroppedCount: stickyOffload.newlyDroppedKeys.length + bodyFitDroppedKeys.length,
37768
- requestImageBytes,
37769
- droppedImages: stickyOffload.droppedCount + bodyFitDroppedKeys.length
37770
- }, requestOptions);
37771
- }
37772
- if (response.body === null) throw new LlmError("Kimi Code returned an empty response body", "PROVIDER_ERROR");
37773
- const reader = response.body.getReader();
37774
- const decoder = new TextDecoder();
37775
- const state = createStreamState$5(wire, requestOptions.sessionId, sideChannel);
37776
- applyCacheWriteTiers(state, response.headers);
37777
- if (!sideChannel) markSessionActive(requestOptions.sessionId);
37778
- let buffer = "";
37779
- /**
37780
- * Set the moment ANY chunk reaches the caller, and never cleared.
37781
- *
37782
- * Deliberately broader than "text arrived": a block-start the caller has
37783
- * already seen repeats just as badly as text it has already read, so the
37784
- * conservative reading is the one that cannot be wrong. It is what keeps the
37785
- * in-band reclassification below pre-output only.
37786
- */
37787
- let outputStarted = false;
37788
- try {
38066
+ if (sentBuild !== void 0 && !sideChannel) {
38067
+ const requestImageBytes = requestImagePayloadLengths(sentBuild.options, images).reduce((sum, bytes) => sum + bytes, 0);
38068
+ const trimmedKeys = new Set(collectRemainingImageKeys(imageTrimmed, images));
38069
+ const sentKeys = new Set(collectRemainingImageKeys(sentBuild.options, images));
38070
+ const bodyFitDroppedKeys = [...trimmedKeys].filter((key) => !sentKeys.has(key));
38071
+ const allDroppedKeys = /* @__PURE__ */ new Set([...stickyOffload.allDroppedKeys, ...bodyFitDroppedKeys]);
38072
+ recordSessionImageBudget(options.sessionId, {
38073
+ allDroppedKeys,
38074
+ newlyDroppedCount: stickyOffload.newlyDroppedKeys.length + bodyFitDroppedKeys.length,
38075
+ requestImageBytes,
38076
+ droppedImages: stickyOffload.droppedCount + bodyFitDroppedKeys.length
38077
+ }, requestOptions);
38078
+ }
38079
+ if (response.body === null) throw new LlmError("Kimi Code returned an empty response body", "PROVIDER_ERROR");
38080
+ const reader = response.body.getReader();
38081
+ const decoder = new TextDecoder();
38082
+ const state = createStreamState$5(wire, requestOptions.sessionId, sideChannel);
38083
+ applyCacheWriteTiers(state, response.headers);
38084
+ if (!sideChannel) markSessionActive(requestOptions.sessionId);
38085
+ let buffer = "";
38086
+ /**
38087
+ * Set the moment ANY chunk reaches the caller, and never cleared.
38088
+ *
38089
+ * Deliberately broader than "text arrived": a block-start the caller has
38090
+ * already seen repeats just as badly as text it has already read, so the
38091
+ * conservative reading is the one that cannot be wrong. It is what keeps the
38092
+ * in-band reclassification below pre-output only.
38093
+ */
38094
+ let outputStarted = false;
37789
38095
  try {
37790
- while (true) {
37791
- const { done, value } = await reader.read();
37792
- if (done) break;
37793
- if (value !== void 0 && value.byteLength > 0) activity?.pulse();
37794
- buffer += decoder.decode(value, { stream: true });
37795
- const lines = buffer.split("\n");
37796
- buffer = lines.pop() ?? "";
37797
- for (const line of lines) {
37798
- activity?.pulse();
37799
- for (const chunk of processLine(line, state, wire)) {
37800
- outputStarted = true;
37801
- yield chunk;
38096
+ try {
38097
+ while (true) {
38098
+ const { done, value } = await reader.read();
38099
+ if (done) break;
38100
+ if (value !== void 0 && value.byteLength > 0) activity?.pulse();
38101
+ buffer += decoder.decode(value, { stream: true });
38102
+ const lines = buffer.split("\n");
38103
+ buffer = lines.pop() ?? "";
38104
+ for (const line of lines) {
38105
+ activity?.pulse();
38106
+ for (const chunk of processLine(line, state, wire)) {
38107
+ outputStarted = true;
38108
+ yield chunk;
38109
+ }
38110
+ if (state.finished) return;
37802
38111
  }
37803
- if (state.finished) return;
37804
38112
  }
38113
+ buffer += decoder.decode();
38114
+ if (buffer.trim() !== "") for (const line of buffer.split("\n")) for (const chunk of processLine(line, state, wire)) {
38115
+ outputStarted = true;
38116
+ yield chunk;
38117
+ }
38118
+ if (state.finished) return;
38119
+ assertStreamComplete$5(state);
38120
+ for (const chunk of closeStream$4(state, servedByAccountId)) {
38121
+ outputStarted = true;
38122
+ yield chunk;
38123
+ }
38124
+ } catch (error) {
38125
+ const inBand = state.streamError;
38126
+ if (error instanceof LlmError && !outputStarted && error.code === "PROVIDER_ERROR" && inBand !== void 0) throw await this.inBandStreamFailure(error, inBand, servedByAccountId);
38127
+ throw streamFailure(error, signal);
37805
38128
  }
37806
- buffer += decoder.decode();
37807
- if (buffer.trim() !== "") for (const line of buffer.split("\n")) for (const chunk of processLine(line, state, wire)) {
37808
- outputStarted = true;
37809
- yield chunk;
37810
- }
37811
- if (state.finished) return;
37812
- assertStreamComplete$5(state);
37813
- for (const chunk of closeStream$4(state, servedByAccountId)) {
37814
- outputStarted = true;
37815
- yield chunk;
37816
- }
37817
- } catch (error) {
37818
- const inBand = state.streamError;
37819
- if (error instanceof LlmError && !outputStarted && error.code === "PROVIDER_ERROR" && inBand !== void 0) throw await this.inBandStreamFailure(error, inBand, servedByAccountId);
37820
- throw streamFailure(error, signal);
38129
+ } finally {
38130
+ if (state.sawUsage && !sideChannel) noteSessionCacheState(requestOptions.sessionId ?? state.sessionId, state);
38131
+ reader.cancel().catch(() => void 0);
37821
38132
  }
37822
38133
  } finally {
37823
- if (state.sawUsage && !sideChannel) noteSessionCacheState(requestOptions.sessionId ?? state.sessionId, state);
37824
- reader.cancel().catch(() => void 0);
38134
+ mainHeaderRelease();
37825
38135
  }
37826
38136
  }
37827
38137
  /**
@@ -81448,8 +81758,13 @@ const POOL_COOLDOWN_MS$1 = 15 * 6e4;
81448
81758
  * The subscription's models at release time, keyed by wire id.
81449
81759
  *
81450
81760
  * Id spellings and prices are transcribed from MODEL_PRICES_URL (fetched
81451
- * 2026-10-21, 37 entries, all chat models — the plan's image models are priced
81452
- * per call and are not in it). Display names use the pricing page's spelling
81761
+ * 2026-11-07, 41 entries, all chat models — the plan's image models are priced
81762
+ * per call and are not in it). A variant the list prices but no other source
81763
+ * describes separately (`deepseek-v4.1-flash-eco`, `gpt-6.1-terra`, `hy4`,
81764
+ * `kimi-k3.1-pro`, added 2026-11-07) transcribes only its price from that list;
81765
+ * its window, output cap, modalities and ladder are inherited from the sibling
81766
+ * row of the same family, which is the rule `deepseek-v4-flash-vision-exp`
81767
+ * already follows. Display names use the pricing page's spelling
81453
81768
  * where that page lists the model (https://open-design.ai/pricing/) and are
81454
81769
  * derived from the id otherwise; the live catalog's own name wins once one is
81455
81770
  * read. Windows, output caps, modalities and ladders come from the sibling
@@ -81603,6 +81918,23 @@ const MODEL_CATALOG$1 = Object.freeze({
81603
81918
  ],
81604
81919
  defaultEffort: "high"
81605
81920
  },
81921
+ "deepseek-v4.1-flash-eco": {
81922
+ name: "DeepSeek V4.1 Flash Eco",
81923
+ pricing: {
81924
+ input: .3,
81925
+ output: 1.2
81926
+ },
81927
+ contextWindow: 1e6,
81928
+ maxTokens: 384e3,
81929
+ input: ["text", "image"],
81930
+ efforts: [
81931
+ "none",
81932
+ "low",
81933
+ "high",
81934
+ "max"
81935
+ ],
81936
+ defaultEffort: "high"
81937
+ },
81606
81938
  "deepseek-v4-flash": {
81607
81939
  name: "DeepSeek V4 Flash",
81608
81940
  pricing: {
@@ -81805,6 +82137,23 @@ const MODEL_CATALOG$1 = Object.freeze({
81805
82137
  "max"
81806
82138
  ]
81807
82139
  },
82140
+ "gpt-6.1-terra": {
82141
+ name: "GPT-6.1 Terra",
82142
+ pricing: {
82143
+ input: 1,
82144
+ output: 5
82145
+ },
82146
+ contextWindow: 105e4,
82147
+ maxTokens: 128e3,
82148
+ input: ["text", "image"],
82149
+ efforts: [
82150
+ "low",
82151
+ "medium",
82152
+ "high",
82153
+ "xhigh",
82154
+ "max"
82155
+ ]
82156
+ },
81808
82157
  "gpt-6-astra": {
81809
82158
  name: "GPT-6 Astra",
81810
82159
  pricing: {
@@ -81900,6 +82249,20 @@ const MODEL_CATALOG$1 = Object.freeze({
81900
82249
  "xhigh"
81901
82250
  ]
81902
82251
  },
82252
+ "hy4": {
82253
+ name: "Hunyuan H4",
82254
+ pricing: {
82255
+ input: .417,
82256
+ output: 1.2505
82257
+ },
82258
+ contextWindow: 1048576,
82259
+ input: ["text"],
82260
+ efforts: [
82261
+ "low",
82262
+ "medium",
82263
+ "high"
82264
+ ]
82265
+ },
81903
82266
  "hy4-preview": {
81904
82267
  name: "Hunyuan H4 Preview",
81905
82268
  pricing: {
@@ -81945,6 +82308,21 @@ const MODEL_CATALOG$1 = Object.freeze({
81945
82308
  "max"
81946
82309
  ]
81947
82310
  },
82311
+ "kimi-k3.1-pro": {
82312
+ name: "Kimi K3.1 Pro",
82313
+ pricing: {
82314
+ input: 2,
82315
+ output: 10
82316
+ },
82317
+ contextWindow: 1048576,
82318
+ maxTokens: 131072,
82319
+ input: ["text", "image"],
82320
+ efforts: [
82321
+ "low",
82322
+ "high",
82323
+ "max"
82324
+ ]
82325
+ },
81948
82326
  "mimo-v2.6-flash": {
81949
82327
  name: "MiMo V2.6 Flash",
81950
82328
  pricing: {
@@ -95359,12 +95737,19 @@ function messageText(data) {
95359
95737
  return "";
95360
95738
  }
95361
95739
  /**
95362
- * 最新用户消息是否明确属于导航任务。
95740
+ * 最新用户消息是否明确属于导航任务,或当前会话正处于只读计划模式(`plan/mode` `active: true`)。
95363
95741
  * @param agent - 工具执行事件里的 agent。
95364
- * @returns 只有明确导航且无源码工作信号时为 true。
95742
+ * @returns 明确导航(无源码工作信号)或处于只读计划模式时为 true。
95365
95743
  */
95366
95744
  function cacheWarmupNavigationIntentOf(agent) {
95367
95745
  const events = eventsOf(agent);
95746
+ for (let index = events.length - 1; index >= 0; index -= 1) {
95747
+ const event = events[index];
95748
+ if (event.type === "plan/mode") {
95749
+ if ((typeof event.data === "object" && event.data !== null ? event.data : void 0)?.active === true) return true;
95750
+ break;
95751
+ }
95752
+ }
95368
95753
  for (let index = events.length - 1; index >= 0; index -= 1) {
95369
95754
  const event = events[index];
95370
95755
  if (event.type !== "user/message") continue;
@@ -95653,7 +96038,13 @@ function installCacheWarmup(ctx, options) {
95653
96038
  const ptcRetrieval = isPtcTransportName(exec.name) && settings.retrievalEnabled === true;
95654
96039
  if (sourceTool && !settings.enabled && !ptcRetrieval) return decision;
95655
96040
  if (retrievalTool && settings.retrievalEnabled !== true) return decision;
95656
- const navigation = retrievalTool || ptcRetrieval ? cacheWarmupNavigationIntentOf(exec.agent) : void 0;
96041
+ const blocks = decision.content ?? result.content;
96042
+ if (blocks.length === 0) return decision;
96043
+ const baseNavigation = retrievalTool || ptcRetrieval ? cacheWarmupNavigationIntentOf(exec.agent) : void 0;
96044
+ const isOversizedSearchDump = (exec.name === "grep" || exec.name === "glob") && blocks.reduce((sum, block) => {
96045
+ return sum + (typeof block === "object" && block !== null && typeof block.text === "string" ? block.text : "").length;
96046
+ }, 0) >= 2e4;
96047
+ const navigation = baseNavigation === true || isOversizedSearchDump ? true : baseNavigation;
95657
96048
  if (retrievalTool && navigation !== true) return decision;
95658
96049
  if (sourceTool && !settings.enabled && navigation !== true) return decision;
95659
96050
  const route = cacheWarmupRouteOf(exec.agent);
@@ -95662,8 +96053,6 @@ function installCacheWarmup(ctx, options) {
95662
96053
  if (sessionId === void 0) return decision;
95663
96054
  const store = storeOf();
95664
96055
  if (store === void 0) return decision;
95665
- const blocks = decision.content ?? result.content;
95666
- if (blocks.length === 0) return decision;
95667
96056
  const content = blocks;
95668
96057
  let durable;
95669
96058
  try {