@wrongstack/tui 0.73.1 → 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 +86 -63
- package/dist/index.js +1474 -568
- 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,29 @@ 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
|
+
}
|
|
15
|
+
|
|
16
|
+
interface Settings {
|
|
17
|
+
mode: 'off' | 'suggest' | 'auto';
|
|
18
|
+
delayMs: number;
|
|
19
|
+
titleAnimation: boolean;
|
|
20
|
+
yolo: boolean;
|
|
21
|
+
streamFleet: boolean;
|
|
22
|
+
chime: boolean;
|
|
23
|
+
confirmExit: boolean;
|
|
24
|
+
nextPrediction: boolean;
|
|
25
|
+
featureMcp: boolean;
|
|
26
|
+
featurePlugins: boolean;
|
|
27
|
+
featureMemory: boolean;
|
|
28
|
+
featureSkills: boolean;
|
|
29
|
+
featureModelsRegistry: boolean;
|
|
30
|
+
contextAutoCompact: boolean;
|
|
31
|
+
contextStrategy: 'hybrid' | 'intelligent' | 'selective';
|
|
32
|
+
logLevel: 'error' | 'warn' | 'info' | 'debug' | 'trace';
|
|
33
|
+
auditLevel: 'minimal' | 'standard' | 'full';
|
|
34
|
+
indexOnStart: boolean;
|
|
35
|
+
maxIterations: number;
|
|
14
36
|
}
|
|
15
37
|
|
|
16
38
|
interface RunTuiOptions {
|
|
@@ -18,57 +40,57 @@ interface RunTuiOptions {
|
|
|
18
40
|
slashRegistry: SlashCommandRegistry;
|
|
19
41
|
attachments: AttachmentStore;
|
|
20
42
|
events: EventBus;
|
|
21
|
-
tokenCounter?: TokenCounter;
|
|
22
|
-
visionAdapters?: VisionAdapters;
|
|
43
|
+
tokenCounter?: TokenCounter | undefined;
|
|
44
|
+
visionAdapters?: VisionAdapters | undefined;
|
|
23
45
|
/** Resolve current model vision support. Falls back to provider capability when omitted. */
|
|
24
|
-
supportsVision?: () => boolean | Promise<boolean
|
|
46
|
+
supportsVision?: (() => boolean | Promise<boolean>) | undefined;
|
|
25
47
|
model: string;
|
|
26
|
-
banner?: boolean;
|
|
48
|
+
banner?: boolean | undefined;
|
|
27
49
|
/** Persists the input queue across crashes; if omitted, the queue is in-memory only. */
|
|
28
|
-
queueStore?: QueueStore;
|
|
50
|
+
queueStore?: QueueStore | undefined;
|
|
29
51
|
/** Surfaces the "⚠ YOLO" chip in the status bar. */
|
|
30
|
-
yolo?: boolean;
|
|
52
|
+
yolo?: boolean | undefined;
|
|
31
53
|
/** Query live YOLO state from the permission policy. */
|
|
32
|
-
getYolo?: () => boolean;
|
|
54
|
+
getYolo?: (() => boolean) | undefined;
|
|
33
55
|
/** Query the live autonomy mode. */
|
|
34
|
-
getAutonomy?: () => 'off' | 'suggest' | 'auto' | 'eternal' | 'eternal-parallel';
|
|
56
|
+
getAutonomy?: (() => 'off' | 'suggest' | 'auto' | 'eternal' | 'eternal-parallel') | undefined;
|
|
35
57
|
/**
|
|
36
58
|
* Access the eternal-autonomy engine. When autonomy mode flips to
|
|
37
59
|
* 'eternal' the TUI drives `runOneIteration()` from the post-slash hook
|
|
38
60
|
* so the engine and TUI never race for the shared Context.
|
|
39
61
|
*/
|
|
40
|
-
getEternalEngine?: () => _wrongstack_core.EternalAutonomyEngine | null;
|
|
62
|
+
getEternalEngine?: (() => _wrongstack_core.EternalAutonomyEngine | null) | undefined;
|
|
41
63
|
/**
|
|
42
64
|
* Access the parallel-eternal engine. When autonomy mode flips to
|
|
43
65
|
* 'eternal-parallel' the TUI drives `runOneIteration()` from the post-slash
|
|
44
66
|
* hook so the engine and TUI never race for the shared Context.
|
|
45
67
|
*/
|
|
46
|
-
getParallelEngine?: () => _wrongstack_core.ParallelEternalEngine | null;
|
|
68
|
+
getParallelEngine?: (() => _wrongstack_core.ParallelEternalEngine | null) | undefined;
|
|
47
69
|
/**
|
|
48
70
|
* Subscribe to live per-iteration events from the eternal engine.
|
|
49
71
|
* Returns an unsubscribe function. TUI uses this to render each
|
|
50
72
|
* iteration as a live timeline entry as it lands.
|
|
51
73
|
*/
|
|
52
|
-
subscribeEternalIteration?: (fn: (entry: _wrongstack_core.JournalEntry) => void) => () => void;
|
|
74
|
+
subscribeEternalIteration?: ((fn: (entry: _wrongstack_core.JournalEntry) => void) => () => void) | undefined;
|
|
53
75
|
/**
|
|
54
76
|
* Subscribe to per-iteration stage transitions from the autonomy engines.
|
|
55
77
|
* TUI uses this to render live status in the status bar.
|
|
56
78
|
*/
|
|
57
|
-
subscribeEternalStage?: (fn: (stage: AutonomyStage) => void) => () => void;
|
|
79
|
+
subscribeEternalStage?: ((fn: (stage: AutonomyStage) => void) => () => void) | undefined;
|
|
58
80
|
/** Renders in the startup banner. Read from the CLI's package.json. */
|
|
59
|
-
appVersion?: string;
|
|
81
|
+
appVersion?: string | undefined;
|
|
60
82
|
/** Provider id for the startup banner ("openai", "anthropic", ...). */
|
|
61
|
-
provider?: string;
|
|
83
|
+
provider?: string | undefined;
|
|
62
84
|
/** Wire family — shown beneath provider in the banner. */
|
|
63
|
-
family?: string;
|
|
85
|
+
family?: string | undefined;
|
|
64
86
|
/** Last 3 chars of the active API key — shown in the banner for visual key-pick verification. */
|
|
65
|
-
keyTail?: string;
|
|
87
|
+
keyTail?: string | undefined;
|
|
66
88
|
/** Snapshot of keyed providers + their model lists for the `/model` picker. Async — the catalog fetch may need to hit disk/network. */
|
|
67
|
-
getPickableProviders?: () => Promise<ProviderOption[]
|
|
89
|
+
getPickableProviders?: (() => Promise<ProviderOption[]>) | undefined;
|
|
68
90
|
/** Apply a (provider, model) pair after the picker confirms. Returns an error string on failure. */
|
|
69
|
-
switchProviderAndModel?: (providerId: string, modelId: string) => string | null;
|
|
91
|
+
switchProviderAndModel?: ((providerId: string, modelId: string) => string | null) | undefined;
|
|
70
92
|
/** Apply an autonomy mode after the picker confirms. Returns an error string on failure. */
|
|
71
|
-
switchAutonomy?: (mode: 'off' | 'suggest' | 'auto' | 'eternal' | 'eternal-parallel') => string | null;
|
|
93
|
+
switchAutonomy?: ((mode: 'off' | 'suggest' | 'auto' | 'eternal' | 'eternal-parallel') => string | null) | undefined;
|
|
72
94
|
/**
|
|
73
95
|
* Model-specific maxContext (tokens), resolved by the CLI via the
|
|
74
96
|
* ModelsRegistry. When omitted, the TUI falls back to the provider
|
|
@@ -76,46 +98,43 @@ interface RunTuiOptions {
|
|
|
76
98
|
* for variants like the 1M-context Opus build. The status bar's
|
|
77
99
|
* context chip uses this for its progress denominator.
|
|
78
100
|
*/
|
|
79
|
-
effectiveMaxContext?: number;
|
|
101
|
+
effectiveMaxContext?: number | undefined;
|
|
80
102
|
/** Absolute project root for goal.json loading. */
|
|
81
|
-
projectRoot?: string;
|
|
82
|
-
/**
|
|
83
|
-
*
|
|
84
|
-
*
|
|
85
|
-
*
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
/**
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
* TUI view.
|
|
97
|
-
*/
|
|
98
|
-
onAfterExit?: () => void;
|
|
103
|
+
projectRoot?: string | undefined;
|
|
104
|
+
/**
|
|
105
|
+
* Terminal title animation on/off. Defaults to true. When false, the
|
|
106
|
+
* OSC-0 window/tab title stays static (the app name only, no spinner).
|
|
107
|
+
* Controlled via /settings → Terminal title animation.
|
|
108
|
+
*/
|
|
109
|
+
titleAnimation?: boolean | undefined;
|
|
110
|
+
/** Play terminal bell (\\x07) when agent run completes. */
|
|
111
|
+
chime?: boolean | undefined;
|
|
112
|
+
/** Show "confirm exit" message on first Ctrl+C instead of "exit". */
|
|
113
|
+
confirmExit?: boolean | undefined;
|
|
114
|
+
/** Active agent mode label shown in the status bar (e.g. "teach", "brief"). */
|
|
115
|
+
modeLabel?: string | undefined;
|
|
116
|
+
/** Live getter for the agent mode label so the status bar updates after /mode. */
|
|
117
|
+
getModeLabel?: (() => string) | undefined;
|
|
99
118
|
/** Called from /clear so the TUI can wipe its history entries while agent.ctx + memory are cleared separately. */
|
|
100
|
-
onClearHistory?: (dispatch: React.Dispatch<{
|
|
119
|
+
onClearHistory?: ((dispatch: React.Dispatch<{
|
|
101
120
|
type: 'clearHistory';
|
|
102
121
|
} | {
|
|
103
122
|
type: 'resetContextChip';
|
|
104
|
-
}>) => void;
|
|
123
|
+
}>) => void) | undefined;
|
|
105
124
|
/**
|
|
106
125
|
* Live director instance. When set, the TUI renders a fleet panel
|
|
107
126
|
* showing every spawned subagent, its current task, streaming output,
|
|
108
127
|
* and runtime cost — updated live from the FleetBus. Pass null or omit
|
|
109
128
|
* when multi-agent / director mode is disabled.
|
|
110
129
|
*/
|
|
111
|
-
director?: Director | null;
|
|
130
|
+
director?: Director | null | undefined;
|
|
112
131
|
/**
|
|
113
132
|
* Optional roster reference for resolving subagent role ids to
|
|
114
133
|
* human-readable names. Same value passed to director.tools().
|
|
115
134
|
*/
|
|
116
135
|
fleetRoster?: Record<string, {
|
|
117
136
|
name: string;
|
|
118
|
-
}
|
|
137
|
+
}> | undefined;
|
|
119
138
|
/**
|
|
120
139
|
* Shared controller for the `/fleet stream on|off` toggle. The slash
|
|
121
140
|
* command runs in the CLI process and needs to flip TUI reducer state;
|
|
@@ -131,7 +150,17 @@ interface RunTuiOptions {
|
|
|
131
150
|
fleetStreamController?: {
|
|
132
151
|
enabled: boolean;
|
|
133
152
|
setEnabled: (enabled: boolean) => void;
|
|
134
|
-
};
|
|
153
|
+
} | undefined;
|
|
154
|
+
/**
|
|
155
|
+
* Controller for the `/enhance on|off` prompt-refinement toggle. The App
|
|
156
|
+
* installs a dispatch-backed `setEnabled` here on mount so the slash command
|
|
157
|
+
* (run in the CLI process) flips the TUI's reducer flag. Mirrors
|
|
158
|
+
* `fleetStreamController`.
|
|
159
|
+
*/
|
|
160
|
+
enhanceController?: {
|
|
161
|
+
enabled: boolean;
|
|
162
|
+
setEnabled: (enabled: boolean) => void;
|
|
163
|
+
} | undefined;
|
|
135
164
|
/**
|
|
136
165
|
* Controller for status bar hidden items. App installs a dispatch-backed
|
|
137
166
|
* setter on mount so the /statusline slash command can update the TUI's
|
|
@@ -148,7 +177,7 @@ interface RunTuiOptions {
|
|
|
148
177
|
agentsMonitorController?: {
|
|
149
178
|
visible: boolean;
|
|
150
179
|
setVisible: (visible: boolean) => void;
|
|
151
|
-
};
|
|
180
|
+
} | undefined;
|
|
152
181
|
/**
|
|
153
182
|
* If set, the App boots straight into goal mode — the text is wrapped
|
|
154
183
|
* in the GOAL preamble and submitted as the first turn. Lets users
|
|
@@ -157,62 +186,56 @@ interface RunTuiOptions {
|
|
|
157
186
|
* The chat shows a one-line "🎯 Goal locked: …" hint; the actual
|
|
158
187
|
* preamble is hidden from the visible history (same as `/goal`).
|
|
159
188
|
*/
|
|
160
|
-
initialGoal?: string;
|
|
189
|
+
initialGoal?: string | undefined;
|
|
161
190
|
/**
|
|
162
191
|
* If set, submitted as the first turn verbatim (no preamble). Mainly
|
|
163
192
|
* for scripted shell aliases — `wstack --tui --ask "summarize foo.md"`
|
|
164
193
|
* — that want one turn pre-populated without the goal-mode framing.
|
|
165
194
|
* Ignored when `initialGoal` is also set.
|
|
166
195
|
*/
|
|
167
|
-
initialAsk?: string;
|
|
196
|
+
initialAsk?: string | undefined;
|
|
168
197
|
/**
|
|
169
198
|
* Directory containing session JSONL files. Required for rewind
|
|
170
199
|
* functionality. When provided the TUI can list checkpoints and
|
|
171
200
|
* trigger a rewind via `/rewind` or Ctrl+R.
|
|
172
201
|
*/
|
|
173
|
-
sessionsDir?: string;
|
|
202
|
+
sessionsDir?: string | undefined;
|
|
174
203
|
/**
|
|
175
204
|
* SDD session context getter. When an SDD session is active, returns
|
|
176
205
|
* the AI prompt context to inject into user messages.
|
|
177
206
|
*/
|
|
178
|
-
getSDDContext?: () => string | null;
|
|
207
|
+
getSDDContext?: (() => string | null) | undefined;
|
|
179
208
|
/**
|
|
180
209
|
* Process AI output for SDD auto-detection (spec, tasks, plan).
|
|
181
210
|
* Returns displayable status messages.
|
|
182
211
|
*/
|
|
183
|
-
onSDDOutput?: (output: string) => Promise<string[]
|
|
212
|
+
onSDDOutput?: ((output: string) => Promise<string[]>) | undefined;
|
|
184
213
|
/**
|
|
185
214
|
* Subscribe to AutoPhase phase/graph events from the PhaseOrchestrator.
|
|
186
215
|
* Returns an unsubscribe function. The TUI uses this to drive the
|
|
187
216
|
* PhaseMonitor and PhasePanel live views via dispatch actions.
|
|
188
217
|
*/
|
|
189
|
-
subscribeAutoPhase?: (handler: (event: string, payload: unknown) => void) => () => void;
|
|
218
|
+
subscribeAutoPhase?: ((handler: (event: string, payload: unknown) => void) => () => void) | undefined;
|
|
190
219
|
/**
|
|
191
220
|
* Read the persisted autonomy settings (defaultMode, autoProceedDelayMs).
|
|
192
221
|
* Used by the SettingsPicker in the TUI on mount and after Ctrl+S toggle.
|
|
193
222
|
*/
|
|
194
|
-
getSettings?: () =>
|
|
195
|
-
mode: 'off' | 'suggest' | 'auto';
|
|
196
|
-
delayMs: number;
|
|
197
|
-
};
|
|
223
|
+
getSettings?: (() => Settings) | undefined;
|
|
198
224
|
/**
|
|
199
|
-
* Persist
|
|
225
|
+
* Persist settings changes. Returns null on success, or an
|
|
200
226
|
* error string on failure (so the TUI can display it as a hint).
|
|
201
227
|
*/
|
|
202
|
-
saveSettings?: (s:
|
|
203
|
-
mode: 'off' | 'suggest' | 'auto';
|
|
204
|
-
delayMs: number;
|
|
205
|
-
}) => string | null | Promise<string | null>;
|
|
228
|
+
saveSettings?: ((s: Settings) => string | null | Promise<string | null>) | undefined;
|
|
206
229
|
/**
|
|
207
230
|
* Predict likely next steps after a completed turn. The CLI wires this from
|
|
208
231
|
* the session provider and the `/next` toggle; it returns [] when prediction
|
|
209
232
|
* is disabled or autonomy isn't 'off'. Display-only — never executed.
|
|
210
233
|
*/
|
|
211
|
-
predictNext?: (input: {
|
|
234
|
+
predictNext?: ((input: {
|
|
212
235
|
userRequest: string;
|
|
213
236
|
assistantSummary: string;
|
|
214
|
-
}) => Promise<string[]
|
|
237
|
+
}) => Promise<string[]>) | undefined;
|
|
215
238
|
}
|
|
216
239
|
declare function runTui(opts: RunTuiOptions): Promise<number>;
|
|
217
240
|
|
|
218
|
-
export { type RunTuiOptions, runTui };
|
|
241
|
+
export { type RunTuiOptions, type Settings, runTui };
|