@oh-my-pi/pi-tui 18.11.3 → 18.12.1

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 (58) hide show
  1. package/CHANGELOG.md +37 -93
  2. package/README.md +36 -0
  3. package/dist/types/chat/advisor-message.d.ts +4 -1
  4. package/dist/types/chat/messages.d.ts +3 -1
  5. package/dist/types/chrome/diff.d.ts +2 -3
  6. package/dist/types/render/hanging-wrap.d.ts +2 -0
  7. package/dist/types/render/render-utils.d.ts +9 -1
  8. package/dist/types/status-line/types.d.ts +3 -0
  9. package/dist/types/terminal-capabilities.d.ts +8 -1
  10. package/dist/types/terminal-multiplexer.d.ts +6 -0
  11. package/dist/types/theme/theme.d.ts +11 -0
  12. package/dist/types/tmux.d.ts +9 -0
  13. package/dist/types/tools/ast-edit.d.ts +2 -2
  14. package/dist/types/tools/ast-grep.d.ts +2 -2
  15. package/dist/types/tools/edit.d.ts +2 -0
  16. package/dist/types/tools/eval.d.ts +51 -7
  17. package/dist/types/tools/find.d.ts +14 -4
  18. package/dist/types/tools/glob.d.ts +3 -3
  19. package/dist/types/tools/grep.d.ts +2 -2
  20. package/dist/types/tools/grouped-file-output.d.ts +3 -3
  21. package/dist/types/tools/read.d.ts +14 -6
  22. package/dist/types/tools/write.d.ts +2 -0
  23. package/package.json +9 -9
  24. package/src/chat/advisor-message.ts +77 -24
  25. package/src/chat/assistant-message.ts +3 -1
  26. package/src/chat/messages.ts +4 -1
  27. package/src/chat/read-tool-group.ts +19 -11
  28. package/src/chat/tool-execution.ts +23 -6
  29. package/src/chrome/diff.ts +4 -9
  30. package/src/components/image.ts +31 -14
  31. package/src/render/hanging-wrap.ts +28 -1
  32. package/src/render/render-utils.ts +16 -2
  33. package/src/status-line/component.ts +1 -0
  34. package/src/status-line/segments.ts +4 -3
  35. package/src/status-line/types.ts +1 -0
  36. package/src/terminal-capabilities.ts +33 -3
  37. package/src/terminal-multiplexer.ts +14 -0
  38. package/src/terminal.ts +11 -2
  39. package/src/theme/theme.ts +46 -14
  40. package/src/tmux.ts +37 -1
  41. package/src/tools/ast-edit.ts +30 -7
  42. package/src/tools/ast-grep.ts +25 -6
  43. package/src/tools/debug.ts +2 -1
  44. package/src/tools/default-renderer.ts +3 -2
  45. package/src/tools/edit.ts +80 -19
  46. package/src/tools/eval.ts +132 -132
  47. package/src/tools/find.ts +71 -18
  48. package/src/tools/glob.ts +51 -17
  49. package/src/tools/grep.ts +94 -13
  50. package/src/tools/grouped-file-output.ts +6 -5
  51. package/src/tools/lsp.ts +23 -18
  52. package/src/tools/mcp.ts +2 -2
  53. package/src/tools/read.ts +55 -25
  54. package/src/tools/task.ts +9 -7
  55. package/src/tools/web-search.ts +2 -1
  56. package/src/tools/write.ts +22 -8
  57. package/src/tools/yield.ts +2 -2
  58. package/src/tui.ts +36 -0
package/CHANGELOG.md CHANGED
@@ -2,6 +2,42 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [18.12.1] - 2026-10-17
6
+
7
+ ### Breaking Changes
8
+
9
+ - `numberedCode`, `readContentCode` and `nativeDiff` take the file's path (`path`) instead of a language, and `describeGroupedOutput` drops its `lang` option: Tern picks the grammar of file contents from their path
10
+
11
+ ### Changed
12
+
13
+ - Advisor notes in Tern read as a callout tinted by their worst severity: its icon and a tally (`Concern`, `1 blocker · 2 concerns`) head the card with the advisor's name at the end, and several notes each lead with their own severity icon
14
+
15
+ ### Fixed
16
+
17
+ - Fixed images rendering blank inside tmux on Kitty-capable terminals when tmux's `allow-passthrough` is off (the default); omp now falls back to SIXEL or the text placeholder instead of sending Kitty graphics tmux drops
18
+ - Fixed Tern drawing tool cards' file contents (write, read, edit, grep, find, ast-grep, ast-edit) plain or in the wrong language when omp did not know the file's extension (`.ptx`) or mapped it to a neighbor (`.cu` as C++); omp now sends the file's path and Tern picks the grammar
19
+
20
+ ## [18.12.0] - 2026-10-17
21
+
22
+ ### Breaking Changes
23
+
24
+ - `FindStats.errors` is replaced by `failed` (judge requests that failed) and `unanswered` (unusable answers), and `FindToolDetails` requires a `coverage` status; the find renderer shows `N/M requests failed` ([#15744](https://github.com/can1357/oh-my-pi/issues/15744))
25
+
26
+ ### Added
27
+
28
+ - Added `pi.showProfile` to `StatusLineSegmentOptions`: `false` keeps the `pi` segment's bare glyph under a named profile, in the rendered bar and in `describe` ([#16063](https://github.com/can1357/oh-my-pi/pull/16063) by [@shgew](https://github.com/shgew))
29
+
30
+ ### Fixed
31
+
32
+ - Fixed sessions run inside tmux silently falling back to the terminal's true-color profile when the client terminal-type probe answered slowly on a loaded machine ([#16020](https://github.com/can1357/oh-my-pi/pull/16020) by [@CharleoYang](https://github.com/CharleoYang))
33
+ - Fixed the `read` result notice printing the absolute resolved path, so a file under the home directory reads `Resolved path: ~/notes.txt` instead of `/home/you/notes.txt` ([#16055](https://github.com/can1357/oh-my-pi/pull/16055) by [@adi-IL](https://github.com/adi-IL)).
34
+ - Fixed grep/read previews and other tool cards passing raw escape sequences from file contents to the terminal, which could switch it to the alternate screen with mouse reporting on, live and again on every resume ([#15963](https://github.com/can1357/oh-my-pi/issues/15963))
35
+ - Fixed a final status-line render after shutdown scheduling another usage refresh ([#15845](https://github.com/can1357/oh-my-pi/issues/15845)).
36
+ - Fixed Ctrl+O on LSP status and other plain LSP responses still clipping every row at 80 columns; expanded rows now wrap to show the full text ([#15824](https://github.com/can1357/oh-my-pi/issues/15824))
37
+ - Fixed Ctrl+O leaving long rows clipped in expanded LSP, debug, MCP, web search fallback, yield, task and custom-tool results; expanded rows now wrap to show the full text, expanded LSP references list every location, and the LSP expand hint no longer appears when nothing is hidden ([#15824](https://github.com/can1357/oh-my-pi/issues/15824))
38
+ - Fixed jagged text and disappearing translucent details in SIXEL images, including re-encoding when the terminal reports a changed background color ([#15891](https://github.com/can1357/oh-my-pi/pull/15891) by [@Bouska](https://github.com/Bouska)).
39
+ - Fixed stale SIXEL backgrounds after terminal restarts, native appearance changes, and failed TSP handshakes, including background changes during the handshake, fixed themes, missing or invalid startup themes, or identical light/dark mappings ([#15891](https://github.com/can1357/oh-my-pi/pull/15891) by [@Bouska](https://github.com/Bouska)).
40
+
5
41
  ## [18.11.3] - 2026-10-16
6
42
 
7
43
  ### Added
@@ -2491,96 +2527,4 @@
2491
2527
 
2492
2528
  - Changed truncation debug logging to run only when `debugRedraw` is enabled
2493
2529
 
2494
- ## [14.0.5] - 2026-04-11
2495
-
2496
- ### Changed
2497
-
2498
- - Updated hash computation to use `Bun.hash()` instead of `Bun.hash.xxHash64()`, which may return `number` in addition to `bigint`
2499
- - Simplified cache key computation in Box component by removing intermediate hash updates and consolidating hash operations
2500
- - Wrapped native text utility functions (`sliceWithWidth`, `truncateToWidth`, `wrapTextWithAnsi`, `extractSegments`) to automatically pass the current default tab width, simplifying the API for consumers
2501
- - Added `getIndentationNoescape` wrapper that uses `process.cwd()` as the project root for relative file paths
2502
- - Re-export `getDefaultTabWidth`, `getIndentation`, and `setDefaultTabWidth` from `@oh-my-pi/pi-utils`; native text helpers still receive tab width via wrappers that read the JS default
2503
-
2504
- ## [13.16.1] - 2026-03-27
2505
-
2506
- ### Added
2507
-
2508
- - Support for optional SearchDb parameter in CombinedAutocompleteProvider constructor for improved fuzzy search performance
2509
- - Fuzzy matching filter for autocomplete suggestions to improve relevance of results
2510
-
2511
- ### Changed
2512
-
2513
- - Fuzzy discovery now applies fuzzy matching filter to results for improved relevance of autocomplete suggestions
2514
- - Autocomplete fuzzy discovery now accepts optional SearchDb instance for faster searches
2515
-
2516
- ## [13.16.0] - 2026-03-27
2517
-
2518
- ### Changed
2519
-
2520
- - Updated tab replacement in editor text sanitization to respect configured tab width setting
2521
-
2522
- ## [13.15.0] - 2026-03-23
2523
-
2524
- ### Added
2525
-
2526
- - Added `renderInlineMarkdown()` function to render inline markdown (bold, italic, code, links, strikethrough) to styled strings
2527
-
2528
- ### Fixed
2529
-
2530
- - Fixed editor consuming user-rebound copy keys, preventing custom keybindings from working in the editor
2531
-
2532
- ## [13.14.1] - 2026-03-21
2533
-
2534
- ### Added
2535
-
2536
- - Added Ctrl+_ as an additional default shortcut for undo
2537
-
2538
- ### Fixed
2539
-
2540
- - Ensured undo functionality respects user-configured keybindings
2541
-
2542
- ## [13.12.0] - 2026-03-14
2543
-
2544
- ### Added
2545
-
2546
- - Added `moveToMessageStart()` and `moveToMessageEnd()` methods to move cursor to the beginning and end of the entire message
2547
-
2548
- ### Fixed
2549
-
2550
- - Fixed autocomplete to preserve `./` prefix when completing relative file and directory paths
2551
- - Fixed paste marker expansion to handle special regex replacement tokens ($1, $2, $&, $$, $`, $') literally in pasted content
2552
-
2553
- ## [13.11.0] - 2026-03-12
2554
-
2555
- ### Fixed
2556
-
2557
- - Fixed OSC 11 background color detection to correctly handle partial escape sequences that arrive mid-buffer, preventing user input from being swallowed
2558
- - Fixed race condition where overlapping OSC 11 queries would be incorrectly cancelled by DA1 sentinels from previous queries
2559
-
2560
- ## [13.7.5] - 2026-03-04
2561
-
2562
- ### Changed
2563
-
2564
- - Extracted word navigation logic into reusable `moveWordLeft` and `moveWordRight` utility functions for consistent cursor movement across components
2565
-
2566
- ## [13.6.2] - 2026-03-03
2567
-
2568
- ### Fixed
2569
-
2570
- - Fixed cursor positioning when content shrinks to empty without clearOnShrink enabled
2571
-
2572
- ## [13.5.4] - 2026-03-01
2573
-
2574
- ### Fixed
2575
-
2576
- - Fixed viewport repaint scrollback accounting during resize oscillation to avoid double-scrolling on height shrink and added exact-row scrollback assertions in overlay regression coverage ([#228](https://github.com/can1357/oh-my-pi/issues/228), [#234](https://github.com/can1357/oh-my-pi/issues/234))
2577
-
2578
- ## [13.5.3] - 2026-03-01
2579
-
2580
- ### Fixed
2581
-
2582
- - Fixed append rendering logic to correctly handle offscreen header changes during content overflow growth, preserving scroll history integrity
2583
- - Fixed visible tail line updates when appending new content during viewport overflow conditions
2584
- - Fixed cursor positioning instability when appending content under external cursor relocation by using absolute screen addressing instead of relative cursor movement
2585
-
2586
- Older entries are archived in [packages/tui/CHANGELOG.md@20c388be2131](https://github.com/can1357/oh-my-pi/blob/20c388be2131e06f731a8759ec3ab6121d6ada1c/packages/tui/CHANGELOG.md).
2530
+ Older entries are archived in [packages/tui/CHANGELOG.md@200e7d2c6ebb](https://github.com/can1357/oh-my-pi/blob/200e7d2c6ebb2e187b167f807b9f68f779c0bf4b/packages/tui/CHANGELOG.md).
package/README.md CHANGED
@@ -38,6 +38,42 @@ tui.addChild(editor);
38
38
  tui.start();
39
39
  ```
40
40
 
41
+ ## SIXEL transparency and terminal backgrounds
42
+
43
+ SIXEL has binary transparency, not fractional alpha. omp blends partially
44
+ transparent image pixels against the terminal's reported OSC 11 background
45
+ before quantization, preserving antialiased text and translucent details.
46
+ Images with alpha are resized in premultiplied form before background compositing
47
+ to prevent dark fringes and hidden-color bleed along scaled transparent edges.
48
+ Fully transparent pixels stay transparent. Kitty and iTerm2 retain their
49
+ existing image paths.
50
+
51
+ When a new OSC 11 report changes the background RGB, SIXEL images are
52
+ re-encoded even if the terminal stays dark or stays light. Terminals supporting
53
+ Mode 2031 trigger this automatically. Otherwise, press Ctrl+L to refresh the
54
+ background after changing it. This introduces no periodic polling.
55
+ Direct terminals replay transcript history using the existing theme-change
56
+ repaint policy; multiplexers repaint the viewport without clearing their native
57
+ scrollback.
58
+
59
+ Cached RGB is cleared when terminal ownership starts or ends, so a restarted
60
+ session without an OSC 11 response cannot inherit the previous terminal's RGB.
61
+ If the terminal cannot report its RGB, or an active multiplexer marks background
62
+ queries as unreliable on the current platform, omp approximates the background
63
+ with black for detected dark appearance or white for light. Untrusted reports
64
+ do not override the existing appearance fallback. Exact edge-color matching is
65
+ not guaranteed with that fallback, transparent terminal windows, or graphics
66
+ overlapping a differently colored background.
67
+
68
+ On known-broken background-query paths, such as macOS inside Zellij, native
69
+ appearance changes also repaint SIXEL images when using a fixed theme or
70
+ identical light/dark theme mappings. `COLORFGBG` still takes precedence over the
71
+ native fallback; reports that leave the effective background unchanged do not
72
+ trigger a repaint.
73
+
74
+ If native TSP negotiation fails, the row renderer resumes these SIXEL refreshes.
75
+ Expecting native support alone does not disable repainting after the failure.
76
+
41
77
  ## Core API
42
78
 
43
79
  ### TUI
@@ -1,6 +1,6 @@
1
1
  import { type Component } from "../tui.js";
2
2
  import type { AdvisorMessageDetails } from "./messages.js";
3
- import { type Theme } from "../theme/index.js";
3
+ import type { Theme } from "../theme/index.js";
4
4
  import { type NativeUiEvent } from "../native/node.js";
5
5
  /** The advisor card: shared by the controlled expansion getter and native toggles. */
6
6
  export interface AdvisorMessageCard extends Component {
@@ -14,6 +14,9 @@ export interface AdvisorMessageCard extends Component {
14
14
  * output (whose `thinkingText` color equals `toolOutput` in most themes):
15
15
  * a bold `customMessageLabel` header tag (skill-card convention), a heavy
16
16
  * rail tinted per-note severity, and the note body on the default text color.
17
+ * Natively it is a callout tinted by its worst note: that severity's icon and
18
+ * the tally head it, the advisor's name ends the head, and with several notes
19
+ * each leads with its own severity icon.
17
20
  *
18
21
  * `getExpanded` owns expansion; a native toggle overrides it for this card
19
22
  * until the next transcript-wide change.
@@ -173,7 +173,9 @@ export declare function isUserInvokedSkillPrompt(message: CustomMessage): boolea
173
173
  * reminders, and auto-continues are not turn starts.
174
174
  */
175
175
  export declare function isUserTurnInitiator(message: CustomMessage): boolean;
176
- export type AdvisorSeverity = "nit" | "concern" | "blocker";
176
+ /** Advisor note severities, weakest first; ranks severity thresholds such as `advisor.continueSeverity`. */
177
+ export declare const ADVISOR_SEVERITIES: readonly ["nit", "concern", "blocker"];
178
+ export type AdvisorSeverity = (typeof ADVISOR_SEVERITIES)[number];
177
179
  /** One queued advice note. */
178
180
  export interface AdvisorNote {
179
181
  note: string;
@@ -7,10 +7,9 @@ import type { NativeNode } from "../native/node.js";
7
7
  * becomes one hunk; the terminal draws gutters, word emphasis and highlighting.
8
8
  * Removed rows carry old line numbers, added rows new ones and context rows
9
9
  * old ones, so the other side is derived from the running line delta.
10
+ * Tern picks the grammar from `path`.
10
11
  */
11
- export declare function nativeDiff(diffText: string, options?: {
12
- filePath?: string;
13
- } & TspProps<"diff">): NativeNode;
12
+ export declare function nativeDiff(diffText: string, props?: TspProps<"diff">): NativeNode;
14
13
  export interface RenderDiffOptions {
15
14
  /** File path used to resolve indentation (.editorconfig + defaults) */
16
15
  filePath?: string;
@@ -3,3 +3,5 @@ import type { Theme } from "../theme/theme.js";
3
3
  export declare function wrapPrefixedLine(prefix: string, continuationPrefix: string, content: string, width: number): string[];
4
4
  /** Preserve a tree connector's ancestor guides while hanging a long node beneath its label. */
5
5
  export declare function wrapTreeLine(line: string, width: number, theme: Theme): string[] | undefined;
6
+ /** Hang a tree row beneath its connector, or a connector-less detail row beneath its guide rails. */
7
+ export declare function wrapGuidedLine(line: string, width: number, theme: Theme): string[];
@@ -105,14 +105,22 @@ export declare function cappedHeadLines(lines: readonly string[], max: number):
105
105
  };
106
106
  /** Get the first nonblank preview lines, trimmed and width-capped. */
107
107
  export declare function getPreviewLines(text: string, maxLines: number, maxLineLen: number, ellipsis?: Ellipsis): string[];
108
+ /** Collapse a possibly multi-line string into one line; whitespace runs (tabs included) become one space. */
109
+ export declare function flattenLine(text: string): string;
108
110
  /**
109
111
  * Collapse a possibly multi-line string into a single line, then truncate it to
110
112
  * `maxWidth` display cells. {@link truncateToWidth} alone caps width but
111
113
  * newlines are zero-width, so multi-line content (markdown briefs, tool args,
112
114
  * provider errors) would otherwise spill a single status row across several
113
- * visual lines. Whitespace runs collapse to one space, so tabs are handled too.
115
+ * visual lines.
114
116
  */
115
117
  export declare function previewLine(text: string, maxWidth: number, ellipsis?: Ellipsis): string;
118
+ /**
119
+ * Clip a result row to `maxWidth` only while collapsed. Expanded rows stay whole
120
+ * so the frame wraps them: the expand key ({@link formatExpandHint}) must reveal
121
+ * text, not re-clip it.
122
+ */
123
+ export declare function clipCollapsed(text: string, maxWidth: number, expanded: boolean | undefined): string;
116
124
  /**
117
125
  * Extract domain from URL, stripping www. prefix.
118
126
  */
@@ -31,6 +31,9 @@ export interface CollabStatus {
31
31
  stateOverride?: CollabSessionState | null;
32
32
  }
33
33
  export interface StatusLineSegmentOptions {
34
+ pi?: {
35
+ showProfile?: boolean;
36
+ };
34
37
  model?: {
35
38
  showThinkingLevel?: boolean;
36
39
  };
@@ -1,6 +1,13 @@
1
1
  import type { HangulCompatibilityJamoWidth } from "./utils.js";
2
2
  export * from "./terminal-multiplexer.js";
3
3
  export { wrapTmuxPassthrough } from "./tmux.js";
4
+ /**
5
+ * Trusted terminal background when reported; otherwise black for detected dark
6
+ * appearance or white for detected light appearance, using theme auto-detection.
7
+ */
8
+ export declare function getTerminalBackgroundColor(): number;
9
+ /** Store an OSC 11 background, or reset to appearance detection (also for tests). */
10
+ export declare function setTerminalBackgroundColor(color: number | undefined): void;
4
11
  export declare enum ImageProtocol {
5
12
  Kitty = "\u001B_G",
6
13
  Iterm2 = "\u001B]1337;File=",
@@ -393,7 +400,7 @@ export declare function getImageDimensions(base64Data: string, mimeType: string)
393
400
  * thread; `null` when the encode fails. For output that cannot wait for an
394
401
  * off-thread encode.
395
402
  */
396
- export declare function encodeSixelNow(base64Data: string, widthPx: number, heightPx: number): string | null;
403
+ export declare function encodeSixelNow(base64Data: string, widthPx: number, heightPx: number, backgroundRgb?: number): string | null;
397
404
  export declare function renderImage(base64Data: string, imageDimensions: ImageDimensions, options?: ImageRenderOptions): {
398
405
  sequence?: string;
399
406
  lines?: string[];
@@ -101,6 +101,12 @@ export declare function hasTerminalMultiplexerSession(multiplexer: TerminalMulti
101
101
  * order. Nested sessions all appear; TERM is not consulted.
102
102
  */
103
103
  export declare function terminalMultiplexerSessions(env?: NodeJS.ProcessEnv): TerminalMultiplexerModule<TerminalMultiplexer>[];
104
+ /**
105
+ * Whether OSC 11 background replies are trusted on this platform. Any active
106
+ * session with `backgroundQueryBrokenOn` matching the platform makes the entire
107
+ * path untrusted; TERM-only classification does not identify an active session.
108
+ */
109
+ export declare function isTerminalBackgroundQueryTrusted(env?: NodeJS.ProcessEnv, platform?: NodeJS.Platform): boolean;
104
110
  /**
105
111
  * The multiplexer TERM names, whether or not its session markers survived.
106
112
  * This is classification's TERM fallback; session markers are not consulted.
@@ -7,6 +7,17 @@ export { isValidThemeColor, type ThemeBg, type ThemeColor } from "./schema.js";
7
7
  export { getAvailableSymbolPresets, isValidSymbolPreset, type SpinnerType, type SymbolKey, type SymbolPreset, } from "./symbols.js";
8
8
  export { Theme } from "./theme-class.js";
9
9
  export { createHighlightStream, getEditorTheme, getMarkdownTheme, getMarkdownThemeWithLinkTargets, getSelectListTheme, getSettingsListTheme, getSymbolTheme, highlightCode, setMarkdownMermaidRendering, warmHighlighter, } from "./tui-adapters.js";
10
+ /**
11
+ * Subscribe to native fallback appearance changes independently of theme changes.
12
+ * Consumers must re-check the effective background: COLORFGBG can override it.
13
+ */
14
+ export declare function onTerminalBackgroundFallbackChange(callback: () => void): () => void;
15
+ /**
16
+ * Detect appearance from trusted OSC 11 reports, then COLORFGBG, then native
17
+ * macOS appearance only on known-broken multiplexer background-query paths.
18
+ * Defaults to dark when none of those signals is available.
19
+ */
20
+ export declare function detectTerminalBackground(): "dark" | "light";
10
21
  /** Active theme; imports remain live across initialization, previews, and theme switches. */
11
22
  export declare var theme: Theme;
12
23
  type ThemeBinding = (value: Theme) => void;
@@ -45,3 +45,12 @@ export declare function resolveTmuxClientTerminalNames(env?: NodeJS.ProcessEnv):
45
45
  * for features.
46
46
  */
47
47
  export declare function tmuxClientRendersSixel(env?: NodeJS.ProcessEnv): boolean;
48
+ /**
49
+ * Whether tmux forwards this pane's `\x1bPtmux;…\x1b\\` passthrough envelopes
50
+ * to the attached client. tmux 3.3+ defaults `allow-passthrough` to `off` and
51
+ * then silently drops every wrapped sequence, so Kitty graphics sent through
52
+ * the envelope never reach a Kitty-capable outer terminal. Resolves the
53
+ * effective pane value (pane → window → global). Queried once per pane;
54
+ * `false` outside tmux or when the query fails.
55
+ */
56
+ export declare function tmuxPaneAllowsPassthrough(env?: NodeJS.ProcessEnv): boolean;
@@ -1,7 +1,7 @@
1
1
  import type { Component } from "../tui.js";
2
2
  import type { Theme } from "../theme/theme.js";
3
3
  import type { OutputMeta } from "./output-meta.js";
4
- import type { NativeToolView, RenderResultOptions } from "./renderer.js";
4
+ import type { NativeToolView, RenderResultContextOptions, RenderResultOptions } from "./renderer.js";
5
5
  /** Display metadata returned by ast-edit. */
6
6
  export interface AstEditToolDetails {
7
7
  totalReplacements: number;
@@ -47,7 +47,7 @@ export declare const astEditToolRenderer: {
47
47
  }>;
48
48
  details?: AstEditToolDetails;
49
49
  isError?: boolean;
50
- }, options: RenderResultOptions, uiTheme: Theme, args?: AstEditRenderArgs): Component;
50
+ }, options: RenderResultContextOptions, uiTheme: Theme, args?: AstEditRenderArgs): Component;
51
51
  describeCall(args: AstEditRenderArgs): NativeToolView;
52
52
  describeResult(result: {
53
53
  content: Array<{
@@ -1,7 +1,7 @@
1
1
  import type { Component } from "../tui.js";
2
2
  import type { Theme } from "../theme/theme.js";
3
3
  import type { OutputMeta } from "./output-meta.js";
4
- import type { NativeToolView, RenderResultOptions } from "./renderer.js";
4
+ import type { NativeToolView, RenderResultContextOptions, RenderResultOptions } from "./renderer.js";
5
5
  /** Display metadata returned by ast-grep. */
6
6
  export interface AstGrepToolDetails {
7
7
  matchCount: number;
@@ -46,7 +46,7 @@ export declare const astGrepToolRenderer: {
46
46
  }>;
47
47
  details?: AstGrepToolDetails;
48
48
  isError?: boolean;
49
- }, options: RenderResultOptions, uiTheme: Theme, args?: AstGrepRenderArgs): Component;
49
+ }, options: RenderResultContextOptions, uiTheme: Theme, args?: AstGrepRenderArgs): Component;
50
50
  describeCall(args: AstGrepRenderArgs): NativeToolView;
51
51
  describeResult(result: {
52
52
  content: Array<{
@@ -133,6 +133,8 @@ export interface EditRenderContext {
133
133
  renderDiff?: (diffText: string, options?: {
134
134
  filePath?: string;
135
135
  }) => string;
136
+ /** Unsanitized result metadata, used only for filesystem link targets. */
137
+ rawDetails?: unknown;
136
138
  }
137
139
  /** Render replacement text until a computed diff preview is available. */
138
140
  export declare function renderStreamingFallback(editMode: EditMode, args: unknown, theme: Theme): string;
@@ -13,30 +13,60 @@ export interface EvalStatusEvent {
13
13
  resolvedThinkingLevel?: ConfiguredThinkingLevel;
14
14
  [key: string]: unknown;
15
15
  }
16
+ /** One column of a table view. */
17
+ export interface EvalTableColumn {
18
+ head: string;
19
+ /** Numeric values: renderers right-align the column. */
20
+ numeric?: boolean;
21
+ }
22
+ /**
23
+ * A pretty rendering of something a cell printed, shown to the user in place
24
+ * of its text; the model only ever sees the text.
25
+ * - `table`: a data frame or `console.table`; leading index columns are plain
26
+ * columns, and a truncated frame's elided rows/columns are `…` cells.
27
+ * - `json`: a structured value (dict/list, object/array) as a collapsible tree.
28
+ * - `markdown`: an object's Markdown representation.
29
+ */
30
+ export type EvalView = {
31
+ kind: "table";
32
+ columns: EvalTableColumn[];
33
+ rows: string[][];
34
+ } | {
35
+ kind: "json";
36
+ value: unknown;
37
+ } | {
38
+ kind: "markdown";
39
+ text: string;
40
+ };
41
+ /**
42
+ * A view and the exact printed text it stands for. Renderers locate `text` in
43
+ * the cell's `output` (entries in print order) and show the view there; an
44
+ * entry whose text is no longer in the output (truncated) is skipped.
45
+ */
46
+ export interface EvalViewEntry {
47
+ text: string;
48
+ view: EvalView;
49
+ }
16
50
  /** Per-cell execution result for transcript rendering. */
17
51
  export interface EvalCellResult {
18
52
  index: number;
19
53
  title?: string;
20
54
  code: string;
21
55
  language?: EvalLanguage;
56
+ /** What the model saw: the cell's printed text plus image notes. */
22
57
  output: string;
23
- /**
24
- * `output` without its `display[N]:` JSON sections, which renderers show
25
- * from `jsonOutputs` instead. Absent when the cell displayed no JSON.
26
- */
27
- textOutput?: string;
58
+ /** Pretty views of spans of `output`, in print order. */
59
+ views?: EvalViewEntry[];
28
60
  status: "pending" | "running" | "complete" | "error";
29
61
  durationMs?: number;
30
62
  exitCode?: number;
31
63
  statusEvents?: EvalStatusEvent[];
32
64
  /** Discrete events dropped from the front of `statusEvents` (see {@link recordStatusEvent}). */
33
65
  statusEventsElided?: number;
34
- hasMarkdown?: boolean;
35
66
  }
36
67
  /** Tool result detail object surfaced to the UI/transcript. */
37
68
  export interface EvalToolDetails {
38
69
  cells?: EvalCellResult[];
39
- jsonOutputs?: unknown[];
40
70
  images?: ImageContent[];
41
71
  statusEvents?: EvalStatusEvent[];
42
72
  /** Discrete events dropped from the front of `statusEvents` (see {@link recordStatusEvent}). */
@@ -105,6 +135,20 @@ export declare function upsertStatusEvent(events: EvalStatusEvent[], event: Eval
105
135
  * events behind an "… N earlier" row.
106
136
  */
107
137
  export declare function recordStatusEvent(log: StatusEventLog, event: EvalStatusEvent): void;
138
+ /** One ordered piece of a cell's output: printed text, or a view shown in place of the text it matched. */
139
+ export type EvalOutputPart = {
140
+ kind: "text";
141
+ text: string;
142
+ } | {
143
+ kind: "view";
144
+ view: EvalView;
145
+ };
146
+ /**
147
+ * Split `output` around its views, in order: each view's `text` is searched
148
+ * from the end of the previous match, unmatched entries are skipped, and
149
+ * blank text between views is dropped (newlines bordering a view trimmed).
150
+ */
151
+ export declare function splitEvalOutput(output: string, views: readonly EvalViewEntry[] | undefined): EvalOutputPart[];
108
152
  /** Render eval code cells, structured display output, and progress events. */
109
153
  export declare const evalToolRenderer: {
110
154
  animatedPendingPreview: true;
@@ -1,7 +1,7 @@
1
1
  import type { Theme } from "../theme/theme.js";
2
2
  import type { Component } from "../tui.js";
3
3
  import type { OutputMeta } from "./output-meta.js";
4
- import type { NativeToolView, RenderResultOptions } from "./renderer.js";
4
+ import type { NativeToolView, RenderResultContextOptions, RenderResultOptions } from "./renderer.js";
5
5
  /** A verified line range with its yes-probability and a one-line preview. */
6
6
  export interface FindRange {
7
7
  start: number;
@@ -22,12 +22,21 @@ export interface FindHit {
22
22
  linesSeen: number;
23
23
  truncated: boolean;
24
24
  }
25
+ /**
26
+ * How much of a search the judge actually covered. `unavailable`: every judge
27
+ * request failed, so an empty result is not evidence of absence. `partial`:
28
+ * some requests failed. `complete`: none failed (or none were needed).
29
+ */
30
+ export type FindCoverage = "complete" | "partial" | "unavailable";
25
31
  /** Search accounting reported alongside the hits. */
26
32
  export interface FindStats {
27
33
  /** Eligible files under the root. */
28
34
  listed: number;
29
35
  requests: number;
30
- errors: number;
36
+ /** Judge requests that failed outright; decides {@link FindCoverage}. */
37
+ failed: number;
38
+ /** Questions a successful response left without a usable answer. */
39
+ unanswered: number;
31
40
  /** Entries judged by name. */
32
41
  judged: number;
33
42
  /** Files whose content was read and sent. */
@@ -51,6 +60,7 @@ export interface FindToolDetails {
51
60
  /** Verified-passage probability at or above which a file is a hit. */
52
61
  threshold: number;
53
62
  hits: FindHit[];
63
+ coverage: FindCoverage;
54
64
  stats: FindStats;
55
65
  elapsedMs: number;
56
66
  /** Session cwd; hit paths are relative to it. */
@@ -74,7 +84,7 @@ export declare const findToolRenderer: {
74
84
  }>;
75
85
  details?: FindToolDetails;
76
86
  isError?: boolean;
77
- }, options: RenderResultOptions, uiTheme: Theme, args?: FindRenderArgs): Component;
87
+ }, options: RenderResultContextOptions, uiTheme: Theme, args?: FindRenderArgs): Component;
78
88
  describeCall(args: FindRenderArgs): NativeToolView;
79
89
  /**
80
90
  * Inline (§7.3 find): `Find “query” 2 hits · 8 files`, then per hit its
@@ -88,7 +98,7 @@ export declare const findToolRenderer: {
88
98
  }>;
89
99
  details?: FindToolDetails;
90
100
  isError?: boolean;
91
- }, options: RenderResultOptions, args?: FindRenderArgs): NativeToolView;
101
+ }, options: RenderResultContextOptions, args?: FindRenderArgs): NativeToolView;
92
102
  mergeCallAndResult: true;
93
103
  animatedPendingPreview: true;
94
104
  animatedPartialResult: true;
@@ -1,5 +1,5 @@
1
1
  import type { Component } from "../tui.js";
2
- import type { NativeToolView, RenderResultOptions } from "./renderer.js";
2
+ import type { NativeToolView, RenderResultContextOptions, RenderResultOptions } from "./renderer.js";
3
3
  import { type Theme } from "../theme/theme.js";
4
4
  import type { OutputMeta } from "./output-meta.js";
5
5
  import type { TruncationResult } from "./streaming-output.js";
@@ -42,7 +42,7 @@ export declare const globToolRenderer: {
42
42
  }>;
43
43
  details?: GlobToolDetails;
44
44
  isError?: boolean;
45
- }, options: RenderResultOptions, uiTheme: Theme, args?: GlobRenderArgs): Component;
45
+ }, options: RenderResultContextOptions, uiTheme: Theme, args?: GlobRenderArgs): Component;
46
46
  describeCall(args: GlobRenderArgs): NativeToolView;
47
47
  /**
48
48
  * Inline (§7.3 glob): `Glob “pattern” 5 files`, then the files as rows
@@ -55,7 +55,7 @@ export declare const globToolRenderer: {
55
55
  }>;
56
56
  details?: GlobToolDetails;
57
57
  isError?: boolean;
58
- }, _options: RenderResultOptions, args?: GlobRenderArgs): NativeToolView;
58
+ }, options: RenderResultContextOptions, args?: GlobRenderArgs): NativeToolView;
59
59
  mergeCallAndResult: true;
60
60
  };
61
61
  export {};
@@ -1,5 +1,5 @@
1
1
  import type { Component } from "../tui.js";
2
- import type { NativeToolView, RenderResultOptions } from "./renderer.js";
2
+ import type { NativeToolView, RenderResultContextOptions, RenderResultOptions } from "./renderer.js";
3
3
  import { type Theme } from "../theme/theme.js";
4
4
  import type { OutputMeta } from "./output-meta.js";
5
5
  import type { TruncationResult } from "./streaming-output.js";
@@ -58,7 +58,7 @@ export declare const grepToolRenderer: {
58
58
  }>;
59
59
  details?: GrepToolDetails;
60
60
  isError?: boolean;
61
- }, options: RenderResultOptions, uiTheme: Theme, args?: GrepRenderArgs): Component;
61
+ }, options: RenderResultContextOptions, uiTheme: Theme, args?: GrepRenderArgs): Component;
62
62
  describeCall(args: GrepRenderArgs): NativeToolView;
63
63
  /**
64
64
  * Inline (§7.3 grep): `Grep “pattern” 5 matches · 2 files in src`, then
@@ -110,11 +110,12 @@ export interface NumberedLine {
110
110
  * Numbered `code` for possibly non-contiguous source lines: one block per run
111
111
  * of consecutive line numbers (`start` = the run's first line, match lines
112
112
  * `mark`ed), with a `…` row wherever the numbers jump or an elision marker
113
- * (`n: null`) sits. No path header: the row or head above names the file.
113
+ * (`n: null`) sits. `path` is the file the lines come from: Tern picks their
114
+ * grammar from it and draws no header (the row or head above names the file).
114
115
  * `wrap` soft-wraps long lines instead of scrolling the block sideways.
115
116
  */
116
117
  export declare function numberedCode(lines: readonly NumberedLine[], opts?: {
117
- lang?: string;
118
+ path?: string;
118
119
  wrap?: boolean;
119
120
  }): NativeNode[];
120
121
  /**
@@ -128,7 +129,6 @@ export declare function numberedCode(lines: readonly NumberedLine[], opts?: {
128
129
  * same file row as a directory search's.
129
130
  */
130
131
  export declare function describeGroupedOutput(lines: readonly string[], options?: {
131
- lang?: (path: string) => string | undefined;
132
132
  maxFiles?: number;
133
133
  file?: string;
134
134
  }): NativeNode[];