feat(tui): implement interactive menu system for model and config selection

This commit is contained in:
asepharyana
2026-09-03 16:13:29 +07:00
parent c53fdfa7c9
commit 2100e7ab54
8 changed files with 532 additions and 73 deletions
+45 -6
View File
@@ -35,11 +35,10 @@ export const COMMANDS: string[] = [
"/help",
"/quit",
"/clear",
"/edit",
"/mcp add",
"/edit <path>",
"/mcp",
"/model",
"/model ls",
"/model add",
"/config",
"/todo",
"/usage",
"/compact",
@@ -256,6 +255,7 @@ export const Overlay = {
ModelSelector: "model_selector",
ClearConfirm: "clear_confirm",
Diff: "diff",
Menu: "menu",
} as const;
export type Overlay = (typeof Overlay)[keyof typeof Overlay];
@@ -299,6 +299,35 @@ export interface ActivityEntry {
count?: number;
}
/* ── Interactive menu ─────────────────────────────────────────────── */
/**
* A single frame in the interactive menu stack. Reusable across every
* configuration surface (models, settings, MCP, todo, …) so each is a
* picker like Claude Code / opencode — never inline sub-commands.
*/
export interface MenuFrame {
/** Stable id used by the resolver to route Enter (e.g. "model:provider"). */
id: string;
title: string;
/** Selectable option labels (one line each). */
items: string[];
/** Optional dim detail shown under each option. */
details?: string[];
/** Footer hint line (keybindings / current value). */
hint?: string;
selected: number;
/** Live type-to-filter: typing narrows/highlights matching rows. */
filter?: string;
}
export const emptyMenuFrame = (): MenuFrame => ({
id: "",
title: "",
items: [],
selected: 0,
});
/* ── Misc state ───────────────────────────────────────────────────── */
/** The "miscellaneous" slice of app state. */
@@ -320,6 +349,8 @@ export class MiscState {
diffScroll = 0;
/** Breadcrumb of the current turn's activity (tools / sub-agents). */
activity: ActivityEntry[] = [];
/** Stack of interactive menu frames (top = currently shown). */
menuStack: MenuFrame[] = [];
pushToast(toast: { kind: string; message: string; createdMs: number; ttlMs: number }): void {
this.toasts.push(toast);
@@ -523,18 +554,26 @@ export const DEFAULT_HELP_TEXT = ` Zesdex TUI — Keyboard Shortcuts
─── Overlays ───
/help Show this help
/model Pick provider → model (interactive)
/config Settings menu (internet, review, provider)
/todo Open tasks (todo) overlay
/usage Open usage statistics
/diff Open git diff overlay
/plan Open plan overlay
/mcp Open MCP server management
/model Open model selector
/compact Compact conversation
/clear Clear transcript
─── Menus (interactive pickers) ───
↑/↓ · j/k Move selection
PgUp/PgDn Page Home/End — jump
g / G Top / Bottom
type a-z Type-to-filter
Enter Open / apply
Esc Back / close
─── Editor Mode ───
/edit <path> Open file for inline editing
Ctrl+S Save changes (not yet wired)
Esc Dismiss editor
─── Legend ───