@xynogen/pix-optimizer 1.1.8 → 1.1.10
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 +30 -11
- package/package.json +1 -1
- package/src/index.ts +5 -3
- package/src/opt.ts +7 -7
- package/src/status.test.ts +19 -8
- package/src/status.ts +36 -7
package/README.md
CHANGED
|
@@ -4,10 +4,10 @@ Token-optimization suite for Pi Coding Agent. Four tools wired into one
|
|
|
4
4
|
extension via `src/index.ts`, fronted by a single `/optimizer` command and one
|
|
5
5
|
shared status-bar cell:
|
|
6
6
|
|
|
7
|
-
- **Caveman** (
|
|
8
|
-
- **RTK** (
|
|
9
|
-
- **TOON** (
|
|
10
|
-
- **Ponytail** (
|
|
7
|
+
- **Caveman** (`Cv`) — terse-output system prompt
|
|
8
|
+
- **RTK** (`Rk`) — prefixes shell commands with `rtk` + injects RTK prompt
|
|
9
|
+
- **TOON** (`Tn`) — jq + TOON guidance for dense JSON (skill lives in pix-skills)
|
|
10
|
+
- **Ponytail** (`Pt`) — lazy-senior-dev system prompt (minimal code, YAGNI)
|
|
11
11
|
|
|
12
12
|
## Command
|
|
13
13
|
|
|
@@ -25,12 +25,31 @@ State persists to `~/.pi/agent/optimizer.json` (caveman/rtk/toon/ponytail).
|
|
|
25
25
|
|
|
26
26
|
## Status bar
|
|
27
27
|
|
|
28
|
-
A single cell always shows
|
|
29
|
-
|
|
28
|
+
A single cell always shows all four tool icons in a fixed order, color-coded by
|
|
29
|
+
state: **accent** when the tool is enabled, **dim** when disabled.
|
|
30
|
+
|
|
31
|
+
### Icon style (Nerd Font, Unicode, or ASCII)
|
|
32
|
+
|
|
33
|
+
The default glyphs (Nerd Font PUA codepoints) are **Nerd Font** symbols and require a patched
|
|
34
|
+
font (e.g. MesloLGS NF). Terminals without one render them as missing-glyph
|
|
35
|
+
“tofu” boxes. Two font-independent fallbacks are available:
|
|
36
|
+
|
|
37
|
+
| Mode | Glyphs | Needs Nerd Font? |
|
|
38
|
+
|---|---|---|
|
|
39
|
+
| `nerd` (default) | Nerd Font PUA glyphs | yes |
|
|
40
|
+
| `unicode` | `♤ ♡ ♢ ♧` (outline card suits) | no |
|
|
41
|
+
| `ascii` | `Cv Rk Tn Pt` | no |
|
|
42
|
+
|
|
43
|
+
Switch the style live from the **`/optimizer` overlay** — a fifth `icons` row
|
|
44
|
+
at the bottom cycles `nerd → unicode → ascii` with `←→`; the choice persists to
|
|
45
|
+
`~/.pi/agent/optimizer.json`.
|
|
46
|
+
|
|
47
|
+
Icons follow the **global** `pix-pretty` mode — set via `/pretty` or `PRETTY_ICONS`
|
|
48
|
+
env var. The optimizer no longer has its own toggle.
|
|
30
49
|
|
|
31
50
|
## Features
|
|
32
51
|
|
|
33
|
-
### Caveman Mode (
|
|
52
|
+
### Caveman Mode (`Cv`)
|
|
34
53
|
|
|
35
54
|
Cuts ~75% of output tokens while keeping full technical accuracy.
|
|
36
55
|
|
|
@@ -44,7 +63,7 @@ Cuts ~75% of output tokens while keeping full technical accuracy.
|
|
|
44
63
|
The `/optimizer` overlay opens a settings dialog when needed. Default level
|
|
45
64
|
for new sessions is restored from `~/.pi/agent/optimizer.json`.
|
|
46
65
|
|
|
47
|
-
### RTK Tool Rewriting (
|
|
66
|
+
### RTK Tool Rewriting (`Rk`)
|
|
48
67
|
|
|
49
68
|
Two layers, both active automatically:
|
|
50
69
|
|
|
@@ -65,7 +84,7 @@ Two layers, both active automatically:
|
|
|
65
84
|
cargo install rtk-ai
|
|
66
85
|
```
|
|
67
86
|
|
|
68
|
-
### TOON / JSON Compression (
|
|
87
|
+
### TOON / JSON Compression (`Tn`)
|
|
69
88
|
|
|
70
89
|
Guidance for handling information-dense JSON via `jq` (query/reshape) and
|
|
71
90
|
`toon` (compress). The system-prompt nudge is injected **only when the user
|
|
@@ -82,7 +101,7 @@ The `toon-json` skill (full workflow + when-NOT-to-use guidance) is bundled in
|
|
|
82
101
|
npm i -g @toon-format/cli
|
|
83
102
|
```
|
|
84
103
|
|
|
85
|
-
### Ponytail Mode (
|
|
104
|
+
### Ponytail Mode (`Pt`)
|
|
86
105
|
|
|
87
106
|
"Lazy senior dev" mode. Governs **what** the agent builds (minimal code,
|
|
88
107
|
YAGNI), orthogonal to Caveman which governs **how** it talks — they pair. Before
|
|
@@ -117,7 +136,7 @@ pi install npm:@xynogen/pix-optimizer
|
|
|
117
136
|
|-------------------|-----------------------------------------------------------|
|
|
118
137
|
| `src/index.ts` | Wires the four tools + shared status, registers `/optimizer` |
|
|
119
138
|
| `src/opt.ts` | The `/optimizer` overlay UI (keyboard nav + cycling) |
|
|
120
|
-
| `src/status.ts` | Shared status-bar cell
|
|
139
|
+
| `src/status.ts` | Shared status-bar cell (`toolIcon()` → shared `pix-pretty` catalog) |
|
|
121
140
|
| `src/caveman.ts` | Caveman logic, levels, prompt |
|
|
122
141
|
| `src/rtk.ts` | RTK prompt + bash command rewriting |
|
|
123
142
|
| `src/json.ts` | jq+TOON guidance, heuristics, system-prompt injection |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xynogen/pix-optimizer",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.10",
|
|
4
4
|
"description": "Performance optimization suite for Pi Coding Agent - caveman mode + RTK tool rewriting + jq/TOON JSON compression + ponytail lazy-dev mode",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.ts",
|
package/src/index.ts
CHANGED
|
@@ -7,9 +7,10 @@
|
|
|
7
7
|
* - toon: jq + TOON guidance for dense JSON (+ bundled skill)
|
|
8
8
|
* - ponytail: lazy-senior-dev system prompt (minimal code, YAGNI)
|
|
9
9
|
*
|
|
10
|
-
* They share ONE status-bar cell (
|
|
11
|
-
*
|
|
12
|
-
*
|
|
10
|
+
* They share ONE status-bar cell (all four icons always shown — dimmed when
|
|
11
|
+
* off, accented when on; icon style is nerd/unicode/ascii, set via /optimizer)
|
|
12
|
+
* and ONE command (/optimizer — an interactive overlay). index.ts wires
|
|
13
|
+
* lifecycle hooks via each module, then registers the overlay command.
|
|
13
14
|
*/
|
|
14
15
|
|
|
15
16
|
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
@@ -26,6 +27,7 @@ import {
|
|
|
26
27
|
import { filterModelWarnings } from "./tool-result-filter.ts";
|
|
27
28
|
|
|
28
29
|
export default function optimizer(pi: ExtensionAPI) {
|
|
30
|
+
// Icons follow the global pix-pretty mode (set via /pretty); no local state.
|
|
29
31
|
const status = new OptimizerStatus();
|
|
30
32
|
|
|
31
33
|
// Each module registers its own lifecycle hooks and returns a handle the
|
package/src/opt.ts
CHANGED
|
@@ -16,12 +16,12 @@
|
|
|
16
16
|
|
|
17
17
|
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
18
18
|
import { frameLines } from "@xynogen/pix-pretty/modal-frame";
|
|
19
|
-
import {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
TOOL_ICONS,
|
|
19
|
+
import type {
|
|
20
|
+
OptimizerHandle,
|
|
21
|
+
OptimizerStatus,
|
|
22
|
+
OptimizerTool,
|
|
24
23
|
} from "./status.ts";
|
|
24
|
+
import { toolIcon } from "./status.ts";
|
|
25
25
|
|
|
26
26
|
/** Min/max content width for the overlay box (excludes 4 cols of chrome). */
|
|
27
27
|
const MIN_CONTENT = 28;
|
|
@@ -150,7 +150,7 @@ export function registerOptCommand(
|
|
|
150
150
|
const on = handles[tool].current() !== "off";
|
|
151
151
|
const sel = i === selected;
|
|
152
152
|
const cursor = sel ? theme.fg("accent", "→") : " ";
|
|
153
|
-
const
|
|
153
|
+
const glyph = theme.fg(on ? "accent" : "dim", toolIcon(tool));
|
|
154
154
|
const name = theme.fg(
|
|
155
155
|
sel ? "accent" : on ? "text" : "muted",
|
|
156
156
|
tool.padEnd(nameWidth),
|
|
@@ -164,7 +164,7 @@ export function registerOptCommand(
|
|
|
164
164
|
on ? "accent" : "dim",
|
|
165
165
|
levelBar(cur, handles[tool].values),
|
|
166
166
|
);
|
|
167
|
-
return `${cursor} ${
|
|
167
|
+
return `${cursor} ${glyph} ${name} ${value} ${bar}`;
|
|
168
168
|
});
|
|
169
169
|
const lines = [
|
|
170
170
|
theme.fg("accent", theme.bold(" Optimizer")),
|
package/src/status.test.ts
CHANGED
|
@@ -3,12 +3,18 @@ import {
|
|
|
3
3
|
OptimizerStatus,
|
|
4
4
|
renderStatus,
|
|
5
5
|
STATUS_KEY,
|
|
6
|
-
|
|
6
|
+
toolIcon,
|
|
7
7
|
} from "./status.ts";
|
|
8
8
|
|
|
9
9
|
/** Tagging colorizer: <accent>X</accent> / <dim>X</dim> for assertions. */
|
|
10
10
|
const tag = (c: string, t: string) => `<${c}>${t}</${c}>`;
|
|
11
11
|
|
|
12
|
+
// Icons resolve against the global pix-pretty mode (default "nerd" in tests).
|
|
13
|
+
const CV = toolIcon("caveman");
|
|
14
|
+
const RK = toolIcon("rtk");
|
|
15
|
+
const TN = toolIcon("toon");
|
|
16
|
+
const PT = toolIcon("ponytail");
|
|
17
|
+
|
|
12
18
|
describe("renderStatus", () => {
|
|
13
19
|
it("shows ALL icons in order, accent when enabled", () => {
|
|
14
20
|
expect(
|
|
@@ -17,7 +23,7 @@ describe("renderStatus", () => {
|
|
|
17
23
|
tag,
|
|
18
24
|
),
|
|
19
25
|
).toBe(
|
|
20
|
-
`<accent>${
|
|
26
|
+
`<accent>${CV}</accent> <accent>${RK}</accent> <accent>${TN}</accent> <accent>${PT}</accent> `,
|
|
21
27
|
);
|
|
22
28
|
});
|
|
23
29
|
|
|
@@ -28,21 +34,26 @@ describe("renderStatus", () => {
|
|
|
28
34
|
tag,
|
|
29
35
|
),
|
|
30
36
|
).toBe(
|
|
31
|
-
`<dim>${
|
|
37
|
+
`<dim>${CV}</dim> <accent>${RK}</accent> <accent>${TN}</accent> <accent>${PT}</accent> `,
|
|
32
38
|
);
|
|
33
39
|
});
|
|
34
40
|
|
|
35
41
|
it("all dim when nothing enabled (cell never empty)", () => {
|
|
36
42
|
expect(renderStatus({}, tag)).toBe(
|
|
37
|
-
`<dim>${
|
|
43
|
+
`<dim>${CV}</dim> <dim>${RK}</dim> <dim>${TN}</dim> <dim>${PT}</dim> `,
|
|
38
44
|
);
|
|
39
45
|
});
|
|
40
46
|
|
|
41
47
|
it("preserves fixed order regardless of insertion order", () => {
|
|
42
48
|
expect(renderStatus({ toon: true, caveman: true }, tag)).toBe(
|
|
43
|
-
`<accent>${
|
|
49
|
+
`<accent>${CV}</accent> <dim>${RK}</dim> <accent>${TN}</accent> <dim>${PT}</dim> `,
|
|
44
50
|
);
|
|
45
51
|
});
|
|
52
|
+
|
|
53
|
+
it("resolves icons via the shared catalog (non-empty glyphs)", () => {
|
|
54
|
+
// toolIcon delegates to pix-pretty's icon(); every tool has a glyph.
|
|
55
|
+
expect([CV, RK, TN, PT].every((g) => g.length > 0)).toBe(true);
|
|
56
|
+
});
|
|
46
57
|
});
|
|
47
58
|
|
|
48
59
|
describe("OptimizerStatus", () => {
|
|
@@ -67,7 +78,7 @@ describe("OptimizerStatus", () => {
|
|
|
67
78
|
expect(last.key).toBe(STATUS_KEY);
|
|
68
79
|
// caveman + toon + ponytail still unset (dim), rtk accent.
|
|
69
80
|
expect(last.text).toBe(
|
|
70
|
-
`<dim>${
|
|
81
|
+
`<dim>${CV}</dim> <accent>${RK}</accent> <dim>${TN}</dim> <dim>${PT}</dim> `,
|
|
71
82
|
);
|
|
72
83
|
});
|
|
73
84
|
|
|
@@ -78,7 +89,7 @@ describe("OptimizerStatus", () => {
|
|
|
78
89
|
status.set("toon", true, ctx as never);
|
|
79
90
|
const last = ctx.calls.at(-1)!;
|
|
80
91
|
expect(last.text).toBe(
|
|
81
|
-
`<accent>${
|
|
92
|
+
`<accent>${CV}</accent> <dim>${RK}</dim> <accent>${TN}</accent> <dim>${PT}</dim> `,
|
|
82
93
|
);
|
|
83
94
|
});
|
|
84
95
|
|
|
@@ -89,7 +100,7 @@ describe("OptimizerStatus", () => {
|
|
|
89
100
|
status.set("rtk", false, ctx as never);
|
|
90
101
|
const last = ctx.calls.at(-1)!;
|
|
91
102
|
expect(last.text).toBe(
|
|
92
|
-
`<dim>${
|
|
103
|
+
`<dim>${CV}</dim> <dim>${RK}</dim> <dim>${TN}</dim> <dim>${PT}</dim> `,
|
|
93
104
|
);
|
|
94
105
|
});
|
|
95
106
|
});
|
package/src/status.ts
CHANGED
|
@@ -17,6 +17,11 @@ import type {
|
|
|
17
17
|
ExtensionContext,
|
|
18
18
|
ThemeColor,
|
|
19
19
|
} from "@earendil-works/pi-coding-agent";
|
|
20
|
+
import {
|
|
21
|
+
type IconKey,
|
|
22
|
+
icon,
|
|
23
|
+
onIconModeChange,
|
|
24
|
+
} from "@xynogen/pix-pretty/icon-catalog";
|
|
20
25
|
|
|
21
26
|
/**
|
|
22
27
|
* Each optimizer tool (caveman/rtk/toon/ponytail) exposes a handle so the
|
|
@@ -42,13 +47,24 @@ export const STATUS_KEY = "pix-optimizer";
|
|
|
42
47
|
/** Tools that participate in the shared indicator, in render order. */
|
|
43
48
|
export type OptimizerTool = "caveman" | "rtk" | "toon" | "ponytail";
|
|
44
49
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
+
/**
|
|
51
|
+
* Icons come from the shared pix-pretty catalog and follow the ONE global icon
|
|
52
|
+
* mode (set via /pretty). The optimizer no longer owns a mode: each tool maps
|
|
53
|
+
* to a semantic catalog key, and the cell renders whatever the active mode
|
|
54
|
+
* resolves — nerd / unicode / ascii — with no per-package knob.
|
|
55
|
+
*/
|
|
56
|
+
const TOOL_ICON_KEY: Record<OptimizerTool, IconKey> = {
|
|
57
|
+
caveman: "opt.caveman",
|
|
58
|
+
rtk: "opt.rtk",
|
|
59
|
+
toon: "opt.toon",
|
|
60
|
+
ponytail: "opt.ponytail",
|
|
50
61
|
};
|
|
51
62
|
|
|
63
|
+
/** Current glyph for a tool, resolved against the active global icon mode. */
|
|
64
|
+
export function toolIcon(tool: OptimizerTool): string {
|
|
65
|
+
return icon(TOOL_ICON_KEY[tool]);
|
|
66
|
+
}
|
|
67
|
+
|
|
52
68
|
/** Fixed left-to-right order of icons in the cell. */
|
|
53
69
|
const TOOL_ORDER: readonly OptimizerTool[] = [
|
|
54
70
|
"caveman",
|
|
@@ -68,7 +84,8 @@ export type Colorize = (color: ThemeColor, text: string) => string;
|
|
|
68
84
|
/**
|
|
69
85
|
* Build the colored status string for a set of tool states. ALL tool icons are
|
|
70
86
|
* always shown, in TOOL_ORDER; each is accent-colored when its tool is enabled
|
|
71
|
-
* and dim when disabled.
|
|
87
|
+
* and dim when disabled. Glyphs resolve against the active global icon mode
|
|
88
|
+
* (see /pretty). `color` applies the theme color (e.g. theme.fg).
|
|
72
89
|
*
|
|
73
90
|
* Pure + exported for tests (pass a tagging colorizer to assert per-icon color).
|
|
74
91
|
* A trailing space separates the cell from the next status segment.
|
|
@@ -78,7 +95,7 @@ export function renderStatus(
|
|
|
78
95
|
color: Colorize,
|
|
79
96
|
): string {
|
|
80
97
|
return `${TOOL_ORDER.map((t) =>
|
|
81
|
-
color(states[t] === true ? ENABLED_COLOR : DISABLED_COLOR,
|
|
98
|
+
color(states[t] === true ? ENABLED_COLOR : DISABLED_COLOR, toolIcon(t)),
|
|
82
99
|
).join(" ")} `;
|
|
83
100
|
}
|
|
84
101
|
|
|
@@ -89,6 +106,17 @@ export function renderStatus(
|
|
|
89
106
|
*/
|
|
90
107
|
export class OptimizerStatus {
|
|
91
108
|
private states: Partial<Record<OptimizerTool, boolean>> = {};
|
|
109
|
+
/** Latest ui ctx seen, so an icon-mode change can repaint without a toggle. */
|
|
110
|
+
private lastCtx: Pick<ExtensionContext, "ui"> | undefined;
|
|
111
|
+
|
|
112
|
+
constructor() {
|
|
113
|
+
// The cell is a pushed status (setStatus), so it does NOT auto-refresh
|
|
114
|
+
// when /pretty flips the global icon mode. Repaint it on mode change
|
|
115
|
+
// using the last-seen ctx (no-op until the cell has painted once).
|
|
116
|
+
onIconModeChange(() => {
|
|
117
|
+
if (this.lastCtx) this.paint(this.lastCtx);
|
|
118
|
+
});
|
|
119
|
+
}
|
|
92
120
|
|
|
93
121
|
/** Current enabled state for one tool (undefined until first set). */
|
|
94
122
|
get(tool: OptimizerTool): boolean | undefined {
|
|
@@ -107,6 +135,7 @@ export class OptimizerStatus {
|
|
|
107
135
|
|
|
108
136
|
/** Repaint the shared cell from current states. */
|
|
109
137
|
paint(ctx: Pick<ExtensionContext, "ui">): void {
|
|
138
|
+
this.lastCtx = ctx;
|
|
110
139
|
const text = renderStatus(this.states, (c, t) => ctx.ui.theme.fg(c, t));
|
|
111
140
|
ctx.ui.setStatus(STATUS_KEY, text);
|
|
112
141
|
}
|