feat: add macOS ZCode runtime support - #4819
Conversation
|
Hey @jzhishu — thanks for opening this as a draft. The protocol notes in the body are useful, especially the |
5f65bc8 to
c4913b9
Compare
|
Hi, sharing a quick status update for this draft PR. Right now this PR is mostly ZCode groundwork: runtime registration, Since opening the PR, I continued digging into the protocol. The current conclusion is that I can now drive the real
The blocker is auth. My local ZCode is using account/OAuth login, and the real upstream model request currently returns So I’m keeping this PR as a draft while we decide the right next step: wait for a stable headless credential path from Zhipu, investigate the GUI |
|
Thanks for the detailed update — this is exactly the kind of draft-state note that's helpful. The I’m routing this update for product/maintainer eyes so we can get a direction on which auth path we actually want to back before you push further into the implementation. |
|
Update: tested the API-key approach — full headless round-trip works I tested the documented API-key path first. The result: it works end-to-end, and the auth blocker from yesterday is resolved on this path. API-key path — full headless round-trip (verified independent of the GUI) Driving a standalone Concretely: bigmodel API key + One key point: the API key's platform must match the endpoint (bigmodel key → OAuth / account login — confirmed not viable headlessly I took the raw OAuth What I'm planning to do next:
|
|
This materially changes the picture — thanks for doing the API-key verification end-to-end. The headless Keeping this as a draft while you wire the |
createZcodeProtocolClient now routes every stdout frame that is not a reply to one of our own requests: async notifications (session/event, state.updated) and server->client requests (method + non-pending id, e.g. interaction/requestProviderRuntimeHeaders) are delivered to onNotification listeners, and respond(id, result) writes an answer frame back. Listeners are isolated from one another and cleared on dispose. Phase 3 protocol groundwork for streaming zcode sessions (issue nexu-io#4692); pure transport, event->OD mapping lands in a follow-up.
createZcodeStreamHandler maps zcode session/event + state.updated frames into OD's chat event set (text_delta, thinking, tool_use, tool_result, usage, status, error, conversation_title). Turn end is the single cumulative final-result payload, not the per-iteration turn-result that fires once per model round-trip in a tool loop; model-request telemetry frames (which carry request/response headers) are dropped rather than forwarded. Covered by unit tests built from the live-captured frame shapes. Phase 3 groundwork for streaming zcode sessions (issue nexu-io#4692); wiring into the daemon run path via the protocol client's onNotification channel lands in a follow-up.
|
Hi there, quick status update on this draft PR. With auth unblocked, I drove the real
On top of that I landed two pieces of code:
Both are covered by unit tests built from the real captured frames (protocol client: 14, parser: 8). This part is internal plumbing with no UI surface yet, so it's verified through tests for now. Next I'll wire this into the run pipeline so a real message round-trip is visible in the UI: per turn, spawn |
|
Thanks — this narrows the protocol shape a lot. The |
|
Thanks — the The two cases I'd still prioritize before this leaves draft are native |
|
@jzhishu I'm holding off on generating review comments for #4819 because this pull request has merge conflicts right now. Please resolve the conflicts with main and push the updated branch. Once that's done, request or wait for the review to run again and I'll take another look. 🔁 Powered by Looper · runner=reviewer · agent=codex · An autonomous AI dev team for your GitHub repos. |
# Conflicts: # apps/daemon/src/runtimes/env.ts # apps/daemon/tests/runtimes/env-and-detection.test.ts # apps/web/src/state/config.ts
|
Quick follow-up from our side: @nettee's current-head review already covers the blockers I would want fixed on this revision, so I'd use those inline comments as the gate for the next update. Once the stdin-failure handling and post- |
nettee
left a comment
There was a problem hiding this comment.
Thanks for the substantial ZCode integration. I found three blocking runtime regressions that need resolution; the inline comments cover the Kimi adapter conversion and a ZCode connection-test failure path.
🔁 Powered by Looper · runner=reviewer · agent=codex · An autonomous AI dev team for your GitHub repos.|
Quick follow-up: @nettee's latest current-head review is the one to drive on Once those inline comments are addressed, the next pass should be in much better shape.
|
nettee
left a comment
There was a problem hiding this comment.
I found two blocking reliability issues in the new ZCode state and session lifecycle. The concrete fixes are in the inline comments.
🔁 Powered by Looper · runner=reviewer · agent=codex · An autonomous AI dev team for your GitHub repos.|
Quick follow-up: @nettee's latest current-head review is the one to work from on Once those inline comments are addressed, the next pass should be in much better shape. |
nettee
left a comment
There was a problem hiding this comment.
I reviewed the ZCode runtime end to end: app-bundle resolution, saved-provider configuration, protocol/session lifecycle, connection-test behavior, Settings persistence, and the focused regression coverage. The changed ranges are coherent and I found no actionable correctness or safety issues.
Thank you for the thorough implementation and follow-up fixes—this is a substantial integration, and the coverage around protocol failures and session recovery is especially appreciated.
🔁 Powered by Looper · runner=reviewer · agent=codex · An autonomous AI dev team for your GitHub repos.
nettee
left a comment
There was a problem hiding this comment.
@jzhishu I reviewed the current ZCode head end to end across the changed ranges: app-bundle detection and persistence, the saved-provider/runtime wiring, the protocol/session lifecycle, the connection-test path, and the focused regression coverage that landed with those pieces. The current implementation is internally consistent and I did not find any actionable correctness or safety issues on d13704d.
I wasn’t able to execute the Vitest suites in this worktree because node_modules are not installed here, but the new daemon and web tests in the diff cover the failure paths I would have expected to probe manually. Thanks for pushing a fairly deep runtime integration through with this much targeted coverage.
Thanks for the thorough end-to-end review and the kind words. Appreciate you checking the latest head across the runtime wiring and failure-path coverage. I’ll keep an eye on CI for the Vitest results. |
|
Thanks for the ZCode follow-through. To verify the current head after the picker and diagnostics updates, could you add a short recording or a small labelled screenshot set of the Settings → Agents ZCode states: (1) the normal unavailable card with the ZCode-specific Choose ZCode.app action; (2) choosing a non-standard ZCode.app and the resulting saved selected-path or not-ready state, then Rescan/refresh; (3) the stale or invalid selected-bundle diagnostic and its recovery guidance; and (4) a successful connection-test result once a valid bundle is available. Please keep the relevant card, selected-path/diagnostic text, and action controls visible in each state. The native macOS picker itself does not need to be recorded. Once this current-head Settings coverage is in, the design side can review the remaining runtime flow with confidence. |
nettee
left a comment
There was a problem hiding this comment.
@jzhishu I reviewed the current ZCode head end to end across the changed ranges: app-bundle detection and persistence, saved-provider/runtime wiring, the protocol and session lifecycle, the connection-test path, the Settings diagnostics flow, and the focused regression coverage that landed with those pieces. The implementation on 90008c83 is internally consistent and I did not find any actionable correctness or safety issues in scope.
I wasn’t able to execute the Vitest suites in this worktree because node_modules are not installed here, but the added daemon and web tests cover the failure paths I would have expected to probe manually. Thanks for pushing a fairly deep runtime integration through with this much targeted coverage.
nettee
left a comment
There was a problem hiding this comment.
@jzhishu I reviewed the current ZCode head end to end across the changed ranges: app-bundle detection and persistence, saved-provider/runtime wiring, the protocol and session lifecycle, the connection-test path, the Settings diagnostics flow, and the focused regression coverage that landed with those pieces. The implementation on 55a3812b is internally consistent and I did not find any actionable correctness or safety issues in scope.
I wasn’t able to execute the Vitest suites in this worktree because node_modules are not installed here, but the added daemon and web tests cover the failure paths I would have expected to probe manually. Thanks for pushing a fairly deep runtime integration through with this much targeted coverage.
# Conflicts: # e2e/lib/playwright/mock-factory.ts
Thanks! I’ve added updated screenshots for all three requested states: ready with the Test action, not detected with aligned card actions, and the setup-failure diagnostic row. The branch is also up to date with |
|
Thanks for adding the updated screenshots and rebasing on |
Thanks for confirming! Appreciate the re-check. |

Fixes #4692
Scope note: this PR implements and validates ZCode support for the macOS app-bundle install path only. Windows discovery/launch support is intentionally left to a follow-up issue/PR once the Windows install layout and app-server entrypoint are verified.
Why
This PR adds first-class
zcoderuntime support to Open Design.The original issue asked for Zhipu ZCode support in OD. During investigation, I found that the macOS ZCode install does not behave like the existing PATH-based local CLI agents: users install
ZCode.app, and the usable integration entrypoint is the bundledapp-serverinside the app bundle. The normal--promptpath is not viable for OD because ZCode's real GUI flow uses the app-server protocol.The first cut is scoped to ZCode's saved API-key provider configuration. OAuth/account-login token refresh is GUI-private, so this PR does not reverse-engineer
app.asarand does not add OD-owned API-key fields.What users will see
Users with ZCode installed in the standard macOS app locations can select
zcodeas an Open Design agent after detection.If ZCode is installed somewhere else, Settings now shows a ZCode-specific
Choose ZCode.appaction instead of asking users to find or paste the internalzcode.cjsexecutable path. OD stores the selected app bundle path and derives the bundled app-server entrypoint internally.ZCode runs stream into the normal OD chat UI: thinking/text deltas, tool calls, tool results, usage, completion, and run errors. ZCode model choices are read from the user's saved ZCode provider config and used for both connection tests and runs.
Connection testing now verifies model availability through the real app-server flow instead of relying on a shallow
session/listprobe.Implementation notes
zcoderuntime usingapp-serverover stdio.session/event/state.updatedframes into OD chat events.workspace/upsertModelProviderandworkspace/setDefaultModel.sessionIds across compatible turns.~/Applications/ZCode.appand/Applications/ZCode.app.ZCODE_BINas a process-level diagnostic/development override only; it is not exposed or saved through Settings.Claude.app; an invalid explicitzcodeAppPathdoes not silently fall back to PATH/auto-discovery.Surface area
odsubcommand orOD_*env var. CLI dual-track is not applicable for the ZCode app bundle picker: standard installs are auto-discovered, non-standard installs require a desktop/macOSZCode.apppicker, andZCODE_BINremains a process-level diagnostic override only.zcodeAppPathto app config / connection-test contracts and adds the native dialog endpoint.skills/,design-systems/,design-templates/, orcraft/entry, and no skills protocol change.Screenshots
Bug fix verification
This is a feature PR, not a bug fix.
Validation
pnpm guardpnpm typecheckpnpm --filter @open-design/daemon testpnpm --filter @open-design/web test/api/runs+ SSE smoke using a fakezcode app-serverBug fix verification
This is a feature PR, not a bug fix.
Validation
pnpm guardpnpm typecheckpnpm --filter @open-design/daemon testpnpm --filter @open-design/web test/api/runs+ SSE smoke using a fakezcode app-server