@oh-my-pi/pi-coding-agent 10.6.1 → 11.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/CHANGELOG.md +44 -0
- package/README.md +80 -79
- package/docs/compaction.md +182 -149
- package/docs/config-usage.md +141 -78
- package/docs/custom-tools.md +45 -16
- package/docs/extension-loading.md +56 -954
- package/docs/extensions.md +192 -51
- package/docs/hooks.md +109 -70
- package/docs/python-repl.md +52 -19
- package/docs/rpc.md +43 -19
- package/docs/sdk.md +270 -211
- package/docs/session-tree-plan.md +60 -417
- package/docs/session.md +104 -39
- package/docs/skills.md +59 -95
- package/docs/theme.md +139 -110
- package/docs/tree.md +42 -33
- package/docs/tui.md +226 -80
- package/package.json +8 -9
- package/src/capability/index.ts +3 -4
- package/src/cli/args.ts +4 -4
- package/src/cli/grep-cli.ts +1 -1
- package/src/commit/agentic/index.ts +4 -3
- package/src/commit/git/index.ts +2 -3
- package/src/commit/map-reduce/index.ts +2 -1
- package/src/config/prompt-templates.ts +2 -0
- package/src/config/settings-schema.ts +30 -7
- package/src/config/settings.ts +0 -14
- package/src/config.ts +2 -2
- package/src/discovery/agents.ts +36 -0
- package/src/discovery/index.ts +1 -0
- package/src/exa/mcp-client.ts +3 -3
- package/src/ipy/executor.ts +5 -7
- package/src/ipy/gateway-coordinator.ts +1 -1
- package/src/ipy/kernel.ts +20 -15
- package/src/ipy/prelude.py +1 -1
- package/src/ipy/runtime.ts +7 -6
- package/src/lsp/lspmux.ts +3 -3
- package/src/main.ts +6 -8
- package/src/mcp/tool-bridge.ts +19 -9
- package/src/modes/components/assistant-message.ts +2 -2
- package/src/modes/components/hook-editor.ts +4 -4
- package/src/modes/components/settings-defs.ts +37 -2
- package/src/modes/components/tool-execution.ts +7 -7
- package/src/modes/controllers/command-controller.ts +2 -2
- package/src/modes/controllers/event-controller.ts +4 -7
- package/src/modes/controllers/input-controller.ts +4 -4
- package/src/modes/controllers/selector-controller.ts +1 -0
- package/src/modes/interactive-mode.ts +3 -5
- package/src/modes/rpc/rpc-mode.ts +8 -9
- package/src/patch/index.ts +6 -6
- package/src/prompts/agents/explore.md +2 -2
- package/src/prompts/agents/frontmatter.md +5 -5
- package/src/prompts/agents/plan.md +3 -2
- package/src/prompts/agents/reviewer.md +1 -1
- package/src/prompts/system/system-prompt.md +1 -3
- package/src/sdk.ts +13 -9
- package/src/session/agent-session.ts +6 -4
- package/src/session/compaction/compaction.ts +3 -3
- package/src/session/session-manager.ts +8 -9
- package/src/ssh/connection-manager.ts +4 -4
- package/src/system-prompt.ts +2 -6
- package/src/task/agents.ts +1 -1
- package/src/task/executor.ts +31 -8
- package/src/task/index.ts +14 -35
- package/src/task/omp-command.ts +3 -1
- package/src/task/output-manager.ts +20 -6
- package/src/task/parallel.ts +3 -3
- package/src/task/render.ts +16 -2
- package/src/task/types.ts +13 -20
- package/src/task/worktree.ts +3 -3
- package/src/tools/ask.ts +3 -8
- package/src/tools/fetch.ts +2 -2
- package/src/tools/gemini-image.ts +5 -6
- package/src/tools/grep.ts +5 -5
- package/src/tools/index.ts +12 -5
- package/src/tools/read.ts +1 -1
- package/src/tools/todo-write.ts +2 -3
- package/src/utils/frontmatter.ts +1 -1
- package/src/utils/image-resize.ts +1 -1
- package/src/utils/timings.ts +3 -2
- package/src/web/scrapers/github.ts +2 -2
- package/src/web/scrapers/utils.ts +2 -3
- package/src/web/scrapers/youtube.ts +2 -3
- package/src/web/search/auth.ts +5 -6
- package/src/web/search/providers/anthropic.ts +3 -2
- package/src/utils/terminal-notify.ts +0 -37
package/docs/theme.md
CHANGED
|
@@ -8,7 +8,7 @@ Themes allow you to customize the colors used throughout the coding agent TUI.
|
|
|
8
8
|
|
|
9
9
|
Every theme must define all color tokens. There are no optional colors.
|
|
10
10
|
|
|
11
|
-
### Core UI (
|
|
11
|
+
### Core UI (11 colors)
|
|
12
12
|
|
|
13
13
|
| Token | Purpose | Examples |
|
|
14
14
|
| -------------- | --------------------- | ------------------------------------ |
|
|
@@ -67,7 +67,7 @@ Note: Diff colors are specific to tool execution boxes and must work with tool b
|
|
|
67
67
|
|
|
68
68
|
### Syntax Highlighting (9 colors)
|
|
69
69
|
|
|
70
|
-
|
|
70
|
+
Used for native syntax highlighting in tool output and editors:
|
|
71
71
|
|
|
72
72
|
| Token | Purpose |
|
|
73
73
|
| ------------------- | -------------------------------- |
|
|
@@ -85,24 +85,44 @@ Future-proofing for syntax highlighting support:
|
|
|
85
85
|
|
|
86
86
|
Editor border colors that indicate the current thinking/reasoning level:
|
|
87
87
|
|
|
88
|
-
| Token | Purpose
|
|
89
|
-
| ----------------- |
|
|
90
|
-
| `thinkingOff` | Border when thinking is off (most subtle)
|
|
91
|
-
| `thinkingMinimal` | Border for minimal thinking
|
|
92
|
-
| `thinkingLow` | Border for low thinking
|
|
93
|
-
| `thinkingMedium` | Border for medium thinking
|
|
94
|
-
| `thinkingHigh` | Border for high thinking
|
|
95
|
-
| `thinkingXhigh` | Border for xhigh thinking (most prominent
|
|
88
|
+
| Token | Purpose |
|
|
89
|
+
| ----------------- | ------------------------------------------ |
|
|
90
|
+
| `thinkingOff` | Border when thinking is off (most subtle) |
|
|
91
|
+
| `thinkingMinimal` | Border for minimal thinking |
|
|
92
|
+
| `thinkingLow` | Border for low thinking |
|
|
93
|
+
| `thinkingMedium` | Border for medium thinking |
|
|
94
|
+
| `thinkingHigh` | Border for high thinking |
|
|
95
|
+
| `thinkingXhigh` | Border for xhigh thinking (most prominent) |
|
|
96
96
|
|
|
97
97
|
These create a visual hierarchy: off → minimal → low → medium → high → xhigh
|
|
98
98
|
|
|
99
|
-
###
|
|
100
|
-
|
|
101
|
-
| Token
|
|
102
|
-
|
|
|
103
|
-
| `bashMode`
|
|
104
|
-
|
|
105
|
-
|
|
99
|
+
### Mode Borders (2 colors)
|
|
100
|
+
|
|
101
|
+
| Token | Purpose |
|
|
102
|
+
| ------------ | ------------------------------------------------ |
|
|
103
|
+
| `bashMode` | Editor border color when in bash mode (! prefix) |
|
|
104
|
+
| `pythonMode` | Editor border color when in python mode (>>>) |
|
|
105
|
+
|
|
106
|
+
### Status Line (14 colors)
|
|
107
|
+
|
|
108
|
+
| Token | Purpose |
|
|
109
|
+
| --------------------- | --------------------------------------- |
|
|
110
|
+
| `statusLineBg` | Status line background |
|
|
111
|
+
| `statusLineSep` | Separators between status line segments |
|
|
112
|
+
| `statusLineModel` | Model segment text |
|
|
113
|
+
| `statusLinePath` | Working directory segment |
|
|
114
|
+
| `statusLineGitClean` | Git segment (clean) |
|
|
115
|
+
| `statusLineGitDirty` | Git segment (dirty) |
|
|
116
|
+
| `statusLineContext` | Context window usage segment |
|
|
117
|
+
| `statusLineSpend` | Token input/total segment |
|
|
118
|
+
| `statusLineStaged` | Git staged count |
|
|
119
|
+
| `statusLineDirty` | Git unstaged count |
|
|
120
|
+
| `statusLineUntracked` | Git untracked count |
|
|
121
|
+
| `statusLineOutput` | Token output/cache output segment |
|
|
122
|
+
| `statusLineCost` | Cost segment |
|
|
123
|
+
| `statusLineSubagents` | Subagent count segment |
|
|
124
|
+
|
|
125
|
+
**Total: 66 color tokens** (all required)
|
|
106
126
|
|
|
107
127
|
### HTML Export Colors (optional)
|
|
108
128
|
|
|
@@ -132,7 +152,7 @@ Themes are defined in JSON files with the following structure:
|
|
|
132
152
|
|
|
133
153
|
```json
|
|
134
154
|
{
|
|
135
|
-
"$schema": "https://raw.githubusercontent.com/can1357/oh-my-pi/main/packages/coding-agent/theme-schema.json",
|
|
155
|
+
"$schema": "https://raw.githubusercontent.com/can1357/oh-my-pi/main/packages/coding-agent/src/modes/theme/theme-schema.json",
|
|
136
156
|
"name": "my-theme",
|
|
137
157
|
"vars": {
|
|
138
158
|
"blue": "#0066cc",
|
|
@@ -151,7 +171,7 @@ Themes are defined in JSON files with the following structure:
|
|
|
151
171
|
|
|
152
172
|
## Symbols
|
|
153
173
|
|
|
154
|
-
Themes can also customize specific UI symbols (icons, separators, bullets, etc.). Use `symbols.preset` to set a theme default (overridden by
|
|
174
|
+
Themes can also customize specific UI symbols (icons, separators, bullets, etc.). Use `symbols.preset` (`unicode`, `nerd`, `ascii`) to set a theme default (overridden by the `symbolPreset` setting), and `symbols.overrides` to override individual keys.
|
|
155
175
|
|
|
156
176
|
Example:
|
|
157
177
|
|
|
@@ -175,12 +195,14 @@ Symbol keys by category:
|
|
|
175
195
|
- Tree: `tree.branch`, `tree.last`, `tree.vertical`, `tree.horizontal`, `tree.hook`
|
|
176
196
|
- Boxes (rounded): `boxRound.topLeft`, `boxRound.topRight`, `boxRound.bottomLeft`, `boxRound.bottomRight`, `boxRound.horizontal`, `boxRound.vertical`
|
|
177
197
|
- Boxes (sharp): `boxSharp.topLeft`, `boxSharp.topRight`, `boxSharp.bottomLeft`, `boxSharp.bottomRight`, `boxSharp.horizontal`, `boxSharp.vertical`, `boxSharp.cross`, `boxSharp.teeDown`, `boxSharp.teeUp`, `boxSharp.teeRight`, `boxSharp.teeLeft`
|
|
178
|
-
- Separators: `sep.powerline`, `sep.powerlineThin`, `sep.powerlineLeft`, `sep.powerlineRight`, `sep.powerlineThinLeft`, `sep.powerlineThinRight`, `sep.dot`, `sep.slash`, `sep.pipe`
|
|
179
|
-
- Icons: `icon.model`, `icon.folder`, `icon.file`, `icon.git`, `icon.branch`, `icon.tokens`, `icon.context`, `icon.cost`, `icon.time`, `icon.pi`, `icon.agents`, `icon.cache`, `icon.input`, `icon.output`, `icon.host`, `icon.session`, `icon.package`, `icon.warning`, `icon.rewind`, `icon.auto`, `icon.extensionSkill`, `icon.extensionTool`, `icon.extensionSlashCommand`, `icon.extensionMcp`, `icon.extensionRule`, `icon.extensionHook`, `icon.extensionPrompt`, `icon.extensionContextFile`, `icon.extensionInstruction`
|
|
198
|
+
- Separators: `sep.powerline`, `sep.powerlineThin`, `sep.powerlineLeft`, `sep.powerlineRight`, `sep.powerlineThinLeft`, `sep.powerlineThinRight`, `sep.block`, `sep.space`, `sep.asciiLeft`, `sep.asciiRight`, `sep.dot`, `sep.slash`, `sep.pipe`
|
|
199
|
+
- Icons: `icon.model`, `icon.plan`, `icon.folder`, `icon.file`, `icon.git`, `icon.branch`, `icon.tokens`, `icon.context`, `icon.cost`, `icon.time`, `icon.pi`, `icon.agents`, `icon.cache`, `icon.input`, `icon.output`, `icon.host`, `icon.session`, `icon.package`, `icon.warning`, `icon.rewind`, `icon.auto`, `icon.extensionSkill`, `icon.extensionTool`, `icon.extensionSlashCommand`, `icon.extensionMcp`, `icon.extensionRule`, `icon.extensionHook`, `icon.extensionPrompt`, `icon.extensionContextFile`, `icon.extensionInstruction`
|
|
180
200
|
- Thinking: `thinking.minimal`, `thinking.low`, `thinking.medium`, `thinking.high`, `thinking.xhigh`
|
|
181
201
|
- Checkboxes: `checkbox.checked`, `checkbox.unchecked`
|
|
182
|
-
- Formatting: `format.bullet`, `format.dash`
|
|
202
|
+
- Formatting: `format.bullet`, `format.dash`, `format.bracketLeft`, `format.bracketRight`
|
|
183
203
|
- Markdown: `md.quoteBorder`, `md.hrChar`, `md.bullet`
|
|
204
|
+
- Language icons: `lang.default`, `lang.typescript`, `lang.javascript`, `lang.python`, `lang.rust`, `lang.go`, `lang.java`, `lang.c`, `lang.cpp`, `lang.csharp`, `lang.ruby`, `lang.php`, `lang.swift`, `lang.kotlin`, `lang.shell`, `lang.html`, `lang.css`, `lang.json`, `lang.yaml`, `lang.markdown`, `lang.sql`, `lang.docker`, `lang.lua`, `lang.text`, `lang.env`, `lang.toml`, `lang.xml`, `lang.ini`, `lang.conf`, `lang.log`, `lang.csv`, `lang.tsv`, `lang.image`, `lang.pdf`, `lang.archive`, `lang.binary`
|
|
205
|
+
- Settings tabs: `tab.display`, `tab.agent`, `tab.input`, `tab.tools`, `tab.config`, `tab.services`, `tab.bash`, `tab.lsp`, `tab.ttsr`, `tab.status`
|
|
184
206
|
|
|
185
207
|
### Color Values
|
|
186
208
|
|
|
@@ -238,55 +260,47 @@ This is useful for:
|
|
|
238
260
|
|
|
239
261
|
## Built-in Themes
|
|
240
262
|
|
|
241
|
-
OMP
|
|
242
|
-
|
|
243
|
-
### `dark` (default)
|
|
263
|
+
OMP ships with `dark` (default), `light`, and 90+ curated themes under `src/modes/theme/defaults/`. Examples include:
|
|
244
264
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
Optimized for light terminal backgrounds with darker, muted colors.
|
|
265
|
+
- **Dark themes**: `dark-aurora`, `dark-gruvbox`, `dark-nord`, `dark-tokyo-night`, `dark-catppuccin`, `dark-dracula`, `dark-solarized`, `dark-github`, `dark-monokai`, `dark-synthwave`
|
|
266
|
+
- **Light themes**: `light-solarized`, `light-gruvbox`, `light-github`, `light-catppuccin`, `light-paper`, `light-dawn`, `light-frost`
|
|
267
|
+
- **Neutral/material**: `graphite`, `obsidian`, `onyx`, `titanium`, `marble`, `pearl`, `alabaster`, `anthracite`
|
|
250
268
|
|
|
251
269
|
## Selecting a Theme
|
|
252
270
|
|
|
253
|
-
Themes are configured in the
|
|
271
|
+
Themes are configured in the Settings UI (Display → Theme) or via the config CLI:
|
|
254
272
|
|
|
255
|
-
```
|
|
256
|
-
|
|
257
|
-
"theme": "dark"
|
|
258
|
-
}
|
|
273
|
+
```bash
|
|
274
|
+
omp config set theme dark
|
|
259
275
|
```
|
|
260
276
|
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
On first run, OMP detects your terminal's background and sets a sensible default (`dark` or `light`).
|
|
277
|
+
On first run, OMP uses the terminal background reported by `COLORFGBG` and falls back to `dark` if unavailable.
|
|
264
278
|
|
|
265
279
|
## Custom Themes
|
|
266
280
|
|
|
267
281
|
### Theme Locations
|
|
268
282
|
|
|
269
|
-
Custom themes are loaded from `~/.omp/agent/themes/*.json
|
|
283
|
+
Custom themes are loaded from `~/.omp/agent/themes/*.json` by default, or from `$PI_CODING_AGENT_DIR/themes` if that environment variable is set.
|
|
270
284
|
|
|
271
285
|
### Creating a Custom Theme
|
|
272
286
|
|
|
273
287
|
1. **Create theme directory:**
|
|
274
288
|
|
|
275
289
|
```bash
|
|
276
|
-
mkdir -p
|
|
290
|
+
mkdir -p "${PI_CODING_AGENT_DIR:-~/.omp/agent}/themes"
|
|
277
291
|
```
|
|
278
292
|
|
|
279
293
|
2. **Create theme file:**
|
|
280
294
|
|
|
281
295
|
```bash
|
|
282
|
-
vim
|
|
296
|
+
vim "${PI_CODING_AGENT_DIR:-~/.omp/agent}/themes/my-theme.json"
|
|
283
297
|
```
|
|
284
298
|
|
|
285
|
-
3. **Define all colors:**
|
|
299
|
+
3. **Define all colors (see the schema for the full list; snippet below shows structure):**
|
|
286
300
|
|
|
287
301
|
```json
|
|
288
302
|
{
|
|
289
|
-
"$schema": "https://raw.githubusercontent.com/can1357/oh-my-pi/main/packages/coding-agent/theme-schema.json",
|
|
303
|
+
"$schema": "https://raw.githubusercontent.com/can1357/oh-my-pi/main/packages/coding-agent/src/modes/theme/theme-schema.json",
|
|
290
304
|
"name": "my-theme",
|
|
291
305
|
"vars": {
|
|
292
306
|
"primary": "#00aaff",
|
|
@@ -309,7 +323,9 @@ Custom themes are loaded from `~/.omp/agent/themes/*.json`.
|
|
|
309
323
|
"toolPendingBg": "#1e1e2e",
|
|
310
324
|
"toolSuccessBg": "#1e2e1e",
|
|
311
325
|
"toolErrorBg": "#2e1e1e",
|
|
312
|
-
"
|
|
326
|
+
"toolTitle": "",
|
|
327
|
+
"toolOutput": "",
|
|
328
|
+
// ...
|
|
313
329
|
|
|
314
330
|
"mdHeading": "#ffaa00",
|
|
315
331
|
"mdLink": "primary",
|
|
@@ -339,14 +355,16 @@ Custom themes are loaded from `~/.omp/agent/themes/*.json`.
|
|
|
339
355
|
"thinkingMinimal": "primary",
|
|
340
356
|
"thinkingLow": "#00aaff",
|
|
341
357
|
"thinkingMedium": "#00ffff",
|
|
342
|
-
"thinkingHigh": "#ff00ff"
|
|
358
|
+
"thinkingHigh": "#ff00ff",
|
|
359
|
+
"thinkingXhigh": "#ff88ff"
|
|
360
|
+
// ... plus bashMode, pythonMode, statusLine* colors
|
|
343
361
|
}
|
|
344
362
|
}
|
|
345
363
|
```
|
|
346
364
|
|
|
347
365
|
4. **Select your theme:**
|
|
348
|
-
- Use
|
|
349
|
-
- Or
|
|
366
|
+
- Use the Settings UI (Display → Theme)
|
|
367
|
+
- Or run `omp config set theme my-theme`
|
|
350
368
|
|
|
351
369
|
## Tips
|
|
352
370
|
|
|
@@ -367,7 +385,7 @@ Custom themes are loaded from `~/.omp/agent/themes/*.json`.
|
|
|
367
385
|
### Color Harmony
|
|
368
386
|
|
|
369
387
|
- Start with a base palette (e.g., Nord, Gruvbox, Tokyo Night)
|
|
370
|
-
- Define your palette in `
|
|
388
|
+
- Define your palette in `vars`
|
|
371
389
|
- Reference colors consistently
|
|
372
390
|
|
|
373
391
|
### Testing
|
|
@@ -444,51 +462,56 @@ Example usage:
|
|
|
444
462
|
|
|
445
463
|
### Terminal Compatibility
|
|
446
464
|
|
|
447
|
-
OMP
|
|
465
|
+
OMP prefers 24-bit RGB colors (`\x1b[38;2;R;G;Bm`) and assumes truecolor on modern terminals.
|
|
448
466
|
|
|
449
|
-
|
|
450
|
-
- ✅ Windows Terminal
|
|
451
|
-
- ✅ VS Code integrated terminal
|
|
452
|
-
- ✅ Modern GNOME Terminal, Konsole
|
|
467
|
+
Color mode detection:
|
|
453
468
|
|
|
454
|
-
|
|
469
|
+
- `COLORTERM=truecolor|24bit` or `WT_SESSION` → truecolor
|
|
470
|
+
- `TERM=dumb`, `TERM=linux`, or empty `TERM` → 256-color fallback
|
|
471
|
+
- Otherwise → truecolor
|
|
455
472
|
|
|
456
|
-
|
|
473
|
+
If you need to confirm terminal hints:
|
|
457
474
|
|
|
458
475
|
```bash
|
|
459
|
-
echo $COLORTERM
|
|
476
|
+
echo $COLORTERM
|
|
460
477
|
```
|
|
461
478
|
|
|
462
479
|
## Example Themes
|
|
463
480
|
|
|
464
481
|
See the built-in themes for complete examples:
|
|
465
482
|
|
|
466
|
-
- [Dark theme](../src/
|
|
467
|
-
- [Light theme](../src/
|
|
483
|
+
- [Dark theme](../src/modes/theme/dark.json)
|
|
484
|
+
- [Light theme](../src/modes/theme/light.json)
|
|
485
|
+
- [Defaults library](../src/modes/theme/defaults)
|
|
468
486
|
|
|
469
487
|
## Schema Validation
|
|
470
488
|
|
|
471
|
-
Themes are validated on load using [TypeBox](https://github.com/sinclairzx81/typebox)
|
|
489
|
+
Themes are validated on load using [TypeBox](https://github.com/sinclairzx81/typebox) and the TypeBox compiler.
|
|
472
490
|
|
|
473
491
|
Invalid themes will show an error with details about what's wrong:
|
|
474
492
|
|
|
475
493
|
```
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
494
|
+
Invalid theme "my-theme":
|
|
495
|
+
|
|
496
|
+
Missing required color tokens:
|
|
497
|
+
- mdHeading
|
|
498
|
+
- mdLink
|
|
499
|
+
|
|
500
|
+
Other errors:
|
|
501
|
+
- /colors/accent: Expected union value
|
|
479
502
|
```
|
|
480
503
|
|
|
481
504
|
For editor support, the JSON schema is available at:
|
|
482
505
|
|
|
483
506
|
```
|
|
484
|
-
https://raw.githubusercontent.com/can1357/oh-my-pi/main/packages/coding-agent/theme-schema.json
|
|
507
|
+
https://raw.githubusercontent.com/can1357/oh-my-pi/main/packages/coding-agent/src/modes/theme/theme-schema.json
|
|
485
508
|
```
|
|
486
509
|
|
|
487
510
|
Add to your theme file for auto-completion and validation:
|
|
488
511
|
|
|
489
512
|
```json
|
|
490
513
|
{
|
|
491
|
-
"$schema": "https://raw.githubusercontent.com/can1357/oh-my-pi/main/packages/coding-agent/theme-schema.json",
|
|
514
|
+
"$schema": "https://raw.githubusercontent.com/can1357/oh-my-pi/main/packages/coding-agent/src/modes/theme/theme-schema.json",
|
|
492
515
|
...
|
|
493
516
|
}
|
|
494
517
|
```
|
|
@@ -511,6 +534,30 @@ class Theme {
|
|
|
511
534
|
bold(text: string): string;
|
|
512
535
|
italic(text: string): string;
|
|
513
536
|
underline(text: string): string;
|
|
537
|
+
strikethrough(text: string): string;
|
|
538
|
+
inverse(text: string): string;
|
|
539
|
+
|
|
540
|
+
// Raw ANSI codes (for composing with other formatters)
|
|
541
|
+
getFgAnsi(color: ThemeColor): string;
|
|
542
|
+
getBgAnsi(color: ThemeBg): string;
|
|
543
|
+
|
|
544
|
+
// Symbol access
|
|
545
|
+
symbol(key: SymbolKey): string;
|
|
546
|
+
styledSymbol(key: SymbolKey, color: ThemeColor): string;
|
|
547
|
+
getSymbolPreset(): SymbolPreset;
|
|
548
|
+
|
|
549
|
+
// Category accessors (return grouped symbol objects)
|
|
550
|
+
get status(): { success, error, warning, ... };
|
|
551
|
+
get nav(): { cursor, selected, expand, collapse, back };
|
|
552
|
+
get icon(): { model, folder, file, git, ... };
|
|
553
|
+
get boxRound(): { topLeft, topRight, ... };
|
|
554
|
+
get boxSharp(): { topLeft, topRight, ... };
|
|
555
|
+
get sep(): { powerline, dot, slash, pipe, ... };
|
|
556
|
+
get thinking(): { minimal, low, medium, high, xhigh };
|
|
557
|
+
get spinnerFrames(): string[];
|
|
558
|
+
|
|
559
|
+
// Language icon lookup
|
|
560
|
+
getLangIcon(lang: string | undefined): string;
|
|
514
561
|
}
|
|
515
562
|
```
|
|
516
563
|
|
|
@@ -522,9 +569,13 @@ The active theme is available as a global singleton in `coding-agent`:
|
|
|
522
569
|
// theme.ts
|
|
523
570
|
export let theme: Theme;
|
|
524
571
|
|
|
525
|
-
export function
|
|
526
|
-
|
|
527
|
-
|
|
572
|
+
export async function initTheme(
|
|
573
|
+
themeName?: string,
|
|
574
|
+
enableWatcher?: boolean,
|
|
575
|
+
symbolPreset?: SymbolPreset,
|
|
576
|
+
colorBlindMode?: boolean
|
|
577
|
+
): Promise<void>;
|
|
578
|
+
export async function setTheme(name: string, enableWatcher?: boolean): Promise<{ success: boolean; error?: string }>;
|
|
528
579
|
|
|
529
580
|
// Usage throughout coding-agent
|
|
530
581
|
import { theme } from "./theme.js";
|
|
@@ -554,51 +605,46 @@ export interface MarkdownTheme {
|
|
|
554
605
|
italic: (text: string) => string;
|
|
555
606
|
strikethrough: (text: string) => string;
|
|
556
607
|
underline: (text: string) => string;
|
|
608
|
+
highlightCode?: (code: string, lang?: string) => string[];
|
|
609
|
+
getMermaidImage?: (sourceHash: string) => MermaidImage | null;
|
|
610
|
+
symbols: SymbolTheme;
|
|
557
611
|
}
|
|
558
612
|
```
|
|
559
613
|
|
|
560
|
-
The `coding-agent`
|
|
614
|
+
The `coding-agent` bridges the theme to TUI components via exported helpers:
|
|
561
615
|
|
|
562
616
|
```typescript
|
|
563
|
-
//
|
|
564
|
-
|
|
565
|
-
import { Markdown } from "@oh-my-pi/pi-tui";
|
|
566
|
-
|
|
567
|
-
// Helper to create markdown theme functions
|
|
568
|
-
function getMarkdownTheme(): MarkdownTheme {
|
|
617
|
+
// Exported helper in theme.ts
|
|
618
|
+
export function getMarkdownTheme(): MarkdownTheme {
|
|
569
619
|
return {
|
|
570
620
|
heading: (text) => theme.fg("mdHeading", text),
|
|
571
621
|
link: (text) => theme.fg("mdLink", text),
|
|
572
|
-
|
|
573
|
-
code: (text) => theme.fg("mdCode", text),
|
|
574
|
-
codeBlock: (text) => theme.fg("mdCodeBlock", text),
|
|
575
|
-
codeBlockBorder: (text) => theme.fg("mdCodeBlockBorder", text),
|
|
576
|
-
quote: (text) => theme.fg("mdQuote", text),
|
|
577
|
-
quoteBorder: (text) => theme.fg("mdQuoteBorder", text),
|
|
578
|
-
hr: (text) => theme.fg("mdHr", text),
|
|
579
|
-
listBullet: (text) => theme.fg("mdListBullet", text),
|
|
622
|
+
// ... all color mappings ...
|
|
580
623
|
bold: (text) => theme.bold(text),
|
|
581
624
|
italic: (text) => theme.italic(text),
|
|
582
625
|
underline: (text) => theme.underline(text),
|
|
583
626
|
strikethrough: (text) => chalk.strikethrough(text),
|
|
627
|
+
symbols: getSymbolTheme(),
|
|
628
|
+
getMermaidImage,
|
|
629
|
+
highlightCode: (code, lang) => {
|
|
630
|
+
/* uses native syntax highlighter */
|
|
631
|
+
},
|
|
584
632
|
};
|
|
585
633
|
}
|
|
586
|
-
|
|
587
|
-
// Create markdown with theme
|
|
588
|
-
const md = new Markdown(text, 1, 1, getMarkdownTheme(), { bgColor: theme.bg("userMessageBg") });
|
|
589
634
|
```
|
|
590
635
|
|
|
591
636
|
This approach:
|
|
592
637
|
|
|
593
638
|
- Keeps TUI components theme-agnostic (reusable in other projects)
|
|
594
639
|
- Maintains type safety via interfaces
|
|
595
|
-
- Allows components to have sensible defaults if no theme provided
|
|
596
640
|
- Centralizes theme access in `coding-agent`
|
|
597
641
|
|
|
642
|
+
Similar helpers exist for other TUI components: `getSelectListTheme()`, `getEditorTheme()`, `getSettingsListTheme()`, `getSymbolTheme()`.
|
|
643
|
+
|
|
598
644
|
**Example usage:**
|
|
599
645
|
|
|
600
646
|
```typescript
|
|
601
|
-
|
|
647
|
+
await initTheme("dark");
|
|
602
648
|
|
|
603
649
|
// Apply foreground colors
|
|
604
650
|
theme.fg("accent", "Selected");
|
|
@@ -620,9 +666,9 @@ const userMsg = theme.bg("userMessageBg", theme.fg("userMessageText", "Hello"));
|
|
|
620
666
|
**Color resolution:**
|
|
621
667
|
|
|
622
668
|
1. **Detect terminal capabilities:**
|
|
623
|
-
-
|
|
624
|
-
-
|
|
625
|
-
-
|
|
669
|
+
- `COLORTERM=truecolor|24bit` or `WT_SESSION` → truecolor
|
|
670
|
+
- `TERM=dumb`, `TERM=linux`, or empty `TERM` → 256-color
|
|
671
|
+
- Otherwise → truecolor
|
|
626
672
|
|
|
627
673
|
2. **Load JSON theme file**
|
|
628
674
|
|
|
@@ -641,26 +687,9 @@ const userMsg = theme.bg("userMessageBg", theme.fg("userMessageText", "Hello"));
|
|
|
641
687
|
```
|
|
642
688
|
|
|
643
689
|
4. **Convert colors to ANSI codes based on terminal capability:**
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
- Hex (
|
|
647
|
-
- 256-color (`42`) → `\x1b[38;5;42m` (keep as-is)
|
|
648
|
-
- Empty string (`""`) → `\x1b[39m`
|
|
649
|
-
|
|
650
|
-
**256-color mode:**
|
|
651
|
-
- Hex (`"#ff0000"`) → convert to nearest RGB cube color → `\x1b[38;5;196m`
|
|
652
|
-
- 256-color (`42`) → `\x1b[38;5;42m` (keep as-is)
|
|
653
|
-
- Empty string (`""`) → `\x1b[39m`
|
|
654
|
-
|
|
655
|
-
**Hex to 256-color conversion:**
|
|
656
|
-
|
|
657
|
-
```typescript
|
|
658
|
-
// Convert RGB to 6x6x6 cube (colors 16-231)
|
|
659
|
-
r_index = Math.round((r / 255) * 5);
|
|
660
|
-
g_index = Math.round((g / 255) * 5);
|
|
661
|
-
b_index = Math.round((b / 255) * 5);
|
|
662
|
-
color_index = 16 + 36 * r_index + 6 * g_index + b_index;
|
|
663
|
-
```
|
|
690
|
+
- Empty string (`""`) → terminal default (foreground/background reset)
|
|
691
|
+
- 256-color (`42`) → `\x1b[38;5;42m` / `\x1b[48;5;42m`
|
|
692
|
+
- Hex or resolved vars → `Bun.color(value, "ansi-16m" | "ansi-256")`
|
|
664
693
|
|
|
665
694
|
5. **Cache as `Theme` instance**
|
|
666
695
|
|
package/docs/tree.md
CHANGED
|
@@ -20,10 +20,9 @@ Sessions are stored as trees where each entry has an `id` and `parentId`. The "l
|
|
|
20
20
|
```
|
|
21
21
|
├─ user: "Hello, can you help..."
|
|
22
22
|
│ └─ assistant: "Of course! I can..."
|
|
23
|
-
│ ├─ user: "Let's try approach A..."
|
|
24
|
-
│ │ └─ assistant: "For approach A..."
|
|
25
|
-
│ │ └─ [
|
|
26
|
-
│ │ └─ user: "That worked..." ← active
|
|
23
|
+
│ ├─ • user: "Let's try approach A..."
|
|
24
|
+
│ │ └─ • assistant: "For approach A..."
|
|
25
|
+
│ │ └─ • [label-name] user: "That worked..."
|
|
27
26
|
│ └─ user: "Actually, approach B..."
|
|
28
27
|
│ └─ assistant: "For approach B..."
|
|
29
28
|
```
|
|
@@ -32,18 +31,25 @@ Sessions are stored as trees where each entry has an `id` and `parentId`. The "l
|
|
|
32
31
|
|
|
33
32
|
| Key | Action |
|
|
34
33
|
|-----|--------|
|
|
35
|
-
| ↑/↓ |
|
|
34
|
+
| ↑/↓ | Move selection |
|
|
35
|
+
| ←/→ | Page up/down |
|
|
36
36
|
| Enter | Select node |
|
|
37
|
-
| Escape
|
|
38
|
-
| Ctrl+
|
|
39
|
-
| Ctrl+O
|
|
37
|
+
| Escape | Clear search (if active) or cancel |
|
|
38
|
+
| Ctrl+C | Cancel |
|
|
39
|
+
| Ctrl+O / Shift+Ctrl+O | Cycle filter forward/back |
|
|
40
|
+
| Alt+D/T/U/L/A | Set filter: default / no-tools / user-only / labeled-only / all |
|
|
41
|
+
| Shift+L | Edit label for selected entry |
|
|
42
|
+
| Type | Search (space-separated tokens) |
|
|
43
|
+
| Backspace | Remove last search character |
|
|
40
44
|
|
|
41
45
|
### Display
|
|
42
46
|
|
|
43
|
-
-
|
|
44
|
-
-
|
|
45
|
-
- Labels shown inline: `[label-name]`
|
|
46
|
-
- Default filter hides `label` and `
|
|
47
|
+
- Tree list height: `max(5, floor(terminalHeight / 2))` lines
|
|
48
|
+
- Active path marked with a bullet (`•`) before each entry (current leaf is last node on the path)
|
|
49
|
+
- Labels shown inline: `[label-name]` before the entry text
|
|
50
|
+
- Default filter hides `label`, `custom`, `model_change`, and `thinking_level_change` entries
|
|
51
|
+
- Assistant messages with only tool calls are hidden unless they contain errors/aborts (current leaf is always shown)
|
|
52
|
+
- `no-tools` filter hides tool result messages
|
|
47
53
|
- Children sorted by timestamp (oldest first)
|
|
48
54
|
|
|
49
55
|
## Selection Behavior
|
|
@@ -66,7 +72,11 @@ If user selects the very first message (has no parent):
|
|
|
66
72
|
|
|
67
73
|
## Branch Summarization
|
|
68
74
|
|
|
69
|
-
|
|
75
|
+
If branch summaries are enabled (`branchSummary.enabled`), the user is prompted:
|
|
76
|
+
|
|
77
|
+
- No summary
|
|
78
|
+
- Summarize
|
|
79
|
+
- Summarize with custom prompt (passed as `customInstructions`)
|
|
70
80
|
|
|
71
81
|
### What Gets Summarized
|
|
72
82
|
|
|
@@ -79,9 +89,8 @@ A → B → C → D → E → F ← old leaf
|
|
|
79
89
|
|
|
80
90
|
Abandoned path: D → E → F (summarized)
|
|
81
91
|
|
|
82
|
-
Summarization stops at
|
|
83
|
-
|
|
84
|
-
2. Compaction node (if encountered first)
|
|
92
|
+
Summarization stops at the common ancestor only.
|
|
93
|
+
Compaction and branch summary entries are included; tool results are ignored.
|
|
85
94
|
|
|
86
95
|
### Summary Storage
|
|
87
96
|
|
|
@@ -91,11 +100,12 @@ Stored as `BranchSummaryEntry`:
|
|
|
91
100
|
interface BranchSummaryEntry {
|
|
92
101
|
type: "branch_summary";
|
|
93
102
|
id: string;
|
|
94
|
-
parentId: string;
|
|
103
|
+
parentId: string | null; // New leaf position (null when navigating to root)
|
|
95
104
|
timestamp: string;
|
|
96
|
-
fromId: string; //
|
|
105
|
+
fromId: string; // Entry the summary is attached to ("root" if null)
|
|
97
106
|
summary: string; // LLM-generated summary
|
|
98
107
|
details?: unknown; // Optional hook data
|
|
108
|
+
fromExtension?: boolean;
|
|
99
109
|
}
|
|
100
110
|
```
|
|
101
111
|
|
|
@@ -107,34 +117,33 @@ interface BranchSummaryEntry {
|
|
|
107
117
|
async navigateTree(
|
|
108
118
|
targetId: string,
|
|
109
119
|
options?: { summarize?: boolean; customInstructions?: string }
|
|
110
|
-
): Promise<{ editorText?: string; cancelled: boolean }>
|
|
120
|
+
): Promise<{ editorText?: string; cancelled: boolean; aborted?: boolean; summaryEntry?: BranchSummaryEntry }>
|
|
111
121
|
```
|
|
112
122
|
|
|
113
123
|
Flow:
|
|
114
124
|
1. Validate target, check no-op (target === current leaf)
|
|
115
125
|
2. Find common ancestor between old leaf and target
|
|
116
|
-
3. Collect entries to summarize (if requested)
|
|
126
|
+
3. Collect entries to summarize (if requested, includes compaction entries)
|
|
117
127
|
4. Fire `session_before_tree` event (hook can cancel or provide summary)
|
|
118
|
-
5. Run default summarizer if needed
|
|
128
|
+
5. Run default summarizer if needed (respects `customInstructions`)
|
|
119
129
|
6. Switch leaf via `branch()` or `branchWithSummary()`
|
|
120
130
|
7. Update agent: `agent.replaceMessages(sessionManager.buildSessionContext().messages)`
|
|
121
|
-
8. Fire `session_tree` event
|
|
122
|
-
9.
|
|
123
|
-
10. Return result with `editorText` if user message was selected
|
|
131
|
+
8. Fire `session_tree` event (includes `summaryEntry`/`fromExtension` when applicable)
|
|
132
|
+
9. Return result with `editorText` if user message was selected
|
|
124
133
|
|
|
125
134
|
### SessionManager
|
|
126
135
|
|
|
127
|
-
- `
|
|
136
|
+
- `getLeafId(): string | null` - Current leaf (null if empty)
|
|
128
137
|
- `resetLeaf(): void` - Set leaf to null (for root user message navigation)
|
|
129
138
|
- `getTree(): SessionTreeNode[]` - Full tree with children sorted by timestamp
|
|
130
139
|
- `branch(id)` - Change leaf pointer
|
|
131
|
-
- `branchWithSummary(id, summary)` - Change leaf and create summary entry
|
|
140
|
+
- `branchWithSummary(id: string | null, summary, details?, fromExtension?)` - Change leaf and create summary entry
|
|
132
141
|
|
|
133
142
|
### InteractiveMode
|
|
134
143
|
|
|
135
144
|
`/tree` command shows `TreeSelectorComponent`, then:
|
|
136
|
-
1.
|
|
137
|
-
2. Call `session.navigateTree()`
|
|
145
|
+
1. If `branchSummary.enabled`, prompt for summary type (including custom prompt)
|
|
146
|
+
2. Call `session.navigateTree()` with `summarize`/`customInstructions`
|
|
138
147
|
3. Clear and re-render chat
|
|
139
148
|
4. Set editor text if applicable
|
|
140
149
|
|
|
@@ -154,7 +163,6 @@ interface TreePreparation {
|
|
|
154
163
|
interface SessionBeforeTreeEvent {
|
|
155
164
|
type: "session_before_tree";
|
|
156
165
|
preparation: TreePreparation;
|
|
157
|
-
model: Model;
|
|
158
166
|
signal: AbortSignal;
|
|
159
167
|
}
|
|
160
168
|
|
|
@@ -172,7 +180,7 @@ interface SessionTreeEvent {
|
|
|
172
180
|
newLeafId: string | null;
|
|
173
181
|
oldLeafId: string | null;
|
|
174
182
|
summaryEntry?: BranchSummaryEntry;
|
|
175
|
-
|
|
183
|
+
fromExtension?: boolean;
|
|
176
184
|
}
|
|
177
185
|
```
|
|
178
186
|
|
|
@@ -192,6 +200,7 @@ export default function(pi: HookAPI) {
|
|
|
192
200
|
|
|
193
201
|
## Error Handling
|
|
194
202
|
|
|
195
|
-
- Summarization failure:
|
|
196
|
-
-
|
|
197
|
-
- Hook returns `cancel: true`:
|
|
203
|
+
- Summarization failure: navigation is cancelled and the caller shows the error
|
|
204
|
+
- Escape during summarization: returns `{ cancelled: true, aborted: true }` and the selector reopens
|
|
205
|
+
- Hook returns `cancel: true`: navigation is cancelled (caller decides UI)
|
|
206
|
+
- Escape in the tree selector clears search first, then cancels if empty
|