@xynogen/pix-optimizer 1.0.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/LICENSE +21 -0
- package/README.md +106 -0
- package/package.json +48 -0
- package/src/caveman.test.ts +239 -0
- package/src/caveman.ts +402 -0
- package/src/index.ts +33 -0
- package/src/json.test.ts +177 -0
- package/src/json.ts +270 -0
- package/src/opt.test.ts +93 -0
- package/src/opt.ts +96 -0
- package/src/rtk.test.ts +173 -0
- package/src/rtk.ts +285 -0
- package/src/skills/toon-json/SKILL.md +101 -0
- package/src/status.test.ts +85 -0
- package/src/status.ts +102 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 xynogen
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# pix-optimizer
|
|
2
|
+
|
|
3
|
+
Token-optimization suite for Pi Coding Agent. Three tools wired into one
|
|
4
|
+
extension via `src/index.ts`, fronted by a single `/opt` command and one
|
|
5
|
+
shared status-bar cell:
|
|
6
|
+
|
|
7
|
+
- **Caveman** (`⛏`) — terse-output system prompt
|
|
8
|
+
- **RTK** (`⚔`) — prefixes shell commands with `rtk` + injects RTK prompt
|
|
9
|
+
- **TOON** (`✂`) — jq + TOON guidance for dense JSON (+ bundled skill)
|
|
10
|
+
|
|
11
|
+
## Command
|
|
12
|
+
|
|
13
|
+
One command routes to every tool:
|
|
14
|
+
|
|
15
|
+
```text
|
|
16
|
+
/opt → status + help
|
|
17
|
+
/opt caveman <level> → set caveman level (1/2/3/lite/full/ultra/micro/off/config)
|
|
18
|
+
/opt rtk [on|off] → toggle RTK rewriting
|
|
19
|
+
/opt toon [on|off] → toggle jq+TOON guidance
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Status bar
|
|
23
|
+
|
|
24
|
+
A single cell always shows all three icons in a fixed order (`⛏ ⚔ ✂`), color-
|
|
25
|
+
coded by state: **accent** when the tool is enabled, **dim** when disabled.
|
|
26
|
+
|
|
27
|
+
## Features
|
|
28
|
+
|
|
29
|
+
### Caveman Mode (`⛏`)
|
|
30
|
+
|
|
31
|
+
Cuts ~75% of output tokens while keeping full technical accuracy.
|
|
32
|
+
|
|
33
|
+
| # | Name | Description |
|
|
34
|
+
|---|-------|------------------------------|
|
|
35
|
+
| 1 | lite | Professional, no fluff |
|
|
36
|
+
| 2 | full | Classic caveman |
|
|
37
|
+
| 3 | ultra | Maximum compression |
|
|
38
|
+
| – | micro | Experimental prompt-minimized |
|
|
39
|
+
|
|
40
|
+
`/opt caveman config` opens a settings dialog. Default level for new sessions
|
|
41
|
+
and status-bar visibility are saved to `~/.pi/agent/caveman.json`.
|
|
42
|
+
|
|
43
|
+
### RTK Tool Rewriting (`⚔`)
|
|
44
|
+
|
|
45
|
+
Two layers, both active automatically:
|
|
46
|
+
|
|
47
|
+
1. **Prompt layer** — injects the RTK system prompt (tells the model to
|
|
48
|
+
prefix commands with `rtk`).
|
|
49
|
+
2. **Execute layer** — rewrites `bash` tool calls, prefixing known commands
|
|
50
|
+
(`git`, `gh`, `cargo`, `npm`, `pnpm`, `docker`, `kubectl`, `ls`, `grep`, …)
|
|
51
|
+
with `rtk` when the model forgets. **Command chains are split on `&&`,
|
|
52
|
+
`||`, `;` and `|`, and every known segment is prefixed** — e.g.
|
|
53
|
+
`git add . && git push` becomes `rtk git add . && rtk git push`.
|
|
54
|
+
Operators inside quotes are ignored, and unparseable commands are left
|
|
55
|
+
untouched. Falls back gracefully when the `rtk` binary is missing
|
|
56
|
+
(warns once).
|
|
57
|
+
|
|
58
|
+
**Requirement:** the `rtk` binary must be on `PATH`.
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
cargo install rtk-ai
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### TOON / JSON Compression (`✂`)
|
|
65
|
+
|
|
66
|
+
Guidance + a bundled `toon-json` skill for handling information-dense JSON via
|
|
67
|
+
`jq` (query/reshape) and `toon` (compress). The system-prompt nudge is injected
|
|
68
|
+
**only when the user prompt mentions JSON** (`json`/`jsonl`/`jq`/`toon`/
|
|
69
|
+
`openapi`/…). TOON shines on uniform/tabular arrays; deeply nested or
|
|
70
|
+
array-of-arrays data and API contracts stay as JSON.
|
|
71
|
+
|
|
72
|
+
**Requirement:** `jq` and `toon` on `PATH`.
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
npm i -g @toon-format/cli
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Installation
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
pi install git:github.com/xynogen/pix-optimizer
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## Architecture
|
|
85
|
+
|
|
86
|
+
| File | Role |
|
|
87
|
+
|-------------------|-----------------------------------------------------------|
|
|
88
|
+
| `src/index.ts` | Wires the three tools + shared status, registers `/opt` |
|
|
89
|
+
| `src/opt.ts` | The `/opt` router: parse, complete, dispatch |
|
|
90
|
+
| `src/status.ts` | Shared status-bar cell + `OptimizerHandle` contract |
|
|
91
|
+
| `src/caveman.ts` | Caveman logic, levels, prompt, settings dialog |
|
|
92
|
+
| `src/rtk.ts` | RTK prompt + bash command rewriting |
|
|
93
|
+
| `src/json.ts` | jq+TOON guidance, heuristics, bundled skill registration |
|
|
94
|
+
|
|
95
|
+
Each tool registers its own lifecycle hooks and exposes an `OptimizerHandle`
|
|
96
|
+
that `/opt` dispatches to. All three share one `OptimizerStatus`.
|
|
97
|
+
|
|
98
|
+
## Development
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
bun test
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## License
|
|
105
|
+
|
|
106
|
+
MIT
|
package/package.json
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@xynogen/pix-optimizer",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Performance optimization suite for Pi Coding Agent - caveman mode + RTK tool rewriting + jq/TOON JSON compression",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "src/index.ts",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"test": "bun test"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"src",
|
|
12
|
+
"README.md",
|
|
13
|
+
"LICENSE"
|
|
14
|
+
],
|
|
15
|
+
"pi": {
|
|
16
|
+
"extensions": ["./src/index.ts"]
|
|
17
|
+
},
|
|
18
|
+
"keywords": [
|
|
19
|
+
"pi",
|
|
20
|
+
"pi-package",
|
|
21
|
+
"pi-extension",
|
|
22
|
+
"optimizer",
|
|
23
|
+
"caveman",
|
|
24
|
+
"rtk",
|
|
25
|
+
"toon",
|
|
26
|
+
"jq",
|
|
27
|
+
"json",
|
|
28
|
+
"performance"
|
|
29
|
+
],
|
|
30
|
+
"author": "xynogen",
|
|
31
|
+
"license": "MIT",
|
|
32
|
+
"repository": {
|
|
33
|
+
"type": "git",
|
|
34
|
+
"url": "git+https://github.com/xynogen/pix-mono.git",
|
|
35
|
+
"directory": "packages/pix-optimizer"
|
|
36
|
+
},
|
|
37
|
+
"homepage": "https://github.com/xynogen/pix-mono/tree/main/packages/pix-optimizer#readme",
|
|
38
|
+
"bugs": {
|
|
39
|
+
"url": "https://github.com/xynogen/pix-mono/issues"
|
|
40
|
+
},
|
|
41
|
+
"publishConfig": {
|
|
42
|
+
"access": "public"
|
|
43
|
+
},
|
|
44
|
+
"peerDependencies": {
|
|
45
|
+
"@earendil-works/pi-coding-agent": "*",
|
|
46
|
+
"@earendil-works/pi-tui": "*"
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
import { describe, it, expect } from "bun:test";
|
|
2
|
+
import {
|
|
3
|
+
LEVELS,
|
|
4
|
+
LEVEL_NUMBERS,
|
|
5
|
+
STOP_ALIASES,
|
|
6
|
+
STATUS_LABELS,
|
|
7
|
+
buildPrompt,
|
|
8
|
+
buildHelp,
|
|
9
|
+
resolveLevel,
|
|
10
|
+
toggleLevel,
|
|
11
|
+
parseConfig,
|
|
12
|
+
DEFAULT_CONFIG,
|
|
13
|
+
type Level,
|
|
14
|
+
} from "./caveman.ts";
|
|
15
|
+
|
|
16
|
+
// ── LEVELS ────────────────────────────────────────────────────────────────────
|
|
17
|
+
|
|
18
|
+
describe("LEVELS", () => {
|
|
19
|
+
it("contains off as first entry", () => {
|
|
20
|
+
expect(LEVELS[0]).toBe("off");
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it("contains all expected levels", () => {
|
|
24
|
+
const expected = ["off", "lite", "full", "ultra", "micro"];
|
|
25
|
+
for (const l of expected) expect(LEVELS).toContain(l);
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
// ── STOP_ALIASES ──────────────────────────────────────────────────────────────
|
|
30
|
+
|
|
31
|
+
describe("STOP_ALIASES", () => {
|
|
32
|
+
it("includes off, stop, quit", () => {
|
|
33
|
+
expect(STOP_ALIASES.has("off")).toBe(true);
|
|
34
|
+
expect(STOP_ALIASES.has("stop")).toBe(true);
|
|
35
|
+
expect(STOP_ALIASES.has("quit")).toBe(true);
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it("does not include active levels", () => {
|
|
39
|
+
expect(STOP_ALIASES.has("full")).toBe(false);
|
|
40
|
+
expect(STOP_ALIASES.has("ultra")).toBe(false);
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
// ── STATUS_LABELS ─────────────────────────────────────────────────────────────
|
|
45
|
+
|
|
46
|
+
describe("STATUS_LABELS", () => {
|
|
47
|
+
it("has a label for every non-off level", () => {
|
|
48
|
+
const nonOff = LEVELS.filter((l) => l !== "off") as Exclude<Level, "off">[];
|
|
49
|
+
for (const l of nonOff) {
|
|
50
|
+
expect(STATUS_LABELS[l]).toBeTruthy();
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it("latin levels are uppercase", () => {
|
|
55
|
+
expect(STATUS_LABELS["lite"]).toBe("LITE");
|
|
56
|
+
expect(STATUS_LABELS["full"]).toBe("FULL");
|
|
57
|
+
expect(STATUS_LABELS["ultra"]).toBe("ULTRA");
|
|
58
|
+
expect(STATUS_LABELS["micro"]).toBe("MICRO");
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
// ── resolveLevel ──────────────────────────────────────────────────────────────
|
|
63
|
+
|
|
64
|
+
describe("resolveLevel", () => {
|
|
65
|
+
it("resolves valid levels", () => {
|
|
66
|
+
expect(resolveLevel("lite")).toBe("lite");
|
|
67
|
+
expect(resolveLevel("full")).toBe("full");
|
|
68
|
+
expect(resolveLevel("ultra")).toBe("ultra");
|
|
69
|
+
expect(resolveLevel("micro")).toBe("micro");
|
|
70
|
+
expect(resolveLevel("off")).toBe("off");
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it("maps stop aliases to off", () => {
|
|
74
|
+
expect(resolveLevel("stop")).toBe("off");
|
|
75
|
+
expect(resolveLevel("quit")).toBe("off");
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
it("is case-insensitive", () => {
|
|
79
|
+
expect(resolveLevel("FULL")).toBe("full");
|
|
80
|
+
expect(resolveLevel("Ultra")).toBe("ultra");
|
|
81
|
+
expect(resolveLevel("STOP")).toBe("off");
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
it("trims whitespace", () => {
|
|
85
|
+
expect(resolveLevel(" full ")).toBe("full");
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
it("returns null for unknown input", () => {
|
|
89
|
+
expect(resolveLevel("unknown")).toBeNull();
|
|
90
|
+
expect(resolveLevel("")).toBeNull();
|
|
91
|
+
expect(resolveLevel("config")).toBeNull(); // config handled separately
|
|
92
|
+
});
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
// ── numeric levels ────────────────────────────────────────────────────────────
|
|
96
|
+
|
|
97
|
+
describe("numeric levels", () => {
|
|
98
|
+
it("maps 1/2/3 to lite/full/ultra", () => {
|
|
99
|
+
expect(resolveLevel("1")).toBe("lite");
|
|
100
|
+
expect(resolveLevel("2")).toBe("full");
|
|
101
|
+
expect(resolveLevel("3")).toBe("ultra");
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
it("maps 0 to off", () => {
|
|
105
|
+
expect(resolveLevel("0")).toBe("off");
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
it("LEVEL_NUMBERS only covers 1-3", () => {
|
|
109
|
+
expect(Object.keys(LEVEL_NUMBERS).sort()).toEqual(["1", "2", "3"]);
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
it("rejects out-of-range numbers", () => {
|
|
113
|
+
expect(resolveLevel("4")).toBeNull();
|
|
114
|
+
expect(resolveLevel("9")).toBeNull();
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
it("trims whitespace around numbers", () => {
|
|
118
|
+
expect(resolveLevel(" 2 ")).toBe("full");
|
|
119
|
+
});
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
// ── buildHelp ─────────────────────────────────────────────────────────────────
|
|
123
|
+
|
|
124
|
+
describe("buildHelp", () => {
|
|
125
|
+
it("lists numeric shortcuts", () => {
|
|
126
|
+
const help = buildHelp("off");
|
|
127
|
+
expect(help).toContain("1");
|
|
128
|
+
expect(help).toContain("lite");
|
|
129
|
+
expect(help).toContain("2");
|
|
130
|
+
expect(help).toContain("full");
|
|
131
|
+
expect(help).toContain("3");
|
|
132
|
+
expect(help).toContain("ultra");
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
it("shows current level when active", () => {
|
|
136
|
+
expect(buildHelp("ultra")).toContain("ULTRA");
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
it("shows off when disabled", () => {
|
|
140
|
+
expect(buildHelp("off")).toContain("off");
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
it("mentions config", () => {
|
|
144
|
+
expect(buildHelp("off")).toContain("config");
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
it("does not mention wenyan", () => {
|
|
148
|
+
expect(buildHelp("off").toLowerCase()).not.toContain("wenyan");
|
|
149
|
+
});
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
// ── toggleLevel ───────────────────────────────────────────────────────────────
|
|
153
|
+
|
|
154
|
+
describe("toggleLevel", () => {
|
|
155
|
+
it("off → full", () => {
|
|
156
|
+
expect(toggleLevel("off")).toBe("full");
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
it("full → off", () => {
|
|
160
|
+
expect(toggleLevel("full")).toBe("off");
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
it("any non-off level → off", () => {
|
|
164
|
+
const nonOff = LEVELS.filter((l) => l !== "off") as Level[];
|
|
165
|
+
for (const l of nonOff) {
|
|
166
|
+
expect(toggleLevel(l)).toBe("off");
|
|
167
|
+
}
|
|
168
|
+
});
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
// ── buildPrompt ───────────────────────────────────────────────────────────────
|
|
172
|
+
|
|
173
|
+
describe("buildPrompt", () => {
|
|
174
|
+
it("returns empty string for off", () => {
|
|
175
|
+
expect(buildPrompt("off")).toBe("");
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
it("returns MICRO_PROMPT for micro (no BASE)", () => {
|
|
179
|
+
const p = buildPrompt("micro");
|
|
180
|
+
expect(p).toContain("Token efficiency");
|
|
181
|
+
expect(p).not.toContain("CAVEMAN MODE");
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
it("includes BASE for all standard levels", () => {
|
|
185
|
+
const standard = ["lite", "full", "ultra"] as Level[];
|
|
186
|
+
for (const l of standard) {
|
|
187
|
+
expect(buildPrompt(l)).toContain("CAVEMAN MODE");
|
|
188
|
+
}
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
it("includes SAFETY clause for all standard levels", () => {
|
|
192
|
+
const standard = ["lite", "full", "ultra"] as Level[];
|
|
193
|
+
for (const l of standard) {
|
|
194
|
+
expect(buildPrompt(l)).toContain("Auto-clarity");
|
|
195
|
+
}
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
it("each level has distinct intensity instructions", () => {
|
|
199
|
+
const lite = buildPrompt("lite");
|
|
200
|
+
const ultra = buildPrompt("ultra");
|
|
201
|
+
expect(lite).toContain("Keep articles");
|
|
202
|
+
expect(ultra).toContain("Abbreviate");
|
|
203
|
+
expect(lite).not.toContain("Abbreviate");
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
// ── parseConfig ───────────────────────────────────────────────────────────────
|
|
209
|
+
|
|
210
|
+
describe("parseConfig", () => {
|
|
211
|
+
it("parses valid config", () => {
|
|
212
|
+
const cfg = parseConfig({ defaultLevel: "ultra", showStatus: false });
|
|
213
|
+
expect(cfg.defaultLevel).toBe("ultra");
|
|
214
|
+
expect(cfg.showStatus).toBe(false);
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
it("falls back to defaults for invalid defaultLevel", () => {
|
|
218
|
+
const cfg = parseConfig({ defaultLevel: "invalid", showStatus: true });
|
|
219
|
+
expect(cfg.defaultLevel).toBe(DEFAULT_CONFIG.defaultLevel);
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
it("falls back to defaults for missing fields", () => {
|
|
223
|
+
const cfg = parseConfig({});
|
|
224
|
+
expect(cfg.defaultLevel).toBe(DEFAULT_CONFIG.defaultLevel);
|
|
225
|
+
expect(cfg.showStatus).toBe(DEFAULT_CONFIG.showStatus);
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
it("falls back to defaults for null/undefined", () => {
|
|
229
|
+
const cfg = parseConfig(null);
|
|
230
|
+
expect(cfg.defaultLevel).toBe(DEFAULT_CONFIG.defaultLevel);
|
|
231
|
+
expect(cfg.showStatus).toBe(DEFAULT_CONFIG.showStatus);
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
it("accepts all valid levels as defaultLevel", () => {
|
|
235
|
+
for (const l of LEVELS) {
|
|
236
|
+
expect(parseConfig({ defaultLevel: l, showStatus: true }).defaultLevel).toBe(l);
|
|
237
|
+
}
|
|
238
|
+
});
|
|
239
|
+
});
|