@oh-my-pi/pi-tui 18.4.11 → 18.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +37 -0
- package/dist/types/components/editor.d.ts +1 -1
- package/dist/types/components/input.d.ts +1 -1
- package/dist/types/native/encode.d.ts +2 -1
- package/dist/types/native/node.d.ts +22 -4
- package/dist/types/overlays/jobs-panel.d.ts +1 -7
- package/dist/types/overlays/report-panel.d.ts +68 -0
- package/dist/types/overlays/thinking-selector.d.ts +2 -2
- package/dist/types/prompt/composer-cache.d.ts +0 -16
- package/dist/types/prompt/composer.d.ts +17 -7
- package/dist/types/prompt/welcome.d.ts +17 -42
- package/dist/types/status-line/context-usage.d.ts +7 -5
- package/dist/types/thinking.d.ts +1 -1
- package/dist/types/tools/task.d.ts +5 -1
- package/package.json +9 -9
- package/src/apps/git/sidebar.ts +2 -2
- package/src/components/editor.ts +2 -1
- package/src/components/input.ts +2 -1
- package/src/desktop-notify.ts +2 -1
- package/src/native/backend.ts +5 -1
- package/src/native/encode.ts +4 -2
- package/src/native/node.ts +21 -4
- package/src/native/reconcile.ts +12 -4
- package/src/overlays/jobs-panel.ts +6 -53
- package/src/overlays/plan-review-overlay.ts +15 -1
- package/src/overlays/report-panel.ts +191 -0
- package/src/overlays/thinking-selector.ts +11 -11
- package/src/prompt/composer-cache.ts +11 -92
- package/src/prompt/composer.ts +29 -27
- package/src/prompt/custom-editor.ts +8 -2
- package/src/prompt/tips.txt +4 -0
- package/src/prompt/welcome.ts +101 -372
- package/src/render/render-utils.ts +5 -1
- package/src/status-line/context-usage.ts +21 -48
- package/src/thinking.ts +1 -1
- package/src/tools/streaming-output.ts +5 -0
- package/src/tools/task.ts +6 -2
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,43 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [18.5.0] - 2026-10-03
|
|
6
|
+
|
|
7
|
+
### Breaking Changes
|
|
8
|
+
|
|
9
|
+
- `WelcomeComponent` no longer takes a model or provider: its constructor is `(version)`, and `setModel()`, `setRecentSessions()`, `setLspServers()`, `handleNativeEvent()`, `RecentSession`, `LspServerInfo`, `WELCOME_SESSION_SLOTS` and `WELCOME_LSP_SLOTS` are gone; `ComposerWelcomeUpdate` drops `modelName`/`providerName`/`recentSessions`/`lspServers`, and `ComposerCache` drops `writeWelcome()`, `writeRecentSessions()`, `writeLspServers()`, `ComposerWelcomeCache` and the `welcome`/`recentSessions`/`lspServers` fields of `ComposerStartupCache`.
|
|
10
|
+
- `renderWelcomeTip()` returns its lines without an indent, `Tip:` and the body wrapped together, for the caller to place.
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- Added `ReportPanel`, a read-only command report: a `/btw`-style titled box with an Esc hint in text mode (above the editor, or as a full-screen page whose body scrolls on the arrow/page/Home/End keys and the wheel), and natively a `/usage`-style sheet whose body the terminal scrolls once it is long, with a Close button ([#14136](https://github.com/can1357/oh-my-pi/pull/14136) by [@H4vC](https://github.com/H4vC)).
|
|
15
|
+
- Added `contextUsageHead()`, the `/context` title naming the model and its window ([#14136](https://github.com/can1357/oh-my-pi/pull/14136) by [@H4vC](https://github.com/H4vC)).
|
|
16
|
+
- Added `Composer.rowsBelow()`, the rows the chrome under a below-transcript root took in the last frame ([#14136](https://github.com/can1357/oh-my-pi/pull/14136) by [@H4vC](https://github.com/H4vC)).
|
|
17
|
+
- Added `Composer.pinInputToBottom()`, which keeps the input on the bottom row after chrome above the editor closes when rows it displaced went to scrollback ([#14136](https://github.com/can1357/oh-my-pi/pull/14136) by [@H4vC](https://github.com/H4vC)).
|
|
18
|
+
- Added a repeatable native `reveal` (`{ at, n }`): a described node scrolls into view again whenever its `n` changes, without being re-added.
|
|
19
|
+
|
|
20
|
+
### Changed
|
|
21
|
+
|
|
22
|
+
- `ContextUsageView` is now a bare report body without its own title, rules or card; `setBreakdown()` was removed ([#14136](https://github.com/can1357/oh-my-pi/pull/14136) by [@H4vC](https://github.com/H4vC)).
|
|
23
|
+
- The terminal welcome banner is the gradient logo beside the `omp` wordmark with the version under it and the tip, centered in the terminal; the logo stands alone when the lockup does not fit, and the tip drops below 50 columns. It no longer greets with "Welcome back!", natively either.
|
|
24
|
+
|
|
25
|
+
### Fixed
|
|
26
|
+
|
|
27
|
+
- Fixed tool previews on Windows showing a working directory on another drive as a raw absolute path instead of its home-shortened `~/…` form.
|
|
28
|
+
- Fixed pasted drive-less `file:///…` URLs (forwarded from a macOS pasteboard or remote session) staying undecoded on Windows instead of loading as image paths.
|
|
29
|
+
- Fixed an output artifact whose file cannot be opened (e.g. a directory in the way) being reported on Windows as a write failure and retried later, instead of a terminal open failure.
|
|
30
|
+
- Fixed plan review's Contents in Tern: clicking an entry, or moving through them with the arrow keys, now scrolls the plan to that section.
|
|
31
|
+
|
|
32
|
+
### Removed
|
|
33
|
+
|
|
34
|
+
- Removed `JobsPanel`, the `/jobs` transcript block; `/jobs` now opens `JobsSheet` natively ([#14138](https://github.com/can1357/oh-my-pi/pull/14138) by [@H4vC](https://github.com/H4vC)).
|
|
35
|
+
|
|
36
|
+
## [18.4.12] - 2026-10-02
|
|
37
|
+
|
|
38
|
+
### Changed
|
|
39
|
+
|
|
40
|
+
- Changed Ctrl+Z in Tern's native composer to undo the last edit (TSP `undo` event) instead of suspending
|
|
41
|
+
|
|
5
42
|
## [18.4.11] - 2026-10-02
|
|
6
43
|
|
|
7
44
|
### Added
|
|
@@ -296,7 +296,7 @@ export declare class Editor implements Component, Focusable {
|
|
|
296
296
|
submit(): void;
|
|
297
297
|
/** Insert text at the current cursor position */
|
|
298
298
|
insertText(text: string): void;
|
|
299
|
-
/** Terminal-side selection edits on the `editor` node (see {@link applyHostEdit}). */
|
|
299
|
+
/** Terminal-side selection edits and undo on the `editor` node (see {@link applyHostEdit}). */
|
|
300
300
|
handleNativeEvent(event: NativeUiEvent): void;
|
|
301
301
|
/**
|
|
302
302
|
* Apply an edit the terminal made over its own selection (TSP `edit`):
|
|
@@ -39,7 +39,7 @@ export declare class Input implements Component, Focusable {
|
|
|
39
39
|
/** Apply terminal paste semantics to text from non-bracketed paste transports
|
|
40
40
|
* (e.g. kitty's OSC 5522 enhanced clipboard read). Mirrors `Editor.pasteText`. */
|
|
41
41
|
pasteText(text: string): void;
|
|
42
|
-
/** Terminal-side selection edits on the `input` node (see {@link applyHostEdit}). */
|
|
42
|
+
/** Terminal-side selection edits and undo on the `input` node (see {@link applyHostEdit}). */
|
|
43
43
|
handleNativeEvent(event: NativeUiEvent): void;
|
|
44
44
|
/**
|
|
45
45
|
* Apply an edit the terminal made over its own selection (TSP `edit`):
|
|
@@ -27,7 +27,8 @@ export declare function encodeTspJson(verb: TspVerb, value: unknown, params?: Ts
|
|
|
27
27
|
/**
|
|
28
28
|
* The `hello` query; callers follow it with a DA1 sentinel. `features: ["edit"]`
|
|
29
29
|
* tells the terminal that omp applies its `edit` events (TSP §8.5), so it may keep a
|
|
30
|
-
* native selection in omp's editors; without it, every key stays omp's.
|
|
30
|
+
* native selection in omp's editors; without it, every key stays omp's. `"undo"`
|
|
31
|
+
* says omp applies `undo` events, so the terminal may turn ⌃Z in a field into one.
|
|
31
32
|
*/
|
|
32
33
|
export declare function encodeTspHelloQuery(version?: string): string;
|
|
33
34
|
/** One decoded APC message: verb, parameters and raw body. */
|
|
@@ -28,10 +28,12 @@ export type NativeNode = {
|
|
|
28
28
|
*/
|
|
29
29
|
readonly key?: string;
|
|
30
30
|
/**
|
|
31
|
-
* Scroll the node into view, placed like the `reveal` op
|
|
32
|
-
* added
|
|
31
|
+
* Scroll the node into view, placed like the `reveal` op. A placement
|
|
32
|
+
* reveals it when it is added: key a node by what it points at to
|
|
33
|
+
* reveal it again on a move. A {@link NativeReveal} reveals it whenever
|
|
34
|
+
* its `n` differs from the previous description of the same node.
|
|
33
35
|
*/
|
|
34
|
-
readonly reveal?:
|
|
36
|
+
readonly reveal?: NativeRevealAt | NativeReveal;
|
|
35
37
|
/**
|
|
36
38
|
* Keyboard scrolling forwarded to the terminal (PgUp/PgDn/End reach the
|
|
37
39
|
* program): moves the scroller at or above the node by `by` whenever
|
|
@@ -42,6 +44,17 @@ export type NativeNode = {
|
|
|
42
44
|
readonly scroll?: NativeScroll;
|
|
43
45
|
};
|
|
44
46
|
}[TspKind];
|
|
47
|
+
/** Where a revealed node lands in its scroller. */
|
|
48
|
+
export type NativeRevealAt = "start" | "end" | "nearest";
|
|
49
|
+
/**
|
|
50
|
+
* A repeatable {@link NativeNode.reveal}: bump `n` to bring an existing node
|
|
51
|
+
* into view again (a Contents entry jumping to its section). A freshly added
|
|
52
|
+
* node is not revealed.
|
|
53
|
+
*/
|
|
54
|
+
export interface NativeReveal {
|
|
55
|
+
readonly at: NativeRevealAt;
|
|
56
|
+
readonly n: number;
|
|
57
|
+
}
|
|
45
58
|
/** A {@link NativeNode.scroll} request. */
|
|
46
59
|
export interface NativeScroll {
|
|
47
60
|
readonly by: TspScrollBy;
|
|
@@ -117,7 +130,12 @@ export type NativeUiEvent = {
|
|
|
117
130
|
| ({
|
|
118
131
|
readonly type: "edit";
|
|
119
132
|
readonly key: string;
|
|
120
|
-
} & NativeTextEdit)
|
|
133
|
+
} & NativeTextEdit)
|
|
134
|
+
/** Undo the last change to an `editor`/`input` node's text (the terminal's ⌃Z); a no-op with no history. */
|
|
135
|
+
| {
|
|
136
|
+
readonly type: "undo";
|
|
137
|
+
readonly key: string;
|
|
138
|
+
};
|
|
121
139
|
/**
|
|
122
140
|
* A primitive edit the terminal made over its own text selection (cut,
|
|
123
141
|
* typing, Backspace/Delete or paste over it, or collapsing it). Offsets are
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { Component } from "../tui.js";
|
|
2
2
|
import type { DescribeContext, NativeNode, NativeUiEvent } from "../native/node.js";
|
|
3
3
|
/** One async job as the session snapshots it. */
|
|
4
4
|
export interface JobsPanelJob {
|
|
@@ -40,12 +40,6 @@ export interface JobsSheetSource {
|
|
|
40
40
|
/** Dismiss the sheet. */
|
|
41
41
|
close(): void;
|
|
42
42
|
}
|
|
43
|
-
/** The `/jobs` block: `ansi` renders in the terminal, the snapshot describes the native frame. */
|
|
44
|
-
export declare class JobsPanel extends Container {
|
|
45
|
-
#private;
|
|
46
|
-
constructor(snapshot: JobsPanelSnapshot, nowMs: number, ansi: readonly Component[]);
|
|
47
|
-
describe(cx: DescribeContext): NativeNode;
|
|
48
|
-
}
|
|
49
43
|
/**
|
|
50
44
|
* The jobs pill's sheet: a centred `lg` glass sheet titled Background jobs.
|
|
51
45
|
* A selectable list of every job (running first) sits over the selected
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import type { TspText } from "@oh-my-pi/pi-wire";
|
|
2
|
+
import { OverlayPanel } from "../chrome/overlay-box.js";
|
|
3
|
+
import type { NativeNode, NativeUiEvent } from "../native/node.js";
|
|
4
|
+
import type { Component } from "../tui.js";
|
|
5
|
+
/** Options of a {@link ReportPanel}. */
|
|
6
|
+
export interface ReportPanelOptions {
|
|
7
|
+
/** Plain title: the text-mode border title, and the native sheet head unless {@link head} is given. */
|
|
8
|
+
readonly title: string;
|
|
9
|
+
/** Styled native sheet head. */
|
|
10
|
+
readonly head?: TspText;
|
|
11
|
+
/** The read-only report; it draws no frame or title of its own. */
|
|
12
|
+
readonly body: Component;
|
|
13
|
+
/**
|
|
14
|
+
* Display form of the key that dismisses the report while it sits above the
|
|
15
|
+
* editor (the editor's interrupt key, which routes to it). Once the panel
|
|
16
|
+
* holds focus ({@link ReportPanel.holdFocus}) the hint shows the key its own
|
|
17
|
+
* input closes on instead.
|
|
18
|
+
*/
|
|
19
|
+
readonly closeKey: string;
|
|
20
|
+
/** The focused panel (native sheet, text-mode full-screen page) closes on Esc / its Close button: this runs. */
|
|
21
|
+
readonly onClose: () => void;
|
|
22
|
+
/**
|
|
23
|
+
* Most rows the text-mode panel may take, borders included (the screen rows
|
|
24
|
+
* left above the editor); a taller report scrolls inside it. `undefined`
|
|
25
|
+
* leaves it uncapped.
|
|
26
|
+
*/
|
|
27
|
+
readonly maxRows?: () => number | undefined;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* A read-only command report (`/changelog`, `/context`, `/tools`, …).
|
|
31
|
+
*
|
|
32
|
+
* Text mode draws a titled box with the body and an Esc hint: above the editor
|
|
33
|
+
* like the `/btw` panel while it fits there (the editor keeps focus and its
|
|
34
|
+
* Esc takes it away), or as a full-screen page on the alternate screen when it
|
|
35
|
+
* is taller, whose body scrolls on the arrow/page/Home/End keys and the wheel.
|
|
36
|
+
* Natively it is a sheet like `/usage`: a centred `lg` glass sheet titled by
|
|
37
|
+
* the report whose body the terminal scrolls (wheel, and the same keys
|
|
38
|
+
* forwarded as scroll requests), then a Close button; Esc closes it.
|
|
39
|
+
*/
|
|
40
|
+
export declare class ReportPanel extends OverlayPanel {
|
|
41
|
+
#private;
|
|
42
|
+
readonly nativeOverlay: NonNullable<Component["nativeOverlay"]>;
|
|
43
|
+
constructor(options: ReportPanelOptions);
|
|
44
|
+
/**
|
|
45
|
+
* The panel is shown with focus (native sheet, text-mode full-screen page):
|
|
46
|
+
* its own {@link handleInput} closes it, so the hint names that key.
|
|
47
|
+
*/
|
|
48
|
+
holdFocus(): void;
|
|
49
|
+
/**
|
|
50
|
+
* Text mode: cap the box to {@link ReportPanelOptions.maxRows}, scrolling a
|
|
51
|
+
* taller body. The cap is a hard limit: when a resize leaves fewer rows than
|
|
52
|
+
* the box's chrome needs, its bottom (the hint and closing border) is cut
|
|
53
|
+
* rather than spilling over the editor.
|
|
54
|
+
*/
|
|
55
|
+
render(width: number): readonly string[];
|
|
56
|
+
/** Text mode: rows the whole box takes at `width` when nothing caps it. */
|
|
57
|
+
heightAt(width: number): number;
|
|
58
|
+
/** The sheet body (the overlay is the frame, and its body the scroller): the report, then Close (Esc). */
|
|
59
|
+
describe(): NativeNode;
|
|
60
|
+
invalidate(): void;
|
|
61
|
+
/**
|
|
62
|
+
* Focused (the native sheet, or the text-mode full-screen page): Esc closes;
|
|
63
|
+
* the arrow, page, Home and End keys and the wheel scroll the body.
|
|
64
|
+
*/
|
|
65
|
+
handleInput(data: string): void;
|
|
66
|
+
/** Close runs what Esc runs. */
|
|
67
|
+
handleNativeEvent(event: NativeUiEvent): void;
|
|
68
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type ConfiguredThinkingLevel } from "../thinking.js";
|
|
2
2
|
import { SelectList, type SgrMouseEvent } from "../index.js";
|
|
3
3
|
import { OverlayPanel } from "../chrome/overlay-box.js";
|
|
4
4
|
import type { DescribeContext, NativeNode, NativeUiEvent } from "../native/node.js";
|
|
@@ -7,7 +7,7 @@ import type { DescribeContext, NativeNode, NativeUiEvent } from "../native/node.
|
|
|
7
7
|
*/
|
|
8
8
|
export declare class ThinkingSelectorComponent extends OverlayPanel {
|
|
9
9
|
#private;
|
|
10
|
-
constructor(currentLevel:
|
|
10
|
+
constructor(currentLevel: ConfiguredThinkingLevel | undefined, availableLevels: ConfiguredThinkingLevel[], onSelect: (level: ConfiguredThinkingLevel) => void, onCancel: () => void);
|
|
11
11
|
describe(cx: DescribeContext): NativeNode | null;
|
|
12
12
|
/** Picker pointer events drive the list exactly as its keys do. */
|
|
13
13
|
handleNativeEvent(event: NativeUiEvent): void;
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import type { LspServerInfo, RecentSession } from "./welcome.js";
|
|
2
1
|
import type { ComposerPreferences, ComposerStatusCache } from "./composer.js";
|
|
3
2
|
import type { SymbolPreset } from "../theme/theme.js";
|
|
4
3
|
/** Theme inputs cached from the last resolved settings load for stable prepaint colors. */
|
|
@@ -8,19 +7,10 @@ export interface ComposerThemePreferences {
|
|
|
8
7
|
readonly darkTheme?: string;
|
|
9
8
|
readonly lightTheme?: string;
|
|
10
9
|
}
|
|
11
|
-
/** Last authoritative model labels shown in the welcome component. */
|
|
12
|
-
export interface ComposerWelcomeCache {
|
|
13
|
-
readonly modelName: string;
|
|
14
|
-
readonly providerName: string;
|
|
15
|
-
}
|
|
16
10
|
/** Speculative composer state read before the settings/session graph is available. */
|
|
17
11
|
export interface ComposerStartupCache {
|
|
18
12
|
readonly preferences?: ComposerPreferences;
|
|
19
13
|
readonly theme?: ComposerThemePreferences;
|
|
20
|
-
readonly welcome?: ComposerWelcomeCache;
|
|
21
|
-
readonly recentSessions: RecentSession[];
|
|
22
|
-
/** `null` when the last run had LSP disabled. */
|
|
23
|
-
readonly lspServers: LspServerInfo[] | null;
|
|
24
14
|
readonly status?: ComposerStatusCache;
|
|
25
15
|
}
|
|
26
16
|
/**
|
|
@@ -43,12 +33,6 @@ export declare class ComposerCache {
|
|
|
43
33
|
read(cwd: string): ComposerStartupCache;
|
|
44
34
|
/** Resolved theme and composer settings for the next prepaint. */
|
|
45
35
|
writeUi(cwd: string, preferences: ComposerPreferences, theme: ComposerThemePreferences): void;
|
|
46
|
-
/** Authoritative model/provider labels for the next welcome prepaint. */
|
|
47
|
-
writeWelcome(cwd: string, welcome: ComposerWelcomeCache): void;
|
|
48
|
-
/** The latest recent-session rows (first four). */
|
|
49
|
-
writeRecentSessions(cwd: string, sessions: readonly RecentSession[]): void;
|
|
50
|
-
/** The latest detected project LSP rows; `null` records that LSP is disabled. */
|
|
51
|
-
writeLspServers(cwd: string, servers: readonly LspServerInfo[] | null): void;
|
|
52
36
|
/** Status-bar inputs for the next prepaint's startup status line. */
|
|
53
37
|
writeStatus(cwd: string, status: ComposerStatusCache): void;
|
|
54
38
|
close(): void;
|
|
@@ -6,7 +6,7 @@ import { type Component, type ResizeScrollbackMode, type TerminalFramePlan, type
|
|
|
6
6
|
import type { NativeSurface, NativeSurfaceProvider } from "../native/node.js";
|
|
7
7
|
import { CustomEditor } from "./custom-editor.js";
|
|
8
8
|
import type { WordCompletionMethod } from "./word-completion.js";
|
|
9
|
-
import {
|
|
9
|
+
import { WelcomeComponent } from "./welcome.js";
|
|
10
10
|
/** Live settings that affect the composer before and after session adoption. */
|
|
11
11
|
export interface ComposerPreferences {
|
|
12
12
|
readonly quiet: boolean;
|
|
@@ -25,11 +25,6 @@ export declare const COMPOSER_DEFAULTS: ComposerPreferences;
|
|
|
25
25
|
/** Welcome data that can be supplied initially or patched as startup resolves it. */
|
|
26
26
|
export interface ComposerWelcomeUpdate {
|
|
27
27
|
readonly version?: string;
|
|
28
|
-
readonly modelName?: string;
|
|
29
|
-
readonly providerName?: string;
|
|
30
|
-
readonly recentSessions?: readonly RecentSession[];
|
|
31
|
-
/** Detected project servers; `null` means LSP is disabled and hides the welcome section. */
|
|
32
|
-
readonly lspServers?: readonly LspServerInfo[] | null;
|
|
33
28
|
}
|
|
34
29
|
/**
|
|
35
30
|
* Status-bar inputs persisted by the last session. The first frame renders
|
|
@@ -122,6 +117,21 @@ export declare class Composer implements TerminalFrameProvider, NativeSurfacePro
|
|
|
122
117
|
#private;
|
|
123
118
|
readonly ui: TUI;
|
|
124
119
|
constructor(options?: ComposerOptions);
|
|
120
|
+
/**
|
|
121
|
+
* Rows the below-transcript chrome under `root` (editor, status line, …)
|
|
122
|
+
* took in the last frame, so a root that grows upward can cap itself to
|
|
123
|
+
* the screen rows left above them; `undefined` before `root` was laid out.
|
|
124
|
+
*/
|
|
125
|
+
rowsBelow(root: Component): number | undefined;
|
|
126
|
+
/**
|
|
127
|
+
* Keep the input on the bottom row while the live rows cannot fill the
|
|
128
|
+
* screen, as after an inline decision panel closes. A tall block that just
|
|
129
|
+
* left the chrome above the editor (a command report) may have scrolled
|
|
130
|
+
* rows into native history that cannot be pulled back; without the pin the
|
|
131
|
+
* editor would jump up to where the shorter frame now ends. The pin lifts
|
|
132
|
+
* once live rows fill the screen again.
|
|
133
|
+
*/
|
|
134
|
+
pinInputToBottom(): void;
|
|
125
135
|
/** Compose the bounded mutable viewport and the next ordered history append. */
|
|
126
136
|
renderFrame(viewport: ViewportSize): TerminalFramePlan;
|
|
127
137
|
/**
|
|
@@ -164,7 +174,7 @@ export declare class Composer implements TerminalFrameProvider, NativeSurfacePro
|
|
|
164
174
|
enableInput(): void;
|
|
165
175
|
/** Apply settings changes without replacing the editor or welcome component. */
|
|
166
176
|
setPreferences(update: Partial<ComposerPreferences>): void;
|
|
167
|
-
/** Patch welcome data in place as
|
|
177
|
+
/** Patch welcome data in place as version, session, and project discovery complete. */
|
|
168
178
|
updateWelcome(update: ComposerWelcomeUpdate): void;
|
|
169
179
|
/** Replace optional header content around the stable welcome scene. */
|
|
170
180
|
setHeaderExtras(before: readonly Component[], after: readonly Component[]): void;
|
|
@@ -1,58 +1,36 @@
|
|
|
1
|
-
import type { DescribeContext, NativeNode
|
|
1
|
+
import type { DescribeContext, NativeNode } from "../native/node.js";
|
|
2
2
|
import type { Component } from "../tui.js";
|
|
3
|
-
/**
|
|
4
|
-
* Fixed number of session rows in the welcome box so its height stays stable
|
|
5
|
-
* across recent-session updates.
|
|
6
|
-
*/
|
|
7
|
-
export declare const WELCOME_SESSION_SLOTS = 4;
|
|
8
|
-
/**
|
|
9
|
-
* Fixed number of LSP-server rows, for the same reason. Overflow is sliced so
|
|
10
|
-
* the box height is constant regardless of how many servers a project has.
|
|
11
|
-
*/
|
|
12
|
-
export declare const WELCOME_LSP_SLOTS = 4;
|
|
13
3
|
/** Pick a tip from `tips`, biased toward "[NEW]" tips by {@link NEW_TIP_WEIGHT};
|
|
14
4
|
* `r` is a uniform sample in [0, 1). Returns "" when `tips` is empty.
|
|
15
5
|
* Exported for tests. */
|
|
16
6
|
export declare function pickWeightedTip(tips: readonly string[], r: number): string;
|
|
17
|
-
export declare function renderWelcomeTip(tip: string, boxWidth: number, phase?: number): string[];
|
|
18
|
-
export interface RecentSession {
|
|
19
|
-
name: string;
|
|
20
|
-
timeAgo: string;
|
|
21
|
-
/** Session file; a native click on the row resumes it. */
|
|
22
|
-
path?: string;
|
|
23
|
-
}
|
|
24
|
-
export interface LspServerInfo {
|
|
25
|
-
name: string;
|
|
26
|
-
status: "ready" | "error" | "connecting" | "available";
|
|
27
|
-
fileTypes: string[];
|
|
28
|
-
}
|
|
29
7
|
/**
|
|
30
|
-
*
|
|
8
|
+
* The welcome tip as lines of at most `width` columns: `Tip:` and the body
|
|
9
|
+
* wrapped together, with no indent, so the banner can center each line.
|
|
10
|
+
* `[]` when `width` leaves no room for a useful line.
|
|
11
|
+
*/
|
|
12
|
+
export declare function renderWelcomeTip(tip: string, width: number, phase?: number): string[];
|
|
13
|
+
/**
|
|
14
|
+
* The session's welcome banner. In a terminal: the gradient logo beside the
|
|
15
|
+
* `omp` wordmark with the version under it (the logo alone when the lockup does
|
|
16
|
+
* not fit) and the tip of the session (dropped below {@link TIP_MIN_COLUMNS}
|
|
17
|
+
* columns). Natively: a card with the same logo, wordmark, version and tip
|
|
18
|
+
* ({@link WelcomeComponent.describe}).
|
|
31
19
|
*/
|
|
32
20
|
export declare class WelcomeComponent implements Component {
|
|
33
21
|
#private;
|
|
34
22
|
private version;
|
|
35
|
-
|
|
36
|
-
private providerName;
|
|
37
|
-
private recentSessions;
|
|
38
|
-
/** Detected project servers; `null` means LSP is disabled and hides the section. */
|
|
39
|
-
private lspServers;
|
|
40
|
-
constructor(version: string, modelName: string, providerName: string, recentSessions?: RecentSession[],
|
|
41
|
-
/** Detected project servers; `null` means LSP is disabled and hides the section. */
|
|
42
|
-
lspServers?: LspServerInfo[] | null);
|
|
23
|
+
constructor(version: string);
|
|
43
24
|
get tip(): string | undefined;
|
|
44
25
|
invalidate(): void;
|
|
45
26
|
/**
|
|
46
|
-
* A `card` (`omp.welcome`)
|
|
47
|
-
* (`omp.welcome.
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
* carry the look (gradient logo, type scale, column hairline); a "[NEW]" tip
|
|
27
|
+
* A `card` (`omp.welcome`) mirroring the terminal banner: the lockup
|
|
28
|
+
* (`omp.welcome.lockup`: the terminal's builtin `omp` mark, which it animates,
|
|
29
|
+
* beside the wordmark with the version under it) and the tip of the session.
|
|
30
|
+
* Roles carry the look (gradient logo, type scale); a "[NEW]" tip
|
|
51
31
|
* carries a terminal-clocked shimmering tag.
|
|
52
32
|
*/
|
|
53
33
|
describe(_cx: DescribeContext): NativeNode;
|
|
54
|
-
/** A click on a recent session resumes it. */
|
|
55
|
-
handleNativeEvent(event: NativeUiEvent): void;
|
|
56
34
|
/** The intro keeps the welcome block mutable; settling lets it retire to history. */
|
|
57
35
|
isTranscriptBlockFinalized(): boolean;
|
|
58
36
|
/**
|
|
@@ -71,9 +49,6 @@ export declare class WelcomeComponent implements Component {
|
|
|
71
49
|
stopIntro(): void;
|
|
72
50
|
/** Update the version embedded in the welcome border title. */
|
|
73
51
|
setVersion(version: string): void;
|
|
74
|
-
setModel(modelName: string, providerName: string): void;
|
|
75
|
-
setRecentSessions(sessions: RecentSession[]): void;
|
|
76
|
-
setLspServers(servers: LspServerInfo[] | null): void;
|
|
77
52
|
render(termWidth: number): readonly string[];
|
|
78
53
|
}
|
|
79
54
|
/** Block-grid brand mark shared by the welcome and setup surfaces. */
|
|
@@ -3,6 +3,7 @@ import type { CompactionSettings } from "@oh-my-pi/pi-agent-core/compaction";
|
|
|
3
3
|
import type { Tool as AiTool, Model } from "@oh-my-pi/pi-ai";
|
|
4
4
|
import type { Theme } from "../theme/index.js";
|
|
5
5
|
import { Container } from "../tui.js";
|
|
6
|
+
import type { TspText } from "@oh-my-pi/pi-wire";
|
|
6
7
|
import type { DescribeContext, NativeNode } from "../native/node.js";
|
|
7
8
|
interface ContextSkill {
|
|
8
9
|
readonly name: string;
|
|
@@ -154,6 +155,8 @@ export declare function computeNonMessageBreakdown(session: NonMessageTokenSourc
|
|
|
154
155
|
* session and model.
|
|
155
156
|
*/
|
|
156
157
|
export declare function computeContextBreakdown(session: ContextUsageSession, options: ContextUsageOptions): ContextBreakdown;
|
|
158
|
+
/** The `/context` title: the model and its window once a model is selected. */
|
|
159
|
+
export declare function contextUsageHead(breakdown: ContextBreakdown): TspText;
|
|
157
160
|
/**
|
|
158
161
|
* Native context-usage panel for terminals without `meter`: the cell grid as
|
|
159
162
|
* unwrapped styled rows beside the legend. The terminal places the legend
|
|
@@ -161,15 +164,14 @@ export declare function computeContextBreakdown(session: ContextUsageSession, op
|
|
|
161
164
|
*/
|
|
162
165
|
export declare function describeContextUsage(breakdown: ContextBreakdown): NativeNode;
|
|
163
166
|
/**
|
|
164
|
-
* The `/context`
|
|
165
|
-
*
|
|
166
|
-
*
|
|
167
|
+
* The `/context` report body, without a frame or title of its own (the panel
|
|
168
|
+
* showing it is titled {@link contextUsageHead}): ANSI renders the cell grid
|
|
169
|
+
* beside the legend; natively it is drawn with `meter`s where the terminal has
|
|
170
|
+
* them and as the glyph grid otherwise.
|
|
167
171
|
*/
|
|
168
172
|
export declare class ContextUsageView extends Container {
|
|
169
173
|
#private;
|
|
170
174
|
constructor(breakdown: ContextBreakdown, theme: Theme);
|
|
171
|
-
/** Replace the shown breakdown in place, refreshing both the ANSI and native views. */
|
|
172
|
-
setBreakdown(breakdown: ContextBreakdown): void;
|
|
173
175
|
describe(cx: DescribeContext): NativeNode;
|
|
174
176
|
}
|
|
175
177
|
/**
|
package/dist/types/thinking.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ import { ThinkingLevel } from "@oh-my-pi/pi-agent-core/thinking";
|
|
|
4
4
|
import { Effort } from "@oh-my-pi/pi-catalog/effort";
|
|
5
5
|
import type { Model } from "@oh-my-pi/pi-catalog/types";
|
|
6
6
|
/** Thinking selectors accepted by CLI inputs, in display order. */
|
|
7
|
-
export declare const CLI_THINKING_LEVELS: readonly
|
|
7
|
+
export declare const CLI_THINKING_LEVELS: readonly ConfiguredThinkingLevel[];
|
|
8
8
|
/**
|
|
9
9
|
* Metadata used to render thinking selector values in the coding-agent UI.
|
|
10
10
|
*/
|
|
@@ -108,6 +108,8 @@ export interface TaskItem {
|
|
|
108
108
|
solutionSpace?: string;
|
|
109
109
|
/** Per-spawn thinking effort: lowest/middle/highest level the resolved model supports. Overrides the agent's default selector (e.g. `auto`). */
|
|
110
110
|
effort?: "lo" | "med" | "hi";
|
|
111
|
+
/** Per-spawn model selector or ordered selector array; overrides agent and settings preferences. */
|
|
112
|
+
model?: string | string[];
|
|
111
113
|
/** Caller-provided output schema; its presence overrides the selected agent's schema. */
|
|
112
114
|
outputSchema?: unknown;
|
|
113
115
|
/** Validation behavior for a caller-provided or inherited output schema. */
|
|
@@ -134,6 +136,8 @@ export interface TaskParams {
|
|
|
134
136
|
solutionSpace?: string;
|
|
135
137
|
/** Per-spawn thinking effort (flat form): lowest/middle/highest level the resolved model supports. */
|
|
136
138
|
effort?: "lo" | "med" | "hi";
|
|
139
|
+
/** Per-spawn model selector or ordered selector array; overrides agent and settings preferences. */
|
|
140
|
+
model?: string | string[];
|
|
137
141
|
/** Caller-provided output schema; its presence overrides the selected agent's schema. */
|
|
138
142
|
outputSchema?: unknown;
|
|
139
143
|
/** Validation behavior for a caller-provided or inherited output schema. */
|
|
@@ -255,7 +259,7 @@ export interface AgentProgress {
|
|
|
255
259
|
resolvedModelRoute?: string;
|
|
256
260
|
/** True when a live advisor was attached to this run's session, not merely enabled in settings. */
|
|
257
261
|
advisor?: boolean;
|
|
258
|
-
/** The agent's latest self-estimate of task completion (0–100), from the periodic `task.
|
|
262
|
+
/** The agent's latest self-estimate of task completion (0–100), from the periodic `task.completionProbe` side request. */
|
|
259
263
|
completionPercent?: number;
|
|
260
264
|
/** Data extracted by registered subprocess tool handlers (keyed by tool name) */
|
|
261
265
|
extractedToolData?: Record<string, unknown[]>;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "@oh-my-pi/pi-tui",
|
|
4
|
-
"version": "18.
|
|
4
|
+
"version": "18.5.0",
|
|
5
5
|
"description": "Terminal User Interface library with differential rendering for efficient text-based applications",
|
|
6
6
|
"homepage": "https://omp.sh",
|
|
7
7
|
"author": {
|
|
@@ -41,14 +41,14 @@
|
|
|
41
41
|
"gen:glyphs": "bun scripts/gen-glyphs.ts"
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
|
-
"@oh-my-pi/omptype": "18.
|
|
45
|
-
"@oh-my-pi/pi-agent-core": "18.
|
|
46
|
-
"@oh-my-pi/pi-ai": "18.
|
|
47
|
-
"@oh-my-pi/pi-catalog": "18.
|
|
48
|
-
"@oh-my-pi/pi-natives": "18.
|
|
49
|
-
"@oh-my-pi/pi-utils": "18.
|
|
50
|
-
"@oh-my-pi/pi-wire": "18.
|
|
51
|
-
"@oh-my-pi/snapcompact": "18.
|
|
44
|
+
"@oh-my-pi/omptype": "18.5.0",
|
|
45
|
+
"@oh-my-pi/pi-agent-core": "18.5.0",
|
|
46
|
+
"@oh-my-pi/pi-ai": "18.5.0",
|
|
47
|
+
"@oh-my-pi/pi-catalog": "18.5.0",
|
|
48
|
+
"@oh-my-pi/pi-natives": "18.5.0",
|
|
49
|
+
"@oh-my-pi/pi-utils": "18.5.0",
|
|
50
|
+
"@oh-my-pi/pi-wire": "18.5.0",
|
|
51
|
+
"@oh-my-pi/snapcompact": "18.5.0"
|
|
52
52
|
},
|
|
53
53
|
"devDependencies": {
|
|
54
54
|
"kitty-vt-wasm": "^0.2.0"
|
package/src/apps/git/sidebar.ts
CHANGED
|
@@ -1007,7 +1007,7 @@ export class Sidebar {
|
|
|
1007
1007
|
* text field being edited. False when not the sidebar's event.
|
|
1008
1008
|
*/
|
|
1009
1009
|
handleNativeEvent(event: NativeUiEvent): boolean {
|
|
1010
|
-
if (event.type === "edit") {
|
|
1010
|
+
if (event.type === "edit" || event.type === "undo") {
|
|
1011
1011
|
const editing = this.editing ? this.selected?.kind : undefined;
|
|
1012
1012
|
const field =
|
|
1013
1013
|
editing === "summary"
|
|
@@ -1017,7 +1017,7 @@ export class Sidebar {
|
|
|
1017
1017
|
: editing === "description"
|
|
1018
1018
|
? this.description
|
|
1019
1019
|
: undefined;
|
|
1020
|
-
field?.
|
|
1020
|
+
field?.handleNativeEvent(event);
|
|
1021
1021
|
return field !== undefined;
|
|
1022
1022
|
}
|
|
1023
1023
|
if (event.type === "select" || event.type === "activate") {
|
package/src/components/editor.ts
CHANGED
|
@@ -2862,9 +2862,10 @@ export class Editor implements Component, Focusable {
|
|
|
2862
2862
|
this.#insertTextAtCursor(text);
|
|
2863
2863
|
}
|
|
2864
2864
|
|
|
2865
|
-
/** Terminal-side selection edits on the `editor` node (see {@link applyHostEdit}). */
|
|
2865
|
+
/** Terminal-side selection edits and undo on the `editor` node (see {@link applyHostEdit}). */
|
|
2866
2866
|
handleNativeEvent(event: NativeUiEvent): void {
|
|
2867
2867
|
if (event.type === "edit") this.applyHostEdit(event);
|
|
2868
|
+
else if (event.type === "undo") this.#applyUndo();
|
|
2868
2869
|
}
|
|
2869
2870
|
|
|
2870
2871
|
/**
|
package/src/components/input.ts
CHANGED
|
@@ -284,9 +284,10 @@ export class Input implements Component, Focusable {
|
|
|
284
284
|
this.#handlePaste(text);
|
|
285
285
|
}
|
|
286
286
|
|
|
287
|
-
/** Terminal-side selection edits on the `input` node (see {@link applyHostEdit}). */
|
|
287
|
+
/** Terminal-side selection edits and undo on the `input` node (see {@link applyHostEdit}). */
|
|
288
288
|
handleNativeEvent(event: NativeUiEvent): void {
|
|
289
289
|
if (event.type === "edit") this.applyHostEdit(event);
|
|
290
|
+
else if (event.type === "undo") this.#undo();
|
|
290
291
|
}
|
|
291
292
|
|
|
292
293
|
/**
|
package/src/desktop-notify.ts
CHANGED
|
@@ -50,7 +50,8 @@ export function hasLinuxDesktopSession(
|
|
|
50
50
|
if (platform !== "linux") return false;
|
|
51
51
|
if (env.DBUS_SESSION_BUS_ADDRESS) return true;
|
|
52
52
|
const runtimeDir = env.XDG_RUNTIME_DIR;
|
|
53
|
-
|
|
53
|
+
// Only reached for Linux, so join with POSIX separators regardless of the host.
|
|
54
|
+
return Boolean(runtimeDir && fileExists(path.posix.join(runtimeDir, "bus")));
|
|
54
55
|
}
|
|
55
56
|
|
|
56
57
|
/**
|
package/src/native/backend.ts
CHANGED
|
@@ -671,6 +671,7 @@ export class NativeBackend {
|
|
|
671
671
|
case "action":
|
|
672
672
|
case "change":
|
|
673
673
|
case "edit":
|
|
674
|
+
case "undo":
|
|
674
675
|
this.#routeUiEvent(event);
|
|
675
676
|
return;
|
|
676
677
|
case "focus": {
|
|
@@ -687,7 +688,7 @@ export class NativeBackend {
|
|
|
687
688
|
}
|
|
688
689
|
|
|
689
690
|
#routeUiEvent(
|
|
690
|
-
event: Extract<TspEvent, { ev: "toggle" | "select" | "activate" | "action" | "change" | "edit" }>,
|
|
691
|
+
event: Extract<TspEvent, { ev: "toggle" | "select" | "activate" | "action" | "change" | "edit" | "undo" }>,
|
|
691
692
|
): void {
|
|
692
693
|
const reconciler = this.#surfaceFor(event.sf)?.reconciler;
|
|
693
694
|
const target = reconciler?.target(event.id);
|
|
@@ -721,6 +722,9 @@ export class NativeBackend {
|
|
|
721
722
|
ui = { type: "edit", key: target.keypath, from, to, text, cursor, len };
|
|
722
723
|
break;
|
|
723
724
|
}
|
|
725
|
+
case "undo":
|
|
726
|
+
ui = { type: "undo", key: target.keypath };
|
|
727
|
+
break;
|
|
724
728
|
}
|
|
725
729
|
target.component.handleNativeEvent(ui);
|
|
726
730
|
this.#host.requestRender();
|
package/src/native/encode.ts
CHANGED
|
@@ -109,10 +109,11 @@ export function encodeTspJson(verb: TspVerb, value: unknown, params?: TspParams,
|
|
|
109
109
|
/**
|
|
110
110
|
* The `hello` query; callers follow it with a DA1 sentinel. `features: ["edit"]`
|
|
111
111
|
* tells the terminal that omp applies its `edit` events (TSP §8.5), so it may keep a
|
|
112
|
-
* native selection in omp's editors; without it, every key stays omp's.
|
|
112
|
+
* native selection in omp's editors; without it, every key stays omp's. `"undo"`
|
|
113
|
+
* says omp applies `undo` events, so the terminal may turn ⌃Z in a field into one.
|
|
113
114
|
*/
|
|
114
115
|
export function encodeTspHelloQuery(version?: string): string {
|
|
115
|
-
return encodeTspJson("q", { q: "hello", v: [TSP_VERSION], app: "omp", features: ["edit"], ver: version });
|
|
116
|
+
return encodeTspJson("q", { q: "hello", v: [TSP_VERSION], app: "omp", features: ["edit", "undo"], ver: version });
|
|
116
117
|
}
|
|
117
118
|
|
|
118
119
|
/** One decoded APC message: verb, parameters and raw body. */
|
|
@@ -172,6 +173,7 @@ const EVENT_REQUIRED: Readonly<Record<string, Readonly<Record<string, "string" |
|
|
|
172
173
|
// `value` varies by control (boolean, number, string, string[], null): the handler checks it.
|
|
173
174
|
change: { id: "string", item: "string" },
|
|
174
175
|
edit: { id: "string", from: "number", to: "number", text: "string", cursor: "number", len: "number" },
|
|
176
|
+
undo: { id: "string" },
|
|
175
177
|
focus: { id: "string" },
|
|
176
178
|
error: { msg: "string" },
|
|
177
179
|
gone: { ids: "array" },
|