Commit Graph

49 Commits

Author SHA1 Message Date
PerishFire f9fe73c836 feat: add DeepSeek Harness support (#6874)
* feat(daemon): scaffold DeepSeek Harness profile protocol

* feat(daemon): integrate DeepSeek Harness profile runtime

* fix(daemon): preserve headless prompts on native resume

* refactor(daemon): model Harness profile resume explicitly

* fix(daemon): resume Harness sessions after cancel

* test(daemon): verify DeepSeek Harness Windows carrier

* test(daemon): reap DeepSeek Harness Windows process tree

* feat(agents): surface DeepSeek Harness models and branding

* fix(daemon): surface Harness credential guidance

* feat: add bundled DeepSeek Harness setup

* fix: link DeepSeek Harness installer

* fix: link official Harness docs

* fix(daemon): distinguish Harness companion install

* test(pack): verify bundled Harness resources on Windows

* fix: harden Harness profile turn lifecycle

Generated-By: looper 0.11.2 (runner=fixer, agent=codex)

* fix(dsh-runtime): stop cancelled restore follow-ups

Generated-By: looper 0.11.2 (runner=fixer, agent=codex)

* fix(daemon): cancel Harness startup before execute

Generated-By: looper 0.11.2 (runner=fixer, agent=codex)

* fix(pack): build DeepSeek runtime on cold cache

---------

Co-authored-by: lefarcen <935902669@qq.com>
Co-authored-by: Looper <looper@noreply.github.com>
2026-08-14 02:07:55 +00:00
open-design-crew[bot] 809d45f27c feat(integrations): add the local Open Design Cloud flow for Codex (#6055)
* feat(daemon): expose Vela login through CLI and MCP

* feat(mcp): add interactive local brief card

* feat(packaged): bootstrap local MCP headlessly

* feat(daemon): secure local BYOK credential profiles

* feat(cli): manage secure BYOK profiles

* feat(web): store BYOK keys in secure profiles

* fix(runs): deduplicate cloud generation requests

* feat(daemon): add end-to-end plugin observability

* fix(pack): include native PTY runtime in desktop packages

Lazy-load node-pty in the daemon so missing native binaries only
disable Terminal and interactive Keychain operations instead of
crashing startup.

Ship and validate target prebuilds in macOS and Windows packages.
Repair the macOS spawn helper before signing, and invalidate stale
Windows packaging caches.

Cover the packaged PTY path in macOS and Windows smoke tests. Require
Vela CLI for every beta desktop build target.

* fix(mcp): localize and stabilize plugin briefs

Keep collect and confirm on one MCP Apps card, report intrinsic size changes,
and remove the fragile widget-state fallback.

Localize brief forms, summaries, status, and public errors from the current
request or Host locale while preserving stable protocol ids and selections.

Keep internal runtime identifiers out of user-facing MCP guidance.

* fix(packaged): register live Studio URLs with daemon

Register the packaged web sidecar loopback origin over namespace-scoped daemon
IPC after dynamic binding.

Invalidate install-info by the live web port and remove the second MCP URL cache
so run and project responses use the current Studio address.

Validate loopback origins and cover registration, rebind, and cache refresh.

* fix(mcp): stabilize brief confirmation lifecycle

Keep confirmed briefs locked after Host publication failures and retry only the cached follow-up message instead of confirming twice.

Replace blank initialization with a compact loading state, accept immediate and delayed tool results, and bump the MCP Apps resource to v3 so Codex does not reuse the stale card.

Add an executable JSDOM Host bridge harness covering double-submit, publication retry, delayed results, and repeated draft notifications. Validated with the full daemon suite, workspace typecheck, and guard.

* fix(mcp): prevent brief app resize feedback loops

Replace the self-observed intrinsic-height loop with deduplicated body measurements so Codex MCP app iframes do not repeatedly resize themselves and fail sandbox startup.

Bump the brief resource URI to v4 to avoid cached v3 cards and cover the regression with the focused brief-app spec. Validated with daemon tests/build, workspace guard/typecheck, a verified beta DMG, and a direct packaged MCP resource smoke.

* fix(mcp): use the final Open Design plugin identity

Make open-design the only accepted external plugin ID across MCP tools, run attribution, artifact version origins, and telemetry. Rename the Brief MCP App resource to v5 and reject the unpublished old ID instead of aliasing it.

Validated with 171 daemon tests, 5 web tests, daemon/web typechecks, and guard.

* chore(pack): bump Vela CLI to 0.0.27

* chore(nix): refresh pnpm dependency hashes

* fix(mcp): honor host and plugin request contracts

Respect independently advertised MCP Apps capabilities and prefer the Codex-native follow-up bridge so confirmed briefs render as readable user turns instead of context-only messages. Bump the brief resource to v6 to invalidate stale cards.\n\nMark Vela login and account probes as open-world interactions, and require stable request IDs for attributed generation so lost responses cannot create a second logical run.

* fix(cli): support keyless BYOK profiles

Add an explicit --no-api-key save mode for local and self-hosted providers while keeping credential-bearing profiles stdin-only. Reject missing or conflicting credential modes and cover both paths in the CLI tests.

* fix(pack): replace headless owner when desktop opens

Advertise headless packaged runtimes as having no visible window, then shut them down before a normal desktop launch continues instead of treating SHOW as a successful focus.

Validated with the focused packaged headless and launcher lifecycle tests (20 passed).

* fix(pack): clean up failed headless startup

Acquire the headless identity, sidecars, and IPC server through one failure-atomic lifecycle so later bootstrap errors close every previously acquired owner in reverse order.

Cover MCP-install and web-identity publication failures; validated with 22 focused tests and the packaged typecheck.

* fix(byok): remove raw provider request contract

Expose only daemon-owned BYOK profile references from shared run types and the web transport, while retaining the daemon's fail-closed rejection for legacy or untyped raw credential payloads.

Validated with 76 web provider tests plus web and contracts typechecks.

* fix(daemon): preserve interrupted run idempotency

Hydrate queued or running durable requests as DAEMON_RESTARTED failures before idempotency reuse, preserving the original request and workflow mappings instead of creating a second cloud operation.

Share the restart transition with boot reconciliation and expose synthetic terminal events to reattaching clients. Validated with 48 focused tests and the daemon typecheck.

* fix(byok): roll back failed credential metadata writes

Snapshot secure-store values before mutation and compensate create, update, and delete operations when profile metadata cannot be persisted, preventing orphaned or lost credentials.

Validated with nine focused credential-service tests and the daemon typecheck.

* fix(web): reconcile selected BYOK profile metadata

Treat the daemon's selected secure profile as authoritative for protocol, endpoint, model, and API version so CLI profile edits cannot leave the browser showing stale execution settings.

Validated with 66 config tests and the web typecheck.

* fix(byok): migrate legacy credentials before cleanup

Import each supported legacy browser credential into a stable daemon-owned secure profile before removing plaintext copies. Keep the original browser record on secure-store or unsupported-provider failures and surface a Settings recovery path.

Cover successful migration, duplicate projections, and injected secure-backend failure while preserving existing Bedrock downgrade behavior in memory.

* fix(byok): secure Windows profiles with DPAPI

Dispatch native Windows BYOK profiles to a CurrentUser DPAPI backend rooted under the resolved daemon data directory. Secrets enter PowerShell only through stdin, encrypted blobs stay separate from non-secret profile metadata, and API responses remain secret-free.

Add platform dispatch coverage, a Windows-only real DPAPI round-trip test, and the packaged Windows smoke path for create, resolve, response-redaction, and delete behavior.

* fix(web): preserve config writes during hydration

* fix(byok): persist secure credentials across entry flows

* test(byok): cover secure onboarding persistence

---------

Co-authored-by: Cheems <94773058+itscheems@users.noreply.github.com>
Co-authored-by: lefarcen <935902669@qq.com>
2026-07-30 02:00:56 +00:00
jaehanbyun 2337932714 feat: expose GPT-5.5 Fast service tier (#4287)
* feat: support Codex service tiers

* fix: forward service tiers through MCP runs

* fix: clear default service tier selections

* fix: preserve service tier on model option updates

* fix: preserve service tier without explicit model

* fix: preserve service tier in connection tests

* test: stabilize API empty stream UI check

* fix: preserve codex service tier labels

* fix: preserve service tier without saved model

* fix: address service tier review follow-ups

* fix: pin legacy chat assistant rows before start

* fix: accept bare model catalog responses
2026-07-22 07:11:03 +00:00
nettee c6ee16be9d feat(daemon): pass open design trace env to AMR (#3667) 2026-06-04 13:37:17 +00:00
chaoxiaoche dbc74a397c feat(agents): CLI detection self-rescue with actionable diagnostics (#3560)
* feat(agents): surface actionable CLI diagnostics

Detect unavailable CLI agents with structured diagnostics, stream agent discovery results to the settings UI, and render actionable fix controls for common setup failures.

Also harden the streamed agents client so server error events and dropped streams surface as failures instead of replacing state with a truncated agent list.

* fix(agents): gate streamed rescan loading

Generated-By: looper 0.9.2 (runner=fixer, agent=codex)

* fix(agents): distinguish non-executable CLI diagnostics

Generated-By: looper 0.9.2 (runner=fixer, agent=codex)

* fix(agents): defer OAuth diagnostics without producer

Generated-By: looper 0.9.2 (runner=fixer, agent=codex)

---------

Co-authored-by: chaoxiaoche <chaoxiaoche@chaoxiaochedeMacBook-Pro.local>
Co-authored-by: Looper <looper@noreply.github.com>
Co-authored-by: Looper Fixer <looper-fixer@noreply.github.com>
Co-authored-by: looper-fixer <looper-fixer@users.noreply.github.com>
2026-06-04 03:18:37 +00:00
fyz3120 428603cf6c Add local custom agent profiles (#378)
Co-authored-by: fuyizheng3120 <fuyizheng3120@users.noreply.github.com>
2026-05-19 13:13:48 +08:00
nettee 28d3e5faf5 Fix Codex wrapper launch paths (#1395) 2026-05-12 17:20:32 +08:00
nettee ab922327f4 refactor(daemon): split agent runtime definitions (#1063) 2026-05-11 15:01:55 +08:00
shangxinyu1 b19aa6c907 Improve Codex CLI path fallback UX (#1205)
* Improve Codex CLI path fallback UX (#1193)

* Handle ENOENT Codex shim fallback
2026-05-11 12:00:47 +08:00
Sid 63a9a08b83 fix(daemon): prefer opencode-cli over opencode binary so OpenCode Desktop installs resolve to the CLI (#814) (#818)
OpenCode Desktop ships two binaries on PATH after install:

  - `opencode`     — GUI launcher; double-clicking it opens the
                     desktop app, never reads stdin.
  - `opencode-cli` — headless CLI; speaks the
                     `run --format json --dangerously-skip-permissions -`
                     protocol the daemon expects.

The OpenCode AGENT_DEF set `bin: 'opencode'`, so
`resolveAgentExecutable` resolved the GUI launcher for every user
with the desktop install. The daemon happily spawned that binary,
but the GUI launcher discards stdin and never emits the JSON event
stream — so the agent silently produced no output for the entire
conversation. Issue #814 tracks the user-visible symptom.

Fix: declare `bin: 'opencode-cli'` and `fallbackBins: ['opencode']`
on the OpenCode adapter. `resolveAgentExecutable` walks `bin`
first, then each fallback in order, so this gives us:

  - Desktop install (both binaries on PATH) → resolves
    `opencode-cli` (the CLI), GUI is ignored. The #814 fix path.
  - Legacy CLI-only install (only `opencode` on PATH, no
    `-cli` suffix) → falls through to `opencode`, which is the
    actual CLI in that install shape, so the daemon keeps working
    unchanged.
  - Neither installed → falls through to null, same as before.

Same mechanism Claude Code uses to fall back to `openclaude`
(issue #235), so this is well-trodden ground in the codebase.

Tests:
- One declarative test asserts `opencode.bin === 'opencode-cli'`
  and `opencode.fallbackBins.includes('opencode')` — runs on every
  platform including Windows, catches anyone who accidentally
  flips `bin` back to the GUI name.
- Two filesystem-backed tests pin the resolution priority: when
  both binaries are on PATH (the desktop case) `opencode-cli`
  wins; when only the legacy `opencode` is on PATH the fallback
  takes over.
- Existing comment guarding "most agents have a single binary"
  updated to remove `opencode` from the example list.

Verified locally:
- daemon vitest: 993/993
- daemon `tsc -p tsconfig.json` and `tsc -p tsconfig.tests.json`: both clean
- i18n-check passes

Reported by @giuliastro, diagnosed by @lefarcen who also asked for
the `opencode-cli --version` output in the issue thread — happy to
narrow this further if their reply turns up subcommand differences
between the two binaries.

Fixes #814
2026-05-09 22:11:46 +08:00
mec dot 039cc3d674 fix(settings): add install onboarding links for unavailable local CLIs (#985)
* fix(settings): add install onboarding links for unavailable local CLIs

* fix(settings): rename Claude config dir label to config directory

---------

Co-authored-by: mrcfps <mrc@powerformer.com>
2026-05-09 21:49:44 +08:00
Nagendhra Madishetti 3c94fa575c feat(daemon): expose gemini-3 preview models and 2.5-flash-lite in the Gemini picker (#986)
* feat(daemon): expose gemini-3 preview models and 2.5-flash-lite in the Gemini fallback list

Issue #981: the Gemini agent picker only offered 2.5 Pro / 2.5 Flash
even though the Gemini CLI ships gemini-3-pro-preview, gemini-3-flash-preview,
and gemini-2.5-flash-lite. Users had to fall back to "Default" or
type the id by hand to reach the newer generation.

Add the three model ids to fallbackModels with the same shape as the
existing entries so the picker surfaces them inline.

* test(daemon): pin Gemini picker fallbackModels order

mrcfps flagged on PR #986 that the new fallback ids only had implicit
coverage via the static array, which means a future reorder/removal in
AGENT_DEFS could silently reshape the Settings UI without tripping CI.
Mirror the codex/qoder regression-test pattern so the Gemini picker
contents stay locked to the documented priority order: default,
gemini-3-pro-preview, gemini-3-flash-preview, gemini-2.5-pro,
gemini-2.5-flash, gemini-2.5-flash-lite.

This is especially worth covering for Gemini because the CLI accepts
arbitrary custom ids, so a regression in the picker would not surface
during manual QA.

---------

Co-authored-by: Nagendhra <nagendhra405@gmail.com>
2026-05-09 08:15:34 +08:00
leprincep35700 2005a5b727 fix: add gpt-5.1 Codex picker options (#946)
* fix: add gpt-5.1 Codex picker options

* test: clarify gpt-5.1 picker coverage

---------

Co-authored-by: leprincep35700 <leprincep35700@users.noreply.github.com>
2026-05-08 21:37:49 +08:00
Marc Chan b06f26a5fd test: strengthen e2e PR coverage (#796)
* test: strengthen e2e PR coverage

* fix: address e2e PR feedback

Generated-By: looper 0.6.1 (runner=fixer, agent=opencode)

* fix: address e2e PR feedback

Generated-By: looper 0.6.1 (runner=fixer, agent=opencode)

* ci: cache Windows packaged smoke builds

* test: fake additional agent runtimes

* fix: address e2e PR feedback

Generated-By: looper 0.6.2 (runner=fixer, agent=opencode)

* fix: address e2e PR feedback

Generated-By: looper 0.6.2 (runner=fixer, agent=opencode)

* fix: address e2e PR feedback

Generated-By: looper 0.6.2 (runner=fixer, agent=opencode)

* fix: address e2e PR feedback

Route tools-pack mac starts through a launch-time packaged config override so portable packaged smoke runs keep using the namespace runtime root that inspect and logs expect.

Generated-By: looper 0.6.2 (runner=fixer, agent=opencode)

* fix: address e2e PR feedback

Fall back to the packaged app's embedded config when the build output config is missing so installed mac starts still work.

Generated-By: looper 0.6.2 (runner=fixer, agent=opencode)

* fix: align packaged mac PR smoke with tools-pack runtime mode

Generated-By: looper 0.6.2 (runner=fixer, agent=opencode)

* fix: address e2e PR feedback

Generated-By: looper 0.6.2 (runner=fixer, agent=opencode)

* fix: address e2e PR feedback

Keep blake3-wasm out of the packaged mac daemon prebundle so the standalone runtime loads the Cloudflare asset hasher from node_modules instead of crashing in ESM.

Generated-By: looper 0.6.2 (runner=fixer, agent=opencode)

* fix: address e2e PR feedback

Skip the portable mac launch override when the bundled packaged config is missing so installed fallback app targets can still boot with packaged defaults.

Add a regression test covering the missing-config start path.

Generated-By: looper 0.6.2 (runner=fixer, agent=opencode)

* fix(pack): remove duplicate mac prebundle dependency key
2026-05-08 16:48:10 +08:00
leprincep35700 bef8203ad9 fix: expand Codex picker coverage (#757)
* fix: add newer Codex model choices

* fix: expand Codex picker coverage

---------

Co-authored-by: leprincep35700 <leprincep35700@users.noreply.github.com>
2026-05-07 20:17:15 +08:00
Tom 8630fd380a feat(daemon): close pi adapter parity gaps
Closes pi adapter parity gaps for image paths, extra allowed dirs, error events, and sendAgentEvent routing.
2026-05-07 20:03:46 +08:00
PerishFire 6efac8887e Improve Windows beta packaging and installer flow (#768)
* Optimize Windows packaged web output

* Fix packaged contracts runtime build

* Optimize Windows packaged size pruning

* Prune Windows root Next payload

* Remove Windows bundled Node runtime

* Prune Windows standalone duplicate Next

* Add tools-pack cache foundation

* Cache Windows packaged build layers

* Cache Windows workspace builds

* Cache Electron-ready Windows app

* Split Windows tools-pack module

* Cache Windows dir build outputs

* Split Windows pack build modules

* Document Windows NSIS smoke namespace limits

* Move Windows NSIS smoke note to agents guide

* Optimize Windows beta packaging

* Bump packaged beta base version

* Improve Windows installer namespace UX

* Improve Windows tools-pack cache keys

* Stabilize Windows beta cache version keys

* Cache Windows workspace build outputs

* Optimize windows release beta cache layers

* Cache windows release dependencies

* Trim windows release cache before save

* Refresh windows tools-pack cache key

* Improve windows installer preflight prompts

* Fallback NSIS installer strings to English

* Fix Windows installer cleanup and preflight

* Improve Windows NSIS state logging

* Fix system NSIS Persian language alias

* Use long-path removal for Windows uninstall

* Fix mac tools-pack tests on Windows

* Address Windows packaging review feedback

* Fix Windows installer cache namespace isolation

* Include web output mode in Windows tarball cache key

* Use unique Windows release cache save keys
2026-05-07 16:44:15 +08:00
shangxinyu1 9b501f12a5 Support overriding the Codex executable path (#755)
* Support overriding the Codex executable path

* Replace save-as-template prompts with an in-app dialog

* Seed local packaged app config from workspace

* Fix packaged config and connection test overrides

* Keep tools-pack mac config seeding self-contained

* Require absolute CODEX_BIN overrides
2026-05-07 15:00:52 +08:00
Sid 0b2b456694 fix(daemon): deliver Copilot prompt via stdin
Avoid Windows ENAMETOOLONG by keeping Copilot prompts out of argv and sending them through stdin instead.\n\nFixes #705
2026-05-07 11:52:30 +08:00
Xinmin Zeng 2455c70d51 fix(daemon, packaged): unbreak GUI-launched agent detection on minimal PATHs (#442) (#614)
* fix(daemon, packaged): unbreak GUI-launched agent detection on minimal PATHs (#442)

GUI-launched daemons (Finder/Dock on macOS, .desktop on Linux) inherit a
stripped PATH from launchd / the desktop session and don't read the
user's interactive shell rc files, so any CLI installed via `npm i -g`
under a sudo-free prefix like ~/.npm-global was silently undetected.

Two layers maintained their own copies of the user-toolchain bin list
(`apps/daemon/src/agents.ts:userToolchainDirs` for the resolver,
`apps/packaged/src/sidecars.ts:resolvePackagedPathEnv` for the packaged
sidecar PATH builder) and had already drifted on `~/.asdf/shims` and
`~/Library/pnpm`. Adding ~/.npm-global to one side would have
preserved the same anti-pattern.

Extracts `wellKnownUserToolchainBins` into @open-design/platform as the
single source of truth, has both layers consume it, and extends the
list to cover ~/.npm-global/bin, ~/.npm-packages/bin, plus
$NPM_CONFIG_PREFIX/bin / $npm_config_prefix/bin for users with a
non-standard prefix. New vitest coverage in the platform package and
a regression test in apps/daemon/tests/agents.test.ts modelled on the
existing mise case.

Verified end-to-end: under PATH=/usr/bin:/bin:/usr/sbin:/sbin (the
launchd default a `.app` actually inherits), `resolveAgentExecutable`
now returns ~/.npm-global/bin/gemini instead of null.

* fix(daemon): isolate OD_AGENT_HOME resolution from $NPM_CONFIG_PREFIX leakage

Address review feedback on PR #614:

- mrcfps spotted that the daemon wrapper called wellKnownUserToolchainBins
  without passing `env`, so the helper read its default process.env. A
  developer or CI runner with NPM_CONFIG_PREFIX / npm_config_prefix
  exported would inject that real <prefix>/bin into resolveOnPath() even
  while the OD_AGENT_HOME hook pointed home at a temp fixture, making
  agent-detection tests environment-dependent. Reproduced locally: with
  OD_AGENT_HOME=<tmp> + NPM_CONFIG_PREFIX=/Users/me/.npm-global,
  resolveAgentExecutable({ bin: 'codex' }) returned the real machine's
  binary instead of null. Wrapper now passes `env: {}` whenever
  homeOverride is set, alongside the existing includeSystemBins gate.

- lefarcen suggested also handling whitespace-only NPM_CONFIG_PREFIX
  values (e.g. NPM_CONFIG_PREFIX=" ") so the helper does not emit a
  bogus "<whitespace>/bin" entry. Added a .trim() check before
  appending.

- lefarcen also suggested a comment pointer from the daemon wrapper to
  the platform helper so readers don't have to grep. Added the
  reference inline.

Coverage:
- packages/platform/tests/index.test.ts: new whitespace-prefix case.
- apps/daemon/tests/agents.test.ts: new env-isolation regression
  asserting that OD_AGENT_HOME + NPM_CONFIG_PREFIX cannot leak the
  real prefix bin into the sandbox.

* test(daemon): preserve $NPM_CONFIG_PREFIX across the env-isolation case (#614)

Address mrcfps's second-round review on PR #614: the env-isolation
regression sets `process.env.NPM_CONFIG_PREFIX = realPrefix` in its
body and then unconditionally `delete`s it in `finally`. On a developer
machine or CI runner that already exported `NPM_CONFIG_PREFIX`, that
mutates the worker-wide env for every later test, making downstream
env-sensitive assertions order-dependent.

Move the save/restore into the file's existing afterEach hook (mirroring
the OD_AGENT_HOME / OD_DAEMON_URL / OD_TOOL_TOKEN pattern) and drop the
in-test `delete`. Same coverage, no worker-state mutation.

* fix(platform): prioritise $NPM_CONFIG_PREFIX over the conventional npm guesses (#614)

Address mrcfps's third-round review on PR #614: when the user has
explicitly configured a prefix via $NPM_CONFIG_PREFIX (or
$npm_config_prefix), that's where `npm i -g` puts the *current*
binaries. The conventional guesses ~/.npm-global / ~/.npm-packages
often hold *stale* installs from an older prefix the user has since
rewritten — searching the env-driven prefix first matches npm's own
resolution order (env > .npmrc > default) and gives "explicit beats
convention" semantics.

Move the env-driven push above the conventional `dirs.push(.npm-global,
.npm-packages)`. Add a vitest case in the platform package that asserts
$NPM_CONFIG_PREFIX/bin's index in the result is strictly less than
~/.npm-global/bin's and ~/.npm-packages/bin's.

`resolveOnPath()` and the packaged PATH builder both preserve insertion
order, so first hit wins and the new ordering propagates to both
layers.

* fix(platform): lift $NPM_CONFIG_PREFIX above every conventional bin (#614)

Address mrcfps's fourth-round review on PR #614: the previous fix only
moved $NPM_CONFIG_PREFIX/bin ahead of ~/.npm-global / ~/.npm-packages,
but ~/.local/bin still appeared earlier in the array. Under a minimal
GUI-launch PATH a stale agent in ~/.local/bin (also a shared dumping
ground for pip --user / cargo install / hand-built binaries) could
outrank the user's *current* explicit npm prefix.

Move the env-driven push to the head of `dirs` so the explicit prefix
wins over every conventional location below — ~/.local/bin included.
Matches npm's own resolution order (env > .npmrc > default) across the
whole list, not just the npm-prefix block.

Tightened the existing order test to assert `explicitIdx === 0` and
that ~/.local/bin's index is strictly greater than the explicit
prefix's index, so a future drift would fail loudly.
2026-05-06 20:35:19 +08:00
mamba 570d06419c feat[qoder cli] add Qoder CLI agent support (#626)
* chore(agent): 增加对 Qoder CLI 的支持和识别

- 在 QUICKSTART 文档中添加 Qoder CLI 为可选本地 agent CLI
- 更新代码中 agents.ts 注释包含 Qoder CLI 扫描支持
- 修改首次加载时检测的可用 CLI 列表,加入 Qoder CLI
- 在多个语言版本的 README 中增加 Qoder CLI 支持及相关徽章统计
- 更新 agent 适配器与事件解析相关的代码注释和文档,包含 qoder-stream-json 解析器
- 调整 Windows 下 spawn 行为以支持 Qoder CLI 的 stdin 提供 prompt
- 修复多语言文档对支持的 CLI 数量描述错误,确保数据保持同步

Change-Id: I388f2f61c60ce8faa7cef5d84eb407950f8bdbfb
Co-developed-by: Qoder <noreply@qoder.com>

* chore(agent): 增加对 Qoder CLI 的支持和识别

- 在 QUICKSTART 文档中添加 Qoder CLI 为可选本地 agent CLI
- 更新代码中 agents.ts 注释包含 Qoder CLI 扫描支持
- 修改首次加载时检测的可用 CLI 列表,加入 Qoder CLI
- 在多个语言版本的 README 中增加 Qoder CLI 支持及相关徽章统计
- 更新 agent 适配器与事件解析相关的代码注释和文档,包含 qoder-stream-json 解析器
- 调整 Windows 下 spawn 行为以支持 Qoder CLI 的 stdin 提供 prompt
- 修复多语言文档对支持的 CLI 数量描述错误,确保数据保持同步

Change-Id: Id33f125b7c0b1a1c0b0274073da74d1578c324f7
Co-developed-by: Qoder <noreply@qoder.com>

* feat(agent-icon): 添加新的Qoder徽标SVG图形组件

- 新增qoderGlyph函数,返回指定大小的SVG格式图形
- 图形包含多路径定义,颜色使用深灰和绿色填充
- 该组件可用于替代或补充现有AgentIcon图标功能
- 提升应用程序的品牌标识和视觉表现力

Change-Id: I4eca18166b5e33bc6229b40b2531d5a54607a560
Co-developed-by: Qoder <noreply@qoder.com>

* Translate to English:

---

**docs(readme): update to expand CLI agents to 16**

- Increased the number of coding agent CLIs from 11 to 16
- New agents included: Devin for Terminal, Kiro CLI, Kilo, Mistral Vibe CLI, DeepSeek TUI

**docs(readme): update to expand supported coding agents to 16**

- Increased the number of supported code agent CLIs from 11 to 16
- Added support for new CLI tools: Devin for Terminal, Kiro CLI, Kilo, Mistral Vibe CLI, DeepSeek CLI
- Added automatic CLI detection and switching while maintaining support for more agents
- Added BYOK proxy TUI
- Expanded compatibility and support coverage in the README’s multiple language versions
- Reflected changes across all README translations (Arabic, German, French, Japanese, Korean)
- Updated badges and descriptions to reflect CLI count and feature changes
- Added event parsers and protocols for the new CLIs in the agent transport implementation
- Updated the BYOK proxy and tool exploration features to be compatible with the expanded CLIs

Change-Id: I89786b4a0b09bd279fb23265c2177076206fc5af
Co-developed-by: Qoder <noreply@qoder.com>

* feat(daemon): 支持 imagePaths 参数作为附件路径传递给 Qoder

- 修改 buildArgs 函数,添加 --attachment 参数处理 imagePaths 中的绝对路径
- 过滤并忽略空字符串、非字符串及相对路径的 imagePaths 项
- 在单元测试中覆盖 imagePaths 参数支持及无效项过滤逻辑
- 在文档中补充 Qoder 运行时适配器对 --attachment 参数的说明

Change-Id: Ibfc3583ba86c6d258d524912559e97b77bf1dc87
Co-developed-by: Qoder <noreply@qoder.com>

* docs(runtime): 说明Qoder适配器继承用户令牌的环境变量

- 添加文档说明检测代理仅为可用性探针,不进行身份验证
- 说明Qoder CLI账号状态独立,认证通过运行时错误路径反馈
- 详细描述子进程环境继承机制及静态环境变量与用户私密令牌区分
- 明确QODER_PERSONAL_ACCESS_TOKEN通过守护进程环境传递,不写入静态环境
- 解释Qoder验证由Qoder CLI负责,支持持久登录和自动化环境变量注入

test(agent): 添加QODER_PERSONAL_ACCESS_TOKEN环境变量继承测试

- 验证qoder适配器环境继承守护进程中的QODER_PERSONAL_ACCESS_TOKEN
- 确认qoder适配器未在静态环境变量中定义用户令牌
- 保证用户私密令牌不会被写入静态适配器环境配置

Change-Id: Ie61869afbe497df1b16879b4e47b35123f758ed8
Co-developed-by: Qoder <noreply@qoder.com>

* fix(daemon): 改进Qoder模式支持及错误处理机制

- 更新Qoder CLI参数,使用`--yolo`替代`--permission-mode bypass_permissions`
- 将工作目录参数从`--cwd`改为`-w`以符合Qoder文档
- 在agent流事件处理中新增错误捕获并通过SSE错误事件发送
- 运行结束时若检测到agent流错误,则标记运行失败
- 测试中fix(daemon): 优化Qoder代理参数与错误处理

- 调整Qoder启动参数,改用`--yolo`和`-w`替代旧参数,避开argv长度限制
- 增强代理流事件处理,捕获并通过SSE错误通同步更新Qoder参数使用及相应断言
- 新增端到端测试,覆盖Qoder助手错误通过SSE错误通道反馈及运行状态失败处理
- 补充工具函数辅助测试事件流读取与运行状态轮询

Change-Id: I5d933745c3659e093b0d2d807f22726e7f83eb48
Co-developed-by: Qoder <noreply@qoder.com>

* feat(qoder-stream): 识别并报告Qoder运行错误事件

- 新增messageFromResult函数以从结果对象提取错误信息
- 在处理result事件时根据is_error字段触发error事件
- error事件携带具体错误消息和原始数据
- 添加测试验证Qoder运行返回is_error且退出码为0时正确触发错误事件
- 更新qoder流解析测试以校验错误事件映射
- 在聊天路由测试中增加针对Qoder错误运行的端到端场景验证

Change-Id: Ie98ac518135dbec3181c52de5a49afdea993e279
Co-developed-by: Qoder <noreply@qoder.com>
2026-05-06 19:54:03 +08:00
Deheng Huang 09b78c2f9b feat(daemon): let Codex image projects use built-in imagegen (#622)
* feat(daemon): let Codex image projects avoid API-key setup

Codex has a built-in image generation path available inside the agent runtime, while the generic media dispatcher still routes gpt-image models through the daemon OpenAI provider. Pass the active agent id into prompt composition so Codex-only gpt-image projects can use built-in imagegen first without changing non-Codex media behavior.

Constraint: Existing media contract remains the default path for non-Codex agents and explicit provider fallback
Rejected: Add a nested daemon Codex media provider | heavier auth, streaming, timeout, cancellation, and output parsing surface for this parity fix
Confidence: high
Scope-risk: narrow
Directive: Keep this override after the media contract so it can intentionally supersede dispatcher-only wording for Codex gpt-image projects
Tested: pnpm --dir apps/daemon exec vitest run -c vitest.config.ts tests/system-prompt-template.test.ts
Tested: pnpm --filter @open-design/daemon typecheck
Tested: pnpm guard
Tested: pnpm typecheck
Not-tested: Live Codex image generation inside the Open Design UI

* fix(daemon): harden Codex imagegen prompt routing

PR review found the Codex override could be superseded by the web-supplied media contract, trusted unvalidated image model metadata, and assumed generated image paths outside the workspace were readable.

This keeps the override daemon-owned, appends it last in the live prompt, validates against registered gpt-image model IDs, allowlists only Codex's generated_images folder, and tightens copy-failure instructions.

Constraint: The web contracts composer still emits the generic media contract without agent identity.

Rejected: Mirror Codex-specific prompt logic into contracts/web | duplicates daemon model registry and still leaves final ordering fragile.

Confidence: high

Scope-risk: narrow

Directive: Keep Codex imagegen override appended after client systemPrompt so it remains the final media instruction for Codex gpt-image projects.

Tested: pnpm --dir apps/daemon exec vitest run -c vitest.config.ts tests/system-prompt-template.test.ts tests/agents.test.ts tests/chat-route.test.ts

Tested: pnpm --filter @open-design/daemon typecheck

Tested: pnpm guard

Tested: pnpm typecheck

Not-tested: Live Codex image generation inside the Open Design UI

* fix(daemon): keep Codex add-dir writable scope narrow

PR review found Codex --add-dir grants writable workspace access, so passing skill, design-system, and linked reference directories through the same chat allowlist broke their documented read-only boundary.

This routes chat extra directories by active agent: Codex receives only the validated generated_images output directory needed for built-in imagegen, while non-Codex adapters keep the existing resource and linked-directory read access behavior.

Constraint: Codex CLI treats --add-dir as writable sandbox expansion.

Constraint: The daemon still stages active skill files into the project cwd as Codex's read-safe path.

Rejected: Keep one shared extraAllowedDirs list for all agents | grants Codex write access to read-only resources.

Confidence: high

Scope-risk: narrow

Directive: Do not add read-only resource/reference directories to Codex --add-dir unless Codex gains a read-only allowlist flag.

Tested: git diff --check -- apps/daemon/src/server.ts apps/daemon/tests/chat-route.test.ts

Tested: pnpm --filter @open-design/daemon exec vitest run tests/chat-route.test.ts

Tested: pnpm --filter @open-design/daemon typecheck

Tested: pnpm guard

Tested: pnpm typecheck

Not-tested: Live Codex image generation inside the Open Design UI

* fix(daemon): validate Codex imagegen add-dir grants

PR review found the generated_images grant still trusted symlinked paths and rendered the Codex override before proving the sandbox grant would be present.

This validates the generated_images directory before prompt assembly, rejects final-component symlinks and protected-root canonical escapes, passes Codex the canonical grant path, and only appends the Codex imagegen override when that same path is in extraAllowedDirs.

Constraint: Codex --add-dir grants writable workspace access, so path aliases into read-only resource roots must be rejected.

Rejected: Keep returning the nominal CODEX_HOME path after validation | leaves Codex operating through a symlink alias instead of the audited grant target.

Confidence: high

Scope-risk: narrow

Directive: Keep Codex imagegen prompt rendering downstream of generated_images validation and grant resolution.

Tested: git diff --check -- apps/daemon/src/server.ts apps/daemon/tests/chat-route.test.ts

Tested: pnpm --filter @open-design/daemon exec vitest run -c vitest.config.ts tests/chat-route.test.ts

Tested: pnpm --filter @open-design/daemon exec vitest run -c vitest.config.ts tests/agents.test.ts tests/chat-route.test.ts

Tested: pnpm --filter @open-design/daemon typecheck

Tested: pnpm guard

Tested: pnpm typecheck

Not-tested: Live Codex image generation inside the Open Design UI
2026-05-06 18:28:16 +08:00
Goemon 95bd7e5373 fix(daemon): add required env field to McpServerStdio + recover from -32602 on set_model (#627)
* fix(daemon): add required env field to McpServerStdio in live-artifacts MCP descriptor

The ACP schema's McpServerStdio marks env as a required field
(List[EnvVariable] with no default). Omitting it causes Pydantic V2
Union validation to fail across all three variants (HttpMcpServer,
SseMcpServer, McpServerStdio), returning -32602 Invalid params on
session/new for agents with mcpDiscovery: 'mature-acp' (Hermes,
Devin, Kimi).

This bug is invisible when mcpServers resolves to an empty array
(no live-artifacts token), so it only manifests when the MCP
live-artifacts integration is enabled.

* fix(daemon): recover from -32602 Invalid params on session/set_model

Extend the existing -32603 Internal error recovery logic to also
handle -32602 (Invalid params) when the set_model request fails.
This allows the prompt to proceed with the default model instead of
hanging or timing out.

Some ACP agents may not support session/set_model or may reject the
model ID — treating this as a non-fatal condition and falling back to
the default model is more resilient than failing the entire run.

* fix(daemon): narrow -32602 handling and update test fixtures for env field

Address PR #627 review feedback:

1. Narrow -32602 Invalid params suppression to setModelRequestId only.
   Unexpected-id -32602 errors are now treated as real protocol failures
   and propagated via fail(), matching the reviewer's suggestion. Only
   -32603 Internal errors from unexpected IDs are still suppressed as
   cleanup noise.

2. Update all buildLiveArtifactsMcpServersForAgent test fixtures to
   include the new required env: [] field.
2026-05-06 16:28:43 +08:00
Sid 33255a8fdf Fix agent CLI config and workspace focus mode (#604)
* fix agent CLI config and workspace focus mode

* address CLI env review follow-ups
2026-05-06 16:06:56 +08:00
Tom 6b2792b03a fix(daemon): remove --no-session from pi adapter to persist session files (#557)
* fix(daemon): remove --no-session from pi adapter to persist session files

The pi agent was the only adapter explicitly passing `--no-session`
in its `buildArgs`, preventing pi from writing session files.
All other adapters either run in single-shot mode by design or use
the ACP JSON-RPC session lifecycle without suppressing persistence.

Removing `--no-session` lets `--mode rpc` retain its default behavior
of writing session state, which is needed for multi-prompt continuity
and matches the rest of the harness ecosystem.

* test(daemon): add pi buildArgs regression tests; fix docs for --no-session removal

- Adds test for pi.buildArgs base shape: returns ["--mode", "rpc"]
  and does not include --no-session (prevents regression).
- Adds test for --model and --thinking option passthrough.
- Updates pi-rpc.ts lifecycle comment to remove [--no-session].
- Updates README.md and all localized READMEs to reflect the
  corrected pi CLI invocation.
2026-05-06 00:26:09 +08:00
Violet 34e8db175d fix(daemon): preserve ANTHROPIC_API_KEY when ANTHROPIC_BASE_URL is set (#514)
* fix(daemon): preserve ANTHROPIC_API_KEY when ANTHROPIC_BASE_URL is set

The claude adapter currently strips ANTHROPIC_API_KEY unconditionally
so that Claude Code's own auth resolution (claude login) wins instead
of silently falling back to API-key billing.

However, when ANTHROPIC_BASE_URL is set the user is intentionally
routing Claude Code to a custom endpoint (e.g. a Kimi/Moonshot proxy).
In that case claude login is meaningless, so preserve the API key so
the child can authenticate against the custom base URL.

* fix(daemon): guard against empty ANTHROPIC_BASE_URL values

Address review feedback: check that ANTHROPIC_BASE_URL contains a
non-empty, non-whitespace string before preserving ANTHROPIC_API_KEY.
This prevents the #398 billing guard from being bypassed when the
variable is set to '' or whitespace.
2026-05-05 21:02:49 +08:00
Marc Chan c3d9136a0c Add live artifacts and Composio connector catalog (#381)
* docs: add live artifacts implementation spec

* docs: align live artifacts implementation plan

* Ralph iteration 1: work in progress

* Ralph iteration 2: work in progress

* Ralph iteration 3: work in progress

* Ralph iteration 4: work in progress

* Ralph iteration 5: work in progress

* Ralph iteration 6: work in progress

* Ralph iteration 7: work in progress

* Ralph iteration 8: work in progress

* Ralph iteration 9: work in progress

* Ralph iteration 10: work in progress

* Ralph iteration 11: work in progress

* Ralph iteration 12: work in progress

* Ralph iteration 13: work in progress

* Ralph iteration 14: work in progress

* Ralph iteration 15: work in progress

* Ralph iteration 16: work in progress

* Ralph iteration 17: work in progress

* Ralph iteration 18: work in progress

* Ralph iteration 19: work in progress

* Ralph iteration 20: work in progress

* Ralph iteration 21: work in progress

* Ralph iteration 22: work in progress

* Ralph iteration 23: work in progress

* Ralph iteration 24: work in progress

* Ralph iteration 25: work in progress

* Ralph iteration 26: work in progress

* Ralph iteration 27: work in progress

* Ralph iteration 28: work in progress

* Ralph iteration 29: work in progress

* Ralph iteration 30: work in progress

* Ralph iteration 31: work in progress

* Ralph iteration 32: work in progress

* Ralph iteration 33: work in progress

* Ralph iteration 34: work in progress

* Ralph iteration 35: work in progress

* Ralph iteration 36: work in progress

* Ralph iteration 37: work in progress

* Ralph iteration 38: work in progress

* Ralph iteration 39: work in progress

* Ralph iteration 40: work in progress

* Ralph iteration 41: work in progress

* Ralph iteration 42: work in progress

* Ralph iteration 43: work in progress

* Ralph iteration 44: work in progress

* Ralph iteration 45: work in progress

* Ralph iteration 46: work in progress

* Ralph iteration 47: work in progress

* Ralph iteration 48: work in progress

* Ralph iteration 49: work in progress

* Ralph iteration 50: work in progress

* Ralph iteration 51: work in progress

* Ralph iteration 52: work in progress

* Ralph iteration 53: work in progress

* Ralph iteration 54: work in progress

* Ralph iteration 55: work in progress

* Ralph iteration 56: work in progress

* Ralph iteration 57: work in progress

* Ralph iteration 58: work in progress

* Ralph iteration 59: work in progress

* Ralph iteration 60: work in progress

* Ralph iteration 61: work in progress

* Ralph iteration 62: work in progress

* Ralph iteration 63: work in progress

* Ralph iteration 64: work in progress

* Ralph iteration 65: work in progress

* Ralph iteration 1: work in progress

* Ralph iteration 2: work in progress

* Ralph iteration 3: work in progress

* Ralph iteration 4: work in progress

* Ralph iteration 5: work in progress

* Ralph iteration 6: work in progress

* Ralph iteration 8: work in progress

* Ralph iteration 9: work in progress

* Ralph iteration 17: work in progress

* Add Composio-backed connectors

* Add Composio-backed connector catalog

* Fix connector callback flow

* Update live artifact connector refresh

* Fix live artifact refresh updates

* Improve live artifact viewer toolbar

* Refine live artifact source tabs

* Expand Composio connector catalog

* Improve Composio connector browsing

* Fix artifact refresh source safety checks

Generated-By: looper 0.4.1 (runner=fixer, agent=opencode)

* Fix live artifacts PR feedback

Generated-By: looper 0.5.0 (runner=fixer, agent=opencode)

* Fix live artifact preview CORS validation

Generated-By: looper 0.0.0-dev (runner=fixer, agent=opencode)

* Fix connector OAuth IPv6 loopback hosts

Allow bracketed IPv6 loopback Host headers when deriving connector OAuth callback URLs so IPv6-bound daemons can complete connection flow.

Generated-By: looper 0.0.0-dev (runner=fixer, agent=opencode)

* Preserve live artifact refresh permissions

Respect explicit refresh permission choices during live artifact create and update flows so revoked connector sources remain gated.

Generated-By: looper 0.0.0-dev (runner=fixer, agent=opencode)

* Fix live artifact preview cache freshness

Generated-By: looper 0.0.0-dev (runner=fixer, agent=opencode)

* Fix live artifact refresh validation

Guard manual refreshes with local daemon checks and reject daemon_tool sources without a toolName before refresh execution.

Generated-By: looper 0.0.0-dev (runner=fixer, agent=opencode)

* Fix Composio credential invalidation

Generated-By: looper 0.0.0-dev (runner=fixer, agent=opencode)

* Fix live artifact CORS methods

Generated-By: looper 0.0.0-dev (runner=fixer, agent=opencode)

* Fix workspace validation

Restore media config test isolation under Vitest setup data-dir overrides and add the missing French live artifact display copy so the workspace test suite stays aligned.\n\nGenerated-By: looper 0.5.2 (runner=fixer, agent=opencode)

* Fix connector safety filtering

Keep agent-preview connector listings aligned with execution safety policy and prune stale Composio OAuth state records before they accumulate.

Generated-By: looper 0.5.2 (runner=fixer, agent=opencode)

* Fix agent runtime cleanup

Generated-By: looper 0.5.2 (runner=fixer, agent=opencode)

* Fix live artifact daemon access

Validate local-only live artifact routes against the peer socket address and pass daemon-resolved CLI paths to ACP MCP descriptors.\n\nGenerated-By: looper 0.5.2 (runner=fixer, agent=opencode)

* Fix connector run limit pruning

Evict stale connector rate-limit buckets so long-lived daemon processes do not retain per-run entries indefinitely.\n\nGenerated-By: looper 0.5.2 (runner=fixer, agent=opencode)

* Fix connector compact schemas

Generated-By: looper 0.5.2 (runner=fixer, agent=opencode)

* Improve connector connection feedback

* Adjust connector gate positioning

* Fix live artifact refresh commits

Avoid marking refresh candidates failed after snapshot or state persistence errors by deferring live artifact mutations until the durable refresh metadata is written. Also align connector OAuth callback host validation with daemon loopback handling.\n\nGenerated-By: looper 0.5.4 (runner=fixer, agent=opencode)

* Improve connector search relevance

* fix(daemon): harden connector connection state

Require loopback daemon validation before connector connect side effects and only clear provider-owned connector statuses during credential reset.

Generated-By: looper 0.5.4 (runner=fixer, agent=opencode)

* fix(daemon): guard connector disconnect route

Require local daemon request validation before connector disconnect side effects.

Generated-By: looper 0.5.4 (runner=fixer, agent=opencode)

* fix(daemon): guard composio config updates

Generated-By: looper 0.5.4 (runner=fixer, agent=opencode)

* fix(daemon): dispatch live artifacts mcp first

Route the live-artifacts MCP server before the generic MCP CLI so od mcp live-artifacts starts the dedicated server instead of failing generic argument parsing.\n\nGenerated-By: looper 0.5.4 (runner=fixer, agent=opencode)

* fix(daemon): handle integer connector schemas

Allow JSON Schema integer connector inputs while preserving fractional-value validation so generated connector tool schemas accept valid page sizes and limits.

Generated-By: looper 0.5.4 (runner=fixer, agent=opencode)

* fix: align live artifact refresh error codes

Generated-By: looper 0.5.4 (runner=fixer, agent=opencode)

* Fix live artifact connector refresh flow

* Update live artifact design cards

* Add beta badge to live artifact form

* Remove live artifact tile model

* Fix live artifact refresh sync

* Fix live artifact MCP refresh durability

Generated-By: looper 0.5.4 (runner=fixer, agent=opencode)

* Fix live artifact refresh safety

Enforce persisted refresh opt-out and connector auto-read gating before refresh sources execute.

Generated-By: looper 0.5.5 (runner=fixer, agent=opencode)
2026-05-05 16:42:11 +08:00
bojie.hbj 0ab98fed07 fix(daemon): correct Claude Code --add-dir capability detection (fix #430) (#440)
Probe 'claude -p --help' (subcommand help) instead of 'claude --help'
(global help), because --add-dir and --include-partial-messages are
subcommand-specific flags that do not appear in the global help output.

Previously, successful capability probing would set caps.addDir = false
because the flag was not found in global help, causing the daemon to
never pass --add-dir to spawned Claude Code processes. This broke
absolute-path reads for skill seeds and design-system specs, as
Claude Code's sandbox policy blocks access to paths outside the
project cwd unless explicitly allowed via --add-dir.

The probing-failure / timeout path already worked correctly (empty
caps object defaults to passing --add-dir). The failure manifested
only when help probing succeeded and explicitly failed to locate
the subcommand flags.

Co-authored-by: bojiehuang <bojiehuang@bojiehuangdeMacBook-Pro.local>
2026-05-05 12:52:31 +08:00
Ajay Satish ec7dafc007 feat(daemon): add Kilo CLI (ACP) (#480)
* docs(readme): refresh contributors wall

* docs(readme): refresh contributors wall

* feat: kilo cli

* fix: use default model option for kilo

* chore: add  agent_diff id unique test

* chore: add deepseek to docs
2026-05-05 09:17:56 +08:00
Irix 6380c48a48 Update Codex sandbox invocation (#477) 2026-05-05 09:15:32 +08:00
alburt b4e69ac61b fix(copilot): copilot prompt processing with correct command format (#466) 2026-05-05 00:28:42 +08:00
Tom Huang da2b007a43 feat(daemon): add DeepSeek TUI as a code agent adapter (#439)
* feat(daemon): add DeepSeek TUI as a code agent adapter

Register `deepseek` (with `deepseek-tui` cargo-only fallback) in
AGENT_DEFS via `deepseek exec --auto [--model X] <prompt>` and plain-text
streaming. Ships `deepseek-v4-pro` / `deepseek-v4-flash` as fallback
model hints; users can paste any other id (incl. NIM / Fireworks /
SGLang routes) via the custom-model input.

Web UI gets a DeepSeek-blue gradient icon, label/alias mapping, and
docs/agent-adapters.md §5.9 documents the auth state, prompt-as-argv
Windows size limit, and the upstream gap that prevents stdin delivery
today (clap declares `prompt: String` as a required positional).

Adds .deepseek/ to .gitignore alongside the other per-agent runtime
data dirs so first-launch trust files don't leak into git.

* fix(daemon): drop unsupported deepseek-tui fallback bin

The `deepseek` dispatcher owns `exec` / `--auto`; `deepseek-tui` is the
runtime companion it invokes. Listing `deepseek-tui` in fallbackBins
advertised availability for a host that only had the TUI binary, but
buildArgs still emitted `<resolved> exec --auto <prompt>` — which
deepseek-tui itself doesn't accept, so the first /api/chat run would
fail. Upstream documents both binaries as required (npm and cargo paths
install them together), so the fallback didn't correspond to a supported
install. Pin the absence in the agents test and update docs §5.9 + the
adapter table to match.

Generated-By: looper 0.4.0 (runner=fixer, agent=claude-code)

* fix(daemon): pre-flight DeepSeek TUI prompts against argv byte budget

DeepSeek's exec mode requires the prompt as a positional argv arg (no
`-` stdin sentinel upstream), so a fully composed OD prompt — system
text + history + skills + design-system content + the user message —
can blow Windows' ~32 KB CreateProcess limit (or Linux MAX_ARG_STRLEN
on extreme edges) and surface as a generic spawn failure instead of
a DeepSeek-specific, user-actionable message. The adapter now declares
`maxPromptArgBytes = 30_000` (leaves ~2.7 KB argv headroom for `exec
--auto --model <id>` and Windows quoting), and the /api/chat spawn
path checks the composed prompt against that budget before calling
`spawn`. Oversized prompts fail fast with `AGENT_PROMPT_TOO_LARGE`
and guidance to reduce skills/design context or pick an adapter with
stdin support.

Generated-By: looper 0.4.0 (runner=fixer, agent=claude-code)

* test(daemon): pin DeepSeek argv-budget guard with regression tests

The previous spawn-path guard inlined the byte-budget check in the
chat handler, so the only safety net for the DeepSeek argv-only
prompt-delivery shape was a static "the field exists" assertion —
nothing actually exercised the AGENT_PROMPT_TOO_LARGE path or the
short-prompt happy path. Extract the check into a pure
`checkPromptArgvBudget(def, composed)` helper in agents.ts, call it
from /api/chat before bin resolution (so the guard is order-
independent and fires regardless of whether the adapter binary is
on PATH in CI), and add a regression test that exercises both the
oversized-prompt branch (over the conservative under-Windows-
CreateProcess budget) and the short-prompt branch, plus a UTF-8
byte-vs-codepoint case and a stdin-adapter no-op case so the guard
can't silently regress or leak onto adapters that ship the prompt
over stdin.

Generated-By: looper 0.4.0 (runner=fixer, agent=claude-code)

* fix(daemon): pre-flight DeepSeek prompts against Windows .cmd-shim quoting

The first-pass argv-byte guard only inspects the raw composed prompt, so
on Windows an npm-installed `deepseek` resolves to a `.cmd` shim and the
spawn path then wraps the call in `cmd.exe /d /s /c "<inner>"` with
every embedded `"` doubled by `quoteWindowsCommandArg`. A quote-heavy
prompt (code blocks, JSON-shaped skill seeds) under the 30,000-byte
budget can therefore still expand past CreateProcess's 32_767-char
`lpCommandLine` cap and surface as a generic spawn ENAMETOOLONG instead
of the DeepSeek-named, actionable `AGENT_PROMPT_TOO_LARGE` the budget
guard was meant to provide. Add a second pure helper
`checkWindowsCmdShimCommandLineBudget(def, resolvedBin, args)` that
mirrors the platform layer's per-arg quoting and recomputes the would-be
command line length whenever the resolved binary is a `.cmd` / `.bat`
shim, and call it from `/api/chat` after `buildArgs` / `resolveAgentBin`
so the same SSE error fires before `spawn`. Pin the new path with a
quote-heavy regression (prompt is under the byte budget but doubles
past the kernel cap) plus no-op tests for non-`.cmd` resolutions, null
bin, and stdin-only adapters so the guard can't drift back.

Generated-By: looper 0.4.0 (runner=fixer, agent=claude-code)

* fix(daemon): extend DeepSeek argv guard to direct .exe Windows installs

The cmd-shim guard added in 9011361 early-returned for non-`.cmd` /
`.bat` resolutions, so a Windows host that resolved `deepseek` directly
to a `.exe` (cargo-installed CLI, hand-built release, anything outside
the npm shim path) bypassed the post-`buildArgs` budget check entirely.
Direct `.exe` spawns skip the `cmd.exe /d /s /c "<inner>"` wrap, but
Node/libuv still composes a CreateProcess `lpCommandLine` by walking
each argv element through `quote_cmd_arg` — every embedded `"` becomes
`\"`, backslashes adjacent to a quote get doubled. A quote-heavy
prompt (code blocks, JSON-shaped skill seeds) under the 30,000-byte
`maxPromptArgBytes` budget can therefore still expand past the kernel's
32_767-char cap on those installs and surface as a generic spawn
ENAMETOOLONG instead of the actionable `AGENT_PROMPT_TOO_LARGE` the
guard was meant to provide.

Add a sibling pure helper `checkWindowsDirectExeCommandLineBudget(def,
resolvedBin, args)` that mirrors libuv's quoting math (empty -> `""`;
no whitespace/quote -> pass-through; quote-only -> simple wrap;
otherwise per-char escape with backslash-doubling around quotes and
trailing backslashes) and recomputes the would-be command line length
whenever the resolved binary is a non-shim Windows install. The two
Windows guards are mutually exclusive: the cmd-shim guard owns
`.bat` / `.cmd`, the direct-exe guard owns everything else, so a
single oversized prompt never double-emits an SSE error. POSIX paths
on POSIX hosts still skip both guards (no CreateProcess in play), and
stdin-delivered adapters still skip the entire post-buildArgs path.

Wire the new helper into `/api/chat` after the cmd-shim check, pin
the path with a quote-heavy regression on a `C:\Program
Files\DeepSeek\deepseek.exe` resolved bin (prompt under the byte
budget but past the kernel cap once libuv-quoted), plus no-op tests
for ordinary prompts, `.cmd`/`.bat` resolutions, POSIX paths,
null/empty bin, and stdin-only adapters, plus a mutual-exclusivity
assertion so the two guards' division of labour can't drift.

Generated-By: looper 0.4.0 (runner=fixer, agent=claude-code)

* fix(daemon): neutralize cmd.exe %var% expansion in DeepSeek argv

Wrap each `%` in `"^%"` inside `quoteWindowsCommandArg` so cmd.exe's
percent-expansion can't substitute env values into a `.cmd`-shim spawn
when the DeepSeek argv carries a prompt mentioning `%DEEPSEEK_API_KEY%`.
Mirror the change in the agents.ts helper used by the budget guard, add
`AGENT_PROMPT_TOO_LARGE` to the contracts so typed SSE consumers
recognize the existing daemon error code, and pin the literal-prompt
contract with regression tests.

Generated-By: looper 0.4.0 (runner=fixer, agent=claude-code)
2026-05-05 00:08:26 +08:00
Daniel Duma, PhD cfd359e05a [codex] Fix Gemini CLI trust handling (#352)
* Fix Gemini CLI trust handling

* Preserve agent spawn env filtering
2026-05-04 21:39:59 +08:00
Sebastian Westberg eb9693d56c fix(daemon): strip ANTHROPIC_API_KEY when spawning Claude Code (#400)
* fix(daemon): strip ANTHROPIC_API_KEY when spawning Claude Code

Claude Code prefers ANTHROPIC_API_KEY over the user's logged-in
subscription auth when both are present, silently billing API usage
even though the daemon's "Local CLI" mode implies the user wants
their `claude login` credentials (Pro/Max plan) to be used. The
daemon inherited the launching shell's env, so anyone who ever
exported ANTHROPIC_API_KEY for SDK work or scripts hit this.

Strip ANTHROPIC_API_KEY from the env passed to spawn for the
claude adapter only, so Claude Code's own auth resolution applies.

Fixes #398

* fix(daemon): strip ANTHROPIC_API_KEY case-insensitively, extract helper, add tests

Address review feedback on #400:

- Extract spawnEnvForAgent helper in agents.ts so the strip is unit-
  testable and lives next to the other agent-spawn primitives.
- Strip ANTHROPIC_API_KEY case-insensitively. Windows env-var names are
  case-insensitive at the kernel level; spreading process.env into a
  plain object loses Node's case-insensitive accessor, so a mixed-case
  Anthropic_Api_Key would survive `delete env.ANTHROPIC_API_KEY` and
  still reach Claude Code via the spawned env block on Windows.
- Add four tests covering: uppercase strip for claude, case-insensitive
  strip for claude, preservation for non-claude adapters, and input
  immutability.

---------

Co-authored-by: Sebastian Westberg <sebastianwestberg@Sebastians-MacBook-Pro.local>
2026-05-04 09:17:37 +08:00
bezineb5 051d9b890d feat(daemon): add Mistral Vibe CLI agent adapter (#354) 2026-05-03 16:19:09 +08:00
Mohamad Yahia 72edd4fc60 fix(clis): Address Codex and Gemini CLIs not being detected by looking for agent CLIs in user toolchain paths (#346) 2026-05-03 14:08:31 +08:00
Sid 58bbc979e3 fix(daemon): lead copilot spawn with -p - so prompt-via-stdin is consumed (#351) 2026-05-03 13:50:15 +08:00
Sid 0d3de899bd fix(daemon): drop literal - argv from codex spawn so prompts deliver via stdin pipe alone (#342)
Recent Codex CLI versions (≥ 0.122 per #237 reports) reject a bare `-`
argv element with `error: unexpected argument '-' found`, exiting code 2
before any prompt is read. Open Design currently appends `-` after the
positional flags in `apps/daemon/src/agents.ts`, while also setting
`promptViaStdin: true` to deliver the prompt via stdin pipe. The `-`
became redundant after PR #258 standardized stdin delivery — only its
removal was missed for codex, leaving the agent unusable on `main` /
0.2.0 across every platform that runs a current Codex CLI.

This matches the pattern that was already corrected for `cursor-agent`
upstream of this commit (apps/daemon/src/agents.ts line ~392 comment),
where the same `-` sentinel was found to surface as a literal user
prompt. The fix here is the codex equivalent: remove the trailing
`args.push('-')` and rely on `promptViaStdin: true` for delivery.

The existing `agents.test.ts` cases asserted `args.at(-1) === '-'`,
which encoded the broken contract; those assertions are dropped and a
new regression test pins `args.includes('-') === false` across the
plugin, model, reasoning, and disable-plugins permutations so the
sentinel can't sneak back in via a future buildArgs branch.

Out of scope for this PR (not yet verified, left for separate
investigation):

- `--full-auto` is also flagged as deprecated by current Codex versions
  (`use \`--sandbox workspace-write\` instead`). It still parses and
  runs — the warning is non-fatal — and the right replacement involves
  pinning the auto-approval policy that `--full-auto` implies, not just
  `--sandbox`. Cleaning this up safely deserves its own PR after
  confirming the modern equivalent.
- OpenCode (`apps/daemon/src/agents.ts:320`) and Qwen Code
  (`apps/daemon/src/agents.ts:433`) follow the same `args.push('-')` +
  `promptViaStdin: true` shape. Whether their current CLIs also reject
  a bare `-` is unverified; if they do, the same minimal fix applies
  there. Calling out for maintainer assessment alongside #163 / #218.

Closes #237.
2026-05-03 10:45:15 +08:00
Nader Dabit 8c61e43c44 Added Devin for Terminal (#301)
* added Devin for Terminal

* updates based on PR feedback
2026-05-02 22:40:08 +08:00
Sid d58b07fdad feat(daemon): auto-detect OpenClaude as a fallback for Claude Code (#263)
Today open-design detects code agents by exact PATH binary name (`claude`,
`codex`, `gemini`, …). OpenClaude (https://github.com/Gitlawb/openclaude)
is an argv-compatible Claude Code fork that ships under the binary name
`openclaude`, so users with only `openclaude` installed see "Claude Code:
not detected" and have to write a wrapper script (issue #235, "Path B"
workaround).

This change adds a generic fallback-bin mechanism and uses it to declare
`openclaude` as a Claude Code fallback:

- `AGENT_DEFS[claude]` gains `fallbackBins: ['openclaude']` — a new
  optional declarative slot. Agents without a fallback are unchanged.
- `resolveAgentExecutable(def)` is a new exported helper that walks
  `[def.bin, ...def.fallbackBins]` and returns the first PATH hit, or
  null. The two existing `resolveOnPath(def.bin)` callsites in
  `probe()` and `resolveAgentBin()` route through this helper instead
  of reading `def.bin` directly.
- `stripFns()` is extended to drop `fallbackBins` from the API response
  payload — same posture as `helpArgs` / `capabilityFlags` / probe-only
  metadata that shouldn't bleed into the public agents list.

Behavior contract:

- If both `claude` and `openclaude` are on PATH, `claude` still wins
  (the order in the candidate list matters).
- If only `openclaude` is on PATH, the agent shows up as "Claude Code"
  and chat / model-listing / spawning all use the resolved openclaude
  path. Users don't need wrappers and the agent picker stays a single
  "Claude Code" entry instead of confusingly splitting into two.
- Agents with no `fallbackBins` field (codex / gemini / opencode / …)
  resolve via `def.bin` exactly as before.

Why fallback (not a separate AGENT_DEFS entry):

The issue author explicitly preferred the fallback shape over a second
top-level "OpenClaude" entry, and OpenClaude is a verbatim Claude Code
fork — the buildArgs / fallbackModels / streamFormat / capabilityFlags
would all be duplicated. A new `fallbackBins` slot keeps the Claude
config single-sourced and lets future drop-in forks be added with one
extra string.

Test coverage (5 new tests in `tests/agents.test.ts`):

1. `claude.fallbackBins` includes `'openclaude'` — declarative regression
   guard so the AGENT_DEFS entry can't silently drift back.
2. `resolveAgentExecutable` prefers `def.bin` when both candidates are
   present (primary always wins).
3. `resolveAgentExecutable` falls back through `fallbackBins` when
   `def.bin` is missing (the OpenClaude-only install case).
4. `resolveAgentExecutable` returns null when no candidate is on PATH.
5. `resolveAgentExecutable` handles defs with no `fallbackBins` field
   (no-regression guard for codex / gemini / opencode / …).

The 4 filesystem-backed cases skip on Windows because resolveOnPath
walks PATHEXT extensions there and the fixture files don't carry them;
the declarative AGENT_DEFS assertion runs on every platform.

All 230 daemon tests pass locally (was 225 before this PR).

Closes #235
2026-05-02 15:29:07 +08:00
Rin 06b1492744 Standardize agent communication via stdin and remove Windows-specific shims logic (#258)
This change moves Claude Code and GitHub Copilot CLI to stdin-based prompt delivery, aligning them with other agents. By doing so, we can bypass OS command-line length limits on Windows and set shell: false universally, improving security and robustness.

Integration of createCommandInvocation ensures that Windows npm shims (.cmd/.bat) are correctly handled while keeping shell: false, addressing the P1 warning from the automated review and maintaining consistent execution across platforms.
2026-05-02 14:59:21 +08:00
lakatos abdd4119b2 fix(daemon): clamp codex reasoning effort to model-supported values (#223)
* fix(daemon): clamp codex reasoning effort to model-supported values

Codex's CLI accepts `none | minimal | low | medium | high | xhigh`, but
real models support narrower subsets — picking Minimal in OD's settings
made every chat turn fail with `agent exited with code 1` because the
OpenAI Responses API rejects `reasoning.effort=minimal` on the gpt-5.2
through 5.5 family with `unsupported_value`.

Add a client-side clamp that maps the user's pick to one the chosen
model accepts (Minimal -> low for gpt-5.5 family, xhigh -> high for
gpt-5.1, gpt-5.1-codex-mini caps at medium). Default / unknown model
is treated as gpt-5.5 since that's codex's current default. The user's
UI pick stays valid; the wire request gets a level the model can use.

* docs(daemon): clarify clampCodexReasoning unknown-model behavior

Per PR review — make explicit that unknown / future model ids pass
through unclamped on purpose. The server error then surfaces as the
signal that a new model family rule should be added here, rather than
silently downgrading every unrecognized id.

* test(daemon): cover codex reasoning-effort clamp matrix

Adds a table-driven test in apps/daemon/tests/agents.test.ts that drives
clampCodexReasoning through the public buildArgs surface. The 18 cases
cover:

- minimal -> low for default / explicit gpt-5.2-5.5
- low / medium / high pass-through on gpt-5.5
- xhigh -> high for gpt-5.1
- gpt-5.1-codex-mini cap (low/minimal -> medium, high/xhigh -> high)
- unknown / future models pass through unchanged
- 'default' reasoning omits the -c flag entirely
- path-style model ids (vendor/gpt-5.5-foo) clamp correctly

Tests stay at the wire level (asserting on the args array codex.buildArgs
produces), keeping the helper non-exported and matching the rest of the
file's style.

* docs(daemon): clarify gpt-5.1-codex-mini accepts medium / high

Per PR review — the original "caps at `medium`" wording was misleading
because the clamp returns `high` for `high` / `xhigh` inputs, which
contradicts the comment. The model actually accepts `{medium, high}`,
so describing it as "accepts only `medium` / `high`" matches the
function's behavior.

Logic unchanged.
2026-05-01 22:58:34 +08:00
Pavel Cherkashin 8c90ef6f55 fix(daemon): deliver Claude Code prompt via stdin to avoid spawn E2BIG/ENAMETOOLONG (#143)
Claude Code is the last agent that still embeds the composed prompt in
argv (`-p <prompt>`). Composed prompts (system prompt + design system +
skill body + user message) routinely exceed:

  - Linux  : MAX_ARG_STRLEN ~128 KB per argv entry → `spawn E2BIG`
  - Windows: CreateProcess command-line cap ~32 KB direct, ~8 KB via
             `.cmd` shim → `spawn ENAMETOOLONG`

the prompt through `child.stdin` (`promptViaStdin: true`). Claude was
explicitly excluded at the time. #97 mitigated the Windows case for
Claude with a `.od-prompt.md` temp-file fallback, but that path still
leaves a stray file in the project, doesn't trigger on Linux, and is
slower than the stdin route the other agents already use.

This change brings Claude in line with the rest:

  - Drop the prompt from argv; keep the bare `-p` print-mode flag
  - Set `promptViaStdin: true` so server.ts pipes `composed` on stdin
  - Add a regression test that asserts the prompt body never lands in
    argv even at 200 KB

Verified locally that `claude -p --output-format stream-json --verbose`
(no positional prompt) reads the prompt from stdin under the default
`--input-format text`, which has no length cap.

Fixes #82
Refs #100, #52
2026-05-01 22:45:10 +08:00
GeorgePSpark 534349aa4c feat(daemon): add Kiro CLI agent adapter (#185)
* feat(daemon): add Kiro CLI agent adapter

* docs: add Kiro CLI to README and agent-adapters

* test(daemon): add kiro fetchModels fallback test
2026-05-01 12:25:26 +08:00
Tom Huang 3f266103b0 feat(media): port generation workflow onto main (#12)
Co-authored-by: Elian <elian@EliandeMacBook-Pro.local>
2026-04-30 22:44:00 +08:00
初晨 39c0399ded fix(daemon): stop passing literal dash to cursor-agent (#160) 2026-04-30 18:06:03 +08:00
Tom 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.
2026-04-30 17:45:11 +08:00
Caprika bd2e71c708 fix codex plugin disable env (#133) 2026-04-30 15:38:46 +08:00
PerishFire c6d11018a0 Refresh desktop integration control plane (#123)
* feat(dev): add desktop tools-dev control plane

* refactor(sidecar): split Open Design contracts

Move Open Design-specific sidecar protocol definitions into @open-design/contracts so sidecar and platform can remain descriptor-driven primitives.

* refactor(daemon): organize package sources

Keep daemon app code, tests, and sidecar entrypoints in separate package directories so each layer can be built and verified independently.

* chore(repo): streamline maintenance entrypoints

Centralize agent guidance by directory and reduce root command chains while preserving the existing build scope.

* docs: translate agent guidance to English

* fix(sidecar): tolerate stale IPC sockets

Remove stale Unix socket files only after confirming no listener is active, so tools-dev can restart after unclean shutdowns.
2026-04-30 14:23:53 +08:00