fix(coding-agent): refresh thinking border from extensions

closes #3888
This commit is contained in:
Mario Zechner
2026-04-30 22:49:31 +02:00
parent f7df474084
commit 95ae590279
5 changed files with 47 additions and 2 deletions

View File

@@ -8,6 +8,7 @@
- Added `message_end` extension result support for replacing finalized messages, enabling extensions to override assistant usage cost ([#3982](https://github.com/badlogic/pi-mono/issues/3982)).
- Added top-level `name` support to `pi.registerProvider()` so extension-registered providers can show a friendly name in `/login` ([#3956](https://github.com/badlogic/pi-mono/issues/3956)).
- Added `ctx.ui.getEditorComponent()` so extensions can wrap the currently configured custom editor factory ([#3935](https://github.com/badlogic/pi-mono/issues/3935)).
- Added a `thinking_level_select` extension event for observing thinking level changes ([#3888](https://github.com/badlogic/pi-mono/issues/3888)).
### Removed
@@ -15,6 +16,8 @@
### Fixed
- Fixed blocked `edit` tool results rendering the rejection reason twice after interactive extension confirmation ([#3830](https://github.com/badlogic/pi-mono/issues/3830)).
- Fixed extension-triggered thinking level changes refreshing the interactive editor border immediately ([#3888](https://github.com/badlogic/pi-mono/issues/3888)).
- Fixed the coding-agent README See Also link to point at `@mariozechner/pi-agent-core` ([#4023](https://github.com/badlogic/pi-mono/issues/4023)).
- Fixed `grep` and `find` tool argument injection for flag-like search patterns ([#4018](https://github.com/badlogic/pi-mono/issues/4018)).
- Updated `@mariozechner/clipboard` to an attested release so package managers with trust policies do not reject installs ([#3946](https://github.com/badlogic/pi-mono/issues/3946)).

View File

@@ -40,6 +40,7 @@ See [examples/extensions/](../examples/extensions/) for working implementations.
- [Resource Events](#resource-events)
- [Session Events](#session-events)
- [Agent Events](#agent-events)
- [Model Events](#model-events)
- [Tool Events](#tool-events)
- [ExtensionContext](#extensioncontext)
- [ExtensionCommandContext](#extensioncommandcontext)
@@ -323,8 +324,12 @@ user sends another prompt ◄─────────────────
└─► session_tree
/model or Ctrl+P (model selection/cycling)
├─► thinking_level_select (if model change changes/clamps thinking level)
└─► model_select
thinking level changes (settings, keybinding, pi.setThinkingLevel())
└─► thinking_level_select
exit (Ctrl+C, Ctrl+D, SIGHUP, SIGTERM)
└─► session_shutdown
```
@@ -649,6 +654,21 @@ pi.on("model_select", async (event, ctx) => {
Use this to update UI elements (status bars, footers) or perform model-specific initialization when the active model changes.
#### thinking_level_select
Fired when the thinking level changes. This is notification-only; handler return values are ignored.
```typescript
pi.on("thinking_level_select", async (event, ctx) => {
// event.level - newly selected thinking level
// event.previousLevel - previous thinking level
ctx.ui.setStatus("thinking", `thinking: ${event.level}`);
});
```
Use this to update extension UI when `pi.setThinkingLevel()`, model changes, or built-in thinking-level controls change the active thinking level.
### Tool Events
#### tool_call
@@ -1502,7 +1522,7 @@ if (model) {
### pi.getThinkingLevel() / pi.setThinkingLevel(level)
Get or set the thinking level. Level is clamped to model capabilities (non-reasoning models always use "off").
Get or set the thinking level. Level is clamped to model capabilities (non-reasoning models always use "off"). Changes emit `thinking_level_select`.
```typescript
const current = pi.getThinkingLevel(); // "off" | "minimal" | "low" | "medium" | "high" | "xhigh"

View File

@@ -120,6 +120,7 @@ export type AgentSessionEvent =
}
| { type: "compaction_start"; reason: "manual" | "threshold" | "overflow" }
| { type: "session_info_changed"; name: string | undefined }
| { type: "thinking_level_changed"; level: ThinkingLevel }
| {
type: "compaction_end";
reason: "manual" | "threshold" | "overflow";
@@ -1505,7 +1506,8 @@ export class AgentSession {
const effectiveLevel = availableLevels.includes(level) ? level : this._clampThinkingLevel(level, availableLevels);
// Only persist if actually changing
const isChanging = effectiveLevel !== this.agent.state.thinkingLevel;
const previousLevel = this.agent.state.thinkingLevel;
const isChanging = effectiveLevel !== previousLevel;
this.agent.state.thinkingLevel = effectiveLevel;
@@ -1514,6 +1516,12 @@ export class AgentSession {
if (this.supportsThinking() || effectiveLevel !== "off") {
this.settingsManager.setDefaultThinkingLevel(effectiveLevel);
}
this._emit({ type: "thinking_level_changed", level: effectiveLevel });
void this._extensionRunner.emit({
type: "thinking_level_select",
level: effectiveLevel,
previousLevel,
});
}
}

View File

@@ -718,6 +718,13 @@ export interface ModelSelectEvent {
source: ModelSelectSource;
}
/** Fired when a new thinking level is selected */
export interface ThinkingLevelSelectEvent {
type: "thinking_level_select";
level: ThinkingLevel;
previousLevel: ThinkingLevel;
}
// ============================================================================
// User Bash Events
// ============================================================================
@@ -958,6 +965,7 @@ export type ExtensionEvent =
| ToolExecutionUpdateEvent
| ToolExecutionEndEvent
| ModelSelectEvent
| ThinkingLevelSelectEvent
| UserBashEvent
| InputEvent
| ToolCallEvent
@@ -1111,6 +1119,7 @@ export interface ExtensionAPI {
on(event: "tool_execution_update", handler: ExtensionHandler<ToolExecutionUpdateEvent>): void;
on(event: "tool_execution_end", handler: ExtensionHandler<ToolExecutionEndEvent>): void;
on(event: "model_select", handler: ExtensionHandler<ModelSelectEvent>): void;
on(event: "thinking_level_select", handler: ExtensionHandler<ThinkingLevelSelectEvent>): void;
on(event: "tool_call", handler: ExtensionHandler<ToolCallEvent, ToolCallEventResult>): void;
on(event: "tool_result", handler: ExtensionHandler<ToolResultEvent, ToolResultEventResult>): void;
on(event: "user_bash", handler: ExtensionHandler<UserBashEvent, UserBashEventResult>): void;

View File

@@ -2658,6 +2658,11 @@ export class InteractiveMode {
this.ui.requestRender();
break;
case "thinking_level_changed":
this.footer.invalidate();
this.updateEditorBorderColor();
break;
case "message_start":
if (event.message.role === "custom") {
this.addMessageToChat(event.message);