mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-24 03:15:46 -06:00
fix(tool-display): avoid recursive search summaries (#114933)
* fix(tool-display): avoid recursive search summaries Fixes #113401.\n\nCo-authored-by: qingminlong <qing.minlong@xydigit.com> * fix(tool-display): recognize neutral search summaries * style(tool-display): format summary matcher
This commit is contained in:
committed by
GitHub
parent
6dbe7ff1e2
commit
ca82f7dfbc
@@ -118,6 +118,9 @@ function summarizeKnownExec(words: string[]): string {
|
||||
const pattern = optionValue(words, ["-e", "--regexp"]) ?? positional[0];
|
||||
const target = positional.length > 1 ? positional.at(-1) : undefined;
|
||||
if (pattern) {
|
||||
if (isUnsafeSearchSummaryPattern(pattern)) {
|
||||
return target ? `search text in ${target}` : "search text";
|
||||
}
|
||||
return target ? `search "${pattern}" in ${target}` : `search "${pattern}"`;
|
||||
}
|
||||
return "search text";
|
||||
@@ -290,6 +293,27 @@ function summarizeKnownExec(words: string[]): string {
|
||||
return /^[A-Za-z0-9._/-]+$/.test(arg) ? `run ${bin} ${arg}` : `run ${bin}`;
|
||||
}
|
||||
|
||||
function isUnsafeSearchSummaryPattern(pattern: string): boolean {
|
||||
const trimmed = pattern.trim();
|
||||
return (
|
||||
!trimmed ||
|
||||
pattern.length > 120 ||
|
||||
/[\r\n`]/u.test(pattern) ||
|
||||
/^Bash failed:/iu.test(trimmed) ||
|
||||
containsGeneratedSearchSummary(trimmed)
|
||||
);
|
||||
}
|
||||
|
||||
// Match the two labels this formatter emits, without hiding normal prose such as
|
||||
// "search engine" or "search textual data".
|
||||
const GENERATED_SEARCH_SUMMARY_FRAGMENT_RE = /^search\s+(?:["']|text(?:\s+in(?:\s|$)|$))/iu;
|
||||
|
||||
function containsGeneratedSearchSummary(pattern: string): boolean {
|
||||
return pattern
|
||||
.split(/(?:\||->)/u)
|
||||
.some((fragment) => GENERATED_SEARCH_SUMMARY_FRAGMENT_RE.test(fragment.trim()));
|
||||
}
|
||||
|
||||
function summarizePipeline(stage: string): string {
|
||||
const pipeline = splitTopLevelPipes(stage);
|
||||
if (pipeline.length > 1) {
|
||||
|
||||
@@ -224,6 +224,56 @@ describe("tool display details", () => {
|
||||
expect(detail).toBe("print lines 1-80 from extensions/discord/src/draft-stream.ts");
|
||||
});
|
||||
|
||||
it("keeps normal search patterns concise", () => {
|
||||
for (const [command, expected] of [
|
||||
['rg "foo|bar" src/agents', 'search "foo|bar" in src/agents'],
|
||||
["rg 'search engine' src/agents", 'search "search engine" in src/agents'],
|
||||
["rg 'search textual data' src/agents", 'search "search textual data" in src/agents'],
|
||||
["rg 'research text in docs' src/agents", 'search "research text in docs" in src/agents'],
|
||||
]) {
|
||||
expect(
|
||||
formatToolDetail(
|
||||
resolveToolDisplay({ name: "exec", args: { command }, detailMode: "explain" }),
|
||||
),
|
||||
).toBe(expected);
|
||||
}
|
||||
});
|
||||
|
||||
it("uses a neutral label for recursive or malformed search patterns", () => {
|
||||
for (const command of [
|
||||
`rg 'search "foo" in src/agents' src`,
|
||||
`rg 'Bash failed: search "foo" in src|search "bar"' src`,
|
||||
`rg 'run printf -> search "foo" in src' src`,
|
||||
"rg 'search text' src",
|
||||
"rg 'search text in src/agents' src",
|
||||
"rg 'foo|search text in src/agents' src",
|
||||
"rg 'run printf -> search text' src",
|
||||
"rg 'line1\nline2' src",
|
||||
"rg 'line with trailing newline\n' src",
|
||||
"rg '`generated command`' src",
|
||||
`rg '${"x".repeat(121)}' src`,
|
||||
`rg '${" ".repeat(121)}x' src`,
|
||||
]) {
|
||||
expect(
|
||||
formatToolDetail(
|
||||
resolveToolDisplay({ name: "exec", args: { command }, detailMode: "explain" }),
|
||||
),
|
||||
).toBe("search text in src");
|
||||
}
|
||||
});
|
||||
|
||||
it("sanitizes recursive search patterns inside pipelines", () => {
|
||||
expect(
|
||||
formatToolDetail(
|
||||
resolveToolDisplay({
|
||||
name: "exec",
|
||||
args: { command: `printf x | rg 'search "foo" in src' .` },
|
||||
detailMode: "explain",
|
||||
}),
|
||||
),
|
||||
).toBe("print text -> search text in .");
|
||||
});
|
||||
|
||||
it("moves cd path to context suffix and appends raw command", () => {
|
||||
const detail = formatToolDetail(
|
||||
resolveToolDisplay({
|
||||
|
||||
Reference in New Issue
Block a user