@oh-my-pi/pi-coding-agent 10.6.2 → 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/extensions.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
>
|
|
1
|
+
> omp can create extensions. Ask it to build one for your use case.
|
|
2
2
|
|
|
3
3
|
# Extensions
|
|
4
4
|
|
|
5
|
-
Extensions are TypeScript modules that extend
|
|
5
|
+
Extensions are TypeScript modules that extend omp's behavior. They can subscribe to lifecycle events, register custom tools callable by the LLM, add commands, and more.
|
|
6
6
|
|
|
7
7
|
**Key capabilities:**
|
|
8
8
|
|
|
@@ -23,7 +23,6 @@ Extensions are TypeScript modules that extend pi's behavior. They can subscribe
|
|
|
23
23
|
- Interactive tools (questions, wizards, custom dialogs)
|
|
24
24
|
- Stateful tools (todo lists, connection pools)
|
|
25
25
|
- External integrations (file watchers, webhooks, CI triggers)
|
|
26
|
-
- Games while you wait (see `snake.ts` example)
|
|
27
26
|
|
|
28
27
|
See [examples/extensions/](../examples/extensions/) for working implementations.
|
|
29
28
|
|
|
@@ -38,6 +37,8 @@ See [examples/extensions/](../examples/extensions/) for working implementations.
|
|
|
38
37
|
- [Lifecycle Overview](#lifecycle-overview)
|
|
39
38
|
- [Session Events](#session-events)
|
|
40
39
|
- [Agent Events](#agent-events)
|
|
40
|
+
- [Input Events](#input-events)
|
|
41
|
+
- [User Bash/Python Events](#user-bashpython-events)
|
|
41
42
|
- [Tool Events](#tool-events)
|
|
42
43
|
- [ExtensionContext](#extensioncontext)
|
|
43
44
|
- [ExtensionCommandContext](#extensioncommandcontext)
|
|
@@ -98,22 +99,24 @@ export default function (pi: ExtensionAPI) {
|
|
|
98
99
|
Test with `--extension` (or `-e`) flag:
|
|
99
100
|
|
|
100
101
|
```bash
|
|
101
|
-
|
|
102
|
+
omp -e ./my-extension.ts
|
|
102
103
|
```
|
|
103
104
|
|
|
104
105
|
## Extension Locations
|
|
105
106
|
|
|
106
107
|
Extensions are auto-discovered from:
|
|
107
108
|
|
|
108
|
-
| Location
|
|
109
|
-
|
|
|
110
|
-
| `~/.omp/agent/extensions/*.ts`
|
|
111
|
-
| `~/.omp/agent/extensions/*/index.ts` | Global (subdirectory) |
|
|
112
|
-
| `.omp/extensions/*.ts`
|
|
113
|
-
| `.omp/extensions/*/index.ts`
|
|
109
|
+
| Location | Scope |
|
|
110
|
+
| ---------------------------------------- | ---------------------------- |
|
|
111
|
+
| `~/.omp/agent/extensions/*.{ts,js}` | Global (all projects) |
|
|
112
|
+
| `~/.omp/agent/extensions/*/index.{ts,js}` | Global (subdirectory) |
|
|
113
|
+
| `.omp/extensions/*.{ts,js}` | Project-local |
|
|
114
|
+
| `.omp/extensions/*/index.{ts,js}` | Project-local (subdirectory) |
|
|
114
115
|
|
|
115
116
|
Legacy `.pi` directories are supported as aliases for the `.omp` paths above.
|
|
116
117
|
|
|
118
|
+
`settings.json` lives in `~/.omp/agent/settings.json` (user) or `.omp/settings.json` (project).
|
|
119
|
+
|
|
117
120
|
Additional paths via `settings.json`:
|
|
118
121
|
|
|
119
122
|
```json
|
|
@@ -125,9 +128,11 @@ Additional paths via `settings.json`:
|
|
|
125
128
|
**Discovery rules:**
|
|
126
129
|
|
|
127
130
|
1. **Direct files:** `extensions/*.ts` or `*.js` → loaded directly
|
|
128
|
-
2. **Subdirectory with index:** `extensions/myext/index.ts` → loaded as single extension
|
|
131
|
+
2. **Subdirectory with index:** `extensions/myext/index.ts` or `index.js` → loaded as single extension
|
|
129
132
|
3. **Subdirectory with package.json:** `extensions/myext/package.json` with `"omp"` field (legacy `"pi"` supported) → loads declared paths
|
|
130
133
|
|
|
134
|
+
Discovery only recurses one level under `extensions/`. Deeper entry points must be listed in the manifest.
|
|
135
|
+
|
|
131
136
|
```
|
|
132
137
|
~/.omp/agent/extensions/
|
|
133
138
|
├── simple.ts # Direct file (auto-discovered)
|
|
@@ -157,7 +162,7 @@ Additional paths via `settings.json`:
|
|
|
157
162
|
The `package.json` approach enables:
|
|
158
163
|
|
|
159
164
|
- Multiple extensions from one package
|
|
160
|
-
- Third-party
|
|
165
|
+
- Third-party dependencies resolved via Bun's module loader
|
|
161
166
|
- Nested source structure (no depth limit within the package)
|
|
162
167
|
- Deployment to and installation from npm
|
|
163
168
|
|
|
@@ -170,7 +175,13 @@ The `package.json` approach enables:
|
|
|
170
175
|
| `@oh-my-pi/pi-ai` | AI utilities (`StringEnum` for Google-compatible enums) |
|
|
171
176
|
| `@oh-my-pi/pi-tui` | TUI components for custom rendering |
|
|
172
177
|
|
|
173
|
-
|
|
178
|
+
`ExtensionAPI` also exposes:
|
|
179
|
+
|
|
180
|
+
- `pi.logger` - file logger (preferred over `console.*`)
|
|
181
|
+
- `pi.typebox` - injected TypeBox module
|
|
182
|
+
- `pi.pi` - access to `@oh-my-pi/pi-coding-agent` exports
|
|
183
|
+
|
|
184
|
+
Dependencies work like any Bun project. Add a `package.json` next to your extension (or in a parent directory), run `bun install`, and imports from `node_modules/` resolve automatically.
|
|
174
185
|
|
|
175
186
|
Node.js built-ins (`node:fs`, `node:path`, etc.) are also available.
|
|
176
187
|
|
|
@@ -199,18 +210,18 @@ export default function (pi: ExtensionAPI) {
|
|
|
199
210
|
}
|
|
200
211
|
```
|
|
201
212
|
|
|
202
|
-
Extensions are loaded via
|
|
213
|
+
Extensions are loaded via Bun's native module loader, so TypeScript works without a build step. Both `.ts` and `.js` entry points are supported.
|
|
203
214
|
|
|
204
215
|
### Extension Styles
|
|
205
216
|
|
|
206
|
-
**Single file** - simplest, for small extensions:
|
|
217
|
+
**Single file** - simplest, for small extensions (also supports `.js`):
|
|
207
218
|
|
|
208
219
|
```
|
|
209
220
|
~/.omp/agent/extensions/
|
|
210
221
|
└── my-extension.ts
|
|
211
222
|
```
|
|
212
223
|
|
|
213
|
-
**Directory with index.ts** - for multi-file extensions:
|
|
224
|
+
**Directory with index.ts** - for multi-file extensions (also supports `index.js`):
|
|
214
225
|
|
|
215
226
|
```
|
|
216
227
|
~/.omp/agent/extensions/
|
|
@@ -226,8 +237,8 @@ Extensions are loaded via [jiti](https://github.com/unjs/jiti), so TypeScript wo
|
|
|
226
237
|
~/.omp/agent/extensions/
|
|
227
238
|
└── my-extension/
|
|
228
239
|
├── package.json # Declares dependencies and entry points
|
|
229
|
-
├──
|
|
230
|
-
├── node_modules/ # After
|
|
240
|
+
├── bun.lockb
|
|
241
|
+
├── node_modules/ # After bun install
|
|
231
242
|
└── src/
|
|
232
243
|
└── index.ts
|
|
233
244
|
```
|
|
@@ -240,26 +251,29 @@ Extensions are loaded via [jiti](https://github.com/unjs/jiti), so TypeScript wo
|
|
|
240
251
|
"zod": "^3.0.0",
|
|
241
252
|
"chalk": "^5.0.0"
|
|
242
253
|
},
|
|
243
|
-
"
|
|
254
|
+
"omp": {
|
|
244
255
|
"extensions": ["./src/index.ts"]
|
|
245
256
|
}
|
|
246
257
|
}
|
|
247
258
|
```
|
|
248
259
|
|
|
249
|
-
|
|
260
|
+
The manifest key can be `omp` (preferred) or `pi` (legacy).
|
|
261
|
+
|
|
262
|
+
Run `bun install` in the extension directory, then imports from `node_modules/` work automatically.
|
|
250
263
|
|
|
251
264
|
## Events
|
|
252
265
|
|
|
253
266
|
### Lifecycle Overview
|
|
254
267
|
|
|
255
268
|
```
|
|
256
|
-
|
|
269
|
+
omp starts
|
|
257
270
|
│
|
|
258
271
|
└─► session_start
|
|
259
272
|
│
|
|
260
273
|
▼
|
|
261
|
-
user
|
|
274
|
+
user submits input ────────────────────────────────────────┐
|
|
262
275
|
│ │
|
|
276
|
+
├─► input (can modify or handle) │
|
|
263
277
|
├─► before_agent_start (can inject message, modify system prompt)
|
|
264
278
|
├─► agent_start │
|
|
265
279
|
│ │
|
|
@@ -289,6 +303,7 @@ user sends another prompt ◄─────────────────
|
|
|
289
303
|
|
|
290
304
|
/compact or auto-compaction
|
|
291
305
|
├─► session_before_compact (can cancel or customize)
|
|
306
|
+
├─► session.compacting (add context or override prompt)
|
|
292
307
|
└─► session_compact
|
|
293
308
|
|
|
294
309
|
/tree navigation
|
|
@@ -311,16 +326,16 @@ pi.on("session_start", async (_event, ctx) => {
|
|
|
311
326
|
});
|
|
312
327
|
```
|
|
313
328
|
|
|
314
|
-
**Examples:** [
|
|
329
|
+
**Examples:** [todo.ts](../examples/extensions/todo.ts), [tools.ts](../examples/extensions/tools.ts)
|
|
315
330
|
|
|
316
331
|
#### session_before_switch / session_switch
|
|
317
332
|
|
|
318
|
-
Fired when starting a new session (`/new`)
|
|
333
|
+
Fired when starting a new session (`/new`), resuming (`/resume`), or forking a session.
|
|
319
334
|
|
|
320
335
|
```typescript
|
|
321
336
|
pi.on("session_before_switch", async (event, ctx) => {
|
|
322
|
-
// event.reason - "new" or "
|
|
323
|
-
// event.targetSessionFile - session we're switching to (
|
|
337
|
+
// event.reason - "new", "resume", or "fork"
|
|
338
|
+
// event.targetSessionFile - session we're switching to ("resume" only)
|
|
324
339
|
|
|
325
340
|
if (event.reason === "new") {
|
|
326
341
|
const ok = await ctx.ui.confirm("Clear?", "Delete all messages?");
|
|
@@ -329,12 +344,12 @@ pi.on("session_before_switch", async (event, ctx) => {
|
|
|
329
344
|
});
|
|
330
345
|
|
|
331
346
|
pi.on("session_switch", async (event, ctx) => {
|
|
332
|
-
// event.reason - "new" or "
|
|
347
|
+
// event.reason - "new", "resume", or "fork"
|
|
333
348
|
// event.previousSessionFile - session we came from
|
|
334
349
|
});
|
|
335
350
|
```
|
|
336
351
|
|
|
337
|
-
**Examples:** [
|
|
352
|
+
**Examples:** [todo.ts](../examples/extensions/todo.ts)
|
|
338
353
|
|
|
339
354
|
#### session_before_branch / session_branch
|
|
340
355
|
|
|
@@ -353,7 +368,7 @@ pi.on("session_branch", async (event, ctx) => {
|
|
|
353
368
|
});
|
|
354
369
|
```
|
|
355
370
|
|
|
356
|
-
**Examples:** [
|
|
371
|
+
**Examples:** [todo.ts](../examples/extensions/todo.ts), [tools.ts](../examples/extensions/tools.ts)
|
|
357
372
|
|
|
358
373
|
#### session_before_compact / session_compact
|
|
359
374
|
|
|
@@ -382,7 +397,21 @@ pi.on("session_compact", async (event, ctx) => {
|
|
|
382
397
|
});
|
|
383
398
|
```
|
|
384
399
|
|
|
385
|
-
|
|
400
|
+
|
|
401
|
+
#### session.compacting
|
|
402
|
+
|
|
403
|
+
Fired before compaction summarization to adjust the prompt or inject extra context.
|
|
404
|
+
|
|
405
|
+
```typescript
|
|
406
|
+
pi.on("session.compacting", async (event, ctx) => {
|
|
407
|
+
// event.messages - messages being summarized
|
|
408
|
+
return {
|
|
409
|
+
context: ["Important context line"],
|
|
410
|
+
prompt: "Summarize with an emphasis on decisions and follow-ups",
|
|
411
|
+
preserveData: { ticketId: "ABC-123" },
|
|
412
|
+
};
|
|
413
|
+
});
|
|
414
|
+
```
|
|
386
415
|
|
|
387
416
|
#### session_before_tree / session_tree
|
|
388
417
|
|
|
@@ -401,7 +430,7 @@ pi.on("session_tree", async (event, ctx) => {
|
|
|
401
430
|
});
|
|
402
431
|
```
|
|
403
432
|
|
|
404
|
-
**Examples:** [
|
|
433
|
+
**Examples:** [tools.ts](../examples/extensions/tools.ts)
|
|
405
434
|
|
|
406
435
|
#### session_shutdown
|
|
407
436
|
|
|
@@ -413,8 +442,6 @@ pi.on("session_shutdown", async (_event, ctx) => {
|
|
|
413
442
|
});
|
|
414
443
|
```
|
|
415
444
|
|
|
416
|
-
**Examples:** [auto-commit-on-exit.ts](../examples/extensions/auto-commit-on-exit.ts)
|
|
417
|
-
|
|
418
445
|
### Agent Events
|
|
419
446
|
|
|
420
447
|
#### before_agent_start
|
|
@@ -440,7 +467,7 @@ pi.on("before_agent_start", async (event, ctx) => {
|
|
|
440
467
|
});
|
|
441
468
|
```
|
|
442
469
|
|
|
443
|
-
**Examples:** [
|
|
470
|
+
**Examples:** [pirate.ts](../examples/extensions/pirate.ts), [plan-mode.ts](../examples/extensions/plan-mode.ts)
|
|
444
471
|
|
|
445
472
|
#### agent_start / agent_end
|
|
446
473
|
|
|
@@ -454,7 +481,7 @@ pi.on("agent_end", async (event, ctx) => {
|
|
|
454
481
|
});
|
|
455
482
|
```
|
|
456
483
|
|
|
457
|
-
**Examples:** [chalk-logger.ts](../examples/extensions/chalk-logger.ts), [
|
|
484
|
+
**Examples:** [chalk-logger.ts](../examples/extensions/chalk-logger.ts), [plan-mode.ts](../examples/extensions/plan-mode.ts)
|
|
458
485
|
|
|
459
486
|
#### turn_start / turn_end
|
|
460
487
|
|
|
@@ -470,7 +497,7 @@ pi.on("turn_end", async (event, ctx) => {
|
|
|
470
497
|
});
|
|
471
498
|
```
|
|
472
499
|
|
|
473
|
-
**Examples:** [
|
|
500
|
+
**Examples:** [plan-mode.ts](../examples/extensions/plan-mode.ts)
|
|
474
501
|
|
|
475
502
|
#### context
|
|
476
503
|
|
|
@@ -484,7 +511,53 @@ pi.on("context", async (event, ctx) => {
|
|
|
484
511
|
});
|
|
485
512
|
```
|
|
486
513
|
|
|
487
|
-
|
|
514
|
+
### Input Events
|
|
515
|
+
|
|
516
|
+
#### input
|
|
517
|
+
|
|
518
|
+
Fired when the user submits input (interactive, RPC, or extension-triggered). Can rewrite or handle input.
|
|
519
|
+
|
|
520
|
+
```typescript
|
|
521
|
+
pi.on("input", async (event, ctx) => {
|
|
522
|
+
// event.text, event.images, event.source
|
|
523
|
+
if (event.text.startsWith("/noop")) {
|
|
524
|
+
return { handled: true };
|
|
525
|
+
}
|
|
526
|
+
return { text: event.text.trim() };
|
|
527
|
+
});
|
|
528
|
+
```
|
|
529
|
+
|
|
530
|
+
### User Bash/Python Events
|
|
531
|
+
|
|
532
|
+
#### user_bash
|
|
533
|
+
|
|
534
|
+
Fired when the user runs a `!`/`!!` command. Return a `result` to override execution.
|
|
535
|
+
|
|
536
|
+
```typescript
|
|
537
|
+
pi.on("user_bash", async (event, ctx) => {
|
|
538
|
+
// event.command, event.excludeFromContext, event.cwd
|
|
539
|
+
if (event.command === "pwd") {
|
|
540
|
+
return {
|
|
541
|
+
result: {
|
|
542
|
+
stdout: event.cwd,
|
|
543
|
+
stderr: "",
|
|
544
|
+
code: 0,
|
|
545
|
+
killed: false,
|
|
546
|
+
},
|
|
547
|
+
};
|
|
548
|
+
}
|
|
549
|
+
});
|
|
550
|
+
```
|
|
551
|
+
|
|
552
|
+
#### user_python
|
|
553
|
+
|
|
554
|
+
Fired when the user runs a `$`/`$$` block. Return a `result` to override execution.
|
|
555
|
+
|
|
556
|
+
```typescript
|
|
557
|
+
pi.on("user_python", async (event, ctx) => {
|
|
558
|
+
// event.code, event.excludeFromContext, event.cwd
|
|
559
|
+
});
|
|
560
|
+
```
|
|
488
561
|
|
|
489
562
|
### Tool Events
|
|
490
563
|
|
|
@@ -504,20 +577,18 @@ pi.on("tool_call", async (event, ctx) => {
|
|
|
504
577
|
});
|
|
505
578
|
```
|
|
506
579
|
|
|
507
|
-
**Examples:** [chalk-logger.ts](../examples/extensions/chalk-logger.ts), [
|
|
580
|
+
**Examples:** [chalk-logger.ts](../examples/extensions/chalk-logger.ts), [plan-mode.ts](../examples/extensions/plan-mode.ts)
|
|
508
581
|
|
|
509
582
|
#### tool_result
|
|
510
583
|
|
|
511
584
|
Fired after tool executes. **Can modify result.**
|
|
512
585
|
|
|
513
586
|
```typescript
|
|
514
|
-
import { isBashToolResult } from "@oh-my-pi/pi-coding-agent";
|
|
515
|
-
|
|
516
587
|
pi.on("tool_result", async (event, ctx) => {
|
|
517
588
|
// event.toolName, event.toolCallId, event.input
|
|
518
589
|
// event.content, event.details, event.isError
|
|
519
590
|
|
|
520
|
-
if (
|
|
591
|
+
if (event.toolName === "bash") {
|
|
521
592
|
// event.details is typed as BashToolDetails
|
|
522
593
|
}
|
|
523
594
|
|
|
@@ -526,7 +597,7 @@ pi.on("tool_result", async (event, ctx) => {
|
|
|
526
597
|
});
|
|
527
598
|
```
|
|
528
599
|
|
|
529
|
-
**Examples:** [
|
|
600
|
+
**Examples:** [plan-mode.ts](../examples/extensions/plan-mode.ts)
|
|
530
601
|
|
|
531
602
|
## ExtensionContext
|
|
532
603
|
|
|
@@ -538,7 +609,7 @@ UI methods for user interaction. See [Custom UI](#custom-ui) for full details.
|
|
|
538
609
|
|
|
539
610
|
### ctx.hasUI
|
|
540
611
|
|
|
541
|
-
`false` in print mode (`-p`), JSON mode, and RPC mode.
|
|
612
|
+
`false` in print mode (`-p`), JSON mode, and RPC mode. UI methods become no-ops, so check before prompting.
|
|
542
613
|
|
|
543
614
|
### ctx.cwd
|
|
544
615
|
|
|
@@ -558,6 +629,18 @@ ctx.sessionManager.getLeafId(); // Current leaf entry ID
|
|
|
558
629
|
|
|
559
630
|
Access to models and API keys.
|
|
560
631
|
|
|
632
|
+
### ctx.getContextUsage()
|
|
633
|
+
|
|
634
|
+
Returns current context usage for the active model, if available.
|
|
635
|
+
|
|
636
|
+
### ctx.compact(instructionsOrOptions?)
|
|
637
|
+
|
|
638
|
+
Trigger compaction programmatically (interactive mode shows UI).
|
|
639
|
+
|
|
640
|
+
### ctx.shutdown()
|
|
641
|
+
|
|
642
|
+
Gracefully shut down and exit.
|
|
643
|
+
|
|
561
644
|
### ctx.isIdle() / ctx.abort() / ctx.hasPendingMessages()
|
|
562
645
|
|
|
563
646
|
Control flow helpers.
|
|
@@ -656,7 +739,7 @@ pi.registerTool({
|
|
|
656
739
|
|
|
657
740
|
// Optional: Custom rendering
|
|
658
741
|
renderCall(args, theme) { ... },
|
|
659
|
-
renderResult(result, options, theme) { ... },
|
|
742
|
+
renderResult(result, options, theme, args) { ... },
|
|
660
743
|
});
|
|
661
744
|
```
|
|
662
745
|
|
|
@@ -684,6 +767,14 @@ pi.sendMessage({
|
|
|
684
767
|
- `"nextTurn"` - Queued for next user prompt. Does not interrupt or trigger anything.
|
|
685
768
|
- `triggerTurn: true` - If agent is idle, trigger an LLM response immediately. Only applies to `"steer"` and `"followUp"` modes (ignored for `"nextTurn"`).
|
|
686
769
|
|
|
770
|
+
### pi.sendUserMessage(content, options?)
|
|
771
|
+
|
|
772
|
+
Send a user message into the session and trigger a turn immediately:
|
|
773
|
+
|
|
774
|
+
```typescript
|
|
775
|
+
pi.sendUserMessage("Follow up with the latest status", { deliverAs: "followUp" });
|
|
776
|
+
```
|
|
777
|
+
|
|
687
778
|
### pi.appendEntry(customType, data?)
|
|
688
779
|
|
|
689
780
|
Persist extension state (does NOT participate in LLM context):
|
|
@@ -749,6 +840,14 @@ if (pi.getFlag("--plan")) {
|
|
|
749
840
|
}
|
|
750
841
|
```
|
|
751
842
|
|
|
843
|
+
### pi.setLabel(label)
|
|
844
|
+
|
|
845
|
+
Set a display label for the extension:
|
|
846
|
+
|
|
847
|
+
```typescript
|
|
848
|
+
pi.setLabel("My Extension");
|
|
849
|
+
```
|
|
850
|
+
|
|
752
851
|
### pi.exec(command, args, options?)
|
|
753
852
|
|
|
754
853
|
Execute a shell command:
|
|
@@ -767,6 +866,19 @@ const active = pi.getActiveTools(); // ["read", "bash", "edit", "write"]
|
|
|
767
866
|
pi.setActiveTools(["read", "bash"]); // Switch to read-only
|
|
768
867
|
```
|
|
769
868
|
|
|
869
|
+
### pi.setModel(model) / pi.getThinkingLevel() / pi.setThinkingLevel(level)
|
|
870
|
+
|
|
871
|
+
Control the active model and thinking level:
|
|
872
|
+
|
|
873
|
+
```typescript
|
|
874
|
+
const model = ctx.modelRegistry.find("anthropic", "claude-sonnet-4-5");
|
|
875
|
+
if (model) {
|
|
876
|
+
const ok = await pi.setModel(model);
|
|
877
|
+
}
|
|
878
|
+
const level = pi.getThinkingLevel();
|
|
879
|
+
pi.setThinkingLevel(level);
|
|
880
|
+
```
|
|
881
|
+
|
|
770
882
|
### pi.events
|
|
771
883
|
|
|
772
884
|
Shared event bus for communication between extensions:
|
|
@@ -778,7 +890,7 @@ pi.events.emit("my:event", { ... });
|
|
|
778
890
|
|
|
779
891
|
## State Management
|
|
780
892
|
|
|
781
|
-
Extensions with state should store it in tool result `details` for proper branching support:
|
|
893
|
+
Extensions with state should store it in tool result `details` for proper branching support. Tools can also implement `onSession` to rebuild or clean up state on start/switch/branch/tree/shutdown:
|
|
782
894
|
|
|
783
895
|
```typescript
|
|
784
896
|
export default function (pi: ExtensionAPI) {
|
|
@@ -829,6 +941,10 @@ pi.registerTool({
|
|
|
829
941
|
action: StringEnum(["list", "add"] as const), // Use StringEnum for Google compatibility
|
|
830
942
|
text: Type.Optional(Type.String()),
|
|
831
943
|
}),
|
|
944
|
+
hidden: false, // Optional: set true to hide unless explicitly enabled
|
|
945
|
+
onSession(event, ctx) {
|
|
946
|
+
// event.reason: "start" | "switch" | "branch" | "tree" | "shutdown"
|
|
947
|
+
},
|
|
832
948
|
|
|
833
949
|
async execute(toolCallId, params, onUpdate, ctx, signal) {
|
|
834
950
|
// Check for cancellation
|
|
@@ -854,7 +970,7 @@ pi.registerTool({
|
|
|
854
970
|
|
|
855
971
|
// Optional: Custom rendering
|
|
856
972
|
renderCall(args, theme) { ... },
|
|
857
|
-
renderResult(result, options, theme) { ... },
|
|
973
|
+
renderResult(result, options, theme, args) { ... },
|
|
858
974
|
});
|
|
859
975
|
```
|
|
860
976
|
|
|
@@ -973,17 +1089,31 @@ ctx.ui.notify("Done!", "info"); // "info" | "warning" | "error"
|
|
|
973
1089
|
ctx.ui.setStatus("my-ext", "Processing...");
|
|
974
1090
|
ctx.ui.setStatus("my-ext", undefined); // Clear
|
|
975
1091
|
|
|
1092
|
+
// Working message shown during streaming
|
|
1093
|
+
ctx.ui.setWorkingMessage("Connecting...");
|
|
1094
|
+
ctx.ui.setWorkingMessage(); // Restore default
|
|
1095
|
+
|
|
976
1096
|
// Widget above editor (string array or factory function)
|
|
977
1097
|
ctx.ui.setWidget("my-widget", ["Line 1", "Line 2"]);
|
|
978
1098
|
ctx.ui.setWidget("my-widget", (tui, theme) => new Text(theme.fg("accent", "Custom"), 0, 0));
|
|
979
1099
|
ctx.ui.setWidget("my-widget", undefined); // Clear
|
|
980
1100
|
|
|
1101
|
+
// Custom header/footer
|
|
1102
|
+
ctx.ui.setHeader((tui, theme) => new Text(theme.fg("accent", "Header"), 0, 0));
|
|
1103
|
+
ctx.ui.setFooter((tui, theme) => new Text(theme.fg("accent", "Footer"), 0, 0));
|
|
1104
|
+
ctx.ui.setHeader(undefined); // Restore default
|
|
1105
|
+
ctx.ui.setFooter(undefined); // Restore default
|
|
1106
|
+
|
|
981
1107
|
// Terminal title
|
|
982
|
-
ctx.ui.setTitle("
|
|
1108
|
+
ctx.ui.setTitle("omp - my-project");
|
|
983
1109
|
|
|
984
1110
|
// Editor text
|
|
985
1111
|
ctx.ui.setEditorText("Prefill text");
|
|
986
1112
|
const current = ctx.ui.getEditorText();
|
|
1113
|
+
|
|
1114
|
+
// Custom editor component
|
|
1115
|
+
ctx.ui.setEditorComponent((tui, theme, keybindings) => new MyEditor(tui, theme, keybindings)); // EditorComponent
|
|
1116
|
+
ctx.ui.setEditorComponent(undefined); // Restore default
|
|
987
1117
|
```
|
|
988
1118
|
|
|
989
1119
|
### Custom Components
|
|
@@ -993,7 +1123,7 @@ For complex UI, use `ctx.ui.custom()`. This temporarily replaces the editor with
|
|
|
993
1123
|
```typescript
|
|
994
1124
|
import { Text, Component } from "@oh-my-pi/pi-tui";
|
|
995
1125
|
|
|
996
|
-
const result = await ctx.ui.custom<boolean>((tui, theme, done) => {
|
|
1126
|
+
const result = await ctx.ui.custom<boolean>((tui, theme, keybindings, done) => {
|
|
997
1127
|
const text = new Text("Press Enter to confirm, Escape to cancel", 1, 1);
|
|
998
1128
|
|
|
999
1129
|
text.onKey = (key) => {
|
|
@@ -1003,7 +1133,7 @@ const result = await ctx.ui.custom<boolean>((tui, theme, done) => {
|
|
|
1003
1133
|
};
|
|
1004
1134
|
|
|
1005
1135
|
return text;
|
|
1006
|
-
});
|
|
1136
|
+
}, { overlay: true });
|
|
1007
1137
|
|
|
1008
1138
|
if (result) {
|
|
1009
1139
|
// User pressed Enter
|
|
@@ -1014,9 +1144,10 @@ The callback receives:
|
|
|
1014
1144
|
|
|
1015
1145
|
- `tui` - TUI instance (for screen dimensions, focus management)
|
|
1016
1146
|
- `theme` - Current theme for styling
|
|
1147
|
+
- `keybindings` - Keybindings manager for resolving bindings
|
|
1017
1148
|
- `done(value)` - Call to close component and return value
|
|
1018
1149
|
|
|
1019
|
-
See [tui.md](tui.md) for the full component API and [examples/extensions/](../examples/extensions/) for working examples (
|
|
1150
|
+
See [tui.md](tui.md) for the full component API and [examples/extensions/](../examples/extensions/) for working examples (todo.ts, tools.ts).
|
|
1020
1151
|
|
|
1021
1152
|
### Message Rendering
|
|
1022
1153
|
|
|
@@ -1049,6 +1180,15 @@ pi.sendMessage({
|
|
|
1049
1180
|
});
|
|
1050
1181
|
```
|
|
1051
1182
|
|
|
1183
|
+
### Themes
|
|
1184
|
+
|
|
1185
|
+
```typescript
|
|
1186
|
+
const themes = await ctx.ui.getAllThemes();
|
|
1187
|
+
const current = ctx.ui.theme;
|
|
1188
|
+
const loaded = await ctx.ui.getTheme("celestial");
|
|
1189
|
+
const result = await ctx.ui.setTheme("celestial");
|
|
1190
|
+
```
|
|
1191
|
+
|
|
1052
1192
|
### Theme Colors
|
|
1053
1193
|
|
|
1054
1194
|
All render functions receive a `theme` object:
|
|
@@ -1080,7 +1220,8 @@ theme.strikethrough(text);
|
|
|
1080
1220
|
| Mode | UI Methods | Notes |
|
|
1081
1221
|
| ------------ | ------------- | ------------------------------- |
|
|
1082
1222
|
| Interactive | Full TUI | Normal operation |
|
|
1223
|
+
| JSON | No-op | `--mode json` output |
|
|
1083
1224
|
| RPC | JSON protocol | Host handles UI |
|
|
1084
1225
|
| Print (`-p`) | No-op | Extensions run but can't prompt |
|
|
1085
1226
|
|
|
1086
|
-
In print
|
|
1227
|
+
In print/JSON/RPC modes, check `ctx.hasUI` before using UI methods.
|