diff --git a/QUICKSTART.md b/QUICKSTART.md index 32c1bd52fa..21537dad48 100644 --- a/QUICKSTART.md +++ b/QUICKSTART.md @@ -65,7 +65,7 @@ open-design/ ├── daemon/ # Node/Express — spawns local agents + serves APIs │ ├── cli.js # `od` bin entry (also used by npm scripts) │ ├── server.js # /api/agents /api/skills /api/design-systems /api/chat /api/upload /api/artifacts/save -│ ├── agents.js # PATH scanner for claude/codex/gemini/opencode/cursor-agent/qwen +│ ├── agents.js # PATH scanner for claude/codex/gemini/opencode/cursor-agent/qwen/copilot │ ├── skills.js # SKILL.md loader (frontmatter parser) │ ├── design-systems.js # DESIGN.md loader │ └── frontmatter.js # tiny YAML-subset parser (no deps) @@ -109,7 +109,7 @@ open-design/ ## Troubleshooting -- **"no agents found on PATH"** — install one of: `claude`, `codex`, `gemini`, `opencode`, `cursor-agent`, `qwen`. Or switch to "Anthropic API · BYOK" in the top bar and paste a key in **Settings**. +- **"no agents found on PATH"** — install one of: `claude`, `codex`, `gemini`, `opencode`, `cursor-agent`, `qwen`, `copilot`. Or switch to "Anthropic API · BYOK" in the top bar and paste a key in **Settings**. - **daemon 500 on /api/chat** — check the daemon terminal for the stderr tail; usually the CLI rejected its args. Different CLIs take different argv shapes; see `daemon/agents.js` `buildArgs` if you need to tweak. - **artifact never renders** — the model produced text without wrapping in ``. Confirm the system prompt is going through (check daemon log) and consider switching to a more capable model or a stricter skill. diff --git a/README.md b/README.md index 4a8cf313db..88304d0677 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Open Design -> **The open-source alternative to [Claude Design][cd].** Local-first, web-deployable, BYOK at every layer — your existing coding agent (Claude Code, Codex, Cursor Agent, Gemini CLI, OpenCode, Qwen) becomes the design engine, driven by **19 composable Skills** and **71 brand-grade Design Systems**. +> **The open-source alternative to [Claude Design][cd].** Local-first, web-deployable, BYOK at every layer — your existing coding agent (Claude Code, Codex, Cursor Agent, Gemini CLI, OpenCode, Qwen, GitHub Copilot CLI) becomes the design engine, driven by **19 composable Skills** and **71 brand-grade Design Systems**.

Open Design — editorial cover: design with the agent on your laptop @@ -8,7 +8,7 @@

License - Agents + Agents Design systems Skills Quickstart @@ -39,7 +39,7 @@ OD stands on four open-source shoulders: | | What you get | |---|---| -| **Coding agents supported** | Claude Code · Codex CLI · Cursor Agent · Gemini CLI · OpenCode · Qwen Code · Anthropic API (BYOK fallback) | +| **Coding agents supported** | Claude Code · Codex CLI · Cursor Agent · Gemini CLI · OpenCode · Qwen Code · GitHub Copilot CLI · Anthropic API (BYOK fallback) | | **Design systems built-in** | **71** — 2 hand-authored starters + 69 product systems (Linear, Stripe, Vercel, Airbnb, Tesla, Notion, Anthropic, Apple, Cursor, Supabase, Figma, …) imported from [`awesome-design-md`][acd2] | | **Skills built-in** | **19** — prototype, deck, mobile, dashboard, pricing, docs, blog, SaaS landing, plus 10 document/work-product templates (PM spec, weekly update, OKRs, runbook, kanban, …) | | **Visual directions** | 5 curated schools (Editorial Monocle · Modern Minimal · Tech Utility · Brutalist · Soft Warm) — each ships a deterministic OKLch palette + font stack | @@ -180,7 +180,7 @@ Adding a skill takes one folder. Read [`docs/skills-protocol.md`](docs/skills-pr ### 1 · We don't ship an agent. Yours is good enough. -The daemon scans your `PATH` for [`claude`](https://docs.anthropic.com/en/docs/claude-code), [`codex`](https://github.com/openai/codex), [`cursor-agent`](https://www.cursor.com/cli), [`gemini`](https://github.com/google-gemini/gemini-cli), [`opencode`](https://opencode.ai/), and [`qwen`](https://github.com/QwenLM/qwen-code) on startup. Whichever it finds becomes the design engine — driven via stdio, with one adapter per CLI. Inspired by [`multica`](https://github.com/multica-ai/multica) and [`cc-switch`](https://github.com/farion1231/cc-switch). No CLI? `Anthropic API · BYOK` is the same pipeline minus the spawn. +The daemon scans your `PATH` for [`claude`](https://docs.anthropic.com/en/docs/claude-code), [`codex`](https://github.com/openai/codex), [`cursor-agent`](https://www.cursor.com/cli), [`gemini`](https://github.com/google-gemini/gemini-cli), [`opencode`](https://opencode.ai/), [`qwen`](https://github.com/QwenLM/qwen-code), and [`copilot`](https://github.com/features/copilot/cli) on startup. Whichever it finds becomes the design engine — driven via stdio, with one adapter per CLI. Inspired by [`multica`](https://github.com/multica-ai/multica) and [`cc-switch`](https://github.com/farion1231/cc-switch). No CLI? `Anthropic API · BYOK` is the same pipeline minus the spawn. ### 2 · Skills are files, not plugins. @@ -239,17 +239,17 @@ Every layer is composable. Every layer is a file you can edit. Read [`src/prompt └─────────┬────────────┘ │ spawn(cli, [...], { cwd: .od/projects/ }) ▼ - ┌──────────────────────────────────────────────────────────┐ - │ claude · codex · cursor-agent · gemini · opencode · qwen│ - │ reads SKILL.md + DESIGN.md, writes artifacts to disk │ - └──────────────────────────────────────────────────────────┘ + ┌────────────────────────────────────────────────────────────────────┐ + │ claude · codex · cursor-agent · gemini · opencode · qwen · copilot│ + │ reads SKILL.md + DESIGN.md, writes artifacts to disk │ + └────────────────────────────────────────────────────────────────────┘ ``` | Layer | Stack | |---|---| | Frontend | Vite 5 + React 18 + TypeScript | | Daemon | Node 20–22 · Express · SSE streaming · `better-sqlite3` for projects/conversations/messages/tabs | -| Agent transport | `child_process.spawn` with `claude-stream-json` parser for Claude Code, line-buffered plain stdout for the rest | +| Agent transport | `child_process.spawn` with typed-event parsers for Claude Code (`claude-stream-json`) and Copilot CLI (`copilot-stream-json`); line-buffered plain stdout for the rest | | Storage | Plain files in `.od/projects//` + SQLite at `.od/db.sqlite` (gitignored) | | Preview | Sandboxed iframe via `srcdoc` + per-skill `` parser | | Export | HTML (inline assets) · PDF (browser print) · PPTX (skill-defined) · ZIP (archiver) | @@ -501,6 +501,7 @@ Auto-detected from `PATH` on daemon boot. No config required. | [Gemini CLI](https://github.com/google-gemini/gemini-cli) | `gemini` | line-buffered | `gemini -p` | | [OpenCode](https://opencode.ai/) | `opencode` | line-buffered | `opencode run` | | [Qwen Code](https://github.com/QwenLM/qwen-code) | `qwen` | line-buffered | `qwen -p` | +| [GitHub Copilot CLI](https://github.com/features/copilot/cli) | `copilot` | `--output-format json` (typed events) | `copilot -p --allow-all-tools --output-format json` | | Anthropic API · BYOK | n/a | SSE direct | Browser fallback when no CLI is on PATH | Adding a new CLI is one entry in [`daemon/agents.js`](daemon/agents.js). Streaming format is one of `claude-stream-json` (typed events) or `plain` (raw text). diff --git a/README.zh-CN.md b/README.zh-CN.md index 5425cf0b5c..0a3b034dba 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -1,6 +1,6 @@ # Open Design -> **[Claude Design][cd] 的开源替代品。** 本地优先、可部署到 Vercel、每一层都 BYOK —— 你机器上已经装好的 coding agent(Claude Code、Codex、Cursor Agent、Gemini CLI、OpenCode、Qwen)就是设计引擎,由 **19 个可组合 Skills** 和 **71 套品牌级 Design System** 驱动。 +> **[Claude Design][cd] 的开源替代品。** 本地优先、可部署到 Vercel、每一层都 BYOK —— 你机器上已经装好的 coding agent(Claude Code、Codex、Cursor Agent、Gemini CLI、OpenCode、Qwen、GitHub Copilot CLI)就是设计引擎,由 **19 个可组合 Skills** 和 **71 套品牌级 Design System** 驱动。

Open Design 封面:与本地 AI 智能体共同设计 @@ -8,7 +8,7 @@

License - Agents + Agents Design systems Skills Quickstart @@ -39,7 +39,7 @@ OD 站在四个开源项目的肩膀上: | | 你拿到的 | |---|---| -| **支持的 coding agent** | Claude Code · Codex CLI · Cursor Agent · Gemini CLI · OpenCode · Qwen Code · Anthropic API(BYOK 兜底) | +| **支持的 coding agent** | Claude Code · Codex CLI · Cursor Agent · Gemini CLI · OpenCode · Qwen Code · GitHub Copilot CLI · Anthropic API(BYOK 兜底) | | **内置 design system** | **71 套** —— 2 套手写起手 + 69 套从 [`awesome-design-md`][acd2] 导入的产品系统(Linear、Stripe、Vercel、Airbnb、Tesla、Notion、Anthropic、Apple、Cursor、Supabase、Figma…) | | **内置 skill** | **19 个** —— 原型 / deck / 移动端 / dashboard / pricing / docs / blog / SaaS landing,外加 10 个文档与办公产物模板(PM 规范、周报、OKR、runbook、看板…) | | **视觉方向** | 5 套精选流派(Editorial Monocle · Modern Minimal · Tech Utility · Brutalist · Soft Warm),每一套自带 OKLch 色板 + 字体栈 | @@ -180,7 +180,7 @@ OD 站在四个开源项目的肩膀上: ### 1 · 我们不带 agent,你的就够好 -Daemon 启动时扫 `PATH`,找 [`claude`](https://docs.anthropic.com/en/docs/claude-code)、[`codex`](https://github.com/openai/codex)、[`cursor-agent`](https://www.cursor.com/cli)、[`gemini`](https://github.com/google-gemini/gemini-cli)、[`opencode`](https://opencode.ai/)、[`qwen`](https://github.com/QwenLM/qwen-code)。哪个在就用哪个 —— 通过 stdio 驱动,每个 CLI 一个 adapter。灵感来自 [`multica`](https://github.com/multica-ai/multica) 和 [`cc-switch`](https://github.com/farion1231/cc-switch)。一个 CLI 都没有?`Anthropic API · BYOK` 就是同一条管线减去 spawn。 +Daemon 启动时扫 `PATH`,找 [`claude`](https://docs.anthropic.com/en/docs/claude-code)、[`codex`](https://github.com/openai/codex)、[`cursor-agent`](https://www.cursor.com/cli)、[`gemini`](https://github.com/google-gemini/gemini-cli)、[`opencode`](https://opencode.ai/)、[`qwen`](https://github.com/QwenLM/qwen-code)、[`copilot`](https://github.com/features/copilot/cli)。哪个在就用哪个 —— 通过 stdio 驱动,每个 CLI 一个 adapter。灵感来自 [`multica`](https://github.com/multica-ai/multica) 和 [`cc-switch`](https://github.com/farion1231/cc-switch)。一个 CLI 都没有?`Anthropic API · BYOK` 就是同一条管线减去 spawn。 ### 2 · Skill 是文件,不是插件 @@ -239,17 +239,17 @@ DISCOVERY 指令 (turn-1 表单、turn-2 品牌分支、TodoWrite、 └─────────┬────────────┘ │ spawn(cli, [...], { cwd: .od/projects/ }) ▼ - ┌──────────────────────────────────────────────────────────┐ - │ claude · codex · cursor-agent · gemini · opencode · qwen│ - │ 读 SKILL.md + DESIGN.md,把 artifact 写到磁盘 │ - └──────────────────────────────────────────────────────────┘ + ┌────────────────────────────────────────────────────────────────────┐ + │ claude · codex · cursor-agent · gemini · opencode · qwen · copilot│ + │ 读 SKILL.md + DESIGN.md,把 artifact 写到磁盘 │ + └────────────────────────────────────────────────────────────────────┘ ``` | 层 | 技术栈 | |---|---| | 前端 | Vite 5 + React 18 + TypeScript | | Daemon | Node 20–22 · Express · SSE 流 · `better-sqlite3` 存项目/对话/消息/tab | -| Agent 传输层 | `child_process.spawn`,Claude Code 走 `claude-stream-json` 解析器,其余走 line-buffered plain stdout | +| Agent 传输层 | `child_process.spawn`,Claude Code 走 `claude-stream-json` 解析器、Copilot CLI 走 `copilot-stream-json`,其余走 line-buffered plain stdout | | 存储 | 纯文件 `.od/projects//` + SQLite `.od/app.sqlite`(已 gitignore,daemon 启动自建) | | 预览 | 沙盒 iframe(`srcdoc`)+ 每个 skill 的 `` parser | | 导出 | HTML(内联资源)· PDF(浏览器打印)· PPTX(skill 自定义)· ZIP(archiver) | @@ -501,6 +501,7 @@ Daemon 启动时从 `PATH` 自动检测,无需配置。 | [Gemini CLI](https://github.com/google-gemini/gemini-cli) | `gemini` | line-buffered | `gemini -p` | | [OpenCode](https://opencode.ai/) | `opencode` | line-buffered | `opencode run` | | [Qwen Code](https://github.com/QwenLM/qwen-code) | `qwen` | line-buffered | `qwen -p` | +| [GitHub Copilot CLI](https://github.com/features/copilot/cli) | `copilot` | `--output-format json`(类型化事件) | `copilot -p --allow-all-tools --output-format json` | | Anthropic API · BYOK | n/a | SSE 直连 | 没装任何 CLI 时的浏览器兜底 | 加一个新 CLI = 在 [`daemon/agents.js`](daemon/agents.js) 里加一项。流式格式从 `claude-stream-json`(类型化事件)和 `plain`(原始文本)两种里选一个。 diff --git a/daemon/agents.js b/daemon/agents.js index 435c8e69ff..f3a5150902 100644 --- a/daemon/agents.js +++ b/daemon/agents.js @@ -251,6 +251,53 @@ export const AGENT_DEFS = [ }, streamFormat: 'plain', }, + { + id: 'copilot', + name: 'GitHub Copilot CLI', + bin: 'copilot', + versionArgs: ['--version'], + // `--allow-all-tools` is required for non-interactive runs: without it + // the CLI blocks waiting for human approval on every tool call. Unlike + // Codex (where `exec` is a dedicated headless subcommand with + // auto-approve baked in) or Claude Code (which inherits its permission + // policy from the user's settings.json), Copilot's `-p` mode always + // prompts unless this flag is passed explicitly. + // + // `--output-format json` produces JSONL that copilot-stream.js parses + // into the same typed events as claude-stream.js. + // + // `--add-dir` (repeatable, same flag as Claude Code's) widens Copilot's + // path-level sandbox to skill seeds + design-system specs outside the + // project cwd. + // + // No `models` subcommand; the CLI accepts whatever the user's Copilot + // subscription exposes. Ship a small evidence-based hint list — the + // default we observed in the JSON stream and the example from + // `copilot --help`. Users can paste any other id via Settings. + fallbackModels: [ + DEFAULT_MODEL_OPTION, + { id: 'claude-sonnet-4.6', label: 'Claude Sonnet 4.6' }, + { id: 'gpt-5.2', label: 'GPT-5.2' }, + ], + buildArgs: (prompt, _imagePaths, extraAllowedDirs = [], options = {}) => { + const args = [ + '-p', + prompt, + '--allow-all-tools', + '--output-format', + 'json', + ]; + if (options.model && options.model !== 'default') { + args.push('--model', options.model); + } + const dirs = (extraAllowedDirs || []).filter( + (d) => typeof d === 'string' && d.length > 0, + ); + for (const d of dirs) args.push('--add-dir', d); + return args; + }, + streamFormat: 'copilot-stream-json', + }, ]; function resolveOnPath(bin) { diff --git a/daemon/copilot-stream.js b/daemon/copilot-stream.js new file mode 100644 index 0000000000..8dfbd4749a --- /dev/null +++ b/daemon/copilot-stream.js @@ -0,0 +1,129 @@ +/** + * Parses GitHub Copilot CLI's `--output-format json` JSONL stream into the + * same UI-friendly events that claude-stream.js emits, so the chat panel + * can render Copilot's thinking / tool calls / text the same way it does + * Claude Code's. + * + * Copilot's schema uses dotted top-level types (`assistant.*`, `tool.*`, + * `session.*`, `user.*`, `result`) with the payload under `data`. The + * `ephemeral: true` events (session.mcp_*, reasoning_delta, etc.) are still + * useful — they carry the streaming deltas — but events we don't have a UI + * lane for (mcp_server_status, skills_loaded, full reasoning recap, turn + * boundaries) are dropped on the floor. + * + * Mapping: + * session.tools_updated -> status (initializing, with model name) + * assistant.turn_start -> status (streaming) + * assistant.reasoning_delta -> thinking_delta + * assistant.message_delta -> text_delta + * tool.execution_start -> tool_use + * tool.execution_complete -> tool_result + * result -> usage + */ + +export function createCopilotStreamHandler(onEvent) { + let buffer = ''; + + function feed(chunk) { + buffer += chunk; + let nl; + while ((nl = buffer.indexOf('\n')) !== -1) { + const line = buffer.slice(0, nl).trim(); + buffer = buffer.slice(nl + 1); + if (!line) continue; + let obj; + try { + obj = JSON.parse(line); + } catch { + onEvent({ type: 'raw', line }); + continue; + } + handleObject(obj); + } + } + + function flush() { + const rem = buffer.trim(); + buffer = ''; + if (!rem) return; + try { + handleObject(JSON.parse(rem)); + } catch { + onEvent({ type: 'raw', line: rem }); + } + } + + function handleObject(obj) { + if (!obj || typeof obj !== 'object' || typeof obj.type !== 'string') return; + const data = obj.data || {}; + + switch (obj.type) { + case 'session.tools_updated': + if (data.model) { + onEvent({ type: 'status', label: 'initializing', model: data.model }); + } + return; + + case 'assistant.turn_start': + onEvent({ type: 'status', label: 'streaming' }); + return; + + case 'assistant.reasoning_delta': + if (typeof data.deltaContent === 'string') { + onEvent({ type: 'thinking_delta', delta: data.deltaContent }); + } + return; + + case 'assistant.message_delta': + if (typeof data.deltaContent === 'string') { + onEvent({ type: 'text_delta', delta: data.deltaContent }); + } + return; + + case 'tool.execution_start': + onEvent({ + type: 'tool_use', + id: data.toolCallId ?? null, + name: data.toolName ?? null, + input: data.arguments ?? null, + }); + return; + + case 'tool.execution_complete': + onEvent({ + type: 'tool_result', + toolUseId: data.toolCallId ?? null, + content: stringifyResult(data.result), + isError: data.success === false, + }); + return; + + case 'result': + // `result` puts usage / exitCode at the top level, not under `data`. + // Treat a missing exitCode as success when `success: true` is set — + // strict `=== 0` would otherwise mis-flag turns where Copilot emits + // usage without a numeric exit code as `error`. + onEvent({ + type: 'usage', + usage: obj.usage ?? null, + stopReason: + obj.success === true || obj.exitCode === 0 ? 'completed' : 'error', + durationMs: obj.usage?.sessionDurationMs ?? null, + }); + return; + + default: + return; + } + } + + return { feed, flush }; +} + +function stringifyResult(r) { + if (r == null) return ''; + if (typeof r === 'string') return r; + if (typeof r.content === 'string') return r.content; + if (typeof r.detailedContent === 'string') return r.detailedContent; + return JSON.stringify(r); +} diff --git a/daemon/server.js b/daemon/server.js index b431a9c360..2d750a197b 100644 --- a/daemon/server.js +++ b/daemon/server.js @@ -16,6 +16,7 @@ import { import { listSkills } from './skills.js'; import { listDesignSystems, readDesignSystem } from './design-systems.js'; import { createClaudeStreamHandler } from './claude-stream.js'; +import { createCopilotStreamHandler } from './copilot-stream.js'; import { renderDesignSystemPreview } from './design-system-preview.js'; import { renderDesignSystemShowcase } from './design-system-showcase.js'; import { lintArtifact, renderFindingsForAgent } from './lint-artifact.js'; @@ -895,6 +896,10 @@ export async function startServer({ port = 7456 } = {}) { const claude = createClaudeStreamHandler((ev) => send('agent', ev)); child.stdout.on('data', (chunk) => claude.feed(chunk)); child.on('close', () => claude.flush()); + } else if (def.streamFormat === 'copilot-stream-json') { + const copilot = createCopilotStreamHandler((ev) => send('agent', ev)); + child.stdout.on('data', (chunk) => copilot.feed(chunk)); + child.on('close', () => copilot.flush()); } else { child.stdout.on('data', (chunk) => send('stdout', { chunk })); } diff --git a/docs/agent-adapters.md b/docs/agent-adapters.md index aa14bad2ff..ea845c72fe 100644 --- a/docs/agent-adapters.md +++ b/docs/agent-adapters.md @@ -90,6 +90,7 @@ If both signals agree, detection is confident. If only one signal fires, we mark | **gemini-cli** | `gemini` | `~/.config/gemini/` | ❌ | ❌ (prompt-injected) | ❌ (regenerate) | ✅ | P2 | | **opencode** | `opencode` | `~/.opencode/` | 〜 | 〜 | ✅ | P2 | | **openclaw** | `openclaw` | `~/.openclaw/` | 〜 | 〜 | 〜 | P2 | +| **copilot** | `copilot` | `~/.copilot/` | ❌ | ✅ (`edit` tool) | ✅ (`--output-format json` JSONL) | P2 | "P0/P1/P2" correspond to the roadmap phases in [`roadmap.md`](roadmap.md). @@ -164,6 +165,14 @@ The adapter declares which strategy to use via `capabilities().nativeSkillLoadin - Less-matured CLIs. Targeting P2. Expect bumps; adapter implementations will likely be the thinnest possible "shell out, parse output, synthesize events" approach. +### 5.7 GitHub Copilot CLI + +- Invocation: `copilot -p "" --allow-all-tools --output-format json --add-dir --add-dir `. `--allow-all-tools` is mandatory in non-interactive mode — without it the CLI blocks waiting for human approval on every tool call. Unlike Codex (where `exec` is a dedicated headless subcommand with auto-approve baked in) or Claude Code (which inherits its permission policy from `~/.claude/settings.json`), Copilot's `-p` mode always prompts unless this flag is passed explicitly. `--add-dir` (repeatable) widens the path-level sandbox so Copilot can read skill seeds and design-system specs that live outside the project cwd. +- Streaming: `--output-format json` emits JSONL with the same expressive shape as Claude Code's stream-json (`assistant.reasoning_delta`, `assistant.message_delta`, `tool.execution_start/complete`, `result`). `daemon/copilot-stream.js` maps these onto the same UI events as `claude-stream.js`. +- Skill loading: prompt injection only. Github Copilot's tool catalog includes a `skill` tool — native format worth reverse-engineering later. +- Surgical edits: dedicated `edit` tool. +- Detection assumes Copilot is already authenticated, via one of: `copilot login` (subcommand, OAuth device flow), the interactive `/login` slash command inside `copilot` with no args. + ## 6. Capability-driven UI The web UI reads `agents.capabilities()` and disables features that the active adapter can't support: diff --git a/src/components/AgentIcon.tsx b/src/components/AgentIcon.tsx index 814398114a..7699bb9924 100644 --- a/src/components/AgentIcon.tsx +++ b/src/components/AgentIcon.tsx @@ -108,6 +108,23 @@ const VISUALS: Record = { ); }, }, + // GitHub Copilot — GitHub-dark with the Copilot two-eye mark. + copilot: { + bg: 'linear-gradient(135deg, #0d1117 0%, #1f2937 100%)', + fg: '#ffffff', + glyph: (s) => { + const c = s / 2; + const eyeOff = s * 0.14; + const eyeRx = s * 0.075; + const eyeRy = s * 0.12; + return ( + + + + + ); + }, + }, // Qwen — Alibaba indigo with stylized Q. qwen: { bg: 'linear-gradient(135deg, #615ced 0%, #8b5cf6 100%)', diff --git a/src/i18n/locales/en.ts b/src/i18n/locales/en.ts index 2eb2c5fe17..1b96e83220 100644 --- a/src/i18n/locales/en.ts +++ b/src/i18n/locales/en.ts @@ -64,7 +64,7 @@ export const en: Dict = { 'settings.rescan': '↻ Rescan', 'settings.rescanTitle': 'Re-scan PATH', 'settings.noAgentsDetected': - 'No agents detected yet. Install one of Claude Code, Codex, Gemini CLI, OpenCode, Cursor Agent, or Qwen, then click Rescan.', + 'No agents detected yet. Install one of Claude Code, Codex, Gemini CLI, OpenCode, Cursor Agent, Qwen, or GitHub Copilot CLI, then click Rescan.', 'settings.apiSection': 'Anthropic API', 'settings.apiKey': 'API key', 'settings.showKey': 'Show key', diff --git a/src/i18n/locales/zh-CN.ts b/src/i18n/locales/zh-CN.ts index fc56864e39..7d0f54e6ca 100644 --- a/src/i18n/locales/zh-CN.ts +++ b/src/i18n/locales/zh-CN.ts @@ -63,7 +63,7 @@ export const zhCN: Dict = { 'settings.rescan': '↻ 重新扫描', 'settings.rescanTitle': '重新扫描 PATH', 'settings.noAgentsDetected': - '尚未检测到任何代理。请安装 Claude Code、Codex、Gemini CLI、OpenCode、Cursor Agent 或 Qwen 中的一个,然后点击「重新扫描」。', + '尚未检测到任何代理。请安装 Claude Code、Codex、Gemini CLI、OpenCode、Cursor Agent、Qwen 或 GitHub Copilot CLI 中的一个,然后点击「重新扫描」。', 'settings.apiSection': 'Anthropic API', 'settings.apiKey': 'API Key', 'settings.showKey': '显示 Key',