Conversation
88f78f1 to
bfd06c4
Compare
* refactor: replace api_client/event_manager/session with per-protocol
operations and Observation modules under protocols/{v1,v2}
* feat: auth health probe selects the protocol once per connection;
identity change forces reconnect, no per-request branching
* feat: connect to the native V2 shared service via CLI discovery;
V1 keeps local spawn, explicit URLs, and port coordination
* fix(renderer): rebuild topbar stats bridge from observation usage
(session.usage.updated and snapshot first, latest entry fallback)
* fix(v2): handle session.usage.updated; drop dead branches for
server-absent session.tool.error and file.watcher.updated
* test: per-protocol contract suites and live-captured V2 fixtures
from a real 2.0.1 server; counterexamples for cross-session event
pollution and malformed usage payloads
* docs: add migration draft under docs/drafts; update bidirectional-sync
recipe for the native V2 service path
|
This might be my last chance to clean up the code; I really wish I had enough time... |
gg and scrolling up stopped at the first protocol page in long sessions. The renderer now pulls older pages through load_older / load_complete_history and grows its window past the merge, with a single view-anchor primitive. - topology: regroup session_tab modules and lru_cache - draft: reorganize as an architecture baseline
|
I started to play with it. I just fixed a bug in v1 where the panel is in perpetual loading. I will try to fix the issue I see as they come. This is a significant change from the prior architecture. I would have liked a simpler and iterative approach. There is a lot of issues at the moment so It's hard to assess if this is a good base or not. I will try to fix some issues and see. |
task.tool_action_line reverse-required the formatter registry to look up child-tool summaries, forming a two-module cycle. The dispatch site (format_tool) owns the registry, so it now passes it down as an argument.
port_mapping required opencode_server only for its static kill_pid, forming a two-module cycle. The function is process tooling, not server identity, so it now lives in util; behavior is unchanged (one level of children, then the parent).
A flat one-level walk leaked grandchildren as orphans. Real trees are deeper than one level: the running server spawns MCP/tool processes that spawn children of their own (measured: serve -> node MCP -> node worker). Depth-first kill order: grandchildren, children, then the parent.
The no_entry_to_infra comment already acknowledged that :checkhealth calls infrastructure directly — diagnostics must drive the real connection lifecycle to verify what they report. Rules can now declare allowed module pairs, so the exception is machine-checked instead of living only in a comment. The health -> server_job edge is the first.
The kill_pid move left a duplicated stub block in port_mapping_spec,
making the file unloadable; concurrent stderr replay hid the syntax
error behind '0 failing tests'. The runner now also reports Lua syntax
errors ('...file.lua:NN: ... near ...') as load errors and treats
Scheduling headers as file windows, so a spec that never loads fails
the run instead of passing silently.
|
I understand
|
|
It's not bad or anything, don't get me wrong. |
|
I completely understand; even my testing on v2 was insufficient. I just urgently need a version that works on v2 besides, having a flawed implementation to critique is also very good. |
- Send selected provider/model/variant via set_session_model before submitting V2 protocol messages. - Sync active session metadata (title/location) from observed sessions.
…cheduler delay The resize path schedules its work from the TextChanged autocmd, so the height settles only when the event loop flushes the callback. Under the concurrent runner another spec can hold the loop past the 100ms window, and vim.wait times out with false, -1. Widen the window and surface the observed height when it still fails.
Servers record mention offsets when the mention is inserted; edits to the surrounding text leave them pointing at the wrong range. Failing the whole snapshot over one misplaced mention made such sessions impossible to open. Degrade to a mention-less attachment and log a warning instead.
prompt_body emptied body.files before the user file loop appended into it, so a submission with file attachments but no editor context crashed on a nil index. Move the empty check to the end of prompt_body; the wire shape is unchanged (no files field when there is nothing to attach). Reported and independently patched by bivashy in PR sudo-tee#494. Co-authored-by: bivashy <me@bivashy.dev>
Extract protocol health probing into per-protocol connection adapters and drop the version pin on V1 health checks, requiring only a healthy status. Own the legacy serve launcher under protocols.v1.server, persist generated passwords to an owner-only per-port state file, and reuse a configured fixed-port server before spawning a new one. Probe retries absorb transient startup transport errors.
The model catalog have the same modelID for different versions of the same model, so we should use the unique id instead.
Add apply_tool_metadata to normalize server-provided file diff metadata for patch/apply_patch tools into result.changes. Wire it into observation ingest for tool input and session.tool.success/failed events. Add patch formatter supporting both part.changes and patchText-based patches, unnumbered update hunks, and add-file diffs with numbered gutter highlights. Register shell under the bash formatter to render V2 shell tools with their native tool name. Include unit tests for shell/patch rendering and metadata-backed line numbers.
Add apply_tool_input to map read/edit/write file paths and skill names from raw tool inputs into normalized formatter fields, and wire it into both snapshot normalization and observation ingestion.
Make close() preserve hidden output buffers when persist_state is enabled, matching toggle() and hide() behavior, instead of always fully tearing down the UI. Update README to document the new close semantics and add unit tests covering buffer preservation across close/reopen.
The permission reply body was sent as the raw answer argument. Wrap it in a table with decision and message fields to match the expected API payload shape, and assert the serialized body in the unit spec.
Capture file path for pasted images used its full temp path, so @mentions in prompts never matched and the image was silently dropped. Fall back to the basename for pasted_image_* files so mentions resolve correctly. Adds unit test covering basename mention offsets for pasted images.
Replace util.is_temp_path check with a filename match for pasted_image_ prefix in chat_context capture_file, and simplify the related test to use /tmp directly.
Move revert_message/unrevert_messages onto the Observation layer so successful actions commit authoritative session state and publish session-change events before returning. - v1 and v2 observations now expose revert_message/unrevert_messages via _start_state_action, updating session.revert inline - session handler undo/redo call the Observation instead of reaching into connection.operations - v1 normalize surfaces session.revert for the renderer - renderer builds the undo summary message from session.revert and hides reverted entries on both incremental and full renders - add unit coverage for handler routing, protocol state commits, and renderer reconcile on revert/redo
Break the monolithic V2 observation module into messages, resources, events, actions, and a shared boundary module, and document the protocol contract in types.lua. Keep event routing and submission semantics unchanged; hang validation annotations at the HTTP boundary instead of duplicating checks in operations.
- add check_types.sh wrapper that resolves VIMRUNTIME for emmylua_check - configure .emmyrc.json vim globals and ignore dirs - document emmylua_ls workflow and contracts in AGENTS.md - fix lint issues: missing icons require, stale type annotations, doc comment cleanup
Split focus subscription from context-related subscriptions so the debounced reload only fires when losing focus, not when focus returns to the opencode window. Move open-action resolution before the focus check so the action is always resolved.
…ession This will also ensure that the current vim selection is forwarded to the new one
|
I think I ran out of bugs or thinks to fix/simplify. It seems to work pretty well for me on both v1 and v2 and the code seems to be well seperated after some polishing There ia a conflict with main I can't fix since I cannot force push on your branch. Do you have any remaining issues with this branch ? Before merging I will create a |
Summary
Reworks the client to speak both OpenCode wire protocols (V1 1.18.x and V2 2.0.x) through a single connection/observation architecture.
What changed
protocols/{v1,v2}modules own native endpoints and event interpretation per protocol;ui/consumes one read-only per-session Observation instead of reducing protocol events.service status/get password); V1 keeps local spawn, explicit URLs, and port coordination.api_client,event_manager,session,renderer/events,event_scope,session_scope.session.usage.updated/ snapshot first, latest entry fallback for V1).run_tests.shnow names the spec file when a test file dies at load time (e.g. requiring a removed module), instead of a bare non-zero exit.Contract
The published OpenAPI spec and the running 2.0.x server disagree at several endpoints (
/api/project/current,renamevia POST, promptcommandfield,forkbody shape). This implementation follows the running server; fixtures undertests/data/v2/are live captures from a real 2.0.1 server. Known future break: upstream dev renamespermission.asked/form.*events.Details in
docs/drafts/v2-migration-draft.md(temporary draft intended to be folded into docs later).Testing
./run_tests.shgreen (minimal, unit, replay).protocol_{v1,v2}_{operations,observation}*_spec.lua.