@wrongstack/tui 0.77.0 → 0.82.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -31,7 +31,6 @@ const exitCode = await runTui({
31
31
  family: 'anthropic',
32
32
  keyTail: '…ABC',
33
33
  effectiveMaxContext: 200_000,
34
- altScreen: true,
35
34
  });
36
35
 
37
36
  process.exit(exitCode);
@@ -76,24 +75,16 @@ process.exit(exitCode);
76
75
  | `Esc` | Close any picker / dialog / agents monitor |
77
76
  | `Ctrl+L` | Clear screen (TUI keeps state — equivalent to scrolling) |
78
77
 
79
- Keyboard shortcuts (always available in managed/alt-screen mode):
80
- - **PgUp/PgDn** — page scroll through chat history.
81
- - **Home/End** — jump to top/bottom of chat history (when input is empty); move cursor to start/end of line (when typing).
82
- - **Ctrl+Home/End** — jump to top/bottom of chat history (always, even when typing).
83
- - **↑/↓** — navigate input history when buffer is empty.
84
-
85
78
  ## Options worth knowing
86
79
 
87
- - **`altScreen: true`** (default) — render into the terminal's alternate screen buffer (vim/less/htop style). The TUI owns the whole viewport, native scrollback is untouched, and the live region cannot leak into terminal history. Raw mode plus alt-screen also means every keystroke — including Ctrl+S, Ctrl+Q, Ctrl+Z, Ctrl+\\ — reaches Ink instead of being consumed by the terminal driver (`runTui` additionally registers no-op handlers for `SIGTSTP`/`SIGQUIT`/`SIGTTIN`/`SIGTTOU` as belt-and-suspenders). Set `false` (or pass `--no-alt-screen`) to render into normal scrollback if you specifically want completed chat to survive after exit; the trade-off is the documented live-region leak on resize / overlay-close / picker-submit, and that some shortcuts may fall through to the terminal.
88
80
  - **`effectiveMaxContext`** — the context-bar denominator. Pass the model-specific value resolved via `ModelsRegistry`, not the family baseline; the 1M Opus variant has a much larger window than the 200k default.
89
81
  - **`queueStore`** — if set, queued input survives a crash. Without it, queued lines are in-memory only.
90
82
  - **`onClearHistory`** — invoked from the `/clear` slash command so the TUI can wipe its rendered history entries (keeping just the banner) while `Agent`/memory reset happens elsewhere.
91
- - **`onAfterExit`** — called once the alt-screen has been restored on clean shutdown. Use it to print "session saved" hints into the user's normal terminal (alt-screen exit erases the TUI view).
92
83
 
93
84
  ## Architecture
94
85
 
95
86
  ```
96
- runTui — entry; sets up bracketed paste, alt-screen, signal handlers
87
+ runTui — entry; sets up bracketed paste, signal handlers
97
88
 
98
89
  App (React component) — useReducer-driven state machine
99
90
  ↓ dispatches events to ↓
@@ -102,6 +93,11 @@ EventBus — agent.run() emits these, the TUI subscribes
102
93
 
103
94
  State is a single `useReducer` `State` shape with discriminated-union `Action`s. The reducer is exported (`reducer`) and unit-tested.
104
95
 
96
+ ## React Version
97
+
98
+ TUI remains on React 18 because ink v5 does not yet fully support React 19.
99
+ WebUI uses React 19. This is a known divergence tracked in this codebase.
100
+
105
101
  ## License
106
102
 
107
103
  MIT
package/dist/index.d.ts CHANGED
@@ -10,7 +10,7 @@ interface ProviderOption {
10
10
  /** Model ids the picker offers in step 2 for this provider. */
11
11
  models: string[];
12
12
  /** Optional dim hint shown next to the model list (e.g. "from saved config"). */
13
- modelsLabel?: string;
13
+ modelsLabel?: string | undefined;
14
14
  }
15
15
 
16
16
  interface Settings {
@@ -40,57 +40,57 @@ interface RunTuiOptions {
40
40
  slashRegistry: SlashCommandRegistry;
41
41
  attachments: AttachmentStore;
42
42
  events: EventBus;
43
- tokenCounter?: TokenCounter;
44
- visionAdapters?: VisionAdapters;
43
+ tokenCounter?: TokenCounter | undefined;
44
+ visionAdapters?: VisionAdapters | undefined;
45
45
  /** Resolve current model vision support. Falls back to provider capability when omitted. */
46
- supportsVision?: () => boolean | Promise<boolean>;
46
+ supportsVision?: (() => boolean | Promise<boolean>) | undefined;
47
47
  model: string;
48
- banner?: boolean;
48
+ banner?: boolean | undefined;
49
49
  /** Persists the input queue across crashes; if omitted, the queue is in-memory only. */
50
- queueStore?: QueueStore;
50
+ queueStore?: QueueStore | undefined;
51
51
  /** Surfaces the "⚠ YOLO" chip in the status bar. */
52
- yolo?: boolean;
52
+ yolo?: boolean | undefined;
53
53
  /** Query live YOLO state from the permission policy. */
54
- getYolo?: () => boolean;
54
+ getYolo?: (() => boolean) | undefined;
55
55
  /** Query the live autonomy mode. */
56
- getAutonomy?: () => 'off' | 'suggest' | 'auto' | 'eternal' | 'eternal-parallel';
56
+ getAutonomy?: (() => 'off' | 'suggest' | 'auto' | 'eternal' | 'eternal-parallel') | undefined;
57
57
  /**
58
58
  * Access the eternal-autonomy engine. When autonomy mode flips to
59
59
  * 'eternal' the TUI drives `runOneIteration()` from the post-slash hook
60
60
  * so the engine and TUI never race for the shared Context.
61
61
  */
62
- getEternalEngine?: () => _wrongstack_core.EternalAutonomyEngine | null;
62
+ getEternalEngine?: (() => _wrongstack_core.EternalAutonomyEngine | null) | undefined;
63
63
  /**
64
64
  * Access the parallel-eternal engine. When autonomy mode flips to
65
65
  * 'eternal-parallel' the TUI drives `runOneIteration()` from the post-slash
66
66
  * hook so the engine and TUI never race for the shared Context.
67
67
  */
68
- getParallelEngine?: () => _wrongstack_core.ParallelEternalEngine | null;
68
+ getParallelEngine?: (() => _wrongstack_core.ParallelEternalEngine | null) | undefined;
69
69
  /**
70
70
  * Subscribe to live per-iteration events from the eternal engine.
71
71
  * Returns an unsubscribe function. TUI uses this to render each
72
72
  * iteration as a live timeline entry as it lands.
73
73
  */
74
- subscribeEternalIteration?: (fn: (entry: _wrongstack_core.JournalEntry) => void) => () => void;
74
+ subscribeEternalIteration?: ((fn: (entry: _wrongstack_core.JournalEntry) => void) => () => void) | undefined;
75
75
  /**
76
76
  * Subscribe to per-iteration stage transitions from the autonomy engines.
77
77
  * TUI uses this to render live status in the status bar.
78
78
  */
79
- subscribeEternalStage?: (fn: (stage: AutonomyStage) => void) => () => void;
79
+ subscribeEternalStage?: ((fn: (stage: AutonomyStage) => void) => () => void) | undefined;
80
80
  /** Renders in the startup banner. Read from the CLI's package.json. */
81
- appVersion?: string;
81
+ appVersion?: string | undefined;
82
82
  /** Provider id for the startup banner ("openai", "anthropic", ...). */
83
- provider?: string;
83
+ provider?: string | undefined;
84
84
  /** Wire family — shown beneath provider in the banner. */
85
- family?: string;
85
+ family?: string | undefined;
86
86
  /** Last 3 chars of the active API key — shown in the banner for visual key-pick verification. */
87
- keyTail?: string;
87
+ keyTail?: string | undefined;
88
88
  /** Snapshot of keyed providers + their model lists for the `/model` picker. Async — the catalog fetch may need to hit disk/network. */
89
- getPickableProviders?: () => Promise<ProviderOption[]>;
89
+ getPickableProviders?: (() => Promise<ProviderOption[]>) | undefined;
90
90
  /** Apply a (provider, model) pair after the picker confirms. Returns an error string on failure. */
91
- switchProviderAndModel?: (providerId: string, modelId: string) => string | null;
91
+ switchProviderAndModel?: ((providerId: string, modelId: string) => string | null) | undefined;
92
92
  /** Apply an autonomy mode after the picker confirms. Returns an error string on failure. */
93
- switchAutonomy?: (mode: 'off' | 'suggest' | 'auto' | 'eternal' | 'eternal-parallel') => string | null;
93
+ switchAutonomy?: ((mode: 'off' | 'suggest' | 'auto' | 'eternal' | 'eternal-parallel') => string | null) | undefined;
94
94
  /**
95
95
  * Model-specific maxContext (tokens), resolved by the CLI via the
96
96
  * ModelsRegistry. When omitted, the TUI falls back to the provider
@@ -98,60 +98,43 @@ interface RunTuiOptions {
98
98
  * for variants like the 1M-context Opus build. The status bar's
99
99
  * context chip uses this for its progress denominator.
100
100
  */
101
- effectiveMaxContext?: number;
101
+ effectiveMaxContext?: number | undefined;
102
102
  /** Absolute project root for goal.json loading. */
103
- projectRoot?: string;
104
- /** Render into the terminal's alternate screen buffer (like vim/less/htop).
105
- * Default: false — native scrollback stays live so chat history is
106
- * scrollable (wheel / Shift+PgUp), which matches the user's
107
- * "this is a chat app, let me scroll the chat" intuition. Pass true
108
- * (or run with `--alt-screen`) for the full-screen mode that owns the
109
- * terminal and prevents resize/overlay leaks of the live region —
110
- * trade-off is that the terminal's native scrollback is suspended
111
- * while the TUI is up and only what's currently on screen is visible.
112
- */
113
- altScreen?: boolean;
103
+ projectRoot?: string | undefined;
114
104
  /**
115
105
  * Terminal title animation on/off. Defaults to true. When false, the
116
106
  * OSC-0 window/tab title stays static (the app name only, no spinner).
117
107
  * Controlled via /settings → Terminal title animation.
118
108
  */
119
- titleAnimation?: boolean;
109
+ titleAnimation?: boolean | undefined;
120
110
  /** Play terminal bell (\\x07) when agent run completes. */
121
- chime?: boolean;
111
+ chime?: boolean | undefined;
122
112
  /** Show "confirm exit" message on first Ctrl+C instead of "exit". */
123
- confirmExit?: boolean;
113
+ confirmExit?: boolean | undefined;
124
114
  /** Active agent mode label shown in the status bar (e.g. "teach", "brief"). */
125
- modeLabel?: string;
115
+ modeLabel?: string | undefined;
126
116
  /** Live getter for the agent mode label so the status bar updates after /mode. */
127
- getModeLabel?: () => string;
128
- /**
129
- * Called right after we exit the alt-screen on a clean shutdown. The
130
- * CLI uses this to print a one-line "session saved to …" hint into
131
- * the user's normal terminal, since alt-screen exit erases the whole
132
- * TUI view.
133
- */
134
- onAfterExit?: () => void;
117
+ getModeLabel?: (() => string) | undefined;
135
118
  /** Called from /clear so the TUI can wipe its history entries while agent.ctx + memory are cleared separately. */
136
- onClearHistory?: (dispatch: React.Dispatch<{
119
+ onClearHistory?: ((dispatch: React.Dispatch<{
137
120
  type: 'clearHistory';
138
121
  } | {
139
122
  type: 'resetContextChip';
140
- }>) => void;
123
+ }>) => void) | undefined;
141
124
  /**
142
125
  * Live director instance. When set, the TUI renders a fleet panel
143
126
  * showing every spawned subagent, its current task, streaming output,
144
127
  * and runtime cost — updated live from the FleetBus. Pass null or omit
145
128
  * when multi-agent / director mode is disabled.
146
129
  */
147
- director?: Director | null;
130
+ director?: Director | null | undefined;
148
131
  /**
149
132
  * Optional roster reference for resolving subagent role ids to
150
133
  * human-readable names. Same value passed to director.tools().
151
134
  */
152
135
  fleetRoster?: Record<string, {
153
136
  name: string;
154
- }>;
137
+ }> | undefined;
155
138
  /**
156
139
  * Shared controller for the `/fleet stream on|off` toggle. The slash
157
140
  * command runs in the CLI process and needs to flip TUI reducer state;
@@ -167,7 +150,7 @@ interface RunTuiOptions {
167
150
  fleetStreamController?: {
168
151
  enabled: boolean;
169
152
  setEnabled: (enabled: boolean) => void;
170
- };
153
+ } | undefined;
171
154
  /**
172
155
  * Controller for the `/enhance on|off` prompt-refinement toggle. The App
173
156
  * installs a dispatch-backed `setEnabled` here on mount so the slash command
@@ -177,7 +160,7 @@ interface RunTuiOptions {
177
160
  enhanceController?: {
178
161
  enabled: boolean;
179
162
  setEnabled: (enabled: boolean) => void;
180
- };
163
+ } | undefined;
181
164
  /**
182
165
  * Controller for status bar hidden items. App installs a dispatch-backed
183
166
  * setter on mount so the /statusline slash command can update the TUI's
@@ -194,7 +177,7 @@ interface RunTuiOptions {
194
177
  agentsMonitorController?: {
195
178
  visible: boolean;
196
179
  setVisible: (visible: boolean) => void;
197
- };
180
+ } | undefined;
198
181
  /**
199
182
  * If set, the App boots straight into goal mode — the text is wrapped
200
183
  * in the GOAL preamble and submitted as the first turn. Lets users
@@ -203,55 +186,55 @@ interface RunTuiOptions {
203
186
  * The chat shows a one-line "🎯 Goal locked: …" hint; the actual
204
187
  * preamble is hidden from the visible history (same as `/goal`).
205
188
  */
206
- initialGoal?: string;
189
+ initialGoal?: string | undefined;
207
190
  /**
208
191
  * If set, submitted as the first turn verbatim (no preamble). Mainly
209
192
  * for scripted shell aliases — `wstack --tui --ask "summarize foo.md"`
210
193
  * — that want one turn pre-populated without the goal-mode framing.
211
194
  * Ignored when `initialGoal` is also set.
212
195
  */
213
- initialAsk?: string;
196
+ initialAsk?: string | undefined;
214
197
  /**
215
198
  * Directory containing session JSONL files. Required for rewind
216
199
  * functionality. When provided the TUI can list checkpoints and
217
200
  * trigger a rewind via `/rewind` or Ctrl+R.
218
201
  */
219
- sessionsDir?: string;
202
+ sessionsDir?: string | undefined;
220
203
  /**
221
204
  * SDD session context getter. When an SDD session is active, returns
222
205
  * the AI prompt context to inject into user messages.
223
206
  */
224
- getSDDContext?: () => string | null;
207
+ getSDDContext?: (() => string | null) | undefined;
225
208
  /**
226
209
  * Process AI output for SDD auto-detection (spec, tasks, plan).
227
210
  * Returns displayable status messages.
228
211
  */
229
- onSDDOutput?: (output: string) => Promise<string[]>;
212
+ onSDDOutput?: ((output: string) => Promise<string[]>) | undefined;
230
213
  /**
231
214
  * Subscribe to AutoPhase phase/graph events from the PhaseOrchestrator.
232
215
  * Returns an unsubscribe function. The TUI uses this to drive the
233
216
  * PhaseMonitor and PhasePanel live views via dispatch actions.
234
217
  */
235
- subscribeAutoPhase?: (handler: (event: string, payload: unknown) => void) => () => void;
218
+ subscribeAutoPhase?: ((handler: (event: string, payload: unknown) => void) => () => void) | undefined;
236
219
  /**
237
220
  * Read the persisted autonomy settings (defaultMode, autoProceedDelayMs).
238
221
  * Used by the SettingsPicker in the TUI on mount and after Ctrl+S toggle.
239
222
  */
240
- getSettings?: () => Settings;
223
+ getSettings?: (() => Settings) | undefined;
241
224
  /**
242
225
  * Persist settings changes. Returns null on success, or an
243
226
  * error string on failure (so the TUI can display it as a hint).
244
227
  */
245
- saveSettings?: (s: Settings) => string | null | Promise<string | null>;
228
+ saveSettings?: ((s: Settings) => string | null | Promise<string | null>) | undefined;
246
229
  /**
247
230
  * Predict likely next steps after a completed turn. The CLI wires this from
248
231
  * the session provider and the `/next` toggle; it returns [] when prediction
249
232
  * is disabled or autonomy isn't 'off'. Display-only — never executed.
250
233
  */
251
- predictNext?: (input: {
234
+ predictNext?: ((input: {
252
235
  userRequest: string;
253
236
  assistantSummary: string;
254
- }) => Promise<string[]>;
237
+ }) => Promise<string[]>) | undefined;
255
238
  }
256
239
  declare function runTui(opts: RunTuiOptions): Promise<number>;
257
240