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

@ -1,5 +1,6 @@
import {
Editor,
isAltEnter,
isCtrlC,
isCtrlD,
isCtrlG,
@ -28,8 +29,14 @@ export class CustomEditor extends Editor {
public onCtrlT?: () => void;
public onCtrlG?: () => void;
public onCtrlZ?: () => void;
public onAltEnter?: () => void;
handleInput(data: string): void {
// Intercept Alt+Enter for follow-up messages
if (isAltEnter(data) && this.onAltEnter) {
this.onAltEnter();
return;
}
// Intercept Ctrl+G for external editor
if (isCtrlG(data) && this.onCtrlG) {
this.onCtrlG();

View file

@ -1,56 +0,0 @@
import { Container, type SelectItem, SelectList } from "@mariozechner/pi-tui";
import { getSelectListTheme } from "../theme/theme.js";
import { DynamicBorder } from "./dynamic-border.js";
/**
* Component that renders a queue mode selector with borders
*/
export class QueueModeSelectorComponent extends Container {
private selectList: SelectList;
constructor(
currentMode: "all" | "one-at-a-time",
onSelect: (mode: "all" | "one-at-a-time") => void,
onCancel: () => void,
) {
super();
const queueModes: SelectItem[] = [
{
value: "one-at-a-time",
label: "one-at-a-time",
description: "Process queued messages one by one (recommended)",
},
{ value: "all", label: "all", description: "Process all queued messages at once" },
];
// Add top border
this.addChild(new DynamicBorder());
// Create selector
this.selectList = new SelectList(queueModes, 2, getSelectListTheme());
// Preselect current mode
const currentIndex = queueModes.findIndex((item) => item.value === currentMode);
if (currentIndex !== -1) {
this.selectList.setSelectedIndex(currentIndex);
}
this.selectList.onSelect = (item) => {
onSelect(item.value as "all" | "one-at-a-time");
};
this.selectList.onCancel = () => {
onCancel();
};
this.addChild(this.selectList);
// Add bottom border
this.addChild(new DynamicBorder());
}
getSelectList(): SelectList {
return this.selectList;
}
}

View file

@ -24,7 +24,8 @@ const THINKING_DESCRIPTIONS: Record<ThinkingLevel, string> = {
export interface SettingsConfig {
autoCompact: boolean;
showImages: boolean;
queueMode: "all" | "one-at-a-time";
steeringMode: "all" | "one-at-a-time";
followUpMode: "all" | "one-at-a-time";
thinkingLevel: ThinkingLevel;
availableThinkingLevels: ThinkingLevel[];
currentTheme: string;
@ -36,7 +37,8 @@ export interface SettingsConfig {
export interface SettingsCallbacks {
onAutoCompactChange: (enabled: boolean) => void;
onShowImagesChange: (enabled: boolean) => void;
onQueueModeChange: (mode: "all" | "one-at-a-time") => void;
onSteeringModeChange: (mode: "all" | "one-at-a-time") => void;
onFollowUpModeChange: (mode: "all" | "one-at-a-time") => void;
onThinkingLevelChange: (level: ThinkingLevel) => void;
onThemeChange: (theme: string) => void;
onThemePreview?: (theme: string) => void;
@ -127,10 +129,17 @@ export class SettingsSelectorComponent extends Container {
values: ["true", "false"],
},
{
id: "queue-mode",
label: "Queue mode",
description: "How to process queued messages while agent is working",
currentValue: config.queueMode,
id: "steering-mode",
label: "Steering mode",
description: "How to deliver steering messages (Enter while streaming)",
currentValue: config.steeringMode,
values: ["one-at-a-time", "all"],
},
{
id: "follow-up-mode",
label: "Follow-up mode",
description: "How to deliver follow-up messages (queued until agent finishes)",
currentValue: config.followUpMode,
values: ["one-at-a-time", "all"],
},
{
@ -227,8 +236,11 @@ export class SettingsSelectorComponent extends Container {
case "show-images":
callbacks.onShowImagesChange(newValue === "true");
break;
case "queue-mode":
callbacks.onQueueModeChange(newValue as "all" | "one-at-a-time");
case "steering-mode":
callbacks.onSteeringModeChange(newValue as "all" | "one-at-a-time");
break;
case "follow-up-mode":
callbacks.onFollowUpModeChange(newValue as "all" | "one-at-a-time");
break;
case "hide-thinking":
callbacks.onHideThinkingBlockChange(newValue === "true");