@wrongstack/tui 0.298.0 → 0.298.2
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 +16 -1
- package/dist/app-key-handler.d.ts +4 -0
- package/dist/app-settings-type.d.ts +30 -2
- package/dist/app-state.d.ts +17 -4
- package/dist/app-status-region.d.ts +7 -2
- package/dist/app-ui-state.d.ts +24 -0
- package/dist/auth-panel-model.d.ts +36 -2
- package/dist/components/fleet-panel.d.ts +3 -1
- package/dist/components/history/copy-geometry.d.ts +61 -0
- package/dist/components/history/sage-output-format.d.ts +7 -6
- package/dist/components/history/scroll-controller-types.d.ts +116 -0
- package/dist/components/history/scrollbar-geometry.d.ts +60 -0
- package/dist/components/history/scrollbar-rail.d.ts +18 -0
- package/dist/components/history/selection-helpers.d.ts +111 -0
- package/dist/components/input.d.ts +8 -1
- package/dist/components/plan-panel.d.ts +30 -3
- package/dist/components/scrollable-history.d.ts +7 -335
- package/dist/components/settings-picker-model.d.ts +13 -52
- package/dist/components/settings-picker.d.ts +10 -5
- package/dist/components/sidebar-content.d.ts +47 -0
- package/dist/components/sidebar-panel-frame.d.ts +80 -0
- package/dist/components/sidebar-panels.d.ts +136 -0
- package/dist/components/sidebar.d.ts +49 -0
- package/dist/components/status-bar-format.d.ts +10 -0
- package/dist/components/status-bar-types.d.ts +7 -0
- package/dist/components/status-bar.d.ts +1 -1
- package/dist/hit-test.d.ts +3 -2
- package/dist/hooks/use-provider-event-bridge.d.ts +1 -1
- package/dist/hooks/use-sidebar-panel-data.d.ts +59 -0
- package/dist/index.js +4224 -2010
- package/dist/input-validation/action-types.d.ts +1 -1
- package/dist/reducers/helpers.d.ts +1 -1
- package/dist/reducers/workspace-panels.d.ts +1 -1
- package/dist/settings-contracts.d.ts +11 -1
- package/dist/ui-contracts.d.ts +54 -0
- package/package.json +8 -8
|
@@ -42,6 +42,13 @@ export interface InputProps {
|
|
|
42
42
|
/** Row count for the hidden placeholder so the bottom region never resizes. */
|
|
43
43
|
placeholderHeight?: number | undefined;
|
|
44
44
|
onKey: (input: string, key: KeyEvent) => void;
|
|
45
|
+
/**
|
|
46
|
+
* Optional cap on the column width used for wrapping and frame sizing.
|
|
47
|
+
* When set, the input area treats this as its effective terminal width
|
|
48
|
+
* instead of `stdout.columns` — needed when the input sits in a column
|
|
49
|
+
* narrower than the full terminal (e.g. beside a sidebar).
|
|
50
|
+
*/
|
|
51
|
+
maxWidth?: number | undefined;
|
|
45
52
|
}
|
|
46
53
|
export interface KeyEvent {
|
|
47
54
|
upArrow: boolean;
|
|
@@ -76,5 +83,5 @@ export interface KeyEvent {
|
|
|
76
83
|
fn?: number | undefined;
|
|
77
84
|
}
|
|
78
85
|
export declare const EMPTY_KEY: KeyEvent;
|
|
79
|
-
export declare const Input: React.MemoExoticComponent<({ prompt, value, cursor, disabled, hint, title, status, animationStyle, workingTime, footerHint, hidden, placeholderHeight, onKey, }: InputProps) => React.ReactElement>;
|
|
86
|
+
export declare const Input: React.MemoExoticComponent<({ prompt, value, cursor, disabled, hint, title, status, animationStyle, workingTime, footerHint, hidden, placeholderHeight, onKey, maxWidth, }: InputProps) => React.ReactElement>;
|
|
80
87
|
//# sourceMappingURL=input.d.ts.map
|
|
@@ -1,4 +1,22 @@
|
|
|
1
1
|
import type React from 'react';
|
|
2
|
+
export interface PlanItem {
|
|
3
|
+
id: string;
|
|
4
|
+
title: string;
|
|
5
|
+
details?: string;
|
|
6
|
+
status: 'open' | 'in_progress' | 'done';
|
|
7
|
+
createdAt: string;
|
|
8
|
+
updatedAt: string;
|
|
9
|
+
}
|
|
10
|
+
export interface PlanPanelData {
|
|
11
|
+
items: PlanItem[];
|
|
12
|
+
title?: string | undefined;
|
|
13
|
+
scope: 'session' | 'project';
|
|
14
|
+
loading: boolean;
|
|
15
|
+
error: string | null;
|
|
16
|
+
updatedAt?: string | undefined;
|
|
17
|
+
setScope: (scope: 'session' | 'project') => void;
|
|
18
|
+
load: (scope: 'session' | 'project', quiet?: boolean) => Promise<void>;
|
|
19
|
+
}
|
|
2
20
|
export interface PlanPanelProps {
|
|
3
21
|
/** Absolute path to the project root. */
|
|
4
22
|
projectRoot: string;
|
|
@@ -8,10 +26,19 @@ export interface PlanPanelProps {
|
|
|
8
26
|
onClose: () => void;
|
|
9
27
|
}
|
|
10
28
|
/**
|
|
11
|
-
*
|
|
29
|
+
* Plan panel data hook (F5 in TUI).
|
|
30
|
+
*
|
|
31
|
+
* Reads the active plan JSON file from disk and renders plan items grouped
|
|
32
|
+
* by status. Shows the current scope and a hint for switching scopes via
|
|
33
|
+
* the /plan tool.
|
|
12
34
|
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
35
|
+
* Each consumer gets its own polling interval, gated by `enabled` (default
|
|
36
|
+
* true). Consumers pass `enabled` reflecting whether their panel surface is
|
|
37
|
+
* actually mounted — e.g. app-view gates the sidebar twin on its slot
|
|
38
|
+
* visibility — so a closed or bottom-routed plan panel does not keep a
|
|
39
|
+
* second 3s file-read poll alive for the whole session (the bottom PlanPanel
|
|
40
|
+
* mounts its own instance of this hook while open).
|
|
15
41
|
*/
|
|
42
|
+
export declare function usePlanPanelData(projectRoot: string, sessionId: string | null, enabled?: boolean): PlanPanelData;
|
|
16
43
|
export declare function PlanPanel({ projectRoot, sessionId, onClose: _onClose, }: PlanPanelProps): React.ReactElement;
|
|
17
44
|
//# sourceMappingURL=plan-panel.d.ts.map
|
|
@@ -1,339 +1,11 @@
|
|
|
1
1
|
import type React from 'react';
|
|
2
|
-
import { type
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
* scroll math needs the live height cache, which lives here, and routing it
|
|
10
|
-
* through app state previously forced totals and offsets to travel through
|
|
11
|
-
* separate commits — the root cause of an entire family of jump bugs.
|
|
12
|
-
*/
|
|
13
|
-
export interface HistoryScrollController {
|
|
14
|
-
/** Scroll by `deltaUp` rows: positive = older content, negative = newer. */
|
|
15
|
-
scrollBy(deltaUp: number): void;
|
|
16
|
-
/** Scroll by one viewport page. */
|
|
17
|
-
scrollPage(dir: 'up' | 'down'): void;
|
|
18
|
-
/** Jump to the oldest retained entry. */
|
|
19
|
-
scrollToTop(): void;
|
|
20
|
-
/** Re-pin to the newest output. */
|
|
21
|
-
scrollToBottom(): void;
|
|
22
|
-
/** Jump to a 0-based cell clicked/dragged on the scrollbar track. */
|
|
23
|
-
scrollToTrackCell(cell: number): void;
|
|
24
|
-
/** True while the viewport is scrolled away from the newest output. */
|
|
25
|
-
isScrolled(): boolean;
|
|
26
|
-
/**
|
|
27
|
-
* True when the viewport cell lands on a copyable card's copy icon. Lets the
|
|
28
|
-
* mouse handler decide synchronously whether to consume the click before
|
|
29
|
-
* firing the async copy. See {@link copyAtViewportCell} for the `row`/`col`
|
|
30
|
-
* coordinate contract.
|
|
31
|
-
*/
|
|
32
|
-
hasCopyTargetAt(row: number, col: number): boolean;
|
|
33
|
-
/**
|
|
34
|
-
* Handle a left-click inside the history viewport. `row` is 0-based from the
|
|
35
|
-
* viewport top; `col` is 0-based from the LEFT EDGE OF THE HISTORY BAND, not
|
|
36
|
-
* the raw terminal column. In the interactive mount the band renders flush at
|
|
37
|
-
* terminal column 0 (the scrollbar occupies the rightmost columns), so the
|
|
38
|
-
* caller passes the terminal column directly; a band that is inset from the
|
|
39
|
-
* left must subtract its left offset first. When the cell lands on a copyable
|
|
40
|
-
* card's copy icon, its content is written to the system clipboard and the
|
|
41
|
-
* entry id is returned; otherwise returns null.
|
|
42
|
-
*/
|
|
43
|
-
copyAtViewportCell(row: number, col: number): Promise<number | null>;
|
|
44
|
-
/**
|
|
45
|
-
* Begin a drag-to-select gesture at `row`,`col` (history-band viewport cell).
|
|
46
|
-
* The cell must be inside a card's row range and inside the rendered band
|
|
47
|
-
* (`0 <= col < termWidth`); the mouse handler has already excluded the rail.
|
|
48
|
-
* Calls that don't satisfy that contract are silently ignored. Existing
|
|
49
|
-
* scrollbar/copy-icon/wheel paths remain intact because they call their own
|
|
50
|
-
* handlers; this only kicks in when the mouse layer explicitly routes a
|
|
51
|
-
* left-press into the card band.
|
|
52
|
-
*/
|
|
53
|
-
beginSelection(row: number, col: number): void;
|
|
54
|
-
/**
|
|
55
|
-
* Extend an active selection to `row`,`col`. If no selection is in progress,
|
|
56
|
-
* the call is a no-op. Crossing into the gutter or below the viewport cancels
|
|
57
|
-
* the drag internally — leaving stale viewport-relative coords around after
|
|
58
|
-
* a mid-drag escape would let the next right-click paste from the wrong
|
|
59
|
-
* card, which is the worse failure mode than the selection disappearing.
|
|
60
|
-
*/
|
|
61
|
-
extendSelection(row: number, col: number): void;
|
|
62
|
-
/**
|
|
63
|
-
* End an active drag (left-release). Does NOT write to the clipboard — the
|
|
64
|
-
* copy is performed by {@link commitSelection}, which is triggered by a
|
|
65
|
-
* separate right-click in the history band (per the drag-select-then-commit
|
|
66
|
-
* contract). If no selection is in progress, the call is a no-op.
|
|
67
|
-
*/
|
|
68
|
-
endSelection(): void;
|
|
69
|
-
/** Drop any in-progress or committed selection without copying. */
|
|
70
|
-
clearSelection(): void;
|
|
71
|
-
/**
|
|
72
|
-
* Commit the active selection to the system clipboard. Returns true if a
|
|
73
|
-
* non-empty selection was resolved and the write succeeded. Returns false
|
|
74
|
-
* silently when there is no selection, the selection is empty (e.g. the drag
|
|
75
|
-
* never moved), or the write fails — the caller can show a transient notice
|
|
76
|
-
* on the truthy branch and stay silent on the falsy branch.
|
|
77
|
-
*/
|
|
78
|
-
commitSelection(): Promise<boolean>;
|
|
79
|
-
}
|
|
80
|
-
/**
|
|
81
|
-
* A clickable copy-icon target resolved in viewport coordinates during the
|
|
82
|
-
* post-render measurement pass. `entryId` identifies a single card or the first
|
|
83
|
-
* member of a compact tool group; `entryIds` contains every group member when
|
|
84
|
-
* present. `startRow`/`endRow` bound the box's visible rows (0-based from the
|
|
85
|
-
* viewport top, `endRow` exclusive); `iconCol` is the 0-based terminal column
|
|
86
|
-
* the icon renders at on the box's first visible row.
|
|
87
|
-
*/
|
|
88
|
-
export interface CopyHit {
|
|
89
|
-
entryId: number;
|
|
90
|
-
entryIds?: readonly number[] | undefined;
|
|
91
|
-
startRow: number;
|
|
92
|
-
endRow: number;
|
|
93
|
-
iconCol: number;
|
|
94
|
-
}
|
|
95
|
-
/** Sentinel returned after copying the active, non-retained tool-stream box. */
|
|
96
|
-
export declare const LIVE_TOOL_STREAM_COPY_ID = -1;
|
|
97
|
-
/** Sentinel returned after copying a drag-select-then-right-click selection.
|
|
98
|
-
* Distinct from any retained entry id so the host can render a different
|
|
99
|
-
* status-line notice ("Selected range copied") without flashing a specific
|
|
100
|
-
* card's copy icon (which only makes sense when a single entry was copied). */
|
|
101
|
-
export declare const SELECTION_COPY_ID = -2;
|
|
102
|
-
/**
|
|
103
|
-
* Resolve the copy target under a viewport cell, or null. A cell matches when
|
|
104
|
-
* its `row` is within the card's visible rows and its `col` is within the
|
|
105
|
-
* icon's cell span. Iterates newest-first so overlapping row estimates favor
|
|
106
|
-
* the most recently rendered card. Exported-shape pure helper for unit tests.
|
|
107
|
-
*/
|
|
108
|
-
export declare function findCopyHit(hits: readonly CopyHit[], row: number, col: number): CopyHit | null;
|
|
109
|
-
/** Resolve a hit to the complete current clipboard payload without performing I/O. */
|
|
110
|
-
export declare function resolveCopyPayload(hit: CopyHit, entriesById: ReadonlyMap<number, HistoryEntry>, liveToolText?: string | undefined): {
|
|
111
|
-
entryId: number;
|
|
112
|
-
text: string;
|
|
113
|
-
} | null;
|
|
114
|
-
/**
|
|
115
|
-
* Rows clipped from the top of the mounted history stack before it appears in
|
|
116
|
-
* the viewport. Scrolled frames clip by the anchor's row offset; pinned frames
|
|
117
|
-
* rely on Ink flex-end clipping, which hides top overflow from mounted groups
|
|
118
|
-
* plus the live tool tail.
|
|
119
|
-
*/
|
|
120
|
-
export declare function copyRegistryVisibleClip(opts: {
|
|
121
|
-
scrolled: boolean;
|
|
122
|
-
clip: number;
|
|
123
|
-
mountedRows: number;
|
|
124
|
-
tailRows: number;
|
|
125
|
-
viewportRows: number;
|
|
126
|
-
}): number;
|
|
127
|
-
/** Build the live tool-stream header hit, accounting for ToolStreamBox's top margin.
|
|
128
|
-
* The `pinnedSlack` offset must match {@link buildCopyRegistry}'s card-hit math so
|
|
129
|
-
* the live-stream icon stays visually aligned with its header row in underfilled
|
|
130
|
-
* pinned frames (flex-end parks the mounted stack at the bottom of the viewport). */
|
|
131
|
-
export declare function liveToolStreamCopyHit(opts: {
|
|
132
|
-
visible: boolean;
|
|
133
|
-
mountedRows: number;
|
|
134
|
-
visibleClip: number;
|
|
135
|
-
viewportRows: number;
|
|
136
|
-
iconCol: number;
|
|
137
|
-
pinnedSlack?: number;
|
|
138
|
-
}): CopyHit | null;
|
|
139
|
-
/**
|
|
140
|
-
* Selection rectangle in viewport cell coordinates, normalized so
|
|
141
|
-
* `topLeft.row <= bottomRight.row` and the column pairs are likewise ordered.
|
|
142
|
-
* Both endpoints are inclusive — the cell at `bottomRight` is selected.
|
|
143
|
-
*/
|
|
144
|
-
export interface SelectionRect {
|
|
145
|
-
topLeft: {
|
|
146
|
-
row: number;
|
|
147
|
-
col: number;
|
|
148
|
-
};
|
|
149
|
-
bottomRight: {
|
|
150
|
-
row: number;
|
|
151
|
-
col: number;
|
|
152
|
-
};
|
|
153
|
-
/** True while the user is still dragging; false after left-release but
|
|
154
|
-
* before either clearSelection or commitSelection runs. */
|
|
155
|
-
inProgress: boolean;
|
|
156
|
-
}
|
|
157
|
-
/** Canonicalize two viewport cells into a SelectionRect. Pure. */
|
|
158
|
-
export declare function normalizeSelection(a: {
|
|
159
|
-
row: number;
|
|
160
|
-
col: number;
|
|
161
|
-
}, b: {
|
|
162
|
-
row: number;
|
|
163
|
-
col: number;
|
|
164
|
-
}, inProgress: boolean): SelectionRect;
|
|
165
|
-
/** True when the column lies outside the rendered card band. Inside the band
|
|
166
|
-
* the layout reserves `SCROLLBAR_HIT_WIDTH` columns for the rail AFTER the
|
|
167
|
-
* band, so `0..termWidth-1` is always in-band and nothing inside needs to be
|
|
168
|
-
* excluded. The mouse handler must already have excluded the rail before
|
|
169
|
-
* calling into the controller — we only check the band bounds here. */
|
|
170
|
-
export declare function isOutOfBand(col: number, termWidth: number): boolean;
|
|
171
|
-
/**
|
|
172
|
-
* One entry's contribution to a drag-selected range. Returned in document
|
|
173
|
-
* (row-index-in-card) coordinates so the caller decides how to slice into
|
|
174
|
-
* the entry's source text. `start` is the column inside the card (0-based
|
|
175
|
-
* from the left edge of the card's visible rectangle, NOT the terminal
|
|
176
|
-
* column — the gutter is excluded by the caller before reaching here).
|
|
177
|
-
* `end` is inclusive. When `startRow === endRow`, the slice is one row; the
|
|
178
|
-
* caller is responsible for translating text columns into source offsets.
|
|
179
|
-
*/
|
|
180
|
-
export interface SelectionSlice {
|
|
181
|
-
entryId: number;
|
|
182
|
-
/** Inclusive row-in-card for the start of the slice. */
|
|
183
|
-
startRow: number;
|
|
184
|
-
/** Inclusive column, 0-based, inside the card's text area (gutter excluded). */
|
|
185
|
-
startCol: number;
|
|
186
|
-
/** Inclusive end row. */
|
|
187
|
-
endRow: number;
|
|
188
|
-
/** Inclusive end column, 0-based. */
|
|
189
|
-
endCol: number;
|
|
190
|
-
}
|
|
191
|
-
/**
|
|
192
|
-
* Translate a viewport-cell selection into per-entry row/col slices, walking
|
|
193
|
-
* the same mounted-group geometry the copy-hit registry uses so the two
|
|
194
|
-
* systems share one row index. Entries wholly outside the selection return
|
|
195
|
-
* nothing. Entries whose vertical span is wholly inside the selection are
|
|
196
|
-
* returned as a single row-range; entries the selection clips at the top or
|
|
197
|
-
* bottom are returned with row bounds matching the clip.
|
|
198
|
-
*
|
|
199
|
-
* `cardVisibleCols` is the number of columns inside the card the user can
|
|
200
|
-
* see — the band width minus the right gutter (`viewportWidth - SCROLLBAR_HIT_WIDTH`).
|
|
201
|
-
* Slices never include the gutter or any column to its right; the caller has
|
|
202
|
-
* already validated that.
|
|
203
|
-
*
|
|
204
|
-
* Returned slices are in document (entry-local) coordinates: `startRow`/`endRow`
|
|
205
|
-
* are rows inside the entry's own geometry, NOT viewport cells. This is what
|
|
206
|
-
* the assembler needs to recover text — slicing into the raw entry text uses
|
|
207
|
-
* per-row layout, which the caller resolves via the layout store.
|
|
208
|
-
*/
|
|
209
|
-
export declare function selectionToSlices(opts: {
|
|
210
|
-
selection: SelectionRect;
|
|
211
|
-
cards: ReadonlyArray<{
|
|
212
|
-
entryId: number;
|
|
213
|
-
/** 0-based viewport row of the card's first visible row. */
|
|
214
|
-
viewportStartRow: number;
|
|
215
|
-
/** 0-based viewport row just past the card's last visible row. */
|
|
216
|
-
viewportEndRow: number;
|
|
217
|
-
}>;
|
|
218
|
-
cardVisibleCols: number;
|
|
219
|
-
}): SelectionSlice[];
|
|
220
|
-
export interface ScrollableHistoryProps extends HistoryProps {
|
|
221
|
-
/** Height of the viewport in rows, computed by App from the bottom region. */
|
|
222
|
-
viewportRows: number;
|
|
223
|
-
/** Receives the imperative scroll controller. The component assigns on
|
|
224
|
-
* mount and clears on unmount. Optional for isolated renderers. */
|
|
225
|
-
controllerRef?: MutableRefObject<HistoryScrollController | null> | undefined;
|
|
226
|
-
/** Reports scroll-state transitions (scrolled away from / re-pinned to the
|
|
227
|
-
* newest output) so the host can adjust key hints. */
|
|
228
|
-
onScrollInfo?: ((info: {
|
|
229
|
-
scrolled: boolean;
|
|
230
|
-
}) => void) | undefined;
|
|
231
|
-
/** Optional cap on the width used for entry wrapping (right panel mode). */
|
|
232
|
-
maxWidth?: number | undefined;
|
|
233
|
-
/** Layout store for persisting entry height data across renders and sessions.
|
|
234
|
-
* When provided, the ScrollableHistory seeds its height cache from the
|
|
235
|
-
* store's persisted measurements and marks entries as measured after render,
|
|
236
|
-
* eliminating estimate-vs-actual scroll jumps on re-render. */
|
|
237
|
-
layoutStore?: import('../layout-store.js').LayoutStore | undefined;
|
|
238
|
-
/**
|
|
239
|
-
* Entry id of the card whose copy icon was just clicked. That card's icon
|
|
240
|
-
* renders in the success color for the brief window the host keeps this set,
|
|
241
|
-
* giving per-card visual feedback alongside the status-line "Copied" notice.
|
|
242
|
-
* `null` / undefined = no card highlighted.
|
|
243
|
-
*/
|
|
244
|
-
copiedEntryId?: number | null | undefined;
|
|
245
|
-
/**
|
|
246
|
-
* Called when the user scrolls near the top of the currently loaded
|
|
247
|
-
* entries. The host should respond by loading older entries from the
|
|
248
|
-
* history archive and dispatching `archiveLoaded` to prepend them.
|
|
249
|
-
*/
|
|
250
|
-
onRequestOlderEntries?: (() => void) | undefined;
|
|
251
|
-
}
|
|
252
|
-
/** Pure thumb geometry for the scrollbar: where the thumb starts and how many
|
|
253
|
-
* cells it spans, given the track height, scroll offset, and total content
|
|
254
|
-
* height. Exported for testing. */
|
|
255
|
-
export declare function scrollbarThumb(rows: number, offset: number, total: number): {
|
|
256
|
-
top: number;
|
|
257
|
-
size: number;
|
|
258
|
-
scrollable: boolean;
|
|
259
|
-
};
|
|
260
|
-
/** Inverse of {@link scrollbarThumb}: given a clicked/dragged 0-based cell on a
|
|
261
|
-
* track of `rows` height, return the scroll offset (rows up from the bottom)
|
|
262
|
-
* that lands the visible window there. Cell 0 (top) → oldest content (max
|
|
263
|
-
* offset); cell rows-1 (bottom) → newest (offset 0). Exported for testing. */
|
|
264
|
-
export declare function scrollOffsetForTrackRow(rows: number, total: number, cell: number): number;
|
|
265
|
-
/**
|
|
266
|
-
* Per-card viewport span for the currently-mounted groups. Mirrors
|
|
267
|
-
* {@link buildCopyRegistry}'s visibleClip math so the drag-select gesture asks
|
|
268
|
-
* the same geometry question the copy-hit registry already answers.
|
|
269
|
-
*/
|
|
270
|
-
export interface MountedCardSpan {
|
|
271
|
-
entryId: number;
|
|
272
|
-
/** 0-based viewport row of the first VISIBLE row of the card. */
|
|
273
|
-
viewportStartRow: number;
|
|
274
|
-
/** 0-based viewport row one past the last VISIBLE row of the card. */
|
|
275
|
-
viewportEndRow: number;
|
|
276
|
-
/** Card's geometry in rows; visibleClip + scrolled-clip aware. */
|
|
277
|
-
totalRows: number;
|
|
278
|
-
entryIds?: readonly number[];
|
|
279
|
-
}
|
|
280
|
-
/**
|
|
281
|
-
* Build per-card viewport spans for every mounted render group. Pure — given
|
|
282
|
-
* the same render-group list, height cache, scroll state, and viewport size,
|
|
283
|
-
* the result is deterministic and matches the copy-hit registry. Exported so
|
|
284
|
-
* tests can verify the span map without mounting the full component.
|
|
285
|
-
*/
|
|
286
|
-
export declare function buildMountedCardSpans(opts: {
|
|
287
|
-
renderGroups: readonly RenderGroup[];
|
|
288
|
-
heightCache: EntryHeightCache;
|
|
289
|
-
scrolled: boolean;
|
|
290
|
-
clip: number;
|
|
291
|
-
tailRows: number;
|
|
292
|
-
viewportRows: number;
|
|
293
|
-
showModelReasoning?: boolean | undefined;
|
|
294
|
-
}): MountedCardSpan[];
|
|
295
|
-
/**
|
|
296
|
-
* Find the card whose viewport row range contains `row`. Pure.
|
|
297
|
-
* Returns null when the row is in a blank gap or outside the viewport.
|
|
298
|
-
*/
|
|
299
|
-
export declare function selectionHitAt(row: number, spans: readonly MountedCardSpan[]): {
|
|
300
|
-
entryId: number;
|
|
301
|
-
entryIds?: readonly number[];
|
|
302
|
-
} | null;
|
|
303
|
-
/**
|
|
304
|
-
* Build the clipboard payload for a selection by slicing into each affected
|
|
305
|
-
* entry's full renderable text. The v1 contract is line-then-column on the
|
|
306
|
-
* entry's source text: each slice exposes `startRow`/`endRow` and
|
|
307
|
-
* `startCol`/`endCol` in card-local coordinates; we split the entry's
|
|
308
|
-
* text on `\n`, keep only the rows inside the row range, and within those
|
|
309
|
-
* rows apply the column range. The matrix matches what the source line
|
|
310
|
-
* index would be when no wrapping occurs — i.e. one card row maps to one
|
|
311
|
-
* source line. Wrap-geometry translation is intentionally absent in v1
|
|
312
|
-
* because the layout store does not yet expose per-card-row wrap segments;
|
|
313
|
-
* it returns when those segments exist and a v1.1 test demands it.
|
|
314
|
-
*
|
|
315
|
-
* `toolGroupsByHeadId` lets a multi-member tool-group expand: when the
|
|
316
|
-
* head id appears with `entryIds.length > 1`, the assembler copies via
|
|
317
|
-
* `copyableTextForEntries` (raw ordered JSON of every member, matching
|
|
318
|
-
* the existing copy-icon contract). A single-entry head falls through
|
|
319
|
-
* to `copyableTextForEntry`.
|
|
320
|
-
*
|
|
321
|
-
* Multi-entry selections are joined with `\n---\n` so the user can see
|
|
322
|
-
* where one card ends and the next begins. Empty selections and
|
|
323
|
-
* selections that resolve to no text return `""` so the caller can fall
|
|
324
|
-
* through silently.
|
|
325
|
-
*/
|
|
326
|
-
export declare function assembleSelectionText(opts: {
|
|
327
|
-
slices: readonly SelectionSlice[];
|
|
328
|
-
entriesById: ReadonlyMap<number, HistoryEntry>;
|
|
329
|
-
/**
|
|
330
|
-
* For each tool-group head id present in `slices`, the ordered member list.
|
|
331
|
-
* When a head has a multi-member group, the assembler slices into the
|
|
332
|
-
* group's combined text via `copyableTextForEntries`. A single-entry
|
|
333
|
-
* head falls through to `copyableTextForEntry`.
|
|
334
|
-
*/
|
|
335
|
-
toolGroupsByHeadId?: ReadonlyMap<number, readonly number[]> | undefined;
|
|
336
|
-
}): string;
|
|
2
|
+
import { type HistoryEntry } from './history.js';
|
|
3
|
+
export type { HistoryScrollController, ScrollableHistoryProps, } from './history/scroll-controller-types.js';
|
|
4
|
+
export { type CopyHit, LIVE_TOOL_STREAM_COPY_ID, SELECTION_COPY_ID, findCopyHit, resolveCopyPayload, copyRegistryVisibleClip, liveToolStreamCopyHit, } from './history/copy-geometry.js';
|
|
5
|
+
export { type SelectionRect, type SelectionSlice, normalizeSelection, isOutOfBand, selectionToSlices, assembleSelectionText, } from './history/selection-helpers.js';
|
|
6
|
+
export { type MountedCardSpan, scrollbarThumb, scrollOffsetForTrackRow, buildMountedCardSpans, selectionHitAt, } from './history/scrollbar-geometry.js';
|
|
7
|
+
export { Scrollbar } from './history/scrollbar-rail.js';
|
|
8
|
+
import type { ScrollableHistoryProps } from './history/scroll-controller-types.js';
|
|
337
9
|
/**
|
|
338
10
|
* Bounded history viewport with stable-anchor virtual scrolling.
|
|
339
11
|
*
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { SettingsPickerPatch } from '../settings-contracts.js';
|
|
1
2
|
/** Selectable presets for the auto-proceed delay, so the field is fully
|
|
2
3
|
* keyboard-cyclable (←/→) instead of needing typed numeric input. */
|
|
3
4
|
export declare const DELAY_PRESETS_MS: number[];
|
|
@@ -81,8 +82,13 @@ export type AnimationStyleChoice = (typeof ANIMATION_STYLE_CHOICES)[number];
|
|
|
81
82
|
/** Human-readable label for an animation style choice (including cycle). */
|
|
82
83
|
export declare function formatAnimationStyle(style: AnimationStyleChoice): string;
|
|
83
84
|
export declare const MODE_DESC: Record<SettingsMode, string>;
|
|
84
|
-
/** Total number of settings rows (used for wrap-around navigation).
|
|
85
|
-
|
|
85
|
+
/** Total number of settings rows (used for wrap-around navigation).
|
|
86
|
+
* Indices 0–44 are the legacy auto-rebuilt Settings surface; 45..44+PANEL_IDS.length
|
|
87
|
+
* are the per-panel position rows (one per PanelId in PANEL_IDS order)
|
|
88
|
+
* added when the showAgentSwarmPanel tri-state was generalized into the
|
|
89
|
+
* per-panel PanelPositionMap. Derived from PANEL_IDS.length so adding
|
|
90
|
+
* a new panel id automatically extends the surface. */
|
|
91
|
+
export declare const SETTINGS_FIELD_COUNT: number;
|
|
86
92
|
/**
|
|
87
93
|
* Field index of the "Thinking word" row. The reducer's per-field switch and
|
|
88
94
|
* the app.tsx key handler both branch on this, so it lives next to the row
|
|
@@ -134,57 +140,12 @@ export declare const THINKING_WORD_PRESETS: readonly ['thinking', 'random', 'wor
|
|
|
134
140
|
export declare const CONFIG_SCOPES: readonly ['global', 'project'];
|
|
135
141
|
export type ConfigScope = (typeof CONFIG_SCOPES)[number];
|
|
136
142
|
/**
|
|
137
|
-
*
|
|
138
|
-
*
|
|
139
|
-
*
|
|
143
|
+
* Re-export of the canonical `SettingsPickerPatch` from `settings-contracts.ts`.
|
|
144
|
+
* That module is the single source of truth so that `Action['patch']` (in
|
|
145
|
+
* app-action-type.ts) and the helpers below stay in lock-step. Adding a new
|
|
146
|
+
* key here requires adding it there too — keep them in sync.
|
|
140
147
|
*/
|
|
141
|
-
export type SettingsPickerPatch
|
|
142
|
-
mode: SettingsMode;
|
|
143
|
-
delayMs: number;
|
|
144
|
-
titleAnimation: boolean;
|
|
145
|
-
yolo: boolean;
|
|
146
|
-
fleetChat: FleetChatVerbosityTui;
|
|
147
|
-
chime: boolean;
|
|
148
|
-
confirmExit: boolean;
|
|
149
|
-
nextPrediction: boolean;
|
|
150
|
-
featureMcp: boolean;
|
|
151
|
-
featurePlugins: boolean;
|
|
152
|
-
featureMemory: boolean;
|
|
153
|
-
featureSkills: boolean;
|
|
154
|
-
featureModelsRegistry: boolean;
|
|
155
|
-
tokenSavingTier: TokenSavingTierTui;
|
|
156
|
-
allowOutsideProjectRoot: boolean;
|
|
157
|
-
contextAutoCompact: boolean;
|
|
158
|
-
contextStrategy: CompactorStrategy;
|
|
159
|
-
contextMode: ContextMode;
|
|
160
|
-
maxConcurrent: number;
|
|
161
|
-
logLevel: LogLevel;
|
|
162
|
-
auditLevel: AuditLevel;
|
|
163
|
-
indexOnStart: boolean;
|
|
164
|
-
multiDiffSummaryThreshold: number;
|
|
165
|
-
maxIterations: number;
|
|
166
|
-
autoProceedMaxIterations: number;
|
|
167
|
-
enhanceDelayMs: number;
|
|
168
|
-
preRefineSeconds: number;
|
|
169
|
-
enhanceEnabled: boolean;
|
|
170
|
-
enhanceLanguage: EnhanceLanguage;
|
|
171
|
-
debugStream: boolean;
|
|
172
|
-
statuslineMode: StatuslineMode;
|
|
173
|
-
reasoningMode: ReasoningMode;
|
|
174
|
-
reasoningEffort: ReasoningEffort;
|
|
175
|
-
reasoningPreserve: boolean;
|
|
176
|
-
thinkingWord: string;
|
|
177
|
-
cacheTtl: CacheTtl;
|
|
178
|
-
configScope: ConfigScope;
|
|
179
|
-
animationStyle: AnimationStyleChoice;
|
|
180
|
-
breakerEnabled: boolean;
|
|
181
|
-
breakerAutoKillResetMs: number;
|
|
182
|
-
showModelReasoning: boolean;
|
|
183
|
-
showAgentSwarmPanel: boolean;
|
|
184
|
-
readSymbols: boolean;
|
|
185
|
-
showSageMemoryInject: boolean;
|
|
186
|
-
sageMemoryInjectThreshold: number;
|
|
187
|
-
}>;
|
|
148
|
+
export type { SettingsPickerPatch };
|
|
188
149
|
/**
|
|
189
150
|
* Human-readable labels for all settings fields (0–SETTINGS_FIELD_COUNT-1),
|
|
190
151
|
* in picker row order. Used by `resolveSettingsFieldValue` for confirmation
|
|
@@ -64,17 +64,22 @@ export interface SettingsPickerProps {
|
|
|
64
64
|
/** Show the "Model Reasoning" blocks in chat history. Default: true. */
|
|
65
65
|
showModelReasoning: boolean;
|
|
66
66
|
/**
|
|
67
|
-
* Show the
|
|
68
|
-
*
|
|
69
|
-
*
|
|
67
|
+
* Show the Mission Queue section (todo items) in the right sidebar. The
|
|
68
|
+
* lower-region FleetPanel is always visible when there is fleet activity;
|
|
69
|
+
* this toggle controls only the sidebar mission queue. Default: 'bottom'.
|
|
70
70
|
*/
|
|
71
|
-
showAgentSwarmPanel:
|
|
71
|
+
showAgentSwarmPanel: import('../app-settings-type.js').AgentSwarmPanelMode;
|
|
72
72
|
/** Show SAGE Memory Inject blocks in tool results. Default: false. */
|
|
73
73
|
showSageMemoryInject: boolean;
|
|
74
74
|
/** Minimum relation strength for SAGE memory injection. Default: 0.85. */
|
|
75
75
|
sageMemoryInjectThreshold: number;
|
|
76
76
|
/** When true, read tool includes codebase-index symbols alongside file content. */
|
|
77
77
|
readSymbols: boolean;
|
|
78
|
+
/**
|
|
79
|
+
* Per-panel placement map (F-key bottom vs right sidebar). One picker row
|
|
80
|
+
* per PanelId in PANEL_IDS order; each row cycles 'bottom' ↔ 'sidebar'.
|
|
81
|
+
*/
|
|
82
|
+
panelPositions: import('../ui-contracts.js').PanelPositionMap;
|
|
78
83
|
/** Raw SSE stream debugging toggle — hex-dump every byte received from providers. */
|
|
79
84
|
debugStream: boolean;
|
|
80
85
|
/** Statusline density: minimum single-line or detailed multi-line. */
|
|
@@ -97,5 +102,5 @@ export interface SettingsPickerProps {
|
|
|
97
102
|
filter?: string | undefined;
|
|
98
103
|
hint?: string | undefined;
|
|
99
104
|
}
|
|
100
|
-
export declare function SettingsPicker({ field, filter, mode, delayMs, titleAnimation, yolo, fleetChat, chime, confirmExit, nextPrediction, featureMcp, featurePlugins, featureMemory, featureSkills, featureModelsRegistry, tokenSavingTier, allowOutsideProjectRoot, maxIterations, autoProceedMaxIterations, enhanceDelayMs, enhanceEnabled, enhanceLanguage, preRefineSeconds, indexOnStart, multiDiffSummaryThreshold, thinkingWord, thinkingWordEditing, thinkingWordDraft, reasoningMode, reasoningEffort, reasoningPreserve, cacheTtl, contextAutoCompact, contextStrategy, contextMode, maxConcurrent, logLevel, auditLevel, debugStream, statuslineMode, configScope, profileConfigPath, animationStyle, breakerEnabled, breakerAutoKillResetMs, showModelReasoning, showAgentSwarmPanel, showSageMemoryInject, sageMemoryInjectThreshold, readSymbols, hint, }: SettingsPickerProps): React.ReactElement;
|
|
105
|
+
export declare function SettingsPicker({ field, filter, mode, delayMs, titleAnimation, yolo, fleetChat, chime, confirmExit, nextPrediction, featureMcp, featurePlugins, featureMemory, featureSkills, featureModelsRegistry, tokenSavingTier, allowOutsideProjectRoot, maxIterations, autoProceedMaxIterations, enhanceDelayMs, enhanceEnabled, enhanceLanguage, preRefineSeconds, indexOnStart, multiDiffSummaryThreshold, thinkingWord, thinkingWordEditing, thinkingWordDraft, reasoningMode, reasoningEffort, reasoningPreserve, cacheTtl, contextAutoCompact, contextStrategy, contextMode, maxConcurrent, logLevel, auditLevel, debugStream, statuslineMode, configScope, profileConfigPath, animationStyle, breakerEnabled, breakerAutoKillResetMs, showModelReasoning, showAgentSwarmPanel, showSageMemoryInject, sageMemoryInjectThreshold, readSymbols, panelPositions, hint, }: SettingsPickerProps): React.ReactElement;
|
|
101
106
|
//# sourceMappingURL=settings-picker.d.ts.map
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { ResumeSessionEntry } from '../app-state.js';
|
|
2
|
+
import type { FleetEntry } from '../app-state-fleet.js';
|
|
3
|
+
import type { TodoItem } from '@wrongstack/core/agent';
|
|
4
|
+
import type React from 'react';
|
|
5
|
+
import type { LiveSessionEntry } from './sessions-panel.js';
|
|
6
|
+
export interface SidebarContentProps {
|
|
7
|
+
/** Live context window data from useStatusbarViewModel. */
|
|
8
|
+
contextWindow: {
|
|
9
|
+
used: number;
|
|
10
|
+
max: number;
|
|
11
|
+
} | undefined;
|
|
12
|
+
/** Fleet entries (leader + subagents) from useStatusbarViewModel. */
|
|
13
|
+
entries: Record<string, FleetEntry>;
|
|
14
|
+
/** Fleet counts summary. */
|
|
15
|
+
fleetCounts: {
|
|
16
|
+
running: number;
|
|
17
|
+
idle: number;
|
|
18
|
+
pending: number;
|
|
19
|
+
completed: number;
|
|
20
|
+
} | undefined;
|
|
21
|
+
/** Current provider label for display. */
|
|
22
|
+
provider?: string | undefined;
|
|
23
|
+
/** Current model label for display. */
|
|
24
|
+
model?: string | undefined;
|
|
25
|
+
/** Actual sidebar width in columns (including border+padding chrome).
|
|
26
|
+
* Used to size the content area and truncate text appropriately. */
|
|
27
|
+
width: number;
|
|
28
|
+
/** Vertical scroll offset — number of rows scrolled from the top. */
|
|
29
|
+
scrollOffset?: number | undefined;
|
|
30
|
+
/** When true, the sidebar has keyboard focus (↑↓ scroll). */
|
|
31
|
+
focused?: boolean | undefined;
|
|
32
|
+
/** Live leader todo board — rendered as a compact mission queue. */
|
|
33
|
+
todos?: readonly TodoItem[] | undefined;
|
|
34
|
+
/** When true, show the agent-swarm + mission-queue section. Gated by the
|
|
35
|
+
* effective agent-swarm panel mode being 'sidebar' (see app-view.tsx). */
|
|
36
|
+
showSwarmSection?: boolean | undefined;
|
|
37
|
+
/** Live sessions from the SessionRegistry — same data as the F10 panel.
|
|
38
|
+
* Shown as compact "live" rows with project name + status + agent count. */
|
|
39
|
+
liveSessions?: readonly LiveSessionEntry[] | undefined;
|
|
40
|
+
/** Recent stored sessions for the `/resume` picker. Shown as compact rows
|
|
41
|
+
* with title + last-activity + outcome badge. */
|
|
42
|
+
resumeSessions?: readonly ResumeSessionEntry[] | undefined;
|
|
43
|
+
/** The current session ID — used to highlight the active session row. */
|
|
44
|
+
currentSessionId?: string | undefined;
|
|
45
|
+
}
|
|
46
|
+
export declare function SidebarContent({ contextWindow, entries, fleetCounts, provider, model, width, scrollOffset, focused, todos, showSwarmSection, liveSessions, resumeSessions, currentSessionId, }: SidebarContentProps): React.ReactElement;
|
|
47
|
+
//# sourceMappingURL=sidebar-content.d.ts.map
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import type React from 'react';
|
|
2
|
+
export interface SidebarPanelFrameProps {
|
|
3
|
+
/** Accent color for border + title (mirrors `theme.monitor.*` on bottom panels). */
|
|
4
|
+
accent: string;
|
|
5
|
+
/** Header glyph, e.g. `glyphs.fleet` or `glyphs.sessions`. */
|
|
6
|
+
icon: string;
|
|
7
|
+
/** Uppercase title (e.g. "FLEET", "PLAN", "AGENTS"). */
|
|
8
|
+
title: string;
|
|
9
|
+
/**
|
|
10
|
+
* Width allocated to this panel frame, including the frame's own border and
|
|
11
|
+
* padding. When nested in RightSidebar, pass that shell's content width —
|
|
12
|
+
* not the outer sidebar width — so both chrome layers remain in bounds.
|
|
13
|
+
*/
|
|
14
|
+
width: number;
|
|
15
|
+
/** Optional quiet subtitle hidden on narrow terminals. */
|
|
16
|
+
kicker?: string | undefined;
|
|
17
|
+
/** Optional right-aligned header content (status badge, counts, etc.). */
|
|
18
|
+
right?: React.ReactNode | undefined;
|
|
19
|
+
/** Footer content (key hints, footer note). Renders under the body. */
|
|
20
|
+
footer?: React.ReactNode | undefined;
|
|
21
|
+
/** Body content. Renders inside the scrollable region. */
|
|
22
|
+
children?: React.ReactNode | undefined;
|
|
23
|
+
/**
|
|
24
|
+
* Body scroll offset (in rows). When the body exceeds the visible window,
|
|
25
|
+
* older rows are clipped from the top and a "↑ N earlier" marker is shown.
|
|
26
|
+
* Pass `0` when no scrolling is needed (single panel fits in viewport).
|
|
27
|
+
*/
|
|
28
|
+
bodyScrollOffset?: number | undefined;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Truncate a string to fit within `max` display columns, adding an ellipsis.
|
|
32
|
+
* Exported so sibling sidebar panel files can use the same string-fitting
|
|
33
|
+
* helper without pulling in sidebar-content.tsx's full implementation.
|
|
34
|
+
*/
|
|
35
|
+
export declare function trunc(s: string, max: number): string;
|
|
36
|
+
/**
|
|
37
|
+
* A section header: colored glyph + bold uppercase label, a dotted leader
|
|
38
|
+
* filling the remaining width, and an optional right-aligned badge. Always
|
|
39
|
+
* renders exactly one row of exactly `innerWidth` columns — the badge is
|
|
40
|
+
* dropped gracefully when there is no room (narrow terminals).
|
|
41
|
+
*/
|
|
42
|
+
export declare function SidebarSectionHeader({ glyph, label, color, badge, badgeColor, innerWidth, }: {
|
|
43
|
+
glyph: string;
|
|
44
|
+
label: string;
|
|
45
|
+
color: string;
|
|
46
|
+
badge?: string | undefined;
|
|
47
|
+
badgeColor?: string | undefined;
|
|
48
|
+
innerWidth: number;
|
|
49
|
+
}): React.ReactElement;
|
|
50
|
+
/** A raised "card" wrapper. On truecolor terminals it gets a subtle lifted
|
|
51
|
+
* surface so sections read as stacked panels; otherwise it is a plain box. */
|
|
52
|
+
export declare function SidebarPanelCard({ innerWidth, marginBottom, children, }: {
|
|
53
|
+
innerWidth: number;
|
|
54
|
+
marginBottom?: number | undefined;
|
|
55
|
+
children: React.ReactNode;
|
|
56
|
+
}): React.ReactElement;
|
|
57
|
+
/**
|
|
58
|
+
* SidebarPanelFrame — the standard chrome wrapper used by every sidebar
|
|
59
|
+
* panel variant. Renders a round border in the panel's accent color with a
|
|
60
|
+
* glyph + title header, optional kicker + right-aligned badge, a scrollable
|
|
61
|
+
* body region, and an optional footer.
|
|
62
|
+
*
|
|
63
|
+
* Scrolling: the body itself doesn't scroll. The host (app-view / SidebarContent)
|
|
64
|
+
* computes scroll offsets from the focused panel index. We accept a
|
|
65
|
+
* `bodyScrollOffset` and a fixed body height so panels that exceed their
|
|
66
|
+
* viewport can be paged with Shift+Tab + ↑↓ while focused. When the body
|
|
67
|
+
* scrolls, a "↑ N earlier" indicator is shown at the top of the body region.
|
|
68
|
+
*/
|
|
69
|
+
export declare function SidebarPanelFrame({ accent, icon, title, width, kicker, right, footer, children, bodyScrollOffset, }: SidebarPanelFrameProps): React.ReactElement;
|
|
70
|
+
/**
|
|
71
|
+
* useSidebarPanelSize — returns a sensible default width / height for a
|
|
72
|
+
* sidebar panel given the terminal dimensions. Width mirrors
|
|
73
|
+
* `computeSidebarWidth` from `sidebar.tsx`; height is the full terminal
|
|
74
|
+
* minus a small safety margin for the focus indicator row.
|
|
75
|
+
*/
|
|
76
|
+
export declare function useSidebarPanelSize(): {
|
|
77
|
+
width: number;
|
|
78
|
+
height: number;
|
|
79
|
+
};
|
|
80
|
+
//# sourceMappingURL=sidebar-panel-frame.d.ts.map
|