feat(coding-agent): add configurable working indicator closes #3413

This commit is contained in:
Mario Zechner
2026-04-20 16:28:39 +02:00
parent 61579214c8
commit 74139c3f66
15 changed files with 248 additions and 65 deletions

View File

@@ -149,6 +149,7 @@ export type {
UserBashEvent,
UserBashEventResult,
WidgetPlacement,
WorkingIndicatorOptions,
WriteToolCallEvent,
WriteToolResultEvent,
} from "./types.js";

View File

@@ -167,8 +167,8 @@ export type ShutdownHandler = () => void;
* Helper function to emit session_shutdown event to extensions.
* Returns true if the event was emitted, false if there were no handlers.
*/
export async function emitSessionShutdownEvent(extensionRunner: ExtensionRunner | undefined): Promise<boolean> {
if (extensionRunner?.hasHandlers("session_shutdown")) {
export async function emitSessionShutdownEvent(extensionRunner: ExtensionRunner): Promise<boolean> {
if (extensionRunner.hasHandlers("session_shutdown")) {
await extensionRunner.emit({
type: "session_shutdown",
});
@@ -185,6 +185,7 @@ const noOpUIContext: ExtensionUIContext = {
onTerminalInput: () => () => {},
setStatus: () => {},
setWorkingMessage: () => {},
setWorkingIndicator: () => {},
setHiddenThinkingLabel: () => {},
setWidget: () => {},
setFooter: () => {},

View File

@@ -102,6 +102,14 @@ export interface ExtensionWidgetOptions {
/** Raw terminal input listener for extensions. */
export type TerminalInputHandler = (data: string) => { consume?: boolean; data?: string } | undefined;
/** Working indicator configuration for the interactive streaming loader. */
export interface WorkingIndicatorOptions {
/** Animation frames. Use an empty array to hide the indicator entirely. */
frames?: string[];
/** Frame interval in milliseconds for animated indicators. */
intervalMs?: number;
}
/**
* UI context for extensions to request interactive UI.
* Each mode (interactive, RPC, print) provides its own implementation.
@@ -128,6 +136,15 @@ export interface ExtensionUIContext {
/** Set the working/loading message shown during streaming. Call with no argument to restore default. */
setWorkingMessage(message?: string): void;
/**
* Configure the interactive working indicator shown during streaming.
*
* - Omit the argument to restore the default animated spinner.
* - Use `frames: ["●"]` for a static indicator.
* - Use `frames: []` to hide the indicator entirely.
*/
setWorkingIndicator(options?: WorkingIndicatorOptions): void;
/** Set the label shown for hidden thinking blocks. Call with no argument to restore default. */
setHiddenThinkingLabel(label?: string): void;

View File

@@ -70,5 +70,6 @@ export {
type ToolResultEvent,
type TurnEndEvent,
type TurnStartEvent,
type WorkingIndicatorOptions,
} from "./extensions/index.js";
export { createSyntheticSourceInfo } from "./source-info.js";