@linxiraos/pi-tui 1.3.2 → 1.4.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.
- package/CHANGELOG.md +181 -181
- package/dist/types/apps/session-picker.d.ts +13 -1
- package/dist/types/autocomplete.d.ts +6 -0
- package/dist/types/components/sparkline.d.ts +34 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/native/describe.d.ts +7 -1
- package/dist/types/native/overlay.d.ts +2 -0
- package/dist/types/native/tone.d.ts +2 -0
- package/dist/types/overlays/agent-hub.d.ts +3 -3
- package/dist/types/overlays/approval-dialog.d.ts +15 -1
- package/dist/types/overlays/jobs-panel.d.ts +3 -0
- package/dist/types/overlays/model-browser.d.ts +1 -1
- package/dist/types/overlays/resume-picker.d.ts +293 -0
- package/dist/types/overlays/resume-tree.d.ts +353 -0
- package/dist/types/overlays/session-selector.d.ts +22 -4
- package/dist/types/render/output-block.d.ts +2 -0
- package/dist/types/render/tool-card.d.ts +2 -0
- package/dist/types/sixel.d.ts +28 -0
- package/dist/types/status-line/host.d.ts +3 -0
- package/dist/types/terminal-capabilities.d.ts +6 -1
- package/dist/types/tools/bash.d.ts +2 -0
- package/dist/types/tools/default-renderer.d.ts +3 -0
- package/dist/types/tools/eval.d.ts +9 -8
- package/dist/types/tools/hub.d.ts +3 -1
- package/dist/types/tools/irc.d.ts +11 -1
- package/dist/types/tools/job-widget.d.ts +226 -0
- package/dist/types/tools/json-tree.d.ts +2 -0
- package/dist/types/tools/line-ranges.d.ts +8 -1
- package/dist/types/tools/mcp.d.ts +23 -0
- package/dist/types/tools/output-meta.d.ts +1 -1
- package/dist/types/tools/read.d.ts +8 -2
- package/dist/types/tools/renderer.d.ts +8 -2
- package/dist/types/tools/result-card.d.ts +1 -1
- package/dist/types/tools/streaming-output.d.ts +1 -0
- package/dist/types/tools/task.d.ts +12 -0
- package/dist/types/tools/wait.d.ts +11 -0
- package/package.json +9 -9
- package/src/apps/session-picker.ts +20 -2
- package/src/autocomplete.d.ts +6 -0
- package/src/autocomplete.ts +21 -6
- package/src/chat/skill-message.ts +16 -17
- package/src/chat/tool-execution.ts +35 -0
- package/src/chrome/transcript-container.ts +85 -13
- package/src/components/editor.ts +17 -7
- package/src/components/image.ts +5 -4
- package/src/components/markdown.ts +11 -3
- package/src/components/sparkline.d.ts +34 -0
- package/src/components/sparkline.ts +89 -0
- package/src/index.d.ts +1 -0
- package/src/index.ts +1 -0
- package/src/native/backend.ts +32 -6
- package/src/native/describe.d.ts +7 -1
- package/src/native/describe.ts +18 -1
- package/src/native/overlay.d.ts +2 -0
- package/src/native/overlay.ts +3 -0
- package/src/native/tone.d.ts +2 -0
- package/src/native/tone.ts +22 -0
- package/src/overlays/agent-hub.ts +14 -10
- package/src/overlays/agent-transcript-viewer.ts +2 -2
- package/src/overlays/agents-hub.ts +2 -1
- package/src/overlays/approval-dialog.ts +59 -13
- package/src/overlays/hub-frame.ts +2 -1
- package/src/overlays/jobs-panel.ts +24 -2
- package/src/overlays/model-browser.ts +3 -0
- package/src/overlays/model-hub.ts +2 -1
- package/src/overlays/resume-picker.ts +706 -0
- package/src/overlays/resume-tree.ts +1901 -0
- package/src/overlays/session-selector.ts +579 -39
- package/src/prompt/attachment-chips.ts +1 -1
- package/src/render/output-block.d.ts +2 -0
- package/src/render/output-block.ts +25 -12
- package/src/render/tool-card.d.ts +2 -0
- package/src/render/tool-card.ts +6 -0
- package/src/sixel.d.ts +28 -0
- package/src/sixel.ts +185 -0
- package/src/status-line/component.ts +19 -2
- package/src/status-line/host.ts +3 -0
- package/src/terminal-capabilities.d.ts +6 -1
- package/src/terminal-capabilities.ts +54 -3
- package/src/theme/symbols.ts +5 -3
- package/src/tools/bash.d.ts +2 -0
- package/src/tools/bash.ts +25 -9
- package/src/tools/default-renderer.d.ts +3 -0
- package/src/tools/default-renderer.ts +54 -17
- package/src/tools/eval.d.ts +9 -8
- package/src/tools/eval.ts +32 -14
- package/src/tools/find.ts +4 -5
- package/src/tools/glob.ts +4 -6
- package/src/tools/grep.ts +2 -4
- package/src/tools/hub.ts +4 -1
- package/src/tools/irc.d.ts +11 -1
- package/src/tools/irc.ts +11 -1
- package/src/tools/job-widget.d.ts +226 -0
- package/src/tools/job-widget.ts +1036 -0
- package/src/tools/json-tree.d.ts +2 -0
- package/src/tools/json-tree.ts +8 -0
- package/src/tools/line-ranges.d.ts +8 -1
- package/src/tools/line-ranges.ts +23 -13
- package/src/tools/mcp.d.ts +23 -0
- package/src/tools/mcp.ts +44 -1
- package/src/tools/output-meta.d.ts +1 -1
- package/src/tools/output-meta.ts +1 -1
- package/src/tools/proc-render.ts +1 -0
- package/src/tools/read.d.ts +8 -2
- package/src/tools/read.ts +64 -21
- package/src/tools/renderer.d.ts +8 -2
- package/src/tools/renderer.ts +8 -2
- package/src/tools/result-card.d.ts +1 -1
- package/src/tools/result-card.ts +1 -2
- package/src/tools/streaming-output.d.ts +1 -0
- package/src/tools/streaming-output.ts +11 -9
- package/src/tools/task.d.ts +12 -0
- package/src/tools/task.ts +25 -1
- package/src/tools/wait.d.ts +11 -0
- package/src/tools/wait.ts +296 -147
- package/src/tui.ts +45 -5
|
@@ -0,0 +1,353 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ANSI three-level resume tree: project → workspace → conversation.
|
|
3
|
+
*
|
|
4
|
+
* Renders the rows produced by the coding-agent resume view model; it never
|
|
5
|
+
* groups sessions itself. The model arrives through {@link ResumeTreeSource},
|
|
6
|
+
* which the host builds from `loadResumeDirectory` + `buildResumeView` (pi-tui
|
|
7
|
+
* cannot depend on the coding-agent package). Scope cycling, collapse state,
|
|
8
|
+
* search focus, pin actions and the delete confirmation live here; view
|
|
9
|
+
* construction and persistence live in the host.
|
|
10
|
+
*/
|
|
11
|
+
import * as path from "node:path";
|
|
12
|
+
import { type Component } from "../index.js";
|
|
13
|
+
export type ResumeTreeScope = "workspace" | "project" | "all";
|
|
14
|
+
/** Persisted picker state (v2 file): scope plus local expansion. */
|
|
15
|
+
export interface ResumeTreePickerState {
|
|
16
|
+
scope: ResumeTreeScope;
|
|
17
|
+
collapsedProjects?: readonly string[];
|
|
18
|
+
expandedProjects?: readonly string[];
|
|
19
|
+
collapsedWorkspaces?: readonly string[];
|
|
20
|
+
/** Absolute paths in the project/workspace/cwd labels; absent means false. */
|
|
21
|
+
fullPaths?: boolean;
|
|
22
|
+
}
|
|
23
|
+
export type ResumeTreeStatus = "complete" | "interrupted" | "aborted" | "error" | "pending" | "unknown";
|
|
24
|
+
export type ResumeTreeDeleteMode = "trash" | "permanent";
|
|
25
|
+
/** The session fields the tree reads from a conversation row. */
|
|
26
|
+
export interface ResumeTreeSession {
|
|
27
|
+
path: string;
|
|
28
|
+
id: string;
|
|
29
|
+
cwd: string;
|
|
30
|
+
size?: number;
|
|
31
|
+
title?: string;
|
|
32
|
+
modified: Date;
|
|
33
|
+
firstMessage?: string;
|
|
34
|
+
}
|
|
35
|
+
export interface ResumeTreeConversation {
|
|
36
|
+
session: ResumeTreeSession;
|
|
37
|
+
key: string;
|
|
38
|
+
id: string;
|
|
39
|
+
path: string;
|
|
40
|
+
title: string;
|
|
41
|
+
cwd: string;
|
|
42
|
+
projectKey: string;
|
|
43
|
+
workspaceKey: string;
|
|
44
|
+
created: Date;
|
|
45
|
+
modified: Date;
|
|
46
|
+
status?: ResumeTreeStatus;
|
|
47
|
+
pinned: boolean;
|
|
48
|
+
current: boolean;
|
|
49
|
+
fork: boolean;
|
|
50
|
+
/** Subagent marker from `session_init.agent`; forks never set it. */
|
|
51
|
+
isSubagent?: boolean;
|
|
52
|
+
agentName?: string;
|
|
53
|
+
parentKey?: string;
|
|
54
|
+
/** Direct subagent children, when the directory attached them. */
|
|
55
|
+
subagents?: readonly ResumeTreeConversation[];
|
|
56
|
+
messageCount: number;
|
|
57
|
+
}
|
|
58
|
+
export interface ResumeTreeWorkspace {
|
|
59
|
+
key: string;
|
|
60
|
+
path: string;
|
|
61
|
+
name: string;
|
|
62
|
+
/** User-configured alias, or null. The directory name never changes. */
|
|
63
|
+
alias?: string | null;
|
|
64
|
+
/** Alias when set, otherwise `name`. */
|
|
65
|
+
displayName?: string;
|
|
66
|
+
projectKey: string;
|
|
67
|
+
branch: string | null;
|
|
68
|
+
pinned: boolean;
|
|
69
|
+
lastActivity: Date | null;
|
|
70
|
+
counts: {
|
|
71
|
+
conversations: number;
|
|
72
|
+
pinnedConversations: number;
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
export interface ResumeTreeProject {
|
|
76
|
+
key: string;
|
|
77
|
+
root: string;
|
|
78
|
+
name: string;
|
|
79
|
+
alias: string | null;
|
|
80
|
+
displayName: string;
|
|
81
|
+
isDefault: boolean;
|
|
82
|
+
pinned: boolean;
|
|
83
|
+
collapsed: boolean;
|
|
84
|
+
lastActivity: Date | null;
|
|
85
|
+
counts: {
|
|
86
|
+
conversations: number;
|
|
87
|
+
workspaces: number;
|
|
88
|
+
pinnedConversations: number;
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
export interface ResumeTreeProjectRow {
|
|
92
|
+
type: "project";
|
|
93
|
+
key: string;
|
|
94
|
+
project: ResumeTreeProject;
|
|
95
|
+
pinned: boolean;
|
|
96
|
+
collapsed: boolean;
|
|
97
|
+
conversationCount: number;
|
|
98
|
+
totalConversationCount: number;
|
|
99
|
+
workspaceCount: number;
|
|
100
|
+
totalWorkspaceCount: number;
|
|
101
|
+
}
|
|
102
|
+
export interface ResumeTreeWorkspaceRow {
|
|
103
|
+
type: "workspace";
|
|
104
|
+
key: string;
|
|
105
|
+
workspace: ResumeTreeWorkspace;
|
|
106
|
+
projectKey: string;
|
|
107
|
+
pinned: boolean;
|
|
108
|
+
conversationCount: number;
|
|
109
|
+
totalConversationCount: number;
|
|
110
|
+
}
|
|
111
|
+
export interface ResumeTreeConversationRow {
|
|
112
|
+
type: "conversation";
|
|
113
|
+
key: string;
|
|
114
|
+
conversation: ResumeTreeConversation;
|
|
115
|
+
projectKey: string;
|
|
116
|
+
workspaceKey: string;
|
|
117
|
+
pinned: boolean;
|
|
118
|
+
current: boolean;
|
|
119
|
+
pinnedOnly?: boolean;
|
|
120
|
+
}
|
|
121
|
+
export type ResumeTreeRow = ResumeTreeProjectRow | ResumeTreeWorkspaceRow | ResumeTreeConversationRow;
|
|
122
|
+
export interface ResumeTreeView {
|
|
123
|
+
scope: {
|
|
124
|
+
kind: ResumeTreeScope;
|
|
125
|
+
projectKey?: string;
|
|
126
|
+
workspaceKey?: string;
|
|
127
|
+
};
|
|
128
|
+
query: {
|
|
129
|
+
raw: string;
|
|
130
|
+
terms?: readonly string[];
|
|
131
|
+
};
|
|
132
|
+
rows: readonly ResumeTreeRow[];
|
|
133
|
+
conversations?: readonly ResumeTreeConversationRow[];
|
|
134
|
+
counts: {
|
|
135
|
+
conversations: number;
|
|
136
|
+
workspaces?: number;
|
|
137
|
+
projects?: number;
|
|
138
|
+
totalConversations: number;
|
|
139
|
+
totalWorkspaces?: number;
|
|
140
|
+
totalProjects?: number;
|
|
141
|
+
};
|
|
142
|
+
/** Branch of the current session's workspace, when known. */
|
|
143
|
+
referenceBranch?: string | null;
|
|
144
|
+
/** Workspace key of the current session, when known. */
|
|
145
|
+
currentWorkspaceKey?: string;
|
|
146
|
+
}
|
|
147
|
+
/** Names and per-scope conversation totals for the scope header. */
|
|
148
|
+
export interface ResumeTreeScopeSummary {
|
|
149
|
+
workspaceName: string;
|
|
150
|
+
projectName: string;
|
|
151
|
+
counts: Record<ResumeTreeScope, number>;
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Host bridge. `buildView` must be a pure projection of the loaded directory;
|
|
155
|
+
* `refresh`/`pin*`/`deleteConversation` perform I/O and resolve when the
|
|
156
|
+
* source's internal state is current again.
|
|
157
|
+
*/
|
|
158
|
+
export interface ResumeTreeSource {
|
|
159
|
+
readonly initialScope: ResumeTreeScope;
|
|
160
|
+
buildView(input: {
|
|
161
|
+
scope: ResumeTreeScope;
|
|
162
|
+
query: string;
|
|
163
|
+
currentSessionPath?: string;
|
|
164
|
+
}): ResumeTreeView | null;
|
|
165
|
+
scopeSummary(): ResumeTreeScopeSummary;
|
|
166
|
+
currentSessionPath?(): string | undefined;
|
|
167
|
+
/** Remember the chosen scope across opens. */
|
|
168
|
+
persistScope?(scope: ResumeTreeScope): void | Promise<void>;
|
|
169
|
+
/** Restored v2 picker state (scope + expansion); absent means defaults. */
|
|
170
|
+
pickerState?(): ResumeTreePickerState;
|
|
171
|
+
/** Persist scope + expansion together (preferred over `persistScope`). */
|
|
172
|
+
persistPickerState?(state: ResumeTreePickerState): void | Promise<void>;
|
|
173
|
+
/** Re-read the directory; resolves once `buildView` reflects the new state. */
|
|
174
|
+
refresh?(): Promise<void>;
|
|
175
|
+
/** Partial scan failures (unreadable project folders) while rows are still listed. */
|
|
176
|
+
scanWarningNames?(): readonly string[];
|
|
177
|
+
/** A failed load: no rows available at all. */
|
|
178
|
+
loadError?(): string | undefined;
|
|
179
|
+
isLoading?(): boolean;
|
|
180
|
+
pinConversation?(conversation: ResumeTreeConversation, pinned: boolean): Promise<void>;
|
|
181
|
+
pinProject?(project: ResumeTreeProject, pinned: boolean): Promise<void>;
|
|
182
|
+
pinWorkspace?(workspace: ResumeTreeWorkspace, pinned: boolean): Promise<void>;
|
|
183
|
+
/** Set the workspace display alias; resolves the name the picker now shows. */
|
|
184
|
+
renameWorkspace?(workspace: ResumeTreeWorkspace, alias: string | null): Promise<string | null>;
|
|
185
|
+
openWorkspace?(workspace: ResumeTreeWorkspace): void | Promise<void>;
|
|
186
|
+
/** Rename the persisted session title; resolves the stored name or null. */
|
|
187
|
+
renameConversation?(conversation: ResumeTreeConversation, title: string): Promise<string | null>;
|
|
188
|
+
/** False hides the conversation rename action (read-only/foreign session). */
|
|
189
|
+
canRenameConversation?(conversation: ResumeTreeConversation): boolean;
|
|
190
|
+
/** Scopes without a project header (workspace/project) resolve the project here. */
|
|
191
|
+
projectByKey?(key: string): ResumeTreeProject | undefined;
|
|
192
|
+
deleteConversation?(conversation: ResumeTreeConversation): Promise<boolean>;
|
|
193
|
+
deleteMode: ResumeTreeDeleteMode;
|
|
194
|
+
}
|
|
195
|
+
export interface ResumeTreeOptions {
|
|
196
|
+
source: ResumeTreeSource;
|
|
197
|
+
getTerminalRows?: () => number;
|
|
198
|
+
onSelect: (conversation: ResumeTreeConversation) => void;
|
|
199
|
+
onCancel: () => void;
|
|
200
|
+
onExit: () => void;
|
|
201
|
+
onRequestRender?: () => void;
|
|
202
|
+
/** Start with the search field focused (the default for a resume picker). */
|
|
203
|
+
searchFocused?: boolean;
|
|
204
|
+
}
|
|
205
|
+
/** Short relative age, localised through the shared session-picker keys. */
|
|
206
|
+
export declare function formatResumeAge(date: Date, now?: number): string;
|
|
207
|
+
/** Middle-ellipsis truncation for path-like text (`a/b/…/x/y`). */
|
|
208
|
+
export declare function middleEllipsis(text: string, maxWidth: number): string;
|
|
209
|
+
/** Pick the path API from the string's own shape, not the host platform. */
|
|
210
|
+
export declare function resumePathApi(value: string): typeof path.posix;
|
|
211
|
+
/** Full path spelled with its own platform's separators (drive, UNC or POSIX). */
|
|
212
|
+
export declare function absoluteResumePath(value: string): string;
|
|
213
|
+
/** Short parent/name tail or the full absolute path, per the picker toggle. */
|
|
214
|
+
export declare function formatResumePath(value: string, fullPaths: boolean): string;
|
|
215
|
+
/** Basename-first path tail (`parent/name`) keeping the platform separator. */
|
|
216
|
+
export declare function resumePathTail(value: string): string;
|
|
217
|
+
/**
|
|
218
|
+
* Truncate from the left so the tail stays readable, keeping a drive/UNC root
|
|
219
|
+
* when there is room for one (`D:\…\repo`, `\\server\share\…\repo`). The
|
|
220
|
+
* returned string never exceeds `maxWidth` visible columns.
|
|
221
|
+
*/
|
|
222
|
+
export declare function truncateResumePath(value: string, maxWidth: number): string;
|
|
223
|
+
/**
|
|
224
|
+
* A workspace branch is noise when it repeats the current workspace's branch;
|
|
225
|
+
* it is kept for the current workspace or when it actually differs.
|
|
226
|
+
*/
|
|
227
|
+
export declare function shouldShowBranch(branch: string | null | undefined, referenceBranch: string | null | undefined, current: boolean, workspaceName?: string): boolean;
|
|
228
|
+
/** Stable right-hand column widths for the conversation list. */
|
|
229
|
+
export interface ConversationColumns {
|
|
230
|
+
status: number;
|
|
231
|
+
turns: number;
|
|
232
|
+
age: number;
|
|
233
|
+
flags: number;
|
|
234
|
+
}
|
|
235
|
+
/** Width of the status column, fixed across rows so every title starts together. */
|
|
236
|
+
export declare function statusColumnWidth(): number;
|
|
237
|
+
/** Column widths across every visible conversation row, so columns stay put while scrolling. */
|
|
238
|
+
export declare function conversationColumns(rows: readonly ResumeTreeConversationRow[], now?: number): ConversationColumns;
|
|
239
|
+
/**
|
|
240
|
+
* One dense conversation row: `status | title | turns | age | flags | ⋯`.
|
|
241
|
+
* The status cell and every metadata column have fixed widths computed once
|
|
242
|
+
* per frame; the title is the only flexible cell, and nothing ever wraps.
|
|
243
|
+
*/
|
|
244
|
+
export declare function renderConversationRow(row: ResumeTreeConversationRow, options: {
|
|
245
|
+
width: number;
|
|
246
|
+
selected: boolean;
|
|
247
|
+
now?: number;
|
|
248
|
+
columns?: ConversationColumns;
|
|
249
|
+
/** Show the conversation cwd as an absolute path instead of omitting it. */
|
|
250
|
+
fullPaths?: boolean;
|
|
251
|
+
}): string;
|
|
252
|
+
/**
|
|
253
|
+
* One workspace sub-header, indented one visible step: a coloured fold+name,
|
|
254
|
+
* a branch chip when it adds information, and right-aligned counts + `⋯`.
|
|
255
|
+
*/
|
|
256
|
+
export declare function renderWorkspaceRow(row: ResumeTreeWorkspaceRow, options: {
|
|
257
|
+
width: number;
|
|
258
|
+
selected: boolean;
|
|
259
|
+
collapsed: boolean;
|
|
260
|
+
referenceBranch?: string | null;
|
|
261
|
+
current?: boolean;
|
|
262
|
+
/** Show absolute workspace paths instead of parent/name tails. */
|
|
263
|
+
fullPaths?: boolean;
|
|
264
|
+
/** Workspace scope has no use for the path label; callers can omit it. */
|
|
265
|
+
showPath?: boolean;
|
|
266
|
+
}): string;
|
|
267
|
+
/**
|
|
268
|
+
* Project section header: pin + name + path tag on the left, counts/workspaces/
|
|
269
|
+
* age right-aligned. The caller draws a full-width rule under it.
|
|
270
|
+
*/
|
|
271
|
+
export declare function renderProjectRow(row: ResumeTreeProjectRow, options: {
|
|
272
|
+
width: number;
|
|
273
|
+
selected: boolean;
|
|
274
|
+
collapsed: boolean;
|
|
275
|
+
now?: number;
|
|
276
|
+
/** Show the absolute project root instead of the parent/name tail. */
|
|
277
|
+
fullPaths?: boolean;
|
|
278
|
+
}): string;
|
|
279
|
+
/** Full-width rule closing a project section header. */
|
|
280
|
+
export declare function renderProjectRule(width: number): string;
|
|
281
|
+
/** A scope-segment hit range on the header line, in tree-local columns. */
|
|
282
|
+
export interface ResumeScopeHit {
|
|
283
|
+
kind: ResumeTreeScope;
|
|
284
|
+
start: number;
|
|
285
|
+
end: number;
|
|
286
|
+
}
|
|
287
|
+
/** The three-tab scope control with per-scope counts, plus its clickable ranges. */
|
|
288
|
+
export declare function renderScopeHeaderHits(scope: ResumeTreeScope, summary: ResumeTreeScopeSummary, width: number): {
|
|
289
|
+
text: string;
|
|
290
|
+
hits: ResumeScopeHit[];
|
|
291
|
+
};
|
|
292
|
+
/** The three-tab scope control with per-scope counts. */
|
|
293
|
+
export declare function renderScopeHeader(scope: ResumeTreeScope, summary: ResumeTreeScopeSummary, width: number): string;
|
|
294
|
+
interface FlatRow {
|
|
295
|
+
row: ResumeTreeRow;
|
|
296
|
+
/** Visible when every ancestor group is expanded. */
|
|
297
|
+
parentKey?: string;
|
|
298
|
+
}
|
|
299
|
+
export interface ResumeTreeState {
|
|
300
|
+
collapsedProjects: Set<string>;
|
|
301
|
+
expandedProjects: Set<string>;
|
|
302
|
+
collapsedWorkspaces: Set<string>;
|
|
303
|
+
}
|
|
304
|
+
/** Flatten model rows under the current local collapse state (headers always stay). */
|
|
305
|
+
export declare function flattenResumeRows(rows: readonly ResumeTreeRow[], state: ResumeTreeState, searching: boolean): FlatRow[];
|
|
306
|
+
/**
|
|
307
|
+
* The ANSI resume tree component. The host mounts it inside its panel chrome;
|
|
308
|
+
* this component renders the scope control, search field, banners and rows.
|
|
309
|
+
*/
|
|
310
|
+
export declare class ResumeTreeComponent implements Component {
|
|
311
|
+
#private;
|
|
312
|
+
readonly onSelect: (conversation: ResumeTreeConversation) => void;
|
|
313
|
+
readonly onCancel: () => void;
|
|
314
|
+
readonly onExit: () => void;
|
|
315
|
+
onRequestRender?: () => void;
|
|
316
|
+
constructor(options: ResumeTreeOptions);
|
|
317
|
+
/** Rebuild the cached view (call after the host refreshes its directory). */
|
|
318
|
+
invalidate(): void;
|
|
319
|
+
get scope(): ResumeTreeScope;
|
|
320
|
+
get fullPaths(): boolean;
|
|
321
|
+
/**
|
|
322
|
+
* Toggle absolute paths. In workspace scope the path is redundant, so the
|
|
323
|
+
* key surfaces a one-line hint and leaves the setting untouched; the
|
|
324
|
+
* project/all scopes actually flip and persist it.
|
|
325
|
+
*/
|
|
326
|
+
toggleFullPaths(): void;
|
|
327
|
+
/** Adopt a host-refreshed view while keeping selection and collapse state. */
|
|
328
|
+
setView(view: ResumeTreeView | null): void;
|
|
329
|
+
/** Cycle workspace → project → all → workspace. */
|
|
330
|
+
cycleScope(direction?: 1 | -1): void;
|
|
331
|
+
/** Switch to a scope (the scope segments and Tab share this path). */
|
|
332
|
+
setScope(scope: ResumeTreeScope): void;
|
|
333
|
+
/** Re-read the directory through the host source. */
|
|
334
|
+
refresh(): Promise<void>;
|
|
335
|
+
/** Focus the search field (the `/` key, and the initial state). */
|
|
336
|
+
focusSearch(): void;
|
|
337
|
+
/** Pin the selected conversation (`p`) or its project (`P`). */
|
|
338
|
+
pinSelected(project: boolean): Promise<void>;
|
|
339
|
+
/**
|
|
340
|
+
* Hit-test an SGR mouse report against the rows the last render recorded.
|
|
341
|
+
* The fullscreen picker paints from screen row 0, so callers pass the
|
|
342
|
+
* component's frame offset (`row` of the first rendered line, `col` of its
|
|
343
|
+
* first content column). Keyboard handling never depends on this path.
|
|
344
|
+
*/
|
|
345
|
+
handleMouse(data: string, offset?: {
|
|
346
|
+
row?: number;
|
|
347
|
+
col?: number;
|
|
348
|
+
}): boolean;
|
|
349
|
+
handleInput(keyData: string): void;
|
|
350
|
+
render(width: number): readonly string[];
|
|
351
|
+
dispose(): void;
|
|
352
|
+
}
|
|
353
|
+
export {};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { type Component, Input } from "../index.js";
|
|
2
2
|
import type { TspPickerGroup, TspPickerItem } from "@linxiraos/pi-wire";
|
|
3
3
|
import type { DescribeContext, NativeNode, NativeUiEvent } from "../native/node.js";
|
|
4
|
+
import { type ResumeSourceLike } from "./resume-picker.js";
|
|
4
5
|
/** Session lifecycle status presented by the picker. */
|
|
5
6
|
export type SessionSelectorStatus = "complete" | "interrupted" | "aborted" | "error" | "pending" | "unknown";
|
|
6
7
|
/** Session listing fields consumed by the picker. */
|
|
@@ -18,6 +19,8 @@ export interface SessionSelectorEntry {
|
|
|
18
19
|
/** Path to the parent session when this one was forked. */
|
|
19
20
|
parentSessionPath?: string;
|
|
20
21
|
}
|
|
22
|
+
import { ResumeTreeComponent } from "./resume-tree.js";
|
|
23
|
+
export type { ResumeConversationLike, ResumeDirectoryLike, ResumeProjectLike, ResumeQueryLike, ResumeScopeInputLike, ResumeScopeKindLike, ResumeSourceLike, ResumeViewLike, ResumeViewRowLike, ResumeWorkspaceLike, } from "./resume-picker.js";
|
|
21
24
|
import { OverlayPanel } from "../chrome/overlay-box.js";
|
|
22
25
|
/** The session list's part of the picker props, plus the memo keys it was built from. */
|
|
23
26
|
interface SessionPickerView {
|
|
@@ -76,6 +79,11 @@ declare class SessionList<T extends SessionSelectorEntry> implements Component {
|
|
|
76
79
|
constructor(sessions: T[], showCwd?: boolean, historyMatcher?: SessionHistoryMatcher, getTerminalRows?: () => number, pinnedIds?: ReadonlySet<string>, currentSessionPath?: string | (() => string | undefined));
|
|
77
80
|
/** Replace the visible dataset, e.g. when toggling folder/all-projects scope. */
|
|
78
81
|
setSessions(sessions: T[], showCwd: boolean, pinnedIds?: ReadonlySet<string>): void;
|
|
82
|
+
/**
|
|
83
|
+
* Resume-model mode: the given sessions are already the model's ordered,
|
|
84
|
+
* filtered view, so mirror them and keep the selection when it survives.
|
|
85
|
+
*/
|
|
86
|
+
syncSessions(sessions: readonly T[], preferredPath?: string | null): void;
|
|
79
87
|
/** Cancel pending async search work; idempotent, called on every picker exit path. */
|
|
80
88
|
dispose(): void;
|
|
81
89
|
removeSession(sessionPath: string): void;
|
|
@@ -125,6 +133,17 @@ export interface SessionSelectorOptions<T extends SessionSelectorEntry = Session
|
|
|
125
133
|
loadAllSessions?: () => Promise<T[]>;
|
|
126
134
|
/** Preloaded all-projects list; cached so the first Tab toggle is instant. */
|
|
127
135
|
allSessions?: T[];
|
|
136
|
+
/**
|
|
137
|
+
* The host's resume model (project → workspace → conversation) and its
|
|
138
|
+
* pure view builder. When set, the native `picker` describes the resume
|
|
139
|
+
* tree instead of the flat day-grouped list; the ANSI path is unchanged.
|
|
140
|
+
*/
|
|
141
|
+
resumeSource?: ResumeSourceLike;
|
|
142
|
+
/**
|
|
143
|
+
* What delete does to the session file: an in-session picker moves it to
|
|
144
|
+
* the trash, `--resume` deletes it permanently. Wording only.
|
|
145
|
+
*/
|
|
146
|
+
deleteMode?: "trash" | "permanent";
|
|
128
147
|
/** Picker heading; defaults to "Resume Session". */
|
|
129
148
|
title?: string;
|
|
130
149
|
/** Primary action label; defaults to "Resume" (ANSI footer defaults to "select"). */
|
|
@@ -160,9 +179,7 @@ export interface SessionSelectorOptions<T extends SessionSelectorEntry = Session
|
|
|
160
179
|
*/
|
|
161
180
|
standalone?: boolean;
|
|
162
181
|
}
|
|
163
|
-
/**
|
|
164
|
-
* Component that renders a session selector with optional confirmation dialog
|
|
165
|
-
*/
|
|
182
|
+
/** Component that renders a session selector with optional confirmation dialog. */
|
|
166
183
|
export declare class SessionSelectorComponent<T extends SessionSelectorEntry = SessionSelectorEntry> extends OverlayPanel {
|
|
167
184
|
#private;
|
|
168
185
|
constructor(sessions: T[], onSelect: (session: T) => void, onCancel: () => void, onExit: () => void, options?: SessionSelectorOptions<T>);
|
|
@@ -196,5 +213,6 @@ export declare class SessionSelectorComponent<T extends SessionSelectorEntry = S
|
|
|
196
213
|
handleNativeEvent(event: NativeUiEvent): void;
|
|
197
214
|
handleInput(keyData: string): void;
|
|
198
215
|
getSessionList(): SessionList<T>;
|
|
216
|
+
/** The ANSI resume tree when the host supplied a resume source. */
|
|
217
|
+
getResumeTree(): ResumeTreeComponent | undefined;
|
|
199
218
|
}
|
|
200
|
-
export {};
|
|
@@ -10,6 +10,8 @@ import type { State } from "./types.js";
|
|
|
10
10
|
export interface OutputBlockOptions {
|
|
11
11
|
header?: string;
|
|
12
12
|
headerMeta?: string;
|
|
13
|
+
/** Facts drawn inside the bottom border (`╰── Wall 0.16s · Timeout 300s ──╯`). */
|
|
14
|
+
footerMeta?: string;
|
|
13
15
|
state?: State;
|
|
14
16
|
sections?: Array<{
|
|
15
17
|
label?: string;
|
|
@@ -22,6 +22,8 @@ export interface ToolCardSnapshot {
|
|
|
22
22
|
/** Structured status header, rendered by the shared status-line primitive. */
|
|
23
23
|
status?: StatusLineOptions;
|
|
24
24
|
headerMeta?: string;
|
|
25
|
+
/** Short facts drawn inside the frame's bottom border (framed); a trailing row otherwise. */
|
|
26
|
+
footerMeta?: string;
|
|
25
27
|
phase?: ToolCardPhase;
|
|
26
28
|
body?: ToolCardContent;
|
|
27
29
|
sections?: readonly ToolCardSection[];
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Give an empty first band an explicit transparent width. Zellij derives the
|
|
3
|
+
* decoded image width from its first pixel row, ignoring the raster minimum
|
|
4
|
+
* for transparent images; an omitted band otherwise makes the image invisible.
|
|
5
|
+
* Palette definitions stay before drawing so cropping can still parse them.
|
|
6
|
+
*/
|
|
7
|
+
export declare function ensureSixelRasterWidth(sequence: string): string;
|
|
8
|
+
/**
|
|
9
|
+
* Crop integer pixel rows from a raw (not tmux-wrapped) SIXEL DCS image.
|
|
10
|
+
* Runs are shifted between adjacent six-pixel bands, never decoded to pixels.
|
|
11
|
+
* Palette selections, overdraw order, transparent gaps and DCS background mode
|
|
12
|
+
* are retained. A nonpositive crop returns the original sequence unchanged.
|
|
13
|
+
*
|
|
14
|
+
* The supported grammar is the native icy_sixel encoder's: one leading raster
|
|
15
|
+
* declaration with positive dimensions and square pixels, prefix RGB/HLS palette
|
|
16
|
+
* definitions, register selections, sixel characters, repeats, `$` and `-`.
|
|
17
|
+
* ESC DCS/ST framing only, as the TUI emits it. Palette definitions after
|
|
18
|
+
* drawing, additional raster declarations, other controls and malformed input
|
|
19
|
+
* throw; forwarding an unsupported image uncropped would reintroduce raster
|
|
20
|
+
* overflow.
|
|
21
|
+
*
|
|
22
|
+
* Without maxHeightPixels the crop is exact, including a partial final band with
|
|
23
|
+
* zero padding bits and the exact declared raster height. Some terminals still
|
|
24
|
+
* allocate all six rows of that final band. The TUI supplies its available pixel
|
|
25
|
+
* height to cap the result at a whole-band boundary, matching the native encoder's
|
|
26
|
+
* policy of dropping bottom pixels rather than overwriting the following row.
|
|
27
|
+
*/
|
|
28
|
+
export declare function cropSixelTop(sequence: string, pixels: number, maxHeightPixels?: number): string;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { AgentMessage, ThinkingLevel } from "@linxiraos/pi-agent-core";
|
|
2
2
|
import type { Tool, UsageLimit, UsageReport } from "@linxiraos/pi-ai";
|
|
3
3
|
import type { Model } from "@linxiraos/pi-catalog/types";
|
|
4
|
+
import type { JobWidgetEntry } from "../tools/job-widget.js";
|
|
4
5
|
import type { CompactionBoundaries } from "./context-usage.js";
|
|
5
6
|
import type { StatusLineSettings, StatusResetExpiry } from "./types.js";
|
|
6
7
|
export interface StatusAccountIdentity {
|
|
@@ -74,6 +75,8 @@ export interface StatusLineSession {
|
|
|
74
75
|
agentId?: string;
|
|
75
76
|
}[];
|
|
76
77
|
} | null | undefined;
|
|
78
|
+
/** Widgets of the running background jobs, in job order; the jobs segment appends the freshest one's glance. */
|
|
79
|
+
getRunningJobWidgets?(): readonly JobWidgetEntry[];
|
|
77
80
|
getGoalModeState(): {
|
|
78
81
|
goal?: {
|
|
79
82
|
status: string;
|
|
@@ -18,7 +18,7 @@ export declare enum NotifyProtocol {
|
|
|
18
18
|
Osc99 = "\u001B]99;;",
|
|
19
19
|
Osc9 = "\u001B]9;"
|
|
20
20
|
}
|
|
21
|
-
export type TerminalId = "kitty" | "ghostty" | "wezterm" | "iterm2" | "vscode" | "alacritty" | "warp" | "orca" | "otty" | "rio" | "tern" | "monstar" | "base" | "trueColor";
|
|
21
|
+
export type TerminalId = "kitty" | "ghostty" | "wezterm" | "iterm2" | "vscode" | "alacritty" | "warp" | "orca" | "otty" | "rio" | "tern" | "monstar" | "zetawork" | "base" | "trueColor";
|
|
22
22
|
/** Terminal capability details used for rendering and protocol selection. */
|
|
23
23
|
export declare class TerminalInfo {
|
|
24
24
|
readonly id: TerminalId;
|
|
@@ -401,6 +401,11 @@ export declare function encodeITerm2(base64Data: string, options?: {
|
|
|
401
401
|
preserveAspectRatio?: boolean;
|
|
402
402
|
inline?: boolean;
|
|
403
403
|
}): string;
|
|
404
|
+
/**
|
|
405
|
+
* The encoded image `encodeITerm2` wrote into `line`, without the size
|
|
406
|
+
* parameters a rewrap changes; undefined for a line without one.
|
|
407
|
+
*/
|
|
408
|
+
export declare function iterm2ImagePayload(line: string): string | undefined;
|
|
404
409
|
export declare function calculateImageRows(imageDimensions: ImageDimensions, targetWidthCells: number, cellDimensions?: CellDimensions): number;
|
|
405
410
|
export declare function getPngDimensions(base64Data: string): ImageDimensions | null;
|
|
406
411
|
export declare function getJpegDimensions(base64Data: string): ImageDimensions | null;
|
|
@@ -117,6 +117,7 @@ export declare function createShellRenderer<TArgs>(config: ShellRendererConfig<T
|
|
|
117
117
|
}, args?: TArgs): NativeToolView;
|
|
118
118
|
mergeCallAndResult: true;
|
|
119
119
|
inline: true;
|
|
120
|
+
tickElapsed: true;
|
|
120
121
|
};
|
|
121
122
|
/** Renders bash command previews and output. */
|
|
122
123
|
export declare const bashToolRenderer: {
|
|
@@ -146,4 +147,5 @@ export declare const bashToolRenderer: {
|
|
|
146
147
|
}, args?: BashRenderArgs | undefined): NativeToolView;
|
|
147
148
|
mergeCallAndResult: true;
|
|
148
149
|
inline: true;
|
|
150
|
+
tickElapsed: true;
|
|
149
151
|
};
|
|
@@ -23,6 +23,9 @@ export declare function formatDefaultToolExecution(input: DefaultToolRenderInput
|
|
|
23
23
|
/**
|
|
24
24
|
* TSP view of the generic fallback card: the tool label with a one-line args
|
|
25
25
|
* summary as the head target; the result as a JSON tree or raw `ansi` output.
|
|
26
|
+
* The complete output goes over the wire — the card-level disclosure clamp the
|
|
27
|
+
* terminal applies is the only bound, so an expanded card keeps every row. JSON
|
|
28
|
+
* the tree's depth, node or scalar caps would cut keeps the raw path instead.
|
|
26
29
|
*/
|
|
27
30
|
export declare function describeDefaultToolExecution(input: DefaultToolRenderInput): NativeToolView;
|
|
28
31
|
/** Render the generic fallback as the state-tinted card used by direct custom tools. */
|
|
@@ -61,7 +61,7 @@ export interface EvalCellResult {
|
|
|
61
61
|
durationMs?: number;
|
|
62
62
|
exitCode?: number;
|
|
63
63
|
statusEvents?: EvalStatusEvent[];
|
|
64
|
-
/**
|
|
64
|
+
/** Evictable events dropped from the front of `statusEvents` (see {@link recordStatusEvent}). */
|
|
65
65
|
statusEventsElided?: number;
|
|
66
66
|
}
|
|
67
67
|
/** Tool result detail object surfaced to the UI/transcript. */
|
|
@@ -69,7 +69,7 @@ export interface EvalToolDetails {
|
|
|
69
69
|
cells?: EvalCellResult[];
|
|
70
70
|
images?: ImageContent[];
|
|
71
71
|
statusEvents?: EvalStatusEvent[];
|
|
72
|
-
/**
|
|
72
|
+
/** Evictable events dropped from the front of `statusEvents` (see {@link recordStatusEvent}). */
|
|
73
73
|
statusEventsElided?: number;
|
|
74
74
|
isError?: boolean;
|
|
75
75
|
meta?: OutputMeta;
|
|
@@ -104,7 +104,7 @@ interface EvalRenderContext {
|
|
|
104
104
|
timeout?: number;
|
|
105
105
|
}
|
|
106
106
|
/**
|
|
107
|
-
* Coalescing key of a progress-snapshot event: `agent` and `
|
|
107
|
+
* Coalescing key of a progress-snapshot event: `agent`, `judge_batch`, and `mcp_progress`
|
|
108
108
|
* events keyed by `id`, where only the newest snapshot matters. Discrete
|
|
109
109
|
* actions (everything else) have no key. Shared by {@link upsertStatusEvent}
|
|
110
110
|
* and the executors' display collectors so both coalesce identically.
|
|
@@ -114,12 +114,12 @@ export declare function statusEventKey(event: {
|
|
|
114
114
|
[key: string]: unknown;
|
|
115
115
|
}): string | undefined;
|
|
116
116
|
/**
|
|
117
|
-
*
|
|
117
|
+
* Evictable status events a log keeps. A cell polling a helper in a loop emits
|
|
118
118
|
* one event per call (hundreds of thousands), and every live update and the
|
|
119
119
|
* persisted tool result would otherwise carry them all.
|
|
120
120
|
*/
|
|
121
121
|
export declare const MAX_STATUS_EVENTS = 200;
|
|
122
|
-
/** A status event list plus the count of
|
|
122
|
+
/** A status event list plus the count of evictable events dropped from its front. */
|
|
123
123
|
export type StatusEventLog = Pick<EvalCellResult, "statusEvents" | "statusEventsElided">;
|
|
124
124
|
/**
|
|
125
125
|
* Append or replace a status event. Progress snapshots (see
|
|
@@ -129,9 +129,10 @@ export type StatusEventLog = Pick<EvalCellResult, "statusEvents" | "statusEvents
|
|
|
129
129
|
export declare function upsertStatusEvent(events: EvalStatusEvent[], event: EvalStatusEvent): void;
|
|
130
130
|
/**
|
|
131
131
|
* {@link upsertStatusEvent} into a bounded log. Past {@link MAX_STATUS_EVENTS},
|
|
132
|
-
* the oldest discrete event is dropped and counted.
|
|
133
|
-
* cards read them, and so does
|
|
134
|
-
*
|
|
132
|
+
* the oldest discrete event or MCP progress snapshot is dropped and counted.
|
|
133
|
+
* Agent/judgment-batch snapshots stay, since agent cards read them, and so does
|
|
134
|
+
* the newest committed `todo` result, which the session todo panel refreshes
|
|
135
|
+
* from. Renderers already show only the newest
|
|
135
136
|
* events behind an "… N earlier" row.
|
|
136
137
|
*/
|
|
137
138
|
export declare function recordStatusEvent(log: StatusEventLog, event: EvalStatusEvent): void;
|
|
@@ -123,6 +123,8 @@ export interface CoordinationDetails {
|
|
|
123
123
|
}[];
|
|
124
124
|
/** Running subagents not represented by a job row in this result. */
|
|
125
125
|
agents?: AgentActivitySnapshot[];
|
|
126
|
+
/** `wait` returned early because blocking would deadlock (mesh S6). */
|
|
127
|
+
status?: "peer-waiting-on-you";
|
|
126
128
|
}
|
|
127
129
|
/** Hub result details: coordination snapshots or launch (process) state. */
|
|
128
130
|
export type HubDetails = CoordinationDetails | LaunchToolDetails;
|
|
@@ -204,7 +206,7 @@ export interface IrcMessage {
|
|
|
204
206
|
/** Delivery outcome for one peer recipient. */
|
|
205
207
|
export interface IrcDeliveryReceipt {
|
|
206
208
|
to: string;
|
|
207
|
-
outcome: "injected" | "woken" | "revived" | "failed";
|
|
209
|
+
outcome: "injected" | "woken" | "revived" | "queued" | "failed";
|
|
208
210
|
error?: string;
|
|
209
211
|
}
|
|
210
212
|
/** Broker-facing launch parameters; the hub adapts its `ps` op to `list` before calling in. */
|
|
@@ -19,11 +19,21 @@ export interface IrcMessage {
|
|
|
19
19
|
* ping-pong forever.
|
|
20
20
|
*/
|
|
21
21
|
wakeRelay?: boolean;
|
|
22
|
+
/**
|
|
23
|
+
* One leg of an `all` broadcast. Like relays, broadcasts never draw an
|
|
24
|
+
* automatic wake-turn reply: every woken idle peer would otherwise answer
|
|
25
|
+
* the broadcaster, mostly to say the message was not for it.
|
|
26
|
+
*/
|
|
27
|
+
broadcast?: boolean;
|
|
22
28
|
}
|
|
23
29
|
/** Delivery outcome for one peer recipient. */
|
|
24
30
|
export interface IrcDeliveryReceipt {
|
|
25
31
|
to: string;
|
|
26
|
-
|
|
32
|
+
/**
|
|
33
|
+
* `queued` is the cross-process offline path: the message is in the peer's
|
|
34
|
+
* persistent mailbox and will be injected when its process next starts.
|
|
35
|
+
*/
|
|
36
|
+
outcome: "injected" | "woken" | "revived" | "queued" | "failed";
|
|
27
37
|
error?: string;
|
|
28
38
|
}
|
|
29
39
|
/** Status ordering for peer rosters in child prompts. */
|