@f5xc-salesdemos/xcsh 17.3.0 → 17.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/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "@f5xc-salesdemos/xcsh",
|
|
4
|
-
"version": "17.
|
|
4
|
+
"version": "17.4.1",
|
|
5
5
|
"description": "Coding agent CLI with read, bash, edit, write tools and session management",
|
|
6
6
|
"homepage": "https://github.com/f5xc-salesdemos/xcsh",
|
|
7
7
|
"author": "Can Boluk",
|
|
@@ -46,12 +46,12 @@
|
|
|
46
46
|
"dependencies": {
|
|
47
47
|
"@agentclientprotocol/sdk": "0.16.1",
|
|
48
48
|
"@mozilla/readability": "^0.6",
|
|
49
|
-
"@f5xc-salesdemos/xcsh-stats": "17.
|
|
50
|
-
"@f5xc-salesdemos/pi-agent-core": "17.
|
|
51
|
-
"@f5xc-salesdemos/pi-ai": "17.
|
|
52
|
-
"@f5xc-salesdemos/pi-natives": "17.
|
|
53
|
-
"@f5xc-salesdemos/pi-tui": "17.
|
|
54
|
-
"@f5xc-salesdemos/pi-utils": "17.
|
|
49
|
+
"@f5xc-salesdemos/xcsh-stats": "17.4.1",
|
|
50
|
+
"@f5xc-salesdemos/pi-agent-core": "17.4.1",
|
|
51
|
+
"@f5xc-salesdemos/pi-ai": "17.4.1",
|
|
52
|
+
"@f5xc-salesdemos/pi-natives": "17.4.1",
|
|
53
|
+
"@f5xc-salesdemos/pi-tui": "17.4.1",
|
|
54
|
+
"@f5xc-salesdemos/pi-utils": "17.4.1",
|
|
55
55
|
"@sinclair/typebox": "^0.34",
|
|
56
56
|
"@xterm/headless": "^6.0",
|
|
57
57
|
"ajv": "^8.18",
|
|
@@ -1313,6 +1313,15 @@ export const SETTINGS_SCHEMA = {
|
|
|
1313
1313
|
default: true,
|
|
1314
1314
|
ui: { tab: "tools", label: "Web Search", description: "Enable the web_search tool for web searching" },
|
|
1315
1315
|
},
|
|
1316
|
+
"web_search.verbose": {
|
|
1317
|
+
type: "boolean",
|
|
1318
|
+
default: false,
|
|
1319
|
+
ui: {
|
|
1320
|
+
tab: "tools",
|
|
1321
|
+
label: "Web Search Verbose",
|
|
1322
|
+
description: "Show detailed search panels (sources, metadata, tokens). When disabled, uses compact output.",
|
|
1323
|
+
},
|
|
1324
|
+
},
|
|
1316
1325
|
|
|
1317
1326
|
"browser.enabled": {
|
|
1318
1327
|
type: "boolean",
|
package/src/web/search/index.ts
CHANGED
|
@@ -192,6 +192,7 @@ async function executeSearch(
|
|
|
192
192
|
for (const provider of providers) {
|
|
193
193
|
lastProvider = provider;
|
|
194
194
|
try {
|
|
195
|
+
const searchStart = performance.now();
|
|
195
196
|
const response = await provider.search({
|
|
196
197
|
query: params.query.replace(/202\d/g, String(new Date().getFullYear())), // LUL
|
|
197
198
|
limit: params.limit,
|
|
@@ -205,6 +206,7 @@ async function executeSearch(
|
|
|
205
206
|
maxUses: params.max_uses,
|
|
206
207
|
userLocation: params.user_location,
|
|
207
208
|
});
|
|
209
|
+
response.durationMs = performance.now() - searchStart;
|
|
208
210
|
|
|
209
211
|
const text = formatForLLM(response);
|
|
210
212
|
|
|
@@ -290,7 +292,9 @@ export const webSearchCustomTool: CustomTool<typeof webSearchSchema, SearchRende
|
|
|
290
292
|
renderResult(result, options: RenderResultOptions, theme: Theme) {
|
|
291
293
|
return renderSearchResult(result, options, theme);
|
|
292
294
|
},
|
|
293
|
-
|
|
295
|
+
|
|
296
|
+
mergeCallAndResult: true as const,
|
|
297
|
+
} as CustomTool<typeof webSearchSchema, SearchRenderDetails> & { mergeCallAndResult: true };
|
|
294
298
|
|
|
295
299
|
export function getSearchTools(): CustomTool<any, any>[] {
|
|
296
300
|
return [webSearchCustomTool];
|
package/src/web/search/render.ts
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
import type { Component } from "@f5xc-salesdemos/pi-tui";
|
|
8
8
|
import { Text, visibleWidth, wrapTextWithAnsi } from "@f5xc-salesdemos/pi-tui";
|
|
9
|
+
import { Settings } from "../../config/settings";
|
|
9
10
|
import type { RenderResultOptions } from "../../extensibility/custom-tools/types";
|
|
10
11
|
import type { Theme } from "../../modes/theme/theme";
|
|
11
12
|
import {
|
|
@@ -25,6 +26,14 @@ import { CachedOutputBlock } from "../../tui/output-block";
|
|
|
25
26
|
import { getSearchProvider } from "./provider";
|
|
26
27
|
import type { SearchResponse } from "./types";
|
|
27
28
|
|
|
29
|
+
function getVerboseSetting(): boolean {
|
|
30
|
+
try {
|
|
31
|
+
return Settings.instance.get("web_search.verbose");
|
|
32
|
+
} catch {
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
28
37
|
const MAX_COLLAPSED_ANSWER_LINES = PREVIEW_LIMITS.COLLAPSED_LINES;
|
|
29
38
|
const MAX_EXPANDED_ANSWER_LINES = PREVIEW_LIMITS.EXPANDED_LINES;
|
|
30
39
|
const MAX_ANSWER_LINE_LEN = TRUNCATE_LENGTHS.LINE;
|
|
@@ -92,13 +101,34 @@ export function renderSearchResult(
|
|
|
92
101
|
return renderFallbackText(rawText, options.expanded, theme);
|
|
93
102
|
}
|
|
94
103
|
|
|
104
|
+
const searchQueries = Array.isArray(response.searchQueries)
|
|
105
|
+
? response.searchQueries.filter(item => typeof item === "string")
|
|
106
|
+
: [];
|
|
107
|
+
|
|
108
|
+
const verbose = getVerboseSetting();
|
|
109
|
+
if (!verbose) {
|
|
110
|
+
const searches = response.usage?.searchRequests ?? 1;
|
|
111
|
+
const plural = searches !== 1 ? "es" : "";
|
|
112
|
+
const dur =
|
|
113
|
+
response.durationMs !== undefined
|
|
114
|
+
? response.durationMs >= 1000
|
|
115
|
+
? `${Math.round(response.durationMs / 1000)}s`
|
|
116
|
+
: `${Math.round(response.durationMs)}ms`
|
|
117
|
+
: "";
|
|
118
|
+
const queryPreview = args?.query
|
|
119
|
+
? truncateToWidth(args.query, 80)
|
|
120
|
+
: searchQueries[0]
|
|
121
|
+
? truncateToWidth(searchQueries[0], 80)
|
|
122
|
+
: undefined;
|
|
123
|
+
const header = queryPreview ? `Web Search("${queryPreview}")` : "Web Search";
|
|
124
|
+
const summary = ` \u23BF Did ${searches} search${plural}${dur ? ` in ${dur}` : ""}`;
|
|
125
|
+
return new Text(`${theme.fg("text", header)}\n${theme.fg("dim", summary)}`, 0, 0);
|
|
126
|
+
}
|
|
127
|
+
|
|
95
128
|
const sources = Array.isArray(response.sources) ? response.sources : [];
|
|
96
129
|
const sourceCount = sources.length;
|
|
97
130
|
const citations = Array.isArray(response.citations) ? response.citations : [];
|
|
98
131
|
const citationCount = citations.length;
|
|
99
|
-
const searchQueries = Array.isArray(response.searchQueries)
|
|
100
|
-
? response.searchQueries.filter(item => typeof item === "string")
|
|
101
|
-
: [];
|
|
102
132
|
const provider = response.provider;
|
|
103
133
|
|
|
104
134
|
// Get answer text
|
|
@@ -288,6 +318,10 @@ export function renderSearchCall(
|
|
|
288
318
|
theme: Theme,
|
|
289
319
|
): Component {
|
|
290
320
|
const query = truncateToWidth(args.query ?? "", 80);
|
|
321
|
+
const verbose = getVerboseSetting();
|
|
322
|
+
if (!verbose) {
|
|
323
|
+
return new Text(`${theme.fg("text", `Web Search("${query}")`)}`, 0, 0);
|
|
324
|
+
}
|
|
291
325
|
const text = renderStatusLine({ icon: "pending", title: "Web Search", description: query }, theme);
|
|
292
326
|
return new Text(text, 0, 0);
|
|
293
327
|
}
|
package/src/web/search/types.ts
CHANGED
|
@@ -94,6 +94,8 @@ export interface SearchResponse {
|
|
|
94
94
|
requestId?: string;
|
|
95
95
|
/** Authentication mode used by the provider (e.g. oauth, api-key) */
|
|
96
96
|
authMode?: string;
|
|
97
|
+
/** Wall-clock duration of the search request in milliseconds */
|
|
98
|
+
durationMs?: number;
|
|
97
99
|
}
|
|
98
100
|
|
|
99
101
|
/** Provider-specific error with optional HTTP status */
|