From 58575888f5a796462ca1a9ab1f64e13fa16728d0 Mon Sep 17 00:00:00 2001 From: Mario Zechner Date: Fri, 17 Jul 2026 09:35:48 +0200 Subject: [PATCH] docs(coding-agent): fix obsolete extension UI examples closes #6735 --- packages/coding-agent/CHANGELOG.md | 4 ++ packages/coding-agent/docs/extensions.md | 6 +- packages/coding-agent/docs/tui.md | 67 ++++++++++++------- .../examples/extensions/README.md | 2 +- 4 files changed, 49 insertions(+), 30 deletions(-) diff --git a/packages/coding-agent/CHANGELOG.md b/packages/coding-agent/CHANGELOG.md index c4cdaefe..3eefbc25 100644 --- a/packages/coding-agent/CHANGELOG.md +++ b/packages/coding-agent/CHANGELOG.md @@ -2,6 +2,10 @@ ## [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 ### New Features diff --git a/packages/coding-agent/docs/extensions.md b/packages/coding-agent/docs/extensions.md index ec1ea00a..00a763ad 100644 --- a/packages/coding-agent/docs/extensions.md +++ b/packages/coding-agent/docs/extensions.md @@ -2708,8 +2708,8 @@ class VimEditor extends CustomEditor { export default function (pi: ExtensionAPI) { pi.on("session_start", (_event, ctx) => { - ctx.ui.setEditorComponent((_tui, theme, keybindings) => - new VimEditor(theme, keybindings) + ctx.ui.setEditorComponent((tui, theme, keybindings) => + new VimEditor(tui, theme, keybindings) ); }); } @@ -2718,7 +2718,7 @@ export default function (pi: ExtensionAPI) { **Key points:** - 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 -- 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 - Pass `undefined` to restore default: `ctx.ui.setEditorComponent(undefined)` diff --git a/packages/coding-agent/docs/tui.md b/packages/coding-agent/docs/tui.md index ca036ee1..d9f78929 100644 --- a/packages/coding-agent/docs/tui.md +++ b/packages/coding-agent/docs/tui.md @@ -90,19 +90,32 @@ Without this propagation, typing with an IME (Chinese, Japanese, Korean, etc.) w ```typescript pi.on("session_start", async (_event, ctx) => { - const handle = ctx.ui.custom(myComponent); - // handle.requestRender() - trigger re-render - // handle.close() - restore normal UI + const result = await ctx.ui.custom((tui, theme, keybindings, done) => + new MyComponent({ + 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 -async execute(toolCallId, params, onUpdate, ctx, signal) { - const handle = pi.ui.custom(myComponent); - // ... - handle.close(); +async execute(toolCallId, params, signal, onUpdate, ctx) { + const result = await ctx.ui.custom((tui, theme, keybindings, done) => + new MyComponent({ + theme, + keybindings, + onChange: () => tui.requestRender(), + onSelect: (value) => done(value), + onCancel: () => done(null), + }) + ); + // Use result... } ``` @@ -374,24 +387,26 @@ Usage in an extension: ```typescript pi.registerCommand("pick", { description: "Pick an item", - handler: async (args, ctx) => { + handler: async (_args, ctx) => { const items = ["Option A", "Option B", "Option C"]; - const selector = new MySelector(items); - - let handle: { close: () => void; requestRender: () => void }; - - await new Promise((resolve) => { - selector.onSelect = (item) => { - ctx.ui.notify(`Selected: ${item}`, "info"); - handle.close(); - resolve(); + const selected = await ctx.ui.custom((tui, _theme, _keybindings, done) => { + const selector = new MySelector(items); + selector.onSelect = done; + selector.onCancel = () => done(null); + + return { + render: (width) => selector.render(width), + handleInput: (data) => { + 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 @@ -885,9 +900,9 @@ class VimEditor extends CustomEditor { export default function (pi: ExtensionAPI) { 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) => - new VimEditor(theme, keybindings) + new VimEditor(tui, theme, keybindings) ); }); } diff --git a/packages/coding-agent/examples/extensions/README.md b/packages/coding-agent/examples/extensions/README.md index c34e9825..d60d6e38 100644 --- a/packages/coding-agent/examples/extensions/README.md +++ b/packages/coding-agent/examples/extensions/README.md @@ -162,7 +162,7 @@ export default function (pi: ExtensionAPI) { parameters: Type.Object({ name: Type.String({ description: "Name to greet" }), }), - async execute(toolCallId, params, onUpdate, ctx, signal) { + async execute(toolCallId, params, signal, onUpdate, ctx) { return { content: [{ type: "text", text: `Hello, ${params.name}!` }], details: {},