@linxiraos/zeta-compact 0.0.0-stage → 1.4.12
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/CHANGELOG.md +115 -0
- package/LICENSE +22 -0
- package/README.md +73 -2
- package/THIRD-PARTY-NOTICES.txt +23064 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/snapcompact.d.ts +731 -0
- package/package.json +68 -5
- package/src/index.ts +1 -0
- package/src/prompts/file-operations.md +5 -0
- package/src/prompts/snapcompact-summary.md +27 -0
- package/src/snapcompact.d.ts +731 -0
- package/src/snapcompact.ts +2656 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
## [Unreleased]
|
|
2
|
+
|
|
3
|
+
## [1.4.12] - 2026-11-08
|
|
4
|
+
|
|
5
|
+
- Synced with upstream OMP v18.18.0.
|
|
6
|
+
- Released as part of Zeta 1.4.12; no package-specific user-visible changes.
|
|
7
|
+
|
|
8
|
+
## [1.4.11] - 2026-11-06
|
|
9
|
+
|
|
10
|
+
- Released as part of Zeta 1.4.11; no package-specific user-visible changes.
|
|
11
|
+
|
|
12
|
+
## [1.4.10] - 2026-11-05
|
|
13
|
+
|
|
14
|
+
- Released as part of Zeta 1.4.10; no package-specific user-visible changes.
|
|
15
|
+
|
|
16
|
+
## [1.4.9] - 2026-11-03
|
|
17
|
+
|
|
18
|
+
- Synced with upstream OMP v18.18.0.
|
|
19
|
+
|
|
20
|
+
## [1.4.7] - 2026-10-30
|
|
21
|
+
|
|
22
|
+
- Synced with upstream OMP v18.18.0.
|
|
23
|
+
|
|
24
|
+
## [1.4.5] - 2026-10-28
|
|
25
|
+
|
|
26
|
+
- Synced with upstream OMP v18.18.0.
|
|
27
|
+
|
|
28
|
+
## [1.4.4] - 2026-10-26
|
|
29
|
+
|
|
30
|
+
- Released as part of Zeta 1.4.4; no package-specific user-visible changes.
|
|
31
|
+
|
|
32
|
+
## [1.4.3] - 2026-10-25
|
|
33
|
+
|
|
34
|
+
- Released as part of Zeta 1.4.3; no package-specific user-visible changes.
|
|
35
|
+
|
|
36
|
+
## [1.4.2] - 2026-10-24
|
|
37
|
+
|
|
38
|
+
- Version alignment with the 1.4.2 release line (no behavioral changes).
|
|
39
|
+
|
|
40
|
+
## [1.4.1] - 2026-10-23
|
|
41
|
+
|
|
42
|
+
- Version alignment with the 1.4.1 release line (no behavioral changes).
|
|
43
|
+
|
|
44
|
+
## [1.4.0] - 2026-10-21
|
|
45
|
+
|
|
46
|
+
- Version line moves to 1.4.0 with the rest of the suite; no user-visible change in this package.
|
|
47
|
+
|
|
48
|
+
## [1.3.2] - 2026-10-19
|
|
49
|
+
|
|
50
|
+
- Version line moves to 1.3.2 with the rest of the suite; no user-visible change in this package.
|
|
51
|
+
|
|
52
|
+
## [1.3.1] - 2026-10-19
|
|
53
|
+
|
|
54
|
+
- 版本线推进至 1.3.1;本版无独立用户可见变化。
|
|
55
|
+
|
|
56
|
+
## [1.3.0] - 2026-10-18
|
|
57
|
+
|
|
58
|
+
### Breaking Changes
|
|
59
|
+
|
|
60
|
+
- `providerImageBudget(provider)` and `providerFrameBudget(provider)` became `providerImageBudget(model)` and `providerFrameBudget(model)`, and `maxFramesForDataBudget(shape)` became `maxFramesForDataBudget(shape, budget)` with a required byte budget ([#15434](https://github.com/can1357/oh-my-pi/pull/15434) by [@will-bogusz](https://github.com/will-bogusz))
|
|
61
|
+
- Removed `PROVIDER_IMAGE_BUDGETS` and `FRAME_DATA_BYTES_BUDGET`: image counts come from the catalog's `image-count-budget` rules, and frame byte budgets from `frameDataBytesBudget(model)` (`DEFAULT_FRAME_DATA_BYTES_BUDGET` where the host has none) ([#15434](https://github.com/can1357/oh-my-pi/pull/15434) by [@will-bogusz](https://github.com/will-bogusz))
|
|
62
|
+
|
|
63
|
+
### Added
|
|
64
|
+
|
|
65
|
+
- Added `plannedFrameTokens` and `Shape.frameTokensVerified`: archive sizing charges a frame its own price when the reader's `image-tokenization` rule is `verified`, and at least `FRAME_TOKEN_ESTIMATE` otherwise ([#15442](https://github.com/can1357/oh-my-pi/pull/15442) by [@will-bogusz](https://github.com/will-bogusz))
|
|
66
|
+
- Added `viewWithoutThinking()`, `textWithoutThinking()`, `readerIncludesThinking()` and an optional `Archive.withoutThinking` variant, so an archive rendered with reasoning can be read by a model that must not see it; without a stored variant the view keeps only reasoning-free text and no frames ([#15436](https://github.com/can1357/oh-my-pi/pull/15436) by [@will-bogusz](https://github.com/will-bogusz))
|
|
67
|
+
|
|
68
|
+
### Fixed
|
|
69
|
+
|
|
70
|
+
- Fixed snapcompact frames for Claude and GPT on Cursor, including its `default` (Auto) route, being drawn at 1568–1932px, which Cursor shrank to 1024px before the model read them; frames now render at the host's catalog `image-max-edge` ([#15448](https://github.com/can1357/oh-my-pi/pull/15448) by [@will-bogusz](https://github.com/will-bogusz))
|
|
71
|
+
- Fixed re-rendering an archive without reasoning keeping every paragraph after the first of a multi-paragraph `¶think:` section ([#15436](https://github.com/can1357/oh-my-pi/pull/15436) by [@will-bogusz](https://github.com/will-bogusz))
|
|
72
|
+
|
|
73
|
+
## [1.2.0] - 2026-10-12
|
|
74
|
+
|
|
75
|
+
- 版本线推进至 1.1.28;本版无独立用户可见变化。
|
|
76
|
+
|
|
77
|
+
## [1.1.27] - 2026-10-07
|
|
78
|
+
|
|
79
|
+
- 版本线推进至 1.1.27;本版无独立用户可见变化。
|
|
80
|
+
|
|
81
|
+
### Breaking Changes
|
|
82
|
+
|
|
83
|
+
- `maxFramesForDataBudget()` now takes the frame shape instead of a byte budget, so the default 1568px shapes get 26 frames instead of 17 ([#14277](https://github.com/can1357/oh-my-pi/pull/14277) by [@will-bogusz](https://github.com/will-bogusz)).
|
|
84
|
+
|
|
85
|
+
### Added
|
|
86
|
+
|
|
87
|
+
- Added `frameBilling`, `frameTokens` and `frameBillingKey`, which price a rendered frame at what the model reading it is billed ([#14291](https://github.com/can1357/oh-my-pi/pull/14291) by [@will-bogusz](https://github.com/will-bogusz))
|
|
88
|
+
|
|
89
|
+
### Fixed
|
|
90
|
+
|
|
91
|
+
- Fixed snapcompact frame token estimates following the gateway instead of the model reading the frames, which mispriced Claude behind OpenRouter or Vertex and Claude 4.6 and older ([#14286](https://github.com/can1357/oh-my-pi/pull/14286) by [@will-bogusz](https://github.com/will-bogusz)).
|
|
92
|
+
|
|
93
|
+
## [1.1.25] - 2026-10-03
|
|
94
|
+
|
|
95
|
+
- 版本线推进至 1.1.25;本版无独立用户可见变化。
|
|
96
|
+
|
|
97
|
+
## [1.1.24] - 2026-10-03
|
|
98
|
+
|
|
99
|
+
- 上游 v18.4.11 集成;本轮无用户可见变更。
|
|
100
|
+
|
|
101
|
+
## [1.1.22] - 2026-09-30
|
|
102
|
+
|
|
103
|
+
- 随 1.1.22 版本线发布;无面向用户的行为变化。
|
|
104
|
+
|
|
105
|
+
## [1.1.19] - 2026-09-22
|
|
106
|
+
|
|
107
|
+
- 版本线推进;本版无独立用户可见变化。
|
|
108
|
+
|
|
109
|
+
## [1.1.18] - 2026-09-22
|
|
110
|
+
|
|
111
|
+
- 包元数据:author/maintainer 更新为 Linxira-OS,LICENSE 追加 Linxira-OS 版权行(发行面变更)。
|
|
112
|
+
|
|
113
|
+
## [1.1.16] - 2026-09-19
|
|
114
|
+
|
|
115
|
+
- 上游 v18.2.5 维护同步。
|
package/LICENSE
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025-2026 Can Bölük
|
|
4
|
+
Copyright (c) 2026 Stencil Labs, Inc.
|
|
5
|
+
|
|
6
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
8
|
+
in the Software without restriction, including without limitation the rights
|
|
9
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
10
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
11
|
+
furnished to do so, subject to the following conditions:
|
|
12
|
+
|
|
13
|
+
The above copyright notice and this permission notice shall be included in all
|
|
14
|
+
copies or substantial portions of the Software.
|
|
15
|
+
|
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
17
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
18
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
19
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
20
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
21
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
22
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,74 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @linxiraos/zeta-compact
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Bitmap-frame context compression for vision-capable LLMs.
|
|
4
|
+
|
|
5
|
+
Instead of asking an LLM to summarize discarded conversation history, snapcompact serializes it and renders the text into dense PNG frames of pixel-font glyphs that vision models read back directly. The whole pass is local and deterministic — no LLM call, no API key, no latency beyond rendering. Rasterization and PNG encoding happen in native code (`@linxiraos/pi-natives`).
|
|
6
|
+
|
|
7
|
+
Built for [omp](https://github.com/can1357/oh-my-pi)'s compaction pipeline, but the rendering API works on arbitrary text.
|
|
8
|
+
|
|
9
|
+
## How it works
|
|
10
|
+
|
|
11
|
+
1. Discarded history is serialized to compact text (`serializeConversation`), with per-tool-result and per-argument character caps.
|
|
12
|
+
2. Text is normalized for the selected native font (`normalize`): ANSI sequences stripped, whitespace collapsed, newline runs folded into a single full-block glyph, box drawing and compatibility symbols folded to ASCII, semantic emoji folded to ASCII labels, decorative emoji dropped, and non-Latin glyphs preserved when either the selected font or the embedded Silver fallback can render them.
|
|
13
|
+
3. Pages of text are rasterized into PNG frames (`render` / `renderMany`). Frame width is fixed per shape; height hugs the rows actually printed, with a 64px minimum so short final frames remain valid for vision processors.
|
|
14
|
+
4. Frames persist in the compaction entry's `preserveData` and are re-attached to the summary message on every context rebuild.
|
|
15
|
+
|
|
16
|
+
Frame shapes are provider-aware, chosen by SQuAD recall evals (see `research/`) against real provider billing:
|
|
17
|
+
|
|
18
|
+
| Reader | Default shape | Notes |
|
|
19
|
+
| --------- | ---------------- | --------------------------------------------------------------------------------------------------------- |
|
|
20
|
+
| Anthropic | `11on16-bw` | X.org 8x13 glyphs on an 11px advance; high-res Claude lines get 1932px frames |
|
|
21
|
+
| Google | `8on22-bw` @2048 | X.org 8x13 glyphs on a 22px pitch; Gemini bills a fixed per-image budget, so larger frames are free chars |
|
|
22
|
+
| OpenAI | `8on22-bw` | X.org 8x13 glyphs on a 22px pitch, sent at `detail: "original"` |
|
|
23
|
+
| Unknown | Anthropic shape | Per-provider image-count budgets guard against gateways that silently drop frames |
|
|
24
|
+
|
|
25
|
+
`resolveShape({ api, id })` matches the model id, not just the wire API — a Claude routed through Vertex or OpenRouter keeps its Claude shape. Frames are priced by the reading model's lineage: its catalog `image-tokenization` rule (so that Claude is billed as Claude, and Opus 4.6 under the standard 1,568-token tier), falling back to the catalog rule for the wire API carrying the request when the lineage has none. A reader with neither costs `FRAME_TOKEN_ESTIMATE` per frame. Archive sizing (`plannedFrameTokens`) charges each frame its own price when the rule is `verified` against provider billing, and at least `FRAME_TOKEN_ESTIMATE` otherwise.
|
|
26
|
+
|
|
27
|
+
Bitmap shapes keep their provider-tuned geometry and draw missing glyphs through the embedded Silver TrueType fallback one character at a time; East Asian (CJK/Kana/Hangul) glyphs render full-width across two cells so they stay legible in the narrow ASCII grid. Selecting `silver16-bw` uses Silver for the whole frame.
|
|
28
|
+
|
|
29
|
+
A host that downscales images before the model reads them (catalog `image-max-edge`; Cursor fits Claude and GPT images into 1024×1024) gets frames rendered at that edge, forced variants included, so the glyphs reach the model at the size they were drawn.
|
|
30
|
+
|
|
31
|
+
## Install
|
|
32
|
+
|
|
33
|
+
```sh
|
|
34
|
+
bun add @linxiraos/zeta-compact
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Ships TypeScript source directly (no build step); requires Bun ≥ 1.4.4.
|
|
38
|
+
|
|
39
|
+
## Usage
|
|
40
|
+
|
|
41
|
+
Render arbitrary text into LLM image blocks:
|
|
42
|
+
|
|
43
|
+
```ts
|
|
44
|
+
import { renderMany, frames, resolveShape } from "@linxiraos/zeta-compact";
|
|
45
|
+
|
|
46
|
+
const images = renderMany(longText, { model }); // ImageContent[], first page first
|
|
47
|
+
const count = frames(longText, { model }); // frame count without rendering
|
|
48
|
+
const shape = resolveShape(model); // eval-optimal Shape for the reader
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Run a full compaction pass over prepared messages:
|
|
52
|
+
|
|
53
|
+
```ts
|
|
54
|
+
import { compact } from "@linxiraos/zeta-compact";
|
|
55
|
+
|
|
56
|
+
const result = await compact(preparation, { model });
|
|
57
|
+
// result.summary — short "resume prior conversation" lead-in, reading guide, and FILES section
|
|
58
|
+
// result.preserveData — bounded archive source + rendered image middle
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## API surface
|
|
62
|
+
|
|
63
|
+
- **Compaction**: `compact`, `CompactionPreparation`, `CompactionResult`, `getPreservedArchive`, `images`, `historyBlocks`, `capFrameDataBytes`
|
|
64
|
+
- **Rendering**: `render`, `renderMany`, `frames`, `geometry`
|
|
65
|
+
- **Shapes**: `SHAPES`, `SHAPE_VARIANTS`, `resolveShape`, `resolveShapeForText`, `idealShapeVariant`, `isShape`, `isShapeVariantName`
|
|
66
|
+
- **Text**: `serializeConversation`, `normalize`, `scanRenderability`, `renderabilityProbeText`, `dimStopwords`, `wrap`
|
|
67
|
+
- **Budgets**: `providerImageBudget`, `frameDataBytesBudget`, `MAX_FRAMES_DEFAULT`, `FRAME_TOKEN_ESTIMATE`, `frameBilling`, `frameTokens`, `frameBillingKey`, `plannedFrameTokens`, `HQ_EDGE_FRAMES`
|
|
68
|
+
- **File ops**: `createFileOps`, `computeFileLists`, `upsertFileOperations`
|
|
69
|
+
|
|
70
|
+
## References
|
|
71
|
+
|
|
72
|
+
- [Monorepo README](https://github.com/Linxira-OS/linxira-zeta#readme)
|
|
73
|
+
- [Compaction architecture](../../docs/compaction.md)
|
|
74
|
+
- [CHANGELOG](./CHANGELOG.md)
|