@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 +6 -10
- package/dist/index.d.ts +44 -61
- package/dist/index.js +279 -406
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
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,
|
|
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
|
|