@oh-my-pi/pi-coding-agent 9.6.0 → 9.6.3
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 +17 -0
- package/docs/theme.md +9 -12
- package/package.json +7 -7
- package/src/exa/render.ts +12 -12
- package/src/ipy/gateway-coordinator.ts +1 -1
- package/src/ipy/kernel.ts +5 -0
- package/src/ipy/runtime.ts +2 -6
- package/src/lsp/render.ts +16 -30
- package/src/modes/components/bash-execution.ts +2 -4
- package/src/modes/components/custom-message.ts +1 -1
- package/src/modes/components/footer.ts +1 -1
- package/src/modes/components/history-search.ts +3 -2
- package/src/modes/components/hook-message.ts +1 -1
- package/src/modes/components/python-execution.ts +2 -4
- package/src/modes/components/read-tool-group.ts +1 -1
- package/src/modes/components/session-selector.ts +7 -11
- package/src/modes/components/status-line/segments.ts +1 -1
- package/src/modes/components/status-line.ts +1 -1
- package/src/modes/components/tool-execution.ts +3 -3
- package/src/modes/components/ttsr-notification.ts +1 -1
- package/src/modes/components/welcome.ts +2 -2
- package/src/modes/controllers/event-controller.ts +3 -3
- package/src/modes/interactive-mode.ts +1 -1
- package/src/modes/theme/theme.ts +0 -11
- package/src/patch/shared.ts +7 -10
- package/src/task/executor.ts +1 -1
- package/src/task/render.ts +31 -33
- package/src/tools/bash.ts +3 -3
- package/src/tools/calculator.ts +3 -3
- package/src/tools/fetch.ts +4 -6
- package/src/tools/python.ts +22 -31
- package/src/tools/read.ts +1 -1
- package/src/tools/render-utils.ts +12 -21
- package/src/tools/review.ts +1 -7
- package/src/tools/ssh.ts +6 -8
- package/src/tools/write.ts +5 -5
- package/src/tui/code-cell.ts +2 -2
- package/src/tui/output-block.ts +2 -2
- package/src/tui/tree-list.ts +1 -3
- package/src/tui/utils.ts +3 -5
- package/src/web/search/render.ts +14 -24
package/src/tools/read.ts
CHANGED
|
@@ -1003,7 +1003,7 @@ export const readToolRenderer = {
|
|
|
1003
1003
|
const offset = args.offset;
|
|
1004
1004
|
const limit = args.limit;
|
|
1005
1005
|
|
|
1006
|
-
let pathDisplay = filePath ||
|
|
1006
|
+
let pathDisplay = filePath || "…";
|
|
1007
1007
|
if (offset !== undefined || limit !== undefined) {
|
|
1008
1008
|
const startLine = offset ?? 1;
|
|
1009
1009
|
const endLine = limit !== undefined ? startLine + limit - 1 : "";
|
|
@@ -5,9 +5,12 @@
|
|
|
5
5
|
* tool renderers to ensure a unified TUI experience.
|
|
6
6
|
*/
|
|
7
7
|
import * as os from "node:os";
|
|
8
|
+
import { type Ellipsis, truncateToWidth } from "@oh-my-pi/pi-tui";
|
|
8
9
|
import type { Theme } from "../modes/theme/theme";
|
|
9
10
|
import { getTreeBranch } from "../tui/utils";
|
|
10
11
|
|
|
12
|
+
export { Ellipsis, truncateToWidth } from "@oh-my-pi/pi-tui";
|
|
13
|
+
|
|
11
14
|
// =============================================================================
|
|
12
15
|
// Standardized Display Constants
|
|
13
16
|
// =============================================================================
|
|
@@ -47,22 +50,12 @@ export const EXPAND_HINT = "(Ctrl+O for more)";
|
|
|
47
50
|
// Text Truncation Utilities
|
|
48
51
|
// =============================================================================
|
|
49
52
|
|
|
50
|
-
/**
|
|
51
|
-
* Truncate text to max length with ellipsis.
|
|
52
|
-
* The most commonly duplicated utility across renderers.
|
|
53
|
-
*/
|
|
54
|
-
export function truncate(text: string, maxLen: number, ellipsis: string): string {
|
|
55
|
-
if (text.length <= maxLen) return text;
|
|
56
|
-
const sliceLen = Math.max(0, maxLen - ellipsis.length);
|
|
57
|
-
return `${text.slice(0, sliceLen)}${ellipsis}`;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
53
|
/**
|
|
61
54
|
* Get first N lines of text as preview, with each line truncated.
|
|
62
55
|
*/
|
|
63
|
-
export function getPreviewLines(text: string, maxLines: number, maxLineLen: number, ellipsis
|
|
56
|
+
export function getPreviewLines(text: string, maxLines: number, maxLineLen: number, ellipsis?: Ellipsis): string[] {
|
|
64
57
|
const lines = text.split("\n").filter(l => l.trim());
|
|
65
|
-
return lines.slice(0, maxLines).map(l =>
|
|
58
|
+
return lines.slice(0, maxLines).map(l => truncateToWidth(l.trim(), maxLineLen, ellipsis));
|
|
66
59
|
}
|
|
67
60
|
|
|
68
61
|
// =============================================================================
|
|
@@ -194,9 +187,9 @@ export function formatBadge(label: string, color: ToolUIColor, theme: Theme): st
|
|
|
194
187
|
* Build a "more items" suffix line for truncated lists.
|
|
195
188
|
* Uses consistent wording pattern.
|
|
196
189
|
*/
|
|
197
|
-
export function formatMoreItems(remaining: number, itemType: string
|
|
190
|
+
export function formatMoreItems(remaining: number, itemType: string): string {
|
|
198
191
|
const safeRemaining = Number.isFinite(remaining) ? remaining : 0;
|
|
199
|
-
return
|
|
192
|
+
return `… ${safeRemaining} more ${pluralize(itemType, safeRemaining)}`;
|
|
200
193
|
}
|
|
201
194
|
|
|
202
195
|
export function formatMeta(meta: string[], theme: Theme): string {
|
|
@@ -252,7 +245,7 @@ export class ToolUIKit {
|
|
|
252
245
|
}
|
|
253
246
|
|
|
254
247
|
moreItems(remaining: number, itemType: string): string {
|
|
255
|
-
return formatMoreItems(remaining, itemType
|
|
248
|
+
return formatMoreItems(remaining, itemType);
|
|
256
249
|
}
|
|
257
250
|
|
|
258
251
|
expandHint(expanded: boolean, hasMore: boolean): string {
|
|
@@ -288,11 +281,11 @@ export class ToolUIKit {
|
|
|
288
281
|
}
|
|
289
282
|
|
|
290
283
|
truncate(text: string, maxLen: number): string {
|
|
291
|
-
return
|
|
284
|
+
return truncateToWidth(text, maxLen);
|
|
292
285
|
}
|
|
293
286
|
|
|
294
287
|
previewLines(text: string, maxLines: number, maxLineLen: number): string[] {
|
|
295
|
-
return getPreviewLines(text, maxLines, maxLineLen
|
|
288
|
+
return getPreviewLines(text, maxLines, maxLineLen);
|
|
296
289
|
}
|
|
297
290
|
|
|
298
291
|
formatBytes(bytes: number): string {
|
|
@@ -457,7 +450,7 @@ export function formatDiagnostics(
|
|
|
457
450
|
const remaining = totalDiags - diagsShown;
|
|
458
451
|
output += `\n ${theme.fg("dim", theme.tree.last)} ${theme.fg(
|
|
459
452
|
"muted",
|
|
460
|
-
|
|
453
|
+
`… ${remaining} more`,
|
|
461
454
|
)} ${formatExpandHint(theme)}`;
|
|
462
455
|
}
|
|
463
456
|
|
|
@@ -697,9 +690,7 @@ export function renderTreeList<T>(
|
|
|
697
690
|
|
|
698
691
|
if (!expanded && items.length > maxCollapsed) {
|
|
699
692
|
const remaining = items.length - maxCollapsed;
|
|
700
|
-
lines.push(
|
|
701
|
-
` ${theme.fg("dim", theme.tree.last)} ${theme.fg("muted", formatMoreItems(remaining, itemType, theme))}`,
|
|
702
|
-
);
|
|
693
|
+
lines.push(` ${theme.fg("dim", theme.tree.last)} ${theme.fg("muted", formatMoreItems(remaining, itemType))}`);
|
|
703
694
|
}
|
|
704
695
|
|
|
705
696
|
return lines;
|
package/src/tools/review.ts
CHANGED
|
@@ -181,13 +181,7 @@ subprocessToolRegistry.register<ReportFindingDetails>("report_finding", {
|
|
|
181
181
|
}
|
|
182
182
|
|
|
183
183
|
if (allData.length > displayCount) {
|
|
184
|
-
container.addChild(
|
|
185
|
-
new Text(
|
|
186
|
-
theme.fg("dim", ` ${theme.format.ellipsis} ${allData.length - displayCount} more findings`),
|
|
187
|
-
0,
|
|
188
|
-
0,
|
|
189
|
-
),
|
|
190
|
-
);
|
|
184
|
+
container.addChild(new Text(theme.fg("dim", ` … ${allData.length - displayCount} more findings`), 0, 0));
|
|
191
185
|
}
|
|
192
186
|
|
|
193
187
|
return container;
|
package/src/tools/ssh.ts
CHANGED
|
@@ -237,8 +237,8 @@ interface SshRenderContext {
|
|
|
237
237
|
|
|
238
238
|
export const sshToolRenderer = {
|
|
239
239
|
renderCall(args: SshRenderArgs, uiTheme: Theme): Component {
|
|
240
|
-
const host = args.host ||
|
|
241
|
-
const command = args.command ||
|
|
240
|
+
const host = args.host || "…";
|
|
241
|
+
const command = args.command || "…";
|
|
242
242
|
const text = renderStatusLine({ icon: "pending", title: "SSH", description: `[${host}] $ ${command}` }, uiTheme);
|
|
243
243
|
return new Text(text, 0, 0);
|
|
244
244
|
},
|
|
@@ -254,8 +254,8 @@ export const sshToolRenderer = {
|
|
|
254
254
|
): Component {
|
|
255
255
|
const { expanded, renderContext } = options;
|
|
256
256
|
const details = result.details;
|
|
257
|
-
const host = args?.host ||
|
|
258
|
-
const command = args?.command ||
|
|
257
|
+
const host = args?.host || "…";
|
|
258
|
+
const command = args?.command || "…";
|
|
259
259
|
const header = renderStatusLine(
|
|
260
260
|
{ icon: "success", title: "SSH", description: `[${host}] $ ${command}` },
|
|
261
261
|
uiTheme,
|
|
@@ -274,7 +274,7 @@ export const sshToolRenderer = {
|
|
|
274
274
|
outputLines.push(
|
|
275
275
|
uiTheme.fg(
|
|
276
276
|
"dim",
|
|
277
|
-
|
|
277
|
+
`… (${skippedCount} earlier lines, showing ${visualLines.length} of ${totalVisualLines}) (ctrl+o to expand)`,
|
|
278
278
|
),
|
|
279
279
|
);
|
|
280
280
|
}
|
|
@@ -289,9 +289,7 @@ export const sshToolRenderer = {
|
|
|
289
289
|
const remaining = outputLinesRaw.length - maxLines;
|
|
290
290
|
outputLines.push(...displayLines.map(line => uiTheme.fg("toolOutput", line)));
|
|
291
291
|
if (remaining > 0) {
|
|
292
|
-
outputLines.push(
|
|
293
|
-
uiTheme.fg("dim", `${uiTheme.format.ellipsis} (${remaining} more lines) (ctrl+o to expand)`),
|
|
294
|
-
);
|
|
292
|
+
outputLines.push(uiTheme.fg("dim", `… (${remaining} more lines) (ctrl+o to expand)`));
|
|
295
293
|
}
|
|
296
294
|
}
|
|
297
295
|
}
|
package/src/tools/write.ts
CHANGED
|
@@ -155,12 +155,12 @@ function formatStreamingContent(content: string, uiTheme: Theme, ui: ToolUIKit):
|
|
|
155
155
|
|
|
156
156
|
let text = "\n\n";
|
|
157
157
|
if (hidden > 0) {
|
|
158
|
-
text += uiTheme.fg("dim",
|
|
158
|
+
text += uiTheme.fg("dim", `… (${hidden} earlier lines)\n`);
|
|
159
159
|
}
|
|
160
160
|
for (const line of displayLines) {
|
|
161
161
|
text += `${uiTheme.fg("toolOutput", ui.truncate(line, 80))}\n`;
|
|
162
162
|
}
|
|
163
|
-
text += uiTheme.fg("dim",
|
|
163
|
+
text += uiTheme.fg("dim", `… (streaming)`);
|
|
164
164
|
return text;
|
|
165
165
|
}
|
|
166
166
|
|
|
@@ -177,7 +177,7 @@ function renderContentPreview(content: string, expanded: boolean, uiTheme: Theme
|
|
|
177
177
|
}
|
|
178
178
|
if (!expanded && hidden > 0) {
|
|
179
179
|
const hint = formatExpandHint(uiTheme, expanded, hidden > 0);
|
|
180
|
-
const moreLine = `${formatMoreItems(hidden, "line"
|
|
180
|
+
const moreLine = `${formatMoreItems(hidden, "line")}${hint ? ` ${hint}` : ""}`;
|
|
181
181
|
text += uiTheme.fg("dim", moreLine);
|
|
182
182
|
}
|
|
183
183
|
return text;
|
|
@@ -190,7 +190,7 @@ export const writeToolRenderer = {
|
|
|
190
190
|
const filePath = shortenPath(rawPath);
|
|
191
191
|
const lang = getLanguageFromPath(rawPath) ?? "text";
|
|
192
192
|
const langIcon = uiTheme.fg("muted", uiTheme.getLangIcon(lang));
|
|
193
|
-
const pathDisplay = filePath ? uiTheme.fg("accent", filePath) : uiTheme.fg("toolOutput",
|
|
193
|
+
const pathDisplay = filePath ? uiTheme.fg("accent", filePath) : uiTheme.fg("toolOutput", "…");
|
|
194
194
|
const spinner =
|
|
195
195
|
options?.spinnerFrame !== undefined ? formatStatusIcon("running", uiTheme, options.spinnerFrame) : "";
|
|
196
196
|
|
|
@@ -218,7 +218,7 @@ export const writeToolRenderer = {
|
|
|
218
218
|
const fileContent = args?.content || "";
|
|
219
219
|
const lang = getLanguageFromPath(rawPath);
|
|
220
220
|
const langIcon = uiTheme.fg("muted", uiTheme.getLangIcon(lang));
|
|
221
|
-
const pathDisplay = filePath ? uiTheme.fg("accent", filePath) : uiTheme.fg("toolOutput",
|
|
221
|
+
const pathDisplay = filePath ? uiTheme.fg("accent", filePath) : uiTheme.fg("toolOutput", "…");
|
|
222
222
|
const lineCount = countLines(fileContent);
|
|
223
223
|
|
|
224
224
|
// Build header with status icon
|
package/src/tui/code-cell.ts
CHANGED
|
@@ -80,7 +80,7 @@ export function renderCodeCell(options: CodeCellOptions, theme: Theme): string[]
|
|
|
80
80
|
const hiddenCodeLines = rawCodeLines.length - codeLines.length;
|
|
81
81
|
if (hiddenCodeLines > 0) {
|
|
82
82
|
const hint = formatExpandHint(theme, expanded, hiddenCodeLines > 0);
|
|
83
|
-
const moreLine = `${formatMoreItems(hiddenCodeLines, "line"
|
|
83
|
+
const moreLine = `${formatMoreItems(hiddenCodeLines, "line")}${hint ? ` ${hint}` : ""}`;
|
|
84
84
|
codeLines.push(theme.fg("dim", moreLine));
|
|
85
85
|
}
|
|
86
86
|
|
|
@@ -95,7 +95,7 @@ export function renderCodeCell(options: CodeCellOptions, theme: Theme): string[]
|
|
|
95
95
|
const remaining = rawLines.length - maxLines;
|
|
96
96
|
if (remaining > 0) {
|
|
97
97
|
const hint = formatExpandHint(theme, expanded, remaining > 0);
|
|
98
|
-
const moreLine = `${formatMoreItems(remaining, "line"
|
|
98
|
+
const moreLine = `${formatMoreItems(remaining, "line")}${hint ? ` ${hint}` : ""}`;
|
|
99
99
|
outputLines.push(theme.fg("dim", moreLine));
|
|
100
100
|
}
|
|
101
101
|
}
|
package/src/tui/output-block.ts
CHANGED
|
@@ -42,7 +42,7 @@ export function renderOutputBlock(options: OutputBlockOptions, theme: Theme): st
|
|
|
42
42
|
const leftWidth = visibleWidth(left);
|
|
43
43
|
const rightWidth = visibleWidth(right);
|
|
44
44
|
const maxLabelWidth = Math.max(0, lineWidth - leftWidth - rightWidth);
|
|
45
|
-
const trimmedLabel = truncateToWidth(rawLabel, maxLabelWidth
|
|
45
|
+
const trimmedLabel = truncateToWidth(rawLabel, maxLabelWidth);
|
|
46
46
|
const labelWidth = visibleWidth(trimmedLabel);
|
|
47
47
|
const fillCount = Math.max(0, lineWidth - leftWidth - labelWidth - rightWidth);
|
|
48
48
|
return `${left}${trimmedLabel}${border(h.repeat(fillCount))}${right}`;
|
|
@@ -69,7 +69,7 @@ export function renderOutputBlock(options: OutputBlockOptions, theme: Theme): st
|
|
|
69
69
|
}
|
|
70
70
|
const allLines = section.lines.flatMap(l => l.split("\n"));
|
|
71
71
|
for (const line of allLines) {
|
|
72
|
-
const text = truncateToWidth(line, contentWidth
|
|
72
|
+
const text = truncateToWidth(line, contentWidth);
|
|
73
73
|
const innerPadding = padding(Math.max(0, contentWidth - visibleWidth(text)));
|
|
74
74
|
const fullLine = `${contentPrefix}${text}${innerPadding}${contentSuffix}`;
|
|
75
75
|
lines.push(padToWidth(fullLine, lineWidth, bgFn));
|
package/src/tui/tree-list.ts
CHANGED
|
@@ -46,9 +46,7 @@ export function renderTreeList<T>(options: TreeListOptions<T>, theme: Theme): st
|
|
|
46
46
|
|
|
47
47
|
if (!expanded && items.length > maxItems) {
|
|
48
48
|
const remaining = items.length - maxItems;
|
|
49
|
-
lines.push(
|
|
50
|
-
`${theme.fg("dim", theme.tree.last)} ${theme.fg("muted", formatMoreItems(remaining, itemType, theme))}`,
|
|
51
|
-
);
|
|
49
|
+
lines.push(`${theme.fg("dim", theme.tree.last)} ${theme.fg("muted", formatMoreItems(remaining, itemType))}`);
|
|
52
50
|
}
|
|
53
51
|
|
|
54
52
|
return lines;
|
package/src/tui/utils.ts
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Shared helpers for tool-rendered UI components.
|
|
3
3
|
*/
|
|
4
|
-
import { padding,
|
|
4
|
+
import { padding, visibleWidth } from "@oh-my-pi/pi-tui";
|
|
5
5
|
import type { Theme, ThemeBg } from "../modes/theme/theme";
|
|
6
6
|
import type { IconType, State } from "./types";
|
|
7
7
|
|
|
8
|
+
export { truncateToWidth } from "@oh-my-pi/pi-tui";
|
|
9
|
+
|
|
8
10
|
export function buildTreePrefix(ancestors: boolean[], theme: Theme): string {
|
|
9
11
|
return ancestors.map(hasNext => (hasNext ? `${theme.tree.vertical} ` : " ")).join("");
|
|
10
12
|
}
|
|
@@ -17,10 +19,6 @@ export function getTreeContinuePrefix(isLast: boolean, theme: Theme): string {
|
|
|
17
19
|
return isLast ? " " : `${theme.tree.vertical} `;
|
|
18
20
|
}
|
|
19
21
|
|
|
20
|
-
export function truncateToWidth(text: string, width: number, ellipsis: string): string {
|
|
21
|
-
return truncateToWidthBase(text, width, ellipsis);
|
|
22
|
-
}
|
|
23
|
-
|
|
24
22
|
export function padToWidth(text: string, width: number, bgFn?: (s: string) => string): string {
|
|
25
23
|
if (width <= 0) return bgFn ? bgFn(text) : text;
|
|
26
24
|
const paddingNeeded = Math.max(0, width - visibleWidth(text));
|
package/src/web/search/render.ts
CHANGED
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
getPreviewLines,
|
|
18
18
|
PREVIEW_LIMITS,
|
|
19
19
|
TRUNCATE_LENGTHS,
|
|
20
|
-
|
|
20
|
+
truncateToWidth,
|
|
21
21
|
} from "../../tools/render-utils";
|
|
22
22
|
import { renderOutputBlock, renderStatusLine, renderTreeList } from "../../tui";
|
|
23
23
|
import type { WebSearchResponse } from "./types";
|
|
@@ -35,7 +35,7 @@ const MAX_REQUEST_ID_LEN = 36;
|
|
|
35
35
|
function renderFallbackText(contentText: string, expanded: boolean, theme: Theme): Component {
|
|
36
36
|
const lines = contentText.split("\n").filter(line => line.trim());
|
|
37
37
|
const maxLines = expanded ? lines.length : 6;
|
|
38
|
-
const displayLines = lines.slice(0, maxLines).map(line =>
|
|
38
|
+
const displayLines = lines.slice(0, maxLines).map(line => truncateToWidth(line.trim(), 110));
|
|
39
39
|
const remaining = lines.length - displayLines.length;
|
|
40
40
|
|
|
41
41
|
const headerIcon = formatStatusIcon("warning", theme);
|
|
@@ -54,7 +54,7 @@ function renderFallbackText(contentText: string, expanded: boolean, theme: Theme
|
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
if (!expanded && remaining > 0) {
|
|
57
|
-
text += `\n ${theme.fg("dim", theme.tree.last)} ${theme.fg("muted", formatMoreItems(remaining, "line"
|
|
57
|
+
text += `\n ${theme.fg("dim", theme.tree.last)} ${theme.fg("muted", formatMoreItems(remaining, "line"))}`;
|
|
58
58
|
}
|
|
59
59
|
|
|
60
60
|
return new Text(text, 0, 0);
|
|
@@ -104,9 +104,7 @@ export function renderWebSearchResult(
|
|
|
104
104
|
const contentText = answerText || rawText;
|
|
105
105
|
const totalAnswerLines = contentText ? contentText.split("\n").filter(l => l.trim()).length : 0;
|
|
106
106
|
const answerLimit = expanded ? MAX_EXPANDED_ANSWER_LINES : MAX_COLLAPSED_ANSWER_LINES;
|
|
107
|
-
const answerPreview = contentText
|
|
108
|
-
? getPreviewLines(contentText, answerLimit, MAX_ANSWER_LINE_LEN, theme.format.ellipsis)
|
|
109
|
-
: [];
|
|
107
|
+
const answerPreview = contentText ? getPreviewLines(contentText, answerLimit, MAX_ANSWER_LINE_LEN) : [];
|
|
110
108
|
|
|
111
109
|
const providerLabel =
|
|
112
110
|
provider === "anthropic"
|
|
@@ -117,9 +115,9 @@ export function renderWebSearchResult(
|
|
|
117
115
|
? "Exa"
|
|
118
116
|
: "Unknown";
|
|
119
117
|
const queryPreview = args?.query
|
|
120
|
-
?
|
|
118
|
+
? truncateToWidth(args.query, 80)
|
|
121
119
|
: searchQueries[0]
|
|
122
|
-
?
|
|
120
|
+
? truncateToWidth(searchQueries[0], 80)
|
|
123
121
|
: undefined;
|
|
124
122
|
const header = renderStatusLine(
|
|
125
123
|
{
|
|
@@ -144,7 +142,7 @@ export function renderWebSearchResult(
|
|
|
144
142
|
theme,
|
|
145
143
|
);
|
|
146
144
|
if (remainingAnswer > 0) {
|
|
147
|
-
answerTree.push(theme.fg("muted", formatMoreItems(remainingAnswer, "line"
|
|
145
|
+
answerTree.push(theme.fg("muted", formatMoreItems(remainingAnswer, "line")));
|
|
148
146
|
}
|
|
149
147
|
|
|
150
148
|
const sourceTree = renderTreeList(
|
|
@@ -160,7 +158,7 @@ export function renderWebSearchResult(
|
|
|
160
158
|
: typeof src.url === "string" && src.url.trim()
|
|
161
159
|
? src.url
|
|
162
160
|
: "Untitled";
|
|
163
|
-
const title =
|
|
161
|
+
const title = truncateToWidth(titleText, 70);
|
|
164
162
|
const url = typeof src.url === "string" ? src.url : "";
|
|
165
163
|
const domain = url ? getDomain(url) : "";
|
|
166
164
|
const age = formatAge(src.ageSeconds) || (typeof src.publishedDate === "string" ? src.publishedDate : "");
|
|
@@ -173,12 +171,7 @@ export function renderWebSearchResult(
|
|
|
173
171
|
const lines: string[] = [`${theme.fg("accent", title)}${metaSuffix}`];
|
|
174
172
|
const snippetText = typeof src.snippet === "string" ? src.snippet : "";
|
|
175
173
|
if (snippetText.trim()) {
|
|
176
|
-
const snippetLines = getPreviewLines(
|
|
177
|
-
snippetText,
|
|
178
|
-
MAX_SNIPPET_LINES,
|
|
179
|
-
MAX_SNIPPET_LINE_LEN,
|
|
180
|
-
theme.format.ellipsis,
|
|
181
|
-
);
|
|
174
|
+
const snippetLines = getPreviewLines(snippetText, MAX_SNIPPET_LINES, MAX_SNIPPET_LINE_LEN);
|
|
182
175
|
for (const snippetLine of snippetLines) {
|
|
183
176
|
lines.push(theme.fg("muted", `${theme.format.dash} ${snippetLine}`));
|
|
184
177
|
}
|
|
@@ -202,7 +195,7 @@ export function renderWebSearchResult(
|
|
|
202
195
|
theme,
|
|
203
196
|
);
|
|
204
197
|
if (!expanded && relatedCount > MAX_COLLAPSED_ITEMS) {
|
|
205
|
-
relatedTree.push(theme.fg("muted", formatMoreItems(relatedCount - MAX_COLLAPSED_ITEMS, "question"
|
|
198
|
+
relatedTree.push(theme.fg("muted", formatMoreItems(relatedCount - MAX_COLLAPSED_ITEMS, "question")));
|
|
206
199
|
}
|
|
207
200
|
|
|
208
201
|
const metaLines: string[] = [];
|
|
@@ -223,16 +216,13 @@ export function renderWebSearchResult(
|
|
|
223
216
|
}
|
|
224
217
|
if (response.requestId) {
|
|
225
218
|
metaLines.push(
|
|
226
|
-
`${theme.fg("muted", "Request:")} ${theme.fg(
|
|
227
|
-
"text",
|
|
228
|
-
truncate(response.requestId, MAX_REQUEST_ID_LEN, theme.format.ellipsis),
|
|
229
|
-
)}`,
|
|
219
|
+
`${theme.fg("muted", "Request:")} ${theme.fg("text", truncateToWidth(response.requestId, MAX_REQUEST_ID_LEN))}`,
|
|
230
220
|
);
|
|
231
221
|
}
|
|
232
222
|
if (searchQueries.length > 0) {
|
|
233
223
|
const queriesPreview = searchQueries.slice(0, MAX_QUERY_PREVIEW);
|
|
234
|
-
const queryList = queriesPreview.map(q =>
|
|
235
|
-
const suffix = searchQueries.length > queriesPreview.length ?
|
|
224
|
+
const queryList = queriesPreview.map(q => truncateToWidth(q, MAX_QUERY_LEN));
|
|
225
|
+
const suffix = searchQueries.length > queriesPreview.length ? "…" : "";
|
|
236
226
|
metaLines.push(`${theme.fg("muted", "Queries:")} ${theme.fg("text", queryList.join("; "))}${suffix}`);
|
|
237
227
|
}
|
|
238
228
|
|
|
@@ -274,7 +264,7 @@ export function renderWebSearchCall(
|
|
|
274
264
|
theme: Theme,
|
|
275
265
|
): Component {
|
|
276
266
|
const provider = args.provider ?? "auto";
|
|
277
|
-
const query =
|
|
267
|
+
const query = truncateToWidth(args.query, 80);
|
|
278
268
|
const text = renderStatusLine({ icon: "pending", title: "Web Search", description: query, meta: [provider] }, theme);
|
|
279
269
|
return new Text(text, 0, 0);
|
|
280
270
|
}
|