billion-context 0.1.56 → 0.1.57-pr.261.129

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -43649,7 +43649,7 @@ function formatRanges(compressible, protectedRanges) {
43649
43649
  if (compressible.length === 0 && protectedRanges.length === 0) {
43650
43650
  return "[No specific ranges detected \u2014 compress any consumed content.]";
43651
43651
  }
43652
- const refNum2 = (ref) => {
43652
+ const refNum3 = (ref) => {
43653
43653
  const m2 = ref.match(/\d+/);
43654
43654
  return m2 ? parseInt(m2[0], 10) : 0;
43655
43655
  };
@@ -43658,8 +43658,8 @@ function formatRanges(compressible, protectedRanges) {
43658
43658
  entries.push({
43659
43659
  startRef: r.startRef,
43660
43660
  endRef: r.endRef,
43661
- startNum: refNum2(r.startRef),
43662
- endNum: refNum2(r.endRef),
43661
+ startNum: refNum3(r.startRef),
43662
+ endNum: refNum3(r.endRef),
43663
43663
  count: r.count,
43664
43664
  tokens: r.tokens,
43665
43665
  toolPct: r.toolPct,
@@ -43676,8 +43676,8 @@ function formatRanges(compressible, protectedRanges) {
43676
43676
  entries.push({
43677
43677
  startRef: r.startRef,
43678
43678
  endRef: r.endRef,
43679
- startNum: refNum2(r.startRef),
43680
- endNum: refNum2(r.endRef),
43679
+ startNum: refNum3(r.startRef),
43680
+ endNum: refNum3(r.endRef),
43681
43681
  count: r.count,
43682
43682
  tokens: r.tokens,
43683
43683
  toolPct: 0,
@@ -46427,13 +46427,13 @@ function renderUncompressedRanges(visible) {
46427
46427
  lines.push(" (no uncompressed messages)");
46428
46428
  return lines.join("\n");
46429
46429
  }
46430
- const refNum2 = (ref) => {
46430
+ const refNum22 = (ref) => {
46431
46431
  const m2 = ref.match(/\d+/);
46432
46432
  return m2 ? parseInt(m2[0], 10) : 0;
46433
46433
  };
46434
46434
  const merged = [];
46435
46435
  for (const m2 of visible) {
46436
- const num3 = refNum2(m2.ref);
46436
+ const num3 = refNum22(m2.ref);
46437
46437
  const last = merged[merged.length - 1];
46438
46438
  if (last && num3 === last.startNum + last.count) {
46439
46439
  last.endRef = m2.ref;
@@ -49919,6 +49919,213 @@ function rewriteJsonResponse(body, ctx) {
49919
49919
  return body;
49920
49920
  }
49921
49921
 
49922
+ // src/preflight.ts
49923
+ var MAX_PREFLIGHT_ROUNDS = 8;
49924
+ var CHUNK_FRACTION = 0.6;
49925
+ var MIN_CHUNK_TOKENS = 2e3;
49926
+ var MIN_SUMMARY_CHARS = 50;
49927
+ var MAX_SUMMARY_OUTPUT_TOKENS = 8192;
49928
+ function refMaps(messages, state) {
49929
+ const refToIdx = /* @__PURE__ */ new Map();
49930
+ const idxToRef = /* @__PURE__ */ new Map();
49931
+ const byRaw = state.messageRefs?.byRaw ?? {};
49932
+ messages.forEach((m2, i) => {
49933
+ const ref = byRaw[m2.id];
49934
+ if (!ref) return;
49935
+ if (!refToIdx.has(ref)) refToIdx.set(ref, i);
49936
+ idxToRef.set(i, ref);
49937
+ });
49938
+ return { refToIdx, idxToRef };
49939
+ }
49940
+ function refNum2(ref) {
49941
+ return Number(ref.replace(/\D/g, "")) || 0;
49942
+ }
49943
+ function estimateCoreMessages(messages) {
49944
+ let tokens = 0;
49945
+ for (const m2 of messages) tokens += defaultCountTokens(m2.text ?? "");
49946
+ return tokens;
49947
+ }
49948
+ function rangeChars2(messages, startIdx, endIdx) {
49949
+ let chars = 0;
49950
+ for (let i = startIdx; i <= endIdx && i < messages.length; i++) {
49951
+ chars += (messages[i].text ?? "").length;
49952
+ }
49953
+ return chars;
49954
+ }
49955
+ function renderRange(messages, startIdx, endIdx) {
49956
+ const parts = [];
49957
+ for (let i = startIdx; i <= endIdx && i < messages.length; i++) {
49958
+ const m2 = messages[i];
49959
+ const text = (m2.text ?? "").trim();
49960
+ if (!text) continue;
49961
+ const label = m2.contentType === "tool-call" ? `assistant tool-call ${m2.toolName ?? "?"}` : m2.contentType === "tool-result" ? `tool result ${m2.toolName ?? "?"}` : m2.contentType === "reasoning" ? "assistant reasoning" : m2.role;
49962
+ parts.push(`[${label}]
49963
+ ${text}`);
49964
+ }
49965
+ return parts.join("\n\n");
49966
+ }
49967
+ function splitChunks(messages, startIdx, endIdx, budgetTokens) {
49968
+ const chunks = [];
49969
+ let cur = startIdx;
49970
+ while (cur <= endIdx) {
49971
+ let tokens = 0;
49972
+ let last = cur;
49973
+ for (let i = cur; i <= endIdx; i++) {
49974
+ const t = defaultCountTokens(messages[i].text ?? "");
49975
+ if (tokens + t > budgetTokens && i > cur) break;
49976
+ tokens += t;
49977
+ last = i;
49978
+ }
49979
+ chunks.push([cur, last]);
49980
+ cur = last + 1;
49981
+ }
49982
+ return chunks;
49983
+ }
49984
+ function summaryPayload(protocol, model, system, content) {
49985
+ if (protocol === "anthropic") {
49986
+ return { model, max_tokens: MAX_SUMMARY_OUTPUT_TOKENS, system, messages: [{ role: "user", content }], stream: false };
49987
+ }
49988
+ if (protocol === "openai") {
49989
+ return { model, max_tokens: MAX_SUMMARY_OUTPUT_TOKENS, messages: [{ role: "system", content: system }, { role: "user", content }], stream: false };
49990
+ }
49991
+ return { model, max_output_tokens: MAX_SUMMARY_OUTPUT_TOKENS, instructions: system, input: [{ role: "user", content }], stream: false };
49992
+ }
49993
+ function extractSummaryText(protocol, json) {
49994
+ if (protocol === "anthropic") {
49995
+ const content = json.content;
49996
+ if (!Array.isArray(content)) return "";
49997
+ return content.map((c) => c && typeof c === "object" && c.type === "text" && typeof c.text === "string" ? c.text : "").join("");
49998
+ }
49999
+ if (protocol === "openai") {
50000
+ const choices = json.choices;
50001
+ if (!Array.isArray(choices) || choices.length === 0) return "";
50002
+ const msg = choices[0].message;
50003
+ if (!msg || typeof msg !== "object") return "";
50004
+ const c = msg.content;
50005
+ if (typeof c === "string") return c;
50006
+ if (Array.isArray(c)) {
50007
+ return c.map((p2) => p2 && typeof p2 === "object" && typeof p2.text === "string" ? p2.text : "").join("");
50008
+ }
50009
+ return "";
50010
+ }
50011
+ if (typeof json.output_text === "string") return json.output_text;
50012
+ const output = json.output;
50013
+ if (!Array.isArray(output)) return "";
50014
+ return output.map((o) => o && typeof o === "object" ? o.content : void 0).filter((c) => Array.isArray(c)).flatMap((c) => c).map((p2) => p2 && typeof p2 === "object" && typeof p2.text === "string" ? p2.text : "").join("");
50015
+ }
50016
+ async function summarizeRange(deps, content, startRef, endRef) {
50017
+ const system = buildCompressSystemPrompt(deps.prompts) + `
50018
+
50019
+ TASK: The conversation segment below (messages ${startRef}\u2013${endRef}) must be compressed because the session context exceeds the current model's window. Write a tier-1 compression summary of the segment following every rule above. Output ONLY the summary text \u2014 no preamble, no closing remarks, no tool calls.`;
50020
+ const { response, clearTimer } = await fetchWithRetry(
50021
+ deps.url,
50022
+ {
50023
+ method: "POST",
50024
+ headers: { "content-type": "application/json", ...deps.headers },
50025
+ body: JSON.stringify(summaryPayload(deps.protocol, deps.model, system, content)),
50026
+ dispatcher: proxyDispatcher(deps.proxyUrl)
50027
+ },
50028
+ void 0,
50029
+ deps.signal,
50030
+ (info) => deps.log("warn", `[preflight] summary attempt ${info.attempt} got HTTP ${info.status}; retrying in ${info.delayMs}ms`)
50031
+ );
50032
+ try {
50033
+ const text = await response.text();
50034
+ let json;
50035
+ try {
50036
+ json = JSON.parse(text);
50037
+ } catch {
50038
+ deps.log("warn", `[preflight] summary response was not JSON: ${text.slice(0, 200)}`);
50039
+ return null;
50040
+ }
50041
+ if (!json || typeof json !== "object") return null;
50042
+ const summary = extractSummaryText(deps.protocol, json).trim();
50043
+ if (summary.length < MIN_SUMMARY_CHARS) {
50044
+ deps.log("warn", `[preflight] summary too short (${summary.length} chars); skipping range`);
50045
+ return null;
50046
+ }
50047
+ return summary;
50048
+ } finally {
50049
+ clearTimer();
50050
+ }
50051
+ }
50052
+ async function preflightCompress(deps, messages) {
50053
+ const limit = deps.config.modelContextLimit;
50054
+ const result = { compressedRanges: 0, savedTokens: 0 };
50055
+ if (limit <= 0) return result;
50056
+ const budget = Math.max(MIN_CHUNK_TOKENS, Math.floor(limit * CHUNK_FRACTION));
50057
+ const minChars = deps.config.compress.minCompressRange;
50058
+ let currentTokens = deps.session.stats.lastInputTokens;
50059
+ let startTokens = -1;
50060
+ for (let round = 0; round < MAX_PREFLIGHT_ROUNDS; round++) {
50061
+ if (deps.signal?.aborted) break;
50062
+ const turn = deps.core.processTurn({
50063
+ messages,
50064
+ state: deps.session.state,
50065
+ config: deps.config,
50066
+ tokenCount: currentTokens,
50067
+ renderTags: "text-only"
50068
+ });
50069
+ deps.session.state = turn.state;
50070
+ currentTokens = Math.max(deps.session.stats.lastInputTokens, estimateCoreMessages(turn.messages));
50071
+ if (startTokens < 0) startTokens = currentTokens;
50072
+ if (currentTokens < limit) break;
50073
+ const ranges = viableRanges(turn.nudge?.compressibleRanges ?? []);
50074
+ if (ranges.length === 0) break;
50075
+ const range = [...ranges].sort((a, b2) => refNum2(a.startRef) - refNum2(b2.startRef))[0];
50076
+ const { refToIdx } = refMaps(messages, deps.session.state);
50077
+ const startIdx = refToIdx.get(range.startRef);
50078
+ const endIdx = refToIdx.get(range.endRef);
50079
+ if (startIdx === void 0 || endIdx === void 0 || startIdx > endIdx) break;
50080
+ let appliedThisRound = 0;
50081
+ for (const [cs2, ce2] of splitChunks(messages, startIdx, endIdx, budget)) {
50082
+ if (currentTokens < limit) break;
50083
+ if (deps.signal?.aborted) break;
50084
+ const maps = refMaps(messages, deps.session.state);
50085
+ const startRef = maps.idxToRef.get(cs2);
50086
+ const endRef = maps.idxToRef.get(ce2);
50087
+ if (!startRef || !endRef) continue;
50088
+ if (rangeChars2(messages, cs2, ce2) < minChars) continue;
50089
+ const content = renderRange(messages, cs2, ce2);
50090
+ if (content.length === 0) continue;
50091
+ let summary;
50092
+ try {
50093
+ summary = await summarizeRange(deps, content, startRef, endRef);
50094
+ } catch (err2) {
50095
+ if (err2 instanceof UpstreamHttpError) {
50096
+ deps.log("warn", `[preflight] summarization failed: HTTP ${err2.status} ${err2.body.slice(0, 200)}`);
50097
+ } else {
50098
+ deps.log("warn", `[preflight] summarization failed: ${String(err2)}`);
50099
+ }
50100
+ break;
50101
+ }
50102
+ if (!summary) continue;
50103
+ const ctx = {
50104
+ core: deps.core,
50105
+ config: deps.config,
50106
+ messages,
50107
+ session: deps.session,
50108
+ log: (msg) => deps.log("info", msg)
50109
+ };
50110
+ const creditBefore = deps.session.stats.compressCreditTokens;
50111
+ const applied = applyRanges(parseCompressInput({ content: [{ startId: startRef, endId: endRef, summary, topic: "preflight overflow compress" }] }), ctx);
50112
+ if (applied.startsWith("[Compression FAILED")) {
50113
+ deps.log("warn", `[preflight] ${applied}`);
50114
+ continue;
50115
+ }
50116
+ const compressed = deps.session.stats.compressCreditTokens - creditBefore;
50117
+ currentTokens = Math.max(0, currentTokens - compressed + defaultCountTokens(summary));
50118
+ deps.session.stats.lastInputTokens += defaultCountTokens(summary);
50119
+ appliedThisRound += 1;
50120
+ result.compressedRanges += 1;
50121
+ }
50122
+ if (appliedThisRound === 0) break;
50123
+ }
50124
+ if (result.compressedRanges > 0) deps.session.stats.lastInputTokens = currentTokens;
50125
+ result.savedTokens = Math.max(0, startTokens - currentTokens);
50126
+ return result;
50127
+ }
50128
+
49922
50129
  // src/web/index.ts
49923
50130
  import { readFileSync as readFileSync3 } from "fs";
49924
50131
  import { dirname as dirname4, join as join3 } from "path";
@@ -50212,6 +50419,10 @@ ${icon} [ACP] ${inner}
50212
50419
 
50213
50420
  // src/loop/core.ts
50214
50421
  var MAX_LOOP_ROUNDS = 10;
50422
+ function maxTruncationRetries() {
50423
+ const raw = Number(process.env.BILI_TRUNCATION_RETRY_MAX);
50424
+ return Number.isInteger(raw) && raw >= 0 ? raw : 2;
50425
+ }
50215
50426
  function isLoopThinking(m2) {
50216
50427
  return m2.contentType === "reasoning" && typeof m2.id === "string" && m2.id.startsWith("acp_loop_");
50217
50428
  }
@@ -50292,6 +50503,7 @@ async function* runCompressLoop(upstream, ctx, requestBody, requestOptions, adap
50292
50503
  let currentUpstream = upstream;
50293
50504
  const coreMessages = [...ctx.messages];
50294
50505
  let degradedRetried = false;
50506
+ let truncationRetries = 0;
50295
50507
  try {
50296
50508
  for (let round = 1; round <= MAX_LOOP_ROUNDS; round++) {
50297
50509
  if (signal?.aborted) break;
@@ -50461,7 +50673,9 @@ async function* runCompressLoop(upstream, ctx, requestBody, requestOptions, adap
50461
50673
  yield adapter.emitToolCall(tc);
50462
50674
  }
50463
50675
  const reRequest = proxyResults.length > 0 && realCalls === 0;
50464
- if (!reRequest) {
50676
+ const zeroContent = assistantText.length === 0 && assistantReasoning.length === 0;
50677
+ const canRetryTruncation = !sawDone && zeroContent && realCalls === 0 && round < MAX_LOOP_ROUNDS && truncationRetries < maxTruncationRetries();
50678
+ if (!reRequest && !canRetryTruncation) {
50465
50679
  if (!sawDone) {
50466
50680
  const partialText = assistantText.length;
50467
50681
  const partialReasoning = assistantReasoning.length;
@@ -50482,7 +50696,14 @@ async function* runCompressLoop(upstream, ctx, requestBody, requestOptions, adap
50482
50696
  yield adapter.emitCompletion({ finishReason: "length", usage });
50483
50697
  return;
50484
50698
  }
50485
- ctx.log(`[acp-loop] round ${round}: proxy tool executed; re-requesting so the model sees the result`);
50699
+ if (canRetryTruncation && !reRequest) {
50700
+ truncationRetries += 1;
50701
+ const max = maxTruncationRetries();
50702
+ ctx.log(`[acp-loop] round ${round}: upstream truncated with no content; auto-retrying (attempt ${truncationRetries}/${max})`);
50703
+ log("warn", `[acp-loop] upstream stream truncated with no content (round ${round}); auto-retrying (attempt ${truncationRetries}/${max})`);
50704
+ } else {
50705
+ ctx.log(`[acp-loop] round ${round}: proxy tool executed; re-requesting so the model sees the result`);
50706
+ }
50486
50707
  if (signal?.aborted) break;
50487
50708
  const fetchUpstream = (body) => fetchWithRetry(
50488
50709
  requestOptions.url,
@@ -50628,6 +50849,20 @@ function shouldReserveOutputHeadroom(protocol) {
50628
50849
 
50629
50850
  // src/loop/adapter-responses.ts
50630
50851
  var RESPONSES_ITEM_ID_MAX = 64;
50852
+ function normalizeResponsesMessageItems(input) {
50853
+ if (!Array.isArray(input)) return 0;
50854
+ let typed = 0;
50855
+ for (const item of input) {
50856
+ if (typeof item !== "object" || item === null) continue;
50857
+ const rec = item;
50858
+ if (rec["type"] !== void 0) continue;
50859
+ if (rec["role"] !== "user" && rec["role"] !== "assistant") continue;
50860
+ if (rec["content"] === void 0) continue;
50861
+ rec["type"] = "message";
50862
+ typed++;
50863
+ }
50864
+ return typed;
50865
+ }
50631
50866
  function sanitizeResponsesInputIds(input) {
50632
50867
  if (!Array.isArray(input)) return;
50633
50868
  for (const item of input) {
@@ -52469,7 +52704,10 @@ function takePendingPluginRegister() {
52469
52704
  var registeredIds = /* @__PURE__ */ new Map();
52470
52705
  function consumePluginRegisterFor(conversationId2) {
52471
52706
  const agent = registeredIds.get(conversationId2);
52472
- if (agent !== void 0) registeredIds.delete(conversationId2);
52707
+ if (agent !== void 0) {
52708
+ registeredIds.delete(conversationId2);
52709
+ registeredIds.set(conversationId2, agent);
52710
+ }
52473
52711
  return agent;
52474
52712
  }
52475
52713
  function handlePluginRegister(payload, res) {
@@ -54789,17 +55027,23 @@ ${bodyBuffer.toString("utf8")}`);
54789
55027
  conversationIdentityResponses(parsed, convHeader),
54790
55028
  parsed
54791
55029
  ) : void 0;
54792
- const conversation = protocol === "anthropic" ? conversationSignalAnthropic(parsed, convHeader) : protocol === "openai" ? conversationSignalOpenai(parsed, convHeader) : subagentNamespace(
55030
+ const openaiSignal = protocol === "openai" ? conversationSignalOpenai(parsed, convHeader) : "";
55031
+ const openaiIdentity = protocol === "openai" ? preferPromptCacheKeyIdentity(
55032
+ convHeader ? { value: openaiSignal, source: "header", clientProvided: true } : { value: openaiSignal, source: "content-fingerprint", clientProvided: false },
55033
+ parsed
55034
+ ) : void 0;
55035
+ const conversation = protocol === "anthropic" ? conversationSignalAnthropic(parsed, convHeader) : protocol === "openai" ? openaiIdentity?.value ?? openaiSignal : subagentNamespace(
54793
55036
  responsesIdentity?.value ?? conversationSignalResponses(parsed, convHeader),
54794
55037
  parsed.instructions
54795
55038
  );
54796
55039
  const sessionId = deriveSessionId(req.headers, protocol, upstreamOrigin, conversation);
54797
- const affinity = affinityToken(responsesIdentity ?? {
55040
+ const bodyIdentity = responsesIdentity ?? openaiIdentity;
55041
+ const affinity = affinityToken(bodyIdentity ?? {
54798
55042
  value: clientConv ?? conversation,
54799
55043
  source: clientConv ? "header" : "generated",
54800
55044
  clientProvided: !!clientConv
54801
55045
  });
54802
- const clientLabel = responsesIdentity?.clientProvided ? responsesIdentity.value : clientConversationHeader(req.headers);
55046
+ const clientLabel = bodyIdentity?.clientProvided ? bodyIdentity.value : clientConversationHeader(req.headers);
54803
55047
  const session = getSession(sessionId, { protocol, upstreamOrigin, label: clientLabel ?? void 0 });
54804
55048
  if (!pluginAgent) {
54805
55049
  const identityAgent = consumePluginRegisterFor(clientConv ?? conversation);
@@ -54822,7 +55066,7 @@ ${bodyBuffer.toString("utf8")}`);
54822
55066
  session.metadata.effectiveContextLimit = reqConfig.modelContextLimit;
54823
55067
  recordPluginSession(pluginConversation ?? conversation, session.id);
54824
55068
  }
54825
- if (protocol === "responses") {
55069
+ if (protocol === "responses" || protocol === "openai") {
54826
55070
  const pck = parsed.prompt_cache_key;
54827
55071
  if (typeof pck === "string" && pck.trim().length > 0) {
54828
55072
  recordPluginSession(pck.trim(), session.id);
@@ -54847,7 +55091,23 @@ ${bodyBuffer.toString("utf8")}`);
54847
55091
  acquireInFlight(session);
54848
55092
  try {
54849
55093
  await withSessionLock(session, async () => {
54850
- prepared = countTokens ? prepareCountTokens(parsed, core, reqConfig, log2, session) : protocol === "anthropic" ? prepareAnthropic(parsed, req, opts, core, reqConfig, reqPrompts, log2, session, pluginMode) : protocol === "openai" ? prepareOpenai(parsed, req, opts, core, reqConfig, reqPrompts, log2, session, pluginMode) : responsesCompact ? prepareResponsesCompact(bodyBuffer, parsed, session) : prepareResponses(parsed, req, opts, core, reqConfig, reqPrompts, log2, session, responsesIdentity, pluginMode);
55094
+ const runPrepare = () => countTokens ? prepareCountTokens(parsed, core, reqConfig, log2, session) : protocol === "anthropic" ? prepareAnthropic(parsed, req, opts, core, reqConfig, reqPrompts, log2, session, pluginMode) : protocol === "openai" ? prepareOpenai(parsed, req, opts, core, reqConfig, reqPrompts, log2, session, pluginMode) : responsesCompact ? prepareResponsesCompact(bodyBuffer, parsed, session) : prepareResponses(parsed, req, opts, core, reqConfig, reqPrompts, log2, session, responsesIdentity, pluginMode);
55095
+ prepared = runPrepare();
55096
+ if (!countTokens && !responsesCompact) {
55097
+ prepared = await preflightCompressIfNeeded(
55098
+ prepared,
55099
+ runPrepare,
55100
+ req,
55101
+ res,
55102
+ opts,
55103
+ core,
55104
+ reqConfig,
55105
+ parsed.model,
55106
+ route,
55107
+ affinity,
55108
+ log2
55109
+ );
55110
+ }
54851
55111
  await forward(req, res, opts, prepared.body, prepared, core, reqConfig, log2, route, affinity);
54852
55112
  if (prepared) {
54853
55113
  rememberPluginMessages(sessionId, prepared.processedMessages, prepared.originalMessages, prepared.nudge);
@@ -54865,8 +55125,15 @@ ${bodyBuffer.toString("utf8")}`);
54865
55125
  }
54866
55126
  }
54867
55127
  var ACP_TAG_MARK = "<acp ";
54868
- function stripKernelSummaries(messages) {
54869
- return messages.filter((m2) => !(m2.id ?? "").startsWith("acp_summary_"));
55128
+ function stripKernelSummaries(messages, state) {
55129
+ const carried = /* @__PURE__ */ new Set();
55130
+ for (const b2 of state.blocks) {
55131
+ if (!b2.active || !b2.compressCallId) continue;
55132
+ if (messages.some((m2) => m2.contentType === "tool-call" && m2.toolCallId === b2.compressCallId)) {
55133
+ carried.add(`acp_summary_${b2.blockId}`);
55134
+ }
55135
+ }
55136
+ return messages.filter((m2) => !(m2.id ?? "").startsWith("acp_summary_") || !carried.has(m2.id));
54870
55137
  }
54871
55138
  function diagTagSummary(messages, sessionId, strategy) {
54872
55139
  let textTagged = 0;
@@ -54921,7 +55188,7 @@ function prepareAnthropic(parsed, req, opts, core, config, prompts, log2, sessio
54921
55188
  }
54922
55189
  log2("info", diagTagSummary(turn.messages, sessionId, "text-only"));
54923
55190
  log2("info", diagNudge(turn, sessionId, tokenCount, config.modelContextLimit, parsed.model));
54924
- processedMessages = stripKernelSummaries(turn.messages);
55191
+ processedMessages = stripKernelSummaries(turn.messages, turn.state);
54925
55192
  reapOrphanBlocks(session, msgs, deactivateBlock);
54926
55193
  rebuiltMessages = coreToAnthropic(processedMessages, cacheControls);
54927
55194
  systemOut = injectSystem(parsed, opts, prompts);
@@ -54977,7 +55244,7 @@ function prepareOpenai(parsed, req, opts, core, config, prompts, log2, session,
54977
55244
  }
54978
55245
  log2("info", diagTagSummary(turn.messages, sessionId, "text-only"));
54979
55246
  log2("info", diagNudge(turn, sessionId, tokenCount, config.modelContextLimit, parsed.model));
54980
- processedMessages = stripKernelSummaries(turn.messages);
55247
+ processedMessages = stripKernelSummaries(turn.messages, turn.state);
54981
55248
  reapOrphanBlocks(session, msgs, deactivateBlock);
54982
55249
  rebuiltMessages = coreToOpenai(processedMessages);
54983
55250
  const sysParts = [];
@@ -55021,6 +55288,10 @@ function prepareResponses(parsed, req, opts, core, config, prompts, log2, sessio
55021
55288
  let responsesProjection;
55022
55289
  let rebuiltInput = parsed.input;
55023
55290
  let toolsOut = parsed.tools;
55291
+ const typedItems = normalizeResponsesMessageItems(parsed.input);
55292
+ if (typedItems > 0) {
55293
+ log2("info", `[${sessionId}] stamped type:"message" on ${typedItems} type-less input item(s) before projection (omp wire form)`);
55294
+ }
55024
55295
  sanitizeResponsesInputIds(parsed.input);
55025
55296
  const droppedEmpty = dropWhitespaceResponsesMessages(parsed.input);
55026
55297
  if (droppedEmpty > 0) {
@@ -55050,7 +55321,7 @@ function prepareResponses(parsed, req, opts, core, config, prompts, log2, sessio
55050
55321
  }
55051
55322
  log2("info", diagTagSummary(turn.messages, sessionId, "text-only"));
55052
55323
  log2("info", diagNudge(turn, sessionId, tokenCount, config.modelContextLimit, parsed.model));
55053
- processedMessages = stripKernelSummaries(turn.messages);
55324
+ processedMessages = stripKernelSummaries(turn.messages, turn.state);
55054
55325
  reapOrphanBlocks(session, msgs, deactivateBlock);
55055
55326
  rebuiltInput = patchResponsesInput(projection, processedMessages);
55056
55327
  if (shouldInject && !process.env.ACP_NO_COMPRESS_PROMPT) {
@@ -55121,7 +55392,7 @@ function prepareCountTokens(parsed, core, config, log2, session) {
55121
55392
  try {
55122
55393
  const { msgs, cacheControls } = anthropicToCore(parsed);
55123
55394
  const turn = core.processTurn({ messages: msgs, state: session.state, config, tokenCount: session.stats.lastInputTokens, renderTags: "text-only" });
55124
- const stripped = stripKernelSummaries(turn.messages);
55395
+ const stripped = stripKernelSummaries(turn.messages, turn.state);
55125
55396
  const rebuiltMessages = coreToAnthropic(stripped, cacheControls);
55126
55397
  log2("info", `[${sessionId}] count_tokens pruned: ${msgs.length} \u2192 ${stripped.length} msgs`);
55127
55398
  return {
@@ -55208,11 +55479,71 @@ function injectResponsesTool(tools, toolsToAdd = ACP_TOOLS_RESPONSES) {
55208
55479
  const additions = toolsToAdd.filter((t) => !present.has(t.name));
55209
55480
  return [...tools, ...additions];
55210
55481
  }
55211
- async function forward(req, res, opts, body, prepared, core, config, log2, route, affinity) {
55482
+ function buildForwardTarget(req, opts, route, affinity) {
55212
55483
  const reqUrl = req.url ?? "";
55213
55484
  const isAbsoluteUrl = /^https?:\/\//i.test(reqUrl);
55214
55485
  const rewritten = route ? route.rewrittenUrl : isAbsoluteUrl ? reqUrl : opts.upstream + reqUrl;
55215
55486
  const upstreamUrl = rewritten.replace(/^mitm:\/\//, "https://");
55487
+ const headers = {};
55488
+ const reqConnNamed = connectionNamedHeaders(req.headers["connection"]);
55489
+ for (const [k2, v2] of Object.entries(req.headers)) {
55490
+ const lower = k2.toLowerCase();
55491
+ if (UPSTREAM_HOP_HEADERS.has(lower) || reqConnNamed.has(lower) || v2 === void 0) continue;
55492
+ headers[k2] = Array.isArray(v2) ? v2.join(", ") : v2;
55493
+ }
55494
+ headers["host"] = new URL(upstreamUrl).host;
55495
+ const betaKey = Object.keys(headers).find((h) => h.toLowerCase() === "x-codex-beta-features");
55496
+ if (betaKey) {
55497
+ const kept = headers[betaKey].split(",").map((s3) => s3.trim()).filter((f2) => f2 && f2 !== "remote_compaction_v2");
55498
+ if (kept.length > 0) headers[betaKey] = kept.join(",");
55499
+ else delete headers[betaKey];
55500
+ }
55501
+ if (affinity && !clientConversationHeader(req.headers)) {
55502
+ headers["x-session-id"] = affinity;
55503
+ }
55504
+ const proxyUrl = resolveProxy(opts.routes, opts.proxy, route?.rewrittenUrl ?? upstreamUrl, opts.proxyFallback);
55505
+ return { upstreamUrl, headers, proxyUrl };
55506
+ }
55507
+ async function preflightCompressIfNeeded(prepared, runPrepare, req, res, opts, core, config, model, route, affinity, log2) {
55508
+ const session = prepared.session;
55509
+ const limit = config.modelContextLimit;
55510
+ const tokenCount = Math.max(session.stats.lastInputTokens, estimateCoreMessages(prepared.processedMessages));
55511
+ if (limit <= 0 || !model || tokenCount < limit) return prepared;
55512
+ if ((prepared.nudge?.compressibleRanges ?? []).length === 0) return prepared;
55513
+ log2("warn", `[${session.id}] context ${tokenCount} tokens exceeds model window ${limit} (model=${model}); preflight compressing before forward`);
55514
+ const { upstreamUrl, headers, proxyUrl } = buildForwardTarget(req, opts, route, affinity);
55515
+ const clientAbort = new AbortController();
55516
+ res.on("close", () => {
55517
+ if (!res.writableEnded) clientAbort.abort();
55518
+ });
55519
+ const started = Date.now();
55520
+ const result = await preflightCompress(
55521
+ {
55522
+ core,
55523
+ session,
55524
+ config,
55525
+ prompts: prepared.prompts ?? defaultPrompts,
55526
+ protocol: prepared.protocol,
55527
+ url: upstreamUrl,
55528
+ headers,
55529
+ model,
55530
+ proxyUrl,
55531
+ signal: clientAbort.signal,
55532
+ log: log2
55533
+ },
55534
+ prepared.originalMessages
55535
+ );
55536
+ if (result.compressedRanges > 0) {
55537
+ log2("info", `[${session.id}] preflight compressed ${result.compressedRanges} range(s), ~${result.savedTokens} tokens saved (${tokenCount} \u2192 ${session.stats.lastInputTokens}) in ${Date.now() - started}ms; rebuilding payload`);
55538
+ const rebuilt = runPrepare();
55539
+ session.stats.requests -= 1;
55540
+ return rebuilt;
55541
+ }
55542
+ log2("warn", `[${session.id}] preflight could not compress enough (~${result.savedTokens} tokens saved); forwarding as-is`);
55543
+ return prepared;
55544
+ }
55545
+ async function forward(req, res, opts, body, prepared, core, config, log2, route, affinity) {
55546
+ const { upstreamUrl, headers, proxyUrl } = buildForwardTarget(req, opts, route, affinity);
55216
55547
  log2("info", `forward ${req.method} \u2192 ${upstreamUrl}`);
55217
55548
  if (process.env.ACP_DEBUG && prepared) {
55218
55549
  const sid = prepared.session.id;
@@ -55254,24 +55585,6 @@ async function forward(req, res, opts, body, prepared, core, config, log2, route
55254
55585
  } catch {
55255
55586
  }
55256
55587
  }
55257
- const headers = {};
55258
- const reqConnNamed = connectionNamedHeaders(req.headers["connection"]);
55259
- for (const [k2, v2] of Object.entries(req.headers)) {
55260
- const lower = k2.toLowerCase();
55261
- if (UPSTREAM_HOP_HEADERS.has(lower) || reqConnNamed.has(lower) || v2 === void 0) continue;
55262
- headers[k2] = Array.isArray(v2) ? v2.join(", ") : v2;
55263
- }
55264
- headers["host"] = new URL(upstreamUrl).host;
55265
- const betaKey = Object.keys(headers).find((h) => h.toLowerCase() === "x-codex-beta-features");
55266
- if (betaKey) {
55267
- const kept = headers[betaKey].split(",").map((s3) => s3.trim()).filter((f2) => f2 && f2 !== "remote_compaction_v2");
55268
- if (kept.length > 0) headers[betaKey] = kept.join(",");
55269
- else delete headers[betaKey];
55270
- }
55271
- if (affinity && !clientConversationHeader(req.headers)) {
55272
- headers["x-session-id"] = affinity;
55273
- }
55274
- const proxyUrl = resolveProxy(opts.routes, opts.proxy, route?.rewrittenUrl ?? upstreamUrl, opts.proxyFallback);
55275
55588
  if (opts.debug) {
55276
55589
  const hdrLog = {};
55277
55590
  for (const [hk, hv] of Object.entries(headers)) {