Repository navigation
Archive-then-fold: default folding for archivable media (Closes #2607, Fixes #2609) - #2640
Conversation
…ads (#2607) Split hasMediaPayload into the media-presence predicate and a new hasUnrecoverableMediaPayload that pins only payloads whose bytes bili cannot store (remote URLs, DeepSeek file refs, google fileData/videoMetadata). Archivable inline media now folds like any other message: assignRefs mints it a numeric ref (legacy BLOCKED entries migrate to fresh numbers, never reusing old ones), buildCompressibleRanges no longer treats it as a barrier, and applyCompression folds it instead of excluding it. Unrecoverable payloads keep the #1188 never-fold exemption; the fold warning now names them and points at decompress({ imageRef }) for the archivable path. Also closes the google fileData detection gap (#2609). package-lock.json: acp-kernel 0.0.110 -> 0.0.112 (this bump; 0.0.110 was already stale vs master's 0.0.111) and pi-subagents 0.1.3 -> 0.1.4 (pre-existing drift synced by npm install --package-lock-only).
…#2607) The recovery index previously ran only with stripImages enabled, but archivable media now folds by default (#2607) and its pixels must exist BEFORE the fold: run buildIncomingImageIndex on every session request (gate drops the flag) and merge-refresh it after prepare, when the turn's refs are assigned, so images in the folded range spill to <state>/retrieve/img/<session>/ under their mNNNNN ref and decompress({ imageRef }) restores them. New e2e test pins the always-on archive; fix-781 e2e lanes now assert the folded-forward shape (placeholders with refs reach the summary input, image bytes leave the forward except the kernel's pinned session-opening user message - first-user pin, prune.ts / DESIGN.md section 8.1). CONFIGURATION en+zh document default folding and the one-image residual.
📦 Built Package ArtifactBranch: Option A — Install this exact build (recommended)npm install -g billion-context@0.0.2892-pr.2640.bf52d39This exact version is immutable and reproducible. The rolling Option B — Download artifact
tar xzf billion-context-pr2640.tgz
npm install -g packageInstall instructions are refreshed on each push. |
[bot] 🏷 结论先行:方向正确、实现干净、测试有牙。唯一硬红灯是 kernel-guard(机械性版本冲突,非代码问题);另分支落后 master 48 提交需先 rebase。因含 我做了什么:checkout PR 分支,通读全部 14 个改动文件(kernel 源 6 含 package.json、kernel 测试 1、host 2、文档 2、bili 测试 2、lockfile 1),逐 wire 核对「可恢复 ⇔ 已落盘」镜像不变量与 id 不复用契约,核对了 CI 状态与断言有效性。本地未预跑全量——node_modules/kernel-dist 未构建,装依赖等于重复 CI 正在跑的 ubuntu+windows 双矩阵,按本地测试纪律交给远程 CI。 结构化八问
阻塞项(merge 前必处理)
次要发现(不阻塞)
判定:方向与实现均对,测试(新增 fold-images-archive、反转后的 fix-781 e2e、kernel media-payload)断言有牙、能兜住这次行为反转。解掉版本冲突并 rebase 后,即可进入人工合并评审。 |
…efault fold, google inlineData fold
- responses lane: default-config fold of an image message, then
resolveDecompress({ imageRef }) against the live session restores
byte-identical pixels from the always-on archive pass
- google lane: inlineData folds out of rebuilt contents once the range
clears the soft-protected zone (last 5 msgs + 5000 tokens + last user);
demand fires at >=20 refs with endId = len-8 so the turn-3 image rides
deep inside the range; post-fold bodies carry no PNG bytes, pixels
spill by ref, decompress restores them
- client echoes the model text it actually receives (fabricated echoes
churn the ref space)
📦 Merged Build PublishedThis merge to master was published as npm install -g billion-context@0.0.226-master.a85e5cd # this exact build
npm install -g billion-context@master # always the newest merged build
|
…ia folding replaces it Default archivable-media folding (ranxianglei#2640) made the opt-in wire-side image strip redundant, and the strip itself broke the prompt cache every turn on three of four wires (sliding cutoff moves the byte boundary per turn; only anthropic had the fold-anchored boundary). Media handling now has exactly one path: fold + archive + decompress({ imageRef }) recovery. - kernel: strip-images.ts (stripHistoricalImages) retired; wire barrel and wire-google tests updated; acp-kernel 0.0.113 -> 0.0.114 (kernel-change: removing a public wire export that exists only for the removed host policy; no compression behavior changes) - host: strip wiring, fold-anchored cutoff, and DEFAULT_STRIP_IMAGES_KEEP_RECENT removed from handle.ts/server.ts/compress-settings.ts; image-restore.ts keeps the always-on index + spill + decompress machinery (that is the default-fold recovery path, not the strip's) - config: compress.stripImages / compress.stripImagesKeepRecent dropped from the type, whitelist, and parser; old configs get a one-time INERT warning (warnInertStripImages) instead of silent no-op - docs: seeds + generated tables regenerated; EN/ZH prose sections replaced with removal notes; decompress error texts no longer reference the flag - tests: strip-images / strip-images-compact / strip-log-observability / strip-cutoff-anchor suites deleted; compress-settings cascade/parse cases removed; new strip-images-removal.test.ts pins the INERT notice + silence Closes ranxianglei#2608 (archival-failure-still-strips existed only on the strip path; with the strip gone there is nothing to fail)
kernel-change: media messages were exempt from folding forever (#1188), which made image-heavy sessions' input floor grow monotonically and fragmented compressible ranges (billion-context#2607). Owner approved the archive-then-fold design in the #2607 thread (2026-10-10): archivable inline media folds like text with its pixels archived by ref BEFORE the fold; only payloads whose bytes bili cannot store stay pinned. The host side cannot express this — the exemption lives in the kernel's ref/range/apply pipeline.Closes #2607 · Fixes #2609
What changes
Kernel (
acp-kernel0.0.111 → 0.0.112):hasUnrecoverableMediaPayloadalongsidehasMediaPayload: pins only media whose bytes bili cannot store locally — remote-URL images, DeepSeek{type:"file"}refs, googlefileData/videoMetadata(the last was previously undetected entirely — Google wire 的 fileData(URL 引用)图像不被识别为媒体负载:可被折叠、折叠后静默丢失且无警告(#1188 不变量缺口) #2609). Archivable = inline base64 / data-URL, including data-URLs inside anthropicurlsources (mirrors what the host's archiver actually stores).assignRefsprotection,buildCompressibleRangesbarrier,applyCompressionexclusion + warning. Archivable media now folds like text: it gets a numericmNNNNNref, no longer fragments compressible ranges, and enters block coverage.BLOCKEDmint a fresh numeric ref at the next prepare — fresh number only, never a reuse (id contract intact).decompress({ imageRef })for the archivable path instead of suggestingstripImages.Host:
buildIncomingImageIndex) runs on every session request instead of only whenstripImagesis enabled, plus a merge-refresh after prepare — when the turn's refs are assigned — so images in a fold range spill to<state>/retrieve/img/<session>/under their ref before any fold can happen. This is what makes default folding lossless for archivable media.Behavior changes (old → new)
decompress({ imageRef })stripImagesstripImages(it cannot help these payloads)stripImagescannot recover bytes bili never hadfileData/videoMetadataURLsBLOCKEDmedia refs<state>/retrieve/img/<session>/disk usagestripImages: truestripImages/stripImagesKeepRecentResidual (documented, accepted): the kernel pins the session-opening user message through folds (first-user pin,
prune.tsrebuildMessages/ DESIGN.md §8.1 — strict providers reject conversations with no user message). If that opening message carries an inline image, that single image stays on the wire for the session's life; every later image folds away. The floor becomes constant (one image), not growing. Changing pin semantics is a kernel product decision beyond this scope — flagged here for owner review rather than silently shipped.Config surface
No new fields, no renames, no re-semantics of existing keys.
compress.stripImagesandcompress.stripImagesKeepRecentkeep exactly their current semantics; docs updated to state they are now an extra lever on top of default folding.Tests
media-payload.test.ts(19 tests): fullhasUnrecoverableMediaPayloadmatrix across all four wires (incl. googlefileData/videoMetadata/functionResponsenesting for Google wire 的 fileData(URL 引用)图像不被识别为媒体负载:可被折叠、折叠后静默丢失且无警告(#1188 不变量缺口) #2609),assignRefsarchivable→numeric + BLOCKED→fresh-ref migration, range span/unspan split, applyCompression fold/exclude split with the new warning text.tests/fold-images-archive.test.ts(always-on archive: spill file appears under the session dir withstripImagesOFF, stable across turns) and the rewritten fix-781 e2e lanes (placeholder + ref reach the summary input; the forward carries no folded image bytes except the pinned opener).npm run typecheck+npm run buildgreen; kernel built and consumed by the bili suite viafile:link.Full regression left to CI.