mirror of
https://github.com/getcompanion-ai/co-mono.git
synced 2026-04-15 12:03:49 +00:00
feat(hooks): expose setTitle to HookUIContext (#446)
This commit is contained in:
parent
affa618b43
commit
5cb7af1ddc
9 changed files with 34 additions and 1 deletions
|
|
@ -2,6 +2,10 @@
|
|||
|
||||
## [Unreleased]
|
||||
|
||||
### Added
|
||||
|
||||
- Hook API: `ctx.ui.setTitle(title)` allows hooks to set the terminal window/tab title ([#446](https://github.com/badlogic/pi-mono/pull/446) by [@aliou](https://github.com/aliou))
|
||||
|
||||
### Changed
|
||||
|
||||
- Expanded keybinding documentation to list all 32 supported symbol keys with notes on ctrl+symbol behavior ([#450](https://github.com/badlogic/pi-mono/pull/450) by [@kaofelix](https://github.com/kaofelix))
|
||||
|
|
@ -1341,4 +1345,4 @@ Initial public release.
|
|||
- Git branch display in footer
|
||||
- Message queueing during streaming responses
|
||||
- OAuth integration for Gmail and Google Calendar access
|
||||
- HTML export with syntax highlighting and collapsible sections
|
||||
- HTML export with syntax highlighting and collapsible sections
|
||||
|
|
|
|||
|
|
@ -437,6 +437,9 @@ ctx.ui.setWidget("my-todos", [
|
|||
]);
|
||||
ctx.ui.setWidget("my-todos", undefined); // Clear widget
|
||||
|
||||
// Set the terminal window/tab title
|
||||
ctx.ui.setTitle("pi - my-project");
|
||||
|
||||
// Set the core input editor text (pre-fill prompts, generated content)
|
||||
ctx.ui.setEditorText("Generated prompt text here...");
|
||||
|
||||
|
|
@ -457,6 +460,10 @@ const currentText = ctx.ui.getEditorText();
|
|||
- Supports ANSI styling via `ctx.ui.theme` (including `strikethrough`)
|
||||
- **Caution:** Keep widgets small (a few lines). Large widgets from multiple hooks can cause viewport overflow and TUI flicker. Max 10 lines total across all string widgets.
|
||||
|
||||
**Terminal title notes:**
|
||||
- Uses OSC escape sequence (works in most modern terminals like iTerm2, Terminal.app, Windows Terminal)
|
||||
- Useful for showing project name, current task, or session status in the terminal tab/window title
|
||||
|
||||
**Custom widget components:**
|
||||
|
||||
For more complex widgets, pass a factory function to `setWidget()`:
|
||||
|
|
|
|||
|
|
@ -93,6 +93,7 @@ function createNoOpUIContext(): HookUIContext {
|
|||
notify: () => {},
|
||||
setStatus: () => {},
|
||||
setWidget: () => {},
|
||||
setTitle: () => {},
|
||||
custom: async () => undefined as never,
|
||||
setEditorText: () => {},
|
||||
getEditorText: () => "",
|
||||
|
|
|
|||
|
|
@ -59,6 +59,7 @@ const noOpUIContext: HookUIContext = {
|
|||
notify: () => {},
|
||||
setStatus: () => {},
|
||||
setWidget: () => {},
|
||||
setTitle: () => {},
|
||||
custom: async () => undefined as never,
|
||||
setEditorText: () => {},
|
||||
getEditorText: () => "",
|
||||
|
|
|
|||
|
|
@ -120,6 +120,13 @@ export interface HookUIContext {
|
|||
*/
|
||||
setWidget(key: string, content: ((tui: TUI, theme: Theme) => Component & { dispose?(): void }) | undefined): void;
|
||||
|
||||
/**
|
||||
* Set the terminal window/tab title.
|
||||
* Uses OSC escape sequence (works in most modern terminals).
|
||||
* @param title - Title text to display
|
||||
*/
|
||||
setTitle(title: string): void;
|
||||
|
||||
/**
|
||||
* Show a custom component with keyboard focus.
|
||||
* The factory receives TUI, theme, and a done() callback to close the component.
|
||||
|
|
|
|||
|
|
@ -685,6 +685,7 @@ export class InteractiveMode {
|
|||
notify: (message, type) => this.showHookNotify(message, type),
|
||||
setStatus: (key, text) => this.setHookStatus(key, text),
|
||||
setWidget: (key, content) => this.setHookWidget(key, content),
|
||||
setTitle: (title) => this.ui.terminal.setTitle(title),
|
||||
custom: (factory) => this.showHookCustom(factory),
|
||||
setEditorText: (text) => this.editor.setText(text),
|
||||
getEditorText: () => this.editor.getText(),
|
||||
|
|
|
|||
|
|
@ -145,6 +145,16 @@ export async function runRpcMode(session: AgentSession): Promise<never> {
|
|||
// Component factories are not supported in RPC mode - would need TUI access
|
||||
},
|
||||
|
||||
setTitle(title: string): void {
|
||||
// Fire and forget - host can implement terminal title control
|
||||
output({
|
||||
type: "hook_ui_request",
|
||||
id: crypto.randomUUID(),
|
||||
method: "setTitle",
|
||||
title,
|
||||
} as RpcHookUIRequest);
|
||||
},
|
||||
|
||||
async custom() {
|
||||
// Custom UI not supported in RPC mode
|
||||
return undefined as never;
|
||||
|
|
|
|||
|
|
@ -196,6 +196,7 @@ export type RpcHookUIRequest =
|
|||
widgetKey: string;
|
||||
widgetLines: string[] | undefined;
|
||||
}
|
||||
| { type: "hook_ui_request"; id: string; method: "setTitle"; title: string }
|
||||
| { type: "hook_ui_request"; id: string; method: "set_editor_text"; text: string };
|
||||
|
||||
// ============================================================================
|
||||
|
|
|
|||
|
|
@ -121,6 +121,7 @@ describe.skipIf(!API_KEY)("Compaction hooks", () => {
|
|||
notify: () => {},
|
||||
setStatus: () => {},
|
||||
setWidget: () => {},
|
||||
setTitle: () => {},
|
||||
custom: async () => undefined as never,
|
||||
setEditorText: () => {},
|
||||
getEditorText: () => "",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue