@xynogen/pix-optimizer 1.0.2 → 1.0.7
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 +10 -7
- package/package.json +1 -1
- package/src/json.test.ts +0 -8
- package/src/json.ts +41 -26
- package/src/rtk.ts +8 -8
- package/src/skills/toon-json/SKILL.md +0 -101
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@ shared status-bar cell:
|
|
|
6
6
|
|
|
7
7
|
- **Caveman** (`⛏`) — terse-output system prompt
|
|
8
8
|
- **RTK** (`⚔`) — prefixes shell commands with `rtk` + injects RTK prompt
|
|
9
|
-
- **TOON** (`✂`) — jq + TOON guidance for dense JSON (
|
|
9
|
+
- **TOON** (`✂`) — jq + TOON guidance for dense JSON (skill lives in pix-skills)
|
|
10
10
|
|
|
11
11
|
## Command
|
|
12
12
|
|
|
@@ -63,11 +63,14 @@ cargo install rtk-ai
|
|
|
63
63
|
|
|
64
64
|
### TOON / JSON Compression (`✂`)
|
|
65
65
|
|
|
66
|
-
Guidance
|
|
67
|
-
`
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
66
|
+
Guidance for handling information-dense JSON via `jq` (query/reshape) and
|
|
67
|
+
`toon` (compress). The system-prompt nudge is injected **only when the user
|
|
68
|
+
prompt mentions JSON** (`json`/`jsonl`/`jq`/`toon`/`openapi`/…). TOON shines
|
|
69
|
+
on uniform/tabular arrays; deeply nested or array-of-arrays data and API
|
|
70
|
+
contracts stay as JSON.
|
|
71
|
+
|
|
72
|
+
The `toon-json` skill (full workflow + when-NOT-to-use guidance) is bundled in
|
|
73
|
+
`pix-skills` and auto-discovered from there.
|
|
71
74
|
|
|
72
75
|
**Requirement:** `jq` and `toon` on `PATH`.
|
|
73
76
|
|
|
@@ -90,7 +93,7 @@ pi install npm:@xynogen/pix-optimizer
|
|
|
90
93
|
| `src/status.ts` | Shared status-bar cell + `OptimizerHandle` contract |
|
|
91
94
|
| `src/caveman.ts` | Caveman logic, levels, prompt, settings dialog |
|
|
92
95
|
| `src/rtk.ts` | RTK prompt + bash command rewriting |
|
|
93
|
-
| `src/json.ts` | jq+TOON guidance, heuristics,
|
|
96
|
+
| `src/json.ts` | jq+TOON guidance, heuristics, system-prompt injection |
|
|
94
97
|
|
|
95
98
|
Each tool registers its own lifecycle hooks and exposes an `OptimizerHandle`
|
|
96
99
|
that `/opt` dispatches to. All three share one `OptimizerStatus`.
|
package/package.json
CHANGED
package/src/json.test.ts
CHANGED
|
@@ -5,7 +5,6 @@ import {
|
|
|
5
5
|
JSON_SYSTEM_PROMPT,
|
|
6
6
|
mentionsJson,
|
|
7
7
|
objectDepth,
|
|
8
|
-
skillDir,
|
|
9
8
|
} from "./json.ts";
|
|
10
9
|
|
|
11
10
|
describe("JSON_SYSTEM_PROMPT", () => {
|
|
@@ -168,10 +167,3 @@ describe("adviseToon", () => {
|
|
|
168
167
|
expect(adviseToon(d2, 2).useToon).toBe(true);
|
|
169
168
|
});
|
|
170
169
|
});
|
|
171
|
-
|
|
172
|
-
describe("skillDir", () => {
|
|
173
|
-
it("points at the bundled toon-json skill", () => {
|
|
174
|
-
const dir = skillDir();
|
|
175
|
-
expect(dir.endsWith("skills/toon-json")).toBe(true);
|
|
176
|
-
});
|
|
177
|
-
});
|
package/src/json.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* json.ts — JSON token-optimization via jq + TOON.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
4
|
+
* A small system-prompt nudge teaching the model to run JSON through
|
|
5
|
+
* `jq` (query/reshape) and `toon` (compress for context), and to convert
|
|
6
|
+
* back to JSON only when a strict contract requires it.
|
|
7
|
+
*
|
|
8
|
+
* The bundled `toon-json` skill lives in pix-skills and is auto-discovered
|
|
9
|
+
* from there — no resources_discover hook needed here.
|
|
10
10
|
*
|
|
11
11
|
* TOON = Token-Oriented Object Notation (https://github.com/toon-format/spec).
|
|
12
12
|
* It shines on uniform/tabular arrays of objects (declare keys once, stream
|
|
@@ -17,8 +17,6 @@
|
|
|
17
17
|
* by index.ts alongside caveman(pi) and rtk(pi).
|
|
18
18
|
*/
|
|
19
19
|
|
|
20
|
-
import { join } from "node:path";
|
|
21
|
-
import { fileURLToPath } from "node:url";
|
|
22
20
|
import type {
|
|
23
21
|
ExtensionAPI,
|
|
24
22
|
ExtensionCommandContext,
|
|
@@ -207,15 +205,6 @@ export function objectDepth(value: unknown): number {
|
|
|
207
205
|
|
|
208
206
|
// ── Bundled skill path ────────────────────────────────────────────────────────
|
|
209
207
|
|
|
210
|
-
/**
|
|
211
|
-
* Absolute path to the bundled `toon-json` skill directory, resolved relative
|
|
212
|
-
* to this module so it works regardless of the extension's install location.
|
|
213
|
-
*/
|
|
214
|
-
export function skillDir(): string {
|
|
215
|
-
const here = fileURLToPath(new URL(".", import.meta.url));
|
|
216
|
-
return join(here, "skills", "toon-json");
|
|
217
|
-
}
|
|
218
|
-
|
|
219
208
|
// ── Pi extension ──────────────────────────────────────────────────────────────
|
|
220
209
|
|
|
221
210
|
export function json(
|
|
@@ -223,10 +212,16 @@ export function json(
|
|
|
223
212
|
status: OptimizerStatus,
|
|
224
213
|
): OptimizerHandle {
|
|
225
214
|
let enabled = true;
|
|
215
|
+
let jqAvailable: boolean | null = null;
|
|
216
|
+
let toonAvailable: boolean | null = null;
|
|
226
217
|
|
|
227
218
|
// Report into the shared optimizer indicator.
|
|
228
219
|
function syncStatus(ctx: Pick<ExtensionContext, "ui">) {
|
|
229
|
-
status.set(
|
|
220
|
+
status.set(
|
|
221
|
+
"toon",
|
|
222
|
+
enabled && jqAvailable !== false && toonAvailable !== false,
|
|
223
|
+
ctx,
|
|
224
|
+
);
|
|
230
225
|
}
|
|
231
226
|
|
|
232
227
|
pi.on("session_start", async (_event, ctx) => {
|
|
@@ -239,18 +234,38 @@ export function json(
|
|
|
239
234
|
syncStatus(ctx);
|
|
240
235
|
});
|
|
241
236
|
|
|
242
|
-
// Surface the bundled skill so the model can load the full workflow.
|
|
243
|
-
pi.on("resources_discover", async () => {
|
|
244
|
-
if (!enabled) return undefined;
|
|
245
|
-
return { skillPaths: [skillDir()] };
|
|
246
|
-
});
|
|
247
|
-
|
|
248
237
|
// Inject the JSON-handling nudge into the system prompt, but ONLY when the
|
|
249
238
|
// user prompt actually mentions JSON / a related token — otherwise it's dead
|
|
250
|
-
// weight in every turn.
|
|
251
|
-
|
|
239
|
+
// weight in every turn. Probe jq/toon lazily here (not at session_start) so
|
|
240
|
+
// we don't add startup overhead for a workflow the user may never trigger.
|
|
241
|
+
pi.on("before_agent_start", async (event, ctx) => {
|
|
252
242
|
if (!enabled) return undefined;
|
|
253
243
|
if (!mentionsJson(event.prompt)) return undefined;
|
|
244
|
+
|
|
245
|
+
// Probe once on first JSON-relevant prompt.
|
|
246
|
+
if (jqAvailable === null || toonAvailable === null) {
|
|
247
|
+
const [jqRes, toonRes] = await Promise.all([
|
|
248
|
+
pi.exec("which", ["jq"], { timeout: 1000 }).catch(() => ({ code: 1 })),
|
|
249
|
+
pi
|
|
250
|
+
.exec("which", ["toon"], { timeout: 1000 })
|
|
251
|
+
.catch(() => ({ code: 1 })),
|
|
252
|
+
]);
|
|
253
|
+
jqAvailable = jqRes.code === 0;
|
|
254
|
+
toonAvailable = toonRes.code === 0;
|
|
255
|
+
if (!jqAvailable)
|
|
256
|
+
ctx.ui.notify(
|
|
257
|
+
"jq not found — JSON/TOON guidance disabled. Install: sudo apt install jq or brew install jq",
|
|
258
|
+
"warning",
|
|
259
|
+
);
|
|
260
|
+
if (!toonAvailable)
|
|
261
|
+
ctx.ui.notify(
|
|
262
|
+
"toon not found — JSON/TOON guidance disabled. Install: bun add -g @toon-format/cli or npm i -g @toon-format/cli",
|
|
263
|
+
"warning",
|
|
264
|
+
);
|
|
265
|
+
syncStatus(ctx);
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
if (jqAvailable === false || toonAvailable === false) return undefined;
|
|
254
269
|
const existing = event.systemPrompt ?? "";
|
|
255
270
|
return { systemPrompt: `${JSON_SYSTEM_PROMPT}\n\n${existing}` };
|
|
256
271
|
});
|
package/src/rtk.ts
CHANGED
|
@@ -286,7 +286,14 @@ export function rtk(
|
|
|
286
286
|
// Keep the status indicator in sync across the agent lifecycle. Probe
|
|
287
287
|
// availability on session start so the icon reflects reality immediately.
|
|
288
288
|
pi.on("session_start", async (_event, ctx) => {
|
|
289
|
-
await checkRtkAvailability();
|
|
289
|
+
const probe = await checkRtkAvailability();
|
|
290
|
+
if (!probe.available && !warnedMissing) {
|
|
291
|
+
ctx.ui.notify(
|
|
292
|
+
"rtk not found — RTK rewriting disabled. Install: cargo install rtk-ai",
|
|
293
|
+
"warning",
|
|
294
|
+
);
|
|
295
|
+
warnedMissing = true;
|
|
296
|
+
}
|
|
290
297
|
syncStatus(ctx);
|
|
291
298
|
});
|
|
292
299
|
pi.on("agent_start", async (_event, ctx) => {
|
|
@@ -340,13 +347,6 @@ export function rtk(
|
|
|
340
347
|
const probe = await checkRtkAvailability();
|
|
341
348
|
|
|
342
349
|
if (!probe.available) {
|
|
343
|
-
if (!warnedMissing) {
|
|
344
|
-
ctx.ui.notify(
|
|
345
|
-
"RTK binary not found. Install: cargo install rtk-ai",
|
|
346
|
-
"warning",
|
|
347
|
-
);
|
|
348
|
-
warnedMissing = true;
|
|
349
|
-
}
|
|
350
350
|
return undefined; // Don't rewrite if rtk not available
|
|
351
351
|
}
|
|
352
352
|
|
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: toon-json
|
|
3
|
-
description: Manipulate information-dense JSON efficiently with jq + TOON. Use when fetching/reading large or repetitive JSON (LLM schemas, OpenAPI specs, API responses, datasets, config dumps) into context. Query/reshape with jq, compress to TOON to cut tokens, decode back to JSON only when a strict contract needs it.
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# TOON + jq: Dense JSON Workflow
|
|
7
|
-
|
|
8
|
-
## Goal
|
|
9
|
-
Carry only the JSON slice you need, in the cheapest encoding. Query with `jq`,
|
|
10
|
-
compress with `toon`, and round-trip back to JSON **only** when a contract
|
|
11
|
-
requires strict JSON.
|
|
12
|
-
|
|
13
|
-
TOON (Token-Oriented Object Notation, https://github.com/toon-format/spec) is a
|
|
14
|
-
line-oriented encoding of the JSON data model. Uniform arrays of objects declare
|
|
15
|
-
their keys once and stream bare rows, so token cost drops sharply on tabular and
|
|
16
|
-
dense data.
|
|
17
|
-
|
|
18
|
-
## The pipeline
|
|
19
|
-
|
|
20
|
-
```bash
|
|
21
|
-
# Fetch → reshape → compress (most common)
|
|
22
|
-
curl -s https://api.example.com/models | jq '.data' | toon
|
|
23
|
-
|
|
24
|
-
# Local file, show token savings
|
|
25
|
-
cat openapi.json | jq '.paths' | toon --stats
|
|
26
|
-
|
|
27
|
-
# Just compress, no query
|
|
28
|
-
cat data.json | toon
|
|
29
|
-
|
|
30
|
-
# Convert TOON back to JSON (strict contract / downstream parser)
|
|
31
|
-
echo "$TOON_BLOB" | toon -d
|
|
32
|
-
cat data.toon | toon --decode
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
`toon` auto-detects direction from input. Force it with `-e` (encode JSON→TOON)
|
|
36
|
-
or `-d` (decode TOON→JSON).
|
|
37
|
-
|
|
38
|
-
### Useful flags
|
|
39
|
-
- `--stats` — print token/byte statistics for the conversion
|
|
40
|
-
- `--delimiter=,|\t|"|"` — array delimiter (comma default; tab/pipe can tokenize better)
|
|
41
|
-
- `--keyFolding=safe` — collapse single-key nesting chains
|
|
42
|
-
- `--no-strict` — lenient decode
|
|
43
|
-
|
|
44
|
-
## Decide before you compress
|
|
45
|
-
|
|
46
|
-
TOON is not always smaller. Pick based on shape:
|
|
47
|
-
|
|
48
|
-
| Shape | Action | Why |
|
|
49
|
-
|---|---|---|
|
|
50
|
-
| Uniform array of objects (same keys, primitive values) | **TOON** | Sweet spot — keys declared once, rows streamed; savings scale with rows × fields |
|
|
51
|
-
| Flat object / primitive array | **TOON** | Drops quotes and braces |
|
|
52
|
-
| Shallow nesting | **TOON** | Indentation cheaper than braces at low depth |
|
|
53
|
-
| Deeply nested / non-uniform | **JSON** | Indentation cost grows; compact JSON can win |
|
|
54
|
-
| Array of arrays | **JSON** | TOON's one structurally-worse case (explicit list markers + inner headers) |
|
|
55
|
-
| API contract / payload to send or store | **JSON** | Must stay valid JSON for the consumer |
|
|
56
|
-
|
|
57
|
-
Rule of thumb: **TOON for reading dense data into context. JSON for contracts.**
|
|
58
|
-
|
|
59
|
-
## When NOT to use TOON
|
|
60
|
-
- Anything sent to or stored by an API that expects JSON.
|
|
61
|
-
- Data a downstream tool/parser must consume as strict JSON.
|
|
62
|
-
- Deeply nested config trees or highly irregular structures.
|
|
63
|
-
- Tiny payloads where the conversion overhead isn't worth it.
|
|
64
|
-
|
|
65
|
-
In those cases, still use `jq` to slice down to what you need — just skip the
|
|
66
|
-
`| toon` step.
|
|
67
|
-
|
|
68
|
-
## Worked examples
|
|
69
|
-
|
|
70
|
-
LLM model list (uniform array → great TOON candidate):
|
|
71
|
-
|
|
72
|
-
```bash
|
|
73
|
-
curl -s https://api.example.com/v1/models | jq '.data | map({id, owned_by, context})' | toon
|
|
74
|
-
```
|
|
75
|
-
```
|
|
76
|
-
[3]{id,owned_by,context}:
|
|
77
|
-
gpt-x,acme,128000
|
|
78
|
-
gpt-y,acme,200000
|
|
79
|
-
gpt-z,acme,1000000
|
|
80
|
-
```
|
|
81
|
-
|
|
82
|
-
OpenAPI paths summary (reshape first, then compress):
|
|
83
|
-
|
|
84
|
-
```bash
|
|
85
|
-
cat openapi.json \
|
|
86
|
-
| jq '[.paths | to_entries[] | {path: .key, methods: (.value | keys)}]' \
|
|
87
|
-
| toon --stats
|
|
88
|
-
```
|
|
89
|
-
|
|
90
|
-
Round-trip back to JSON for an API call:
|
|
91
|
-
|
|
92
|
-
```bash
|
|
93
|
-
RESHAPED=$(cat payload.toon | toon -d)
|
|
94
|
-
curl -s -X POST https://api.example.com/ingest -d "$RESHAPED"
|
|
95
|
-
```
|
|
96
|
-
|
|
97
|
-
## Checklist
|
|
98
|
-
1. **Query** — narrow with `jq` to the exact slice needed.
|
|
99
|
-
2. **Decide** — uniform/tabular/shallow → TOON; nested/array-of-arrays/contract → JSON.
|
|
100
|
-
3. **Compress** — `| toon` (add `--stats` to confirm savings).
|
|
101
|
-
4. **Round-trip** — `toon -d` only when strict JSON is required downstream.
|