* chore: unify product name display to OpenDesign repo-wide Rename the user-facing product name from "Open Design" to "OpenDesign" across documentation, web/desktop UI strings, i18n locales, prompts, plugin/skill/design-system content, changelogs, and specs, matching the landing-page rename already in flight. Deliberately excluded so installed-app identity stays untouched: - packages/release PRODUCT_NAME and everything derived from it (app bundle names, installer/registry identity, updater feeds) - tools/pack, tools/release, apps/packaged, landing page (PR #6983) - mocks/ recorded traces and LICENSE - test fixtures and comments that encode real on-disk install paths (Open Design.app, Program Files\Open Design, AppData paths) Validated with pnpm guard, pnpm typecheck, and targeted web/desktop/host test runs over the renamed strings. * fix(web): keep two-letter author monogram for CamelCase brand names authorInitials split words on whitespace only, so the renamed single-token author name "OpenDesign" produced a one-letter monogram. Treat lower-to-upper CamelCase boundaries as word breaks so the avatar fallback stays "OD". * fix(release): restore spaced Windows source artifact names in win.ps1 tools/pack still derives builder outputs from the unchanged PRODUCT_NAME ("Open Design"), so the asset script must look for the spaced filenames. Matches the mac/mac-intel/linux asset scripts, which were already kept on the original names. --------- Co-authored-by: Joey <236967869+joeylee12629-star@users.noreply.github.com>
11 KiB
Runtime Adapter Current State
Purpose
The runtime adapter layer lets the daemon drive locally installed AI-agent
CLIs through one OpenDesign run contract. It resolves and probes each CLI,
builds a runtime-specific invocation, delivers the composed prompt, normalizes
the runtime's output, and publishes run events to the web UI and od CLI.
Current Source Layout
The implementation is split by responsibility:
apps/daemon/src/runtimes/registry.tsowns the built-in registry and appends configured local profiles.apps/daemon/src/runtimes/defs/*.tscontains one runtime definition per built-in adapter.apps/daemon/src/agents.tsis now only a compatibility re-export surface; it is not the definition source.apps/daemon/src/runtimes/types.tsdefinesRuntimeAgentDefand the detected agent shape.apps/daemon/src/runtimes/detection.ts,launch.ts,executables.ts,invocation.ts, andmodels.tsown probing, executable resolution, process launch normalization, and model validation.apps/daemon/src/routes/runs.tsownsPOST /api/runs, run event streaming, cancellation, and the compatibilityPOST /api/chatroute. The current run execution pipeline is assembled inapps/daemon/src/server.ts.apps/daemon/src/runtimes/claude-stream.ts,json-event-stream.ts,qoder-stream.ts, andapps/daemon/src/copilot-stream.tsnormalize runtime-specific structured output.apps/daemon/src/agent-protocol/owns the shared JSON-line transport and the ACP and pi RPC protocol implementations.
Registered Runtimes
BASE_AGENT_DEFS in apps/daemon/src/runtimes/registry.ts currently contains
26 built-in adapter definitions. AGENT_DEFS also appends valid local profiles
loaded by readLocalAgentProfileDefs(), so an installation can expose more
entries than the built-in list.
| Stream / protocol | Built-in adapter IDs | CLI binaries |
|---|---|---|
claude-stream-json |
claude, amp, codebuddy |
claude, amp, codebuddy |
json-event-stream |
codex, opencode, byok-opencode, cursor-agent, mimo |
codex, opencode-cli, opencode-cli, cursor-agent, mimo |
acp-json-rpc |
amr, devin, hermes, trae-cli, kimi, kiro, kilo, vibe, reasonix |
vela, devin, hermes, traecli, kimi, kiro-cli, kilo, vibe-acp, reasonix |
pi-rpc |
pi |
pi |
qoder-stream-json |
qoder |
qodercli |
copilot-stream-json |
copilot |
copilot |
plain |
grok-build, qwen, deepseek, aider, antigravity, atomcode |
grok, qwen, deepseek, aider, agy, atomcode |
There is no registered gemini adapter. The standalone Gemini CLI runtime was
retired when Kimi ACP was restored. The JSON event parser still understands a
Gemini-shaped stream as an internal compatibility path for buffered
Antigravity output; that parser branch does not make Gemini a selectable
runtime.
Runtime Definition Contract
Each RuntimeAgentDef supplies the declarative data and hooks needed by the
shared orchestration layer. The main groups are:
- Identity and executable discovery:
id,name,bin,fallbackBins,versionArgs, and optional help/capability probes. - Model discovery and validation:
fallbackModels, optionallistModelsorfetchModels, optionalreasoningOptions, and custom-model policy. - Invocation:
buildArgs(), optional runtime environment, prompt delivery mode, image support, and prompt-size constraints. - Output normalization:
streamFormatand, for the shared JSON event stream,eventParser. - Integrations: MCP discovery/injection metadata, authentication probes, inactivity timeouts, and install/documentation metadata.
- Session continuity: CLI resume, captured stream session IDs, or ACP
session/load, depending on the runtime.
Local profiles inherit a built-in adapter and may override identity, binary, arguments, environment, models, and version/help probes. A profile cannot replace a built-in ID, and an unknown explicit base adapter is rejected.
Detection Flow
The batch entry point is detectAgents(); detectAgentsStream() yields the
same results as each probe settles.
- Iterate over the registry, including valid local profiles.
- Use
resolveAgentLaunch()to select the executable that the run path will actually launch. This includes configured binaries, compatible fallback binaries, and wrapper/native-launch normalization. - Run the version probe. A missing, non-executable, or broken target is reported as unavailable with a diagnostic.
- For an invocable runtime, probe advertised CLI capabilities, models, and authentication concurrently.
- Use live model discovery when it succeeds; otherwise expose the adapter's
fallback model list and mark its source as
fallback. - Refresh the model-validation cache from the result surfaced to clients.
A failed probe is isolated to that adapter instead of removing every agent from the picker. Detection results include availability, resolved path, version, models and their source, stream metadata, authentication state, and diagnostics where applicable.
Run Flow
apps/daemon/src/routes/runs.ts exposes the durable run API:
POST /api/runscreates and starts a run.GET /api/runs/:id/eventsstreams persisted and live run events.POST /api/runs/:id/cancelcancels the run.POST /api/chatremains the compatibility chat/SSE entry point.
For a local runtime, the shared execution pipeline:
- Resolves
RuntimeAgentDeffrom the request'sagentIdand validates the selected model, reasoning option, project, attachments, and tool bundle. - Resolves the project working directory. This spec MUST NOT define daemon
data paths; read root
AGENTS.md→ Daemon data directory contract. - Composes the daemon system prompt, applicable conversation context, active skill and design-system content, attachments, and the current user turn.
- Stages active skill side files inside the project when possible and builds the runtime-specific allowed-directory set. Design-system bodies are read by the daemon and folded into the prompt.
- Resolves the same launch target used by detection, calls
buildArgs(), normalizes the platform-specific invocation, and starts the child with an argument array andshell: false. - Delivers the prompt through the adapter's declared input mode and routes stdout through the matching stream or protocol handler.
- Publishes normalized agent events and lifecycle state to the run service, while tracking cancellation, retries, inactivity, artifacts, usage, and native-session recovery.
Prompt Delivery and Session Continuity
Prompt delivery is no longer one universal argv strategy:
- Stdin-capable adapters declare
promptViaStdin. Claude usespromptInputFormat: 'stream-json'; other stdin adapters receive text. grok-buildandatomcodeopt into daemon-created prompt files.- ACP and pi RPC sessions send the prompt through their protocol handshake.
- Any remaining argv-based adapter is checked against platform command-line budgets before launch.
Session continuity is likewise adapter-specific:
- Claude, Codebuddy, and OpenCode can continue a CLI-owned session.
- Codex captures the thread ID from
thread.startedand resumes that explicit thread on later turns. - Pi persists and reuses its RPC session file.
- AMR can capture an ACP durable session ID and resume with
session/load. - Other adapters continue to receive daemon-composed conversation context.
The daemon owns the resume identity checks and transparent reseed behavior, so runtime definitions only declare the mechanism they support.
Output Normalization
The run pipeline selects a handler from streamFormat:
| Format | Current handler |
|---|---|
claude-stream-json |
createClaudeStreamHandler() in runtimes/claude-stream.ts |
json-event-stream |
createJsonEventStreamHandler() in runtimes/json-event-stream.ts, parameterized by eventParser |
qoder-stream-json |
createQoderStreamHandler() in runtimes/qoder-stream.ts |
copilot-stream-json |
createCopilotStreamHandler() in copilot-stream.ts |
pi-rpc |
attachPiRpcSession() from agent-protocol/pi-rpc/ |
acp-json-rpc |
attachAcpSession() from agent-protocol/acp/ |
plain |
guarded stdout/stderr forwarding |
Structured handlers normalize runtime output into events such as status,
text_delta, thinking_start, thinking_delta, tool_use, tool_result,
usage, and error. The shared run layer applies role-marker and substantive-
output guards before completing the run.
ACP and Pi Protocol Layout
The old flat apps/daemon/src/acp.ts and apps/daemon/src/pi-rpc.ts modules no
longer exist. Their current boundary is:
apps/daemon/src/agent-protocol/
├── core/ shared JSON-line transport
├── acp/ ACP model detection, session setup, RPC, and update mapping
├── pi-rpc/ pi model parsing, session lifecycle, and event mapping
└── index.ts explicit public re-exports
core/ is the shared foundation. ACP and pi RPC do not import each other's
internals. See apps/daemon/src/agent-protocol/README.md for the module's
public surface and dependency rules.
Safety and Lifecycle Guarantees
The current adapter layer includes these protections:
- Detection and execution resolve the same launch target; a run does not fall
back to blindly spawning
def.binafter detection fails. - Child processes use argument arrays with
shell: false; platform wrapper normalization is centralized in the invocation layer. - Model IDs, reasoning choices, attachment paths, prompt budgets, working directories, and optional external MCP injection are validated before use.
- Structured protocol stages and the overall run have timeout/inactivity guards.
POST /api/runs/:id/cancelpropagates cancellation to the active child or protocol session, with forced shutdown as a fallback.- Native session IDs are persisted only for adapters that declare a resume mechanism, and stale resume targets are cleared and reseeded once.
Current Architecture Boundary
The runtime layer has already moved beyond a single agents.ts object array:
definitions, probing, executable resolution, prompt budgeting, parsers, and
subprocess protocols are separate modules. It remains intentionally centered
on declarative RuntimeAgentDef records plus shared run orchestration rather
than independent adapter classes implementing detect(), run(), cancel(),
and resume().
Cancellation, retries, persistence, SSE/AG-UI delivery, and most resume policy
are run-service concerns. Runtime definitions own only the CLI-specific facts
and hooks needed by that shared pipeline. Cloud/API provider execution remains
a separate provider path; byok-opencode is the local OpenCode bridge.