diff --git a/README.md b/README.md index 518d451745..153ff7cba6 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ Codeg (Code Generation) is a multi-agent coding workspace: run every AI coding agent in one place — and let them work together. -It aggregates your sessions from every supported agent CLI into one searchable workspace, and lets a main agent delegate to sub-agents of other types within a single task. Work you'd rather not sit through goes on a to-do board instead — each task in its own branch, running unattended, waiting for your review before it lands. Codeg runs as a desktop app, a standalone server, or a Docker container, with native iOS and Android clients for when you're away from your desk; fifteen agents come built in, and you can register any other ACP-compatible agent yourself. +It aggregates your sessions from every supported agent CLI into one searchable workspace, and lets a main agent delegate to sub-agents of other types within a single task. Work you'd rather not sit through goes on a to-do board instead — each task in its own branch, running unattended, waiting for your review before it lands. Codeg runs as a desktop app, a standalone server, or a Docker container, with native iOS and Android clients for when you're away from your desk; sixteen agents come built in, and you can register any other ACP-compatible agent yourself. ![workspace](./docs/images/workspace-light.png#gh-light-mode-only) ![workspace](./docs/images/workspace-dark.png#gh-dark-mode-only) @@ -90,7 +90,7 @@ It aggregates your sessions from every supported agent CLI into one searchable w ## 🤖 Supported Agents -Claude Code · Codex · Gemini · OpenClaw · OpenCode · Cline · Hermes · CodeBuddy · Kimi Code · Pi · Grok · Cursor · DeepSeek Harness · Qoder · Google Antigravity +Claude Code · Codex · Gemini · OpenClaw · OpenCode · Cline · Hermes · CodeBuddy · Kimi Code · Pi · Grok · Cursor · DeepSeek Harness · Qoder · Google Antigravity · ZCode Codeg installs, pins, and updates most of them for you. See [Supported Agents](https://docs.codeg.app/guide/supported-agents) for the full roster, each agent's runtime requirements, and where it keeps its sessions on disk. diff --git a/docs/STRATEGY-MEMO.md b/docs/STRATEGY-MEMO.md new file mode 100644 index 0000000000..c55948acbe --- /dev/null +++ b/docs/STRATEGY-MEMO.md @@ -0,0 +1,396 @@ +# Codeg 战略备忘录 + +> 内部决策记录。整理于一次深度代码评审 + 商业化讨论之后。 +> 目的:把散落在对话里的分析、判断、案例、待办沉淀下来,避免重复讨论。 +> 2026-08-16 第二次更新:性能深度扫描 + 上游 issue 需求验证(见二、三、六、九节标注)。 + +--- + +## 一、项目定位(已确认,不再动摇) + +**Codeg = 多智能体编码工作台(Multi-Agent Coding Workspace)。** + +- 服务对象:**开发者**(不是非开发者,不是垂直行业) +- 核心能力:**跨进程异构 agent 委托**(不是单进程换模型) +- 不做:**Cursor 平替、通用 agent 平台、垂直行业方案** + +### 定位边界(加宽 vs 跳船) + +| 允许 | 禁止 | +|------|------| +| 覆盖开发者的更多环节(编码/文档/审查) | 脱离开发者去做通用市场 | +| 引入更多编码 agent(Pi/GenericAgent) | 引入非编码 agent 后转去做非开发场景 | +| 加宽定位(开发者全流程) | 跳船(服务完全不同的人群) | + +--- + +## 二、技术资产评审(代码级事实) + +### 已完成且扎实的部分 + +| 模块 | 规模 | 评价 | +|------|------|------| +| `acp/delegation/` | ~1.4 万行 Rust,200+ 测试 | **核心护城河**,工程深度极高 | +| `acp/` 顶层 | ~2.5 万行(connection/manager/lifecycle 等) | ACP 协议完整实现 | +| `parsers/` | ~1.8 万行,10 个 agent | 会话聚合,覆盖广 | +| 双模式架构 | codeg / codeg-server / codeg-mcp | 部署形态齐全,`_core` 函数共用 | + +### delegation 模块的技术亮点(护城河来源) + +1. **跨进程真委托** — `delegate_to_agent` 起独立 PID,不是进程内换 prompt +2. **异步 fan-out** — 同时开多个子 agent,`get_delegation_status` 批量长轮询 +3. **取消级联** — 四种取消路径全覆盖(外部/子/父连接/父轮次) +4. **Setup 窗口竞态处理** — inflight 注册 + checkpoint + atomic park,零信任时序 +5. **深度限制** — `depth.rs` 防递归爆炸,带 cap 防脏数据 +6. **安全边界** — 一次性 token + parent scoping + UDS/piped 传输 +7. **测试覆盖** — broker 109 测试、companion 53、listener 25,覆盖全边界条件 +8. **trait 解耦** — `ConnectionSpawner` 为 v3 远程 agent 预留扩展点 + +### 当前短板(v1 限制,2026-08-16 复测) + +1. **v1 是 one-shot** — `broker.rs:2527` `disconnect` 写死,子 agent 跑完即杀。`continue_with_session`/`close_session` 仍不存在,`acp/delegation/mod.rs:29` 注释还挂着 v2 计划 +2. **巨石文件三座山** — `commands/acp.rs` 17020 行、`acp/connection.rs` 16155 行、`broker.rs` 8481 行(此前记 7554,又长了 ~930;前两个比 broker 更大,之前漏记)。broker 约 4750 行是测试,外移到 `broker_tests.rs` 是零风险减半 +3. **没有远程 agent** — 只能调度本机,v3 未实现 +4. **结果不落库(比原记轻)** — 完整文本只在 512MB 内存 FIFO 缓存(`broker.rs:79`);但有界 `text_preview` 已持久化进父会话 tool-call meta(`meta_writer.rs:281`),淘汰后 UI 仍有预览。真缺口是"全文不落库",不是"什么都不落" +5. **前端两个上帝对象** — `acp-agent-settings.tsx` 11818 行(单个设置页)、`acp-connections-context.tsx` 5606 行(~99 个 switch/case 的事件分发层) + +### 性能优化机会(2026-08-16 深度扫描,按收益排序) + +1. **侧边栏全量遍历** — `get_sidebar_data`/`list_folders`/`get_stats` 每次都走 `list_conversations_sync`(`commands/conversations.rs:342`),13 个 parser 全目录遍历,但文件夹树只需要 `folder_path`。前端已自己绕开(`skills-settings.tsx:713` 注释承认慢)。改 DB 文件夹索引 = 用户可感知的最大提升 +2. **活跃会话整文件重解析** — 摘要缓存键 `(mtime,size)`(`summary_cache.rs:64`),流式期间每次列表刷新都对整个 JSONL 逐行反序列化(`claude.rs:846`)。`transcript_watermark` 已跟踪字节位置但从未用于增量读(`claude.rs:1866` 注释自认;codex 直接返回 `None`)。基础设施都在,只差接线 +3. **patch 行号解析无缓存** — `resolve_patch_line_numbers` 每个 patch 块全量读目标文件(`parsers/mod.rs:1002`),7 个 parser 共用;同一大文件 N 个 patch = N 次全量读。一次 HashMap memo 即可 +4. **会话文件定位 O(全树)** — Codex 按 id 每次 WalkDir(`codex.rs:336`),Claude 全目录 read_dir(`claude.rs:1060`);id→path 索引变 O(1) +5. **干净的部分(不用动)** — DB 索引齐全、无 N+1、WAL 配置正确;前端虚拟化(virtua)+ RAF 批处理是真做了的;启动无阻塞扫描,感知慢在首次侧边栏(冷缓存 + 上述第 1 条) + +--- + +## 三、产品演进路线(v1 → v2 → v3) + +### v1(现状):一次性委托 + +- 子 agent 跑完第一轮 `TurnComplete` → broker `disconnect` → 杀掉 +- 父 LLM 拿到结果文本,委托结束 +- 暴露 6 个工具:`delegate_to_agent` / `get_delegation_status` / `cancel_delegation` / `check_user_feedback` / `ask_user_question` / `get_session_info` + +### v2:多轮子会话(Continue Session)— 短期 1-2 月 + +**目标**:子会话长期存活,支持多轮交互 + +**工具变化**:新增 `continue_with_session` / `close_session` + +**为什么不难**: +- ACP 协议本身支持多轮(Codeg 已实现 `session/load` / `session/resume`,主会话在用) +- 只需删除 `finalize_delegation` 末尾的 `disconnect`,改成等显式 close +- 取消级联/深度限制/inflight 注册早已为长期会话设计,现在大材小用 + +**真正难点**:状态管理(TTL、并发上限、父结束时的级联关闭、中途失败语义) + +**价值**:从"工具调用"升级为"Agent 团队",产品形态质变 + +### v3:远程 Agent(Remote Spawner)— 中期 3-6 月 + +**目标**:agent 跑在远程,broker 不变 + +**架构**:新增 `RemoteSpawner` 实现 `ConnectionSpawner` trait,broker 零改动 + +**难点不在 Codeg**(写 RemoteSpawner 不难),在基础设施: +- 远程执行环境(sandbox、API key 管理、资源隔离) +- 网络可靠性(远程超时处理) +- 安全(权限模型、审计) +- 认证(多租户隔离) +- 计费 + +**价值**:从"本地工具"升级为"云平台",商业化的钥匙 + +**需求验证(2026-08-16)**:上游 issue #461「以持久 Session 为成员的 Team / Chatroom」——社区独立提出了与功能 B/v2 同构的构想。这是 v2 值得做的最直接外部证据。 + +### v2 必须先于 v3 的理由 + +1. 远程 agent 冷启动成本高,只换一个 turn 的结果经济不成立 → 需要 v2 多轮 +2. v2 纯本地,风险低,能快速验证产品形态 + +--- + +## 四、商业化分析 + +### 市场定位的真实判断 + +**Codeg 的差异化不是"多智能体",而是"多智能体的跨进程编排"。** + +- OpenCode / Pi / DriFox 做的是"单进程多模型/多 prompt"(第一层) +- Codeg 做的是"跨进程真委托"(第二层) +- **不在一个维度上竞争** + +### 四条变现路径(垂直行业已划掉) + +| 路径 | 可行性 | 说明 | +|------|--------|------| +| 开发者工具变现(企业版/团队) | 🟢 最现实 | 开发者为效率付费,Codeg 主场 | +| 托管云 | 🟡 有需求 | 但要扛运维成本 | +| API 计费层 | 🟡 灰色 | 中国市场对接海外模型有法律风险 | +| ~~垂直行业~~ | ❌ 划掉 | 底座是编码 agent,做不了行业方案 | + +### 为什么垂直行业划掉 + +- 垂直行业(律所/金融/医疗)不会以 Claude Code/Codex 为底座 +- 这些 agent 是通用编码 agent,不具备行业专业性 +- 行业数据不能出境(合规问题) +- 没有行业知识库 + +### 最诚实的商业化判断 + +**最大风险:在"多 agent 协作"需求真正普及前,上游平台方可能下场。** +- 窗口期 12-18 个月 +- 最该做的:抢心智占有率("多智能体协作 = Codeg") + +**最该先验证的问题(未回答)**: +1. 现在有没有人重度依赖 Codeg 的 delegation? +2. 你和同事自己日常用 delegation 吗? + +> 这两个问题不回答,所有路径都是空中楼阁。先找 10 个真实用户问三个问题: +> 你用它干过什么?没有它你会怎么做?愿意付多少钱? + +--- + +## 五、案例研究 + +### CoolVibe(coolvibe.io)— 参照系 + +| 维度 | 数据 | +|------|------| +| 本质 | Agent 的网页查看器(壳子) | +| 投入 | 4 个月,~3 万美元 | +| 定价 | 免费 / Pro $29.9/年 | +| 现状 | "订阅免费送"(还在买用户阶段) | +| V2EX 热度 | 1054 条回复 | +| 公开营收 | 查不到 | +| 团队 | xterminal 团队(有成功经验) | + +**启示**: +1. "壳子"能赚钱,但前提是痛点明确且高频 +2. 定价对齐"省下的时间",不是"技术多复杂" +3. 免费送订阅是冷启动的合理策略 +4. CoolVibe 比深得多的 Codeg 先验证了"给 agent 做壳"能跑通 + +### DriFox(github.com/martin98-afk/DriFox)— 反面教材 + 经验库 + +| 维度 | 数据 | +|------|------| +| 本质 | PyQt 桌面对话助手(Cursor 平替) | +| 规模 | 15 万行 Python | +| Stars | **24**(2 个月) | +| 定位错误 | 堆 33 插件做"Cursor 平替",死路 | + +**DriFox 走的错路(Codeg 绝不能走)**: +- 自己做 agent 和 Cursor 正面打(蚂蚁 vs 太阳) +- 堆功能数量拼不过飞轮(数据/生态/资本) +- "平替"定位是诅咒(永远活在正品阴影里) + +**Cursor 的体量(参照)**: +- ARR $40 亿(2026.06 年化) +- 估值 $290-500 亿 +- 日活 100 万+ +- 融资 $23 亿 D 轮 + +### ACP 协议现状 + +- 官方 35+ 兼容 agent +- 已被 Zed / JetBrains / Google / GitHub 采纳 +- 事实标准(类似 LSP 之于语言服务器) +- **zcode 不在列表**(截至 2026-07) + +--- + +## 六、可执行的功能规划 + +### 🎯 功能 A:编程 PK(周末项目,优先级最高) + +**是什么**:同一个任务同时分发给多个 agent,看谁做得好 + +**为什么做**: +1. 成本极低(底层全有,只缺对比 UI)——周末能做完 +2. 硬核技术的最佳展示窗口(把不可见的委托变成可视化) +3. 赛道真空(DriFox 24 star 不构成威胁,异构 PK 无人做) +4. 自带传播(天然话题性 + 可视化 + 争议性) +5. 低成本的市场探测器(PK 没人理 → 大方向要重新考虑) + +**为什么 Codeg 能做、别人不能**: +- Cursor:单进程,没法真异构并行 +- DriFox:单进程,SubAgent 是换 prompt +- OpenCode/Pi:同上 +- **只有 Codeg 有跨进程 ACP 委托** + +**技术可行性(已确认)**: +- `delegate_to_agent` 已支持 fan-out ✅ +- `get_delegation_status` 已支持批量等 ✅ +- `DelegationSuccess` 已带 `duration_ms`/`token_usage`/`turn_count` ✅ +- `DelegationContext` 已流到前端 ✅ +- **只缺一层横向对比 UI** + +**实施档位**: + +| 档位 | 内容 | 工作量 | +|------|------|--------| +| A 最小可玩 | PK 触发器 + 分屏视图 + 计分板 | 周六一天 | +| B 好看+分享 | diff 对比 + 实时终端 + 分享截图 + 任务模板 | +周日上午 | +| C 评判 | 自动测试裁判 + LLM 裁判 | 周日下午(选做) | + +**关键代码位置**: +- 触发器:`src/components/composer/`(加 PK 模式开关) +- 对比组件:新建 `src/components/chat/agent-pk-arena.tsx` +- 数据复用:`src/hooks/use-delegation-card-model.ts`(已解出 agent/task/status/childId) +- 渲染复用:`src/components/message/sub-agent-session-dialog.tsx`(已会渲染单个子 agent) +- 分享截图:`html-to-image`(package.json 已有依赖) + +**传播策略**: +- V2EX 发帖,标题方向:"周末做了个 AI 编程 PK 场:让 Claude Code、Codex、Gemini 同时写贪吃蛇,看谁快" +- 每场 PK 都是一次传播机会 + +**需求验证(2026-08-16)**:上游 issue #428「缺乏派发 subagent 状态的监视」——用户独立要 delegation 可视化监控,与 PK 共用数据层(`use-delegation-card-model.ts`),做完 PK 顺手就有,算免费赠品。 + +### 🎯 功能 B:角色化 Agent 团队(PK 之后的第二张牌) + +**是什么**:预设 leader/build/review 等角色,一键发起"Claude 当 leader 分任务给 Codex(build)和 Gemini(review)" + +**为什么做**: +- 比 PK 更接近"真实有用的工作"(协作 > 竞技) +- 和 PK 共用同一套 delegation 底层,只换 prompt 和 UI +- 让 Codeg 从"对比工具"延伸为"团队编排平台" + +**来源**:DriFox 的 `plugins/system/agents/*.md`(角色 prompt 设计精良,可借鉴) + +**与 v2 的关系**:角色化团队天然需要多轮子会话(v2),但可以先做 one-shot 版本 + +--- + +## 七、从 DriFox 可借鉴的具体设计 + +### 值得偷(按价值排序) + +#### 1. 角色化 agent prompt 模板 +- 来源:`plugins/system/agents/{build,leader,review,explore,plan}.md` +- 用途:Codeg 的角色化团队功能 +- 关键原则(直接抄): + - "不做超出需求的功能。一次性代码不做抽象。" + - "不要顺手改进相邻代码。不要重构没坏的东西。" + - "每一行变更都应该能直接追溯到用户的请求。" + - "使用 question 工具提问,优先提供选项" + +#### 2. 工具安全分类(三分法) +- 来源:`app/tools/command_safety.py` + `app/tools/tool_classifier.py` +- 用途:Codeg 加一层自己的安全护栏(企业版刚需) +- 规则: + - 危险(write/edit/bash/mouse)→ 审批 + - 安全(read/grep/glob/webfetch)→ 放行 + - 命令三分法:无元字符直接跑 / 有管道重定向需确认 / 黑名单拒绝 + +#### 3. "关键文档"记忆机制 +- 来源:`app/core/memory_manager.py` 的 `KeyDocumentsRepository` +- 用途:解决子 agent 冷启动不懂项目上下文的痛点 +- 做法:用户标记项目重要文件(README/架构文档/API 约定),委托时自动注入 task prompt + +#### 4. 任务邮件分发(轻量跨窗口协作) +- 来源:`app/core/team_manager.py`(文件邮箱) +- 用途:v3 远程 agent 的备选轻量方案 +- 优先级:低(记住有这个方案) + +#### 5. AGENTS.md 作为项目笔记 +- DriFox 印证了这是事实标准,Codeg 已在用,继续走 + +### 明确不要偷 + +| 不偷 | 理由 | +|------|------| +| PyQt 桌面浮动窗 | 架构不同,非核心价值 | +| 33 个插件 | 功能堆砌是它 24 star 的原因 | +| 进程内 SubAgent DAG | Codeg 跨进程委托更强 | +| ECharts 力导向图 | PK 用并排对比更直观 | +| LSP 集成(11 种语言) | Cursor 的战场,别送 | + +--- + +## 八、关于接入 zcode 的结论 + +**结论:暂不接入。** + +理由: +- zcode 不开源,改不了,只能向 Z.ai 提需求 +- zcode 不支持 ACP(不在官方 35+ 兼容列表) +- 不支持 ACP → 只能做 L1(会话导入 parser),不能做 L2(完整调度) +- L1 单独价值低(装饰性,用户在 zcode 自己的 app 里已能看会话) +- zcode 加 ACP 是 Z.ai 的战略决策,Codeg 这边无法推动 + +**zcode 数据格式(已摸清,备用)**: +- `~/.zcode/cli/db/db.sqlite` — 主库(session/message/part/todo 表) +- `~/.zcode/v2/tasks-index.sqlite` — 任务索引 +- `~/.zcode/cli/rollout/*.jsonl` — 原始模型 IO 流 +- `~/.zcode/cli/agents/sess_*/agent_*/` — 子 agent 会话 + +如果未来 zcode 支持 ACP,接入成本分两档(2026-08-16 修正,依据:上游 DSH 集成案例): + +**L1(会话导入,半天,4 处)**: +1. `models/agent.rs` — `AgentType` 枚举 +2. `acp/registry.rs` — `AcpAgentMeta` +3. `parsers/mod.rs` — 注册 +4. `parsers/zcode.rs` — 会话导入(可选) + +**L2(完整内置 agent,六层 ~25 处,量级 3-5 天)**: +完整参考:上游提交 `3845e9df`「feat(deepseek): integrate DeepSeek Harness as a built-in agent」,+3271/−50 行,改动约 25 个文件。六层清单: + +| 层 | 改动点 | 示例(DSH 提交) | +|----|--------|----------------| +| 1. 身份层 | `AgentType` 枚举 + wire 名 + 防自定义 shadow | `models/agent.rs`(+12) | +| 2. 启动层 | 注册表元数据:npm 包/版本/node 要求/认证方式 | `acp/registry.rs`(+44) | +| 3. 历史层 | 原生会话解析器(会话进列表/统计/导入,工作量最大) | `parsers/deepseek.rs`(+1291) | +| 4. 运行时层 | 沙箱根目录 / env 键 / skills 存储 / 只读路径 | `file_system_runtime.rs`、`commands/acp.rs`(+237) | +| 5. 协议层 | ACP capabilities / MCP 接线 / 传输限制 | `connection.rs`、`commands/mcp.rs`(+398) | +| 6. 防御层 | 自定义注册表冲突校验 + 文档 | `custom_registry.rs`(+52) | + +> **教训**:曾以为"加一个 agent = 改 4 处",实际"内置 agent"是六层全通——只做 1/2 层的 PR 会被上游以"不够一等公民"拒绝(2026-08-16 DSH PR 实测)。以后评估任何"接新 agent"的工作量,按此清单逐层核对。 + +--- + +## 九、关键待办与未决问题 + +### 必须先回答的问题(阻塞所有商业化决策) + +- [ ] **现在有没有人重度依赖 Codeg 的 delegation?**(找 10 个真实用户) +- [ ] **你和同事自己日常用 delegation 吗?**(如果造的人都不用,别指望别人用) + +### 功能待办(按优先级) + +- [ ] **编程 PK**(周末项目) — 最低成本验证 + 传播 +- [ ] **角色化 Agent 团队**(PK 之后) — 第二个场景 +- [ ] **v2 多轮子会话** — 产品形态质变,1-2 月 +- [ ] **v3 远程 agent** — 商业化钥匙,3-6 月 + +### 工程待办(2026-08-16 新增,按收益排序) + +- [ ] **侧边栏 DB 文件夹索引** — 干掉 13-parser 全量遍历(性能机会 1) +- [ ] **增量会话解析** — 接通已有但闲置的 `transcript_watermark`(性能机会 2) +- [ ] **broker.rs 测试外移** — ~4750 行拆到 `broker_tests.rs`,零风险减半 +- [ ] **patch 行号解析加 memo** — 一次 HashMap 的事(性能机会 3) + +### 上游影响力机会(刷存在感,非主线) + +- [ ] **#391/#387 流式重复文本** — 维护者自己未定位根因(在等用户补 seq 数据);修了就是硬通货 +- [ ] **#396 preferred-config 过滤** — 0xlinn 已给出精确根因:通用路径不按 advertised options 过滤,867 次/23天的重复报错;修法是照抄 grok 路径已有守卫(`connection.rs:1947`)+ `mode` 白名单 +- [x] **#408 接入 qoder cli**(2026-08-17 已完成,待提 PR)— 六层全通:身份/注册表(`qoder-cli`,npx `@qoder-ai/qodercli@1.1.23`,`--acp`)/解析器(Claude 信封格式,`~/.qoder/projects//.jsonl`,state.json 标题加密故走 transcript 明文)/沙箱(`QODER_CONFIG_DIR` RootSlot,实测 `~/.qoder` 可写)/协议(原生 ACP,loadSession+list/resume/fork 全有,MCP 走 settings.json 合并写入+转发跳过)/防御(`qoder-cli` 冲突校验)。规避了既往坑:#396 serde 重命名(测试钉死)、过期 env 误报(important keys 置空)、#468 标题问题(明文派生)。活体验证:server 模式 spawn→握手→prompt→turn_complete→transcript 解析全通。qoder 会话历史与 DSH 等宽(比 DSH 便宜在原生 ACP,贵在 MCP 转发语义相反:qoder 读自己的 settings.json,进跳过名单) + +### 不做清单(防止分心) + +- [x] ~~接入 zcode~~(暂缓,等 ACP) +- [x] ~~垂直行业方案~~(底座不匹配) +- [x] ~~做 Cursor 平替~~(蚂蚁 vs 太阳) +- [x] ~~堆功能数量~~(学 DriFox 的教训) +- [x] ~~脱离开发者市场~~(丢弃所有资产) + +--- + +## 十、一句话总结 + +> **Codeg 的硬核技术(跨进程异构委托)是真的,但"硬核"本身不产生收入,产生收入的是"有一群人离不开它"。** +> +> **当下的优先级:先用最低成本(PK)验证"多 agent 并行"对开发者有没有吸引力 → 如果有,做 v2/v3 深化 → 如果没有,重新评估方向。** +> +> **别再纠结"能不能打过 Cursor"——那不是 Codeg 该问的问题。该问的是:Cursor 用户有什么事想做但 Cursor 架构上做不到?** diff --git a/docs/readme/README.ar.md b/docs/readme/README.ar.md index 853353c810..d81cbf6a2c 100644 --- a/docs/readme/README.ar.md +++ b/docs/readme/README.ar.md @@ -19,7 +19,7 @@ Codeg (Code Generation) هو مساحة عمل برمجية متعددة الوكلاء: شغّل كل وكلاء البرمجة بالذكاء الاصطناعي في مكان واحد — ودعهم يعملون معًا. -يجمع جلساتك من كل واجهات الوكلاء المدعومة في مساحة عمل واحدة قابلة للبحث، ويتيح للوكيل الرئيسي أن يفوّض إلى وكلاء فرعيين من أنواع أخرى داخل المهمة نفسها. أما العمل الذي لا تريد الجلوس لمتابعته فيذهب إلى لوحة المهام قيد الانتظار: كل مهمة في فرعها الخاص، تعمل دون إشراف، وتنتظر مراجعتك قبل أن تُدمج. ويعمل Codeg كتطبيق سطح مكتب أو خادم مستقل أو حاوية Docker، إضافةً إلى تطبيقَي iOS وAndroid الأصليين لمواصلة العمل بعيدًا عن مكتبك؛ يأتي بخمسة عشر وكيلاً مدمجًا، ويمكنك تسجيل أي وكيل آخر متوافق مع ACP بنفسك. +يجمع جلساتك من كل واجهات الوكلاء المدعومة في مساحة عمل واحدة قابلة للبحث، ويتيح للوكيل الرئيسي أن يفوّض إلى وكلاء فرعيين من أنواع أخرى داخل المهمة نفسها. أما العمل الذي لا تريد الجلوس لمتابعته فيذهب إلى لوحة المهام قيد الانتظار: كل مهمة في فرعها الخاص، تعمل دون إشراف، وتنتظر مراجعتك قبل أن تُدمج. ويعمل Codeg كتطبيق سطح مكتب أو خادم مستقل أو حاوية Docker، إضافةً إلى تطبيقَي iOS وAndroid الأصليين لمواصلة العمل بعيدًا عن مكتبك؛ يأتي بستة عشر وكيلاً مدمجًا، ويمكنك تسجيل أي وكيل آخر متوافق مع ACP بنفسك. ![مساحة العمل](../images/workspace-light.png#gh-light-mode-only) ![مساحة العمل](../images/workspace-dark.png#gh-dark-mode-only) @@ -90,7 +90,7 @@ Codeg (Code Generation) هو مساحة عمل برمجية متعددة الو ## 🤖 الوكلاء المدعومون -Claude Code · Codex · Gemini · OpenClaw · OpenCode · Cline · Hermes · CodeBuddy · Kimi Code · Pi · Grok · Cursor · DeepSeek Harness · Qoder · Google Antigravity +Claude Code · Codex · Gemini · OpenClaw · OpenCode · Cline · Hermes · CodeBuddy · Kimi Code · Pi · Grok · Cursor · DeepSeek Harness · Qoder · Google Antigravity · ZCode يتولّى Codeg تثبيت معظمهم وتثبيت إصداراتهم وتحديثهم نيابةً عنك. راجع [الوكلاء المدعومون](https://docs.codeg.app/guide/supported-agents) للقائمة الكاملة، ومتطلبات تشغيل كل وكيل، وموضع حفظ جلساته على القرص. diff --git a/docs/readme/README.de.md b/docs/readme/README.de.md index 4ea85f64cf..576306d224 100644 --- a/docs/readme/README.de.md +++ b/docs/readme/README.de.md @@ -19,7 +19,7 @@ Codeg (Code Generation) ist ein Multi-Agent-Coding-Workspace: Führe jeden KI-Coding-Agenten an einem Ort aus — und lass sie zusammenarbeiten. -Codeg bündelt die Sitzungen aller unterstützten Agenten-CLIs in einem durchsuchbaren Workspace und lässt einen Haupt-Agenten innerhalb einer Aufgabe an Sub-Agenten anderer Typen delegieren. Arbeit, bei der du nicht danebensitzen willst, kommt stattdessen aufs To-do-Board — jede Aufgabe in ihrem eigenen Branch, unbeaufsichtigt laufend und wartend auf deine Freigabe, bevor sie landet. Codeg läuft als Desktop-App, eigenständiger Server oder Docker-Container, dazu native iOS- und Android-Clients für die Zeit fernab vom Schreibtisch; fünfzehn Agenten sind eingebaut, und jeden weiteren ACP-kompatiblen Agenten kannst du selbst registrieren. +Codeg bündelt die Sitzungen aller unterstützten Agenten-CLIs in einem durchsuchbaren Workspace und lässt einen Haupt-Agenten innerhalb einer Aufgabe an Sub-Agenten anderer Typen delegieren. Arbeit, bei der du nicht danebensitzen willst, kommt stattdessen aufs To-do-Board — jede Aufgabe in ihrem eigenen Branch, unbeaufsichtigt laufend und wartend auf deine Freigabe, bevor sie landet. Codeg läuft als Desktop-App, eigenständiger Server oder Docker-Container, dazu native iOS- und Android-Clients für die Zeit fernab vom Schreibtisch; sechzehn Agenten sind eingebaut, und jeden weiteren ACP-kompatiblen Agenten kannst du selbst registrieren. ![Workspace](../images/workspace-light.png#gh-light-mode-only) ![Workspace](../images/workspace-dark.png#gh-dark-mode-only) @@ -90,7 +90,7 @@ Codeg bündelt die Sitzungen aller unterstützten Agenten-CLIs in einem durchsuc ## 🤖 Unterstützte Agenten -Claude Code · Codex · Gemini · OpenClaw · OpenCode · Cline · Hermes · CodeBuddy · Kimi Code · Pi · Grok · Cursor · DeepSeek Harness · Qoder · Google Antigravity +Claude Code · Codex · Gemini · OpenClaw · OpenCode · Cline · Hermes · CodeBuddy · Kimi Code · Pi · Grok · Cursor · DeepSeek Harness · Qoder · Google Antigravity · ZCode Die meisten davon installiert, fixiert und aktualisiert Codeg für dich. Die vollständige Liste, die Laufzeit-Anforderungen jedes Agenten und den Ablageort seiner Sitzungen findest du unter [Unterstützte Agenten](https://docs.codeg.app/guide/supported-agents). diff --git a/docs/readme/README.es.md b/docs/readme/README.es.md index aa020efdee..7597809156 100644 --- a/docs/readme/README.es.md +++ b/docs/readme/README.es.md @@ -19,7 +19,7 @@ Codeg (Code Generation) es un espacio de trabajo de programación multiagente: ejecuta todos tus agentes de IA en un mismo lugar y deja que trabajen juntos. -Reúne las sesiones de todas las CLI de agentes compatibles en un único espacio de trabajo con búsqueda y permite que un agente principal delegue en subagentes de otros tipos dentro de una misma tarea. El trabajo que prefieres no vigilar va al tablero de tareas pendientes: cada tarea en su propia rama, ejecutándose sin supervisión, esperando tu revisión antes de aterrizar. Codeg funciona como aplicación de escritorio, servidor independiente o contenedor Docker, con clientes nativos de iOS y Android para cuando estás lejos del escritorio; trae quince agentes integrados y puedes registrar tú mismo cualquier otro agente compatible con ACP. +Reúne las sesiones de todas las CLI de agentes compatibles en un único espacio de trabajo con búsqueda y permite que un agente principal delegue en subagentes de otros tipos dentro de una misma tarea. El trabajo que prefieres no vigilar va al tablero de tareas pendientes: cada tarea en su propia rama, ejecutándose sin supervisión, esperando tu revisión antes de aterrizar. Codeg funciona como aplicación de escritorio, servidor independiente o contenedor Docker, con clientes nativos de iOS y Android para cuando estás lejos del escritorio; trae dieciséis agentes integrados y puedes registrar tú mismo cualquier otro agente compatible con ACP. ![Espacio de trabajo](../images/workspace-light.png#gh-light-mode-only) ![Espacio de trabajo](../images/workspace-dark.png#gh-dark-mode-only) @@ -90,7 +90,7 @@ Reúne las sesiones de todas las CLI de agentes compatibles en un único espacio ## 🤖 Agentes compatibles -Claude Code · Codex · Gemini · OpenClaw · OpenCode · Cline · Hermes · CodeBuddy · Kimi Code · Pi · Grok · Cursor · DeepSeek Harness · Qoder · Google Antigravity +Claude Code · Codex · Gemini · OpenClaw · OpenCode · Cline · Hermes · CodeBuddy · Kimi Code · Pi · Grok · Cursor · DeepSeek Harness · Qoder · Google Antigravity · ZCode Codeg instala, fija la versión y actualiza la mayoría de ellos por ti. Consulta [Agentes compatibles](https://docs.codeg.app/guide/supported-agents) para ver la lista completa, los requisitos de ejecución de cada uno y dónde guarda sus sesiones en disco. diff --git a/docs/readme/README.fr.md b/docs/readme/README.fr.md index a5665517ef..89040cb425 100644 --- a/docs/readme/README.fr.md +++ b/docs/readme/README.fr.md @@ -19,7 +19,7 @@ Codeg (Code Generation) est un espace de travail de programmation multi-agents : faites tourner tous vos agents de codage IA au même endroit — et laissez-les travailler ensemble. -Il regroupe les sessions de toutes les CLI d'agents supportées dans un espace de travail unique et consultable, et permet à un agent principal de déléguer à des sous-agents d'autres types au sein d'une même tâche. Le travail que vous préférez ne pas surveiller part sur un tableau de tâches à faire : chaque tâche sur sa propre branche, exécutée sans surveillance, en attente de votre relecture avant d'atterrir. Codeg fonctionne en application de bureau, en serveur autonome ou en conteneur Docker, avec des clients natifs iOS et Android pour les moments où vous n'êtes pas à votre bureau ; quinze agents sont intégrés, et vous pouvez enregistrer vous-même n'importe quel autre agent compatible ACP. +Il regroupe les sessions de toutes les CLI d'agents supportées dans un espace de travail unique et consultable, et permet à un agent principal de déléguer à des sous-agents d'autres types au sein d'une même tâche. Le travail que vous préférez ne pas surveiller part sur un tableau de tâches à faire : chaque tâche sur sa propre branche, exécutée sans surveillance, en attente de votre relecture avant d'atterrir. Codeg fonctionne en application de bureau, en serveur autonome ou en conteneur Docker, avec des clients natifs iOS et Android pour les moments où vous n'êtes pas à votre bureau ; seize agents sont intégrés, et vous pouvez enregistrer vous-même n'importe quel autre agent compatible ACP. ![Espace de travail](../images/workspace-light.png#gh-light-mode-only) ![Espace de travail](../images/workspace-dark.png#gh-dark-mode-only) @@ -90,7 +90,7 @@ Il regroupe les sessions de toutes les CLI d'agents supportées dans un espace d ## 🤖 Agents supportés -Claude Code · Codex · Gemini · OpenClaw · OpenCode · Cline · Hermes · CodeBuddy · Kimi Code · Pi · Grok · Cursor · DeepSeek Harness · Qoder · Google Antigravity +Claude Code · Codex · Gemini · OpenClaw · OpenCode · Cline · Hermes · CodeBuddy · Kimi Code · Pi · Grok · Cursor · DeepSeek Harness · Qoder · Google Antigravity · ZCode Codeg installe, épingle et met à jour la plupart d'entre eux pour vous. Voir [Agents supportés](https://docs.codeg.app/guide/supported-agents) pour la liste complète, les prérequis d'exécution de chacun et l'emplacement de ses sessions sur le disque. diff --git a/docs/readme/README.ja.md b/docs/readme/README.ja.md index f46e23d4dd..7e7a6c5a47 100644 --- a/docs/readme/README.ja.md +++ b/docs/readme/README.ja.md @@ -19,7 +19,7 @@ Codeg(Code Generation)はマルチエージェント・コーディングワークスペースです。あらゆる AI コーディングエージェントをひとつの場所で動かし、そして協働させます。 -対応するすべてのエージェント CLI のセッションを検索可能なワークスペースへ集約し、ひとつのタスクの中でメインエージェントが別種類のサブエージェントへ委譲できます。付きっきりで見ていたくない作業は ToDo タスクに書いておけば、それぞれが専用のブランチで無人のまま進み、あなたのレビューを待ってから取り込まれます。Codeg はデスクトップアプリ・スタンドアロンサーバー・Docker コンテナのいずれとしても動作し、ネイティブの iOS / Android クライアントもあるのでデスクを離れても作業を続けられます。エージェントは 15 種を内蔵し、ACP 互換の任意のエージェントを自分で登録することもできます。 +対応するすべてのエージェント CLI のセッションを検索可能なワークスペースへ集約し、ひとつのタスクの中でメインエージェントが別種類のサブエージェントへ委譲できます。付きっきりで見ていたくない作業は ToDo タスクに書いておけば、それぞれが専用のブランチで無人のまま進み、あなたのレビューを待ってから取り込まれます。Codeg はデスクトップアプリ・スタンドアロンサーバー・Docker コンテナのいずれとしても動作し、ネイティブの iOS / Android クライアントもあるのでデスクを離れても作業を続けられます。エージェントは 16 種を内蔵し、ACP 互換の任意のエージェントを自分で登録することもできます。 ![ワークスペース](../images/workspace-light.png#gh-light-mode-only) ![ワークスペース](../images/workspace-dark.png#gh-dark-mode-only) @@ -90,7 +90,7 @@ Codeg(Code Generation)はマルチエージェント・コーディングワ ## 🤖 対応エージェント -Claude Code · Codex · Gemini · OpenClaw · OpenCode · Cline · Hermes · CodeBuddy · Kimi Code · Pi · Grok · Cursor · DeepSeek Harness · Qoder · Google Antigravity +Claude Code · Codex · Gemini · OpenClaw · OpenCode · Cline · Hermes · CodeBuddy · Kimi Code · Pi · Grok · Cursor · DeepSeek Harness · Qoder · Google Antigravity · ZCode その多くは Codeg がインストール・バージョン固定・更新まで面倒を見ます。全リスト、各エージェントの実行環境要件、セッションの保存場所は [対応エージェント](https://docs.codeg.app/guide/supported-agents) を参照してください。 diff --git a/docs/readme/README.ko.md b/docs/readme/README.ko.md index de3b8542b4..099b982455 100644 --- a/docs/readme/README.ko.md +++ b/docs/readme/README.ko.md @@ -19,7 +19,7 @@ Codeg(Code Generation)는 멀티 에이전트 코딩 워크스페이스입니다. 모든 AI 코딩 에이전트를 한곳에서 실행하고, 서로 협업하게 만듭니다. -지원되는 모든 에이전트 CLI의 세션을 검색 가능한 하나의 워크스페이스로 모으고, 하나의 작업 안에서 메인 에이전트가 다른 종류의 서브 에이전트에게 위임할 수 있습니다. 지켜보고 앉아 있기 아까운 일은 할 일 보드에 적어 두세요. 각 작업이 자기 브랜치에서 무인으로 돌아가고, 반영되기 전에 당신의 검토를 기다립니다. Codeg는 데스크톱 앱·독립 서버·Docker 컨테이너 어느 형태로든 실행되고, 네이티브 iOS·Android 클라이언트가 있어 자리를 비운 사이에도 작업을 이어갈 수 있습니다. 열다섯 개의 에이전트가 기본 내장되며, ACP를 지원하는 다른 에이전트를 직접 등록할 수도 있습니다. +지원되는 모든 에이전트 CLI의 세션을 검색 가능한 하나의 워크스페이스로 모으고, 하나의 작업 안에서 메인 에이전트가 다른 종류의 서브 에이전트에게 위임할 수 있습니다. 지켜보고 앉아 있기 아까운 일은 할 일 보드에 적어 두세요. 각 작업이 자기 브랜치에서 무인으로 돌아가고, 반영되기 전에 당신의 검토를 기다립니다. Codeg는 데스크톱 앱·독립 서버·Docker 컨테이너 어느 형태로든 실행되고, 네이티브 iOS·Android 클라이언트가 있어 자리를 비운 사이에도 작업을 이어갈 수 있습니다. 열여섯 개의 에이전트가 기본 내장되며, ACP를 지원하는 다른 에이전트를 직접 등록할 수도 있습니다. ![워크스페이스](../images/workspace-light.png#gh-light-mode-only) ![워크스페이스](../images/workspace-dark.png#gh-dark-mode-only) @@ -90,7 +90,7 @@ Codeg(Code Generation)는 멀티 에이전트 코딩 워크스페이스입니다 ## 🤖 지원 에이전트 -Claude Code · Codex · Gemini · OpenClaw · OpenCode · Cline · Hermes · CodeBuddy · Kimi Code · Pi · Grok · Cursor · DeepSeek Harness · Qoder · Google Antigravity +Claude Code · Codex · Gemini · OpenClaw · OpenCode · Cline · Hermes · CodeBuddy · Kimi Code · Pi · Grok · Cursor · DeepSeek Harness · Qoder · Google Antigravity · ZCode 이 중 대부분은 Codeg가 대신 설치하고, 버전을 고정하고, 업데이트합니다. 전체 목록과 각 에이전트의 실행 환경 요구 사항, 세션이 디스크에 저장되는 위치는 [지원 에이전트](https://docs.codeg.app/guide/supported-agents)를 참고하세요. diff --git a/docs/readme/README.pt.md b/docs/readme/README.pt.md index 0e4830cdc5..01185b78aa 100644 --- a/docs/readme/README.pt.md +++ b/docs/readme/README.pt.md @@ -19,7 +19,7 @@ O Codeg (Code Generation) é um espaço de trabalho de programação multiagente: rode todos os seus agentes de IA em um só lugar — e deixe que trabalhem juntos. -Ele agrega as sessões de todas as CLIs de agentes suportadas em um único espaço de trabalho pesquisável e permite que um agente principal delegue a subagentes de outros tipos dentro de uma mesma tarefa. O trabalho que você prefere não acompanhar vai para o quadro de tarefas a fazer: cada tarefa no próprio branch, rodando sem supervisão, esperando a sua revisão antes de entrar. O Codeg roda como aplicativo de desktop, servidor independente ou contêiner Docker, com clientes nativos de iOS e Android para quando você está longe da mesa; quinze agentes já vêm integrados e você pode registrar por conta própria qualquer outro agente compatível com ACP. +Ele agrega as sessões de todas as CLIs de agentes suportadas em um único espaço de trabalho pesquisável e permite que um agente principal delegue a subagentes de outros tipos dentro de uma mesma tarefa. O trabalho que você prefere não acompanhar vai para o quadro de tarefas a fazer: cada tarefa no próprio branch, rodando sem supervisão, esperando a sua revisão antes de entrar. O Codeg roda como aplicativo de desktop, servidor independente ou contêiner Docker, com clientes nativos de iOS e Android para quando você está longe da mesa; dezesseis agentes já vêm integrados e você pode registrar por conta própria qualquer outro agente compatível com ACP. ![Espaço de trabalho](../images/workspace-light.png#gh-light-mode-only) ![Espaço de trabalho](../images/workspace-dark.png#gh-dark-mode-only) @@ -90,7 +90,7 @@ Ele agrega as sessões de todas as CLIs de agentes suportadas em um único espa ## 🤖 Agentes suportados -Claude Code · Codex · Gemini · OpenClaw · OpenCode · Cline · Hermes · CodeBuddy · Kimi Code · Pi · Grok · Cursor · DeepSeek Harness · Qoder · Google Antigravity +Claude Code · Codex · Gemini · OpenClaw · OpenCode · Cline · Hermes · CodeBuddy · Kimi Code · Pi · Grok · Cursor · DeepSeek Harness · Qoder · Google Antigravity · ZCode O Codeg instala, fixa a versão e atualiza a maioria deles por você. Veja [Agentes suportados](https://docs.codeg.app/guide/supported-agents) para a lista completa, os requisitos de execução de cada um e onde ele guarda as sessões em disco. diff --git a/docs/readme/README.zh-CN.md b/docs/readme/README.zh-CN.md index 8d163c8a1b..3b2f53aacd 100644 --- a/docs/readme/README.zh-CN.md +++ b/docs/readme/README.zh-CN.md @@ -19,7 +19,7 @@ Codeg(Code Generation)是一个多智能体编码工作台:把所有 AI 编码智能体收进同一个地方 —— 并让它们协同工作。 -它将所有受支持智能体 CLI 的会话聚合进一个可搜索的工作区,让主智能体在同一个任务内委派给其它类型的子智能体。不想守着做完的活,可以写进待办任务:每个任务待在自己的分支上无人值守地跑,做完了等你验收才落地。Codeg 可作为桌面应用、独立服务器或 Docker 容器运行,还有原生 iOS 与 Android 客户端,让你离开电脑后也能接手正在跑的任务;内置十五个智能体,你也可以自行注册任何其它兼容 ACP 的智能体。 +它将所有受支持智能体 CLI 的会话聚合进一个可搜索的工作区,让主智能体在同一个任务内委派给其它类型的子智能体。不想守着做完的活,可以写进待办任务:每个任务待在自己的分支上无人值守地跑,做完了等你验收才落地。Codeg 可作为桌面应用、独立服务器或 Docker 容器运行,还有原生 iOS 与 Android 客户端,让你离开电脑后也能接手正在跑的任务;内置十六个智能体,你也可以自行注册任何其它兼容 ACP 的智能体。 ![工作区](../images/workspace-light.png#gh-light-mode-only) ![工作区](../images/workspace-dark.png#gh-dark-mode-only) @@ -90,7 +90,7 @@ Codeg(Code Generation)是一个多智能体编码工作台:把所有 AI ## 🤖 支持的 Agent -Claude Code · Codex · Gemini · OpenClaw · OpenCode · Cline · Hermes · CodeBuddy · Kimi Code · Pi · Grok · Cursor · DeepSeek Harness · Qoder · Google Antigravity +Claude Code · Codex · Gemini · OpenClaw · OpenCode · Cline · Hermes · CodeBuddy · Kimi Code · Pi · Grok · Cursor · DeepSeek Harness · Qoder · Google Antigravity · ZCode 其中大部分 Codeg 都能替你安装、锁定版本并更新。完整名单、各自的运行环境要求以及会话在磁盘上的存放位置,见 [支持的智能体](https://docs.codeg.app/zh/guide/supported-agents)。 diff --git a/docs/readme/README.zh-TW.md b/docs/readme/README.zh-TW.md index 3b37bfffcf..3af588989f 100644 --- a/docs/readme/README.zh-TW.md +++ b/docs/readme/README.zh-TW.md @@ -19,7 +19,7 @@ Codeg(Code Generation)是一個多智慧體編碼工作台:把所有 AI 編碼智慧體收進同一個地方 —— 並讓它們協同工作。 -它將所有支援的智慧體 CLI 的工作階段聚合進一個可搜尋的工作區,讓主智慧體在同一個任務內委派給其它類型的子智慧體。不想守著做完的活,可以寫進待辦任務:每個任務待在自己的分支上無人看管地跑,做完了等你驗收才落地。Codeg 可作為桌面應用、獨立伺服器或 Docker 容器執行,還有原生 iOS 與 Android 用戶端,讓你離開電腦後也能接手正在跑的任務;內建十五個智慧體,你也可以自行註冊任何其它相容 ACP 的智慧體。 +它將所有支援的智慧體 CLI 的工作階段聚合進一個可搜尋的工作區,讓主智慧體在同一個任務內委派給其它類型的子智慧體。不想守著做完的活,可以寫進待辦任務:每個任務待在自己的分支上無人看管地跑,做完了等你驗收才落地。Codeg 可作為桌面應用、獨立伺服器或 Docker 容器執行,還有原生 iOS 與 Android 用戶端,讓你離開電腦後也能接手正在跑的任務;內建十六個智慧體,你也可以自行註冊任何其它相容 ACP 的智慧體。 ![工作區](../images/workspace-light.png#gh-light-mode-only) ![工作區](../images/workspace-dark.png#gh-dark-mode-only) @@ -90,7 +90,7 @@ Codeg(Code Generation)是一個多智慧體編碼工作台:把所有 AI ## 🤖 支援的 Agent -Claude Code · Codex · Gemini · OpenClaw · OpenCode · Cline · Hermes · CodeBuddy · Kimi Code · Pi · Grok · Cursor · DeepSeek Harness · Qoder · Google Antigravity +Claude Code · Codex · Gemini · OpenClaw · OpenCode · Cline · Hermes · CodeBuddy · Kimi Code · Pi · Grok · Cursor · DeepSeek Harness · Qoder · Google Antigravity · ZCode 其中大部分 Codeg 都能替你安裝、鎖定版本並更新。完整名單、各自的執行環境需求以及工作階段在磁碟上的存放位置,見 [支援的智慧體](https://docs.codeg.app/zh/guide/supported-agents)。 diff --git a/src-tauri/src/acp/connection.rs b/src-tauri/src/acp/connection.rs index 0c2fc506cd..619e4e78cd 100644 --- a/src-tauri/src/acp/connection.rs +++ b/src-tauri/src/acp/connection.rs @@ -1423,13 +1423,18 @@ fn pi_launch_preflight(runtime_env: &BTreeMap) -> Option /// Transcript directory for an agent that codeg must record itself, or `None` /// for agents with their own store parser. /// -/// Only custom ACP agents are recorded: every built-in has a dedicated parser -/// reading the agent's native transcript, and recording those too would double -/// the storage while risking two disagreeing histories. +/// Custom ACP agents are recorded because they have no native store to parse. +/// ZCode is the exception among built-ins: its adapter keeps history in ZCode's +/// private (undocumented) store, which codeg deliberately does not read, so the +/// built-in records its own ACP transcript through the same path. Every other +/// built-in has a dedicated parser reading the agent's native transcript, and +/// recording those too would double the storage while risking two disagreeing +/// histories. fn transcript_dir_for(agent_type: AgentType) -> Option<&'static str> { - agent_type - .custom_id() - .map(|_| registry::registry_id_for(agent_type)) + match agent_type { + AgentType::Custom(_) | AgentType::ZCode => Some(registry::registry_id_for(agent_type)), + _ => None, + } } /// Ensure a custom agent's transcript file exists with its header. No-op for @@ -1737,6 +1742,77 @@ fn agent_debug_callback( } } +/// Standard install locations of the ZCode CLI `.cjs` entry, probed when the +/// settings env does not carry an explicit `ZCODE_CODEG_ENTRY`. The adapter +/// refuses to guess this itself ("this binary never searches for it"), so the +/// host must. +fn zcode_entry_candidates(home: Option<&Path>) -> Vec { + let mut candidates = Vec::new(); + if cfg!(target_os = "macos") { + candidates.push(PathBuf::from( + "/Applications/ZCode.app/Contents/Resources/glm/zcode.cjs", + )); + } + // Per-user app installs live under ~/Applications on every platform's + // bundle convention; harmless to probe where no such layout exists. + if let Some(home) = home { + candidates.push(home.join("Applications/ZCode.app/Contents/Resources/glm/zcode.cjs")); + } + candidates +} + +/// Ensure `ZCODE_CODEG_ENTRY` names a readable ZCode CLI entry, or fail the +/// launch with an install-prompt-routable message instead of letting the +/// adapter exit `E_ENTRY` mid-handshake. +/// +/// An explicit value from Agent Settings → ZCode always wins (and is validated +/// — a stale absolute path must not silently fall back to a probe hit). Only +/// when it is absent are the standard locations probed. +fn ensure_zcode_entry_env( + merged_env: &mut Vec<(String, String)>, + home: Option<&Path>, +) -> Result<(), String> { + ensure_zcode_entry_env_with(merged_env, &zcode_entry_candidates(home)) +} + +/// The testable core of [`ensure_zcode_entry_env`]: probe a GIVEN candidate +/// list so tests never depend on what happens to be installed on the machine. +fn ensure_zcode_entry_env_with( + merged_env: &mut Vec<(String, String)>, + candidates: &[PathBuf], +) -> Result<(), String> { + if let Some(index) = merged_env + .iter() + .position(|(k, _)| k == "ZCODE_CODEG_ENTRY") + { + let value = merged_env[index].1.clone(); + let path = Path::new(&value); + if path.is_absolute() && path.is_file() { + return Ok(()); + } + return Err(format!( + "ZCODE_CODEG_ENTRY is set to \"{value}\", which is not an absolute path to a \ + readable file. Fix or clear it in Agent Settings → ZCode → Environment." + )); + } + for candidate in candidates { + if candidate.is_file() { + merged_env.push(( + "ZCODE_CODEG_ENTRY".to_string(), + candidate.to_string_lossy().to_string(), + )); + return Ok(()); + } + } + Err( + "ZCode CLI entry not found. Install the ZCode app, or set ZCODE_CODEG_ENTRY to the \ + absolute path of its .cjs entry (e.g. \ + /Applications/ZCode.app/Contents/Resources/glm/zcode.cjs) in Agent Settings → \ + ZCode → Environment." + .to_string(), + ) +} + async fn build_agent( agent_type: AgentType, runtime_env: &BTreeMap, @@ -1794,6 +1870,16 @@ async fn build_agent( } } let mut merged_env = merge_agent_env(env, runtime_env, scratch); + // The zcode-codeg adapter requires the ZCode app's .cjs entry via + // env and exits E_ENTRY without it; resolve or fail fast here, + // before the spawn turns it into an opaque protocol error. + if agent_type == AgentType::ZCode { + if let Err(message) = + ensure_zcode_entry_env(&mut merged_env, dirs::home_dir().as_deref()) + { + return Err(AcpError::SdkNotInstalled(message)); + } + } // Resolve the config-derived preset HERE (like Grok's // `grok_launch_permission_mode` below) so the policy helper stays a // pure function over the env list. @@ -22148,6 +22234,107 @@ mod tests { ); } + #[test] + fn zcode_entry_env_accepts_explicit_absolute_file() { + let entry = std::env::temp_dir().join("codeg-zcode-test-entry.cjs"); + std::fs::write(&entry, "// stub\n").unwrap(); + let mut env = vec![( + "ZCODE_CODEG_ENTRY".to_string(), + entry.to_string_lossy().to_string(), + )]; + assert!(ensure_zcode_entry_env_with(&mut env, &[]).is_ok()); + // The explicit value is kept verbatim, never replaced by a probe. + assert_eq!(env[0].1, entry.to_string_lossy().to_string()); + let _ = std::fs::remove_file(&entry); + } + + #[test] + fn zcode_entry_env_rejects_stale_override_without_falling_back() { + // A configured path that no longer resolves must fail loudly — + // silently probing past it would hand the adapter a DIFFERENT ZCode + // install than the one the user pinned. + let mut env = vec![( + "ZCODE_CODEG_ENTRY".to_string(), + "/definitely/not/a/real/zcode.cjs".to_string(), + )]; + let hit = std::env::temp_dir().join("codeg-zcode-stale-override-hit.cjs"); + std::fs::write(&hit, "// stub\n").unwrap(); + let err = + ensure_zcode_entry_env_with(&mut env, std::slice::from_ref(&hit)).unwrap_err(); + assert!(err.contains("ZCODE_CODEG_ENTRY"), "got: {err}"); + assert!(!env.iter().any(|(k, _)| k != "ZCODE_CODEG_ENTRY")); + let _ = std::fs::remove_file(&hit); + } + + #[test] + fn zcode_entry_env_probes_first_existing_candidate_when_unset() { + let miss = std::env::temp_dir().join("codeg-zcode-probe-miss.cjs"); + let hit = std::env::temp_dir().join("codeg-zcode-probe-own-hit.cjs"); + std::fs::write(&hit, "// stub\n").unwrap(); + let mut env: Vec<(String, String)> = Vec::new(); + ensure_zcode_entry_env_with(&mut env, &[miss, hit.clone()]).unwrap(); + assert_eq!( + env, + vec![( + "ZCODE_CODEG_ENTRY".to_string(), + hit.to_string_lossy().to_string() + )] + ); + let _ = std::fs::remove_file(&hit); + } + + #[test] + fn zcode_entry_env_errors_with_guidance_when_nothing_resolves() { + let mut env: Vec<(String, String)> = Vec::new(); + let miss = std::env::temp_dir().join("codeg-zcode-probe-miss.cjs"); + let err = ensure_zcode_entry_env_with(&mut env, &[miss]).unwrap_err(); + assert!(err.contains("ZCODE_CODEG_ENTRY"), "got: {err}"); + assert!(err.contains("Agent Settings"), "got: {err}"); + assert!(env.is_empty(), "no entry may be injected on failure"); + } + + #[test] + fn zcode_entry_candidates_cover_standard_locations() { + let home = PathBuf::from("/home/tester"); + let candidates = zcode_entry_candidates(Some(&home)); + // The per-user bundle location is always probed... + assert!(candidates.contains( + &home.join("Applications/ZCode.app/Contents/Resources/glm/zcode.cjs") + )); + // ...and on macOS the system /Applications bundle comes first so the + // common install wins without touching $HOME. + if cfg!(target_os = "macos") { + assert_eq!( + candidates.first().map(PathBuf::as_path), + Some(Path::new( + "/Applications/ZCode.app/Contents/Resources/glm/zcode.cjs" + )) + ); + } + // Nothing to probe without a home — the error path guides the user. + assert!(zcode_entry_candidates(None).is_empty() || cfg!(target_os = "macos")); + } + + #[test] + fn transcript_recording_covers_custom_agents_and_zcode_only() { + // ZCode is the one built-in whose history codeg must record itself; + // every other built-in has a dedicated native-store parser, and + // recording those too would double the storage. + assert_eq!(transcript_dir_for(AgentType::ZCode), Some("zcode-acp")); + assert_eq!( + transcript_dir_for(AgentType::custom("goose").unwrap()), + Some("goose") + ); + for builtin in crate::models::agent::BUILTIN_AGENT_TYPES { + let expected = matches!(builtin, AgentType::ZCode); + assert_eq!( + transcript_dir_for(*builtin).is_some(), + expected, + "unexpected transcript recording for {builtin:?}" + ); + } + } + #[test] fn cursor_companion_title_resolves_status_report() { // Real-device shape: companion.rs::render_batch_report's compact JSON. diff --git a/src-tauri/src/acp/delegation/companion.rs b/src-tauri/src/acp/delegation/companion.rs index 64416b3ac6..a173498b8e 100644 --- a/src-tauri/src/acp/delegation/companion.rs +++ b/src-tauri/src/acp/delegation/companion.rs @@ -2658,7 +2658,7 @@ mod tests { let agents = delegate["inputSchema"]["properties"]["agent_type"]["enum"] .as_array() .unwrap(); - assert_eq!(agents.len(), 15); + assert_eq!(agents.len(), 16); assert!(agents.iter().any(|a| a == "hermes")); assert!(agents.iter().any(|a| a == "code_buddy")); assert!(agents.iter().any(|a| a == "kimi_code")); @@ -2668,6 +2668,7 @@ mod tests { assert!(agents.iter().any(|a| a == "deepseek")); assert!(agents.iter().any(|a| a == "qoder")); assert!(agents.iter().any(|a| a == "antigravity")); + assert!(agents.iter().any(|a| a == "zcode")); // get_delegation_status takes a single id param — task_ids (required) — // plus wait_ms. The legacy single `task_id` param is gone. let status = tools @@ -2707,11 +2708,11 @@ mod tests { .as_array() .unwrap() .clone(); - assert_eq!(agents.len(), 17, "15 builtins + 2 distinct customs"); + assert_eq!(agents.len(), 18, "16 builtins + 2 distinct customs"); // Builtins keep the embedded order and come first. assert_eq!(agents[0], "claude_code"); - assert_eq!(agents[15], "custom:goose"); - assert_eq!(agents[16], "custom:amp"); + assert_eq!(agents[16], "custom:goose"); + assert_eq!(agents[17], "custom:amp"); // The other delegation tools carry no agent_type and are untouched. let status = tools .as_array() @@ -2746,13 +2747,13 @@ mod tests { .as_array() .unwrap() .clone(); - assert_eq!(agents.len(), 14, "15 builtins - 2 disabled + 1 custom"); + assert_eq!(agents.len(), 15, "16 builtins - 2 disabled + 1 custom"); assert!(!agents.contains(&serde_json::json!("codex"))); assert!(!agents.contains(&serde_json::json!("grok"))); // Survivors keep the embedded order, customs still come last. assert_eq!(agents[0], "claude_code"); assert_eq!(agents[1], "open_code"); - assert_eq!(agents[13], "custom:goose"); + assert_eq!(agents[14], "custom:goose"); } // An empty disabled list (the parent omitted `--disabled-agents`) leaves @@ -2774,9 +2775,10 @@ mod tests { .as_array() .unwrap() .clone(); - assert_eq!(agents.len(), 15); + assert_eq!(agents.len(), 16); assert_eq!(agents[0], "claude_code"); assert_eq!(agents[14], "antigravity"); + assert_eq!(agents[15], "zcode"); } #[tokio::test] diff --git a/src-tauri/src/acp/delegation/tool_schema.json b/src-tauri/src/acp/delegation/tool_schema.json index 7176af1e67..48316ec366 100644 --- a/src-tauri/src/acp/delegation/tool_schema.json +++ b/src-tauri/src/acp/delegation/tool_schema.json @@ -26,7 +26,8 @@ "cursor", "deepseek", "qoder", - "antigravity" + "antigravity", + "zcode" ], "description": "Which local agent runs the sub-task. Pick the one best suited to the work — or, when the user's message names an agent via `@AgentName` / `codeg://agent/`, use that exact `` slug (e.g. `codeg://agent/claude_code` means `claude_code`)." }, diff --git a/src-tauri/src/acp/file_system_runtime.rs b/src-tauri/src/acp/file_system_runtime.rs index 801a55d416..499ca9fe5a 100644 --- a/src-tauri/src/acp/file_system_runtime.rs +++ b/src-tauri/src/acp/file_system_runtime.rs @@ -694,6 +694,11 @@ fn agent_root_slots(agent_type: AgentType) -> &'static [RootSlot] { default_rel: &[".pi", "agent", "sessions"], }, ], + // ZCode, like a custom ACP agent, has no codeg-known private directory + // layout: codeg never reads ZCode's store (the built-in's history is + // codeg's own ACP transcript), so there is nothing to widen the + // sandbox roots for. + AgentType::ZCode => &[], // A custom ACP agent has no codeg-known private directory layout — // codeg never reads its store (history comes from codeg's own ACP // transcript), so there is nothing to widen the sandbox roots for. diff --git a/src-tauri/src/acp/registry.rs b/src-tauri/src/acp/registry.rs index 07b67286a2..a9b1fb447a 100644 --- a/src-tauri/src/acp/registry.rs +++ b/src-tauri/src/acp/registry.rs @@ -243,10 +243,11 @@ pub fn builtin_acp_agents() -> Vec { AgentType::DeepSeek, AgentType::Qoder, AgentType::Antigravity, + AgentType::ZCode, ] } -/// Every agent codeg can currently drive: the fifteen built-ins followed by +/// Every agent codeg can currently drive: the sixteen built-ins followed by /// the user's registered custom ACP agents (sorted by id). pub fn all_acp_agents() -> Vec { let mut agents = builtin_acp_agents(); @@ -271,6 +272,7 @@ pub fn registry_id_for(agent_type: AgentType) -> &'static str { AgentType::DeepSeek => "deepseek-acp", AgentType::Qoder => "qoder-cli", AgentType::Antigravity => "antigravity-acp", + AgentType::ZCode => "zcode-acp", // A custom agent's registry id IS its identity. AgentType::Custom(id) => id, } @@ -293,6 +295,7 @@ pub fn from_registry_id(id: &str) -> Option { "deepseek-acp" => Some(AgentType::DeepSeek), "qoder-cli" => Some(AgentType::Qoder), "antigravity-acp" => Some(AgentType::Antigravity), + "zcode-acp" => Some(AgentType::ZCode), // Only ids the user has actually registered resolve. An unregistered // id must stay `None` so the ACP-registry picker still offers it as // "addable" rather than treating it as already supported. @@ -2531,6 +2534,49 @@ pub fn get_agent_meta(agent_type: AgentType) -> AcpAgentMeta { }), }, }, + AgentType::ZCode => AcpAgentMeta { + agent_type, + supports_mcp: true, + name: "ZCode", + description: "ZCode coding agent (ACP via the pinned zcode-codeg adapter)", + // `zcode-codeg-acp` is NOT a first-party ZCode server: it is the + // pinned community adapter (zcode-codeg-adapter) + // that speaks ACP on stdio while driving the ZCode app's private + // backend. The verified handshake advertises `loadSession`, so + // codeg's resume rung works; per-session model/mode selection + // arrives through standard `configOptions`, so the composer + // selectors need no per-agent code. MCP servers are forwarded on + // the `session/new` wire (stdio), including the codeg-mcp + // delegation companion. + // + // ENTRY IS AN ENV CONTRACT, NOT A FLAG. The adapter refuses to + // guess where the ZCode CLI lives: `ZCODE_CODEG_ENTRY` must name + // the app's `.cjs` entry (e.g. + // `/Applications/ZCode.app/Contents/Resources/glm/zcode.cjs`) or + // the process exits `E_ENTRY` before the handshake. connection.rs + // probes the standard install locations at launch and the + // agent-settings env map can override the path (plus optional + // `ZCODE_CODEG_CONFIG` for the adapter's own config file). Auth is + // the user's existing ZCode login — the adapter neither reads nor + // refreshes credentials. + // + // NO NATIVE TRANSCRIPT. ZCode is the first built-in whose history + // is codeg's OWN ACP recording (`parsers::acp_native`), the same + // store custom agents use — see `transcript_dir_for` in + // connection.rs. Sessions that predate the built-in (the + // `custom:zcode-codeg` adapter registration) keep their custom + // identity; `zcode-codeg` remains a valid custom id on purpose. + // + // `engines.node: "^22.16.0 || ^24.0.0 || ^25.0.0"`. + distribution: AgentDistribution::Npx { + version: "0.1.3", + package: "zcode-codeg-adapter@0.1.3", + cmd: "zcode-codeg-acp", + args: &[], + env: &[], + node_required: Some("22.16.0"), + }, + }, // Handled by the early return above; kept so the match stays // exhaustive without a catch-all that could swallow a new built-in. AgentType::Custom(_) => unreachable!("custom agents resolve via custom_registry"), @@ -2880,6 +2926,15 @@ mod tests { "@qoder-ai/qodercli@1.1.57", Some("20.0.0"), ); + // The zcode-codeg adapter pin must stay EXACT: the audited ACP core + // is only what the pinned version ships, and version/package drift + // would leave the Upgrade button installing an unaudited build. + assert_npx_version( + AgentType::ZCode, + "0.1.3", + "zcode-codeg-adapter@0.1.3", + Some("22.16.0"), + ); assert_binary_version(AgentType::OpenCode, "1.18.31", "/releases/download/v1.18.31/"); // Hermes rides the community npm bridge (upstream retired its PyPI // channel at 0.19.0; see the registry entry). The npm package version diff --git a/src-tauri/src/commands/acp.rs b/src-tauri/src/commands/acp.rs index f46a18839b..c2e3bb7f15 100644 --- a/src-tauri/src/commands/acp.rs +++ b/src-tauri/src/commands/acp.rs @@ -8545,6 +8545,11 @@ pub(crate) fn skill_storage_spec(agent_type: AgentType) -> Option None, // codeg cannot detect where an arbitrary ACP agent loads skills from, // so custom agents are gated on the user's own declaration: that the // agent reads the shared `.agents/skills` store (the cross-agent @@ -10234,6 +10239,13 @@ fn cascade_update_agent_config( // METHOD, never a credential, so there is nothing here to // reconcile either. } + AgentType::ZCode => { + // ZCode authenticates against the user's existing ZCode login and + // its adapter neither reads nor refreshes credentials, so there is + // no model-provider surface for the cascade to reconcile. The + // launch-contract env (`ZCODE_CODEG_ENTRY`, optional + // `ZCODE_CODEG_CONFIG`) is managed through the generic env panel. + } AgentType::Custom(_) => { // Custom agents are deliberately configuration-free: codeg writes // no config file for them and they are excluded from the diff --git a/src-tauri/src/commands/mcp.rs b/src-tauri/src/commands/mcp.rs index 37c933cd55..2113d7fbe0 100644 --- a/src-tauri/src/commands/mcp.rs +++ b/src-tauri/src/commands/mcp.rs @@ -3276,6 +3276,12 @@ pub fn read_servers_for_agent_type( // itself at session setup — see the Antigravity section above for why // it rides the forward skip list rather than the wire. AgentType::Antigravity => read_antigravity_servers(), + // The zcode-codeg adapter takes MCP servers as `session/new`'s + // `mcpServers` (stdio) — the ACP wire is the delivery path, so ZCode + // must stay OFF the forward skip list in `connection.rs`. Like DeepSeek + // it has no codeg-managed native MCP store to read back here; unlike + // DeepSeek there is not even a codeg-side `$HOME/mcp.json` record yet. + AgentType::ZCode => Ok(BTreeMap::new()), // Custom agents get MCP purely over the ACP wire (`session/new`'s // `mcpServers`); codeg deliberately knows nothing about their native // config files, so there is no per-agent store to read back here. diff --git a/src-tauri/src/db/service/agent_setting_service.rs b/src-tauri/src/db/service/agent_setting_service.rs index cd98684acf..1c7722efbc 100644 --- a/src-tauri/src/db/service/agent_setting_service.rs +++ b/src-tauri/src/db/service/agent_setting_service.rs @@ -43,6 +43,7 @@ fn default_enabled(agent_type: AgentType) -> bool { | AgentType::DeepSeek | AgentType::Qoder | AgentType::Antigravity + | AgentType::ZCode // A user who just registered a custom agent wants to use it. | AgentType::Custom(_) ) diff --git a/src-tauri/src/db/service/import_service.rs b/src-tauri/src/db/service/import_service.rs index 3a04e60a50..938905ef52 100644 --- a/src-tauri/src/db/service/import_service.rs +++ b/src-tauri/src/db/service/import_service.rs @@ -10,7 +10,7 @@ use crate::models::{AgentType, ConversationSummary, ImportResult}; use crate::parsers::{build_agent_parser, path_eq_for_matching, AgentParser}; /// Every locally-parsable agent, in the canonical parser order. -const ALL_PARSER_AGENTS: [AgentType; 15] = [ +const ALL_PARSER_AGENTS: [AgentType; 16] = [ AgentType::ClaudeCode, AgentType::Codex, AgentType::OpenCode, @@ -26,6 +26,7 @@ const ALL_PARSER_AGENTS: [AgentType; 15] = [ AgentType::DeepSeek, AgentType::Qoder, AgentType::Antigravity, + AgentType::ZCode, ]; fn build_parser(agent_type: AgentType) -> Box { diff --git a/src-tauri/src/models/agent.rs b/src-tauri/src/models/agent.rs index bc38571361..f698f478ed 100644 --- a/src-tauri/src/models/agent.rs +++ b/src-tauri/src/models/agent.rs @@ -36,12 +36,13 @@ pub enum AgentType { DeepSeek, Qoder, Antigravity, + ZCode, /// A user-registered ACP agent, identified by its ACP-registry id /// (interned). Ordered last so built-ins keep their relative order. Custom(&'static str), } -/// The fifteen compile-time agents, in declaration order. Does NOT include +/// The sixteen compile-time agents, in declaration order. Does NOT include /// custom agents — use [`crate::acp::registry::all_acp_agents`] for the live /// set that includes them. pub const BUILTIN_AGENT_TYPES: &[AgentType] = &[ @@ -60,6 +61,7 @@ pub const BUILTIN_AGENT_TYPES: &[AgentType] = &[ AgentType::DeepSeek, AgentType::Qoder, AgentType::Antigravity, + AgentType::ZCode, ]; impl AgentType { @@ -107,6 +109,7 @@ impl AgentType { AgentType::DeepSeek => Cow::Borrowed("deepseek"), AgentType::Qoder => Cow::Borrowed("qoder"), AgentType::Antigravity => Cow::Borrowed("antigravity"), + AgentType::ZCode => Cow::Borrowed("zcode"), AgentType::Custom(id) => Cow::Owned(format!("{CUSTOM_AGENT_WIRE_PREFIX}{id}")), } } @@ -130,6 +133,7 @@ impl AgentType { "deepseek" => Some(AgentType::DeepSeek), "qoder" => Some(AgentType::Qoder), "antigravity" => Some(AgentType::Antigravity), + "zcode" => Some(AgentType::ZCode), other => other .strip_prefix(CUSTOM_AGENT_WIRE_PREFIX) .and_then(AgentType::custom), @@ -172,6 +176,7 @@ pub fn is_valid_custom_agent_id(id: &str) -> bool { | "deepseek" | "qoder" | "antigravity" + | "zcode" ) } @@ -207,6 +212,7 @@ impl fmt::Display for AgentType { AgentType::DeepSeek => write!(f, "DeepSeek Harness"), AgentType::Qoder => write!(f, "Qoder"), AgentType::Antigravity => write!(f, "Google Antigravity"), + AgentType::ZCode => write!(f, "ZCode"), // Prefer the registered display name; fall back to the raw id when // the registry has not been hydrated (or the agent was deleted // while conversations still reference it). @@ -242,6 +248,7 @@ mod tests { (AgentType::DeepSeek, "deepseek"), (AgentType::Qoder, "qoder"), (AgentType::Antigravity, "antigravity"), + (AgentType::ZCode, "zcode"), ]; for (agent, wire) in expected { assert_eq!(agent.as_wire(), wire); @@ -312,6 +319,7 @@ mod tests { "deepseek", "qoder", "antigravity", + "zcode", ] { assert!( !is_valid_custom_agent_id(bad), @@ -323,6 +331,10 @@ mod tests { assert!(is_valid_custom_agent_id("qwen-code")); assert!(is_valid_custom_agent_id("github-copilot-cli")); assert!(is_valid_custom_agent_id("my_agent.v2")); + // The pre-builtin custom-agent id for the ZCode adapter stays a valid + // custom id: conversations persisted as `custom:zcode-codeg` must keep + // resolving, not be orphaned by the built-in `zcode` wire name. + assert!(is_valid_custom_agent_id("zcode-codeg")); // 64 chars is the ceiling. assert!(is_valid_custom_agent_id(&"a".repeat(64))); assert!(!is_valid_custom_agent_id(&"a".repeat(65))); @@ -335,6 +347,8 @@ mod tests { assert!(AgentType::Cursor < AgentType::DeepSeek); assert!(AgentType::DeepSeek < AgentType::Qoder); assert!(AgentType::Qoder < AgentType::Antigravity); + assert!(AgentType::Antigravity < AgentType::ZCode); + assert!(AgentType::ZCode < AgentType::custom("goose").unwrap()); // Custom agents order lexicographically among themselves. assert!(AgentType::custom("aaa").unwrap() < AgentType::custom("bbb").unwrap()); } diff --git a/src-tauri/src/parsers/mod.rs b/src-tauri/src/parsers/mod.rs index 38d391e1c1..8aa9061771 100644 --- a/src-tauri/src/parsers/mod.rs +++ b/src-tauri/src/parsers/mod.rs @@ -316,6 +316,10 @@ pub fn build_agent_parser(agent_type: AgentType) -> Box { AgentType::DeepSeek => Box::new(deepseek::DeepSeekParser::new()), AgentType::Qoder => Box::new(qoder::QoderParser::new()), AgentType::Antigravity => Box::new(antigravity::AntigravityParser::new()), + // ZCode's adapter keeps history in ZCode's private store, which codeg + // deliberately does not read; the built-in records its own ACP + // transcript instead — the same store custom agents use. + AgentType::ZCode => Box::new(acp_native::AcpNativeParser::new(agent_type)), // Custom ACP agents have no native store to reverse-engineer; their // history is codeg's own ACP transcript. AgentType::Custom(_) => Box::new(acp_native::AcpNativeParser::new(agent_type)), diff --git a/src/components/agent-icon.tsx b/src/components/agent-icon.tsx index bb471e8aa2..55645d3853 100644 --- a/src/components/agent-icon.tsx +++ b/src/components/agent-icon.tsx @@ -440,6 +440,24 @@ const AntigravityMonoIcon = memo(function AntigravityMonoIcon({ ) }) +const ZCodeMonoIcon = memo(function ZCodeMonoIcon({ size = "1em" }: IconProps) { + // A plain "Z" monogram — NOT an official ZCode mark (none is published to + // the ACP registry CDN yet). Replace with the official glyph when one lands. + return ( + + ZCode + + + ) +}) + const CursorMonoIcon = memo(function CursorMonoIcon({ size = "1em", }: IconProps) { @@ -483,6 +501,7 @@ const MONO_ICONS: Partial> = { cursor: CursorMonoIcon, qoder: QoderMonoIcon, antigravity: AntigravityMonoIcon, + zcode: ZCodeMonoIcon, } // Per-agent color override for mono marks, layered on top of the default diff --git a/src/components/settings/delegation-agent-defaults.tsx b/src/components/settings/delegation-agent-defaults.tsx index 7775f29f2d..aed60358bb 100644 --- a/src/components/settings/delegation-agent-defaults.tsx +++ b/src/components/settings/delegation-agent-defaults.tsx @@ -72,6 +72,7 @@ const BUILTIN_AGENT_TYPES: AgentType[] = [ "deepseek", "qoder", "antigravity", + "zcode", ] interface CachedSnapshot { diff --git a/src/lib/types.ts b/src/lib/types.ts index 4b8fdd62a6..c5de1ca510 100644 --- a/src/lib/types.ts +++ b/src/lib/types.ts @@ -15,6 +15,7 @@ export type BuiltinAgentType = | "deepseek" | "qoder" | "antigravity" + | "zcode" /** * Which agent backs a conversation. @@ -935,6 +936,7 @@ export const AGENT_DISPLAY_ORDER: BuiltinAgentType[] = [ "deepseek", "qoder", "antigravity", + "zcode", ] const AGENT_DISPLAY_ORDER_INDEX = new Map( @@ -969,6 +971,7 @@ export const ALL_AGENT_TYPES: BuiltinAgentType[] = [ "deepseek", "qoder", "antigravity", + "zcode", ] export const MODEL_PROVIDER_AGENT_TYPES: BuiltinAgentType[] = [ @@ -1280,6 +1283,7 @@ export const AGENT_LABELS: Record = { deepseek: "DeepSeek Harness", qoder: "Qoder", antigravity: "Google Antigravity", + zcode: "ZCode", } export const AGENT_COLORS: Record = { @@ -1298,6 +1302,7 @@ export const AGENT_COLORS: Record = { deepseek: "bg-[#4D6BFE]", qoder: "bg-[#6C4CF1]", antigravity: "bg-[#1A73E8]", + zcode: "bg-[#00B96B]", } // ACP connection status (matches Rust ConnectionStatus)