@wrongstack/tui 1.0.19 → 1.0.26

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.
Files changed (159) hide show
  1. package/dist/app-action-type.d.ts +85 -1
  2. package/dist/app-key-handler.d.ts +1 -1
  3. package/dist/app-panel-state.d.ts +561 -0
  4. package/dist/app-props.d.ts +21 -1
  5. package/dist/app-reducer.d.ts +1 -1
  6. package/dist/app-state-core-types.d.ts +13 -0
  7. package/dist/app-state.d.ts +8 -534
  8. package/dist/app-status-region.d.ts +2 -1
  9. package/dist/app-ui-state.d.ts +2 -0
  10. package/dist/app-view-contract.d.ts +1 -1
  11. package/dist/app-view-pickers.d.ts +2 -1
  12. package/dist/app-view-state.d.ts +2 -0
  13. package/dist/app.d.ts +2 -2
  14. package/dist/auth-panel-model.d.ts +1 -0
  15. package/dist/background-strip-model.d.ts +65 -0
  16. package/dist/brain-panel-model.d.ts +7 -7
  17. package/dist/chat-search-slash.d.ts +15 -0
  18. package/dist/clipboard.d.ts +14 -1
  19. package/dist/components/agent-monitor-presentation.d.ts +61 -0
  20. package/dist/components/agents-monitor.d.ts +3 -49
  21. package/dist/components/audit-panel.d.ts +2 -1
  22. package/dist/components/auth-panel.d.ts +3 -1
  23. package/dist/components/background-strip.d.ts +20 -0
  24. package/dist/components/brain-panel.d.ts +3 -1
  25. package/dist/components/chat-search-bar.d.ts +19 -0
  26. package/dist/components/checkpoint-timeline.d.ts +7 -3
  27. package/dist/components/confirm-prompt.d.ts +6 -7
  28. package/dist/components/connections-panel.d.ts +2 -1
  29. package/dist/components/context-panel-sections.d.ts +53 -0
  30. package/dist/components/context-panel-types.d.ts +66 -0
  31. package/dist/components/context-panel.d.ts +2 -66
  32. package/dist/components/exit-confirm-panel.d.ts +2 -0
  33. package/dist/components/file-picker.d.ts +2 -1
  34. package/dist/components/help-panel.d.ts +5 -3
  35. package/dist/components/history/code-block.d.ts +2 -136
  36. package/dist/components/history/diff-model.d.ts +143 -0
  37. package/dist/components/history/scroll-controller-types.d.ts +11 -0
  38. package/dist/components/history/scrollbar-rail.d.ts +14 -2
  39. package/dist/components/history/use-history-controller.d.ts +5 -0
  40. package/dist/components/history/utils.d.ts +3 -9
  41. package/dist/components/history/visual-tool-output.d.ts +8 -0
  42. package/dist/components/input.d.ts +1 -1
  43. package/dist/components/kanban-panel-presentation.d.ts +114 -0
  44. package/dist/components/kanban-panel.d.ts +2 -47
  45. package/dist/components/mailbox-panel.d.ts +2 -1
  46. package/dist/components/mcp-picker.d.ts +3 -1
  47. package/dist/components/mode-picker.d.ts +3 -1
  48. package/dist/components/model-picker.d.ts +1 -1
  49. package/dist/components/monitor-shell.d.ts +19 -4
  50. package/dist/components/phase-monitor.d.ts +3 -1
  51. package/dist/components/plugin-picker.d.ts +3 -1
  52. package/dist/components/powerline-rail.d.ts +6 -3
  53. package/dist/components/prompt-picker-model.d.ts +16 -0
  54. package/dist/components/prompt-picker.d.ts +2 -16
  55. package/dist/components/provider-colors.d.ts +2 -12
  56. package/dist/components/refine-countdown-panel.d.ts +4 -3
  57. package/dist/components/resource-menu-model.d.ts +3 -0
  58. package/dist/components/resource-menu.d.ts +3 -3
  59. package/dist/components/scrollable-history.d.ts +1 -1
  60. package/dist/components/send-mode-model.d.ts +44 -0
  61. package/dist/components/send-mode-picker.d.ts +2 -43
  62. package/dist/components/settings-picker-row-list.d.ts +2 -1
  63. package/dist/components/settings-picker.d.ts +3 -1
  64. package/dist/components/shadow-panel.d.ts +2 -1
  65. package/dist/components/sidebar-content.d.ts +1 -47
  66. package/dist/components/sidebar-ipc-icons.d.ts +9 -0
  67. package/dist/components/sidebar-panel-agents.d.ts +10 -0
  68. package/dist/components/sidebar-panel-connections.d.ts +11 -0
  69. package/dist/components/sidebar-panel-coordinator.d.ts +11 -0
  70. package/dist/components/sidebar-panel-fleet.d.ts +16 -0
  71. package/dist/components/sidebar-panel-project.d.ts +12 -0
  72. package/dist/components/sidebar-panel-worktree.d.ts +10 -0
  73. package/dist/components/sidebar-panel-wrong-proxy.d.ts +25 -0
  74. package/dist/components/sidebar-panels-workspace.d.ts +10 -79
  75. package/dist/components/sidebar-presentation.d.ts +98 -0
  76. package/dist/components/sidebar.d.ts +3 -1
  77. package/dist/components/skill-picker.d.ts +2 -1
  78. package/dist/components/slash-confirm-panel.d.ts +2 -0
  79. package/dist/components/slash-menu.d.ts +2 -1
  80. package/dist/components/slash-modal-frame.d.ts +9 -0
  81. package/dist/components/status-bar-rails-async.d.ts +2 -2
  82. package/dist/components/status-bar-types.d.ts +6 -0
  83. package/dist/components/status-bar.d.ts +1 -1
  84. package/dist/components/statusline-picker-model.d.ts +45 -0
  85. package/dist/components/statusline-picker.d.ts +2 -41
  86. package/dist/components/tools-picker.d.ts +3 -1
  87. package/dist/components/user-input-prompt.d.ts +4 -2
  88. package/dist/connection-actions.d.ts +20 -0
  89. package/dist/connections-health.d.ts +8 -1
  90. package/dist/esc-close-panels.d.ts +0 -1
  91. package/dist/f-key-panels.d.ts +4 -0
  92. package/dist/hooks/fork-at-checkpoint.d.ts +25 -0
  93. package/dist/hooks/use-active-theme.d.ts +2 -1
  94. package/dist/hooks/use-app-execution-pipeline.d.ts +1 -1
  95. package/dist/hooks/use-app-panels-state.d.ts +1 -1
  96. package/dist/hooks/use-app-picker-keys.d.ts +5 -2
  97. package/dist/hooks/use-chip-staleness-guard.d.ts +6 -0
  98. package/dist/hooks/use-core-tui-commands.d.ts +7 -2
  99. package/dist/hooks/use-file-search.d.ts +10 -0
  100. package/dist/hooks/use-fleet-generation-gate.d.ts +4 -3
  101. package/dist/hooks/use-panel-controllers.d.ts +1 -1
  102. package/dist/hooks/use-picker-keys-brain-statusline.d.ts +4 -0
  103. package/dist/hooks/use-picker-keys-types.d.ts +1 -0
  104. package/dist/hooks/use-provider-warmup.d.ts +9 -0
  105. package/dist/hooks/use-queue-manager.d.ts +11 -1
  106. package/dist/hooks/use-session-rewind.d.ts +8 -1
  107. package/dist/hooks/use-shadow-panel.d.ts +1 -1
  108. package/dist/hooks/use-sidebar-panel-data.d.ts +7 -5
  109. package/dist/hooks/use-skill-mention-picker.d.ts +6 -0
  110. package/dist/hooks/use-slash-picker.d.ts +1 -1
  111. package/dist/hooks/use-stable-key-handler.d.ts +8 -1
  112. package/dist/hooks/use-status-sync-interval.d.ts +3 -2
  113. package/dist/hooks/use-statusbar-view-model.d.ts +2 -2
  114. package/dist/hooks/use-tui-environment-state.d.ts +3 -0
  115. package/dist/hooks/use-tui-event-bridge.d.ts +12 -0
  116. package/dist/hooks/use-windowed-picker.d.ts +3 -4
  117. package/dist/index.js +29522 -25452
  118. package/dist/ink.d.ts +5 -5
  119. package/dist/input-graphemes.d.ts +4 -0
  120. package/dist/input-key-router.d.ts +2 -0
  121. package/dist/input-tokens.d.ts +10 -0
  122. package/dist/input-validation/action-types.d.ts +1 -1
  123. package/dist/input-validation/limits.d.ts +2 -0
  124. package/dist/input-validation-coordination.d.ts +9 -0
  125. package/dist/input-validation-display.d.ts +9 -0
  126. package/dist/input-validation.d.ts +0 -52
  127. package/dist/kanban-arguments.d.ts +48 -0
  128. package/dist/kanban-command-types.d.ts +53 -0
  129. package/dist/kanban-reports.d.ts +42 -0
  130. package/dist/kanban-slash.d.ts +4 -125
  131. package/dist/key-routes/key-route-background-strip.d.ts +14 -0
  132. package/dist/key-routes/key-route-chat-search.d.ts +24 -0
  133. package/dist/key-routes/key-route-overlay.d.ts +2 -2
  134. package/dist/layout-store.d.ts +2 -2
  135. package/dist/memory-slash-render.d.ts +1 -1
  136. package/dist/message-checkpoint.d.ts +19 -0
  137. package/dist/motion.d.ts +16 -0
  138. package/dist/on-panel-open.d.ts +1 -1
  139. package/dist/picker-text-input.d.ts +4 -0
  140. package/dist/reducers/chat-search.d.ts +11 -0
  141. package/dist/reducers/composer-action-types.d.ts +6 -0
  142. package/dist/reducers/composer-pickers.d.ts +4 -0
  143. package/dist/reducers/composer.d.ts +1 -5
  144. package/dist/reducers/message-jump.d.ts +16 -0
  145. package/dist/reducers/panel-pickers.d.ts +1 -1
  146. package/dist/reducers/workspace-panels.d.ts +1 -1
  147. package/dist/resume-session-tree.d.ts +8 -0
  148. package/dist/rewind-prompt.d.ts +24 -0
  149. package/dist/run-tui-options.d.ts +24 -5
  150. package/dist/scroll-anchor.d.ts +6 -0
  151. package/dist/statusline-palette.d.ts +4 -0
  152. package/dist/submit-controller.d.ts +1 -1
  153. package/dist/submit-slash-command.d.ts +67 -0
  154. package/dist/theme-utils.d.ts +1 -1
  155. package/dist/transcript-search.d.ts +38 -0
  156. package/dist/ui-contracts.d.ts +2 -1
  157. package/dist/use-app-controller.d.ts +157 -0
  158. package/dist/use-controller-key-pipeline.d.ts +217 -0
  159. package/package.json +7 -7
@@ -1,73 +1,9 @@
1
- import type { ContextBreakdown } from '@wrongstack/core/utils';
2
1
  import type React from 'react';
3
- import type { MemoryContextMonitorState } from '../memory-context-monitor.js';
4
- export interface ContextPanelData {
5
- ctxPct: number | undefined;
6
- ctxTokens: number | undefined;
7
- ctxMaxTokens: number | undefined;
8
- provider: string;
9
- model: string;
10
- mode: string;
11
- uptime: string;
12
- /**
13
- * Cumulative prompt-cache stats from the per-session TokenCounter.
14
- * Surfaced in the panel so `/context` answers "how much of my spend
15
- * is hitting the cache" without asking the user to chase the CLI
16
- * `/context cache` subcommand.
17
- *
18
- * `savedUsd` is the gross read-discount USD figure computed by the
19
- * counter (cache-read tokens × (input price − cache-read price)).
20
- * `cacheWrite5m` / `cacheWrite1h` are present when the upstream exposed
21
- * an Anthropic-style TTL split (Anthropic family, including MiniMax
22
- * routed through the Anthropic Messages surface); OpenAI-family
23
- * gateways emit only the aggregate and leave them undefined.
24
- */
25
- cacheStats?: {
26
- readTokens: number;
27
- writeTokens: number;
28
- cacheWrite5m?: number | undefined;
29
- cacheWrite1h?: number | undefined;
30
- hitRatio: number;
31
- savedUsd: number;
32
- } | undefined;
33
- /**
34
- * How far the cached prefix reaches through the live request, in
35
- * tokens. Drawn on the per-request coverage meter so users see the
36
- * exact extent of the cache, not just a percentage.
37
- */
38
- cacheCoverageTokens?: number | undefined;
39
- /** Session cache telemetry split by provider, including fallback/model switches. */
40
- providerCacheStats?: Array<{
41
- provider: string;
42
- input: number;
43
- cacheRead: number;
44
- cacheWrite: number;
45
- cacheWrite5m?: number | undefined;
46
- cacheWrite1h?: number | undefined;
47
- hitRatio: number;
48
- }> | undefined;
49
- /**
50
- * Real, measured per-category token accounting for the live request. When
51
- * present the Composition tab shows honest numbers; when absent (no request
52
- * has been assembled yet) the tab shows an empty state instead of fabricated
53
- * percentages.
54
- */
55
- breakdown: ContextBreakdown | undefined;
56
- fleetEntries: Array<{
57
- name: string;
58
- status: string;
59
- currentTool: string | undefined;
60
- ctxPct: number | undefined;
61
- }>;
62
- leaderIterations: number;
63
- leaderToolCalls: number;
64
- leaderStatus: string;
65
- memoryContext: MemoryContextMonitorState;
66
- }
2
+ import type { ContextPanelData } from './context-panel-types.js';
67
3
  interface ContextPanelProps {
68
4
  data: ContextPanelData;
69
5
  onClose: () => void;
70
6
  }
71
7
  export declare function ContextPanel({ data, onClose }: ContextPanelProps): React.ReactElement;
72
- export {};
8
+ export type { ContextPanelData } from './context-panel-types.js';
73
9
  //# sourceMappingURL=context-panel.d.ts.map
@@ -5,6 +5,8 @@ interface ExitConfirmPanelProps {
5
5
  backgroundCount?: number | undefined;
6
6
  }
7
7
  export interface ExitConfirmationKey {
8
+ ctrl?: boolean | undefined;
9
+ meta?: boolean | undefined;
8
10
  escape?: boolean | undefined;
9
11
  return?: boolean | undefined;
10
12
  }
@@ -3,6 +3,7 @@ export interface FilePickerProps {
3
3
  query: string;
4
4
  matches: string[];
5
5
  selected: number;
6
+ maxRows?: number | undefined;
6
7
  }
7
- export declare function FilePicker({ query, matches, selected }: FilePickerProps): React.ReactElement;
8
+ export declare function FilePicker({ query, matches, selected, maxRows, }: FilePickerProps): React.ReactElement;
8
9
  //# sourceMappingURL=file-picker.d.ts.map
@@ -5,13 +5,15 @@ export interface HelpEntry {
5
5
  category: string;
6
6
  aliases?: string[] | undefined;
7
7
  argsHint?: string | undefined;
8
+ help?: string | undefined;
8
9
  }
9
- interface HelpPanelProps {
10
+ export interface HelpPanelProps {
10
11
  entries: HelpEntry[];
11
12
  filter: string;
12
13
  selected: number;
13
14
  hint?: string | undefined;
15
+ maxRows?: number | undefined;
16
+ detailScroll?: number | undefined;
14
17
  }
15
- export declare function HelpPanel({ entries, filter, selected, hint }: HelpPanelProps): React.ReactElement;
16
- export {};
18
+ export declare function HelpPanel({ entries, filter, selected, hint, maxRows, detailScroll, }: HelpPanelProps): React.ReactElement;
17
19
  //# sourceMappingURL=help-panel.d.ts.map
@@ -1,96 +1,14 @@
1
- import { type DiffLineRow, type DiffPreview } from '@wrongstack/tools/tool-diff';
1
+ import type { DiffLineRow, DiffPreview } from '@wrongstack/tools/tool-diff';
2
2
  import type React from 'react';
3
3
  import { type Lang, type Token } from '../../highlight.js';
4
4
  export type { DiffLineKind, DiffLineRow, DiffPreview } from '@wrongstack/tools/tool-diff';
5
- /**
6
- * A parsed diff paired with the file it belongs to. Used when a tool
7
- * produces diffs for several files at once (currently `replace`); each
8
- * `DiffFilePreview` renders as one labeled `DiffFileBlock`.
9
- */
10
- export interface DiffFilePreview {
11
- path: string;
12
- preview: DiffPreview;
13
- }
14
- interface OmittedDiffSummary {
15
- fileCount: number;
16
- added: number;
17
- removed: number;
18
- }
19
- /** Renderable file previews plus aggregate data for files omitted by the cap. */
20
- export type DiffFilePreviews = DiffFilePreview[] & {
21
- omitted?: OmittedDiffSummary | undefined;
22
- };
23
- /**
24
- * Hard ceiling for one file's rendered diff preview. Diff rows are React/Ink
25
- * elements and therefore retained by the active virtual-history window; an
26
- * unbounded preview lets a single generated-file edit defeat virtualization.
27
- * Totals for the whole diff remain available through `added`/`removed`, while
28
- * the footer reports the hidden portion.
29
- */
30
- export declare const DIFF_MAX_LINES = 200;
31
- /** Maximum number of per-file diff blocks retained for one tool entry. */
32
- export declare const MULTI_DIFF_MAX_FILES = 20;
33
- /** Maximum rendered diff rows retained across every file in one tool entry. */
34
- export declare const MULTI_DIFF_MAX_ROWS = 400;
5
+ export * from './diff-model.js';
35
6
  /** Syntax-highlighted, framed code block. */
36
7
  declare function CodeBlockImpl({ code, lang, contentWidth, }: {
37
8
  code: string;
38
9
  lang: Lang;
39
10
  contentWidth: number;
40
11
  }): React.ReactElement;
41
- /**
42
- * Minimum number of files before a summary footer is rendered above the
43
- * per-file blocks. Below this threshold each file's own `… +N -M hidden`
44
- * footer carries enough signal; above it, a single aggregate line keeps
45
- * the screen from being drowned in per-file tail lines.
46
- *
47
- * This is the default when no user-tunable value is supplied. The
48
- * settings picker exposes `MULTI_DIFF_SUMMARY_THRESHOLD_PRESETS` so
49
- * users can raise the cutoff (e.g. for very wide terminals) or lower
50
- * it (e.g. for tiny scrollback), or set it to 0 to suppress the
51
- * summary entirely.
52
- */
53
- export declare const MULTI_DIFF_SUMMARY_THRESHOLD = 5;
54
- /**
55
- * Aggregate stats across a list of per-file diffs — used to print a
56
- * single summary line at the top of a multi-file diff view when there
57
- * are enough files to make the rollup useful.
58
- */
59
- export interface MultiDiffSummary {
60
- fileCount: number;
61
- added: number;
62
- removed: number;
63
- hiddenAdded: number;
64
- hiddenRemoved: number;
65
- /** Number of rendered files whose preview was truncated (has hidden rows).
66
- * Does not include files omitted entirely by the multi-file render ceiling;
67
- * those are tracked separately via {@link omittedFiles}. */
68
- truncatedFiles: number;
69
- /** Files omitted entirely by the multi-file render ceiling. Guaranteed non-negative. */
70
- omittedFiles: number;
71
- }
72
- /**
73
- * Sum the totals of a list of per-file diff previews. Files that were
74
- * parsed but have no rows (e.g. entirely empty after the no-op skip) are
75
- * excluded from the rollup so the summary reflects what the user will
76
- * actually see rendered below.
77
- */
78
- export declare function summarizeMultiFileDiffs(items: DiffFilePreviews): MultiDiffSummary;
79
- /**
80
- * Format a multi-file diff summary as a single dim italic line, suitable
81
- * for rendering above the per-file blocks. Mirrors the per-file footer's
82
- * `… +N -M hidden` shape so a reader who has seen the footer recognises
83
- * the format. Returns `null` when there's nothing useful to surface
84
- * (no files, or below the user's threshold where the per-file footer
85
- * already covers the rollup).
86
- *
87
- * @param threshold User-tunable cutoff. Pass `MULTI_DIFF_SUMMARY_THRESHOLD`
88
- * for the default behaviour, `0` to suppress the summary entirely
89
- * (always returns null), or a positive number to set a custom cutoff.
90
- * A negative value is treated as "use default" so callers can pass an
91
- * `undefined`-coerced settings value without a separate branch.
92
- */
93
- export declare function formatMultiDiffSummary(summary: MultiDiffSummary, threshold?: number): string | null;
94
12
  /**
95
13
  * One labeled diff — used to render a per-file block inside multi-file
96
14
  * diff views (e.g. when `replace` modifies several files). The path label
@@ -105,12 +23,6 @@ export declare function DiffFileBlock({ path, preview, useColor, contentWidth, }
105
23
  /** Pass-through to {@link DiffBlock}. See that component for details. */
106
24
  contentWidth?: number | undefined;
107
25
  }): React.ReactElement;
108
- /**
109
- * Human-readable change-size line for a diff — `Added N lines, removed M
110
- * lines` (Claude Code phrasing). Omits the zero side; returns `null` when
111
- * nothing changed so callers can skip the line entirely.
112
- */
113
- export declare function formatDiffStats(added: number, removed: number): string | null;
114
26
  /**
115
27
  * Return the token list to render on a diff wash (`diffAddBg` /
116
28
  * `diffDelBg`). When `onWash` is false the input is returned unchanged —
@@ -176,52 +88,6 @@ export declare function DiffBlock({ rows, hidden, added, removed, hiddenAdded, h
176
88
  */
177
89
  contentWidth?: number | undefined;
178
90
  }): React.ReactElement;
179
- /**
180
- * Parse a unified-diff string into a {@link DiffPreview}. Thin wrapper over the
181
- * shared, single-source-of-truth `parseUnifiedDiffPreview` in
182
- * @wrongstack/tools/tool-diff (which the WebUI and HQ also read). Kept as a
183
- * local export so this module's many callers and tests are unchanged.
184
- */
185
- export declare function parseUnifiedDiff(diff: string, maxLines: number): DiffPreview;
186
- /**
187
- * Pull a unified-diff string out of a tool's JSON output, then turn it
188
- * into a small, structured preview suitable for colour-coded rendering.
189
- */
190
- export declare function extractDiffPreview(toolName: string, output: string | undefined, input?: unknown | undefined): DiffPreview | undefined;
191
- /**
192
- * Pull one diff preview per file from a `replace` tool result. Each entry
193
- * has a `path` (best-effort: `results[i].path`, falling back to the input
194
- * argument when every result is for the same file) and a `preview` ready
195
- * for `DiffFileBlock` / `DiffBlock` rendering.
196
- *
197
- * Returns `undefined` when no per-file diff is recoverable (e.g. an empty
198
- * `results` array, no diff fields, or the result isn't a JSON object).
199
- *
200
- * Note: For a single entry point that handles `replace`, `diff`, and
201
- * `patch` (the three tools whose output can span multiple files), use
202
- * {@link extractMultiFileDiffs} instead — this function is kept for the
203
- * narrower replace-specific test cases.
204
- */
205
- export declare function extractReplaceDiffs(toolName: string, output: string | undefined, input?: unknown | undefined): DiffFilePreviews | undefined;
206
- /**
207
- * Pull a list of per-file diffs from a tool result that may span multiple
208
- * files. Handles:
209
- *
210
- * - `replace`: JSON `{ results: [{ path, diff }, …] }` (path per result,
211
- * fallback to the input path when the result omits one).
212
- * - `diff`: JSON `{ diff: string }` where `diff` is a git-style multi-file
213
- * unified diff (split on `diff --git` headers).
214
- * - `patch`: either JSON `{ diff: string, files: string[] }` or a raw
215
- * unified-diff string (split on `diff --git` headers, falling back to
216
- * `--- a/<path>` if no `diff --git` is present).
217
- *
218
- * Returns `undefined` when the tool isn't multi-file capable, the output
219
- * is missing/unparseable, or no per-file diff is recoverable. Returns an
220
- * empty array (not undefined) when the output parses but every entry has
221
- * an empty diff after trimming — the caller treats both as "nothing to
222
- * render" but the distinction is useful in tests.
223
- */
224
- export declare function extractMultiFileDiffs(toolName: string, output: string | undefined, input?: unknown | undefined): DiffFilePreviews | undefined;
225
91
  /**
226
92
  * Syntax-highlighted code / diff block.
227
93
  *
@@ -0,0 +1,143 @@
1
+ /**
2
+ * Pure diff model for tool-result cards: per-file preview types, render
3
+ * ceilings, multi-file rollups and extraction from tool output. No Ink or
4
+ * React — `code-block.tsx` renders it and re-exports it.
5
+ */
6
+ import { type DiffPreview } from '@wrongstack/tools/tool-diff';
7
+ export type { DiffLineKind, DiffLineRow, DiffPreview } from '@wrongstack/tools/tool-diff';
8
+ /**
9
+ * A parsed diff paired with the file it belongs to. Used when a tool
10
+ * produces diffs for several files at once (currently `replace`); each
11
+ * `DiffFilePreview` renders as one labeled `DiffFileBlock`.
12
+ */
13
+ export interface DiffFilePreview {
14
+ path: string;
15
+ preview: DiffPreview;
16
+ }
17
+ interface OmittedDiffSummary {
18
+ fileCount: number;
19
+ added: number;
20
+ removed: number;
21
+ }
22
+ /** Renderable file previews plus aggregate data for files omitted by the cap. */
23
+ export type DiffFilePreviews = DiffFilePreview[] & {
24
+ omitted?: OmittedDiffSummary | undefined;
25
+ };
26
+ /**
27
+ * Hard ceiling for one file's rendered diff preview. Diff rows are React/Ink
28
+ * elements and therefore retained by the active virtual-history window; an
29
+ * unbounded preview lets a single generated-file edit defeat virtualization.
30
+ * Totals for the whole diff remain available through `added`/`removed`, while
31
+ * the footer reports the hidden portion.
32
+ */
33
+ export declare const DIFF_MAX_LINES = 200;
34
+ /** Maximum number of per-file diff blocks retained for one tool entry. */
35
+ export declare const MULTI_DIFF_MAX_FILES = 20;
36
+ /** Maximum rendered diff rows retained across every file in one tool entry. */
37
+ export declare const MULTI_DIFF_MAX_ROWS = 400;
38
+ /**
39
+ * Minimum number of files before a summary footer is rendered above the
40
+ * per-file blocks. Below this threshold each file's own `… +N -M hidden`
41
+ * footer carries enough signal; above it, a single aggregate line keeps
42
+ * the screen from being drowned in per-file tail lines.
43
+ *
44
+ * This is the default when no user-tunable value is supplied. The
45
+ * settings picker exposes `MULTI_DIFF_SUMMARY_THRESHOLD_PRESETS` so
46
+ * users can raise the cutoff (e.g. for very wide terminals) or lower
47
+ * it (e.g. for tiny scrollback), or set it to 0 to suppress the
48
+ * summary entirely.
49
+ */
50
+ export declare const MULTI_DIFF_SUMMARY_THRESHOLD = 5;
51
+ /**
52
+ * Aggregate stats across a list of per-file diffs — used to print a
53
+ * single summary line at the top of a multi-file diff view when there
54
+ * are enough files to make the rollup useful.
55
+ */
56
+ export interface MultiDiffSummary {
57
+ fileCount: number;
58
+ added: number;
59
+ removed: number;
60
+ hiddenAdded: number;
61
+ hiddenRemoved: number;
62
+ /** Number of rendered files whose preview was truncated (has hidden rows).
63
+ * Does not include files omitted entirely by the multi-file render ceiling;
64
+ * those are tracked separately via {@link omittedFiles}. */
65
+ truncatedFiles: number;
66
+ /** Files omitted entirely by the multi-file render ceiling. Guaranteed non-negative. */
67
+ omittedFiles: number;
68
+ }
69
+ /**
70
+ * Sum the totals of a list of per-file diff previews. Files that were
71
+ * parsed but have no rows (e.g. entirely empty after the no-op skip) are
72
+ * excluded from the rollup so the summary reflects what the user will
73
+ * actually see rendered below.
74
+ */
75
+ export declare function summarizeMultiFileDiffs(items: DiffFilePreviews): MultiDiffSummary;
76
+ /**
77
+ * Format a multi-file diff summary as a single dim italic line, suitable
78
+ * for rendering above the per-file blocks. Mirrors the per-file footer's
79
+ * `… +N -M hidden` shape so a reader who has seen the footer recognises
80
+ * the format. Returns `null` when there's nothing useful to surface
81
+ * (no files, or below the user's threshold where the per-file footer
82
+ * already covers the rollup).
83
+ *
84
+ * @param threshold User-tunable cutoff. Pass `MULTI_DIFF_SUMMARY_THRESHOLD`
85
+ * for the default behaviour, `0` to suppress the summary entirely
86
+ * (always returns null), or a positive number to set a custom cutoff.
87
+ * A negative value is treated as "use default" so callers can pass an
88
+ * `undefined`-coerced settings value without a separate branch.
89
+ */
90
+ export declare function formatMultiDiffSummary(summary: MultiDiffSummary, threshold?: number): string | null;
91
+ /**
92
+ * Human-readable change-size line for a diff — `Added N lines, removed M
93
+ * lines` (Claude Code phrasing). Omits the zero side; returns `null` when
94
+ * nothing changed so callers can skip the line entirely.
95
+ */
96
+ export declare function formatDiffStats(added: number, removed: number): string | null;
97
+ /**
98
+ * Parse a unified-diff string into a {@link DiffPreview}. Thin wrapper over the
99
+ * shared, single-source-of-truth `parseUnifiedDiffPreview` in
100
+ * @wrongstack/tools/tool-diff (which the WebUI and HQ also read). Kept as a
101
+ * local export so this module's many callers and tests are unchanged.
102
+ */
103
+ export declare function parseUnifiedDiff(diff: string, maxLines: number): DiffPreview;
104
+ /**
105
+ * Pull a unified-diff string out of a tool's JSON output, then turn it
106
+ * into a small, structured preview suitable for colour-coded rendering.
107
+ */
108
+ export declare function extractDiffPreview(toolName: string, output: string | undefined, input?: unknown | undefined): DiffPreview | undefined;
109
+ /**
110
+ * Pull one diff preview per file from a `replace` tool result. Each entry
111
+ * has a `path` (best-effort: `results[i].path`, falling back to the input
112
+ * argument when every result is for the same file) and a `preview` ready
113
+ * for `DiffFileBlock` / `DiffBlock` rendering.
114
+ *
115
+ * Returns `undefined` when no per-file diff is recoverable (e.g. an empty
116
+ * `results` array, no diff fields, or the result isn't a JSON object).
117
+ *
118
+ * Note: For a single entry point that handles `replace`, `diff`, and
119
+ * `patch` (the three tools whose output can span multiple files), use
120
+ * {@link extractMultiFileDiffs} instead — this function is kept for the
121
+ * narrower replace-specific test cases.
122
+ */
123
+ export declare function extractReplaceDiffs(toolName: string, output: string | undefined, input?: unknown | undefined): DiffFilePreviews | undefined;
124
+ /**
125
+ * Pull a list of per-file diffs from a tool result that may span multiple
126
+ * files. Handles:
127
+ *
128
+ * - `replace`: JSON `{ results: [{ path, diff }, …] }` (path per result,
129
+ * fallback to the input path when the result omits one).
130
+ * - `diff`: JSON `{ diff: string }` where `diff` is a git-style multi-file
131
+ * unified diff (split on `diff --git` headers).
132
+ * - `patch`: either JSON `{ diff: string, files: string[] }` or a raw
133
+ * unified-diff string (split on `diff --git` headers, falling back to
134
+ * `--- a/<path>` if no `diff --git` is present).
135
+ *
136
+ * Returns `undefined` when the tool isn't multi-file capable, the output
137
+ * is missing/unparseable, or no per-file diff is recoverable. Returns an
138
+ * empty array (not undefined) when the output parses but every entry has
139
+ * an empty diff after trimming — the caller treats both as "nothing to
140
+ * render" but the distinction is useful in tests.
141
+ */
142
+ export declare function extractMultiFileDiffs(toolName: string, output: string | undefined, input?: unknown | undefined): DiffFilePreviews | undefined;
143
+ //# sourceMappingURL=diff-model.d.ts.map
@@ -25,6 +25,12 @@ export interface HistoryScrollController {
25
25
  scrollToBottom(): void;
26
26
  /** Jump to a 0-based cell clicked/dragged on the scrollbar track. */
27
27
  scrollToTrackCell(cell: number): void;
28
+ /**
29
+ * Bring the card holding `entryId` to the viewport top (re-pinning when it
30
+ * sits too close to the bottom). Returns false when the entry is not
31
+ * retained or not rendered.
32
+ */
33
+ scrollToEntry(entryId: number): boolean;
28
34
  /** True while the viewport is scrolled away from the newest output. */
29
35
  isScrolled(): boolean;
30
36
  /**
@@ -151,6 +157,11 @@ export interface ScrollableHistoryProps extends HistoryProps {
151
157
  * `null` / undefined = no card highlighted.
152
158
  */
153
159
  copiedEntryId?: number | null | undefined;
160
+ /**
161
+ * Entry the transcript search currently selects. Its card gets a marker in
162
+ * the rail's reserved gap column, so marking never reflows content.
163
+ */
164
+ markedEntryId?: number | null | undefined;
154
165
  /**
155
166
  * Called when the user scrolls near the top of the currently loaded
156
167
  * entries. The host should respond by loading older entries from the
@@ -15,12 +15,24 @@
15
15
  import type React from 'react';
16
16
  import type { CopyHit } from './copy-geometry.js';
17
17
  import { type SelectionBandStore } from './selection-band-store.js';
18
- export declare function Scrollbar({ rows, offset, total, copyHits, copiedEntryId, selectionBandStore, }: {
18
+ interface ScrollbarProps {
19
19
  rows: number;
20
20
  offset: number;
21
21
  total: number;
22
22
  copyHits: readonly CopyHit[];
23
23
  copiedEntryId?: number | null | undefined;
24
+ /** Transcript-search hit; its card's first row shows a marker in the gap column. */
25
+ markedEntryId?: number | null | undefined;
24
26
  selectionBandStore?: SelectionBandStore | undefined;
25
- }): React.ReactElement;
27
+ }
28
+ /**
29
+ * The rail renders one Box + five Texts per viewport row, and its parent
30
+ * rebuilds `copyHits` as a fresh array on every flush (streaming included).
31
+ * Compare only what the rail actually draws — each hit's row, entry id and
32
+ * whether it has an inspect glyph — so an unchanged rail skips the repaint.
33
+ * Drag-selection updates bypass props entirely through the band store.
34
+ */
35
+ export declare function scrollbarPropsEqual(prev: ScrollbarProps, next: ScrollbarProps): boolean;
36
+ export declare const Scrollbar: React.MemoExoticComponent<({ rows, offset, total, copyHits, copiedEntryId, markedEntryId, selectionBandStore, }: ScrollbarProps) => React.ReactElement>;
37
+ export {};
26
38
  //# sourceMappingURL=scrollbar-rail.d.ts.map
@@ -36,6 +36,11 @@ interface UseHistoryControllerOptions {
36
36
  entriesByIdRef: {
37
37
  current: Map<number, HistoryEntry>;
38
38
  };
39
+ /** Render-group index for every retained entry id, including entries
40
+ * folded into a compact tool group. */
41
+ groupIndexByEntryIdRef?: {
42
+ current: ReadonlyMap<number, number>;
43
+ } | undefined;
39
44
  toolStreamRef: {
40
45
  current: {
41
46
  name: string;
@@ -1,10 +1,10 @@
1
1
  export { countLines, firstNonEmpty, fmtBytes, fmtDuration, fmtTok, formatMatchHit, numOf, scanNumberedRange, shortenPath, stringOf, truncMid, tryParseJson, } from './basic-format.js';
2
+ export { extractSageBlock, type ParsedSageMemoryLine, parseSageMemoryLine, resolveEntrySage, type SageSplit, } from './sage-output-format.js';
2
3
  export { AssistantStreamBox, assistantStreamBoxHeight, MAX_STREAM_DISPLAY_CHARS, streamBoxRows, ToolStreamBox, tailForDisplay, toolStreamBoxHeight, } from './stream-box.js';
4
+ export { formatToolArgs } from './tool-arg-format.js';
3
5
  export type { ToolVisualLine, ToolVisualLineKind } from './tool-visual-types.js';
4
6
  export { ToolOutputLines } from './visual-lines.js';
5
- import type { ToolVisualLine } from './tool-visual-types.js';
6
- export { extractSageBlock, type ParsedSageMemoryLine, parseSageMemoryLine, resolveEntrySage, type SageSplit, } from './sage-output-format.js';
7
- export { formatToolArgs } from './tool-arg-format.js';
7
+ export { formatToolVisualOutput } from './visual-tool-output.js';
8
8
  /**
9
9
  * Like `formatToolOutput` but strips SAGE-injected memory lines first.
10
10
  * Returns the tool output lines and any SAGE block lines separately.
@@ -20,10 +20,4 @@ sageLines?: readonly string[] | undefined): {
20
20
  * Distil a tool's result text into 0–N digest lines the renderer can stack.
21
21
  */
22
22
  export declare function formatToolOutput(toolName: string, output: string | undefined, ok: boolean, _outputBytes?: number | undefined, outputLines?: number | undefined): string[];
23
- /**
24
- * Build richer terminal-native rows for common tool outputs. This handles both
25
- * raw JSON-shaped results used by unit tests and the compact serializer text
26
- * emitted in real sessions.
27
- */
28
- export declare function formatToolVisualOutput(toolName: string, output: string | undefined, ok: boolean, input?: unknown | undefined): ToolVisualLine[] | undefined;
29
23
  //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1,8 @@
1
+ import type { ToolVisualLine } from './tool-visual-types.js';
2
+ /**
3
+ * Build richer terminal-native rows for common tool outputs. This handles both
4
+ * raw JSON-shaped results used by unit tests and the compact serializer text
5
+ * emitted in real sessions.
6
+ */
7
+ export declare function formatToolVisualOutput(toolName: string, output: string | undefined, ok: boolean, input?: unknown | undefined): ToolVisualLine[] | undefined;
8
+ //# sourceMappingURL=visual-tool-output.d.ts.map
@@ -91,5 +91,5 @@ export interface KeyEvent {
91
91
  fn?: number | undefined;
92
92
  }
93
93
  export declare const EMPTY_KEY: KeyEvent;
94
- export declare const Input: React.MemoExoticComponent<({ prompt, value, cursor, disabled, hint, title, railIcon, accent, status, animationStyle, workingTime, footerHint, hidden, placeholderHeight, onKey, maxWidth, }: InputProps) => React.ReactElement>;
94
+ export declare const Input: React.MemoExoticComponent<({ prompt, value, cursor, disabled, hint, title, railIcon, accent, status, animationStyle, workingTime, footerHint, hidden, placeholderHeight, onKey, maxWidth, }: InputProps) => React.ReactElement | null>;
95
95
  //# sourceMappingURL=input.d.ts.map
@@ -0,0 +1,114 @@
1
+ import { type KanbanBoard, type KanbanBoardSummary, type KanbanLifecycleStage, type KanbanTask } from '@wrongstack/kanban';
2
+ import type React from 'react';
3
+ import { type KanbanAuditSummary } from '../kanban-audit.js';
4
+ export declare function CompactBoard({ board, activeTaskId, rows, width, }: {
5
+ board: KanbanBoard;
6
+ activeTaskId: string | undefined;
7
+ rows: number;
8
+ width: number;
9
+ }): React.ReactElement;
10
+ export declare function PromptLine({ prompt }: {
11
+ prompt: PromptMode;
12
+ }): React.ReactElement;
13
+ export declare function BoardList({ boards, selected, }: {
14
+ boards: KanbanBoardSummary[];
15
+ selected: number;
16
+ }): React.ReactElement;
17
+ /**
18
+ * Pure, deterministic layout math for the kanban board's column view.
19
+ *
20
+ * Reserves horizontal space for the chrome that surrounds the columns
21
+ * (board list panel + task detail panel + gaps + outer border), then
22
+ * picks the largest column count that still keeps every column at least
23
+ * `minColumnWidth` cols wide, and finally shrinks each column's width to
24
+ * match the available budget (never below `minColumnWidth`).
25
+ *
26
+ * Exported so Sprint 2's regression tests can pin the math down without
27
+ * mounting Ink.
28
+ */
29
+ export declare function computeBoardColumnLayout(totalColumns: number, terminalWidth: number): {
30
+ visibleColumnCount: number;
31
+ columnWidth: number;
32
+ overflow: number;
33
+ };
34
+ export declare function BoardColumns({ board, activeTaskId, terminalWidth, }: {
35
+ board: KanbanBoard;
36
+ activeTaskId?: string | undefined;
37
+ terminalWidth?: number | undefined;
38
+ }): React.ReactElement;
39
+ /**
40
+ * Whether a board enforces the managed Kanban Agent lifecycle. Managed boards
41
+ * reject free-form status/column writes (see `assertManagedTaskPatchAllowed`
42
+ * in `@wrongstack/kanban`), so the TUI must route progress through
43
+ * `transitionTask` rather than `moveTask`/`updateTask`.
44
+ */
45
+ export declare function isManagedBoard(board: KanbanBoard | null): boolean;
46
+ /**
47
+ * The next stage a managed card may advance to, or null when the card is
48
+ * already at the terminal `done` stage (or the current stage is unknown).
49
+ * The domain only allows one-step forward transitions; callers must keep
50
+ * this in lockstep with `KANBAN_AGENT_STAGES` in `@wrongstack/kanban`.
51
+ *
52
+ * Exported so unit tests can pin the stage order without rendering the panel.
53
+ */
54
+ export declare function nextManagedStage(current: KanbanLifecycleStage): KanbanLifecycleStage | null;
55
+ /**
56
+ * Look up the lifecycle stage that owns the given column under a managed
57
+ * Kanban Agent board. Returns null when the board is not managed, or when
58
+ * the column is not mapped to any of the five canonical stages (treated
59
+ * as a legacy/custom column by the renderer).
60
+ */
61
+ export declare function stageForColumn(board: Pick<KanbanBoard, 'lifecycle'>, columnId: string): KanbanLifecycleStage | null;
62
+ export declare function TaskDetail({ board, task, target, }: {
63
+ board: KanbanBoard;
64
+ task: KanbanTask | null;
65
+ target?: KanbanBoardSummary | undefined;
66
+ }): React.ReactElement;
67
+ /**
68
+ * Pure success-criteria summary string. Returns null when there are no
69
+ * checks. Format: "Criteria N/M passed".
70
+ */
71
+ export declare function summarizeSuccessCriteria(task: KanbanTask): string | null;
72
+ /**
73
+ * Pure goal-metrics rollup string. Returns null when there are no metrics.
74
+ * Format: "Metrics 2 met · 1 missed · 0 waived · 0 pending" (zero counts
75
+ * are skipped to keep the line short).
76
+ */
77
+ export declare function summarizeGoalMetrics(task: KanbanTask): string | null;
78
+ /**
79
+ * Inline Kanban Cleaner summary — mirrors the WebUI's `KanbanCleanerAlert`
80
+ * but pinned to the project root. Shows the headline counts at the top
81
+ * of the panel and the top-3 issues, scoped per board so users see what
82
+ * the Cleaner would flag without leaving the TUI.
83
+ *
84
+ * The component renders nothing when the audit is empty so a clean
85
+ * board doesn't add visual noise.
86
+ */
87
+ export declare function AuditAlert({ summary, topN, }: {
88
+ summary: KanbanAuditSummary;
89
+ topN?: number | undefined;
90
+ }): React.ReactElement | null;
91
+ export declare function BoardSummary({ board, target, }: {
92
+ board: KanbanBoard;
93
+ target?: KanbanBoardSummary | undefined;
94
+ }): React.ReactElement;
95
+ export declare function nextBoard(boards: KanbanBoardSummary[], boardId: string | undefined): KanbanBoardSummary | undefined;
96
+ export declare function adjacentColumn(columns: KanbanBoard['columns'], columnId: string, delta: -1 | 1): KanbanBoard['columns'][number] | undefined;
97
+ export declare function doneColumnId(board: KanbanBoard): string | undefined;
98
+ export declare function clamp(value: number, min: number, max: number): number;
99
+ export type PromptMode = {
100
+ kind: 'createBoard';
101
+ buffer: string;
102
+ } | {
103
+ kind: 'addTask';
104
+ buffer: string;
105
+ } | {
106
+ kind: 'confirmDeleteTask';
107
+ task: KanbanTask;
108
+ } | {
109
+ kind: 'transitionTask';
110
+ task: KanbanTask;
111
+ to: KanbanLifecycleStage;
112
+ buffer: string;
113
+ };
114
+ //# sourceMappingURL=kanban-panel-presentation.d.ts.map