You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
v2: protocol carries no part id; consumer requires one, so text references never reach the jump pipeline #523
Jumping to a symbol/file via <CR> silently misses every file mentioned in assistant text but not touched by a tool call. Tool-edited files work; text-only references never reach the jump pipeline.
Cause
The V2 event protocol does not carry a part id for text/reasoning content. A live server test on 2.0.28 (/api/event) shows session.text.ended payloads are { sessionID, assistantMessageID, ordinal, text } — identity is assistantMessageID + ordinal, and no textID/part.id exists on the wire for these parts (tool parts are the exception: session.tool.* carries a real tool id).
The consumer path assumes every part has part.id:
lua/opencode/ui/reference_facts.luaM.rebuild gates the whole loop on if part.id (:159) and keys the part_refs cache and reference_parser.clear on part.id. V2 text parts never have one, so they are skipped before collect_part_refs runs.
reference_parser.parse_references(part.text, part.id) and the emitted refs carry part_id = part.id.
lua/opencode/protocols/v2/observation/messages.luaordinal_content (:145) builds { kind = kind, text = '' } and only uses ordinal as an internal index key ("text:0", "reasoning:0"); the ordinal is never stored on the content part, so downstream has no way to reconstruct identity either.
This is not a normalize bug: V2 wire events genuinely have no part id for text/reasoning, and V1's content_mappers keeping id = part.id (protocols/v1/normalize.lua:587,598) reflects a V1-only property. The fix belongs in the consumer.
Why it's silent
Tool parts carry id + target.path, so files the assistant edited still reach current_files and drive symbol jump. Only assistant text references are dropped, and both paths share current_files — the broken path is masked by the working tool path. In practice: jumping to a symbol in a file the assistant only mentions (no edit tool call) always fails with No symbol target found.
Fix
Give the V2 consumer a stable per-part identity from the wire data: (assistantMessageID, kind, ordinal).
In lua/opencode/protocols/v2/observation/messages.lua, store the ordinal on the content part in ordinal_content (e.g. content.ordinal = data.ordinal), so identity survives normalization.
In lua/opencode/ui/reference_facts.lua, derive a synthetic part_id for parts lacking one — message.id .. ':' .. kind .. ':' .. tostring(ordinal) — and use it for the part_refs cache, reference_parser bookkeeping, and the refs' part_id field. Tool parts keep their real id.
V1 is unaffected (it already has part.id). No change to normalize.lua needed.
changed the title [-]v2: assistant text/reasoning parts drop id, text references never reach jump pipeline[/-][+]v2: protocol carries no part id; consumer requires one, so text references never reach the jump pipeline[/+]on Oct 14, 2026
Activity
jensenojs commentedon Oct 14, 2026
still need code clean..
[-]v2: assistant text/reasoning parts drop id, text references never reach jump pipeline[/-][+]v2: protocol carries no part id; consumer requires one, so text references never reach the jump pipeline[/+]