diff --git a/package-lock.json b/package-lock.json index b98a8c8..672b2d3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,7 +15,7 @@ "devDependencies": { "@types/node": "^22.0.0", "@types/node-forge": "^1.3.14", - "acp-kernel": "0.0.34", + "acp-kernel": "0.0.36", "fzstd": "0.1.1", "node-forge": "^1.4.0", "tar": "^7.5.22", @@ -972,9 +972,9 @@ } }, "node_modules/acp-kernel": { - "version": "0.0.34", - "resolved": "https://registry.npmjs.org/acp-kernel/-/acp-kernel-0.0.34.tgz", - "integrity": "sha512-iB1B7A92xYESmtBNJlUUP27A9t7yP/ULkC+rgnHDrwvC/rGJBMgkm0/P2tnXPRadwUNfXUoL3CGGzg7EkTUF8A==", + "version": "0.0.36", + "resolved": "https://registry.npmjs.org/acp-kernel/-/acp-kernel-0.0.36.tgz", + "integrity": "sha512-w3lyfah74H35HHBzmw/jwLVixPRfC1K7wbFjKrwoV1qdw5847kjzNxiJ3i6upEY3YPJI517A5FyPhne0vbvSVg==", "dev": true, "license": "MIT", "engines": { diff --git a/package.json b/package.json index 938e6d1..4c6a6c4 100644 --- a/package.json +++ b/package.json @@ -41,7 +41,7 @@ "devDependencies": { "@types/node": "^22.0.0", "@types/node-forge": "^1.3.14", - "acp-kernel": "0.0.34", + "acp-kernel": "0.0.36", "fzstd": "0.1.1", "node-forge": "^1.4.0", "tar": "^7.5.22", diff --git a/src/server.ts b/src/server.ts index 4afb6af..b40842e 100644 --- a/src/server.ts +++ b/src/server.ts @@ -1,6 +1,6 @@ import http from "node:http"; import fs from "node:fs"; -import { createCore, type CompressionCore, type Config, type CoreMessage, type NudgeDecision, type Prompts, defaultPrompts, estimateTokensFast, renderNudgeText, deactivateBlock } from "acp-kernel"; +import { createCore, type CompressionCore, type Config, type CoreMessage, type NudgeDecision, type Prompts, defaultPrompts, estimateTokensFast, renderNudgeText, deactivateBlock, viableRanges } from "acp-kernel"; import { resolveCompress, resolveCompressPrompts, resolveRequestConfig } from "./compress-settings.js"; import type { ProxyOptions } from "./config.js"; import { loadOptions, loadRoutes } from "./config.js"; @@ -870,6 +870,10 @@ function prepareAnthropic( const tokenCount = session.stats.lastInputTokens; const turn = core.processTurn({ messages: msgs, state: session.state, config, tokenCount, renderTags: "text-only" }); session.state = turn.state; + // Drop sub-viability fragments before any consumer sees them: a tiny + // range in the list makes batched compress attempts fail atomically + // (kernel validates the whole batch). Mirrors billion-context-pi. + if (turn.nudge) turn.nudge.compressibleRanges = viableRanges(turn.nudge.compressibleRanges); nudge = turn.nudge; session.stats.contextTokens = tokenCount; if (!session.meta.title) { @@ -948,6 +952,10 @@ function prepareOpenai( const tokenCount = session.stats.lastInputTokens; const turn = core.processTurn({ messages: msgs, state: session.state, config, tokenCount, renderTags: "text-only" }); session.state = turn.state; + // Drop sub-viability fragments before any consumer sees them: a tiny + // range in the list makes batched compress attempts fail atomically + // (kernel validates the whole batch). Mirrors billion-context-pi. + if (turn.nudge) turn.nudge.compressibleRanges = viableRanges(turn.nudge.compressibleRanges); nudge = turn.nudge; session.stats.contextTokens = tokenCount; if (!session.meta.title) { @@ -1044,6 +1052,10 @@ function prepareResponses( const tokenCount = session.stats.lastInputTokens; const turn = core.processTurn({ messages: msgs, state: session.state, config, tokenCount, renderTags: process.env.ACP_RENDER_NONE ? "none" : "text-only" }); session.state = turn.state; + // Drop sub-viability fragments before any consumer sees them: a tiny + // range in the list makes batched compress attempts fail atomically + // (kernel validates the whole batch). Mirrors billion-context-pi. + if (turn.nudge) turn.nudge.compressibleRanges = viableRanges(turn.nudge.compressibleRanges); nudge = turn.nudge; session.stats.contextTokens = tokenCount; if (!session.meta.title) {