mirror of
https://github.com/wu736139669/hapi.git
synced 2026-08-05 06:24:37 +00:00
* fix(acp): derive tool_call input from kind+title fallback
Gemini 2.5 Flash and 3 Flash Preview omit rawInput entirely on
tool_call events while emitting prose (non-JSON) thoughts. Neither
the existing rawInput path nor JSON-thought hoisting fires, so the
UI shows "Input: null" alongside a perfectly readable title like
"README.md" or "ls -la /tmp".
Add a conservative fallback that maps known kinds to a minimal
input shape:
read -> { file_path: title }
execute -> { command: title }
search -> { pattern: title }
think -> null (topic-update prose has no clean arg mapping)
unknown -> null (no guessing on shapes we have not verified)
Priority: rawInput > hoisted JSON thought > kind+title derive.
Lock the new behaviour with synthetic unit tests (8 cases) and a
real-Gemini fixture suite captured from gemini-3-flash-preview
and gemini-2.5-flash via ACP stdio (4 fixtures, 33/27/13/4 raw
sessionUpdate events). The fixtures double as regression guards
against future ACP handler changes.
* fix(web): suppress duplicate subtitle when equal to tool title
Gemini ACP emits a tool_call whose title field is a human-readable
summary (often the verbatim shell command or file path). Combined with
the kind+title input fallback, an unknown-tool card ends up with the
same string in both the title and subtitle slots — e.g. title
"cat /tmp/hello.txt" over subtitle "cat /tmp/hello.txt".
Add a guard in getToolPresentation's unknown-tool branch: emit
subtitle only when it differs from toolName. The known-tool and
mcp__* branches are unaffected.
* test(acp): align Gemini fixtures to current model set
- Drop gemini-2.5-flash fixtures: the captures came from a model that
is not part of the PR's evidence model set, and re-running the
capture is gated on quota that is not currently available.
- Refresh gemini-3-flash-preview read_file / run_shell fixtures with
a fresh live capture so they reflect the latest ACP shape (e.g.
a `kind: think` tool_call expressing reasoning when the model emits
no agent_thought_chunk).
- Update fixture-replay expectations: read_file no longer requires
reasoning chunks (zero are emitted on this path) and now requires
>= 2 tool_calls (think + read).
* feat(web): promote semantic title for Gemini ACP tool cards
When the unknown-tool ToolCard would render the same string as both
the title and the subtitle, promote a semantic label to the title
slot so the card reads like a sentence:
cat /tmp/hello.txt → Run shell / cat /tmp/hello.txt
README.md → Read file / README.md
*.ts → Search / *.ts
This is a web-only ergonomic change; the underlying ACP message
shape (tool_name = title, input = derived from kind+title) is
unchanged. Builds on the dedup guard so the title-equals-subtitle
case is now handled by promotion rather than by hiding the subtitle.
* fix(acp): derive tool_call.input for kind=edit from locations[0].path
Gemini's write_file and replace tools both surface as ACP tool_call
with kind="edit" and rawInput omitted. The path lives on locations[0]
from the very first event; the title is prose like "Writing to foo.txt"
or "foo.txt: old => new", which is not safely usable as a file_path.
Extend the kind+title fallback to read locations[0].path when kind is
"edit", and synthesize { file_path } from it. Title fallback is
intentionally not used here so we never feed prose into file_path.
Lock the behaviour in with two new fixtures captured live from
gemini-3-flash-preview (write_file and replace) plus two synthetic
unit tests covering the locations-present and locations-empty paths.
* test(acp): add gemini-3.1-pro-preview fixtures for regression coverage
Captured 4 raw ACP `sessionUpdate` sequences from a live
`gemini-3.1-pro-preview` session via the same isolated hub +
runner + spawn pattern used for the existing flash captures
(read_file 31 events / run_shell 83 events / write_file 4 events /
edit_file 11 events).
The pro tier reuses the same kind/title shape as flash:
`rawInput` is omitted on every tool_call across read / execute /
edit kinds, so the kind+title (and locations[0].path for edit)
fallback is exactly what derives the modal Input. Locking these
fixtures in guards against future regressions on a second model.
The fixture-based regression test gains 4 entries (read / shell /
write / edit) mirroring the flash matrix; assertions are unchanged.
ACP handler suite: 53 -> 57 pass.
59 lines
1.6 KiB
JSON
59 lines
1.6 KiB
JSON
{
|
|
"model": "gemini-3.1-pro-preview",
|
|
"scenario": "write_file",
|
|
"prompt": "Please create a new file at cli/pr-fixture-write.txt with the content 'pro fixture line'",
|
|
"captured_at": "2026-05-04T03:08:46.000Z",
|
|
"updates": [
|
|
{
|
|
"sessionUpdate": "tool_call",
|
|
"toolCallId": "write_file-1777864040205-1",
|
|
"status": "in_progress",
|
|
"title": "Writing to cli/pr-fixture-write.txt",
|
|
"content": [],
|
|
"locations": [
|
|
{
|
|
"path": "/home/lupin/workspace/hapi-fix-gemini-display/cli/pr-fixture-write.txt"
|
|
}
|
|
],
|
|
"kind": "edit"
|
|
},
|
|
{
|
|
"sessionUpdate": "tool_call_update",
|
|
"toolCallId": "write_file-1777864040205-1",
|
|
"status": "completed",
|
|
"title": "Writing to cli/pr-fixture-write.txt",
|
|
"content": [
|
|
{
|
|
"type": "diff",
|
|
"path": "/home/lupin/workspace/hapi-fix-gemini-display/cli/pr-fixture-write.txt",
|
|
"oldText": "",
|
|
"newText": "pro fixture line",
|
|
"_meta": {
|
|
"kind": "add"
|
|
}
|
|
}
|
|
],
|
|
"locations": [
|
|
{
|
|
"path": "/home/lupin/workspace/hapi-fix-gemini-display/cli/pr-fixture-write.txt"
|
|
}
|
|
],
|
|
"kind": "edit"
|
|
},
|
|
{
|
|
"sessionUpdate": "agent_message_chunk",
|
|
"content": {
|
|
"type": "text",
|
|
"text": "`cli/pr-fixture-write"
|
|
}
|
|
},
|
|
{
|
|
"sessionUpdate": "agent_message_chunk",
|
|
"content": {
|
|
"type": "text",
|
|
"text": ".txt` 파일 생성을 완료했습니다. 요청하신 내용이 성공적으로 작성되었습니다."
|
|
}
|
|
}
|
|
]
|
|
}
|