feat(coding-agent): complete steer()/followUp() migration

- Update settings-manager with steeringMode/followUpMode (migrates old queueMode)
- Update sdk.ts to use new mode options
- Update settings-selector UI to show both modes
- Add Alt+Enter keybind for follow-up messages
- Update RPC API: steer/follow_up commands, set_steering_mode/set_follow_up_mode
- Update rpc-client with new methods
- Delete dead code: queue-mode-selector.ts
- Update tests for new API
- Update mom/context.ts stubs
- Update web-ui example
This commit is contained in:
Mario Zechner 2026-01-02 23:47:53 +01:00
parent 58c423ba36
commit 3ae02a6849
12 changed files with 173 additions and 106 deletions

View file

@ -173,10 +173,17 @@ export class RpcClient {
}
/**
* Queue a message while agent is streaming.
* Queue a steering message to interrupt the agent mid-run.
*/
async queueMessage(message: string): Promise<void> {
await this.send({ type: "queue_message", message });
async steer(message: string): Promise<void> {
await this.send({ type: "steer", message });
}
/**
* Queue a follow-up message to be processed after the agent finishes.
*/
async followUp(message: string): Promise<void> {
await this.send({ type: "follow_up", message });
}
/**
@ -248,10 +255,17 @@ export class RpcClient {
}
/**
* Set queue mode.
* Set steering mode.
*/
async setQueueMode(mode: "all" | "one-at-a-time"): Promise<void> {
await this.send({ type: "set_queue_mode", mode });
async setSteeringMode(mode: "all" | "one-at-a-time"): Promise<void> {
await this.send({ type: "set_steering_mode", mode });
}
/**
* Set follow-up mode.
*/
async setFollowUpMode(mode: "all" | "one-at-a-time"): Promise<void> {
await this.send({ type: "set_follow_up_mode", mode });
}
/**

View file

@ -253,9 +253,14 @@ export async function runRpcMode(session: AgentSession): Promise<never> {
return success(id, "prompt");
}
case "queue_message": {
await session.queueMessage(command.message);
return success(id, "queue_message");
case "steer": {
await session.steer(command.message);
return success(id, "steer");
}
case "follow_up": {
await session.followUp(command.message);
return success(id, "follow_up");
}
case "abort": {
@ -279,7 +284,8 @@ export async function runRpcMode(session: AgentSession): Promise<never> {
thinkingLevel: session.thinkingLevel,
isStreaming: session.isStreaming,
isCompacting: session.isCompacting,
queueMode: session.queueMode,
steeringMode: session.steeringMode,
followUpMode: session.followUpMode,
sessionFile: session.sessionFile,
sessionId: session.sessionId,
autoCompactionEnabled: session.autoCompactionEnabled,
@ -334,12 +340,17 @@ export async function runRpcMode(session: AgentSession): Promise<never> {
}
// =================================================================
// Queue Mode
// Queue Modes
// =================================================================
case "set_queue_mode": {
session.setQueueMode(command.mode);
return success(id, "set_queue_mode");
case "set_steering_mode": {
session.setSteeringMode(command.mode);
return success(id, "set_steering_mode");
}
case "set_follow_up_mode": {
session.setFollowUpMode(command.mode);
return success(id, "set_follow_up_mode");
}
// =================================================================

View file

@ -18,7 +18,8 @@ import type { CompactionResult } from "../../core/compaction/index.js";
export type RpcCommand =
// Prompting
| { id?: string; type: "prompt"; message: string; images?: ImageContent[] }
| { id?: string; type: "queue_message"; message: string }
| { id?: string; type: "steer"; message: string }
| { id?: string; type: "follow_up"; message: string }
| { id?: string; type: "abort" }
| { id?: string; type: "new_session"; parentSession?: string }
@ -34,8 +35,9 @@ export type RpcCommand =
| { id?: string; type: "set_thinking_level"; level: ThinkingLevel }
| { id?: string; type: "cycle_thinking_level" }
// Queue mode
| { id?: string; type: "set_queue_mode"; mode: "all" | "one-at-a-time" }
// Queue modes
| { id?: string; type: "set_steering_mode"; mode: "all" | "one-at-a-time" }
| { id?: string; type: "set_follow_up_mode"; mode: "all" | "one-at-a-time" }
// Compaction
| { id?: string; type: "compact"; customInstructions?: string }
@ -69,7 +71,8 @@ export interface RpcSessionState {
thinkingLevel: ThinkingLevel;
isStreaming: boolean;
isCompacting: boolean;
queueMode: "all" | "one-at-a-time";
steeringMode: "all" | "one-at-a-time";
followUpMode: "all" | "one-at-a-time";
sessionFile?: string;
sessionId: string;
autoCompactionEnabled: boolean;
@ -85,7 +88,8 @@ export interface RpcSessionState {
export type RpcResponse =
// Prompting (async - events follow)
| { id?: string; type: "response"; command: "prompt"; success: true }
| { id?: string; type: "response"; command: "queue_message"; success: true }
| { id?: string; type: "response"; command: "steer"; success: true }
| { id?: string; type: "response"; command: "follow_up"; success: true }
| { id?: string; type: "response"; command: "abort"; success: true }
| { id?: string; type: "response"; command: "new_session"; success: true; data: { cancelled: boolean } }
@ -125,8 +129,9 @@ export type RpcResponse =
data: { level: ThinkingLevel } | null;
}
// Queue mode
| { id?: string; type: "response"; command: "set_queue_mode"; success: true }
// Queue modes
| { id?: string; type: "response"; command: "set_steering_mode"; success: true }
| { id?: string; type: "response"; command: "set_follow_up_mode"; success: true }
// Compaction
| { id?: string; type: "response"; command: "compact"; success: true; data: CompactionResult }