mirror of
https://github.com/teamchong/pxpipe.git
synced 2026-07-22 02:02:51 +02:00
fix(render): use readable profile for dense images
This commit is contained in:
+5
-9
@@ -37,7 +37,7 @@
|
||||
*/
|
||||
|
||||
import type { ContentBlock, ImageBlock, Message, TextBlock, ToolUseBlock, ToolResultBlock } from './types.js';
|
||||
import { DENSE_CONTENT_CHARS_PER_IMAGE, renderTextToPngsWithCharLimit, shrinkColsToContent } from './render.js';
|
||||
import { DENSE_CONTENT_CHARS_PER_IMAGE, DENSE_CONTENT_COLS, DENSE_RENDER_STYLE, renderTextToPngsWithCharLimit } from './render.js';
|
||||
import { bytesToBase64 } from './png.js';
|
||||
|
||||
/** Function predicate signature for the break-even gate. Passed in by the
|
||||
@@ -341,14 +341,10 @@ export async function collapseHistory(
|
||||
return { messages, info };
|
||||
}
|
||||
// Render. No cache_control here — caller decides placement.
|
||||
// Width-shrink: history collapse always renders a single image-set of
|
||||
// collapsed conversation prose, which is typically much narrower than
|
||||
// the configured `cols` (100 default). Shrinking the canvas to the
|
||||
// longest wrapped line saves ~50% of pixel area on short collapsed
|
||||
// history blocks. The gate's `imageTokensCost()` is computed with the
|
||||
// same `shrinkColsToContent` so prediction matches reality.
|
||||
const effCols = shrinkColsToContent(text, o.cols);
|
||||
const imgs = await renderTextToPngsWithCharLimit(text, effCols, DENSE_CONTENT_CHARS_PER_IMAGE);
|
||||
// Dense history is user-visible context, not the static system-slab cache
|
||||
// anchor. Render it with the readable dense profile instead of the 313-col
|
||||
// full-canvas profile; otherwise lockfiles/code/config collapse into pixel mush.
|
||||
const imgs = await renderTextToPngsWithCharLimit(text, DENSE_CONTENT_COLS, DENSE_CONTENT_CHARS_PER_IMAGE, DENSE_RENDER_STYLE);
|
||||
if (imgs.length === 0) {
|
||||
info.reason = 'render_empty';
|
||||
return { messages, info };
|
||||
|
||||
@@ -44,6 +44,8 @@ export const READABLE_CHARS_PER_IMAGE = 50000;
|
||||
* dense for OCR on lockfiles/JSON/code. Keep those blocks paged into smaller
|
||||
* images so the model can read them reliably. */
|
||||
export const DENSE_CONTENT_CHARS_PER_IMAGE = 6000;
|
||||
export const DENSE_CONTENT_COLS = 180;
|
||||
export const DENSE_RENDER_STYLE: RenderStyle = { cellWBonus: 2, cellHBonus: 2, aa: true };
|
||||
/** Default columns per row. 1568 px / 5 px-per-cell = 313 cells. We render
|
||||
* at the full canvas width by default — no shrink-to-content. */
|
||||
const DEFAULT_COLS = 313;
|
||||
|
||||
@@ -35,6 +35,8 @@ import {
|
||||
CELL_H,
|
||||
READABLE_CHARS_PER_IMAGE,
|
||||
DENSE_CONTENT_CHARS_PER_IMAGE,
|
||||
DENSE_CONTENT_COLS,
|
||||
DENSE_RENDER_STYLE,
|
||||
renderTextToPngsWithCharLimit,
|
||||
} from './render.js';
|
||||
import { bytesToBase64 } from './png.js';
|
||||
@@ -1764,7 +1766,7 @@ async function textToImageBlocks(
|
||||
const imgs =
|
||||
effectiveNumCols > 1
|
||||
? await renderTextToPngsMultiCol(text, effectiveCols, effectiveNumCols)
|
||||
: await renderTextToPngsWithCharLimit(text, effectiveCols, DENSE_CONTENT_CHARS_PER_IMAGE);
|
||||
: await renderTextToPngsWithCharLimit(text, DENSE_CONTENT_COLS, DENSE_CONTENT_CHARS_PER_IMAGE, DENSE_RENDER_STYLE);
|
||||
let droppedChars = 0;
|
||||
let pixels = 0;
|
||||
const droppedCodepoints = new Map<number, number>();
|
||||
|
||||
+25
-1
@@ -24,7 +24,12 @@ import {
|
||||
} from '../src/core/transform.js';
|
||||
import { toTrackEvent } from '../src/core/tracker.js';
|
||||
import type { ProxyEvent } from '../src/core/proxy.js';
|
||||
import { DENSE_CONTENT_CHARS_PER_IMAGE } from '../src/core/render.js';
|
||||
import {
|
||||
DENSE_CONTENT_CHARS_PER_IMAGE,
|
||||
DENSE_CONTENT_COLS,
|
||||
DENSE_RENDER_STYLE,
|
||||
renderTextToPngsWithCharLimit,
|
||||
} from '../src/core/render.js';
|
||||
|
||||
// Default render config: cols=100, 195 lines/img → ~19,500 chars/img if
|
||||
// lines fully fill the width. For shorter lines, the budget is dominated
|
||||
@@ -70,6 +75,25 @@ describe('estimateImageCount', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('dense readable render profile', () => {
|
||||
it('uses larger glyph cells and multiple readable pages for lockfile-shaped text', async () => {
|
||||
const lockish = Array.from({ length: 200 }, (_, i) =>
|
||||
` pkg-${i}@npm:1.${i}.0(peer@npm:^${i}.0.0)(typescript@npm:^5.${i % 10}.0): checksum=${'a'.repeat(24)}`,
|
||||
).join('\n');
|
||||
|
||||
const imgs = await renderTextToPngsWithCharLimit(
|
||||
lockish,
|
||||
DENSE_CONTENT_COLS,
|
||||
DENSE_CONTENT_CHARS_PER_IMAGE,
|
||||
DENSE_RENDER_STYLE,
|
||||
);
|
||||
|
||||
expect(imgs.length).toBeGreaterThanOrEqual(3);
|
||||
expect(imgs[0]!.width).toBeGreaterThan(1000);
|
||||
expect(imgs[0]!.width).toBeLessThanOrEqual(1568);
|
||||
});
|
||||
});
|
||||
|
||||
describe('classifyContent', () => {
|
||||
it('flags JSON objects as structured', () => {
|
||||
const json = JSON.stringify({ foo: 'bar', baz: [1, 2, 3] }, null, 2);
|
||||
|
||||
Reference in New Issue
Block a user