Skip to content

feat: pi file-free injection (#535 phase 1) - #536

Merged
ranxianglei merged 2 commits into
masterfrom
2026-09-04_535-pi-file-free
Sep 5, 2026
Merged

ranxianglei merged 2 commits into
masterfrom
2026-09-04_535-pi-file-free

Conversation

@ranxianglei

Copy link
Copy Markdown
Owner

#535 phase 1 (pi). Closes nothing yet — the issue tracks all four phases.

What changes

bili pi no longer creates the ~/.pi/agent-bili overlay and no longer sets PI_CODING_AGENT_DIR. pi always runs on its real home; every in-session write (settings edits, models-store.json, run-history.jsonl, auth.json, sessions/) lands in the real home, so nothing is ever silently lost (#531 root fix for pi).

Injection becomes file-free:

  • Provider URL rewrites — the launcher passes BILI_PROVIDER_REWRITES (JSON {providerKey: wrapUpstream(...)} for http upstreams) through the child env; the bili pi extension consumes it at load and calls pi.registerProvider(key, { baseUrl }) (queued at extension load, applied before any model traffic). HTTPS upstreams keep their real baseUrls and ride HTTPS_PROXY cert-MITM as before.
  • Native compaction off — replaced the generated settings.json (compaction.enabled=false) with an in-extension session_before_compact handler returning {cancel:true} only for reason==="threshold"||"overflow" (manual /compact stays user-owned — exact parity with the old setting). Armed only when BILLION_CONTEXT_PROXY is present, so a plain pi with the plugin installed stays fully native. omp is untouched: its event has no reason field yet (upstream PR pending).

Safety

  • Refuses to launch (before spawning anything) when http rewrites are needed but the extension cannot load (dist/agent/pi.js missing and plugin not installed) — without this the rewrites would silently vanish and traffic would go direct.
  • A stale inherited PI_CODING_AGENT_DIR (e.g. launching from inside a legacy overlay shell) is stripped from the child env and ignored for discovery + plugin detection.
  • Old overlays are left in place untouched — no merge-back, no deletion (per 注入零文件化:废除 overlay/临时目录机制(#531 设计返工) #535).

Verification

  • npm run typecheck clean; npm test 1041/1043 (the 2 known env-dependent fails in plugin-agent.test.ts, fail only when the runner itself sits behind a live BILLION_CONTEXT_PROXY); npm run build ok.
  • New tests: buildPiEnv manifest (3), plugin registerProvider from env (3), session_before_compact cancel semantics (2), launcher refusal + no-overlay-dir (1).
  • E2E on this machine: node dist/index.js pi -- --model vllm/glm-5.3 -p '...' → proxy log shows forward POST → …:8199/v1/chat/completions through the /bili/ route; ~/.pi/agent-bili and real home untouched (mtime check); child env carries the manifest and no PI_CODING_AGENT_DIR.

…es + extension compaction cancel, overlay/PI_CODING_AGENT_DIR removed for pi
@github-actions

github-actions Bot commented Sep 4, 2026 •

Copy link
Copy Markdown
Contributor

📦 Built Package Artifact

Branch: 2026-09-04_535-pi-file-free (f93d5ca)

Option A — Install from npm PR tag (recommended)

npm install -g billion-context@pr-536

Each push to this PR publishes a new version under the pr-536 npm tag.

Option B — Download artifact

  1. Download the artifact from the Actions run
  2. Extract the tarball and install:
tar xzf billion-context-pr536.tgz
npm install -g package

This comment is automatically updated on each push.

@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 ework agent · qwen3.8-27b

[bot] 🏷 Reviewing #536 now — checking out the branch (03f7753 on v0.1.84), auditing the diff against the #535 design, and running typecheck/test/build locally. Will follow up with findings; initial read: the shape matches the agreed zero-file design (env manifest → registerProvider, compaction cancel gated on BILLION_CONTEXT_PROXY + reason), and I'm specifically poking at edge cases (stale installed plugin, stale PI_CODING_AGENT_DIR in the standalone discover path, https-wrapped baseUrls in real models.json).

@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 ework agent · qwen3.8-27b

[bot] 🏷 Review of #536 (pi file-free injection, #535 phase 1) — verified locally on 03f7753.

Verification (this machine)

  • npm run typecheck ✅ clean · npm run build ✅ · npm test 1042/1043 — the single fail is resolveClientCommand: codex/claude resolve to themselves, env-dependent (a /usr/bin/codex exists on PATH here so resolution returns the absolute path); unrelated to this diff. Your 2 known BILLION_CONTEXT_PROXY-dependent fails didn't reproduce here.
  • New tests all pass, including the refusal-before-spawn assertion (clientArgsSeen.length === 0 — no proxy child leaked, since the check sits above ensureProxyRunning at launcher.ts:1923 vs :1938).

Conformance to the #535 design — all good

  • Env manifest → registerProvider at load (src/agent/pi.ts:246-255), applied before round 1; per-key try/catch degrades loudly ("traffic for this provider goes direct").
  • session_before_compact cancel gated on agent === "pi" and BILLION_CONTEXT_PROXY (src/agent/pi.ts:264-270); cancels only threshold/overflow, manual /compact untouched — exact parity with the old compaction.enabled=false semantics for auto-compaction; omp correctly not armed (no reason field upstream yet).
  • Stale PI_CODING_AGENT_DIR: stripped from child env (:1991), ignored for discovery (discoveryEnv :1913) and plugin detection (piRealHome :1920). I checked there is no standalone discover CLI path left exposed — src/discover.ts only runs inside the spawned proxy child, whose env is already stripped.
  • Old overlays are left in place (nothing deletes/merges them) ✅; omp/opencode/codex/claude branches byte-identical apart from the comment touch ✅.
  • parseProviderRewrites handles bad JSON / non-object / non-http(s) values safely, all covered by tests.

⚠️ One regression I'd like fixed before merge: httpsRewrites is dropped for pi

The old preparePiHttpRewrite (pre-PR, fadfcdd) handled both lists: http upstreams got wrapped to /bili/, and providers whose models.json baseUrl was already /bili/<https>-wrapped (README Option 2 manual setup) were unwrapped to the raw https URL (p.baseUrl = r.realUpstream) so HTTPS_PROXY cert-MITM could intercept them.

The new pi path only consumes routes.httpRewrites (launcher.ts:1987) — routes.httpsRewrites is computed (and even feeds the MITM whitelist via httpsDomains) but never applied client-side. Every other client branch consumes both lists (omp :2006, opencode :2026, codex :2105, claude :2122); pi is now the odd one out.

Impact: a pi user whose real models.json carries a hand-wrapped <origin>/bili/https://… baseUrl upgrades and runs bili pi → pi keeps pointing at the embedded origin over plain HTTP. Since the launcher always spawns a fresh instance on a new port, that origin is stale → connection refused (or, worst case, hits whatever else now listens there). Silent, and asymmetric — the MITM side is fully prepared for the host, only the client pointer is missing.

Suggested fix (~10 lines, stays fully file-free, zero extension changes — parseProviderRewrites already accepts https values and registerProvider applies any URL generically):

  • buildPiEnv: also merge httpsRewrites into the manifest with their raw real values (manifest[r.key] = r.realUpstream, no wrapping).
  • Refusal condition at launcher.ts:1923: fire when httpRewrites.length + httpsRewrites.length > 0 (today a wrapped-https-only config gets neither manifest nor refusal — exactly the silent-direct case this PR's own safety guard exists to prevent).
  • One test mirroring the existing buildPiEnv manifest test with an https entry.

Minor (follow-up OK, not blocking)

  1. Stale installed-plugin edge: the refusal check counts "installed" via isBiliPiEntry, which matches any node_modules/billion-context path. If settings.json points at a different, older install lacking registerProvider support, the launcher skips -e and the old plugin silently ignores BILI_PROVIDER_REWRITES → http traffic direct, unnoticed. Normal flow stays coherent (install writes the current root; auto-update replaces in place), so this needs two installs with the config pointing at the older one. Cheap guard: in the extension, when BILI_PROVIDER_REWRITES is set but typeof pi.registerProvider !== "function", log one loud warning instead of skipping silently (src/agent/pi.ts:247).
  2. Nit: the reworded doc comment at src/launcher.ts:~1094 has unbalanced parens — "(line-based, indentation-tracked): HTTP → /bili/ wrap, wrapped-HTTPS → raw https for cert MITM) riding…" — the opening paren was dropped in the edit.

Verdict

Design and implementation match the agreed zero-file spec well and the safety story (refuse-before-spawn, real-home-only, plain-pi-untouched) checks out. I'd like the httpsRewrites gap closed first — it's small and it's the same class of bug the refusal guard was added to prevent. Happy to implement the fix (finding 1 + the two minors) on your branch if you want; otherwise push your own follow-up and I'll re-verify.

…iew)

buildPiEnv now takes httpsRewrites and emits RAW https values into the
BILI_PROVIDER_REWRITES manifest — a hand-wrapped `<origin>/bili/https://...`
baseUrl (README Option 2) gets repointed off the stale embedded origin onto
the cert-MITM path, matching what every other client branch already did.
The pre-spawn refusal now fires for https-only rewrites too, and the
extension warns loudly when BILI_PROVIDER_REWRITES is set but the running
pi build has no registerProvider API (stale installed plugin).
@ranxianglei

Copy link
Copy Markdown
Owner Author

Review fix pushed (f93d5ca):

  • buildPiEnv now takes httpsRewrites and merges RAW values into the BILI_PROVIDER_REWRITES manifest — a hand-wrapped <origin>/bili/https://... baseUrl (README Option 2) is repointed off the stale embedded origin onto the cert-MITM path, matching every other client branch.
  • Pre-spawn refusal now fires for https-only rewrites too (httpRewrites.length + httpsRewrites.length > 0), before any proxy child spawns.
  • Extension warns loudly when BILI_PROVIDER_REWRITES is set but the running pi build has no registerProvider API (stale installed plugin) instead of silently ignoring the manifest.
  • Doc-comment parens nit fixed.
  • Tests: https-merge manifest test + https-only refusal test. Full suite 1045/1045 (with live-proxy env unset), typecheck clean, build OK.

The stacked PR #538 was rebased onto this fix (8a86fd3) — still incremental on top of this branch.

@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 ework agent · qwen3.8-27b

[bot] 🏷 Re-verified f93d5ca — all four review points confirmed fixed. ✅

Checked the fix commit line-by-line against the review:

  1. httpsRewrites merged into manifest — buildPiEnv now takes httpsRewrites as a 5th param and emits manifest[r.key] = r.realUpstream (raw, unwrapped) while http entries stay wrapUpstream(origin, …) (src/launcher.ts:332-357). A hand-wrapped <origin>/bili/https://… baseUrl now gets repointed off the stale embedded origin onto the cert-MITM path, matching every other client branch. Call site passes both lists (:1999).
  2. Refusal widened — condition is now httpRewrites.length > 0 || httpsRewrites.length > 0, still above ensureProxyRunning, so an https-only config can no longer slip through silently direct (src/launcher.ts:1935).
  3. Stale-plugin warning — extension now logs BILI_PROVIDER_REWRITES is set but this pi build has no registerProvider API — provider traffic goes DIRECT… instead of ignoring the manifest (src/agent/pi.ts:247-252).
  4. Comment parens — "MITM) riding" → "MITM, riding" ✅.

New tests are exactly the right shape: buildPiEnv manifest deep-equal with one wrapped + one raw entry, and an https-only refusal test using a realistic Option-2 models.json (http://127.0.0.1:8787/bili/https://api.openai.com/v1) with dist/agent/pi.js removed.

Local run on f93d5ca: typecheck clean · npm test 1044/1045 · build ok. The single failure is the same env-dependent one from before — resolveClientCommand: codex/claude resolve to themselves fails only because /usr/bin/codex exists on this box (resolution returns the absolute path); unrelated to this diff. Your 1045/1045 claim holds on a machine without that binary.

LGTM — ready for merge once you say so (merge itself stays yours per house rules). Noted stacked PR #538 rebased to 8a86fd3; I haven't reviewed it separately — it should come through its own notification.

@ranxianglei
ranxianglei merged commit 1365537 into master Sep 5, 2026
6 checks passed
cskwork pushed a commit to cskwork/billion-context that referenced this pull request Oct 21, 2026
…tension API > generated files

hermes/dsh one-liners, per-client redirect table, discovery table and temp-config bullets updated in EN+ZH; injection-priority note added next to 'Two compression modes'. pi/omp doc lines intentionally left to PR ranxianglei#536.
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