Skip to content

fix: inline typebox into dist (ACP tags/nudge silently disappeared) - #18

Merged
ranxianglei merged 1 commit into
masterfrom
2026-08-01_fix-typebox-not-inlined
Aug 1, 2026
Merged

ranxianglei merged 1 commit into
masterfrom
2026-08-01_fix-typebox-not-inlined

Conversation

@ranxianglei

Copy link
Copy Markdown
Owner

问题(Blocker)

ACP 的标签注入和 nudge 静默消失了——本会话从头到尾没有任何 `` 标签、没有 nudge,但 `acp_status` 工具照常工作。

根因

`tsup.config.ts` 把 `typebox` 列在 `external`,导致 `dist/index.js` 保留了 4 处运行时 `import { Type } from "typebox"`。但:

  1. pai-acp 的 `package.json` 没有任何 dependencies(typebox 是 `@earendil-works/pi-coding-agent` 的间接依赖)
  2. pi 的安装布局(`~/.pi/agent/npm/node_modules/`)任何层级都没有 typebox

结果:session 启动时 `import "typebox"` 抛 `ERR_MODULE_NOT_FOUND`,扩展的模块求值崩溃,pi 静默丢弃它 → `context` 事件 handler 没注册 → 无标签注入、无 nudge。`acp_status` 工具通过另一条加载路径侥幸能用,造成"扩展加载了但功能没了"的迷惑表象。

修复

从 `external` 移除 `typebox`,加入 `noExternal` 强制 esbuild 内联(typebox 是 ESM-only 且无 `main`,这是 tsup 默认不当 external 的原因)。

dist 从 123KB → 330KB(内联了 typebox 运行时)。验证:dist 里 `from "typebox"` 0 残留,且在完全没有 typebox 的环境下能干净加载(context handler 注册、4 工具 + 4 命令)。

影响

Blocker 级回归:每个在 typebox 不可解析的 pi 布局下运行的 pai-acp 安装都有静默的 context-management 失效。很可能在工具 schema 开始 import Type 时引入。

typecheck ✅ · 32/32 tests ✅

-1/+1,单文件。

…udge)

tsup.config.ts listed "typebox" in `external`, so dist/index.js kept four
runtime `import { Type } from "typebox"` statements. But pai-acp's
package.json has NO dependencies (typebox is a transitive dep of
@earendil-works/pi-coding-agent), and the pi install layout
(~/.pi/agent/npm/node_modules/) does NOT contain typebox at any level.
Result: at session start, `import "typebox"` threw ERR_MODULE_NOT_FOUND,
the extension's module evaluation crashed, and pi silently dropped it —
so the `context` event handler never registered, meaning NO ref-tag
injection and NO nudge, even though the acp_status tool still worked
(loaded via a separate path). ACP compression effectively disappeared.

Remove "typebox" from `external` and add it to `noExternal` to force
esbuild to bundle it (typebox is ESM-only with no `main`, which is why
tsup left it external by default). dist grows 123KB→330KB (now carries
the typebox runtime inline); verified zero `from "typebox"` remain and
that the dist loads cleanly in an environment with NO typebox installed
(context handler registers, 4 tools + 4 commands).

This is a Blocker-class regression: every pai-acp install that ran under
a pi layout without a resolvable typebox had silent context-management
failure. Likely introduced when tool schemas started importing Type.

typecheck clean; 32/32 tests pass.
@ranxianglei
ranxianglei merged commit 1c8a4af into master Aug 1, 2026
3 checks passed
aerostone pushed a commit to aerostone/billion-context-pi that referenced this pull request Aug 27, 2026
…rowth threshold

- usage floor: when the local sent-view estimate under-reports (CJK/GBK
  content on k9s/Qwen ran 2-4x low, nudges stayed idle at 128% real
  usage), trust pi's provider-anchored getContextUsage().tokens; a 1.5x
  window cap rejects the no-usage tree-fallback (omp ranxianglei#18 false EMERGENCY)
- self-heal: parse k9s 'maximum context length of N' (regex required
  'is N'), so the learned-window recenter can fire on k9s 400s
- config: default nudgeGrowthTokens now scales with the window
  (min(50k, max(20k, 25% of limit))) instead of a flat 50k that let
  small-window sessions ride fragmented context past the hard bands
- system prompt: warn that an oversized single tool call hits the
  output budget and is dropped (k9s sessions died looping on one giant
  file write)

Upstreams the manual dist usage-floor patch (ACP-K9S-PATCH-v1) that the
k9s forensics work had been re-applying by hand after every upgrade.
ranxianglei pushed a commit that referenced this pull request Aug 31, 2026
…m usage scan

The host's real context usage is already anchored on the last assistant's
provider-reported usage (+ trailing estimate) and is the same value
density.update is fed — floor and calibration target become one quantity.
Drops lastProviderPromptTokens and its unit tests; removes the
session-tree regression test (omp #18 scenario, no longer applicable).
HangxiangMa pushed a commit to HangxiangMa/billion-context-pi that referenced this pull request Sep 21, 2026
…ounting

Same class of bug as omp ranxianglei#39: pi's getContextUsage anchors on the last
assistant's provider-reported usage when available (~ the real sent view),
but falls back to summing the whole session tree when providers report no
usage. The tree includes compressed originals and never shrinks, so after
compression (or after switching to a smaller-window model) it can exceed
the window many times over while the real sent view is a few percent —
permanent false EMERGENCY nudges while the session keeps working.

- context transform / acp_status / /acp panel all pass
  estimateTokens(coreMessages, coveredIds) + systemPrompt estimate to
  processTurn (same scale as the kernel breakdown)
- the tree-scale number is logged (sessionTokens) and displayed on the
  panel's footer-scale line only
- kit pin 0.1.1 -> 0.2.0: panel gains scale labels and same-scale
  Session-only derivation (unprunedTokens now passed; omp issue ranxianglei#18)
- regression tests: 366K tree / 180K window / 36K sent view must NOT
  emergency; a real 270K sent view MUST (red on old code, green now)
HangxiangMa pushed a commit to HangxiangMa/billion-context-pi that referenced this pull request Sep 21, 2026
…m usage scan

The host's real context usage is already anchored on the last assistant's
provider-reported usage (+ trailing estimate) and is the same value
density.update is fed — floor and calibration target become one quantity.
Drops lastProviderPromptTokens and its unit tests; removes the
session-tree regression test (omp ranxianglei#18 scenario, no longer applicable).
HangxiangMa pushed a commit to HangxiangMa/billion-context-pi that referenced this pull request Sep 21, 2026
… successful compress

pi's getContextUsage() anchors on the last assistant message with valid
provider usage. A successful compress lands AFTER that anchor, so the next
LLM call floors the meter at the pre-compress request size and re-runs the
emergency decision (nudge + mechanical tool-result truncation) on context
that was just shrunk; the panel keeps showing the old large number too.

- new src/floor-stale.ts: usageAnchorPredatesCompression(entries) scans the
  branch for the last valid assistant usage anchor (same validity rule as
  pi's getAssistantUsage) vs the last successful compress toolResult
  (panel >0 blocks; failed/no-op compresses don't count)
- skip the floor while stale at all three processTurn sites (context
  transform, acp_status, /acp panel; the panel's sessionTokens number too)
- mirrors pi's own post-compaction check: "usage source must be
  post-compaction" (agent-session.js)
- fixes the floor comment in src/index.ts that claimed "can't cause a
  false emergency" (not true for usage-less providers' tree-sum fallback —
  now documented as the accepted omp ranxianglei#18 trade-off)
- docs: token-calibration-plan.md banner marks the density system removed
  in ranxianglei#258 and records the current design + accepted trade-offs
- tests: 8 unit cases + extension-level regression (97% usage anchor
  predating a successful compress -> no emergency nudge); 422 pass
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant