@wrongstack/tui 0.302.2 → 0.303.0
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/dist/app-action-type.d.ts +14 -0
- package/dist/app-props.d.ts +16 -2
- package/dist/app-state.d.ts +7 -0
- package/dist/components/design-picker.d.ts +3 -0
- package/dist/components/resume-picker.d.ts +4 -0
- package/dist/components/theme-picker.d.ts +21 -0
- package/dist/hooks/use-active-theme.d.ts +14 -0
- package/dist/hooks/use-app-picker-keys.d.ts +2 -1
- package/dist/hooks/use-picker-keys-types.d.ts +7 -0
- package/dist/hooks/use-theme-state.d.ts +16 -0
- package/dist/hooks/use-windowed-picker.d.ts +68 -0
- package/dist/index.js +2188 -1352
- package/dist/input-validation/action-types.d.ts +1 -1
- package/dist/reducers/composer.d.ts +1 -1
- package/dist/reducers/helpers.d.ts +1 -1
- package/dist/run-tui-options.d.ts +11 -1
- package/dist/theme.d.ts +42 -0
- package/dist/workbench-slash.d.ts +9 -0
- package/package.json +7 -7
|
@@ -160,6 +160,20 @@ export type Action = {
|
|
|
160
160
|
} | {
|
|
161
161
|
type: 'autonomyPickerHint';
|
|
162
162
|
text?: string | undefined;
|
|
163
|
+
}
|
|
164
|
+
/** Theme picker — opened by `/theme`. Selecting a row swaps the palette and
|
|
165
|
+
* persists the choice via the ConfigStore bridge from the host. */
|
|
166
|
+
| {
|
|
167
|
+
type: 'themePickerOpen';
|
|
168
|
+
selected?: number;
|
|
169
|
+
} | {
|
|
170
|
+
type: 'themePickerClose';
|
|
171
|
+
} | {
|
|
172
|
+
type: 'themePickerMove';
|
|
173
|
+
delta: number;
|
|
174
|
+
} | {
|
|
175
|
+
type: 'themePickerHint';
|
|
176
|
+
text?: string | undefined;
|
|
163
177
|
} | {
|
|
164
178
|
type: 'modePickerOpen';
|
|
165
179
|
modes: ModeOption[];
|
package/dist/app-props.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import type { Agent } from '@wrongstack/core/agent';
|
|
2
2
|
import type { CoordinatorEvent, Director } from '@wrongstack/core/coordination';
|
|
3
|
+
import type { EventBus } from '@wrongstack/core/kernel';
|
|
3
4
|
import type { SlashCommandRegistry } from '@wrongstack/core/registry';
|
|
4
5
|
import type { QueueStore } from '@wrongstack/core/storage';
|
|
5
|
-
import type { AttachmentStore, AutonomyStage, ContextSnapshot, FleetChatVerbosity, Message, TokenCounter, TokenSavingTier } from '@wrongstack/core/types';
|
|
6
|
-
import type { EventBus } from '@wrongstack/core/kernel';
|
|
6
|
+
import type { AttachmentStore, AutonomyStage, ConfigStore, ContextSnapshot, FleetChatVerbosity, Message, TokenCounter, TokenSavingTier } from '@wrongstack/core/types';
|
|
7
7
|
import type { VisionAdapters } from '@wrongstack/runtime/vision';
|
|
8
8
|
import type { SddLifecycleResult, SddRunControl } from '@wrongstack/sdd';
|
|
9
9
|
import type React from 'react';
|
|
@@ -205,11 +205,25 @@ export interface AppProps {
|
|
|
205
205
|
*/
|
|
206
206
|
/** Settings shape — shared between getSettings and saveSettings. */
|
|
207
207
|
getSettings?: (() => Settings) | undefined;
|
|
208
|
+
/**
|
|
209
|
+
* Live view over the persisted user config. The TUI uses this to:
|
|
210
|
+
* - apply `themePreset` on boot (so `/theme` choices persist across
|
|
211
|
+
* restarts), and
|
|
212
|
+
* - write `themePreset` back when the picker Enter handler fires
|
|
213
|
+
* (so the picker shows `[active]` on the right row next session).
|
|
214
|
+
*
|
|
215
|
+
* Optional for hosts that don't expose a config store (e.g. tests);
|
|
216
|
+
* when omitted the TUI stays on the default catppuccin palette and
|
|
217
|
+
* picker changes are ephemeral.
|
|
218
|
+
*/
|
|
219
|
+
configStore?: ConfigStore | undefined;
|
|
208
220
|
/**
|
|
209
221
|
* Persist settings changes. Returns null on success, or an
|
|
210
222
|
* error string on failure (so the TUI can display it as a hint).
|
|
211
223
|
*/
|
|
212
224
|
saveSettings?: ((s: Settings) => string | null | Promise<string | null>) | undefined;
|
|
225
|
+
/** Persist the active theme preset to disk so the next boot starts with it. */
|
|
226
|
+
saveThemePreset?: ((preset: import('@wrongstack/core/types').ThemePresetId) => Promise<void>) | undefined;
|
|
213
227
|
/** Load toggleable plugin rows for the interactive plugin picker. */
|
|
214
228
|
getPluginItems?: (() => PluginPickerItem[]) | undefined;
|
|
215
229
|
/** Toggle one plugin from the interactive picker and return the refreshed rows. */
|
package/dist/app-state.d.ts
CHANGED
|
@@ -167,6 +167,13 @@ export type State = {
|
|
|
167
167
|
selected: number;
|
|
168
168
|
hint?: string | undefined;
|
|
169
169
|
};
|
|
170
|
+
/** Single-step theme picker — opened by `/theme`. Lists every preset and
|
|
171
|
+
* applies the chosen one instantly (in-place palette mutation + persist). */
|
|
172
|
+
themePicker: {
|
|
173
|
+
open: boolean;
|
|
174
|
+
selected: number;
|
|
175
|
+
hint?: string | undefined;
|
|
176
|
+
};
|
|
170
177
|
/** Agent mode picker — opened by `/mode`. Selects teach/brief/code-reviewer/etc. */
|
|
171
178
|
modePicker: {
|
|
172
179
|
open: boolean;
|
|
@@ -9,6 +9,9 @@ export interface DesignPickerProps {
|
|
|
9
9
|
* Design Studio kit picker overlay (opened by `/design`). Presentational only —
|
|
10
10
|
* navigation/selection state lives in the reducer; Enter runs `/design <id>
|
|
11
11
|
* <stack>` through the normal submit path, which pins the kit + loads its spec.
|
|
12
|
+
*
|
|
13
|
+
* Windowed via {@link useWindowedPicker} so 50+ installed kits stay
|
|
14
|
+
* navigable on small terminals.
|
|
12
15
|
*/
|
|
13
16
|
export declare function DesignPicker({ kits, selected, stack }: DesignPickerProps): React.ReactElement;
|
|
14
17
|
//# sourceMappingURL=design-picker.d.ts.map
|
|
@@ -11,6 +11,10 @@ export interface ResumePickerProps {
|
|
|
11
11
|
* Interactive session-resume picker. Renders a scrollable list of recent
|
|
12
12
|
* sessions with metadata (id, date, tokens, tools, outcome badge) so the user
|
|
13
13
|
* can pick one to resume. The current session is grayed out and non-selectable.
|
|
14
|
+
*
|
|
15
|
+
* Windowed via {@link useWindowedPicker} with `rowSpan=3` — each session takes
|
|
16
|
+
* three rows (title line, meta line, preview line). The window auto-recenters
|
|
17
|
+
* on the focused session so 30+ entries stay navigable on a 24-row terminal.
|
|
14
18
|
*/
|
|
15
19
|
export declare function ResumePicker({ sessions, selected, busy, error, hint, }: ResumePickerProps): React.ReactElement;
|
|
16
20
|
//# sourceMappingURL=resume-picker.d.ts.map
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type React from 'react';
|
|
2
|
+
import type { ThemeName, ThemePickerOption } from '../theme.js';
|
|
3
|
+
export interface ThemePickerProps {
|
|
4
|
+
options: readonly ThemePickerOption[];
|
|
5
|
+
selected: number;
|
|
6
|
+
activeId: ThemeName;
|
|
7
|
+
hint?: string | undefined;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Interactive theme picker. Mirrors the autonomy-picker visual pattern
|
|
11
|
+
* (bordered box, ↑/↓ navigate, Enter apply, Esc cancel) so the two
|
|
12
|
+
* pickers look and feel consistent. The currently active preset is
|
|
13
|
+
* highlighted with a `[active]` marker so the user can see whether
|
|
14
|
+
* their selection will actually change anything.
|
|
15
|
+
*
|
|
16
|
+
* The list is windowed via {@link useWindowedPicker} so 15+ presets stay
|
|
17
|
+
* usable on small terminals — a top-aligned `…` marker appears when the
|
|
18
|
+
* focused row is below the start of the visible window.
|
|
19
|
+
*/
|
|
20
|
+
export declare function ThemePicker({ options, selected, activeId, hint, }: ThemePickerProps): React.ReactElement;
|
|
21
|
+
//# sourceMappingURL=theme-picker.d.ts.map
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Subscribes to the module-scoped active theme so a render reads the
|
|
3
|
+
* current `theme` snapshot. Used by the App shell to force a re-render
|
|
4
|
+
* when `setActiveTheme()` mutates the global theme — child components
|
|
5
|
+
* read `theme` directly via destructuring, so the parent re-render
|
|
6
|
+
* propagates the new palette into the whole tree.
|
|
7
|
+
*
|
|
8
|
+
* The hook itself returns the live `theme` reference; callers don't
|
|
9
|
+
* typically need to use it (they can keep reading `theme` directly),
|
|
10
|
+
* but exposing it lets test code and stat panels introspect the active
|
|
11
|
+
* palette without re-implementing the listener.
|
|
12
|
+
*/
|
|
13
|
+
export declare function useActiveTheme(): import("../theme.js").Theme;
|
|
14
|
+
//# sourceMappingURL=use-active-theme.d.ts.map
|
|
@@ -31,7 +31,8 @@ interface UseAppPickerKeysOptions {
|
|
|
31
31
|
handleShadowStop: () => Promise<void>;
|
|
32
32
|
statuslineHiddenForPicker: () => StatuslineItem[];
|
|
33
33
|
onPickerEnter: () => Promise<void>;
|
|
34
|
+
onThemePickerEnter?: () => void;
|
|
34
35
|
}
|
|
35
|
-
export declare function useAppPickerKeys({ host, state, dispatch, environment, statusbar, panelControllers, authPanelController, brainController, lastEnterAtRef, inputGateRef, submitRef, promptUsageRef, setDraft, acceptSlashPickerSelection, changeBrainRisk, handleModelPicked, handleShadowStart, handleShadowStop, statuslineHiddenForPicker, onPickerEnter, }: UseAppPickerKeysOptions): (input: string, key: import("../components/input.js").KeyEvent, isEnter: boolean) => boolean;
|
|
36
|
+
export declare function useAppPickerKeys({ host, state, dispatch, environment, statusbar, panelControllers, authPanelController, brainController, lastEnterAtRef, inputGateRef, submitRef, promptUsageRef, setDraft, acceptSlashPickerSelection, changeBrainRisk, handleModelPicked, handleShadowStart, handleShadowStop, statuslineHiddenForPicker, onPickerEnter, onThemePickerEnter, }: UseAppPickerKeysOptions): (input: string, key: import("../components/input.js").KeyEvent, isEnter: boolean) => boolean;
|
|
36
37
|
export {};
|
|
37
38
|
//# sourceMappingURL=use-app-picker-keys.d.ts.map
|
|
@@ -51,6 +51,13 @@ export interface PickerKeysHost {
|
|
|
51
51
|
onShadowStop: (() => Promise<void> | void) | undefined;
|
|
52
52
|
onFKeyPickerEnter: (() => void) | undefined;
|
|
53
53
|
onPickerEnter: (() => Promise<void>) | undefined;
|
|
54
|
+
/**
|
|
55
|
+
* Enter-handler for the `/theme` picker. The key dispatcher delegates
|
|
56
|
+
* the apply step here so the parent can call `setActiveTheme()` and
|
|
57
|
+
* persist the choice to configStore. Optional — omitted hosts simply
|
|
58
|
+
* leave Enter as a no-op (the picker still navigates, just doesn't apply).
|
|
59
|
+
*/
|
|
60
|
+
onThemePickerEnter?: (() => void) | undefined;
|
|
54
61
|
onSlashPickerTab: (() => void) | undefined;
|
|
55
62
|
}
|
|
56
63
|
//# sourceMappingURL=use-picker-keys-types.d.ts.map
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { ConfigStore } from '@wrongstack/core/types';
|
|
2
|
+
/**
|
|
3
|
+
* Boot-time theme wiring: reads `config.themePreset` once on mount, applies it
|
|
4
|
+
* via `setActiveTheme()`, and subscribes to the live `ConfigStore` so any
|
|
5
|
+
* in-session update (e.g. from the REPL or a future hot-reload) is mirrored
|
|
6
|
+
* into the visible palette immediately.
|
|
7
|
+
*
|
|
8
|
+
* Falls back to the current preset (catppuccin at first mount) if the config
|
|
9
|
+
* has no `themePreset` set — that's the legacy behaviour for users without an
|
|
10
|
+
* explicit choice, and it makes the picker UI immediately meaningful on first
|
|
11
|
+
* run because the active row is highlighted.
|
|
12
|
+
*/
|
|
13
|
+
export declare function useThemeState({ configStore }: {
|
|
14
|
+
configStore: ConfigStore | undefined;
|
|
15
|
+
}): void;
|
|
16
|
+
//# sourceMappingURL=use-theme-state.d.ts.map
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One shared viewport-windowing rule for the pickers that overlay the chat
|
|
3
|
+
* history (theme / autonomy / design / resume).
|
|
4
|
+
*
|
|
5
|
+
* Before this hook, every picker rendered every option as a static
|
|
6
|
+
* `<Box flexDirection="column">`. That was fine for autonomy's 5 options but
|
|
7
|
+
* started overflowing as soon as `/theme` carried 15 presets and `/resume`
|
|
8
|
+
* could list 30+ sessions. The pickers live inside the scrollable chat
|
|
9
|
+
* viewport — they share its row budget — so windowing has to be driven off
|
|
10
|
+
* `useTerminalSize` and per-picker chrome, not a hardcoded count.
|
|
11
|
+
*
|
|
12
|
+
* The hook returns the inclusive `start` and exclusive `end` of the visible
|
|
13
|
+
* slice plus `hasAbove` / `hasBelow` indicators the caller can render as
|
|
14
|
+
* `…` markers. When the caller moves `selected`, the next call re-centers
|
|
15
|
+
* the viewport on the new index — no imperative scroll needed.
|
|
16
|
+
*/
|
|
17
|
+
export interface UseWindowedPickerOptions {
|
|
18
|
+
/** Total option count. */
|
|
19
|
+
readonly total: number;
|
|
20
|
+
/** Currently focused option index. The window re-centers on this. */
|
|
21
|
+
readonly selected: number;
|
|
22
|
+
/** Rows each option consumes (resume-picker entries take 3 lines). */
|
|
23
|
+
readonly rowSpan?: number | undefined;
|
|
24
|
+
/**
|
|
25
|
+
* Rows the picker itself reserves around the list — top/bottom border,
|
|
26
|
+
* header, hint, padding. Defaults to 4 which matches the current
|
|
27
|
+
* `borderStyle="round"` + 2-line header pattern. Pass 0 for a naked list.
|
|
28
|
+
*/
|
|
29
|
+
readonly chromeRows?: number | undefined;
|
|
30
|
+
/**
|
|
31
|
+
* Rows the surrounding app shell reserves — input bar + status bar + the
|
|
32
|
+
* scrollable history's own chrome. Defaults to 6, which covers the input
|
|
33
|
+
* bar (1), status bar (1), and a 4-row safety margin for header / hint /
|
|
34
|
+
* padding. Bump this if your caller knows it needs more breathing room.
|
|
35
|
+
*/
|
|
36
|
+
readonly shellReservedRows?: number | undefined;
|
|
37
|
+
/** Minimum visible options even on a tiny terminal. Defaults to 3. */
|
|
38
|
+
readonly minVisible?: number | undefined;
|
|
39
|
+
}
|
|
40
|
+
export interface WindowedPickerSlice {
|
|
41
|
+
/** Inclusive start index of the visible window. */
|
|
42
|
+
readonly start: number;
|
|
43
|
+
/** Exclusive end index of the visible window. */
|
|
44
|
+
readonly end: number;
|
|
45
|
+
/** True when at least one option is hidden above `start`. */
|
|
46
|
+
readonly hasAbove: boolean;
|
|
47
|
+
/** True when at least one option is hidden below `end - 1`. */
|
|
48
|
+
readonly hasBelow: boolean;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Compute a windowed slice of a picker list. Pure given the inputs — the only
|
|
52
|
+
* "reactive" part is `useTerminalSize` so the window re-flows when the user
|
|
53
|
+
* resizes their terminal while a picker is open.
|
|
54
|
+
*
|
|
55
|
+
* Behavior contract:
|
|
56
|
+
* - Visible count is `floor((rows - chrome) / rowSpan)`, clamped to
|
|
57
|
+
* `[minVisible, total]`. A 1-row terminal always shows at least
|
|
58
|
+
* `minVisible` options even if that overflows — better to bleed than to
|
|
59
|
+
* hide the focused row.
|
|
60
|
+
* - The window stays centered on `selected` once the picker is past the
|
|
61
|
+
* first page; on the first page it stays top-aligned so the user sees
|
|
62
|
+
* the list start. `selected < 0 || selected >= total` is treated as no
|
|
63
|
+
* focus and the window anchors to index 0.
|
|
64
|
+
* - Empty / single-option lists always render `[0, total)` with both
|
|
65
|
+
* `hasAbove` and `hasBelow` false.
|
|
66
|
+
*/
|
|
67
|
+
export declare function useWindowedPicker({ total, selected, rowSpan, chromeRows, shellReservedRows, minVisible, }: UseWindowedPickerOptions): WindowedPickerSlice;
|
|
68
|
+
//# sourceMappingURL=use-windowed-picker.d.ts.map
|