mu-harness 0.30.0 → 0.32.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.
@@ -47,14 +47,17 @@ const GRID_CELLS = GRID_COLS * GRID_ROWS;
47
47
  const GRID_WIDTH = GRID_COLS * 2 - 1; // glyphs joined by single spaces
48
48
  const USED = '⛁'; // a filled context cell (Claude Code's /context glyph)
49
49
  const FREEG = '⛶'; // a free cell
50
- const BUFFER_COLOR = '\x1b[93m'; // bright yellow the compaction reserve
51
- // ANSI SGR codes mu's TUI text utils are ANSI-aware so these render in the terminal;
52
- // the companion strips them (plain text), keeping the labelled breakdown readable.
50
+ // Truecolor SGR — distinct, readable hues (mu's TUI utils + the companion both strip/parse
51
+ // these correctly). Secondary text uses a single grey so only the category glyphs carry colour.
53
52
  const RESET = '\x1b[0m';
54
- const DIM = '\x1b[2m';
53
+ const GREY = '\x1b[38;2;153;153;153m';
55
54
  const BOLD = '\x1b[1m';
56
- const ITALIC_DIM = '\x1b[2;3m';
57
- const paint = (s, color) => `${color}${s}${RESET}`;
55
+ const ITALIC = '\x1b[3m';
56
+ const BUFFER_COLOR = '\x1b[38;2;255;193;7m'; // amber — the compaction reserve
57
+ // Reset BEFORE the colour too: the TUI note prefixes each line with a `dim` muted style,
58
+ // and a bare `\x1b[38;2;…m` only sets the foreground — it wouldn't clear the inherited dim,
59
+ // which darkened the first cell of every row. The leading reset wipes it.
60
+ const paint = (s, color) => `${RESET}${color}${s}${RESET}`;
58
61
  const fmtTok = (n) => (n >= 1e6 ? `${(n / 1e6).toFixed(1)}M` : n >= 1000 ? `${(n / 1000).toFixed(1)}k` : `${n}`);
59
62
  const pctStr = (n, w) => {
60
63
  if (w <= 0)
@@ -121,16 +124,16 @@ export const createContextCommand = () => ({
121
124
  }
122
125
  return { n: estTokens(text.length), exact: false };
123
126
  };
124
- // label, text, ANSI colour one per category, in render order (descriptive labels à la Claude Code).
127
+ // label, text, truecolordistinct hues across the wheel, in render order.
125
128
  const SPEC = [
126
- ['System prompt', sys.agent, '\x1b[36m'], // cyan — the agent prompt
127
- ['Environment', sys.env, '\x1b[33m'], // yellow — the <env> block
128
- ['Instructions', sys.instructions, '\x1b[34m'], // blue — AGENTS.md / CLAUDE.md
129
- ['Memory', sys.memory, '\x1b[35m'], // magenta — MEMORY.md
130
- ['Tools', `${toolSchemas}\n${sys.toolPrompts}`, '\x1b[31m'], // red — schemas + tool prompts
131
- ['You', byRole('user'), '\x1b[32m'], // green — your messages
132
- ['Agent', byRole('assistant'), '\x1b[94m'], // bright blue — assistant replies
133
- ['Tool results', byRole('tool'), '\x1b[90m'], // grey — tool results
129
+ ['System prompt', sys.agent, '\x1b[38;2;239;108;82m'], // coral — the agent prompt
130
+ ['Environment', sys.env, '\x1b[38;2;129;199;132m'], // green — the <env> block
131
+ ['Instructions', sys.instructions, '\x1b[38;2;100;181;246m'], // blue — AGENTS.md / CLAUDE.md
132
+ ['Memory', sys.memory, '\x1b[38;2;186;104;200m'], // purple — MEMORY.md
133
+ ['Tools', `${toolSchemas}\n${sys.toolPrompts}`, '\x1b[38;2;77;182;172m'], // teal — schemas + tool prompts
134
+ ['You', byRole('user'), '\x1b[38;2;121;134;203m'], // indigo — your messages
135
+ ['Agent', byRole('assistant'), '\x1b[38;2;240;98;146m'], // pink — assistant replies
136
+ ['Tool results', byRole('tool'), '\x1b[38;2;0;188;212m'], // cyan — tool results (distinct from amber buffer)
134
137
  ];
135
138
  const measured = await Promise.all(SPEC.map(([, text]) => measure(text)));
136
139
  const cats = SPEC.map(([label, , color], i) => ({ label, n: measured[i].n, color })).filter((c) => c.n > 0);
@@ -144,21 +147,21 @@ export const createContextCommand = () => ({
144
147
  // Right-hand info column — model, totals, then per-category usage (Claude Code's /context).
145
148
  const info = [];
146
149
  if (model) {
147
- info.push(model.split('/').pop() ?? model);
148
- info.push(paint(model, DIM));
150
+ info.push(`${RESET}${model.split('/').pop() ?? model}`);
151
+ info.push(paint(model, GREY));
149
152
  }
150
153
  if (window > 0)
151
- info.push(paint(`${mark(total)}/${fmtTok(window)} tokens (${pctStr(total, window)})`, DIM));
154
+ info.push(paint(`${mark(total)}/${fmtTok(window)} tokens (${pctStr(total, window)})`, GREY));
152
155
  info.push('');
153
- info.push(paint('Estimated usage by category', ITALIC_DIM));
156
+ info.push(`${RESET}${ITALIC}${GREY}Estimated usage by category${RESET}`);
154
157
  for (const c of cats) {
155
- info.push(`${paint(USED, c.color)} ${c.label}: ${paint(`${mark(c.n)} tokens (${pctStr(c.n, window)})`, DIM)}`);
158
+ info.push(`${paint(USED, c.color)} ${c.label}: ${paint(`${mark(c.n)} tokens (${pctStr(c.n, window)})`, GREY)}`);
156
159
  }
157
160
  if (window > 0) {
158
- info.push(`${paint(USED, BUFFER_COLOR)} Compaction buffer: ${paint(`${fmtTok(buffer)} tokens (${pctStr(buffer, window)})`, DIM)}`);
159
- info.push(`${paint(FREEG, DIM)} Free space: ${paint(`${fmtTok(free)} (${pctStr(free, window)})`, DIM)}`);
161
+ info.push(`${paint(USED, BUFFER_COLOR)} Compaction buffer: ${paint(`${fmtTok(buffer)} tokens (${pctStr(buffer, window)})`, GREY)}`);
162
+ info.push(`${paint(FREEG, GREY)} Free space: ${paint(`${fmtTok(free)} (${pctStr(free, window)})`, GREY)}`);
160
163
  }
161
- const lines = [`${BOLD}Context Usage${RESET}`];
164
+ const lines = [`${RESET}${BOLD}Context Usage${RESET}`];
162
165
  if (window > 0) {
163
166
  // Grid: category cells, then free, with the compaction buffer at the very end.
164
167
  const cellTokens = Math.max(1, window / GRID_CELLS);
@@ -170,7 +173,7 @@ export const createContextCommand = () => ({
170
173
  const bufCells = Math.min(ratio(buffer), Math.max(0, GRID_CELLS - cells.length));
171
174
  const freeCells = Math.max(0, GRID_CELLS - cells.length - bufCells);
172
175
  for (let i = 0; i < freeCells; i++)
173
- cells.push(paint(FREEG, DIM));
176
+ cells.push(paint(FREEG, GREY));
174
177
  for (let i = 0; i < bufCells; i++)
175
178
  cells.push(paint(USED, BUFFER_COLOR));
176
179
  cells.length = GRID_CELLS;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mu-harness",
3
- "version": "0.30.0",
3
+ "version": "0.32.0",
4
4
  "description": "Agent harness: createHarness wires mu-core into a host — XDG paths, model registry, plugins, disk-loaded agents & skills, sub-agents, sessions (JSONL + SQLite catalog), slash commands, permission/approval hooks, an optional scheduler, and a composable TUI chat app",
5
5
  "license": "MIT",
6
6
  "main": "./script/index.js",
@@ -23,8 +23,8 @@
23
23
  "@swc/wasm-typescript": "^1.15.0",
24
24
  "cli-highlight": "^2.1.11",
25
25
  "croner": "^9.0.0",
26
- "mu-core": "^0.30.0",
27
- "mu-tui": "^0.30.0",
26
+ "mu-core": "^0.32.0",
27
+ "mu-tui": "^0.32.0",
28
28
  "ws": "^8.18.0"
29
29
  },
30
30
  "_generatedBy": "dnt@dev",
@@ -54,14 +54,17 @@ const GRID_CELLS = GRID_COLS * GRID_ROWS;
54
54
  const GRID_WIDTH = GRID_COLS * 2 - 1; // glyphs joined by single spaces
55
55
  const USED = '⛁'; // a filled context cell (Claude Code's /context glyph)
56
56
  const FREEG = '⛶'; // a free cell
57
- const BUFFER_COLOR = '\x1b[93m'; // bright yellow the compaction reserve
58
- // ANSI SGR codes mu's TUI text utils are ANSI-aware so these render in the terminal;
59
- // the companion strips them (plain text), keeping the labelled breakdown readable.
57
+ // Truecolor SGR — distinct, readable hues (mu's TUI utils + the companion both strip/parse
58
+ // these correctly). Secondary text uses a single grey so only the category glyphs carry colour.
60
59
  const RESET = '\x1b[0m';
61
- const DIM = '\x1b[2m';
60
+ const GREY = '\x1b[38;2;153;153;153m';
62
61
  const BOLD = '\x1b[1m';
63
- const ITALIC_DIM = '\x1b[2;3m';
64
- const paint = (s, color) => `${color}${s}${RESET}`;
62
+ const ITALIC = '\x1b[3m';
63
+ const BUFFER_COLOR = '\x1b[38;2;255;193;7m'; // amber — the compaction reserve
64
+ // Reset BEFORE the colour too: the TUI note prefixes each line with a `dim` muted style,
65
+ // and a bare `\x1b[38;2;…m` only sets the foreground — it wouldn't clear the inherited dim,
66
+ // which darkened the first cell of every row. The leading reset wipes it.
67
+ const paint = (s, color) => `${RESET}${color}${s}${RESET}`;
65
68
  const fmtTok = (n) => (n >= 1e6 ? `${(n / 1e6).toFixed(1)}M` : n >= 1000 ? `${(n / 1000).toFixed(1)}k` : `${n}`);
66
69
  const pctStr = (n, w) => {
67
70
  if (w <= 0)
@@ -128,16 +131,16 @@ const createContextCommand = () => ({
128
131
  }
129
132
  return { n: estTokens(text.length), exact: false };
130
133
  };
131
- // label, text, ANSI colour one per category, in render order (descriptive labels à la Claude Code).
134
+ // label, text, truecolordistinct hues across the wheel, in render order.
132
135
  const SPEC = [
133
- ['System prompt', sys.agent, '\x1b[36m'], // cyan — the agent prompt
134
- ['Environment', sys.env, '\x1b[33m'], // yellow — the <env> block
135
- ['Instructions', sys.instructions, '\x1b[34m'], // blue — AGENTS.md / CLAUDE.md
136
- ['Memory', sys.memory, '\x1b[35m'], // magenta — MEMORY.md
137
- ['Tools', `${toolSchemas}\n${sys.toolPrompts}`, '\x1b[31m'], // red — schemas + tool prompts
138
- ['You', byRole('user'), '\x1b[32m'], // green — your messages
139
- ['Agent', byRole('assistant'), '\x1b[94m'], // bright blue — assistant replies
140
- ['Tool results', byRole('tool'), '\x1b[90m'], // grey — tool results
136
+ ['System prompt', sys.agent, '\x1b[38;2;239;108;82m'], // coral — the agent prompt
137
+ ['Environment', sys.env, '\x1b[38;2;129;199;132m'], // green — the <env> block
138
+ ['Instructions', sys.instructions, '\x1b[38;2;100;181;246m'], // blue — AGENTS.md / CLAUDE.md
139
+ ['Memory', sys.memory, '\x1b[38;2;186;104;200m'], // purple — MEMORY.md
140
+ ['Tools', `${toolSchemas}\n${sys.toolPrompts}`, '\x1b[38;2;77;182;172m'], // teal — schemas + tool prompts
141
+ ['You', byRole('user'), '\x1b[38;2;121;134;203m'], // indigo — your messages
142
+ ['Agent', byRole('assistant'), '\x1b[38;2;240;98;146m'], // pink — assistant replies
143
+ ['Tool results', byRole('tool'), '\x1b[38;2;0;188;212m'], // cyan — tool results (distinct from amber buffer)
141
144
  ];
142
145
  const measured = await Promise.all(SPEC.map(([, text]) => measure(text)));
143
146
  const cats = SPEC.map(([label, , color], i) => ({ label, n: measured[i].n, color })).filter((c) => c.n > 0);
@@ -151,21 +154,21 @@ const createContextCommand = () => ({
151
154
  // Right-hand info column — model, totals, then per-category usage (Claude Code's /context).
152
155
  const info = [];
153
156
  if (model) {
154
- info.push(model.split('/').pop() ?? model);
155
- info.push(paint(model, DIM));
157
+ info.push(`${RESET}${model.split('/').pop() ?? model}`);
158
+ info.push(paint(model, GREY));
156
159
  }
157
160
  if (window > 0)
158
- info.push(paint(`${mark(total)}/${fmtTok(window)} tokens (${pctStr(total, window)})`, DIM));
161
+ info.push(paint(`${mark(total)}/${fmtTok(window)} tokens (${pctStr(total, window)})`, GREY));
159
162
  info.push('');
160
- info.push(paint('Estimated usage by category', ITALIC_DIM));
163
+ info.push(`${RESET}${ITALIC}${GREY}Estimated usage by category${RESET}`);
161
164
  for (const c of cats) {
162
- info.push(`${paint(USED, c.color)} ${c.label}: ${paint(`${mark(c.n)} tokens (${pctStr(c.n, window)})`, DIM)}`);
165
+ info.push(`${paint(USED, c.color)} ${c.label}: ${paint(`${mark(c.n)} tokens (${pctStr(c.n, window)})`, GREY)}`);
163
166
  }
164
167
  if (window > 0) {
165
- info.push(`${paint(USED, BUFFER_COLOR)} Compaction buffer: ${paint(`${fmtTok(buffer)} tokens (${pctStr(buffer, window)})`, DIM)}`);
166
- info.push(`${paint(FREEG, DIM)} Free space: ${paint(`${fmtTok(free)} (${pctStr(free, window)})`, DIM)}`);
168
+ info.push(`${paint(USED, BUFFER_COLOR)} Compaction buffer: ${paint(`${fmtTok(buffer)} tokens (${pctStr(buffer, window)})`, GREY)}`);
169
+ info.push(`${paint(FREEG, GREY)} Free space: ${paint(`${fmtTok(free)} (${pctStr(free, window)})`, GREY)}`);
167
170
  }
168
- const lines = [`${BOLD}Context Usage${RESET}`];
171
+ const lines = [`${RESET}${BOLD}Context Usage${RESET}`];
169
172
  if (window > 0) {
170
173
  // Grid: category cells, then free, with the compaction buffer at the very end.
171
174
  const cellTokens = Math.max(1, window / GRID_CELLS);
@@ -177,7 +180,7 @@ const createContextCommand = () => ({
177
180
  const bufCells = Math.min(ratio(buffer), Math.max(0, GRID_CELLS - cells.length));
178
181
  const freeCells = Math.max(0, GRID_CELLS - cells.length - bufCells);
179
182
  for (let i = 0; i < freeCells; i++)
180
- cells.push(paint(FREEG, DIM));
183
+ cells.push(paint(FREEG, GREY));
181
184
  for (let i = 0; i < bufCells; i++)
182
185
  cells.push(paint(USED, BUFFER_COLOR));
183
186
  cells.length = GRID_CELLS;