diff --git a/packages/coding-agent/docs/extensions.md b/packages/coding-agent/docs/extensions.md index 332ce755..09cae0a8 100644 --- a/packages/coding-agent/docs/extensions.md +++ b/packages/coding-agent/docs/extensions.md @@ -1556,6 +1556,9 @@ ctx.ui.setTitle("pi - my-project"); ctx.ui.setEditorText("Prefill text"); const current = ctx.ui.getEditorText(); +// Paste into editor (triggers paste handling, including collapse for large content) +ctx.ui.pasteToEditor("pasted content"); + // Tool output expansion const wasExpanded = ctx.ui.getToolsExpanded(); ctx.ui.setToolsExpanded(true); diff --git a/packages/coding-agent/src/core/extensions/runner.ts b/packages/coding-agent/src/core/extensions/runner.ts index 4b69c6eb..44bb323e 100644 --- a/packages/coding-agent/src/core/extensions/runner.ts +++ b/packages/coding-agent/src/core/extensions/runner.ts @@ -175,6 +175,7 @@ const noOpUIContext: ExtensionUIContext = { setHeader: () => {}, setTitle: () => {}, custom: async () => undefined as never, + pasteToEditor: () => {}, setEditorText: () => {}, getEditorText: () => "", editor: async () => undefined, diff --git a/packages/coding-agent/src/core/extensions/types.ts b/packages/coding-agent/src/core/extensions/types.ts index 45bf4806..4362b6af 100644 --- a/packages/coding-agent/src/core/extensions/types.ts +++ b/packages/coding-agent/src/core/extensions/types.ts @@ -162,6 +162,9 @@ export interface ExtensionUIContext { }, ): Promise; + /** Paste text into the editor, triggering paste handling (collapse for large content). */ + pasteToEditor(text: string): void; + /** Set the text in the core input editor. */ setEditorText(text: string): void; diff --git a/packages/coding-agent/src/modes/interactive/interactive-mode.ts b/packages/coding-agent/src/modes/interactive/interactive-mode.ts index 2d7207f1..b325c59e 100644 --- a/packages/coding-agent/src/modes/interactive/interactive-mode.ts +++ b/packages/coding-agent/src/modes/interactive/interactive-mode.ts @@ -1383,6 +1383,7 @@ export class InteractiveMode { setHeader: (factory) => this.setExtensionHeader(factory), setTitle: (title) => this.ui.terminal.setTitle(title), custom: (factory, options) => this.showExtensionCustom(factory, options), + pasteToEditor: (text) => this.editor.handleInput(`\x1b[200~${text}\x1b[201~`), setEditorText: (text) => this.editor.setText(text), getEditorText: () => this.editor.getText(), editor: (title, prefill) => this.showExtensionEditor(title, prefill), diff --git a/packages/coding-agent/src/modes/rpc/rpc-mode.ts b/packages/coding-agent/src/modes/rpc/rpc-mode.ts index 78b9849e..4ab920ce 100644 --- a/packages/coding-agent/src/modes/rpc/rpc-mode.ts +++ b/packages/coding-agent/src/modes/rpc/rpc-mode.ts @@ -197,6 +197,11 @@ export async function runRpcMode(session: AgentSession): Promise { return undefined as never; }, + pasteToEditor(text: string): void { + // Paste handling not supported in RPC mode - falls back to setEditorText + this.setEditorText(text); + }, + setEditorText(text: string): void { // Fire and forget - host can implement editor control output({ diff --git a/packages/tui/src/editor-component.ts b/packages/tui/src/editor-component.ts index 87ec9581..c6b6c43d 100644 --- a/packages/tui/src/editor-component.ts +++ b/packages/tui/src/editor-component.ts @@ -19,6 +19,9 @@ export interface EditorComponent extends Component { /** Set the text content */ setText(text: string): void; + /** Handle raw terminal input (key presses, paste sequences, etc.) */ + handleInput(data: string): void; + // ========================================================================= // Callbacks (required) // =========================================================================