docs(coding-agent): fix obsolete extension UI examples closes #6735

This commit is contained in:
Mario Zechner
2026-07-17 09:35:48 +02:00
parent e5e8726836
commit 58575888f5
4 changed files with 49 additions and 30 deletions
+4
View File
@@ -2,6 +2,10 @@
## [Unreleased] ## [Unreleased]
### Fixed
- Fixed obsolete custom UI, custom tool, and custom editor examples in the extension documentation ([#6735](https://github.com/earendil-works/pi/issues/6735)).
## [0.80.10] - 2026-07-16 ## [0.80.10] - 2026-07-16
### New Features ### New Features
+3 -3
View File
@@ -2708,8 +2708,8 @@ class VimEditor extends CustomEditor {
export default function (pi: ExtensionAPI) { export default function (pi: ExtensionAPI) {
pi.on("session_start", (_event, ctx) => { pi.on("session_start", (_event, ctx) => {
ctx.ui.setEditorComponent((_tui, theme, keybindings) => ctx.ui.setEditorComponent((tui, theme, keybindings) =>
new VimEditor(theme, keybindings) new VimEditor(tui, theme, keybindings)
); );
}); });
} }
@@ -2718,7 +2718,7 @@ export default function (pi: ExtensionAPI) {
**Key points:** **Key points:**
- Extend `CustomEditor` (not base `Editor`) to get app keybindings (escape to abort, ctrl+d, model switching) - Extend `CustomEditor` (not base `Editor`) to get app keybindings (escape to abort, ctrl+d, model switching)
- Call `super.handleInput(data)` for keys you don't handle - Call `super.handleInput(data)` for keys you don't handle
- Factory receives `theme` and `keybindings` from the app - Factory receives `tui`, `theme`, and `keybindings` from the app
- Use `ctx.ui.getEditorComponent()` before `setEditorComponent()` to wrap the previously configured custom editor - Use `ctx.ui.getEditorComponent()` before `setEditorComponent()` to wrap the previously configured custom editor
- Pass `undefined` to restore default: `ctx.ui.setEditorComponent(undefined)` - Pass `undefined` to restore default: `ctx.ui.setEditorComponent(undefined)`
+41 -26
View File
@@ -90,19 +90,32 @@ Without this propagation, typing with an IME (Chinese, Japanese, Korean, etc.) w
```typescript ```typescript
pi.on("session_start", async (_event, ctx) => { pi.on("session_start", async (_event, ctx) => {
const handle = ctx.ui.custom(myComponent); const result = await ctx.ui.custom<string | null>((tui, theme, keybindings, done) =>
// handle.requestRender() - trigger re-render new MyComponent({
// handle.close() - restore normal UI theme,
keybindings,
onChange: () => tui.requestRender(),
onSelect: (value) => done(value),
onCancel: () => done(null),
})
);
}); });
``` ```
**In custom tools** via `pi.ui.custom()`: **In custom tools** via `ctx.ui.custom()`:
```typescript ```typescript
async execute(toolCallId, params, onUpdate, ctx, signal) { async execute(toolCallId, params, signal, onUpdate, ctx) {
const handle = pi.ui.custom(myComponent); const result = await ctx.ui.custom<string | null>((tui, theme, keybindings, done) =>
// ... new MyComponent({
handle.close(); theme,
keybindings,
onChange: () => tui.requestRender(),
onSelect: (value) => done(value),
onCancel: () => done(null),
})
);
// Use result...
} }
``` ```
@@ -374,24 +387,26 @@ Usage in an extension:
```typescript ```typescript
pi.registerCommand("pick", { pi.registerCommand("pick", {
description: "Pick an item", description: "Pick an item",
handler: async (args, ctx) => { handler: async (_args, ctx) => {
const items = ["Option A", "Option B", "Option C"]; const items = ["Option A", "Option B", "Option C"];
const selector = new MySelector(items); const selected = await ctx.ui.custom<string | null>((tui, _theme, _keybindings, done) => {
const selector = new MySelector(items);
let handle: { close: () => void; requestRender: () => void }; selector.onSelect = done;
selector.onCancel = () => done(null);
await new Promise<void>((resolve) => {
selector.onSelect = (item) => { return {
ctx.ui.notify(`Selected: ${item}`, "info"); render: (width) => selector.render(width),
handle.close(); handleInput: (data) => {
resolve(); selector.handleInput(data);
tui.requestRender();
},
invalidate: () => selector.invalidate(),
}; };
selector.onCancel = () => {
handle.close();
resolve();
};
handle = ctx.ui.custom(selector);
}); });
if (selected !== null) {
ctx.ui.notify(`Selected: ${selected}`, "info");
}
} }
}); });
``` ```
@@ -486,7 +501,7 @@ class CachedComponent {
} }
``` ```
Call `invalidate()` when state changes, then `handle.requestRender()` to trigger re-render. Call `invalidate()` when state changes, then use the injected `tui.requestRender()` to trigger re-render.
## Invalidation and Theme Changes ## Invalidation and Theme Changes
@@ -885,9 +900,9 @@ class VimEditor extends CustomEditor {
export default function (pi: ExtensionAPI) { export default function (pi: ExtensionAPI) {
pi.on("session_start", (_event, ctx) => { pi.on("session_start", (_event, ctx) => {
// Factory receives theme and keybindings from the app // Factory receives the TUI, theme, and keybindings from the app
ctx.ui.setEditorComponent((tui, theme, keybindings) => ctx.ui.setEditorComponent((tui, theme, keybindings) =>
new VimEditor(theme, keybindings) new VimEditor(tui, theme, keybindings)
); );
}); });
} }
@@ -162,7 +162,7 @@ export default function (pi: ExtensionAPI) {
parameters: Type.Object({ parameters: Type.Object({
name: Type.String({ description: "Name to greet" }), name: Type.String({ description: "Name to greet" }),
}), }),
async execute(toolCallId, params, onUpdate, ctx, signal) { async execute(toolCallId, params, signal, onUpdate, ctx) {
return { return {
content: [{ type: "text", text: `Hello, ${params.name}!` }], content: [{ type: "text", text: `Hello, ${params.name}!` }],
details: {}, details: {},