feat(web_search): truncate results in TUI view, expand with ctrl+o
Add renderResult showing a collapsed preview (count + first 3 results) until expanded via Ctrl+O. The full markdown still goes to the model via content, so only the display is affected.
This commit is contained in:
@@ -1,7 +1,12 @@
|
|||||||
// Pi-Web Extension - Registers `web_search` and `web_fetch` tools backed by
|
// Pi-Web Extension - Registers `web_search` and `web_fetch` tools backed by
|
||||||
// a shared headless Firefox session. Provider config lives in
|
// a shared headless Firefox session. Provider config lives in
|
||||||
// ~/.pi/pi-web/config.json (env overrides supported).
|
// ~/.pi/pi-web/config.json (env overrides supported).
|
||||||
import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
|
import {
|
||||||
|
keyHint,
|
||||||
|
type AgentToolResult,
|
||||||
|
type ExtensionAPI,
|
||||||
|
type Theme,
|
||||||
|
} from "@mariozechner/pi-coding-agent";
|
||||||
import { Text } from "@mariozechner/pi-tui";
|
import { Text } from "@mariozechner/pi-tui";
|
||||||
import { Type } from "typebox";
|
import { Type } from "typebox";
|
||||||
import { ConfigError, loadConfig, resolveSettings } from "./src/config.ts";
|
import { ConfigError, loadConfig, resolveSettings } from "./src/config.ts";
|
||||||
@@ -10,6 +15,9 @@ import { searchKagi } from "./src/providers/kagi.ts";
|
|||||||
import { searchSearxng } from "./src/providers/searxng.ts";
|
import { searchSearxng } from "./src/providers/searxng.ts";
|
||||||
import { SearchError, type SearchResult } from "./src/types.ts";
|
import { SearchError, type SearchResult } from "./src/types.ts";
|
||||||
|
|
||||||
|
// Collapsed-view preview cap. The full list still goes to the model via `content`.
|
||||||
|
const PREVIEW_RESULTS = 3;
|
||||||
|
|
||||||
function formatResults(results: SearchResult[]): string {
|
function formatResults(results: SearchResult[]): string {
|
||||||
if (results.length === 0) return "(no results)";
|
if (results.length === 0) return "(no results)";
|
||||||
return results
|
return results
|
||||||
@@ -17,6 +25,30 @@ function formatResults(results: SearchResult[]): string {
|
|||||||
.join("\n\n");
|
.join("\n\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function renderSearchResult(
|
||||||
|
result: AgentToolResult<unknown>,
|
||||||
|
expanded: boolean,
|
||||||
|
theme: Theme,
|
||||||
|
): Text {
|
||||||
|
const fullText = result.content[0]?.type === "text" ? result.content[0].text : "";
|
||||||
|
const raw = (result.details as { raw?: SearchResult[] } | undefined)?.raw;
|
||||||
|
|
||||||
|
// Expanded or unavailable details: show the full markdown the model received.
|
||||||
|
if (expanded || !raw || raw.length === 0) {
|
||||||
|
return new Text(fullText, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
let text = theme.fg("muted", `${raw.length} result(s):`);
|
||||||
|
for (const r of raw.slice(0, PREVIEW_RESULTS)) {
|
||||||
|
text += `\n${theme.fg("toolTitle", r.title)} ${theme.fg("dim", r.url)}`;
|
||||||
|
}
|
||||||
|
const more = raw.length - PREVIEW_RESULTS;
|
||||||
|
if (more > 0) {
|
||||||
|
text += `\n${theme.fg("dim", `... ${more} more (${keyHint("app.tools.expand", "to expand")})`)}`;
|
||||||
|
}
|
||||||
|
return new Text(text, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
function formatFetch(r: FetchResult): string {
|
function formatFetch(r: FetchResult): string {
|
||||||
const header =
|
const header =
|
||||||
r.title && r.title.trim()
|
r.title && r.title.trim()
|
||||||
@@ -55,6 +87,9 @@ export default function (pi: ExtensionAPI) {
|
|||||||
text.setText(theme.fg("toolTitle", theme.bold(`web_search "${display}"`)));
|
text.setText(theme.fg("toolTitle", theme.bold(`web_search "${display}"`)));
|
||||||
return text;
|
return text;
|
||||||
},
|
},
|
||||||
|
renderResult(result, { expanded }, theme) {
|
||||||
|
return renderSearchResult(result, expanded, theme);
|
||||||
|
},
|
||||||
async execute(_toolCallId, params) {
|
async execute(_toolCallId, params) {
|
||||||
try {
|
try {
|
||||||
const results = await runSearch(params.query);
|
const results = await runSearch(params.query);
|
||||||
|
|||||||
Reference in New Issue
Block a user