-
Notifications
You must be signed in to change notification settings - Fork 9k
Description
Feature hasn't been suggested before.
- I have verified this feature I'm about to request hasn't been suggested before.
Describe the enhancement you want to request
Current Problem:
When building UIs on top of Opencode, there is no way to access tool arguments until the LLM has finished streaming the entire tool call. When the LLM writes or edits large files, we have a 10-60s delay before any information is streamed. This leads to generic implementations like Writing file... as placeholders even though the file path is available in the first few bytes of the streamed JSON.
Current behavior:
- Tool appears with status: "pending"
- state.input is {}, state.raw is ""
- 10-60+ seconds pass while LLM streams {"path": "/foo/bar.tsx", "content": "...hundreds of lines..."}
- Tool transitions to status: "running" with fully parsed state.input
The file path is streamed early, but developers have no way to access it until the entire tool call is complete.
Root cause:
The streaming infrastructure exists but deltas are discarded.
In packages/opencode/src/session/processor.ts:
typescriptcase "tool-input-delta":
break // Delta discarded
case "tool-input-end":
break // Completion ignored
Meanwhile, state.raw is defined in the ToolStatePending schema but never populated.
Proposed solution:
Accumulate tool-input-delta events into state.raw and publish incremental updates.
typescriptcase "tool-input-delta":
const match = toolcalls[value.id]
if (match && match.state.status === "pending") {
await Session.updatePart({
...match,
state: {
...match.state,
raw: (match.state.raw || "") + value.delta,
},
})
}
break
This would allow consumers/developers to parse partial JSON from state.raw to extract early fields (like path), and show meaningful UI feedback during long tool calls. Plus, this maintains backward compatibility (consumers ignoring state.raw are unaffected).
For my use case, I'm streaming generative UI into my chat (similar to cursor) and showing a generic event is super ugly and causes a big hit to UX.
Would love to open a PR on this if the change seems reasonable (for the sake of speed), no obligation to accept it if it conflicts with desired behavior.