mirror of
https://github.com/nexu-io/open-design.git
synced 2026-10-27 09:51:12 +01:00
main
9
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
75693e95f4 |
[OPEND-3114] feat(od-next): open registered agents and CLI BYOK (#8702)
* feat(od-next): open registered runtimes and CLI BYOK Use the effective runtime registry for OD Next admission and remove retired capability qualification. Keep native observation and existing resume/cold recovery, with the evidence graph owned by observability contracts. Add run-scoped BYOK connection flags with caller-selected environment key input and reuse the existing provider bridge. Accept equivalent frozen Skill JSON and Base64 representations while preserving content and ownership boundaries. Validated with focused contracts, runtime, public Run and CLI regressions; eight real native agents and a real BYOK request/production pair; guard and workspace typecheck. Refs #8701. * fix(web): describe BYOK project file tools Explain that API-provider project runs use OpenCode file tools and require OpenCode to be available. Update the existing notice in all 19 locales and its component/browser regressions. Validated with red/green notice checks, real settings and preview follow-ups, guard and workspace typecheck. Refs #8701. * fix(od-next): preserve hidden prototype form feedback Keep HTML hidden semantics within the shared layout layer without overriding authored product CSS or hidden-until-found behavior. This fixes name errors remaining visible after a successful registration. Validated with a red/green Chromium regression, three resource-boundary checks, a real Claude follow-up with desktop/mobile form interaction, guard and workspace typecheck. Refs #8701. * test(od-next): make Run fixtures select their execution path Explicitly select ordinary Runs for retry persistence, plain stdout replay and the compatibility single-run telemetry case. Keep task hierarchy and terminal fallback telemetry cases active, and assert the selected path. Restore owner write permission to the leftover-agent fixture's frozen directories only during teardown so recursive deletion works on POSIX. Skip symlinks and preserve cleanup errors and every original behavior check. Reproduced all four CI failures before the fix. Focused daemon and E2E checks passed (12 tests), along with guard, workspace typecheck and focused LSP diagnostics. Refs #8701. * fix(daemon): avoid passing Pi resource directories as prompt files Pi reads existing --append-system-prompt paths as files. Stop passing skills, design systems and task input directories there; their resource paths already travel in the composed RPC prompt. Validated with 104 focused runtime/RPC tests, a real Pi 1.1.0 offline startup red/green probe, workspace typecheck and guard. * fix(web): coalesce streamed calls in generation progress Fold in-flight snapshots and terminal inputs through the existing tool-event reducer before rendering the Design Files progress feed. Keep the latest input, stable call identity and the limit of twelve distinct calls. Reproduced the duplicate React key warning before the fix. Runtime and progress-feed regressions now pass alongside existing in-flight tool-row tests. * fix(web): preserve forms and browser storage in prototype previews Permit client-side form submission in opaque interactive previews. Route Web Storage artifacts through the existing isolated powered preview, including daemon hints for large files, and retain guards when isolation is unavailable. Verified URL and srcDoc form interaction, persisted values after reload, and host isolation with focused Chromium regressions. Focused viewer/runtime and daemon tests, workspace typecheck and guard passed. * test(web): keep srcDoc fixtures on the opaque preview path Use an existing non-storage sandbox-shim signal in transport lifecycle fixtures now that Web Storage artifacts select the isolated preview origin. Preserve every reload, activation, recovery and manual-save assertion. Validated all 338 cases in the three affected FileViewer test files, workspace guard and typecheck, and focused diagnostics. * fix(byok): accept keyless IPv6 loopback providers Recognize the bracketed IPv6 hostname returned by WHATWG URL parsing in both settings validation and the OpenCode BYOK runtime. Keep remote hosts key-required. Validated with focused daemon and Web tests, settings browser checks, workspace typecheck and guard. * fix(daemon): restore Pi sessions and preserve completed RPC turns Load prior Pi history with switch_session and capture the authoritative sessionFile through nonblocking get_state. Treat a host-requested SIGTERM after a clean completed turn as shutdown, including Pi builds that report exit 143, while preserving real errors and cancellation. Validated with focused protocol and public Run lifecycle tests, a real Pi generation and native resumed edit, workspace typecheck and guard. * fix(preview): isolate project storage and preserve hidden controls Give powered previews stable per-project loopback origins and reserve those hosts for matching powered GETs before API or static exceptions. Advertise the capability so newer Web clients retain the opaque fallback with older daemons. Reuse the active powered transport in Present. Share a low-specificity hidden-control guard across URL and srcDoc previews without overriding explicit author rules or until-found; preserve doctype mode when synthesizing a missing head. Validated with actual two-project storage, Workers, reload, Present and API isolation browser witnesses, form/hidden regressions, focused Web and daemon checks, workspace typecheck and guard. * test(e2e): align public canaries with best-effort OD Next Read the remaining recipe identity marker without the retired serialized package hash. Make the fake OpenCode help probe finite. Exercise the current public question-form action, completed question turns/new answer tasks, and no-artifact normal endings while retaining cancellation, artifact and deck assertions. Validated with six fake-runtime cases and focused active/off public browser canaries with explicit rollout flags; no production completion policy or timeout was relaxed. * fix(od-next): guide focus restoration after list updates Prefer native modal lifecycle and restore focus to a current control after list rerenders, falling back to the primary action when a filtered item disappears. Real OpenCode and Pi prototypes exposed detached-trigger focus loss. Keep this as best-effort build guidance, without output contracts or automatic repair rounds. Validated the actual artifacts through normal public edit tasks and browser interaction checks; profile resource tests passed. * fix(od-next): retain focus through inline task updates Extend the existing live-control guidance to inline list actions. Real Copilot and Qoder boards also lost keyboard focus when status updates rebuilt their cards; hidden filtered items need a visible fallback. * fix: align Discovery integration tests and presentation storage * test(daemon): tolerate transient memory origin cleanup races --------- Co-authored-by: zhouzheng <zhouzheng@refly.ai> |
||
|
|
91f22f301d |
refactor(daemon): split acp.ts + pi-rpc.ts into an agent-protocol/ capability-barrel (#5200)
* refactor(daemon): split acp.ts + pi-rpc.ts into agent-protocol/ capability-barrel Move acp.ts (1744) and pi-rpc.ts (684) into a single agent-protocol/ capability-barrel module: a core/ foundation kernel (shared JSON-line-stream transport) plus per-protocol concern subdirs (acp/, pi-rpc/), each with a barrel. The shared createJsonLineStream transport moves into core/, dissolving the former pi-rpc -> acp edge into a clean star topology (allowedEdges: []). Pure structural move: every function body byte-identical (verified via line-multiset, 1960==1960, 0 added/0 dropped); public surface reproduced exactly (10 names) through the root barrel. All importers repointed to ./agent-protocol/index.js (server.ts, connectionTest.ts, runtimes/defs/shared.ts + 5 test files). Guard registration deferred (check-barrel-imports infra not on main yet). * docs(daemon): @module docblocks, per-export JSDoc, and README for agent-protocol/ Documentation only — zero code lines changed (verified by line-multiset, 1960==1960). Every file gets a @module docblock, every exported symbol gets JSDoc, and README.md mirrors design-systems/README.md (What changed / Why this shape / Import conventions / Directory structure / Consumers). * fix(daemon): repoint verify-amr-real-vela script to the agent-protocol barrel The acp.ts -> agent-protocol/ split stops emitting dist/acp.js, so the real-vela smoke verifier's dynamic import of ../dist/acp.js would fail with ERR_MODULE_NOT_FOUND after a clean build. Repoint it to ../dist/agent-protocol/index.js, which re-exports attachAcpSession. Verified: daemon build emits dist/agent-protocol/index.js and the script's import resolves attachAcpSession as a function. --------- Co-authored-by: LA <la@LAs-MacBook-Pro.lan> |
||
|
|
aa782365e0 |
feat(daemon): pass parentSession in pi RPC new_session for conversational continuity (#3434)
* feat(daemon): pass parentSession in pi RPC new_session for conversational continuity
Add parentSession option to attachPiRpcSession that sends
new_session { parentSession } before prompt on pi's stdin.
pi loads the prior .jsonl session file, forking conversation
history into the new session.
- resolveLastSessionPath(cwd) scans <cwd>/.pi/sessions/ for
the most recently modified .jsonl
- piParentSessionPaths Map in server.ts persists the last
session path per effectiveCwd
- Backward compatible — no new_session sent when no prior
session exists
- 3 new tests covering stdin ordering, backward compat, and
session path capture after agent_end
Closes #3414
* fix: replace str shorthand with string in parentSession test type annotations
* fix(daemon): scope pi session resume to conversations
* fix(daemon): handle pi parent session failures
* fix(daemon): clear stale pi session on capture miss
* fix(daemon): keep pi resume failure SSE code stable
---------
Co-authored-by: Siri-Ray <2667192167@qq.com>
|
||
|
|
32b706a2ec |
fix(daemon): surface pi turn errors (#3349)
- apps/daemon/src/pi-rpc.ts - apps/daemon/tests/pi-rpc.test.ts Surface Pi RPC assistant turn_end stopReason=error messages as daemon error events so upstream provider failures do not complete as empty zero-token runs. |
||
|
|
32d820e4ee |
fix(daemon): typecheck leaf modules (#943)
* update drift * fix(daemon): typecheck leaf modules * fix(daemon): decode Qoder stdout buffers Generated-By: looper 0.5.6 (runner=fixer, agent=opencode) |
||
|
|
8630fd380a |
feat(daemon): close pi adapter parity gaps
Closes pi adapter parity gaps for image paths, extra allowed dirs, error events, and sendAgentEvent routing. |
||
|
|
5df04c29a3 |
feat(daemon): add model name to pi initial status and RPC abort on cancel (#618)
* feat(daemon): add model name to pi initial status and RPC abort on cancel - Emit status:initializing with model name before pi responds so the UI shows 'pi · claude-sonnet-4-5' — matching Claude Code, Copilot, Gemini, and Cursor Agent model-name parity - Replace raw SIGTERM with RPC abort command on cancel, giving pi a chance to clean up gracefully before SIGTERM fallback - Wire run.acpSession onto the run object so cancel() can dispatch to session.abort() for pi and ACP adapters - Add stdinOpen guard so sendCommand is a no-op after stdin closes - Add 4 tests covering initializing status, abort wire format, and stdin-closed guard * fix(daemon): gate stdout parser after abort to prevent post-cancel events Once abort() sets finished=true, the stdout listener kept feeding chunks into mapPiRpcEvent, so text_delta/tool/status events could still be emitted during the PI_ABORT_GRACE_MS window. Add a finished guard at the top of the parser callback so no agent events are forwarded after abort, while still draining stdout cleanly. Adds a test that aborts mid-session, then feeds message_update and tool events, proving zero post-abort agent events are emitted. * refactor(daemon): own SIGTERM fallback in cancel, rewrite abort tests as integration - Move SIGTERM fallback from pi-rpc abort() to runs cancel() so the termination guarantee is centralized — a misbehaving session can't leave the child alive indefinitely (address lefarcen P3 on L130) - Remove the setTimeout/SIGTERM from abort(); it now only sends the RPC abort command, termination is the caller's responsibility - Rewrite initial-status and abort tests as integration tests that exercise attachPiRpcSession against mock child processes instead of duplicating private sendCommand/send helpers inline (address lefarcen P3 on L453 and L491) - All 28 tests pass |
||
|
|
5a0f954297 |
fix(daemon): emit tool_use from tool_execution_start in pi-rpc (#186)
* fix(daemon): emit tool_use from tool_execution_start in pi-rpc The pi-rpc adapter emitted tool_use from message_end, which fires before tool execution starts. The web UI pairs tool results to prior tool_use events, so receiving tool_result without a preceding tool_use broke tool card rendering and file auto-open behavior. Move tool_use emission to tool_execution_start, matching the pattern in copilot-stream.ts. Remove redundant tool call extraction from message_end (tool_use is now emitted at execution time, usage is already emitted from turn_end). Extract mapPiRpcEvent as a pure exported function so tests exercise the real event mapping logic instead of an inlined copy that can diverge from production. Ref: mrcfps review comments on PR #117 * docs(daemon): clarify mapPiRpcEvent mutability contract The function mutates ctx.sentFirstToken to track streaming state. Calling it "pure" is misleading; revised the doc comment to say no I/O or child process interaction instead. * fix(pi-rpc): remove redundant status(tool) emission from tool_execution_start Now that tool_use fires inline from tool_execution_start, the accompanying status(tool) event is redundant: tool_use already carries the tool name, and the UI renders running state from the tool card. The extra status pill breaks consecutive tool_use grouping in AssistantMessage.buildBlocks. Aligns with copilot-stream, which emits only tool_use from tool.execution_start with no status event. |
||
|
|
8f34e39b7b |
feat(daemon): add pi coding agent adapter (#117)
* feat(daemon): add pi coding agent adapter Add pi (https://pi.dev) as a supported coding agent, using its --mode rpc JSON-RPC protocol over stdio for structured event streaming. Changes: - apps/daemon/pi-rpc.js: new RPC session handler that drives pi's --mode rpc protocol, translating typed agent events (text_delta, thinking_delta, tool_use, tool_result, usage, status) into the daemon's UI event format. Auto-resolves extension UI requests (fire-and-forget consumed, dialogs auto-approved) so pi stays unblocked in the headless web UI. Kills the process after agent_end since pi's RPC process is designed for multi-prompt sessions. - apps/daemon/agents.js: add pi agent definition with custom fetchModels (pi --list-models outputs to stderr, not stdout), 575+ models from 20+ providers, reasoning/thinking level support via --thinking flag, and streamFormat 'pi-rpc'. - apps/daemon/server.js: wire pi-rpc stream format to attachPiRpcSession; skip stdin.end() for pi-rpc since the RPC session manages stdin bidirectionally. - apps/daemon/acp.js: export createJsonLineStream for reuse by pi-rpc.js. - apps/daemon/pi-rpc.test.mjs: 19 unit tests covering model list parsing (TSV, dedup, edge cases), RPC event translation (text, thinking, tools, usage, compaction, retry), sendCommand wire format, extension UI auto-resolution. - e2e/tests/structured-streams.test.ts: add pi RPC tool_use/tool_result event mapping test alongside existing Claude/Copilot fixtures. Verified end-to-end: daemon /api/chat → pi RPC → SSE stream with status, text_delta, usage, and tool events. Live E2E test passes (OD_E2E_RUNTIMES=pi). All 59 project tests green. * refactor(daemon): migrate pi-rpc to TypeScript Follow upstream #118 TypeScript migration convention: rename pi-rpc.js → pi-rpc.ts and pi-rpc.test.mjs → pi-rpc.test.ts with @ts-nocheck header (same as all other daemon modules). Import paths remain ./pi-rpc.js per NodeNext module resolution. * fix(daemon): avoid duplicate usage events in pi-rpc handler Pi emits both message_end and turn_end per turn, both carrying usage data. Emitting from both handlers caused double-counting in the UI and any consumer that aggregates usage. Remove usage emission from the message_end branch since turn_end is the canonical per-turn usage source. Keep tool call extraction in message_end (unique data not available in turn_end). Add regression test confirming exactly one usage event is emitted when both message_end and turn_end carry usage for the same turn. Addresses Copilot P2 review on PR #117. * fix(daemon): scope pi RPC id counter per session, bump graceful shutdown Move nextRpcId and sendCommand inside attachPiRpcSession as local state, matching the pattern in acp.ts where nextId is scoped per session. Prevents RPC id collisions across concurrent /api/chat requests. Bump post-agent_end SIGTERM grace period from 2s to 5s and make it configurable via PI_GRACEFUL_SHUTDOWN_MS env var for resource- constrained machines. Add test confirming concurrent sessions get independent id sequences. * fix(daemon): wrap parser.feed in try-catch in pi-rpc Catch errors from parser.feed and route them through the existing fail() handler instead of letting them propagate as unhandled exceptions. |