@mariozechner/pi-coding-agent 0.49.3 → 0.50.1
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 +110 -1
- package/README.md +310 -1230
- package/dist/cli/args.d.ts +5 -0
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +57 -23
- package/dist/cli/args.js.map +1 -1
- package/dist/cli/config-selector.d.ts +14 -0
- package/dist/cli/config-selector.d.ts.map +1 -0
- package/dist/cli/config-selector.js +31 -0
- package/dist/cli/config-selector.js.map +1 -0
- package/dist/cli/session-picker.d.ts.map +1 -1
- package/dist/cli/session-picker.js +1 -1
- package/dist/cli/session-picker.js.map +1 -1
- package/dist/core/agent-session.d.ts +60 -37
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +272 -69
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/auth-storage.d.ts +8 -18
- package/dist/core/auth-storage.d.ts.map +1 -1
- package/dist/core/auth-storage.js +39 -55
- package/dist/core/auth-storage.js.map +1 -1
- package/dist/core/bash-executor.d.ts.map +1 -1
- package/dist/core/bash-executor.js +2 -1
- package/dist/core/bash-executor.js.map +1 -1
- package/dist/core/diagnostics.d.ts +15 -0
- package/dist/core/diagnostics.d.ts.map +1 -0
- package/dist/core/diagnostics.js +2 -0
- package/dist/core/diagnostics.js.map +1 -0
- package/dist/core/export-html/template.css +9 -0
- package/dist/core/export-html/template.js +6 -4
- package/dist/core/extensions/index.d.ts +1 -1
- package/dist/core/extensions/index.d.ts.map +1 -1
- package/dist/core/extensions/index.js.map +1 -1
- package/dist/core/extensions/loader.d.ts +1 -1
- package/dist/core/extensions/loader.d.ts.map +1 -1
- package/dist/core/extensions/loader.js +10 -1
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/extensions/runner.d.ts +9 -3
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +39 -12
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/types.d.ts +112 -1
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/footer-data-provider.d.ts +9 -2
- package/dist/core/footer-data-provider.d.ts.map +1 -1
- package/dist/core/footer-data-provider.js +13 -0
- package/dist/core/footer-data-provider.js.map +1 -1
- package/dist/core/model-registry.d.ts +42 -2
- package/dist/core/model-registry.d.ts.map +1 -1
- package/dist/core/model-registry.js +154 -44
- package/dist/core/model-registry.js.map +1 -1
- package/dist/core/model-resolver.d.ts.map +1 -1
- package/dist/core/model-resolver.js +3 -2
- package/dist/core/model-resolver.js.map +1 -1
- package/dist/core/package-manager.d.ts +130 -0
- package/dist/core/package-manager.d.ts.map +1 -0
- package/dist/core/package-manager.js +1177 -0
- package/dist/core/package-manager.js.map +1 -0
- package/dist/core/prompt-templates.d.ts +6 -0
- package/dist/core/prompt-templates.d.ts.map +1 -1
- package/dist/core/prompt-templates.js +114 -54
- package/dist/core/prompt-templates.js.map +1 -1
- package/dist/core/resource-loader.d.ts +160 -0
- package/dist/core/resource-loader.d.ts.map +1 -0
- package/dist/core/resource-loader.js +604 -0
- package/dist/core/resource-loader.js.map +1 -0
- package/dist/core/sdk.d.ts +14 -105
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +52 -304
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +45 -1
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/settings-manager.d.ts +34 -16
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +104 -25
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/skills.d.ts +18 -10
- package/dist/core/skills.d.ts.map +1 -1
- package/dist/core/skills.js +126 -93
- package/dist/core/skills.js.map +1 -1
- package/dist/core/system-prompt.d.ts +3 -27
- package/dist/core/system-prompt.d.ts.map +1 -1
- package/dist/core/system-prompt.js +16 -103
- package/dist/core/system-prompt.js.map +1 -1
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +2 -1
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/read.d.ts.map +1 -1
- package/dist/core/tools/read.js +4 -4
- package/dist/core/tools/read.js.map +1 -1
- package/dist/index.d.ts +12 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -6
- package/dist/index.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +209 -97
- package/dist/main.js.map +1 -1
- package/dist/modes/interactive/components/bordered-loader.d.ts +5 -1
- package/dist/modes/interactive/components/bordered-loader.d.ts.map +1 -1
- package/dist/modes/interactive/components/bordered-loader.js +29 -9
- package/dist/modes/interactive/components/bordered-loader.js.map +1 -1
- package/dist/modes/interactive/components/config-selector.d.ts +71 -0
- package/dist/modes/interactive/components/config-selector.d.ts.map +1 -0
- package/dist/modes/interactive/components/config-selector.js +468 -0
- package/dist/modes/interactive/components/config-selector.js.map +1 -0
- package/dist/modes/interactive/components/footer.d.ts.map +1 -1
- package/dist/modes/interactive/components/footer.js +4 -0
- package/dist/modes/interactive/components/footer.js.map +1 -1
- package/dist/modes/interactive/components/index.d.ts +1 -0
- package/dist/modes/interactive/components/index.d.ts.map +1 -1
- package/dist/modes/interactive/components/index.js +1 -0
- package/dist/modes/interactive/components/index.js.map +1 -1
- package/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/oauth-selector.js +3 -4
- package/dist/modes/interactive/components/oauth-selector.js.map +1 -1
- package/dist/modes/interactive/components/session-selector.d.ts +18 -1
- package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/session-selector.js +195 -87
- package/dist/modes/interactive/components/session-selector.js.map +1 -1
- package/dist/modes/interactive/components/skill-invocation-message.d.ts +17 -0
- package/dist/modes/interactive/components/skill-invocation-message.d.ts.map +1 -0
- package/dist/modes/interactive/components/skill-invocation-message.js +47 -0
- package/dist/modes/interactive/components/skill-invocation-message.js.map +1 -0
- package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/tool-execution.js +5 -5
- package/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +42 -2
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +538 -204
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/theme/dark.json +1 -1
- package/dist/modes/interactive/theme/light.json +1 -1
- package/dist/modes/interactive/theme/theme-schema.json +8 -1
- package/dist/modes/interactive/theme/theme.d.ts +8 -1
- package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
- package/dist/modes/interactive/theme/theme.js +72 -25
- package/dist/modes/interactive/theme/theme.js.map +1 -1
- package/dist/modes/print-mode.d.ts.map +1 -1
- package/dist/modes/print-mode.js +7 -74
- package/dist/modes/print-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-mode.js +17 -82
- package/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/dist/utils/git.d.ts +2 -0
- package/dist/utils/git.d.ts.map +1 -0
- package/dist/utils/git.js +6 -0
- package/dist/utils/git.js.map +1 -0
- package/dist/utils/shell.d.ts +1 -0
- package/dist/utils/shell.d.ts.map +1 -1
- package/dist/utils/shell.js +14 -1
- package/dist/utils/shell.js.map +1 -1
- package/dist/utils/sleep.d.ts +5 -0
- package/dist/utils/sleep.d.ts.map +1 -0
- package/dist/utils/sleep.js +17 -0
- package/dist/utils/sleep.js.map +1 -0
- package/docs/compaction.md +23 -21
- package/docs/custom-provider.md +538 -0
- package/docs/development.md +69 -0
- package/docs/extensions.md +182 -118
- package/docs/images/doom-extension.png +0 -0
- package/docs/images/interactive-mode.png +0 -0
- package/docs/images/tree-view.png +0 -0
- package/docs/json.md +79 -0
- package/docs/keybindings.md +162 -0
- package/docs/models.md +193 -0
- package/docs/packages.md +168 -0
- package/docs/prompt-templates.md +67 -0
- package/docs/providers.md +147 -0
- package/docs/sdk.md +111 -178
- package/docs/session.md +167 -16
- package/docs/settings.md +216 -0
- package/docs/shell-aliases.md +13 -0
- package/docs/skills.md +111 -202
- package/docs/terminal-setup.md +65 -0
- package/docs/themes.md +295 -0
- package/docs/tui.md +36 -5
- package/docs/windows.md +17 -0
- package/examples/README.md +1 -0
- package/examples/extensions/README.md +22 -2
- package/examples/extensions/bookmark.ts +50 -0
- package/examples/extensions/custom-provider-anthropic/index.ts +604 -0
- package/examples/extensions/custom-provider-anthropic/package-lock.json +24 -0
- package/examples/extensions/custom-provider-anthropic/package.json +19 -0
- package/examples/extensions/custom-provider-gitlab-duo/index.ts +349 -0
- package/examples/extensions/custom-provider-gitlab-duo/package.json +16 -0
- package/examples/extensions/custom-provider-gitlab-duo/test.ts +82 -0
- package/examples/extensions/doom-overlay/doom/build.sh +1 -1
- package/examples/extensions/event-bus.ts +43 -0
- package/examples/extensions/message-renderer.ts +59 -0
- package/examples/extensions/session-name.ts +27 -0
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/examples/sdk/02-custom-model.ts +3 -3
- package/examples/sdk/03-custom-prompt.ts +20 -9
- package/examples/sdk/04-skills.ts +26 -27
- package/examples/sdk/06-extensions.ts +15 -6
- package/examples/sdk/07-context-files.ts +22 -18
- package/examples/sdk/08-prompt-templates.ts +19 -14
- package/examples/sdk/09-api-keys-and-oauth.ts +5 -12
- package/examples/sdk/10-settings.ts +3 -3
- package/examples/sdk/12-full-control.ts +16 -7
- package/examples/sdk/README.md +24 -30
- package/package.json +4 -4
- package/docs/theme.md +0 -617
- package/examples/extensions/chalk-logger.ts +0 -26
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# Development
|
|
2
|
+
|
|
3
|
+
See [AGENTS.md](../../../AGENTS.md) for additional guidelines.
|
|
4
|
+
|
|
5
|
+
## Setup
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
git clone https://github.com/badlogic/pi-mono
|
|
9
|
+
cd pi-mono
|
|
10
|
+
npm install
|
|
11
|
+
npm run build
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
Run from source:
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
./pi-test.sh
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Forking / Rebranding
|
|
21
|
+
|
|
22
|
+
Configure via `package.json`:
|
|
23
|
+
|
|
24
|
+
```json
|
|
25
|
+
{
|
|
26
|
+
"piConfig": {
|
|
27
|
+
"name": "pi",
|
|
28
|
+
"configDir": ".pi"
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Change `name`, `configDir`, and `bin` field for your fork. Affects CLI banner, config paths, and environment variable names.
|
|
34
|
+
|
|
35
|
+
## Path Resolution
|
|
36
|
+
|
|
37
|
+
Three execution modes: npm install, standalone binary, tsx from source.
|
|
38
|
+
|
|
39
|
+
**Always use `src/config.ts`** for package assets:
|
|
40
|
+
|
|
41
|
+
```typescript
|
|
42
|
+
import { getPackageDir, getThemeDir } from "./config.js";
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Never use `__dirname` directly for package assets.
|
|
46
|
+
|
|
47
|
+
## Debug Command
|
|
48
|
+
|
|
49
|
+
`/debug` (hidden) writes to `~/.pi/agent/pi-debug.log`:
|
|
50
|
+
- Rendered TUI lines with ANSI codes
|
|
51
|
+
- Last messages sent to the LLM
|
|
52
|
+
|
|
53
|
+
## Testing
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
./test.sh # Run non-LLM tests (no API keys needed)
|
|
57
|
+
npm test # Run all tests
|
|
58
|
+
npm test -- test/specific.test.ts # Run specific test
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Project Structure
|
|
62
|
+
|
|
63
|
+
```
|
|
64
|
+
packages/
|
|
65
|
+
ai/ # LLM provider abstraction
|
|
66
|
+
agent/ # Agent loop and message types
|
|
67
|
+
tui/ # Terminal UI components
|
|
68
|
+
coding-agent/ # CLI and interactive mode
|
|
69
|
+
```
|
package/docs/extensions.md
CHANGED
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
|
|
5
5
|
Extensions are TypeScript modules that extend pi's behavior. They can subscribe to lifecycle events, register custom tools callable by the LLM, add commands, and more.
|
|
6
6
|
|
|
7
|
+
> **Placement for /reload:** Put extensions in `~/.pi/agent/extensions/` (global) or `.pi/extensions/` (project-local) for auto-discovery. Use `pi -e ./path.ts` only for quick tests. Extensions in auto-discovered locations can be hot-reloaded with `/reload`.
|
|
8
|
+
|
|
7
9
|
**Key capabilities:**
|
|
8
10
|
- **Custom tools** - Register tools the LLM can call via `pi.registerTool()`
|
|
9
11
|
- **Event interception** - Block or modify tool calls, inject context, customize compaction
|
|
@@ -46,6 +48,7 @@ See [examples/extensions/](../examples/extensions/) for working implementations.
|
|
|
46
48
|
- [Custom UI](#custom-ui)
|
|
47
49
|
- [Error Handling](#error-handling)
|
|
48
50
|
- [Mode Behavior](#mode-behavior)
|
|
51
|
+
- [Examples Reference](#examples-reference)
|
|
49
52
|
|
|
50
53
|
## Quick Start
|
|
51
54
|
|
|
@@ -102,6 +105,8 @@ pi -e ./my-extension.ts
|
|
|
102
105
|
|
|
103
106
|
## Extension Locations
|
|
104
107
|
|
|
108
|
+
> **Security:** Extensions run with your full system permissions and can execute arbitrary code. Only install from sources you trust.
|
|
109
|
+
|
|
105
110
|
Extensions are auto-discovered from:
|
|
106
111
|
|
|
107
112
|
| Location | Scope |
|
|
@@ -115,47 +120,18 @@ Additional paths via `settings.json`:
|
|
|
115
120
|
|
|
116
121
|
```json
|
|
117
122
|
{
|
|
118
|
-
"
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
3. **Subdirectory with package.json:** `extensions/myext/package.json` with `"pi"` field → loads declared paths
|
|
127
|
-
|
|
128
|
-
```
|
|
129
|
-
~/.pi/agent/extensions/
|
|
130
|
-
├── simple.ts # Direct file (auto-discovered)
|
|
131
|
-
├── my-tool/
|
|
132
|
-
│ └── index.ts # Subdirectory with index (auto-discovered)
|
|
133
|
-
└── my-extension-pack/
|
|
134
|
-
├── package.json # Declares multiple extensions
|
|
135
|
-
├── node_modules/ # Dependencies installed here
|
|
136
|
-
└── src/
|
|
137
|
-
├── safety-gates.ts # First extension
|
|
138
|
-
└── custom-tools.ts # Second extension
|
|
139
|
-
```
|
|
140
|
-
|
|
141
|
-
```json
|
|
142
|
-
// my-extension-pack/package.json
|
|
143
|
-
{
|
|
144
|
-
"name": "my-extension-pack",
|
|
145
|
-
"dependencies": {
|
|
146
|
-
"zod": "^3.0.0"
|
|
147
|
-
},
|
|
148
|
-
"pi": {
|
|
149
|
-
"extensions": ["./src/safety-gates.ts", "./src/custom-tools.ts"]
|
|
150
|
-
}
|
|
123
|
+
"packages": [
|
|
124
|
+
"npm:@foo/bar@1.0.0",
|
|
125
|
+
"git:github.com/user/repo@v1"
|
|
126
|
+
],
|
|
127
|
+
"extensions": [
|
|
128
|
+
"/path/to/local/extension.ts",
|
|
129
|
+
"/path/to/local/extension/dir"
|
|
130
|
+
]
|
|
151
131
|
}
|
|
152
132
|
```
|
|
153
133
|
|
|
154
|
-
|
|
155
|
-
- Multiple extensions from one package
|
|
156
|
-
- Third-party npm dependencies (resolved via jiti)
|
|
157
|
-
- Nested source structure (no depth limit within the package)
|
|
158
|
-
- Deployment to and installation from npm
|
|
134
|
+
To share extensions via npm or git as pi packages, see [packages.md](packages.md).
|
|
159
135
|
|
|
160
136
|
## Available Imports
|
|
161
137
|
|
|
@@ -303,6 +279,8 @@ exit (Ctrl+C, Ctrl+D)
|
|
|
303
279
|
|
|
304
280
|
### Session Events
|
|
305
281
|
|
|
282
|
+
See [session.md](session.md) for session storage internals and the SessionManager API.
|
|
283
|
+
|
|
306
284
|
#### session_start
|
|
307
285
|
|
|
308
286
|
Fired on initial session load.
|
|
@@ -313,8 +291,6 @@ pi.on("session_start", async (_event, ctx) => {
|
|
|
313
291
|
});
|
|
314
292
|
```
|
|
315
293
|
|
|
316
|
-
**Examples:** [claude-rules.ts](../examples/extensions/claude-rules.ts), [custom-header.ts](../examples/extensions/custom-header.ts), [file-trigger.ts](../examples/extensions/file-trigger.ts), [status-line.ts](../examples/extensions/status-line.ts), [todo.ts](../examples/extensions/todo.ts), [tools.ts](../examples/extensions/tools.ts)
|
|
317
|
-
|
|
318
294
|
#### session_before_switch / session_switch
|
|
319
295
|
|
|
320
296
|
Fired when starting a new session (`/new`) or switching sessions (`/resume`).
|
|
@@ -336,8 +312,6 @@ pi.on("session_switch", async (event, ctx) => {
|
|
|
336
312
|
});
|
|
337
313
|
```
|
|
338
314
|
|
|
339
|
-
**Examples:** [confirm-destructive.ts](../examples/extensions/confirm-destructive.ts), [dirty-repo-guard.ts](../examples/extensions/dirty-repo-guard.ts), [status-line.ts](../examples/extensions/status-line.ts), [todo.ts](../examples/extensions/todo.ts)
|
|
340
|
-
|
|
341
315
|
#### session_before_fork / session_fork
|
|
342
316
|
|
|
343
317
|
Fired when forking via `/fork`.
|
|
@@ -355,8 +329,6 @@ pi.on("session_fork", async (event, ctx) => {
|
|
|
355
329
|
});
|
|
356
330
|
```
|
|
357
331
|
|
|
358
|
-
**Examples:** [confirm-destructive.ts](../examples/extensions/confirm-destructive.ts), [dirty-repo-guard.ts](../examples/extensions/dirty-repo-guard.ts), [git-checkpoint.ts](../examples/extensions/git-checkpoint.ts), [todo.ts](../examples/extensions/todo.ts), [tools.ts](../examples/extensions/tools.ts)
|
|
359
|
-
|
|
360
332
|
#### session_before_compact / session_compact
|
|
361
333
|
|
|
362
334
|
Fired on compaction. See [compaction.md](compaction.md) for details.
|
|
@@ -384,11 +356,9 @@ pi.on("session_compact", async (event, ctx) => {
|
|
|
384
356
|
});
|
|
385
357
|
```
|
|
386
358
|
|
|
387
|
-
**Examples:** [custom-compaction.ts](../examples/extensions/custom-compaction.ts), [trigger-compact.ts](../examples/extensions/trigger-compact.ts)
|
|
388
|
-
|
|
389
359
|
#### session_before_tree / session_tree
|
|
390
360
|
|
|
391
|
-
Fired on `/tree` navigation.
|
|
361
|
+
Fired on `/tree` navigation. See [tree.md](tree.md) for tree navigation concepts.
|
|
392
362
|
|
|
393
363
|
```typescript
|
|
394
364
|
pi.on("session_before_tree", async (event, ctx) => {
|
|
@@ -403,8 +373,6 @@ pi.on("session_tree", async (event, ctx) => {
|
|
|
403
373
|
});
|
|
404
374
|
```
|
|
405
375
|
|
|
406
|
-
**Examples:** [todo.ts](../examples/extensions/todo.ts), [tools.ts](../examples/extensions/tools.ts)
|
|
407
|
-
|
|
408
376
|
#### session_shutdown
|
|
409
377
|
|
|
410
378
|
Fired on exit (Ctrl+C, Ctrl+D, SIGTERM).
|
|
@@ -415,8 +383,6 @@ pi.on("session_shutdown", async (_event, ctx) => {
|
|
|
415
383
|
});
|
|
416
384
|
```
|
|
417
385
|
|
|
418
|
-
**Examples:** [auto-commit-on-exit.ts](../examples/extensions/auto-commit-on-exit.ts)
|
|
419
|
-
|
|
420
386
|
### Agent Events
|
|
421
387
|
|
|
422
388
|
#### before_agent_start
|
|
@@ -442,8 +408,6 @@ pi.on("before_agent_start", async (event, ctx) => {
|
|
|
442
408
|
});
|
|
443
409
|
```
|
|
444
410
|
|
|
445
|
-
**Examples:** [claude-rules.ts](../examples/extensions/claude-rules.ts), [pirate.ts](../examples/extensions/pirate.ts), [plan-mode/index.ts](../examples/extensions/plan-mode/index.ts), [preset.ts](../examples/extensions/preset.ts), [ssh.ts](../examples/extensions/ssh.ts)
|
|
446
|
-
|
|
447
411
|
#### agent_start / agent_end
|
|
448
412
|
|
|
449
413
|
Fired once per user prompt.
|
|
@@ -456,8 +420,6 @@ pi.on("agent_end", async (event, ctx) => {
|
|
|
456
420
|
});
|
|
457
421
|
```
|
|
458
422
|
|
|
459
|
-
**Examples:** [chalk-logger.ts](../examples/extensions/chalk-logger.ts), [git-checkpoint.ts](../examples/extensions/git-checkpoint.ts), [plan-mode/index.ts](../examples/extensions/plan-mode/index.ts)
|
|
460
|
-
|
|
461
423
|
#### turn_start / turn_end
|
|
462
424
|
|
|
463
425
|
Fired for each turn (one LLM response + tool calls).
|
|
@@ -472,11 +434,9 @@ pi.on("turn_end", async (event, ctx) => {
|
|
|
472
434
|
});
|
|
473
435
|
```
|
|
474
436
|
|
|
475
|
-
**Examples:** [git-checkpoint.ts](../examples/extensions/git-checkpoint.ts), [plan-mode/index.ts](../examples/extensions/plan-mode/index.ts), [status-line.ts](../examples/extensions/status-line.ts)
|
|
476
|
-
|
|
477
437
|
#### context
|
|
478
438
|
|
|
479
|
-
Fired before each LLM call. Modify messages non-destructively.
|
|
439
|
+
Fired before each LLM call. Modify messages non-destructively. See [session.md](session.md) for message types.
|
|
480
440
|
|
|
481
441
|
```typescript
|
|
482
442
|
pi.on("context", async (event, ctx) => {
|
|
@@ -486,8 +446,6 @@ pi.on("context", async (event, ctx) => {
|
|
|
486
446
|
});
|
|
487
447
|
```
|
|
488
448
|
|
|
489
|
-
**Examples:** [plan-mode/index.ts](../examples/extensions/plan-mode/index.ts)
|
|
490
|
-
|
|
491
449
|
### Model Events
|
|
492
450
|
|
|
493
451
|
#### model_select
|
|
@@ -499,20 +457,18 @@ pi.on("model_select", async (event, ctx) => {
|
|
|
499
457
|
// event.model - newly selected model
|
|
500
458
|
// event.previousModel - previous model (undefined if first selection)
|
|
501
459
|
// event.source - "set" | "cycle" | "restore"
|
|
502
|
-
|
|
503
|
-
const prev = event.previousModel
|
|
504
|
-
? `${event.previousModel.provider}/${event.previousModel.id}`
|
|
460
|
+
|
|
461
|
+
const prev = event.previousModel
|
|
462
|
+
? `${event.previousModel.provider}/${event.previousModel.id}`
|
|
505
463
|
: "none";
|
|
506
464
|
const next = `${event.model.provider}/${event.model.id}`;
|
|
507
|
-
|
|
465
|
+
|
|
508
466
|
ctx.ui.notify(`Model changed (${event.source}): ${prev} -> ${next}`, "info");
|
|
509
467
|
});
|
|
510
468
|
```
|
|
511
469
|
|
|
512
470
|
Use this to update UI elements (status bars, footers) or perform model-specific initialization when the active model changes.
|
|
513
471
|
|
|
514
|
-
**Examples:** [model-status.ts](../examples/extensions/model-status.ts)
|
|
515
|
-
|
|
516
472
|
### Tool Events
|
|
517
473
|
|
|
518
474
|
#### tool_call
|
|
@@ -531,8 +487,6 @@ pi.on("tool_call", async (event, ctx) => {
|
|
|
531
487
|
});
|
|
532
488
|
```
|
|
533
489
|
|
|
534
|
-
**Examples:** [chalk-logger.ts](../examples/extensions/chalk-logger.ts), [permission-gate.ts](../examples/extensions/permission-gate.ts), [plan-mode/index.ts](../examples/extensions/plan-mode/index.ts), [protected-paths.ts](../examples/extensions/protected-paths.ts)
|
|
535
|
-
|
|
536
490
|
#### tool_result
|
|
537
491
|
|
|
538
492
|
Fired after tool executes. **Can modify result.**
|
|
@@ -553,8 +507,6 @@ pi.on("tool_result", async (event, ctx) => {
|
|
|
553
507
|
});
|
|
554
508
|
```
|
|
555
509
|
|
|
556
|
-
**Examples:** [git-checkpoint.ts](../examples/extensions/git-checkpoint.ts), [plan-mode/index.ts](../examples/extensions/plan-mode/index.ts)
|
|
557
|
-
|
|
558
510
|
### User Bash Events
|
|
559
511
|
|
|
560
512
|
#### user_bash
|
|
@@ -575,8 +527,6 @@ pi.on("user_bash", (event, ctx) => {
|
|
|
575
527
|
});
|
|
576
528
|
```
|
|
577
529
|
|
|
578
|
-
**Examples:** [ssh.ts](../examples/extensions/ssh.ts), [interactive-shell.ts](../examples/extensions/interactive-shell.ts)
|
|
579
|
-
|
|
580
530
|
### Input Events
|
|
581
531
|
|
|
582
532
|
#### input
|
|
@@ -643,7 +593,7 @@ Current working directory.
|
|
|
643
593
|
|
|
644
594
|
### ctx.sessionManager
|
|
645
595
|
|
|
646
|
-
Read-only access to session state
|
|
596
|
+
Read-only access to session state. See [session.md](session.md) for the full SessionManager API and entry types.
|
|
647
597
|
|
|
648
598
|
```typescript
|
|
649
599
|
ctx.sessionManager.getEntries() // All entries
|
|
@@ -811,8 +761,6 @@ pi.registerTool({
|
|
|
811
761
|
});
|
|
812
762
|
```
|
|
813
763
|
|
|
814
|
-
**Examples:** [hello.ts](../examples/extensions/hello.ts), [question.ts](../examples/extensions/question.ts), [questionnaire.ts](../examples/extensions/questionnaire.ts), [todo.ts](../examples/extensions/todo.ts), [truncated-tool.ts](../examples/extensions/truncated-tool.ts)
|
|
815
|
-
|
|
816
764
|
### pi.sendMessage(message, options?)
|
|
817
765
|
|
|
818
766
|
Inject a custom message into the session.
|
|
@@ -836,8 +784,6 @@ pi.sendMessage({
|
|
|
836
784
|
- `"nextTurn"` - Queued for next user prompt. Does not interrupt or trigger anything.
|
|
837
785
|
- `triggerTurn: true` - If agent is idle, trigger an LLM response immediately. Only applies to `"steer"` and `"followUp"` modes (ignored for `"nextTurn"`).
|
|
838
786
|
|
|
839
|
-
**Examples:** [file-trigger.ts](../examples/extensions/file-trigger.ts), [plan-mode/index.ts](../examples/extensions/plan-mode/index.ts)
|
|
840
|
-
|
|
841
787
|
### pi.sendUserMessage(content, options?)
|
|
842
788
|
|
|
843
789
|
Send a user message to the agent. Unlike `sendMessage()` which sends custom messages, this sends an actual user message that appears as if typed by the user. Always triggers a turn.
|
|
@@ -883,8 +829,6 @@ pi.on("session_start", async (_event, ctx) => {
|
|
|
883
829
|
});
|
|
884
830
|
```
|
|
885
831
|
|
|
886
|
-
**Examples:** [plan-mode/index.ts](../examples/extensions/plan-mode/index.ts), [preset.ts](../examples/extensions/preset.ts), [snake.ts](../examples/extensions/snake.ts), [tools.ts](../examples/extensions/tools.ts)
|
|
887
|
-
|
|
888
832
|
### pi.setSessionName(name)
|
|
889
833
|
|
|
890
834
|
Set the session display name (shown in session selector instead of first message).
|
|
@@ -954,15 +898,13 @@ pi.registerCommand("deploy", {
|
|
|
954
898
|
});
|
|
955
899
|
```
|
|
956
900
|
|
|
957
|
-
**Examples:** [custom-footer.ts](../examples/extensions/custom-footer.ts), [custom-header.ts](../examples/extensions/custom-header.ts), [handoff.ts](../examples/extensions/handoff.ts), [pirate.ts](../examples/extensions/pirate.ts), [plan-mode/index.ts](../examples/extensions/plan-mode/index.ts), [preset.ts](../examples/extensions/preset.ts), [qna.ts](../examples/extensions/qna.ts), [send-user-message.ts](../examples/extensions/send-user-message.ts), [snake.ts](../examples/extensions/snake.ts), [summarize.ts](../examples/extensions/summarize.ts), [todo.ts](../examples/extensions/todo.ts), [tools.ts](../examples/extensions/tools.ts)
|
|
958
|
-
|
|
959
901
|
### pi.registerMessageRenderer(customType, renderer)
|
|
960
902
|
|
|
961
903
|
Register a custom TUI renderer for messages with your `customType`. See [Custom UI](#custom-ui).
|
|
962
904
|
|
|
963
905
|
### pi.registerShortcut(shortcut, options)
|
|
964
906
|
|
|
965
|
-
Register a keyboard shortcut.
|
|
907
|
+
Register a keyboard shortcut. See [keybindings.md](keybindings.md) for the shortcut format and built-in keybindings.
|
|
966
908
|
|
|
967
909
|
```typescript
|
|
968
910
|
pi.registerShortcut("ctrl+shift+p", {
|
|
@@ -973,8 +915,6 @@ pi.registerShortcut("ctrl+shift+p", {
|
|
|
973
915
|
});
|
|
974
916
|
```
|
|
975
917
|
|
|
976
|
-
**Examples:** [plan-mode/index.ts](../examples/extensions/plan-mode/index.ts), [preset.ts](../examples/extensions/preset.ts)
|
|
977
|
-
|
|
978
918
|
### pi.registerFlag(name, options)
|
|
979
919
|
|
|
980
920
|
Register a CLI flag.
|
|
@@ -992,8 +932,6 @@ if (pi.getFlag("--plan")) {
|
|
|
992
932
|
}
|
|
993
933
|
```
|
|
994
934
|
|
|
995
|
-
**Examples:** [plan-mode/index.ts](../examples/extensions/plan-mode/index.ts), [preset.ts](../examples/extensions/preset.ts)
|
|
996
|
-
|
|
997
935
|
### pi.exec(command, args, options?)
|
|
998
936
|
|
|
999
937
|
Execute a shell command.
|
|
@@ -1003,8 +941,6 @@ const result = await pi.exec("git", ["status"], { signal, timeout: 5000 });
|
|
|
1003
941
|
// result.stdout, result.stderr, result.code, result.killed
|
|
1004
942
|
```
|
|
1005
943
|
|
|
1006
|
-
**Examples:** [auto-commit-on-exit.ts](../examples/extensions/auto-commit-on-exit.ts), [dirty-repo-guard.ts](../examples/extensions/dirty-repo-guard.ts), [git-checkpoint.ts](../examples/extensions/git-checkpoint.ts)
|
|
1007
|
-
|
|
1008
944
|
### pi.getActiveTools() / pi.getAllTools() / pi.setActiveTools(names)
|
|
1009
945
|
|
|
1010
946
|
Manage active tools.
|
|
@@ -1016,11 +952,9 @@ const names = all.map(t => t.name); // Just names if needed
|
|
|
1016
952
|
pi.setActiveTools(["read", "bash"]); // Switch to read-only
|
|
1017
953
|
```
|
|
1018
954
|
|
|
1019
|
-
**Examples:** [plan-mode/index.ts](../examples/extensions/plan-mode/index.ts), [preset.ts](../examples/extensions/preset.ts), [tools.ts](../examples/extensions/tools.ts)
|
|
1020
|
-
|
|
1021
955
|
### pi.setModel(model)
|
|
1022
956
|
|
|
1023
|
-
Set the current model. Returns `false` if no API key is available for the model.
|
|
957
|
+
Set the current model. Returns `false` if no API key is available for the model. See [models.md](models.md) for configuring custom models.
|
|
1024
958
|
|
|
1025
959
|
```typescript
|
|
1026
960
|
const model = ctx.modelRegistry.find("anthropic", "claude-sonnet-4-5");
|
|
@@ -1032,8 +966,6 @@ if (model) {
|
|
|
1032
966
|
}
|
|
1033
967
|
```
|
|
1034
968
|
|
|
1035
|
-
**Examples:** [preset.ts](../examples/extensions/preset.ts)
|
|
1036
|
-
|
|
1037
969
|
### pi.getThinkingLevel() / pi.setThinkingLevel(level)
|
|
1038
970
|
|
|
1039
971
|
Get or set the thinking level. Level is clamped to model capabilities (non-reasoning models always use "off").
|
|
@@ -1043,8 +975,6 @@ const current = pi.getThinkingLevel(); // "off" | "minimal" | "low" | "medium"
|
|
|
1043
975
|
pi.setThinkingLevel("high");
|
|
1044
976
|
```
|
|
1045
977
|
|
|
1046
|
-
**Examples:** [preset.ts](../examples/extensions/preset.ts)
|
|
1047
|
-
|
|
1048
978
|
### pi.events
|
|
1049
979
|
|
|
1050
980
|
Shared event bus for communication between extensions:
|
|
@@ -1054,6 +984,70 @@ pi.events.on("my:event", (data) => { ... });
|
|
|
1054
984
|
pi.events.emit("my:event", { ... });
|
|
1055
985
|
```
|
|
1056
986
|
|
|
987
|
+
### pi.registerProvider(name, config)
|
|
988
|
+
|
|
989
|
+
Register or override a model provider dynamically. Useful for proxies, custom endpoints, or team-wide model configurations.
|
|
990
|
+
|
|
991
|
+
```typescript
|
|
992
|
+
// Register a new provider with custom models
|
|
993
|
+
pi.registerProvider("my-proxy", {
|
|
994
|
+
baseUrl: "https://proxy.example.com",
|
|
995
|
+
apiKey: "PROXY_API_KEY", // env var name or literal
|
|
996
|
+
api: "anthropic-messages",
|
|
997
|
+
models: [
|
|
998
|
+
{
|
|
999
|
+
id: "claude-sonnet-4-20250514",
|
|
1000
|
+
name: "Claude 4 Sonnet (proxy)",
|
|
1001
|
+
reasoning: false,
|
|
1002
|
+
input: ["text", "image"],
|
|
1003
|
+
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
|
1004
|
+
contextWindow: 200000,
|
|
1005
|
+
maxTokens: 16384
|
|
1006
|
+
}
|
|
1007
|
+
]
|
|
1008
|
+
});
|
|
1009
|
+
|
|
1010
|
+
// Override baseUrl for an existing provider (keeps all models)
|
|
1011
|
+
pi.registerProvider("anthropic", {
|
|
1012
|
+
baseUrl: "https://proxy.example.com"
|
|
1013
|
+
});
|
|
1014
|
+
|
|
1015
|
+
// Register provider with OAuth support for /login
|
|
1016
|
+
pi.registerProvider("corporate-ai", {
|
|
1017
|
+
baseUrl: "https://ai.corp.com",
|
|
1018
|
+
api: "openai-responses",
|
|
1019
|
+
models: [...],
|
|
1020
|
+
oauth: {
|
|
1021
|
+
name: "Corporate AI (SSO)",
|
|
1022
|
+
async login(callbacks) {
|
|
1023
|
+
// Custom OAuth flow
|
|
1024
|
+
callbacks.onAuth({ url: "https://sso.corp.com/..." });
|
|
1025
|
+
const code = await callbacks.onPrompt({ message: "Enter code:" });
|
|
1026
|
+
return { refresh: code, access: code, expires: Date.now() + 3600000 };
|
|
1027
|
+
},
|
|
1028
|
+
async refreshToken(credentials) {
|
|
1029
|
+
// Refresh logic
|
|
1030
|
+
return credentials;
|
|
1031
|
+
},
|
|
1032
|
+
getApiKey(credentials) {
|
|
1033
|
+
return credentials.access;
|
|
1034
|
+
}
|
|
1035
|
+
}
|
|
1036
|
+
});
|
|
1037
|
+
```
|
|
1038
|
+
|
|
1039
|
+
**Config options:**
|
|
1040
|
+
- `baseUrl` - API endpoint URL. Required when defining models.
|
|
1041
|
+
- `apiKey` - API key or environment variable name. Required when defining models (unless `oauth` provided).
|
|
1042
|
+
- `api` - API type: `"anthropic-messages"`, `"openai-completions"`, `"openai-responses"`, etc.
|
|
1043
|
+
- `headers` - Custom headers to include in requests.
|
|
1044
|
+
- `authHeader` - If true, adds `Authorization: Bearer` header automatically.
|
|
1045
|
+
- `models` - Array of model definitions. If provided, replaces all existing models for this provider.
|
|
1046
|
+
- `oauth` - OAuth provider config for `/login` support. When provided, the provider appears in the login menu.
|
|
1047
|
+
- `streamSimple` - Custom streaming implementation for non-standard APIs.
|
|
1048
|
+
|
|
1049
|
+
See [custom-provider.md](custom-provider.md) for advanced topics: custom streaming APIs, OAuth details, model definition reference.
|
|
1050
|
+
|
|
1057
1051
|
## State Management
|
|
1058
1052
|
|
|
1059
1053
|
Extensions with state should store it in tool result `details` for proper branching support:
|
|
@@ -1214,6 +1208,7 @@ The built-in limit is **50KB** (~10k tokens) and **2000 lines**, whichever is hi
|
|
|
1214
1208
|
import {
|
|
1215
1209
|
truncateHead, // Keep first N lines/bytes (good for file reads, search results)
|
|
1216
1210
|
truncateTail, // Keep last N lines/bytes (good for logs, command output)
|
|
1211
|
+
truncateLine, // Truncate a single line to maxBytes with ellipsis
|
|
1217
1212
|
formatSize, // Human-readable size (e.g., "50KB", "1.5MB")
|
|
1218
1213
|
DEFAULT_MAX_BYTES, // 50KB
|
|
1219
1214
|
DEFAULT_MAX_LINES, // 2000
|
|
@@ -1272,7 +1267,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
1272
1267
|
|
|
1273
1268
|
### Custom Rendering
|
|
1274
1269
|
|
|
1275
|
-
Tools can provide `renderCall` and `renderResult` for custom TUI display. See [tui.md](tui.md) for the full component API.
|
|
1270
|
+
Tools can provide `renderCall` and `renderResult` for custom TUI display. See [tui.md](tui.md) for the full component API and [tool-execution.ts](https://github.com/badlogic/pi-mono/blob/main/packages/coding-agent/src/modes/interactive/components/tool-execution.ts) for how built-in tools render.
|
|
1276
1271
|
|
|
1277
1272
|
Tool output is wrapped in a `Box` that handles padding and background. Your render methods return `Component` instances (typically `Text`).
|
|
1278
1273
|
|
|
@@ -1388,12 +1383,6 @@ const text = await ctx.ui.editor("Edit:", "prefilled text");
|
|
|
1388
1383
|
ctx.ui.notify("Done!", "info"); // "info" | "warning" | "error"
|
|
1389
1384
|
```
|
|
1390
1385
|
|
|
1391
|
-
**Examples:**
|
|
1392
|
-
- `ctx.ui.select()`: [confirm-destructive.ts](../examples/extensions/confirm-destructive.ts), [dirty-repo-guard.ts](../examples/extensions/dirty-repo-guard.ts), [git-checkpoint.ts](../examples/extensions/git-checkpoint.ts), [permission-gate.ts](../examples/extensions/permission-gate.ts), [plan-mode/index.ts](../examples/extensions/plan-mode/index.ts), [question.ts](../examples/extensions/question.ts), [questionnaire.ts](../examples/extensions/questionnaire.ts)
|
|
1393
|
-
- `ctx.ui.confirm()`: [confirm-destructive.ts](../examples/extensions/confirm-destructive.ts)
|
|
1394
|
-
- `ctx.ui.editor()`: [handoff.ts](../examples/extensions/handoff.ts)
|
|
1395
|
-
- `ctx.ui.setEditorText()`: [handoff.ts](../examples/extensions/handoff.ts), [qna.ts](../examples/extensions/qna.ts)
|
|
1396
|
-
|
|
1397
1386
|
#### Timed Dialogs with Countdown
|
|
1398
1387
|
|
|
1399
1388
|
Dialogs support a `timeout` option that auto-dismisses with a live countdown display:
|
|
@@ -1481,7 +1470,7 @@ const current = ctx.ui.getEditorText();
|
|
|
1481
1470
|
ctx.ui.setEditorComponent((tui, theme, keybindings) => new VimEditor(tui, theme, keybindings));
|
|
1482
1471
|
ctx.ui.setEditorComponent(undefined); // Restore default editor
|
|
1483
1472
|
|
|
1484
|
-
// Theme management
|
|
1473
|
+
// Theme management (see themes.md for creating themes)
|
|
1485
1474
|
const themes = ctx.ui.getAllThemes(); // [{ name: "dark", path: "/..." | undefined }, ...]
|
|
1486
1475
|
const lightTheme = ctx.ui.getTheme("light"); // Load without switching
|
|
1487
1476
|
const result = ctx.ui.setTheme("light"); // Switch by name
|
|
@@ -1492,14 +1481,6 @@ ctx.ui.setTheme(lightTheme!); // Or switch by Theme object
|
|
|
1492
1481
|
ctx.ui.theme.fg("accent", "styled text"); // Access current theme
|
|
1493
1482
|
```
|
|
1494
1483
|
|
|
1495
|
-
**Examples:**
|
|
1496
|
-
- `ctx.ui.setStatus()`: [plan-mode/index.ts](../examples/extensions/plan-mode/index.ts), [preset.ts](../examples/extensions/preset.ts), [status-line.ts](../examples/extensions/status-line.ts)
|
|
1497
|
-
- `ctx.ui.setWidget()`: [plan-mode/index.ts](../examples/extensions/plan-mode/index.ts)
|
|
1498
|
-
- `ctx.ui.setFooter()`: [custom-footer.ts](../examples/extensions/custom-footer.ts)
|
|
1499
|
-
- `ctx.ui.setHeader()`: [custom-header.ts](../examples/extensions/custom-header.ts)
|
|
1500
|
-
- `ctx.ui.setEditorComponent()`: [modal-editor.ts](../examples/extensions/modal-editor.ts)
|
|
1501
|
-
- `ctx.ui.setTheme()`: [mac-system-theme.ts](../examples/extensions/mac-system-theme.ts)
|
|
1502
|
-
|
|
1503
1484
|
### Custom Components
|
|
1504
1485
|
|
|
1505
1486
|
For complex UI, use `ctx.ui.custom()`. This temporarily replaces the editor with your component until `done()` is called:
|
|
@@ -1558,8 +1539,6 @@ const result = await ctx.ui.custom<string | null>(
|
|
|
1558
1539
|
|
|
1559
1540
|
See [tui.md](tui.md) for the full `OverlayOptions` API and [overlay-qa-tests.ts](../examples/extensions/overlay-qa-tests.ts) for examples.
|
|
1560
1541
|
|
|
1561
|
-
**Examples:** [handoff.ts](../examples/extensions/handoff.ts), [plan-mode/index.ts](../examples/extensions/plan-mode/index.ts), [preset.ts](../examples/extensions/preset.ts), [qna.ts](../examples/extensions/qna.ts), [snake.ts](../examples/extensions/snake.ts), [summarize.ts](../examples/extensions/summarize.ts), [todo.ts](../examples/extensions/todo.ts), [tools.ts](../examples/extensions/tools.ts), [overlay-test.ts](../examples/extensions/overlay-test.ts)
|
|
1562
|
-
|
|
1563
1542
|
### Custom Editor
|
|
1564
1543
|
|
|
1565
1544
|
Replace the main input editor with a custom implementation (vim mode, emacs mode, etc.):
|
|
@@ -1601,8 +1580,6 @@ export default function (pi: ExtensionAPI) {
|
|
|
1601
1580
|
|
|
1602
1581
|
See [tui.md](tui.md) Pattern 7 for a complete example with mode indicator.
|
|
1603
1582
|
|
|
1604
|
-
**Examples:** [modal-editor.ts](../examples/extensions/modal-editor.ts)
|
|
1605
|
-
|
|
1606
1583
|
### Message Rendering
|
|
1607
1584
|
|
|
1608
1585
|
Register a custom renderer for messages with your `customType`:
|
|
@@ -1636,7 +1613,7 @@ pi.sendMessage({
|
|
|
1636
1613
|
|
|
1637
1614
|
### Theme Colors
|
|
1638
1615
|
|
|
1639
|
-
All render functions receive a `theme` object
|
|
1616
|
+
All render functions receive a `theme` object. See [themes.md](themes.md) for creating custom themes and the full color palette.
|
|
1640
1617
|
|
|
1641
1618
|
```typescript
|
|
1642
1619
|
// Foreground colors
|
|
@@ -1654,6 +1631,19 @@ theme.italic(text)
|
|
|
1654
1631
|
theme.strikethrough(text)
|
|
1655
1632
|
```
|
|
1656
1633
|
|
|
1634
|
+
For syntax highlighting in custom tool renderers:
|
|
1635
|
+
|
|
1636
|
+
```typescript
|
|
1637
|
+
import { highlightCode, getLanguageFromPath } from "@mariozechner/pi-coding-agent";
|
|
1638
|
+
|
|
1639
|
+
// Highlight code with explicit language
|
|
1640
|
+
const highlighted = highlightCode("const x = 1;", "typescript", theme);
|
|
1641
|
+
|
|
1642
|
+
// Auto-detect language from file path
|
|
1643
|
+
const lang = getLanguageFromPath("/path/to/file.rs"); // "rust"
|
|
1644
|
+
const highlighted = highlightCode(code, lang, theme);
|
|
1645
|
+
```
|
|
1646
|
+
|
|
1657
1647
|
## Error Handling
|
|
1658
1648
|
|
|
1659
1649
|
- Extension errors are logged, agent continues
|
|
@@ -1665,7 +1655,81 @@ theme.strikethrough(text)
|
|
|
1665
1655
|
| Mode | UI Methods | Notes |
|
|
1666
1656
|
|------|-----------|-------|
|
|
1667
1657
|
| Interactive | Full TUI | Normal operation |
|
|
1668
|
-
| RPC | JSON protocol | Host handles UI |
|
|
1658
|
+
| RPC (`--mode rpc`) | JSON protocol | Host handles UI, see [rpc.md](rpc.md) |
|
|
1659
|
+
| JSON (`--mode json`) | No-op | Event stream to stdout, see [json.md](json.md) |
|
|
1669
1660
|
| Print (`-p`) | No-op | Extensions run but can't prompt |
|
|
1670
1661
|
|
|
1671
|
-
In
|
|
1662
|
+
In non-interactive modes, check `ctx.hasUI` before using UI methods.
|
|
1663
|
+
|
|
1664
|
+
## Examples Reference
|
|
1665
|
+
|
|
1666
|
+
All examples in [examples/extensions/](../examples/extensions/).
|
|
1667
|
+
|
|
1668
|
+
| Example | Description | Key APIs |
|
|
1669
|
+
|---------|-------------|----------|
|
|
1670
|
+
| **Tools** |||
|
|
1671
|
+
| `hello.ts` | Minimal tool registration | `registerTool` |
|
|
1672
|
+
| `question.ts` | Tool with user interaction | `registerTool`, `ui.select` |
|
|
1673
|
+
| `questionnaire.ts` | Multi-step wizard tool | `registerTool`, `ui.custom` |
|
|
1674
|
+
| `todo.ts` | Stateful tool with persistence | `registerTool`, `appendEntry`, `renderResult`, session events |
|
|
1675
|
+
| `truncated-tool.ts` | Output truncation example | `registerTool`, `truncateHead` |
|
|
1676
|
+
| `tool-override.ts` | Override built-in read tool | `registerTool` (same name as built-in) |
|
|
1677
|
+
| **Commands** |||
|
|
1678
|
+
| `pirate.ts` | Modify system prompt per-turn | `registerCommand`, `before_agent_start` |
|
|
1679
|
+
| `summarize.ts` | Conversation summary command | `registerCommand`, `ui.custom` |
|
|
1680
|
+
| `handoff.ts` | Cross-provider model handoff | `registerCommand`, `ui.editor`, `ui.custom` |
|
|
1681
|
+
| `qna.ts` | Q&A with custom UI | `registerCommand`, `ui.custom`, `setEditorText` |
|
|
1682
|
+
| `send-user-message.ts` | Inject user messages | `registerCommand`, `sendUserMessage` |
|
|
1683
|
+
| `shutdown-command.ts` | Graceful shutdown command | `registerCommand`, `shutdown()` |
|
|
1684
|
+
| **Events & Gates** |||
|
|
1685
|
+
| `permission-gate.ts` | Block dangerous commands | `on("tool_call")`, `ui.confirm` |
|
|
1686
|
+
| `protected-paths.ts` | Block writes to specific paths | `on("tool_call")` |
|
|
1687
|
+
| `confirm-destructive.ts` | Confirm session changes | `on("session_before_switch")`, `on("session_before_fork")` |
|
|
1688
|
+
| `dirty-repo-guard.ts` | Warn on dirty git repo | `on("session_before_*")`, `exec` |
|
|
1689
|
+
| `input-transform.ts` | Transform user input | `on("input")` |
|
|
1690
|
+
| `model-status.ts` | React to model changes | `on("model_select")`, `setStatus` |
|
|
1691
|
+
| `claude-rules.ts` | Load rules from files | `on("session_start")`, `on("before_agent_start")` |
|
|
1692
|
+
| `file-trigger.ts` | File watcher triggers messages | `sendMessage` |
|
|
1693
|
+
| **Compaction & Sessions** |||
|
|
1694
|
+
| `custom-compaction.ts` | Custom compaction summary | `on("session_before_compact")` |
|
|
1695
|
+
| `trigger-compact.ts` | Trigger compaction manually | `compact()` |
|
|
1696
|
+
| `git-checkpoint.ts` | Git stash on turns | `on("turn_end")`, `on("session_fork")`, `exec` |
|
|
1697
|
+
| `auto-commit-on-exit.ts` | Commit on shutdown | `on("session_shutdown")`, `exec` |
|
|
1698
|
+
| **UI Components** |||
|
|
1699
|
+
| `status-line.ts` | Footer status indicator | `setStatus`, session events |
|
|
1700
|
+
| `custom-footer.ts` | Replace footer entirely | `registerCommand`, `setFooter` |
|
|
1701
|
+
| `custom-header.ts` | Replace startup header | `on("session_start")`, `setHeader` |
|
|
1702
|
+
| `modal-editor.ts` | Vim-style modal editor | `setEditorComponent`, `CustomEditor` |
|
|
1703
|
+
| `rainbow-editor.ts` | Custom editor styling | `setEditorComponent` |
|
|
1704
|
+
| `widget-placement.ts` | Widget above/below editor | `setWidget` |
|
|
1705
|
+
| `overlay-test.ts` | Overlay components | `ui.custom` with overlay options |
|
|
1706
|
+
| `overlay-qa-tests.ts` | Comprehensive overlay tests | `ui.custom`, all overlay options |
|
|
1707
|
+
| `notify.ts` | Simple notifications | `ui.notify` |
|
|
1708
|
+
| `timed-confirm.ts` | Dialogs with timeout | `ui.confirm` with timeout/signal |
|
|
1709
|
+
| `mac-system-theme.ts` | Auto-switch theme | `setTheme`, `exec` |
|
|
1710
|
+
| **Complex Extensions** |||
|
|
1711
|
+
| `plan-mode/` | Full plan mode implementation | All event types, `registerCommand`, `registerShortcut`, `registerFlag`, `setStatus`, `setWidget`, `sendMessage`, `setActiveTools` |
|
|
1712
|
+
| `preset.ts` | Saveable presets (model, tools, thinking) | `registerCommand`, `registerShortcut`, `registerFlag`, `setModel`, `setActiveTools`, `setThinkingLevel`, `appendEntry` |
|
|
1713
|
+
| `tools.ts` | Toggle tools on/off UI | `registerCommand`, `setActiveTools`, `SettingsList`, session events |
|
|
1714
|
+
| **Remote & Sandbox** |||
|
|
1715
|
+
| `ssh.ts` | SSH remote execution | `registerFlag`, `on("user_bash")`, `on("before_agent_start")`, tool operations |
|
|
1716
|
+
| `interactive-shell.ts` | Persistent shell session | `on("user_bash")` |
|
|
1717
|
+
| `sandbox/` | Sandboxed tool execution | Tool operations |
|
|
1718
|
+
| `subagent/` | Spawn sub-agents | `registerTool`, `exec` |
|
|
1719
|
+
| **Games** |||
|
|
1720
|
+
| `snake.ts` | Snake game | `registerCommand`, `ui.custom`, keyboard handling |
|
|
1721
|
+
| `space-invaders.ts` | Space Invaders game | `registerCommand`, `ui.custom` |
|
|
1722
|
+
| `doom-overlay/` | Doom in overlay | `ui.custom` with overlay |
|
|
1723
|
+
| **Providers** |||
|
|
1724
|
+
| `custom-provider-anthropic/` | Custom Anthropic proxy | `registerProvider` |
|
|
1725
|
+
| `custom-provider-gitlab-duo/` | GitLab Duo integration | `registerProvider` with OAuth |
|
|
1726
|
+
| **Messages & Communication** |||
|
|
1727
|
+
| `message-renderer.ts` | Custom message rendering | `registerMessageRenderer`, `sendMessage` |
|
|
1728
|
+
| `event-bus.ts` | Inter-extension events | `pi.events` |
|
|
1729
|
+
| **Session Metadata** |||
|
|
1730
|
+
| `session-name.ts` | Name sessions for selector | `setSessionName`, `getSessionName` |
|
|
1731
|
+
| `bookmark.ts` | Bookmark entries for /tree | `setLabel` |
|
|
1732
|
+
| **Misc** |||
|
|
1733
|
+
| `antigravity-image-gen.ts` | Image generation tool | `registerTool`, Google Antigravity |
|
|
1734
|
+
| `inline-bash.ts` | Inline bash in tool calls | `on("tool_call")` |
|
|
1735
|
+
| `with-deps/` | Extension with npm dependencies | Package structure with `package.json` |
|
|
Binary file
|
|
Binary file
|
|
Binary file
|