Files
Joey-nexu f1a0b60c6c chore: unify product name display to OpenDesign repo-wide (#6998)
* 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>
2026-08-18 07:09:45 +00:00

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.ts owns the built-in registry and appends configured local profiles.
  • apps/daemon/src/runtimes/defs/*.ts contains one runtime definition per built-in adapter. apps/daemon/src/agents.ts is now only a compatibility re-export surface; it is not the definition source.
  • apps/daemon/src/runtimes/types.ts defines RuntimeAgentDef and the detected agent shape.
  • apps/daemon/src/runtimes/detection.ts, launch.ts, executables.ts, invocation.ts, and models.ts own probing, executable resolution, process launch normalization, and model validation.
  • apps/daemon/src/routes/runs.ts owns POST /api/runs, run event streaming, cancellation, and the compatibility POST /api/chat route. The current run execution pipeline is assembled in apps/daemon/src/server.ts.
  • apps/daemon/src/runtimes/claude-stream.ts, json-event-stream.ts, qoder-stream.ts, and apps/daemon/src/copilot-stream.ts normalize 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, optional listModels or fetchModels, optional reasoningOptions, and custom-model policy.
  • Invocation: buildArgs(), optional runtime environment, prompt delivery mode, image support, and prompt-size constraints.
  • Output normalization: streamFormat and, 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.

  1. Iterate over the registry, including valid local profiles.
  2. 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.
  3. Run the version probe. A missing, non-executable, or broken target is reported as unavailable with a diagnostic.
  4. For an invocable runtime, probe advertised CLI capabilities, models, and authentication concurrently.
  5. Use live model discovery when it succeeds; otherwise expose the adapter's fallback model list and mark its source as fallback.
  6. 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/runs creates and starts a run.
  • GET /api/runs/:id/events streams persisted and live run events.
  • POST /api/runs/:id/cancel cancels the run.
  • POST /api/chat remains the compatibility chat/SSE entry point.

For a local runtime, the shared execution pipeline:

  1. Resolves RuntimeAgentDef from the request's agentId and validates the selected model, reasoning option, project, attachments, and tool bundle.
  2. Resolves the project working directory. This spec MUST NOT define daemon data paths; read root AGENTS.md → Daemon data directory contract.
  3. Composes the daemon system prompt, applicable conversation context, active skill and design-system content, attachments, and the current user turn.
  4. 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.
  5. Resolves the same launch target used by detection, calls buildArgs(), normalizes the platform-specific invocation, and starts the child with an argument array and shell: false.
  6. Delivers the prompt through the adapter's declared input mode and routes stdout through the matching stream or protocol handler.
  7. 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 uses promptInputFormat: 'stream-json'; other stdin adapters receive text.
  • grok-build and atomcode opt 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.started and 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.bin after 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/cancel propagates 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.