@oh-my-pi/pi-tui 18.2.10 → 18.3.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 +32 -0
- package/THIRD-PARTY-NOTICES.txt +1 -1
- package/dist/types/apps/ps-data.d.ts +1 -1
- package/dist/types/apps/ps-top.d.ts +1 -1
- package/dist/types/chat/chat-transcript-builder.d.ts +1 -1
- package/dist/types/overlays/annotation-overlay.d.ts +30 -0
- package/dist/types/overlays/annotation-types.d.ts +84 -0
- package/dist/types/overlays/copy-selector.d.ts +30 -2
- package/dist/types/overlays/copy-targets.d.ts +2 -0
- package/dist/types/overlays/model-hub.d.ts +2 -2
- package/dist/types/overlays/oauth-selector.d.ts +3 -6
- package/dist/types/overlays/usage-dashboard.d.ts +2 -0
- package/dist/types/prompt/image-source.d.ts +9 -8
- package/dist/types/render/render-utils.d.ts +2 -0
- package/dist/types/status-line/context-usage.d.ts +3 -1
- package/dist/types/theme/mermaid-cache.d.ts +4 -6
- package/dist/types/tools/bash.d.ts +7 -0
- package/dist/types/tools/daemon.d.ts +46 -0
- package/dist/types/tools/irc.d.ts +30 -0
- package/dist/types/tools/line-ranges.d.ts +1 -1
- package/dist/types/tools/proc-render.d.ts +34 -0
- package/dist/types/tools/read.d.ts +4 -1
- package/dist/types/tools/task.d.ts +4 -0
- package/dist/types/tools/wait.d.ts +131 -0
- package/dist/types/tools/write.d.ts +4 -0
- package/dist/types/tools/xd-url.d.ts +8 -0
- package/dist/types/windows-altgr.d.ts +54 -0
- package/package.json +13 -10
- package/src/apps/debug/protocol-probe.ts +1 -1
- package/src/apps/ps-data.ts +1 -1
- package/src/apps/ps-top.ts +1 -1
- package/src/chat/chat-transcript-builder.ts +4 -4
- package/src/chat/tool-execution.ts +8 -8
- package/src/chat/transcript-render-helpers.ts +3 -3
- package/src/components/markdown.ts +1 -1
- package/src/desktop-notify.ts +1 -1
- package/src/overlays/annotation-overlay.ts +1145 -0
- package/src/overlays/annotation-types.ts +78 -0
- package/src/overlays/copy-selector.ts +45 -19
- package/src/overlays/copy-targets.ts +3 -3
- package/src/overlays/model-hub.ts +5 -4
- package/src/overlays/oauth-selector.ts +8 -12
- package/src/overlays/plan-review-overlay.ts +213 -40
- package/src/overlays/settings-defs.ts +1 -0
- package/src/overlays/usage-dashboard.ts +120 -25
- package/src/prompt/image-source.ts +9 -8
- package/src/prompt/welcome.ts +4 -1
- package/src/render/render-utils.ts +1 -1
- package/src/setup/scenes/sign-in.ts +1 -1
- package/src/status-line/component.ts +15 -4
- package/src/status-line/context-usage.ts +15 -3
- package/src/status-line/segments.ts +3 -3
- package/src/terminal-capabilities.ts +16 -7
- package/src/terminal.ts +8 -1
- package/src/theme/mermaid-cache.ts +83 -25
- package/src/tools/bash.ts +14 -1
- package/src/tools/daemon.ts +51 -0
- package/src/tools/index.ts +2 -2
- package/src/tools/irc.ts +33 -0
- package/src/tools/line-ranges.ts +13 -3
- package/src/tools/proc-render.ts +294 -0
- package/src/tools/read.ts +22 -1
- package/src/tools/task.ts +18 -0
- package/src/tools/wait.ts +595 -0
- package/src/tools/write.ts +76 -0
- package/src/tools/xd-url.ts +9 -0
- package/src/windows-altgr.ts +227 -0
- package/dist/types/tools/hub.d.ts +0 -342
- package/src/tools/hub.ts +0 -1492
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
import type { Component } from "../tui";
|
|
2
|
+
import { createCachedComponent, Ellipsis, renderStatusLine, renderTreeList, truncateToWidth } from "../render";
|
|
3
|
+
import {
|
|
4
|
+
cappedHeadLines,
|
|
5
|
+
formatBadge,
|
|
6
|
+
formatDuration,
|
|
7
|
+
formatErrorDetail,
|
|
8
|
+
formatStatusIcon,
|
|
9
|
+
PREVIEW_LIMITS,
|
|
10
|
+
TRUNCATE_LENGTHS,
|
|
11
|
+
replaceTabs,
|
|
12
|
+
type ToolUIColor,
|
|
13
|
+
} from "../render/render-utils";
|
|
14
|
+
import type { Theme } from "../theme/theme";
|
|
15
|
+
import type { RenderResultOptions } from "./renderer";
|
|
16
|
+
import type { AgentActivitySnapshot, CoordinationDetails, JobSnapshot } from "./wait";
|
|
17
|
+
import type { IrcDeliveryReceipt } from "./irc";
|
|
18
|
+
import type { DaemonSnapshot } from "./daemon";
|
|
19
|
+
import { styleTerminalRow } from "./terminal-output";
|
|
20
|
+
|
|
21
|
+
export interface ProcReadDetails {
|
|
22
|
+
jobs?: JobSnapshot[];
|
|
23
|
+
agents?: AgentActivitySnapshot[];
|
|
24
|
+
daemons?: DaemonSnapshot[];
|
|
25
|
+
job?: JobSnapshot;
|
|
26
|
+
daemon?: DaemonSnapshot;
|
|
27
|
+
log?: string;
|
|
28
|
+
terminalRows?: string[];
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export type ProcWriteDetails =
|
|
32
|
+
| CoordinationDetails
|
|
33
|
+
| { action: "stop" | "stdin" | "mode"; daemon: DaemonSnapshot; input?: string; mode?: string };
|
|
34
|
+
|
|
35
|
+
/** Process operation selected by a write URL, independent of its content. */
|
|
36
|
+
export type ProcWriteAction = "stdin" | "mode" | "kill";
|
|
37
|
+
|
|
38
|
+
interface ToolResult {
|
|
39
|
+
content: Array<{ type: string; text?: string }>;
|
|
40
|
+
isError?: boolean;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function firstText(result: ToolResult): string {
|
|
44
|
+
return result.content.find(item => item.type === "text")?.text ?? "";
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function safe(value: string): string {
|
|
48
|
+
return replaceTabs(value).replace(/\r/g, "");
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function card(lines: (width: number, expanded: boolean) => string[], options: RenderResultOptions): Component {
|
|
52
|
+
return createCachedComponent(
|
|
53
|
+
() => Boolean(options.expanded),
|
|
54
|
+
(width, expanded) =>
|
|
55
|
+
lines(width, expanded)
|
|
56
|
+
.flatMap(line => line.split("\n"))
|
|
57
|
+
.map(line => truncateToWidth(safe(line), width, Ellipsis.Unicode)),
|
|
58
|
+
{ paddingX: 1 },
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function preview(body: string, expanded: boolean, theme: Theme, tone: "dim" | "toolOutput" = "dim"): string[] {
|
|
63
|
+
if (!body.trim()) return [];
|
|
64
|
+
const limit = expanded ? PREVIEW_LIMITS.EXPANDED_LINES : PREVIEW_LIMITS.COLLAPSED_LINES;
|
|
65
|
+
const shown = cappedHeadLines(
|
|
66
|
+
body.split("\n").filter(line => line.trim()),
|
|
67
|
+
limit,
|
|
68
|
+
);
|
|
69
|
+
const quote = theme.fg("dim", theme.md.quoteBorder);
|
|
70
|
+
const lines = shown.lines.map(
|
|
71
|
+
line =>
|
|
72
|
+
` ${quote} ${theme.fg(tone, truncateToWidth(safe(line.trim()), TRUNCATE_LENGTHS.LINE, Ellipsis.Unicode))}`,
|
|
73
|
+
);
|
|
74
|
+
if (shown.hidden) lines.push(` ${quote} ${theme.fg("dim", `… +${shown.hidden} more lines`)}`);
|
|
75
|
+
return lines;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function receiptColor(outcome: IrcDeliveryReceipt["outcome"]): ToolUIColor {
|
|
79
|
+
return outcome === "failed" ? "error" : outcome === "revived" ? "warning" : "success";
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export function renderAgentWrite(
|
|
83
|
+
to: string,
|
|
84
|
+
body: string,
|
|
85
|
+
result: ToolResult | undefined,
|
|
86
|
+
details: CoordinationDetails | undefined,
|
|
87
|
+
options: RenderResultOptions,
|
|
88
|
+
theme: Theme,
|
|
89
|
+
): Component {
|
|
90
|
+
return card((width, expanded) => {
|
|
91
|
+
const recipient = safe(details?.to || to || "…");
|
|
92
|
+
const title = `IRC ${theme.nav.selected} ${recipient}`;
|
|
93
|
+
const receipts = details?.receipts ?? [];
|
|
94
|
+
const delivered = receipts.filter(receipt => receipt.outcome !== "failed").length;
|
|
95
|
+
const failed = receipts.length - delivered;
|
|
96
|
+
const error = result?.isError || (failed > 0 && delivered === 0);
|
|
97
|
+
const meta: string[] = [];
|
|
98
|
+
if (recipient === "all") meta.push("broadcast");
|
|
99
|
+
if (receipts.length === 1) meta.push(theme.fg(receiptColor(receipts[0]!.outcome), receipts[0]!.outcome));
|
|
100
|
+
else if (receipts.length > 1) {
|
|
101
|
+
if (delivered) meta.push(theme.fg("success", `${delivered} delivered`));
|
|
102
|
+
if (failed) meta.push(theme.fg("error", `${failed} failed`));
|
|
103
|
+
}
|
|
104
|
+
const header = renderStatusLine(
|
|
105
|
+
result === undefined
|
|
106
|
+
? { icon: "pending", title, meta }
|
|
107
|
+
: error
|
|
108
|
+
? { icon: "error", title, meta }
|
|
109
|
+
: { iconOverride: theme.styledSymbol("tool.irc", "accent"), title, meta },
|
|
110
|
+
theme,
|
|
111
|
+
);
|
|
112
|
+
if (result?.isError && receipts.length === 0)
|
|
113
|
+
return [header, formatErrorDetail(firstText(result) || "Message delivery failed.", theme)];
|
|
114
|
+
const lines = [header, ...preview(body, expanded, theme)];
|
|
115
|
+
if (result && receipts.length === 0)
|
|
116
|
+
lines.push(theme.fg("muted", firstText(result) || "No live peers to broadcast to."));
|
|
117
|
+
if (receipts.length > 1 || failed > 0) {
|
|
118
|
+
lines.push(
|
|
119
|
+
...renderTreeList(
|
|
120
|
+
{
|
|
121
|
+
items: receipts,
|
|
122
|
+
expanded,
|
|
123
|
+
maxCollapsed: PREVIEW_LIMITS.COLLAPSED_ITEMS,
|
|
124
|
+
itemType: "recipient",
|
|
125
|
+
renderItem: receipt =>
|
|
126
|
+
`${theme.fg("toolOutput", safe(receipt.to))} ${formatBadge(receipt.outcome, receiptColor(receipt.outcome), theme)}${receipt.error ? ` ${theme.fg("error", `${theme.format.dash} ${safe(receipt.error)}`)}` : ""}`,
|
|
127
|
+
},
|
|
128
|
+
theme,
|
|
129
|
+
),
|
|
130
|
+
);
|
|
131
|
+
}
|
|
132
|
+
return lines.map(line => truncateToWidth(line, width, Ellipsis.Unicode));
|
|
133
|
+
}, options);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function daemonMeta(daemon: DaemonSnapshot, theme: Theme): string[] {
|
|
137
|
+
const stateColor =
|
|
138
|
+
daemon.state === "ready" || daemon.state === "running"
|
|
139
|
+
? "success"
|
|
140
|
+
: daemon.state === "failed"
|
|
141
|
+
? "error"
|
|
142
|
+
: "warning";
|
|
143
|
+
const meta = [theme.fg(stateColor, daemon.state)];
|
|
144
|
+
if (daemon.pid !== undefined) meta.push(`pid ${daemon.pid}`);
|
|
145
|
+
meta.push(
|
|
146
|
+
`${daemon.exitedAt === undefined ? "up" : "ran"} ${formatDuration(Math.max(0, (daemon.exitedAt ?? Date.now()) - daemon.startedAt))}`,
|
|
147
|
+
);
|
|
148
|
+
if (daemon.detached) meta.push("detached");
|
|
149
|
+
else if (daemon.persist) meta.push("persistent");
|
|
150
|
+
return meta;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function jobRow(job: JobSnapshot, theme: Theme): string {
|
|
154
|
+
const icon = formatStatusIcon(
|
|
155
|
+
job.status === "cancelled"
|
|
156
|
+
? "aborted"
|
|
157
|
+
: job.status === "failed"
|
|
158
|
+
? "error"
|
|
159
|
+
: job.status === "running"
|
|
160
|
+
? "running"
|
|
161
|
+
: "done",
|
|
162
|
+
theme,
|
|
163
|
+
);
|
|
164
|
+
return `${icon} ${formatBadge(job.type, job.status === "failed" ? "error" : job.status === "cancelled" ? "warning" : "accent", theme)} ${theme.fg("toolOutput", safe(job.id))} ${theme.fg("dim", safe(job.label))} ${theme.fg("dim", formatDuration(job.durationMs))}`;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/** Render live and completed process writes with the URL-selected operation. */
|
|
168
|
+
export function renderProcWrite(
|
|
169
|
+
id: string,
|
|
170
|
+
action: ProcWriteAction,
|
|
171
|
+
content: string | undefined,
|
|
172
|
+
result: ToolResult | undefined,
|
|
173
|
+
details: ProcWriteDetails | undefined,
|
|
174
|
+
options: RenderResultOptions,
|
|
175
|
+
theme: Theme,
|
|
176
|
+
): Component {
|
|
177
|
+
return card((_width, expanded) => {
|
|
178
|
+
const title = `Proc ${action} ${safe(id || "…")}`;
|
|
179
|
+
const daemon = details && "daemon" in details ? details.daemon : undefined;
|
|
180
|
+
const header = renderStatusLine(
|
|
181
|
+
{
|
|
182
|
+
icon:
|
|
183
|
+
result === undefined ? "pending" : result.isError ? "error" : action === "kill" ? "aborted" : "success",
|
|
184
|
+
title,
|
|
185
|
+
meta: daemon ? daemonMeta(daemon, theme) : action === "mode" && content ? [safe(content)] : [],
|
|
186
|
+
},
|
|
187
|
+
theme,
|
|
188
|
+
);
|
|
189
|
+
if (result?.isError) return [header, formatErrorDetail(firstText(result) || "Process operation failed.", theme)];
|
|
190
|
+
const lines = [header];
|
|
191
|
+
if (content && action === "stdin") lines.push(...preview(content, expanded, theme));
|
|
192
|
+
if (details && "op" in details && details.op === "cancel") {
|
|
193
|
+
const jobs = details.jobs ?? [];
|
|
194
|
+
const outcomes = details.cancelled ?? [];
|
|
195
|
+
lines.push(
|
|
196
|
+
...renderTreeList(
|
|
197
|
+
{
|
|
198
|
+
items: outcomes,
|
|
199
|
+
expanded,
|
|
200
|
+
maxCollapsed: PREVIEW_LIMITS.COLLAPSED_ITEMS,
|
|
201
|
+
itemType: "job",
|
|
202
|
+
renderItem: outcome => {
|
|
203
|
+
const job = jobs.find(item => item.id === outcome.id);
|
|
204
|
+
return `${job ? `${jobRow(job, theme)} ` : `${theme.fg("toolOutput", safe(outcome.id))} `}${formatBadge(outcome.status, outcome.status === "cancelled" ? "warning" : "error", theme)}`;
|
|
205
|
+
},
|
|
206
|
+
},
|
|
207
|
+
theme,
|
|
208
|
+
),
|
|
209
|
+
);
|
|
210
|
+
}
|
|
211
|
+
return lines;
|
|
212
|
+
}, options);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
export function renderProcRead(
|
|
216
|
+
id: string,
|
|
217
|
+
result: ToolResult | undefined,
|
|
218
|
+
details: ProcReadDetails | undefined,
|
|
219
|
+
options: RenderResultOptions,
|
|
220
|
+
theme: Theme,
|
|
221
|
+
): Component {
|
|
222
|
+
return card((_width, expanded) => {
|
|
223
|
+
const title = id ? `Proc ${safe(id)}` : "Proc jobs & services";
|
|
224
|
+
const daemon = details?.daemon;
|
|
225
|
+
const header = renderStatusLine(
|
|
226
|
+
{
|
|
227
|
+
icon: result === undefined ? "pending" : result.isError ? "error" : "info",
|
|
228
|
+
title,
|
|
229
|
+
meta: daemon ? daemonMeta(daemon, theme) : [],
|
|
230
|
+
},
|
|
231
|
+
theme,
|
|
232
|
+
);
|
|
233
|
+
if (result?.isError) return [header, formatErrorDetail(firstText(result) || "Process read failed.", theme)];
|
|
234
|
+
if (!result) return [header];
|
|
235
|
+
if (details?.job)
|
|
236
|
+
return [
|
|
237
|
+
header,
|
|
238
|
+
jobRow(details.job, theme),
|
|
239
|
+
...preview(
|
|
240
|
+
details.log ?? details.job.errorText ?? details.job.resultText ?? "",
|
|
241
|
+
expanded,
|
|
242
|
+
theme,
|
|
243
|
+
"toolOutput",
|
|
244
|
+
),
|
|
245
|
+
];
|
|
246
|
+
if (daemon) {
|
|
247
|
+
const output = details.terminalRows ?? (details.log ?? "").split("\n").filter(Boolean);
|
|
248
|
+
const limit = expanded ? PREVIEW_LIMITS.EXPANDED_LINES : PREVIEW_LIMITS.COLLAPSED_LINES;
|
|
249
|
+
const visible = output
|
|
250
|
+
.slice(-limit)
|
|
251
|
+
.map(
|
|
252
|
+
line =>
|
|
253
|
+
` ${styleTerminalRow(truncateToWidth(safe(line), TRUNCATE_LENGTHS.LINE, Ellipsis.Unicode), theme.fg("toolOutput", ""))}`,
|
|
254
|
+
);
|
|
255
|
+
if (output.length > limit) visible.unshift(theme.fg("dim", ` … ${output.length - limit} earlier lines`));
|
|
256
|
+
return [header, ...visible];
|
|
257
|
+
}
|
|
258
|
+
if (id && !details?.jobs && !details?.daemons && !details?.agents) {
|
|
259
|
+
return [header, ...preview(firstText(result), expanded, theme, "toolOutput")];
|
|
260
|
+
}
|
|
261
|
+
const jobs = details?.jobs ?? [];
|
|
262
|
+
const services = details?.daemons ?? [];
|
|
263
|
+
const agents = details?.agents ?? [];
|
|
264
|
+
const meta = [
|
|
265
|
+
`${jobs.length} jobs`,
|
|
266
|
+
`${services.length} services`,
|
|
267
|
+
...(agents.length ? [`${agents.length} agents`] : []),
|
|
268
|
+
];
|
|
269
|
+
const listHeader = renderStatusLine({ icon: "info", title, meta }, theme);
|
|
270
|
+
const items = [
|
|
271
|
+
...jobs.map(job => ({ label: jobRow(job, theme) })),
|
|
272
|
+
...services.map(service => ({
|
|
273
|
+
label: `${formatBadge("service", "accent", theme)} ${theme.fg("toolOutput", safe(service.name))} ${formatBadge(service.state, service.state === "failed" ? "error" : service.state === "ready" || service.state === "running" ? "success" : "warning", theme)} ${daemonMeta(service, theme).slice(1).join(theme.sep.dot)}`,
|
|
274
|
+
})),
|
|
275
|
+
...agents.map(agent => ({
|
|
276
|
+
label: `${formatBadge("agent", agent.live ? "accent" : "warning", theme)} ${theme.fg("toolOutput", safe(agent.id))} ${theme.fg("dim", formatDuration(agent.ageMs))}`,
|
|
277
|
+
})),
|
|
278
|
+
];
|
|
279
|
+
return [
|
|
280
|
+
listHeader,
|
|
281
|
+
...renderTreeList(
|
|
282
|
+
{
|
|
283
|
+
items,
|
|
284
|
+
expanded,
|
|
285
|
+
maxCollapsed: PREVIEW_LIMITS.COLLAPSED_ITEMS,
|
|
286
|
+
itemType: "process",
|
|
287
|
+
renderItem: item => item.label,
|
|
288
|
+
},
|
|
289
|
+
theme,
|
|
290
|
+
),
|
|
291
|
+
...(items.length ? [] : [theme.fg("dim", "No background jobs or services.")]),
|
|
292
|
+
];
|
|
293
|
+
}, options);
|
|
294
|
+
}
|
package/src/tools/read.ts
CHANGED
|
@@ -4,7 +4,7 @@ import { LINE_RANGE_CHUNK_SOURCE, parseLineRanges } from "./line-ranges";
|
|
|
4
4
|
import * as path from "node:path";
|
|
5
5
|
import type { Component } from "../tui";
|
|
6
6
|
import { Text } from "../components/text";
|
|
7
|
-
import type { RenderResultOptions, ToolRenderer } from "./renderer";
|
|
7
|
+
import type { RenderResultOptions, ToolActivityContext, ToolActivitySummary, ToolRenderer } from "./renderer";
|
|
8
8
|
import { getLanguageFromPath } from "../lang-from-path";
|
|
9
9
|
import type { Theme } from "../theme/theme";
|
|
10
10
|
import { fileHyperlink, renderCodeCell, renderMarkdownCell, renderStatusLine } from "../render";
|
|
@@ -16,6 +16,7 @@ import { formatBytes, sanitizeDisplayLines, shortenPath, wrapBrackets } from "..
|
|
|
16
16
|
|
|
17
17
|
import type { OutputMeta } from "./output-meta";
|
|
18
18
|
import type { TruncationResult } from "./streaming-output";
|
|
19
|
+
import { renderProcRead, type ProcReadDetails } from "./proc-render";
|
|
19
20
|
|
|
20
21
|
/** Read result metadata retains truncation statistics, not a second copy of the body. */
|
|
21
22
|
export type ReadTruncationStats = Omit<TruncationResult, "content">;
|
|
@@ -23,6 +24,7 @@ export type ReadTruncationStats = Omit<TruncationResult, "content">;
|
|
|
23
24
|
/** Display metadata for file and URL reads. */
|
|
24
25
|
export interface ReadToolDetails {
|
|
25
26
|
kind?: "file" | "url";
|
|
27
|
+
proc?: ProcReadDetails;
|
|
26
28
|
/** Filesystem hyperlink target resolved by the executing tool. */
|
|
27
29
|
displayTarget?: string;
|
|
28
30
|
truncation?: ReadTruncationStats;
|
|
@@ -91,6 +93,7 @@ const INTERNAL_SCHEMES_WITH_SELECTORS: Record<string, true> = {
|
|
|
91
93
|
memory: true,
|
|
92
94
|
omp: true,
|
|
93
95
|
pr: true,
|
|
96
|
+
proc: true,
|
|
94
97
|
rule: true,
|
|
95
98
|
security: true,
|
|
96
99
|
skill: true,
|
|
@@ -266,9 +269,19 @@ function formatReadPathLink(
|
|
|
266
269
|
|
|
267
270
|
/** Render file, image, and URL reads in the transcript. */
|
|
268
271
|
export const readToolRenderer = {
|
|
272
|
+
activitySummary(args: unknown, _context: ToolActivityContext): ToolActivitySummary {
|
|
273
|
+
const input = args as ReadRenderArgs | undefined;
|
|
274
|
+
const rawPath =
|
|
275
|
+
typeof input?.file_path === "string" ? input.file_path : typeof input?.path === "string" ? input.path : "";
|
|
276
|
+
if (/^proc:\/\//i.test(rawPath))
|
|
277
|
+
return { label: "Process", detail: rawPath.slice("proc://".length) || "jobs & services" };
|
|
278
|
+
return { label: "Read", detail: shortenPath(rawPath) };
|
|
279
|
+
},
|
|
269
280
|
renderCall(args: ReadRenderArgs, _options: RenderResultOptions, uiTheme: Theme): Component {
|
|
270
281
|
const rawPath =
|
|
271
282
|
typeof args.file_path === "string" ? args.file_path : typeof args.path === "string" ? args.path : "";
|
|
283
|
+
if (/^proc:\/\//i.test(rawPath))
|
|
284
|
+
return renderProcRead(rawPath.slice("proc://".length), undefined, undefined, _options, uiTheme);
|
|
272
285
|
if (isReadableUrlPath(rawPath)) {
|
|
273
286
|
return renderReadUrlCall({ path: rawPath, raw: args.raw }, _options, uiTheme);
|
|
274
287
|
}
|
|
@@ -296,6 +309,14 @@ export const readToolRenderer = {
|
|
|
296
309
|
const urlDetails = result.details as ReadUrlToolDetails | undefined;
|
|
297
310
|
const baseRawPathForKind =
|
|
298
311
|
typeof args?.file_path === "string" ? args.file_path : typeof args?.path === "string" ? args.path : "";
|
|
312
|
+
if (/^proc:\/\//i.test(baseRawPathForKind))
|
|
313
|
+
return renderProcRead(
|
|
314
|
+
baseRawPathForKind.slice("proc://".length),
|
|
315
|
+
result,
|
|
316
|
+
result.details?.proc,
|
|
317
|
+
options,
|
|
318
|
+
uiTheme,
|
|
319
|
+
);
|
|
299
320
|
if (urlDetails?.kind === "url" || isReadableUrlPath(baseRawPathForKind)) {
|
|
300
321
|
return renderReadUrlResult(
|
|
301
322
|
result as {
|
package/src/tools/task.ts
CHANGED
|
@@ -636,6 +636,18 @@ function renderDescriptionLines(description: string, prefix: string, width: numb
|
|
|
636
636
|
return wrapTextWithAnsi(description, contentWidth).map(line => `${boundedPrefix}${theme.fg("dim", line)}`);
|
|
637
637
|
}
|
|
638
638
|
|
|
639
|
+
/** `routed:` note from a `before_subagent_spawn` model replacement; empty when unrouted. */
|
|
640
|
+
function renderRouteLine(route: string | undefined, continuePrefix: string, maxWidth: number, theme: Theme): string[] {
|
|
641
|
+
if (!route) return [];
|
|
642
|
+
return [
|
|
643
|
+
truncateTaskRow(
|
|
644
|
+
`${continuePrefix}${theme.fg("dim", `routed: ${replaceTabs(sanitizeText(route))}`)}`,
|
|
645
|
+
maxWidth,
|
|
646
|
+
"",
|
|
647
|
+
),
|
|
648
|
+
];
|
|
649
|
+
}
|
|
650
|
+
|
|
639
651
|
/**
|
|
640
652
|
* Render streaming progress for a single agent.
|
|
641
653
|
*/
|
|
@@ -688,6 +700,7 @@ function renderAgentProgress(
|
|
|
688
700
|
if (fullDescription && !row.descriptionShown) {
|
|
689
701
|
lines.push(...renderDescriptionLines(fullDescription, continuePrefix, maxWidth, theme));
|
|
690
702
|
}
|
|
703
|
+
lines.push(...renderRouteLine(progress.resolvedModelRoute, continuePrefix, maxWidth, theme));
|
|
691
704
|
|
|
692
705
|
lines.push(...renderTaskSection(progress.assignment ?? progress.task, continuePrefix, expanded, theme));
|
|
693
706
|
|
|
@@ -1029,6 +1042,7 @@ function renderAgentResult(
|
|
|
1029
1042
|
if (fullDescription && !description) {
|
|
1030
1043
|
lines.push(...renderDescriptionLines(fullDescription, continuePrefix, maxWidth, theme));
|
|
1031
1044
|
}
|
|
1045
|
+
lines.push(...renderRouteLine(result.resolvedModelRoute, continuePrefix, maxWidth, theme));
|
|
1032
1046
|
|
|
1033
1047
|
lines.push(...renderTaskSection(result.assignment ?? result.task, continuePrefix, expanded, theme));
|
|
1034
1048
|
|
|
@@ -1858,6 +1872,8 @@ export interface AgentProgress {
|
|
|
1858
1872
|
resolvedThinkingLevel?: ConfiguredThinkingLevel;
|
|
1859
1873
|
/** True when {@link resolvedModel} is the target of an active retry fallback (not the originally configured model). Lets observer-only UIs (collab guests, Agent Hub rows with no live session) flag the fallback and keep the provider. */
|
|
1860
1874
|
resolvedModelIsFallback?: boolean;
|
|
1875
|
+
/** Extension routing note (e.g. model-pools) explaining why {@link resolvedModel} was chosen. */
|
|
1876
|
+
resolvedModelRoute?: string;
|
|
1861
1877
|
/** True when a live advisor was attached to this run's session, not merely enabled in settings. */
|
|
1862
1878
|
advisor?: boolean;
|
|
1863
1879
|
/** Data extracted by registered subprocess tool handlers (keyed by tool name) */
|
|
@@ -1935,6 +1951,8 @@ export interface SingleResult {
|
|
|
1935
1951
|
resolvedThinkingLevel?: ConfiguredThinkingLevel;
|
|
1936
1952
|
/** True when {@link resolvedModel} is the target of an active retry fallback. Mirrors {@link AgentProgress.resolvedModelIsFallback} onto the settled result. */
|
|
1937
1953
|
resolvedModelIsFallback?: boolean;
|
|
1954
|
+
/** Mirrors {@link AgentProgress.resolvedModelRoute} onto the settled result. */
|
|
1955
|
+
resolvedModelRoute?: string;
|
|
1938
1956
|
/** Retains {@link AgentProgress.advisor} after the advised session is disposed. */
|
|
1939
1957
|
advisor?: boolean;
|
|
1940
1958
|
error?: string;
|