Skip to content

Commit 9ec1a3d

Browse files
authored
Hide code searcher result payload (#633)
1 parent fd62c67 commit 9ec1a3d

5 files changed

Lines changed: 112 additions & 11 deletions

File tree

agents/file-explorer/code-searcher.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ const codeSearcher: SecretAgentDefinition = {
8585
yield {
8686
toolName: 'set_output',
8787
input: {
88+
message: '',
8889
results: toolResults,
8990
},
9091
includeToolCall: false,
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import { describe, expect, test } from 'bun:test'
2+
import React from 'react'
3+
import { renderToStaticMarkup } from 'react-dom/server'
4+
5+
import { initializeThemeStore } from '../../../hooks/use-theme'
6+
import { CodeSearchComponent } from '../code-search'
7+
8+
import type { ChatTheme } from '../../../types/theme-system'
9+
import type { ToolBlock } from '../types'
10+
11+
initializeThemeStore()
12+
13+
const createToolBlock = (
14+
output?: string,
15+
): ToolBlock & { toolName: 'code_search' } => ({
16+
type: 'tool',
17+
toolName: 'code_search',
18+
toolCallId: 'code-search-test',
19+
input: {
20+
pattern: 'getAgentBaseName',
21+
cwd: 'cli/src/utils',
22+
},
23+
output,
24+
})
25+
26+
describe('CodeSearchComponent', () => {
27+
test('uses formatted match count from current code search output', () => {
28+
const result = CodeSearchComponent.render(
29+
createToolBlock(`Found 2 matches
30+
./message-block-helpers.ts:
31+
Line 13: export const getAgentBaseName = (type: string): string => {
32+
Line 196: getAgentBaseName(options.agentType ?? '') === 'code-searcher'`),
33+
{} as ChatTheme,
34+
{
35+
availableWidth: 80,
36+
indentationOffset: 0,
37+
labelWidth: 10,
38+
},
39+
)
40+
41+
const markup = renderToStaticMarkup(<>{result.content}</>)
42+
43+
expect(markup).toContain('getAgentBaseName in cli/src/utils (2 results)')
44+
})
45+
})

cli/src/components/tools/code-search.tsx

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,22 @@ export const CodeSearchComponent = defineToolComponent({
2323

2424
if (toolBlock.output && typeof toolBlock.output === 'string') {
2525
const lines = toolBlock.output.split('\n')
26+
const matchCountLine = lines.find((line) =>
27+
/^Found \d+ matches?$/.test(line.trim()),
28+
)
29+
const parsedTotalResults = matchCountLine
30+
?.trim()
31+
.match(/^Found (\d+) matches?$/)?.[1]
2632

27-
for (const line of lines) {
28-
const trimmed = line.trim()
33+
if (parsedTotalResults !== undefined) {
34+
totalResults = Number(parsedTotalResults)
35+
} else {
36+
for (const line of lines) {
37+
const trimmed = line.trim()
2938

30-
// Result lines start with a number followed by a colon
31-
if (/^\d+:/.test(trimmed)) {
32-
totalResults++
39+
if (/^(?:Line\s+)?\d+:/.test(trimmed)) {
40+
totalResults++
41+
}
3342
}
3443
}
3544
}
@@ -52,12 +61,7 @@ export const CodeSearchComponent = defineToolComponent({
5261

5362
// Return as content using SimpleToolCallItem
5463
return {
55-
content: (
56-
<SimpleToolCallItem
57-
name="Search"
58-
description={summary}
59-
/>
60-
),
64+
content: <SimpleToolCallItem name="Search" description={summary} />,
6165
}
6266
},
6367
})

cli/src/utils/__tests__/message-block-helpers.test.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -376,6 +376,23 @@ describe('extractSpawnAgentResultContent', () => {
376376
hasError: false,
377377
})
378378
})
379+
380+
test('uses an empty structuredOutput message as no display content', () => {
381+
const result = extractSpawnAgentResultContent({
382+
type: 'structuredOutput',
383+
value: {
384+
message: '',
385+
results: [
386+
{
387+
stdout: 'Found 1 match\n./file.ts:\nLine 1: needle',
388+
message: 'Exit code: 0',
389+
},
390+
],
391+
},
392+
})
393+
394+
expect(result).toEqual({ content: '', hasError: false })
395+
})
379396
})
380397

381398
describe('appendInterruptionNotice', () => {

docs/testing.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,37 @@ CLI hook testing note: React 19 + Bun + RTL `renderHook()` is unreliable; prefer
99
## CLI tmux Testing
1010

1111
For testing CLI behavior via tmux, use the helper scripts in `scripts/tmux/`. These handle bracketed paste mode and session logging automatically. Session data is saved to `debug/tmux-sessions/` in YAML format and can be viewed with `bun scripts/tmux/tmux-viewer/index.tsx`. See `scripts/tmux/README.md` for details.
12+
13+
Useful workflow for agents:
14+
15+
```bash
16+
# Start the dev CLI in a detached tmux session.
17+
SESSION=$(./scripts/tmux/tmux-cli.sh start --name cli-check -w 160 -h 40 --wait 6)
18+
19+
# Capture the initial screen. Captures are written to debug/tmux-sessions/$SESSION/.
20+
./scripts/tmux/tmux-cli.sh capture "$SESSION" --label initial
21+
22+
# Send a prompt. The helper uses bracketed paste so text is not dropped.
23+
./scripts/tmux/tmux-cli.sh send "$SESSION" "Search for getAgentBaseName and report what you find" --wait-idle 4
24+
25+
# Capture after the run, then inspect the saved capture text.
26+
./scripts/tmux/tmux-cli.sh capture "$SESSION" --label after-search --wait 2
27+
28+
# Clean up when finished.
29+
./scripts/tmux/tmux-cli.sh stop "$SESSION"
30+
```
31+
32+
If a change can be verified with a small local harness instead of a live model-backed CLI run, run that harness inside tmux too. This still checks terminal rendering and produces a capture:
33+
34+
```bash
35+
SESSION=$(./scripts/tmux/tmux-cli.sh start \
36+
--name render-check \
37+
-w 160 -h 20 \
38+
--wait 1 \
39+
--command "bun .context/my-render-check.tsx")
40+
41+
./scripts/tmux/tmux-cli.sh capture "$SESSION" --label rendered
42+
./scripts/tmux/tmux-cli.sh stop "$SESSION"
43+
```
44+
45+
When verifying UI output, prefer checking the saved capture file for concrete strings that should and should not appear. For example, after expanding a code-searcher agent, check that the capture shows the search summary but not raw structured payload keys like `results:` or `stdout:`.

0 commit comments

Comments
 (0)