26 KiB
作成
LocalTicketBackend によって作成されました。
項目更新
Ticket item updated: title, body.
項目更新
Ticket item updated: title, body.
Plan
Implementation started.
Plan for this pass:
- Inspect local Worker protocol transport and current Backend/frontend HTTP operation mappings.
- Add a Backend/runtime protocol command transport that accepts existing
protocol::Methodpayloads rather than per-operation HTTP endpoints. - Route TUI Backend Runtime client through that protocol transport for run/notify/completion/cancel/pause/resume/compact/rewind operations.
- Route browser Console operations through the same protocol transport and stop using HTTP operation endpoints as the normal path.
- Keep existing HTTP endpoints only as compatibility where needed, not as frontend/TUI authority.
Implementation report
Implementation update:
Implemented the first full protocol-transport pass for Backend/runtime Worker controls.
Backend/runtime:
- Added
Runtime::send_protocol_method(...)inworker-runtime.Method::ListCompletionsreturns directEvent::Completionsfor same-command-connection semantics.- Other methods are delivered unchanged to the execution backend.
- Added
WorkerExecutionBackend::dispatch_method(...)and concrete support inWorkerRuntimeExecutionBackend.- This accepts existing
protocol::Methodvalues instead of translating through operation-specific HTTP request DTOs.
- This accepts existing
- Added runtime command WebSocket:
/v1/workers/{worker_id}/protocol/ws- accepts raw
protocol::MethodJSON frames - returns raw direct
protocol::EventJSON frames where needed
- Added workspace-server command WebSocket:
/api/runtimes/{runtime_id}/workers/{worker_id}/protocol/ws/api/w/{workspace_id}/runtimes/{runtime_id}/workers/{worker_id}/protocol/ws
- Added
RuntimeRegistry::send_protocol_method(...)and embedded runtime forwarding.
TUI client:
- Reworked
BackendRuntimeClientsosend(&Method)no longer maps to HTTP/input, lifecycle, or unsupported diagnostics. - It now opens a command WS to
/protocol/wsand sends cloned rawprotocol::Methodvalues. - Direct command response events are merged into the existing event queue alongside observation WS events.
- This removes the previous unsupported handling for pause/resume/compact/completions/rewind at the TUI client transport layer.
Browser Console:
- Added command WS connection to
/protocol/wswhile keeping/events/wsas observation stream. - Removed normal operation use of HTTP
POST /inputandPOST /completionsfrom the Console page. - Composer send now maps to protocol methods:
- user input ->
Method::Runwith protocolSegment[] - system input ->
Method::Notify { auto_run: true } :compact->Method::Compact:rewind->Method::ListRewindTargets:peer->Method::RegisterPeer
- user input ->
- Completion lookup now sends
Method::ListCompletionsover command WS and waits for directEvent::Completions. - Added frontend controls for cancel / pause / resume / compact / rewind target request / rewind to target.
Compatibility note:
- Existing HTTP operation endpoints remain in backend/server as compatibility for now, but the TUI Backend client and browser Console normal path now use protocol transport.
Verification run under nix develop:
cargo fmt -- --checkcargo check -p worker-runtime -p yoi-workspace-server -p client -p tuicargo test -p client backend_runtime --libcargo test -p yoi-workspace-server registry_worker_list_can_be_scoped_by_runtime_id --libcargo test -p worker-runtime --features ws-server --lib worker_backendgit diff --check
Frontend check note:
web/workspace/package.jsoncurrently has no check script and local frontend dependencies are not installed in this worktree.- Attempted temporary
npm exec --package svelte-check --package typescript -- svelte-check, but the tool bootstrap failed before checking project code. - The Svelte page was updated against the generated protocol types in
web/workspace/src/lib/generated/protocol.ts, but a frontend-native check still needs to be run in an environment with the frontend deps installed.
Implementation report
Follow-up implementation after design clarification:
Changed the transport split so /events/ws no longer exists. /protocol/ws is now the single Worker protocol WebSocket for both directions:
- client -> runtime/backend: raw
protocol::MethodJSON frames - runtime/backend -> client: raw
protocol::EventJSON frames
Runtime changes:
- Removed
/v1/workers/{worker_id}/events/wsroute. - Removed runtime-specific event WS envelope/diagnostic frame types.
- Extended
/v1/workers/{worker_id}/protocol/wsto stream snapshot/backlog/live observation events as rawprotocol::Eventwhile also accepting method frames on the same socket.
Workspace Backend changes:
- Removed public
/api/.../events/wsand/api/w/.../events/wsroutes. - Removed Backend client event WS envelope types.
- Workspace
/protocol/wsnow proxies/streams raw protocol events and forwards raw protocol methods on the same socket. - Runtime observation source endpoint generation now targets runtime
/protocol/wsinstead of/events/ws.
Client/frontend changes:
- TUI
BackendRuntimeClientno longer opens a separate observation socket. It uses only/protocol/wsfor send and receive. - Browser Console no longer opens both observation and command sockets. It uses one protocol socket for replay/live events, completions, rewind targets, and controls.
- Removed old frontend
ClientWorkerEventWs*types. - Updated frontend UI tests to assert protocol-only Console behavior and absence of operation HTTP paths.
Verification:
nix develop -c cargo fmt -- --checknix develop -c cargo check -p worker-runtime -p yoi-workspace-server -p client -p tuinix develop -c cargo test -p client backend_runtime --libnix develop -c cargo test -p worker-runtime --features ws-server --lib protocol_wsnix develop -c cargo test -p yoi-workspace-server protocol_ws --libnix develop -c cargo test -p yoi-workspace-server proxy_maps_runtime_worker_not_found_http_404_to_protocol_error_event --libdeno test --allow-read web/workspace/src/lib/workspace/console/worker-console.ui.test.tsfromweb/workspacegit diff --check
Implementation report
Bug fix after manual TUI send failure:
Observed symptom:
- TUI send over Backend protocol reported a
does not support Worker protocol command transportstyle error.
Root cause:
/events/wshad been removed and/protocol/wsunified, but workspace-server still handled inbound clientprotocol::Methodby callingRuntimeRegistry::send_protocol_method(...).- For remote runtime-backed workers, Backend must be only a protocol WS proxy. Calling the registry default method hits the unsupported path instead of tunneling the frame to the runtime's
/protocol/ws.
Fix:
- Workspace-server now branches by observation/protocol source:
RemoteWs: proxy raw WebSocket frames bidirectionally between client/api/.../protocol/wsand runtime/v1/.../protocol/ws. Backend does not deserialize or interpret method frames in this path.Embedded: use in-process runtime adapter for method dispatch while streaming embedded observation events.
- Added/updated test so sending
Method::ListCompletionsthrough the workspace-server protocol proxy returnsEvent::Completionsfrom the runtime, proving method frames reach the runtime instead of the Backend unsupported fallback.
Verification:
nix develop -c cargo fmt -- --checknix develop -c cargo check -p yoi-workspace-server -p client -p worker-runtimenix develop -c cargo test -p yoi-workspace-server proxies_worker_protocol_ws_as_raw_events --libnix develop -c cargo test -p client backend_runtime --libnix develop -c cargo test -p worker-runtime --features ws-server --lib protocol_wsnix develop -c cargo test -p yoi-workspace-server protocol_ws --libdeno test --allow-read web/workspace/src/lib/workspace/console/worker-console.ui.test.tsgit diff --check
Implementation report
Bug fix for missing local echo in TUI/Web:
Observed symptom:
- Sending from TUI/Web over unified
/protocol/wsreached the runtime and was accepted asprotocol_method, but the user's sent content did not appear in the Console.
Root cause:
- The old HTTP input path emitted observation events for accepted input via
input_protocol_event(...)(Event::UserMessagefor user input /Event::SystemItemfor system input). - The new raw
Method::Run/Method::Notifyprotocol path dispatched the method to the execution backend but did not record the corresponding observation echo event. - Therefore the unified protocol stream had assistant/runtime events, but no echo event representing the user-sent content.
Fix:
- Added protocol-method observation echo in
worker-runtimeafter acceptedRuntime::send_protocol_method(...)dispatch. Method::Runnow recordsEvent::UserMessage { segments }.Method::Notifynow records a system inputEvent::SystemItem.- Kept compact/list_rewind_targets/register_peer command echoes aligned with the old command-input observation shape.
- Added a runtime protocol WS regression test: send
Method::Runover/protocol/wsand assert the same socket receivesEvent::UserMessagewith the sent text.
Verification:
nix develop -c cargo fmt -- --checknix develop -c cargo check -p worker-runtime -p yoi-workspace-server -p client -p tuinix develop -c cargo test -p worker-runtime --features ws-server --lib protocol_ws_echoes_accepted_run_as_user_messagenix develop -c cargo test -p worker-runtime --features ws-server --lib protocol_wsnix develop -c cargo test -p yoi-workspace-server protocol_ws --libnix develop -c cargo test -p client backend_runtime --libgit diff --check
Implementation report
Correction after review:
The previous fix synthesized Event::UserMessage in Runtime::send_protocol_method(...). That was the wrong layer. UserMessage is part of the normal Worker protocol/log output path and should not be constructed by the runtime transport layer.
Root cause refined:
- The embedded Worker backend bridge only subscribed to
WorkerHandle::event_tx. - Local socket clients also subscribe to
SegmentLogSinklive entries;LogEntry::UserInputis mapped toEvent::UserMessagethere. - Runtime observation/protocol streaming missed that
SegmentLogSinklive-entry path, so user input echo events were absent when using runtime protocol transport.
Fix:
- Removed the runtime-side synthetic protocol-method echo from
Runtime::send_protocol_method(...). - Updated
WorkerRuntimeExecutionBackend::connect_handle(...)to bridge both:- direct Worker protocol events from
WorkerHandle::subscribe() - live session log entries from
handle.sink.subscribe_with_snapshot()
- direct Worker protocol events from
- Added runtime bridge mapping matching local IPC behavior:
LogEntry::SegmentStart->Event::SegmentRotatedLogEntry::UserInput->Event::UserMessageLogEntry::SystemItem->Event::SystemItemLogEntry::Invoke->Event::InvokeStart
- Removed the fake protocol-WS echo test that depended on synthetic runtime behavior.
- Added a unit test that locks the normal bridge mapping: live
LogEntry::UserInputmaps toEvent::UserMessage.
Verification:
nix develop -c cargo fmt -- --checknix develop -c cargo check -p worker-runtime -p yoi-workspace-server -p client -p tuinix develop -c cargo test -p worker-runtime --features ws-server --lib runtime_bridge_maps_live_user_input_log_entry_to_user_messagenix develop -c cargo test -p worker-runtime --features ws-server --lib protocol_wsnix develop -c cargo test -p yoi-workspace-server protocol_ws --libnix develop -c cargo test -p client backend_runtime --libgit diff --check
Decision
Design correction / implementation target:
Runtime protocol WS should be thin. /v1/workers/{worker_id}/protocol/ws is already worker-id scoped, so after worker lookup it should not reimplement Worker protocol semantics. It should connect the WebSocket framing to the same Worker protocol session behavior used by local IPC.
Current issue:
- Local IPC protocol session in
worker/src/ipc/server.rsalready knows how to combine:WorkerHandle::event_txprotocol eventsSegmentLogSinklive log entries (LogEntry::UserInput->Event::UserMessage, etc.)Methodframe reading and event writing
- Runtime WS has been recreating similar logic in
worker-runtime/src/http_server.rs/worker_backend.rs. - This duplicated logic caused drift: runtime protocol streaming initially missed
SegmentLogSinklive entries, and a bad synthetic echo workaround was added before being corrected.
Decision:
- Do not make runtime/backend interpret normal Worker protocol operations.
- Backend remains a raw protocol WS proxy for remote runtime workers.
- Runtime remains a worker-id lookup + lifecycle boundary; for protocol WS it should delegate to a shared Worker protocol session implementation.
- Local IPC and runtime WS should use the same session logic so user echo, system items, invoke events, completions, rewind, pause/resume, etc. cannot diverge.
Implementation target:
- Extract the local IPC protocol session logic into a reusable Worker protocol session helper that is not Unix-socket-specific.
- Local IPC server uses the helper.
- Runtime protocol WS uses the same helper or a thin adapter around it.
- Remove duplicated live-entry/event bridging from runtime-specific code where possible.
- Keep lifecycle/runtime management outside the protocol session helper.
Implementation report
Implementation update for thin runtime protocol session:
- Added
worker::ipc::protocol_sessionas the shared Worker protocol session helper.subscribe_worker_protocol_session(&WorkerHandle)centralizes snapshot + alert + live log entry + event subscriptions.live_log_entry_event(LogEntry)centralizes the local IPC mapping:SegmentStart->Event::SegmentRotatedUserInput->Event::UserMessageSystemItem->Event::SystemItemInvoke->Event::InvokeStart
dispatch_worker_protocol_method(...)centralizes same-connection direct response handling forListCompletions, forwarding other methods toWorkerHandle::send.
- Updated local IPC server to use the shared helper instead of owning its own mapping/subscription logic.
- Updated
worker-runtimeembedded backend bridge to use the same shared helper for live Worker/log event bridging. - Removed the duplicated
live_log_entry_eventmapping from runtime-specific code.
Scope note:
- This keeps Backend as raw WS proxy for remote runtime workers.
- Runtime still performs worker-id lookup and execution/lifecycle boundary work, but protocol stream composition now uses the same Worker session helper as local IPC instead of maintaining a separate mapping implementation.
- Full WS socket pump and Unix JSONL pump still have transport-specific loops, but the protocol subscription/mapping/direct-response semantics are no longer duplicated.
Verification:
nix develop -c cargo fmt -- --checknix develop -c cargo check -p worker-runtime -p worker -p yoi-workspace-server -p client -p tuinix develop -c cargo test -p worker --lib ipc::protocol_sessionnix develop -c cargo test -p worker --lib ipc::servernix develop -c cargo test -p worker-runtime --features ws-server --lib protocol_wsnix develop -c cargo test -p yoi-workspace-server protocol_ws --libnix develop -c cargo test -p client backend_runtime --libgit diff --check
Implementation report
Implementation update for shared protocol frame/pump semantics:
- Added Method/Event-specific JSON codec helpers in
protocol::stream:encode_method/decode_methodencode_event/decode_eventJsonLineReader::next_method()JsonLineWriter::write_event()
- Updated local IPC to use the shared codec helpers and the shared
worker::ipc::protocol_sessionsemantics. - Updated runtime WS and workspace-server embedded protocol handling to use the same
decode_method/encode_eventhelpers instead of directserde_jsoncalls. - Updated Backend runtime client and remote observation client to use
encode_method/decode_eventfor protocol frames.
Resulting split:
- Shared:
- JSON shape for
protocol::Method/protocol::Event - Method/Event encode/decode
- WorkerHandle subscription semantics
- live
LogEntry -> Eventmapping - direct-response method semantics such as
ListCompletions
- JSON shape for
- Transport-specific:
- Unix IPC uses JSONL line boundary.
- WebSocket uses one text frame per JSON value.
This makes WS effectively a frame-boundary adapter around the same JSON protocol frames rather than a separate protocol implementation.
Verification:
nix develop -c cargo fmt -- --checknix develop -c cargo check -p protocol -p worker -p worker-runtime -p yoi-workspace-server -p client -p tuinix develop -c cargo test -p worker --lib ipc::protocol_sessionnix develop -c cargo test -p worker --lib ipc::servernix develop -c cargo test -p worker-runtime --features ws-server --lib protocol_wsnix develop -c cargo test -p yoi-workspace-server protocol_ws --libnix develop -c cargo test -p client backend_runtime --libgit diff --check
Comment
Reported issue before implementation:
- TUI shows the
Compacting...progress/status indication. - Web Console does not show the same indication.
Investigation plan:
- Compare TUI protocol/event handling with Web Console protocol/event handling.
- Confirm whether the relevant protocol event reaches the browser and is dropped by frontend state/rendering, or whether the event is not forwarded through the Backend/runtime protocol WS path.
- Fix the narrow missing mapping/rendering path without adding a synthetic event outside the normal Worker protocol/session flow.
Implementation report
Implementation report for Web Console compact/rotation display gap:
- Web Console already handled live
compact_startby projecting aCompacting…status row. - The projection was still ignoring
segment_rotated, while TUI reseeds the visible transcript from the new segment start entry. This made Web diverge around compaction/segment-rotation boundaries. - Updated
web/workspace/src/lib/workspace/console/model.tssosegment_rotatedreprojectsevent.data.entrythrough the same log-entry projection path used bysnapshot. - Added a Web projection regression test asserting
segment_rotatedreplaces stale visible rows with the new segment seed. - While running Web check, fixed a narrow
list_completionsTypeScript narrowing issue in+page.svelte: command completions return early, then the file completion kind/prefix are captured before the Promise closure.
Verification:
cd web/workspace && deno test --allow-read=src --allow-env=VSCODE_TEXTMATE_DEBUG src/lib/workspace/console/model.test.tscd web/workspace && deno task checkpasses with 0 errors; it still reports 2 existing a11y warnings in+page.svelte.git diff --check
Comment
Requested Web Console timeline-bar display change before implementation:
- Keep user-message markers/items as they are today.
- For assistant display in the timeline bar, show only the last assistant item within each turn.
Implementation plan:
- Locate the Web timeline-bar projection/rendering path.
- Change only the timeline-bar item derivation/filtering, not the underlying transcript/event model.
- Add/update focused Web tests if there is a projection helper; otherwise verify through existing Web check and keep the diff scoped.
Implementation report
Implementation report for Web Console timeline-bar assistant filtering:
- Added
selectConsoleTimelineLines()inweb/workspace/src/lib/workspace/console/model.ts. - The selector keeps every
userline in the timeline selection. - Assistant lines are grouped by user-delimited turns, and only the last assistant line in each turn is selected.
- Non-user/non-assistant lines remain excluded from the timeline bar selection.
- Updated
+page.sveltetimeline layout construction to use the selector before converting selected lines to timeline marks. Positioning still uses the full transcript line count, so marks remain aligned to scroll position. - Added a focused model test for
user, assistant, tool, assistant, user, assistant, assistantto assert the selected timeline items areu1,a2,u2, anda4.
Verification:
cd web/workspace && deno test --allow-read=src --allow-env=VSCODE_TEXTMATE_DEBUG src/lib/workspace/console/model.test.tscd web/workspace && deno task checkpassed with 0 errors; it still reports the existing 2 a11y warnings in+page.svelte.git diff --check
Note: deno fmt --check on the touched files still reports existing formatting changes outside this patch scope, so it was not used as the gating check for this small change.
Comment
Requested Web Console tool-path display change before implementation:
- Use the Worker's protocol
snapshot.greeting.cwdas the display base. - For known display portions of edit-related tools plus
Read,Grep, andGlob, show absolute paths relative to cwd. - Do not globally replace arbitrary tool output text; only rewrite known path-bearing parts of known tool display formats.
Implementation plan:
- Carry
greeting.cwdthrough the Web Console projection state. - Add a focused display normalizer for known tool output formats:
Read ... from <path>/ read error path forms if present.- grep result path prefixes such as
<path>:line:...and summary lines like matching lines in files. - glob found-path listing entries.
- edit/write-style success/error lines that explicitly include a file path.
- Add focused model tests for the supported formats and keep transcript/protocol payloads unchanged.
Implementation report
Implementation report for Web Console known tool-path display relativization:
- Web Console projection now carries
snapshot.greeting.cwdinConsoleProjection. - Each
ToolCallViewcaptures the current cwd so later rendering can use the correct display base without changing protocol payloads or stored tool output. - Added path-display normalization scoped to known tool display formats only:
Read:file_pathdisplay andRead ... from <path>summary/detail path.Write:file_pathdisplay and knownCreated/Overwrote/Wrote/ related result-line path prefixes.Edit:file_pathdisplay and knownEdited <path> (...)result-line path prefix.Glob: line-start cwd paths in result preview.Grep: line-start cwd paths in result preview, includingpath:line:...output.
- Paths outside cwd are left absolute.
- Arbitrary default tool output, Bash output, and argument JSON/details are not globally rewritten.
Tests:
- Added a focused Web model regression test with
snapshot.greeting.cwd = /repocovering Read/Write/Edit/Glob/Grep display output. - The test asserts cwd-contained paths become relative while
/outside/...paths remain absolute.
Verification:
cd web/workspace && deno test --allow-read=src --allow-env=VSCODE_TEXTMATE_DEBUG src/lib/workspace/console/model.test.tscd web/workspace && deno task checkpassed with 0 errors; it still reports the existing 2 a11y warnings in+page.svelte.git diff --check
Comment
Requested Web Console composer a11y/focus refactor before implementation:
- Requirement: clicking anywhere in the composer input surface except the button should focus the textarea.
- Preferred structure: do not add
role="button"to a layout<div>and do not wrap the send button in a<label>. - Instead, make the textarea itself occupy the input surface and use padding/overlay layout for the footer and send button.
- The send button remains structurally outside/above the textarea surface and handles submit normally.
- Expected result: remove the clickable
<div>a11y warning while preserving the composer click-to-focus behavior.
Implementation report
Implementation report for Web Console composer focus/a11y refactor:
- Removed the
onclick={handleComposerShellClick}layout-div focus handler and deletedhandleComposerShellClick. - Kept the composer shell as non-interactive layout.
- Made the textarea itself occupy the input surface:
- larger min-height
- right/bottom padding reserved for the overlaid footer and send button
cursor: text
- Changed the footer to an absolute overlay with
pointer-events: none, so clicks on non-button footer/composer area pass through to the textarea. - Kept the send button as a normal submit button with
pointer-events: auto. - Updated the Web UI fixture test to assert the shell no longer has the click handler and the overlay pointer-event layout is present.
Verification:
cd web/workspace && deno test --allow-read=src --allow-env=VSCODE_TEXTMATE_DEBUG src/lib/workspace/console/worker-console.ui.test.tscd web/workspace && deno task checkgit diff --check
Result: svelte-check found 0 errors and 0 warnings.