@xamukavila/pxpipe 0.8.0 → 0.9.0

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/README.md CHANGED
@@ -16,7 +16,7 @@ measured per-request against a free `count_tokens` counterfactual in
16
16
 
17
17
  This is what the model sees instead of text:
18
18
 
19
- ![example: a real `transformRequest` output: system prompt + tool docs reflowed into one dense 1573×1248 page, instruction banner on top, ↵ marking original newlines](https://raw.githubusercontent.com/teamchong/pxpipe/main/docs/assets/example-render.png)
19
+ ![example: a real `transformRequest` output: system prompt + tool docs reflowed into one dense 1573×1248 page, instruction banner on top, ↵ marking original newlines](https://raw.githubusercontent.com/XamuAvila/pxpipe/main/docs/assets/example-render.png)
20
20
 
21
21
  *~48k chars of system prompt + tool docs: ≈25k tokens as text, ≈2.7k image
22
22
  tokens as this page. Real pipeline output; the model reads renders like this
@@ -45,7 +45,7 @@ rate is why Opus is opt-in.
45
45
  ## Try it (30 seconds)
46
46
 
47
47
  ```bash
48
- npx pxpipe-proxy # proxy on 127.0.0.1:47821
48
+ npx @xamukavila/pxpipe # proxy on 127.0.0.1:47821
49
49
  ANTHROPIC_BASE_URL=http://127.0.0.1:47821 claude # point Claude Code at it
50
50
  ```
51
51
 
@@ -74,8 +74,8 @@ are imaged.
74
74
  loses money on sparse prose (~3.5 chars/token); a profitability gate
75
75
  (calibrated on N=391 production rows) images only where the math wins.
76
76
  - **Model scope:** default `PXPIPE_MODELS=claude-fable-5,gpt-5.6`. Opus
77
- 4.7/4.8 misread ~7% of renders and GPT 5.5 degrades on imaged context, so
78
- both are opt-in via `PXPIPE_MODELS` or the dashboard chips.
77
+ 4.6/4.7/4.8 misread ~7% of renders and GPT 5.5 degrades on imaged context, so
78
+ all are opt-in via `PXPIPE_MODELS` or the dashboard chips.
79
79
  `PXPIPE_MODELS=off` disables imaging. Everything else passes through
80
80
  byte-identical. On the GPT path, tool definitions stay native JSON and no
81
81
  Anthropic `cache_control` markers are used.
@@ -127,7 +127,7 @@ bench below shows it is cheaper and cache-stable, **not** that recall holds.
127
127
  | Library | `transformAnthropicMessages({ …, caveman: true })` | boolean, default `false` |
128
128
 
129
129
  ```bash
130
- PXPIPE_CAVEMAN=1 npx pxpipe-proxy # prose compression ON (experiment)
130
+ PXPIPE_CAVEMAN=1 npx @xamukavila/pxpipe # prose compression ON (experiment)
131
131
  ```
132
132
 
133
133
  ⚠️ Flipping the flag changes the rendered image bytes, which **busts warm image
@@ -172,6 +172,29 @@ PXPIPE_CAVEMAN=1 bash bench/run.sh --model 'claude-opus-4-6[1m]' --label caveman
172
172
  node bench/score.mjs bench/runs/<off-dir> bench/runs/<caveman-dir>
173
173
  ```
174
174
 
175
+ ### Does it hurt recall?
176
+
177
+ A recall A/B (`eval/caveman-slab/`, pre-registered) put seeded facts into an
178
+ imaged system-prompt slab and compared **plain image vs caveman image** at
179
+ production density, fable-5, N=50 answerable + 10 unanswerable per arm:
180
+
181
+ | arm | answerable correct | confabulated (never-stated facts) |
182
+ |---|---:|---:|
183
+ | plain image | 31/50 (62%) | 3/10 |
184
+ | caveman image | 32/50 (64%) | 0/10 |
185
+
186
+ Tied within noise across every fact type (decision, numeric, path, name,
187
+ negation); caveman confabulated *less*. **caveman does not measurably hurt
188
+ recall vs plain imaging** — and the caveman-rendered slabs cost **−6.9% image
189
+ tokens** (10,751 → 10,004 across the 10 slabs), so the saving is free of recall
190
+ cost. Two caveats keep this from being a default-on green light: both arms hit a
191
+ ~63% **floor** (the single dense page is hard to read — plain fails the same
192
+ way, so the floor is the render, not caveman), and the eval deliberately omits
193
+ the production "fact sheet" that keeps exact identifiers as text
194
+ (`transform.ts:1627`), so the numeric/path misses it counts would not occur in
195
+ production. Full design, results, and follow-ups:
196
+ [`eval/caveman-slab/DESIGN.md`](eval/caveman-slab/DESIGN.md).
197
+
175
198
  ## How it works
176
199
 
177
200
  ```
@@ -188,7 +211,7 @@ sparse prose stays text. Events log to `~/.pxpipe/events.jsonl`.
188
211
  ## Library use (no proxy)
189
212
 
190
213
  ```ts
191
- import { renderTextToImages, transformAnthropicMessages } from "pxpipe-proxy";
214
+ import { renderTextToImages, transformAnthropicMessages } from "@xamukavila/pxpipe";
192
215
 
193
216
  const { pages } = await renderTextToImages(toolResultText); // pages[i].png: Uint8Array
194
217
  const { body, applied, info } = await transformAnthropicMessages({
@@ -245,10 +268,10 @@ Three kinds of *input* blocks, each behind a profitability gate:
245
268
  Everything else passes through byte-identical: your messages, recent turns,
246
269
  the model's output (it is the response, the proxy never touches it), sparse
247
270
  prose, and anything too small to win. Models outside the allowlist pass
248
- through entirely — the default scope is Fable 5 and GPT 5.6 only. Opus 4.8
249
- and GPT 5.5 read imaged content measurably worse (FINDINGS.md 2026-06-16),
250
- so they are deliberately opt-in via the dashboard or `PXPIPE_MODELS`, never
251
- silently imaged.
271
+ through entirely — the default scope is Fable 5 and GPT 5.6 only. Opus
272
+ 4.6/4.7/4.8 and GPT 5.5 read imaged content measurably worse (FINDINGS.md
273
+ 2026-06-16), so they are deliberately opt-in via the dashboard or
274
+ `PXPIPE_MODELS`, never silently imaged.
252
275
 
253
276
  **Has it ever failed for real, outside the benchmarks?**
254
277
  Yes, once in weeks of daily use: the model recalled a person's name from
@@ -7,11 +7,11 @@ function baseModelId(model) {
7
7
  /** Dashboard runtime override; null = fall back to PXPIPE_MODELS env / built-in default. In-memory only. */
8
8
  let runtimeModelBases = null;
9
9
  /** Built-in default scope when PXPIPE_MODELS is unset: Fable 5 (Claude) plus
10
- * GPT 5.6. GPT 5.5 and Opus 4.8 are intentionally off — same pipeline but
10
+ * GPT 5.6. GPT 5.5 and Opus 4.6/4.7/4.8 are intentionally off — same pipeline but
11
11
  * measurably worse at reading imaged content (FINDINGS.md 2026-06-16: Opus 4.8
12
12
  * ~2pp arithmetic, 6/15 dense-hex recall vs Fable's 100/100; GPT 5.5 likewise
13
13
  * degrades on imaged history/context) — so silently imaging them is the wrong
14
- * default. Both stay opt-in via the dashboard chips or PXPIPE_MODELS. */
14
+ * default. All stay opt-in via the dashboard chips or PXPIPE_MODELS. */
15
15
  const DEFAULT_MODEL_BASES = ['claude-fable-5', 'gpt-5.6'];
16
16
  function falsey(v) {
17
17
  return /^(0|false|no|off|none)$/i.test(v.trim());
@@ -8,7 +8,7 @@
8
8
  */
9
9
  import { DENSE_CONTENT_CHARS_PER_IMAGE, DENSE_CONTENT_COLS, MAX_HEIGHT_PX, PAD_X, CELL_W, } from './render.js';
10
10
  // Dogfood the public SDK: render via the same `./transform` entry external
11
- // consumers import (pxpipe-proxy/transform → renderTextToImages), not the
11
+ // consumers import (@xamukavila/pxpipe/transform → renderTextToImages), not the
12
12
  // internal leaf renderer.
13
13
  import { renderTextToImages } from './library.js';
14
14
  import { estimateImageCount, ANTHROPIC_PIXELS_PER_TOKEN, IMAGE_COST_SAFETY_MARGIN, REPORT_CHARS_PER_TOKEN } from './transform.js';
@@ -324,7 +324,7 @@ export async function runExportCore(sourceText, opts) {
324
324
  // Render to PNG pages via the public SDK primitive. shrink=true sizes the canvas
325
325
  // to the widest line so short-line code isn't padded to full width; multiCol='auto'
326
326
  // packs as many columns side-by-side as fit. Same render surface shipped to external
327
- // SDK consumers (pxpipe-proxy/transform).
327
+ // SDK consumers (@xamukavila/pxpipe/transform).
328
328
  const { pages: images } = await renderTextToImages(sourceText, {
329
329
  cols: opts.cols,
330
330
  shrink: true,
@@ -60,6 +60,7 @@ const MODEL_CATALOG = [
60
60
  { id: 'claude-fable-5', label: 'Fable 5' },
61
61
  { id: 'claude-opus-4-8', label: 'Opus 4.8' },
62
62
  { id: 'claude-opus-4-7', label: 'Opus 4.7' },
63
+ { id: 'claude-opus-4-6', label: 'Opus 4.6' },
63
64
  { id: 'claude-sonnet-5', label: 'Sonnet 5' },
64
65
  { id: 'claude-sonnet-4-6', label: 'Sonnet 4.6' },
65
66
  ];
package/dist/node.js CHANGED
@@ -6749,6 +6749,7 @@ var MODEL_CATALOG = [
6749
6749
  { id: "claude-fable-5", label: "Fable 5" },
6750
6750
  { id: "claude-opus-4-8", label: "Opus 4.8" },
6751
6751
  { id: "claude-opus-4-7", label: "Opus 4.7" },
6752
+ { id: "claude-opus-4-6", label: "Opus 4.6" },
6752
6753
  { id: "claude-sonnet-5", label: "Sonnet 5" },
6753
6754
  { id: "claude-sonnet-4-6", label: "Sonnet 4.6" }
6754
6755
  ];
@@ -8349,7 +8350,7 @@ Use with OpenAI-compatible GPT clients:
8349
8350
  `);
8350
8351
  }
8351
8352
  function printVersion() {
8352
- const injected = true ? "0.8.0" : void 0;
8353
+ const injected = true ? "0.9.0" : void 0;
8353
8354
  console.log(injected ?? process.env.npm_package_version ?? "unknown");
8354
8355
  }
8355
8356
  function toWebRequest(req) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xamukavila/pxpipe",
3
- "version": "0.8.0",
3
+ "version": "0.9.0",
4
4
  "description": "Token-saving proxy for Claude Code: renders bulky context (system prompt, tool docs, old history) as dense PNGs to cut input tokens. Runs on Node and Cloudflare Workers.",
5
5
  "type": "module",
6
6
  "bin": {