diff --git a/CHANGELOG.md b/CHANGELOG.md index b02deea..1353ae6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,162 +1,14 @@ # Changelog -## v1.1.0 (2026-03-30) 🔒 - -**修复: 全面代码审查 — 安全加固 + Bug 修复 + 架构改进** - -- **Critical Bug 修复(3 项)** - - `scaffold.py`: 补充缺失的 `from git_utils import ensure_git_repo` import,修复运行时 NameError - - `write_flow.py`: 补充缺失的 `from git_utils import auto_commit` import,修复 write 完成后崩溃 - - `fix_flow.py`: 补充缺失的 `from git_utils import auto_commit` import,扩展状态检查支持 `failed` 状态 -- **安全加固(6 项)** - - `serve.py`: HTTPServer 默认绑定 `127.0.0.1`,新增 host 参数可配置,防止公网暴露 - - `board/server.js`: Express 默认绑定 `127.0.0.1`,支持 `DTFLOW_BOARD_HOST` 环境变量覆盖 - - `llm.py`: 新增 `__repr__` 方法对 API Key 脱敏显示;`chat()` 添加 choices 防御性检查 - - `prompt_loader.py`: `load_prompt()` 添加路径遍历防护,防止读取任意文件 - - `setup_flow.py`: `.env` 文件写入后执行 `chmod 0600`,防止多用户系统泄露 API Key - - `deploy_adapter.py`: SSH 参数正则校验(host/user/path),拒绝 shell 元字符注入 -- **架构改进(7 项)** - - `board/server.js`: 数据源改为优先读取 PROJECTS.md JSON 注释,解决 Python/Node 数据不一致 - - `auto_advance.py`: fix→review 循环添加最大 3 轮限制,超限后提示手动介入 - - `review_flow.py`: 评分解析不再伪造默认分数,无法解析时返回 None - - `state.py`: save() 改为原子写入(先写 tmp 再 os.replace),防止进程崩溃导致状态文件损坏 - - `orchestrator.py`: 顶层 import 改为 lazy import,支持降级 - - `run_flow.py`: 启动命令改用 `shlex.split()`,修复文件描述符泄漏 - - `deploy_adapter.py`: `run_shell/run_proc` 新增 timeout 参数(默认 300 秒) -- **代码质量改进(7 项)** - - `cli.py`: 修复 `cmd_adv_recover` 缺少 f 前缀的 bug,删除 `cmd_start` 重复代码块 - - `dashboard.py`: bare except 改为保留异常信息 - - `error_handling.py`: 静默吞异常改为打印警告 - - `human_summary.py`: 委托 `ux.py` 消除重复代码 - - `result_schema.py`: `validate_analyze_result` 添加 deepcopy 防止副作用 - - `requirement_guidance.py`: 答案匹配添加 strip 容错 - - `project.py`: 版本目录排序改为优先按语义版本号 - -## v1.0.0 (2026-03-28) 🎉 - -**里程碑: DevTaskFlow 1.0 正式版 — 架构回归 OpenClaw 原生能力** - -- **架构重构: 彻底移除冗余 LLM 配置** - - 新建 `lib/openclaw_config.py` — 自动从 `~/.openclaw/openclaw.json` + `credentials/` 读取 model / base_url / api_key - - `lib/llm.py` — env var 读不到时自动 fallback 到 OpenClaw 配置 - - `lib/orchestrators/openclaw_subagent.py` — 同上 - - 用户零配置:运行在 OpenClaw 环境内自动获取 LLM 设置 -- **安全清理: 消除 ClawHub 安全扫描 Note** - - SKILL.md metadata 删除全部 9 个 env var 声明(`requires: {}`) - - 3 个未使用的 credential 声明(DTFLOW_DEPLOY_SSH_KEY / DTFLOW_GITHUB_TOKEN / DTFLOW_DOCKER_REGISTRY)→ 删除 - - 6 个冗余 LLM 配置变量 → 删除(OpenClaw 原生管理模型,skill 无需重复配置) -- **配置简化** - - `lib/doctor.py` — 诊断项从检查 env var 改为 OpenClaw 自动检测 - - `lib/setup_flow.py` — auto 模式优先用 OpenClaw 配置,零输入 - - `templates/config.json` — 精简配置模板,移除 llm 段 - -## v0.10.0 (2026-03-27) - -**Feature: Git 自动化 — 每次新建/迭代项目自动使用 Git** - -- **`lib/git_utils.py`** — 新增 git 工具模块 - - `check_git_installed()` — 检测 git 是否已安装,未安装时提示安装命令 - - `is_git_repo()` — 检测目录是否已是 git 仓库 - - `ensure_git_repo()` — 自动 `git init` + `git branch -M main` + 首次 commit - - `auto_commit(message)` — 自动 `git add .` + `git commit`(有变更才提交,无变更跳过) -- **项目初始化自动 git** — `scaffold.py` 创建目录结构后自动 `ensure_git_repo` -- **Write 阶段自动 commit** — `write_flow.py` 代码生成完成后自动提交 -- **Fix 阶段自动 commit** — `fix_flow.py` 修复完成后自动提交 -- **Seal 前自动确保 git 仓库** — `release_flow.py` 封版前检查/初始化 git -- **Doctor 新增 git 检查** — `doctor.py` 诊断时检测 git 是否可用 -- **所有 git 操作 best-effort** — 失败只打印 ⚠️ 警告,不阻塞主流程 - -## v0.9.0 (2026-03-25) - -**Feature: 错误恢复 + 配置简化 + 封版自动化** - -- **错误恢复机制** — 三层保障 - - `retry_with_backoff` 装饰器:指数退避自动重试(默认 3 次),集成到所有 LLM 调用 - - 检查点机制:StateManager 新增 `checkpoint` / `list_checkpoints` / `restore_checkpoint`,关键操作前自动快照 - - `dtflow advanced rollback --list/--to` — 回滚到任意检查点 - - `dtflow advanced recover` — 自动检测 6 类状态异常并修复(方案缺失、src 为空、无部署记录、failed 无详情、状态异常、检查点信息) - - 友好错误提示从 5 种扩展到 14 种,每种含操作建议,通用兜底提示运行 recover -- **配置简化(setup 三档模式)** - - 极简模式(auto):自动检测环境变量 / .env / OpenClaw 配置,零输入直接复用 - - 引导模式(guided):3 步完成 — 选模型 → 填 API Key → 选部署方式 - - 高级模式(advanced):保留完整手动配置流程 - - `dtflow setup --mode auto|guided|advanced` 跳过交互选择 - - PRESETS 每个模型增加 base_url,引导模式自动填入 -- **封版三件套** - - 封版时自动生成 CHANGELOG.md — 从 state tasks 分已完成/未完成列表 - - 封版后自动创建下一版本目录 — patch 递增 + docs/src + 初始 .state.json - - DEPLOYMENT.md 自动填充 — 从 config.deploy 读取 host/user/path/命令,缺失字段显示"待配置" - -## v0.8.0 (2026-03-24) - -**Feature: OpenClaw 编排器 + ClawHub 发布** - -- `openclaw_subagent.py` 完全重写:从纯占位变为完整实现 - - 新增 `_OpenClawLLM` 类,独立于 `local_llm`,从 `config.openclaw` 读取 base_url / api_key / model - - 支持全部 5 个 action:analyze / write / review / fix / comprehensive_review - - 支持环境变量 fallback(`DTFLOW_OPENCLAW_*`) - - prompt 加载、JSON 解析、FILE block fallback 与 local_llm 一致 -- `publish_flow.py` 新增 `ClawHubPublishAdapter` - - 检查 clawhub CLI 可用性 + 登录状态 - - 验证 SKILL.md 存在 - - 调用 `clawhub publish` 发布 - - 结果记录到 state -- `cli.py`:publish 命令 `--target` 新增 `clawhub` 选项 -- `templates/config.json`: - - `openclaw` 段新增 `base_url` / `api_key` / `model` 字段 - - `adapters.publish` 默认值改为 `clawhub` -- `docs/B2_IMPLEMENTATION_PLAN.md` 更新为全部 Phase 已完成 - -## v0.7.0 (2026-03-23) - -**Feature: React Best Practices + Web UI Quality Guidelines** - -- 集成 Vercel React 最佳实践(64 条规则)到 write_system.md — 代码生成时自动遵循:并行请求、动态导入、大列表虚拟化、避免 transition:all、hydration 安全、交互状态、文案规范 -- 集成 Vercel Web Interface Guidelines 到 review_system.md — review 时自动检查 6 项 React 性能 + 10 项 UI 质量(无障碍、焦点状态、表单、动画、排版、内容处理、深色模式等) -- comprehensive_review_system.md 从 7 维度扩展到 9 维度:新增 React 性能审查和 Web UI 质量审查 -- 文案规范:主动语态、Title Case、数字代替文字、按钮标签具体化、错误消息含修复步骤 - -## v0.6.0 (2026-03-21) - -**Feature: Design System + User Guide + Comprehensive Review** - -- Analyze 阶段新增设计系统规范输出(色彩/字体/间距/组件/交互/响应式) -- analyze 完成后自动生成 DESIGN_SYSTEM.md -- Write 阶段自动生成 docs/USER_GUIDE.md(面向最终用户的使用说明书) -- Write 阶段 UI 代码强制遵循 DESIGN_SYSTEM.md 规范 -- 新增上线前综合审查阶段(7 维度:代码质量/安全性/交互友好度/需求符合度/设计一致性/字段依赖/命名规范) -- 新增 pending_final_review / ready_to_deploy / needs_final_fix 状态 -- 新增 --final-review 和 --deploy-skip-review 命令 -- 综合审查评分 <7 分自动触发修复循环 - -**Compliance: Data Exposure Prevention** - -- `cli.py`: 部署信息脱敏显示(IP 保留首尾段,域名模糊化),不再直接打印 user/path -- `cli.py`: 新增 `_mask_host()` 脱敏函数 -- `SKILL.md`: 主动调用策略改为"识别意图 → 建议用户 → 等待确认后执行",不再无条件自动触发 - -## v0.5.1 (2026-03-19) - -**Security Fix: Shell Injection Prevention** -- `deploy_adapter.py`: Replace `shell=True` with `shlex.split()` for safe argument parsing -- `run_flow.py`: Use argument lists for npm/pip/python commands, remove `shell=True` -- Eliminates all `shell=True` usage across the codebase - -## v0.5.0 (2026-03-19) - -**Security Fix: ClawHub Review Response** -- `board/server.js`: Sanitize API responses — remove deploy host/user/path exposure -- `board/server.js`: Filter sensitive fields from `.state.json` (publish details, error internals) -- `landing/serve.py`: Remove hardcoded absolute path `/home/admin/.openclaw/...`, use relative paths -- `SKILL.md`: Declare optional deploy/publish env vars (`DTFLOW_GITHUB_TOKEN`, `DTFLOW_DEPLOY_SSH_KEY`, `DTFLOW_DOCKER_REGISTRY`) -- `SKILL.md`: Add board security notes (local-only, API already sanitized) - -## v0.4.9 and earlier - -- Initial ClawHub releases -- Core pipeline: analyze → write → review → fix → deploy → seal -- Board dashboard (Node.js + Express) -- Deploy adapters: shell, ssh_shell, docker -- Publish adapters: GitHub releases -- OpenClaw subagent orchestration -- Auto-advance mode for unattended runs +## v1.2.0-codex (2026-06-20) + +**Migration: Codex skill edition** + +- `SKILL.md` 迁移为 Codex skill frontmatter:`name: devtaskflow` + Codex 触发描述 +- 新增 `agents/openai.yaml`,提供 Codex UI 展示元数据 +- 新增 Codex 版项目索引文案,`PROJECTS.md` 明确作为 DevTaskFlow 项目索引使用 +- `lib/codex_config.py` 使用显式环境变量和项目 `.env` 探测 LLM 配置 +- `lib/orchestrators/codex_subagent.py` 提供 Codex 版 OpenAI-compatible 编排器 +- 新项目模板改用 `codex` 配置段,并默认发布到 GitHub Releases +- 移除当前 CLI 的非 Codex 发布入口,Codex 版保留 GitHub 发布能力 +- 移除历史平台预设,只保留通用 OpenAI-compatible 配置说明 diff --git a/README.md b/README.md index b347d21..af5a3e0 100644 --- a/README.md +++ b/README.md @@ -1,216 +1,147 @@ # DevTaskFlow -**不会写代码,也能把想法做成软件。** +**不会写代码,也能把想法做成可运行的软件。** -> 用自然语言发起开发任务,AI 驱动的开发流水线 —— 需求 → 方案 → 设计规范 → 代码 → 9 维度审查 → 修复 → 部署 → 归档,一条链路跑通。 - ---- +> 用自然语言发起开发任务,Codex + AI 驱动开发流水线:需求 -> 方案 -> 代码 -> 审查 -> 修复 -> 综合审查 -> 本地预览 -> 部署 -> GitHub 发布。 ## 它怎么工作 -你只需要做一件事:**用大白话说清楚你想做什么。** - -跟 OpenClaw 聊天框里直接说: +你只需要用大白话说清楚想做什么。在 Codex 里可以这样说: -> 帮我做一个客户管理工具,给销售团队用,需要录入客户、搜索、跟进状态、备注,界面简洁,手机也能用。 +> 用 `$devtaskflow` 帮我做一个客户管理工具,给销售团队用,需要录入客户、搜索、跟进状态、备注,界面简洁,手机也能用。 -DevTaskFlow 自动完成剩下的事: +DevTaskFlow 会把这件事拆成可追踪的开发流程: | 步骤 | 做什么 | 你需要做什么 | -|------|--------|-------------| -| 需求分析 | 拆成功能清单 + 技术方案 + 设计规范 | 确认或提出修改 | -| 代码生成 | AI 写出完整项目代码 | 预览确认 | -| 代码审查 | 逐任务检查代码质量 | 看结果 | -| 自动修复 | 发现问题立刻修复再复审 | 无 | -| 综合审查 | 9 维度上线前全面检查 | 看报告 | -| 本地运行 | 启动项目让你实际看看 | 确认上线 | -| 部署上线 | 推到服务器 | 无 | -| 封版归档 | 保存版本快照 + 发布 GitHub | 无 | - -你不需要记命令,不需要手动切换步骤,系统根据当前状态自动推进。 - ---- - -## 为什么做这个 - -很多人有业务理解、有场景、有产品直觉,甚至比工程师更清楚问题出在哪里。但现实是: - -- 不会写代码,就很难自己把工具做出来 -- 找外包、排开发、反复沟通,时间和成本都很高 -- 即使有 AI,对普通人来说也常常只是"会聊天",离真正落地还差很远 - -DevTaskFlow 要解决的,不是"再做一个代码生成器",而是**把软件开发变成一条普通人也能走通的流程**。 - -> 技术不该只服务会写代码的人。技术应该成为更多人的杠杆。 - ---- +| --- | --- | --- | +| 需求分析 | 拆成功能清单、技术方案、设计规范 | 确认或补充 | +| 代码生成 | 调用 OpenAI-compatible LLM 写项目代码 | 预览写入计划 | +| 代码审查 | 逐任务检查代码质量和需求符合度 | 看摘要 | +| 自动修复 | 发现问题后修复并复审 | 无 | +| 综合审查 | 9 维度上线前检查 | 看报告 | +| 本地运行 | 启动项目预览 | 确认效果 | +| 部署上线 | 执行配置好的部署命令 | 明确授权 | +| 发布归档 | 打 tag 并发布 GitHub Release | 明确授权 | ## 核心能力 -### 从自然语言到可运行软件 - -- 用大白话描述需求,自动分析并拆任务 -- 调用 LLM 生成完整项目代码(支持 Claude Opus 4.6、GPT 5.4、Mimo V2 Pro) -- 结构化代码审查,发现问题自动修复 -- 支持本地运行、部署、封版、GitHub 发布 -- 多项目看板,进度一目了然 - -### 零配置,开箱即用 - -- 自动从 OpenClaw 环境读取 LLM 配置,无需手动填写 API Key -- 三档配置模式:极简(自动检测)/ 引导(3 步)/ 高级(完整自定义) -- 新建项目自动 `git init`,全流程自动 commit,封版自动打 tag - -### 可靠的开发流水线 +- 从自然语言需求生成可运行项目 +- 分析、写代码、审查、修复、最终审查一条链路推进 +- 支持本地运行、部署、封版、GitHub Release 发布 +- 多项目看板,进度可追踪 +- 写入前 dry-run 预览,路径写入限制在项目目录内 +- 支持 Codex 环境中的显式 API 配置和项目 `.env` -- **8 步自动化流程** — 需求分析 → 代码生成 → 逐任务审查 → 自动修复 → 9 维度综合审查 → 本地预览 → 部署上线 → 封版归档 -- **错误三层恢复** — 指数退避自动重试 + 检查点快照回滚 + 异常状态自动检测 -- **封版自动化** — 自动生成 CHANGELOG、创建下一版本目录、填充部署文档 -- **14 种错误类型** — 每种给出具体操作建议,不甩锅 - -### 智能体编排 - -- 支持本地 LLM / OpenClaw 子 agent 双模式,可独立配置 API 端点和模型 -- 一键发布 skill 到 ClawHub - -### 工程质量保障 - -- **设计系统规范** — 分析阶段自动生成色彩/字体/间距/组件/交互规范,UI 代码自动遵循 -- **React 最佳实践** — 自动遵循 Vercel 规范:并行请求、动态导入、大列表虚拟化、hydration 安全 -- **9 维度综合审查** — 代码质量、安全性、交互友好度、需求符合度、设计一致性、字段依赖、命名规范、React 性能、Web UI 质量 -- **使用说明书** — 每个项目自动生成面向最终用户的 USER_GUIDE.md - -### 安全与护栏 - -- 状态机推进,每一步都有记录 -- 写入前可预览(dry-run) -- 审查 / 修复闭环,避免越修越乱 -- 路径安全限制,不会写到项目外面 -- 部署信息脱敏,敏感数据不暴露 -- 主动调用需用户确认,不会无条件触发部署 - ---- +## 快速开始 -## 适合谁 +### 前置条件 -- **不会写代码但想把想法做出来的人** — 产品经理、运营、创业者、业务负责人 -- **会写代码但想提升效率的人** — 快速验证想法、标准化开发流程 -- **需要"流程可追踪"的团队** — 每一步都知道发生了什么,有版本记录可回溯 +- Codex CLI/Desktop 或支持 Codex skills 的运行环境 +- Python 3.10+ +- Node.js 18+(仅看板服务需要) +- 一个 OpenAI-compatible LLM API Key ---- +安装 Python 依赖: -## 工作流 - -```text -提需求 → 分析(含设计规范)→ 确认 → 生成代码(含使用说明)→ 逐任务审查 → 修复循环 → 综合审查(9 维度)→ 本地预览 → 部署 → 封版 → GitHub 发布 +```bash +pip install -r requirements.txt ``` -每一步都有状态,每一步都能继续 / 恢复,每一步都能被看见。 +### 安装到 Codex skills ---- - -## 快速开始 - -### 前置条件 - -- [OpenClaw](https://clawhub.com) 环境已安装 -- Python 3.10+ -- 一个 LLM API Key(Claude / OpenAI / Mimo 均可) - -### 1. 安装 +把本目录放到 Codex skills 目录中,目录名保持 `devtaskflow`: ```bash -clawhub install devtaskflow +mkdir -p ~/.codex/skills +cp -R /path/to/devtaskflow ~/.codex/skills/devtaskflow ``` -### 2. 配置(v1.0.0 零配置启动) +如果你是在这个仓库里开发或审查,可以直接在当前目录运行命令。 -v1.0.0 支持自动从 OpenClaw 配置中读取 LLM 设置,大部分情况下**无需手动配置**即可直接使用。 +### 配置 LLM -如需自定义: +推荐用项目 `.env` 或环境变量显式配置: ```bash -dtflow setup # 交互式配置(可选) +DTFLOW_LLM_BASE_URL=https://api.openai.com/v1 +DTFLOW_LLM_API_KEY=sk-... +DTFLOW_LLM_MODEL=<你的账号可用的模型 ID> ``` -### 3. 发起新项目 +也支持 Codex/OpenAI 常见变量: -在 OpenClaw 聊天中直接说: +```bash +OPENAI_API_KEY=sk-... +OPENAI_BASE_URL=https://api.openai.com/v1 +OPENAI_MODEL=<你的账号可用的模型 ID> +``` -> 新建一个项目,叫 crm-lite,我想做一个给销售团队用的客户管理工具。 +DevTaskFlow 不读取 Codex 会话或账号文件,避免隐式使用凭据。 -系统自动:创建项目 → 分析需求 → 生成设计规范 → 拆任务 → 写代码 → 审查 → 修复 → 综合审查 → 部署。 +### 发起新项目 -### 4. 查看进度 +在 Codex 中说: -> 看下项目进度 +> 用 `$devtaskflow` 新建一个项目,叫 crm-lite,我想做一个给销售团队用的客户管理工具。 -或者用可视化看板: +也可以直接运行: ```bash -dtflow board --serve # → http://localhost:8765 +dtflow start --new-project --name crm-lite --idea "给销售团队用的客户管理工具,需要录入客户、搜索、跟进状态、备注,界面简洁,手机也能用" ``` ---- - -## 常用操作 - -所有操作都通过自然语言完成。以下是一些示例: +## 常用命令 +```bash +dtflow setup +dtflow start --new-project --name NAME --idea "需求" +dtflow start +dtflow start --confirm +dtflow start --confirm-write +dtflow start --feedback "修改意见" +dtflow start --run +dtflow start --final-review +dtflow start --deploy +dtflow board +dtflow board --serve +dtflow board-query --name PROJECT +dtflow advanced publish --target github ``` -"帮我分析一下这个需求能不能做" → 启动需求分析 -"方案没问题,开始写代码" → 确认并生成代码 -"先别部署,我想看看效果" → 本地运行预览 -"可以了,上线吧" → 部署上线 -"发布到 GitHub" → 封版并创建 Release -"改成蓝色主题" → 反馈修改 -``` - ---- -## 安全与约束 +## 工作流 -- 写入路径限制在项目目录内 -- 配置和密钥走环境变量 / 本地配置 -- 部署信息脱敏显示(IP/域名模糊化) -- 主动调用需用户确认,不会无条件触发部署 -- 写入前可预览(dry-run) -- 审查与修复分阶段执行 -- 项目与版本分层管理 +```text +提需求 -> 分析(含设计规范)-> 确认 -> 生成代码 -> 逐任务审查 -> 修复循环 -> 综合审查 -> 本地预览 -> 部署 -> 封版 -> GitHub 发布 +``` ---- +每一步都有状态,每一步都能继续、恢复和查看。 ## 架构 ```text - OpenClaw / 自然语言交互层 - │ - ┌─────────┴─────────┐ - │ pipeline core │ 开发主流程(analyze → write → review → fix → comprehensive_review → deploy → seal) - │ orchestrator │ 调度层(本地 LLM / OpenClaw 子 agent) - │ state + board │ 项目状态与看板 - │ adapters │ 对接外部能力(LLM、部署、归档、GitHub) - └───────────────────┘ + Codex / 自然语言交互层 + | + +---------+---------+ + | pipeline core | analyze -> write -> review -> fix -> final_review -> deploy -> seal + | orchestrator | local_llm / codex_subagent + | state + board | 项目状态与看板 + | adapters | LLM、部署、归档、GitHub Release + +-------------------+ ``` ---- - -## 支持的模型 - -| 模型 | 说明 | -|------|------| -| Claude Opus 4.6 | 综合能力最强,推荐复杂项目 | -| GPT 5.4 Pro | OpenAI 旗舰,大型项目首选 | -| GPT 5.4 | 性价比高,适合中小项目 | -| 小米 Mimo V2 Pro | 国产模型,中文表现好 | +## 安全与约束 ---- +- 写入路径限制在项目目录内 +- 配置和密钥走环境变量或项目 `.env` +- 部署信息脱敏显示 +- 主动部署和发布前必须确认 +- 写入前可预览 +- 审查与修复分阶段执行 +- 项目与版本分层管理 ## 版本 -当前版本:**v1.0.0** — [查看完整更新日志](CHANGELOG.md) - ---- +当前版本:**v1.2.0-codex** — Codex skill migration. ## License diff --git a/SKILL.md b/SKILL.md index d1d257a..d1d2f01 100644 --- a/SKILL.md +++ b/SKILL.md @@ -1,219 +1,171 @@ --- -name: DevTaskFlow -version: 1.1.0 -description: 用自然语言发起开发任务,AI 驱动的开发流水线。Describe your idea, get working software. 适合产品、运营、业务人员从 0 搭建项目。 -metadata: - { - "openclaw": { - "requires": { - "python": ">=3.10", - "node": ">=18" - } - } - } -license: MIT-0 +name: devtaskflow +description: Use DevTaskFlow when a user wants to start, continue, govern, or release a tracked software project from plain-language requirements. Trigger for new app/tool/platform ideas, adding project memory and governance to an existing repo while continuing development, resuming a DevTaskFlow project, checking what stage a project is in, identifying missing requirements or blockers, running AI-assisted analysis/implementation/review/fix/preview/deploy flows, sealing a version, or publishing a generated project. Do not force DevTaskFlow for isolated one-off edits unless the user asks for project tracking, long-running goal work, governance, versioning, or release discipline. --- -# DevTaskFlow — Agent 使用手册 +# DevTaskFlow -## 什么时候用 +DevTaskFlow is a Codex skill plus CLI for running a software-development pipeline from natural language: requirements -> plan -> code -> review -> fixes -> final review -> local preview -> deploy -> release. -当用户表达以下意图时,**主动建议**使用本工具: +It also carries a light personal-project standard layer for durable project memory: `AGENTS.md`, `docs/project/`, `docs/process/`, `docs/decisions/`, `docs/versions/`, and `ops/` when deployment is in scope. -- "我想做一个 XXX 系统/工具/平台" -- "帮我开发一个 XXX" -- "我需要一个 XXX,功能是..." -- 用户描述了一个软件/系统需求 -- 用户问项目进展、想继续做、想看进度 +## Before Acting -**识别意图后,向用户建议使用本工具,但必须等用户确认后再执行。** 尤其是涉及代码生成、部署、发布等操作,不要在未经确认的情况下自动执行。 +- Use DevTaskFlow directly when the user explicitly asks for `$devtaskflow`, a tracked goal project, versioned development, governance, progress tracking, preview/deploy/release flow, or continuing an existing DevTaskFlow project. +- Suggest DevTaskFlow, then ask before creating files, when the request only implicitly looks like a long-running project or existing-repo governance task. +- Do not force DevTaskFlow for small one-off bug fixes, code reviews, refactors, or explanations unless the user asks to bring that work under project tracking. +- If the user's request is vague, first clarify only the missing decision that blocks the next stage, such as audience, core workflow, login/auth needs, data model, integrations, deployment target, or acceptance criteria. +- Run commands from the project root that contains `.dtflow/config.json`. For a new tracked project or an existing repo being brought under DevTaskFlow, `dtflow start --new-project` creates the structure. +- If Python dependencies are missing, install them with `pip install -r requirements.txt` from the DevTaskFlow skill directory. +- For personal long-running projects, multi-window work, subagent work, handoff memory, or version freeze, read `references/personal-project-standards.md` before deciding the project structure or release steps. +- Treat analyze, review, final review, and seal as standards-driven gates: do not skip missing non-goals, acceptance criteria, version docs, tests, deployment notes, or release-freeze blockers. +- Before `seal`, deploy, publish, commit, tag, or any command that produces release/git side effects, ask for explicit user authorization. -## Token 消耗参考 +## LLM Configuration -开发一个项目会消耗大量 token,提前告知用户: +DevTaskFlow calls an OpenAI-compatible `/chat/completions` endpoint. Configure one of these before running generation: -| 项目规模 | 预估 Token 消耗 | 示例 | -|---------|---------------|------| -| 小型 | 300-500 万 | 简单的个人工具、静态页面、小表单 | -| 中型 | ~4000 万 | 多页面管理后台、带数据库的应用、用户系统 | -| 大型 | 2 亿+ | 复杂业务系统、多角色权限、API 集成 | - -消耗取决于需求复杂度、迭代次数、审查修复次数。首次可先用小项目试水。 - -## 支持的模型 - -推荐模型:Claude Opus 4.6(复杂项目首选)、GPT 5.4(性价比高)、小米 Mimo V2 Pro(中文好)。完整列表和说明见 README.md。 - -## 编排模式 - -DevTaskFlow 支持两种编排模式,通过 `config.json` 的 `adapters.orchestration` 切换: - -### local_llm(默认) - -直接使用环境变量中的 LLM 配置: - -``` +```bash DTFLOW_LLM_BASE_URL=https://api.openai.com/v1 -DTFLOW_LLM_API_KEY=sk-xxx -DTFLOW_LLM_MODEL=gpt-4o +DTFLOW_LLM_API_KEY=sk-... +DTFLOW_LLM_MODEL= ``` -### openclaw_subagent +Codex-friendly fallbacks are also supported: -使用独立的 LLM 配置,与主 LLM 分离。适合在 OpenClaw 环境下使用不同模型处理开发任务。 +- `OPENAI_API_KEY`, `OPENAI_BASE_URL`, `OPENAI_MODEL` +- Project `.env` +- Optional independent orchestration variables: `DTFLOW_CODEX_BASE_URL`, `DTFLOW_CODEX_API_KEY`, `DTFLOW_CODEX_MODEL` -配置方式 A — `config.json` 的 `openclaw` 段: +Do not read or expose Codex account/session files. Ask the user to provide an explicit API key or environment variable when configuration is missing. -```json -{ - "adapters": { "orchestration": "openclaw_subagent" }, - "openclaw": { - "base_url": "https://api.example.com/v1", - "api_key": "sk-xxx", - "model": "claude-opus-4-6", - "timeout_seconds": 900 - } -} -``` - -配置方式 B — 环境变量: - -``` -DTFLOW_OPENCLAW_BASE_URL=https://api.example.com/v1 -DTFLOW_OPENCLAW_API_KEY=sk-xxx -DTFLOW_OPENCLAW_MODEL=claude-opus-4-6 -``` - -如果 `config.json` 中字段为空,自动 fallback 到环境变量。 - -## 核心命令 +## Core Commands ```bash -dtflow setup # 配置 AI 服务(交互式) -dtflow start --new-project --name NAME --idea "需求" # 开始新项目 -dtflow start # 继续上次进度 -dtflow start --confirm # 确认分析方案,开始生成代码(先预览,用户确认后再写入) -dtflow start --confirm-write # 在预览确认后,正式执行代码写入 -dtflow start --feedback "修改意见" # 提出修改 -dtflow start --run # 本地预览 -dtflow start --deploy # 部署上线并封版 -dtflow start --final-review # 执行上线前综合审查(9 维度) -dtflow start --deploy-skip-review # 跳过综合审查直接部署(仅在用户明确要求跳过或时间紧迫时使用,建议默认走完整审查流程) -dtflow board # 所有项目状态(文字) -dtflow board --serve # 启动可视化看板服务 -dtflow board-query --name PROJECT # 单个项目详情(文字) -dtflow advanced publish --target github # 发布到 GitHub Releases -dtflow advanced publish --target clawhub # 发布到 ClawHub +dtflow setup +dtflow start --new-project --name NAME --idea "需求" +dtflow start +dtflow start --confirm +dtflow start --confirm-write +dtflow start --feedback "修改意见" +dtflow start --run +dtflow start --final-review +dtflow start --deploy +dtflow board +dtflow board --serve +dtflow board-query --name PROJECT +dtflow advanced publish --target github ``` -## 工作流程 - -### 用户提出新需求 - -**如果用户有明确需求描述**(比如"我想做一个客户管理工具"): -1. `dtflow start --new-project --name 项目名 --idea "用户的需求原文"` -2. 系统创建项目、给出补充建议 -3. 向用户展示建议,问是否要补充 -4. 确认后自动 analyze → 展示任务列表 -5. `dtflow start --confirm` → 自动 write(先预览)→ review → fix → review -6. 全部任务通过后 → **建议先 compact 一次**(减少上下文累积导致的幻觉)— 提醒主 agent 使用 `/compact` 或清理上下文后再执行综合审查 → 综合审查(`dtflow start --final-review`)— 9 维度全面检查 -7. 综合审查通过 → `dtflow start --run` 本地预览 -8. 用户确认没问题 → `dtflow start --deploy` - -**如果用户需求模糊**(比如"我想做个东西管理客户信息"): -1. 不要直接调用 dtflow,先通过对话引导收集需求 -2. 问清楚: - - 给谁用的?(团队/客户/个人) - - 最核心的功能是什么? - - 需要登录吗? - - 有技术偏好吗?(不知道就帮你选) -3. 收集到足够信息后,拼成需求调用 dtflow start - -### 用户想本地预览 - -1. `dtflow start --run` -2. 返回访问链接给用户 - -### 用户想看项目进展 - -1. 检查看板服务是否在运行(`curl -s http://localhost:8765 > /dev/null && echo "running" || echo "stopped"`) -2. 如果在运行 → 发链接 -3. 如果不在运行 → `dtflow board` 文字版 - -### 用户问某个项目详情 - -1. `dtflow board-query --name 项目名` -2. 把文字结果发给用户 - -### 用户想继续之前的项目 - -1. `dtflow start`(不加参数,自动继续) -2. 根据输出告知用户当前阶段 - -### 用户想发布 - -**发布到 GitHub:** -1. 确保项目已封版(sealed)或已部署(deployed) -2. 确保已安装 `gh` CLI 并登录 -3. `dtflow advanced publish --target github` - -**发布到 ClawHub:** -1. 确保项目已封版或已部署 -2. 确保已安装 `clawhub` CLI 并登录 -3. 确保项目根目录有 `SKILL.md` -4. `dtflow advanced publish --target clawhub` - -### 首次使用(环境未配置) - -1. `dtflow setup` 交互式引导(含 AI 配置 + 部署方式选择) -2. 非交互环境下手动创建 `.env`: - ``` - DTFLOW_LLM_BASE_URL=... - DTFLOW_LLM_API_KEY=... - DTFLOW_LLM_MODEL=... - ``` - -## 状态机 - -`dtflow start` 自动推进,你只需知道阶段: - -| 状态 | 含义 | 你该说什么 | -|------|------|-----------| -| created | 刚创建 | "项目已创建,正在分析需求..." | -| pending_confirm | 方案已出 | "我分析了你的需求,建议做这几件事:..." | -| confirmed | 已确认 | "好的,开始生成代码..." | -| writing/written | 代码已生成 | "代码写好了,我在检查..." | -| needs_fix | 有问题 | "发现几个小问题,已修复:..." | -| review_passed | 审查通过 | "代码没问题了,要本地先看看效果吗?" | -| pending_final_review | 综合审查待执行 | "运行 dtflow start --final-review 执行综合审查,或 --deploy-skip-review 跳过" | -| ready_to_deploy | 综合审查通过 | "可以部署了,运行 dtflow start --deploy" | -| needs_final_fix | 综合审查发现问题 | "运行 dtflow start 自动修复并重新审查" | -| sealed | 已封版 | "上线完成!" | - -## 向用户展示什么 - -**不要暴露:** analyze、DEV_PLAN.md、orchestration、config.json、.state.json、token 数 -**应该说:** "我分析了需求"、"代码已生成"、"检查过了没问题"、"可以部署了" - -## 注意事项 - -- `dtflow setup` 是交互式命令,在非交互环境不可用 -- 所有命令在项目根目录运行,项目根目录是包含 `.dtflow/config.json` 的目录,可通过 `ls .dtflow/config.json` 确认 -- board 的 Node.js 应用需要 `npm install`(首次自动执行) -- 看板服务默认端口 8765,**仅限本地使用,不要暴露到公网** -- board API 已脱敏:不返回 host/user/path 等敏感部署信息 -- `run` 本地预览需要项目有可执行的启动命令(npm start / python app.py 等) -- Docker 部署需要本地安装 Docker -- `openclaw_subagent` 编排器需要在 `config.json` 或环境变量中配置独立的 LLM 连接信息 - -### 常见问题处理 +## Entry Modes -- **dtflow 命令报错**: 检查是否在项目根目录(含 `.dtflow/config.json`)、模型 API Key 是否有效、余额是否充足 -- **部署失败**: 检查 Docker/SSH 连接、目标服务器权限、config.json 中的 deploy 配置 -- **审查反复不通过**: 检查是否有结构性问题(如框架选择不当),必要时让用户给出报错信息手动排查 -- **run 启动失败**: 检查项目启动命令(`npm start` / `python app.py`)、依赖是否安装完整 - -### 边界场景 +### New Tracked Project + +Use this when the user wants to build a new app, tool, internal system, dashboard, automation, SDK, script, or platform as a tracked goal. -- **用户想取消项目**: 归档项目(状态设为 archived)但不删除文件,保留以便后续恢复 -- **用户中途改需求**: 如果是小调整 → 用 `dtflow start --feedback "修改意见"` 在当前版本迭代;如果是大方向变更 → 建议新建版本(`dtflow advanced version --new`) +1. Run `dtflow start --new-project --name NAME --idea "user's original requirement"`. +2. Confirm the project skeleton includes `AGENTS.md`, stable project docs, process docs, decisions, and `docs/versions/`. +3. Show the generated requirement suggestions and ask whether the user wants to add anything. +4. Continue with `dtflow start --confirm` after the user approves the plan. +5. Use `dtflow start --confirm-write` after previewing the write plan. +6. Let DevTaskFlow run review/fix loops until task review passes. +7. Run `dtflow start --final-review` before deployment unless the user explicitly asks to skip it. +8. Run `dtflow start --run` for local preview and give the local URL to the user. +9. Deploy only after the user confirms the preview. + +### Existing Repo Governance And Development + +Use this when the user has an existing project and wants DevTaskFlow to add structure, memory, version discipline, or goal-driven development while continuing real implementation work. + +1. Inspect the repo first: read `AGENTS.md` if present, existing README/docs, package files, test/build commands, and current git status. +2. If `.dtflow/config.json` is missing, ask before adding DevTaskFlow files, then run `dtflow start --new-project --path /absolute/repo/path --name NAME --idea "governance and development goal"`. +3. Keep existing project conventions as the source of truth; DevTaskFlow docs should record and organize them, not replace them. +4. Fill or flag gaps in `docs/project/`, `docs/process/`, `docs/versions/`, and `AGENTS.md`: purpose, target users, core workflow, non-goals, acceptance criteria, commands, risks, deployment notes, and rollback method. +5. Continue with the same staged workflow as a new project: analyze, confirm, preview write plan, implement, review, fix, final review, preview, deploy, and seal when authorized. + +### Existing DevTaskFlow Project + +Use this when `.dtflow/config.json` already exists or the user asks to continue/check progress. + +- To continue the current project, run `dtflow start`. +- To add a small change request, run `dtflow start --feedback "user feedback"`. +- For major scope changes, do not overwrite the current version. Ask whether to finish/seal the current version first, use the already-created next version after sealing, or start a separate tracked project. +- To inspect progress, use `dtflow board` or `dtflow board-query --name PROJECT`. +- For sealed versions, treat new scope as the next version unless the user explicitly asks for a patch or erratum. + +## Stage Orientation + +When entering an existing DevTaskFlow project, orient before acting: + +1. Find the project root with `.dtflow/config.json`. +2. Run `dtflow advanced status` from the project root, or `dtflow board-query --name PROJECT` from the workspace. +3. Read `AGENTS.md`, current `docs/project/` files, current `docs/versions//docs/REQUIREMENTS.md`, and current review/final-review docs when present. +4. Check `.state.json` only as internal state. Use it to identify `status`, `current_task`, `tasks`, `last_summary`, and `last_error`, but do not expose raw state files to the user. +5. Report the current stage, the next useful action, and any missing blockers in plain language. + +## Stage Actions + +| State | Meaning | Default action | +| --- | --- | --- | +| `initialized` / `created` | Project or version exists, requirements may be incomplete | Collect or add the version goal, target users, core workflow, scope, non-goals, and acceptance criteria; then run `dtflow start`. | +| `pending_confirm` | Analysis plan is ready | Summarize plan and gaps; run `dtflow start --confirm` only after approval, or `dtflow start --feedback "..."` for changes. | +| `confirmed` | Plan is approved | Run `dtflow start` to preview the write plan. | +| `writing` / `written` | Code generation is underway or just completed | Let review continue with `dtflow start`; summarize files and next review stage. | +| `reviewing` | Task review is underway | Wait or continue with `dtflow start`; do not deploy yet. | +| `needs_fix` / `fixing` | Review found issues | Run `dtflow start` to fix and re-review; surface blocker themes without dumping raw review files. | +| `review_passed` | A task or all tasks passed review | Run `dtflow start` to move to the next task; if no tasks remain, prepare final review. | +| `pending_final_review` | All task reviews passed; final review is next | Recommend context compaction if needed, then run `dtflow start --final-review`. | +| `ready_to_deploy` | Final review passed | Offer local preview with `dtflow start --run`; deploy only after user confirmation. | +| `needs_final_fix` | Final review found blockers | Run `dtflow start` to fix final-review issues; report missing tests, docs, deployment notes, or acceptance gaps. | +| `deployed` / `all_done` | Deployment or all work is complete | Offer seal/release-freeze; run seal only after explicit authorization. | +| `sealed` | Version is finalized | Treat new scope as a new version, patch, or erratum based on user intent. | +| `failed` | Last action failed | Run `dtflow advanced status` and, if needed, `dtflow advanced doctor` or `dtflow advanced recover`; explain `last_error` plainly. | + +## Missing Context To Surface + +Always surface missing context when it affects the next stage: + +- Product: version goal, target users, core workflow, functional scope, non-goals, data scope, acceptance criteria. +- Engineering: stack, existing conventions, typecheck/test/build commands, important error paths, migration needs. +- Design: target device sizes, density, key screens, empty/error states, copy quality, usability risks. +- Operations: deployment target, build artifact, deploy method, preview URL, verification, rollback method. +- Release: unresolved P0/P1 tasks, placeholders, failed checks, dirty git status, missing changelog, unapproved commit/tag/publish steps. + +## Personal Project Standard + +- Keep stable project facts in `docs/project/`; keep version facts in `docs/versions/`; keep cross-version decisions in `docs/decisions/`. +- Treat `AGENTS.md` as the project-level collaboration contract and reading map. Do not put private machine paths, secrets, temporary prompts, or one-person-only preferences there. +- During analysis, require a version goal, target users, core workflow, functional scope, explicit non-goals, data scope, acceptance criteria, risks, and dependencies. +- During review, include product copy quality, design usability, development tests, observable error paths, and deployment readiness when relevant. +- When the user says "封版", run the release-freeze checks before commit, tag, deployment archive, or release publishing; blockers must be fixed or explicitly moved into an accepted patch/erratum flow. + +## Status Language + +Translate internal states into user-facing language: + +| State | Meaning | User-facing summary | +| --- | --- | --- | +| `initialized` / `created` | Project/version created | "项目已创建,正在补齐目标和需求。" | +| `pending_confirm` | Plan ready | "方案已生成,等你确认或补充。" | +| `confirmed` | Approved | "已确认,开始生成代码。" | +| `writing` / `written` | Code generation underway/done | "代码已生成,我在审查。" | +| `needs_fix` | Review found issues | "发现问题,正在修复并复审。" | +| `review_passed` | Task review passed | "任务级审查通过,可以做最终审查。" | +| `ready_to_deploy` | Final review passed | "最终审查通过,可以预览或部署。" | +| `needs_final_fix` | Final review failed | "最终审查发现问题,需要修复。" | +| `failed` | Last action failed | "上一步失败,我会先定位原因和可恢复路径。" | +| `sealed` | Version finalized | "版本已封版。" | + +## What To Show + +- Show concise progress, decisions, preview URLs, review summaries, and next steps. +- Avoid exposing implementation internals such as `DEV_PLAN.md`, `.state.json`, raw orchestration payloads, hidden config files, API keys, or token counts. +- For failures, summarize the likely cause and next command to try. Use `dtflow advanced doctor` for environment diagnostics. + +## Notes + +- `dtflow setup` is interactive; in non-interactive Codex work, prefer writing `.env` only when the user has explicitly provided credentials. +- The board server is local-only and defaults to port `8765`. +- `dtflow start --deploy` currently deploys and then seals through auto-advance. Treat it as a release action that needs explicit authorization, not as a lightweight preview. +- Docker deployment requires Docker. GitHub release publishing requires `gh` to be installed and authenticated. +- `codex_subagent` is an optional OpenAI-compatible orchestration mode configured through the `codex` block; `local_llm` remains the default. diff --git a/agents/openai.yaml b/agents/openai.yaml new file mode 100644 index 0000000..140ee49 --- /dev/null +++ b/agents/openai.yaml @@ -0,0 +1,7 @@ +interface: + display_name: "DevTaskFlow" + short_description: "Track, govern, and ship software projects." + default_prompt: "Use $devtaskflow to start or continue a tracked software project with governance, review checkpoints, and version memory." + +policy: + allow_implicit_invocation: true diff --git a/board/server.js b/board/server.js index 209ed4a..390c6f6 100644 --- a/board/server.js +++ b/board/server.js @@ -9,7 +9,7 @@ const WORKSPACE = process.env.DTFLOW_WORKSPACE || process.cwd(); const PORT = process.env.DTFLOW_BOARD_PORT || 8765; function loadProjects() { - // 优先从 PROJECTS.md 注释中的 JSON 加载(与 Python 端一致) + // 优先从 PROJECTS.md 项目索引注释中的 JSON 加载(与 Python 端一致) const mdFile = path.join(WORKSPACE, 'PROJECTS.md'); if (fs.existsSync(mdFile)) { try { @@ -25,7 +25,7 @@ function loadProjects() { } } } catch (e) { - console.warn('⚠️ 解析 PROJECTS.md 失败,尝试 fallback 到 PROJECTS.json:', e.message); + console.warn('⚠️ 解析 PROJECTS.md 项目索引失败,尝试 fallback 到 PROJECTS.json:', e.message); } } // fallback: 读取 PROJECTS.json diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index e84a293..573c863 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -2,7 +2,7 @@ ## 产品边界(当前) -- ClawHub:仅用于分发 DevTaskFlow skill 本身 +- Codex skills:用于分发和触发 DevTaskFlow skill 本身 - GitHub:用于被 DevTaskFlow 管理项目的封版发布 - dashboard:仅作为项目总览页,不承担复杂项目管理能力 - analyze:输出架构与实施方案,不做工时估算/排期管理 @@ -26,12 +26,12 @@ CLI (dtflow) │ └── seal ├── orchestrator │ ├── local_llm - │ └── openclaw_subagent + │ └── codex_subagent └── adapters ├── llm adapter ├── deploy adapter ├── archive adapter - └── openclaw adapter + └── codex adapter ``` ## 当前实现状态(v0.1) @@ -40,10 +40,10 @@ CLI (dtflow) - `orchestrator.py` 作为统一编排入口 - `orchestrators/local_llm.py` 承接 `analyze / write / review / fix` -- `orchestrators/openclaw_subagent.py` 作为 OpenClaw 子 agent 统一接口占位适配器 +- `orchestrators/codex_subagent.py` 作为 Codex 子任务统一接口适配器 - `analyze.py / write_flow.py / review_flow.py / fix_flow.py` 已切换为通过 orchestrator 调度 - prompts 已外置到 `prompts/` -- 新增 `openclaw_bridge.py`,负责构造未来真实 OpenClaw 请求描述 +- 新增 `codex_bridge.py`,负责构造 Codex 子任务请求描述 - 新增 `result_schema.py / result_parser.py`,提供 JSON-first 协议基础层 - `write_flow.py` 已增加路径安全校验,防止写出项目目录 - `status` 可查看 `last_action / last_result_format / last_summary / last_error` @@ -52,7 +52,7 @@ CLI (dtflow) 当前尚未完成: -- OpenClaw `sessions_spawn` 的真实接线 +- Codex 子任务真实调度接线 - 结果渲染层与协议层进一步分离 - FILE block / Markdown fallback 继续退场 - 更完整的 failed / resume / async 恢复体系 @@ -60,9 +60,9 @@ CLI (dtflow) ## 设计原则 ### 1. Core / Adapter / Orchestrator 分离 -- 核心流程不直接绑定 OpenClaw -- OpenClaw 子 agent 协作作为可选 orchestrator / adapter 存在 -- 本地 LLM 模式与 OpenClaw 模式可切换 +- 核心流程不直接绑定 Codex 运行时内部 API +- Codex 子任务协作作为可选 orchestrator / adapter 存在 +- 本地 LLM 模式与 Codex 子任务模式可切换 ### 2. 安全优先 - API Key 禁止硬编码 @@ -71,7 +71,7 @@ CLI (dtflow) ### 3. 项目先于版本 - 每次开发任务必须先绑定到一个 project -- project 需要进入当前工作区的总看板(PROJECTS.md) +- project 需要进入当前工作区的项目索引(PROJECTS.md) - 然后才能启动具体版本迭代 ### 4. 项目自描述 @@ -85,7 +85,7 @@ CLI (dtflow) ## 下一步演进 ### v0.2 -- OpenClaw 子 agent 真实调度 +- Codex 子任务真实调度 - deploy / seal / publish 进一步 adapter 化 - renderer 层独立 - 更强的 async / resume 能力 diff --git a/docs/B2_IMPLEMENTATION_PLAN.md b/docs/B2_IMPLEMENTATION_PLAN.md index 45e760b..bdc29d1 100644 --- a/docs/B2_IMPLEMENTATION_PLAN.md +++ b/docs/B2_IMPLEMENTATION_PLAN.md @@ -35,14 +35,14 @@ - [x] deploy adapters(shell / ssh_shell / docker) - [x] archive adapter(本地归档) - [x] GitHub publish adapter(tag + release) -- [x] OpenClaw orchestration adapter(v0.8.0 完善) -- [x] ClawHub publish adapter(v0.8.0 新增) +- [x] Codex orchestration adapter(v1.2.0 迁移) +- [x] GitHub publish adapter(v0.8.0 新增) ## Phase 5 ✅ 文档与示例 - [x] README 完善 - [x] 示例项目骨架 -- [x] 安装方式文档(clawhub install) +- [x] Codex skill 安装方式文档 - [x] 迁移指南(dev-pipeline → DevTaskFlow) ## 设计决策 @@ -50,7 +50,7 @@ 1. 项目配置目录采用 `.dtflow/` 2. 命令名采用 `dtflow` 3. 敏感配置全部走环境变量 -4. OpenClaw 协作作为 adapter,而不是核心硬依赖 +4. Codex 协作作为 adapter,而不是核心硬依赖 5. 旧版 dev-pipeline 不直接硬改,采用新目录重建 -6. 编排器统一走 OpenAI compatible API,不依赖 OpenClaw 运行时 +6. 编排器统一走 OpenAI compatible API,不依赖 Codex 运行时内部 API 7. 部署信息脱敏显示,安全合规 diff --git a/example-project/.dtflow/config.json b/example-project/.dtflow/config.json index c890bc6..68b7039 100644 --- a/example-project/.dtflow/config.json +++ b/example-project/.dtflow/config.json @@ -23,11 +23,13 @@ "orchestration": "local_llm", "publish": "github" }, - "openclaw": { - "agent_id": "skill-runner", + "codex": { + "base_url": "", + "api_key": "", + "model": "", + "agent_id": "codex-skill-runner", "mode": "run", - "timeout_seconds": 900, - "model": "Opus" + "timeout_seconds": 900 }, "deploy": { "build_command": "", diff --git a/landing/index.html b/landing/index.html index 7281ba0..da9ce90 100644 --- a/landing/index.html +++ b/landing/index.html @@ -89,12 +89,12 @@ box-shadow: 0 8px 24px rgba(240, 246, 252, 0.15); } - .btn-clawhub { + .btn-codex { background: transparent; color: #bc8cff; border: 2px solid #bc8cff; } - .btn-clawhub:hover { + .btn-codex:hover { background: rgba(188, 140, 255, 0.1); transform: translateY(-2px); box-shadow: 0 8px 24px rgba(188, 140, 255, 0.15); @@ -213,16 +213,16 @@

DevTaskFlow

GitHub - + - ClawHub + Codex Skill
- $ npm install -g devtaskflow + $ git clone https://github.com/cwyhkyochen-a11y/devtaskflow ~/.codex/skills/devtaskflow
diff --git a/lib/cli.py b/lib/cli.py index 6e6dc39..4666fb2 100644 --- a/lib/cli.py +++ b/lib/cli.py @@ -406,7 +406,7 @@ def cmd_advanced(args): print(' dtflow advanced fix 手动修复问题') print(' dtflow advanced deploy 手动部署') print(' dtflow advanced seal 手动封版') - print(' dtflow advanced publish 发布到 GitHub / ClawHub') + print(' dtflow advanced publish 发布到 GitHub Releases') print(' dtflow advanced rollback 回滚到检查点') print(' dtflow advanced recover 自动检测修复状态异常') print(' dtflow advanced next-version 计算下一个版本号') @@ -966,8 +966,8 @@ def main(): p_adv_seal = advanced_sub.add_parser('seal', help='手动封版') p_adv_seal.set_defaults(func=cmd_adv_seal) - p_adv_publish = advanced_sub.add_parser('publish', help='发布到 GitHub / ClawHub') - p_adv_publish.add_argument('--target', default='github', choices=['github', 'clawhub']) + p_adv_publish = advanced_sub.add_parser('publish', help='发布到 GitHub Releases') + p_adv_publish.add_argument('--target', default='github', choices=['github']) p_adv_publish.add_argument('--allow-dirty', action='store_true') p_adv_publish.add_argument('--force-tag', action='store_true') p_adv_publish.add_argument('--replace-release', action='store_true') diff --git a/lib/codex_bridge.py b/lib/codex_bridge.py new file mode 100644 index 0000000..5efd47c --- /dev/null +++ b/lib/codex_bridge.py @@ -0,0 +1,11 @@ +def build_codex_request(config: dict, action: str, payload: dict) -> dict: + codex = config.get('codex', {}) + return { + 'runtime': 'subagent', + 'agent_id': codex.get('agent_id', ''), + 'mode': codex.get('mode', 'run'), + 'model': codex.get('model', ''), + 'timeout_seconds': codex.get('timeout_seconds', 900), + 'action': action, + 'payload': payload, + } diff --git a/lib/codex_config.py b/lib/codex_config.py new file mode 100644 index 0000000..7590434 --- /dev/null +++ b/lib/codex_config.py @@ -0,0 +1,88 @@ +"""Detect Codex/OpenAI-compatible LLM settings for DevTaskFlow.""" +import os +from pathlib import Path + + +def _parse_env_file(env_path: Path) -> dict: + result = {} + try: + for line in env_path.read_text(encoding='utf-8').splitlines(): + line = line.strip() + if not line or line.startswith('#') or '=' not in line: + continue + key, _, value = line.partition('=') + result[key.strip()] = value.strip().strip('"').strip("'") + except Exception: + pass + return result + + +def _first(*values: str) -> str: + for value in values: + if value: + return value.strip() + return '' + + +def _guess_base_url(model: str) -> str: + return 'https://api.openai.com/v1' + + +def detect_codex_llm(project_root: Path | None = None) -> dict: + """Return {base_url, api_key, model, source} for Codex-friendly execution. + + DevTaskFlow intentionally does not read Codex account/session files. Use an + explicit project .env or process environment variables so credentials remain + visible to the user and easy to rotate. + """ + env = os.environ + file_cfg = {} + if project_root: + file_cfg = _parse_env_file(project_root / '.env') + else: + cwd_env = Path.cwd() / '.env' + if cwd_env.exists(): + file_cfg = _parse_env_file(cwd_env) + + base_url = _first( + env.get('DTFLOW_LLM_BASE_URL', ''), + env.get('DTFLOW_CODEX_BASE_URL', ''), + file_cfg.get('DTFLOW_LLM_BASE_URL', ''), + file_cfg.get('DTFLOW_CODEX_BASE_URL', ''), + env.get('OPENAI_BASE_URL', ''), + file_cfg.get('OPENAI_BASE_URL', ''), + ).rstrip('/') + api_key = _first( + env.get('DTFLOW_LLM_API_KEY', ''), + env.get('DTFLOW_CODEX_API_KEY', ''), + file_cfg.get('DTFLOW_LLM_API_KEY', ''), + file_cfg.get('DTFLOW_CODEX_API_KEY', ''), + env.get('OPENAI_API_KEY', ''), + file_cfg.get('OPENAI_API_KEY', ''), + ) + model = _first( + env.get('DTFLOW_LLM_MODEL', ''), + env.get('DTFLOW_CODEX_MODEL', ''), + file_cfg.get('DTFLOW_LLM_MODEL', ''), + file_cfg.get('DTFLOW_CODEX_MODEL', ''), + env.get('OPENAI_MODEL', ''), + file_cfg.get('OPENAI_MODEL', ''), + ) + + source = '未配置' + if env.get('DTFLOW_LLM_API_KEY') or env.get('DTFLOW_CODEX_API_KEY'): + source = 'DevTaskFlow 环境变量' + elif file_cfg.get('DTFLOW_LLM_API_KEY') or file_cfg.get('DTFLOW_CODEX_API_KEY'): + source = '项目 .env' + elif env.get('OPENAI_API_KEY') or file_cfg.get('OPENAI_API_KEY'): + source = 'OpenAI 环境变量' + + if api_key and model and not base_url: + base_url = _guess_base_url(model) + + return { + 'base_url': base_url, + 'api_key': api_key, + 'model': model, + 'source': source, + } diff --git a/lib/doctor.py b/lib/doctor.py index 27e28b3..3150e66 100644 --- a/lib/doctor.py +++ b/lib/doctor.py @@ -15,15 +15,15 @@ def run_doctor(start: Path | None = None): else: checks.append(('project_root', False, '未找到 .dtflow/config.json')) - # LLM 检查:优先检测 OpenClaw 配置 + # LLM 检查:优先检测 Codex/OpenAI-compatible 配置 try: - from openclaw_config import detect_openclaw_llm - oc = detect_openclaw_llm() + from codex_config import detect_codex_llm + oc = detect_codex_llm(root) has_llm = bool(oc.get('base_url') and oc.get('api_key') and oc.get('model')) - llm_source = 'OpenClaw 自动配置' if has_llm else os.getenv('DTFLOW_LLM_BASE_URL') and '环境变量' or '未配置' + llm_source = oc.get('source', 'Codex/OpenAI 环境变量') if has_llm else os.getenv('DTFLOW_LLM_BASE_URL') and '环境变量' or '未配置' except Exception: has_llm = bool(os.getenv('DTFLOW_LLM_BASE_URL')) - llm_source = '环境变量' if has_llm else '未配置(openclaw_config 导入失败)' + llm_source = '环境变量' if has_llm else '未配置(codex_config 导入失败)' checks.append(('llm', has_llm, f'LLM 服务 ({llm_source})')) return checks diff --git a/lib/llm.py b/lib/llm.py index ce1ac9f..7ce8035 100644 --- a/lib/llm.py +++ b/lib/llm.py @@ -8,16 +8,16 @@ class LLMError(Exception): class OpenAICompatibleLLM: def __init__(self, config: dict): - from openclaw_config import detect_openclaw_llm + from codex_config import detect_codex_llm llm = config.get('llm', {}) self.base_url = os.getenv(llm.get('base_url_env', 'DTFLOW_LLM_BASE_URL'), '').rstrip('/') self.api_key = os.getenv(llm.get('api_key_env', 'DTFLOW_LLM_API_KEY'), '') self.model = os.getenv(llm.get('model_env', 'DTFLOW_LLM_MODEL'), '') - # Fallback: 自动从 OpenClaw 配置读取 + # Fallback: Codex-friendly env/project .env detection. if not all([self.base_url, self.api_key, self.model]): - oc = detect_openclaw_llm() + oc = detect_codex_llm() if not self.base_url: self.base_url = oc.get('base_url', '') if not self.api_key: diff --git a/lib/openclaw_bridge.py b/lib/openclaw_bridge.py deleted file mode 100644 index 38e4621..0000000 --- a/lib/openclaw_bridge.py +++ /dev/null @@ -1,14 +0,0 @@ -from pathlib import Path - - -def build_openclaw_request(config: dict, action: str, payload: dict) -> dict: - openclaw = config.get('openclaw', {}) - return { - 'runtime': 'subagent', - 'agent_id': openclaw.get('agent_id', ''), - 'mode': openclaw.get('mode', 'run'), - 'model': openclaw.get('model', ''), - 'timeout_seconds': openclaw.get('timeout_seconds', 900), - 'action': action, - 'payload': payload, - } diff --git a/lib/openclaw_config.py b/lib/openclaw_config.py deleted file mode 100644 index d97f2b5..0000000 --- a/lib/openclaw_config.py +++ /dev/null @@ -1,73 +0,0 @@ -"""从 OpenClaw 配置自动读取 LLM 设置""" -import json -import os -from pathlib import Path - - -def _load_openclaw_config() -> dict: - config_path = Path.home() / '.openclaw' / 'openclaw.json' - if not config_path.exists(): - return {} - try: - return json.loads(config_path.read_text(encoding='utf-8')) - except Exception as e: - print(f'⚠️ openclaw_config: 读取配置文件失败: {e}') - return {} - - -def _read_api_key(provider: str) -> str: - """从 ~/.openclaw/credentials/ 读取 API Key""" - cred_dir = Path.home() / '.openclaw' / 'credentials' - # 尝试 {provider}:default.api - for suffix in [f'{provider}:default.api', f'{provider}.api']: - cred_file = cred_dir / suffix - if cred_file.exists(): - try: - return cred_file.read_text(encoding='utf-8').strip() - except Exception as e: - print(f'⚠️ 读取凭据文件 {cred_file} 失败: {e}') - continue - return '' - - -def detect_openclaw_llm() -> dict: - """自动检测 OpenClaw 的 LLM 配置,返回 {base_url, api_key, model}。 - 任一字段获取失败则对应值为空字符串。 - """ - cfg = _load_openclaw_config() - if not cfg: - return {'base_url': '', 'api_key': '', 'model': ''} - - # 1. 获取主模型 (如 "openrouter/xiaomi/mimo-v2-pro") - primary = cfg.get('agents', {}).get('defaults', {}).get('model', {}).get('primary', '') - if not primary: - return {'base_url': '', 'api_key': '', 'model': ''} - - # 2. 解析 provider 名 - # 格式: "provider/model-id" 或 "provider/sub-provider/model-id" - parts = primary.split('/') - providers = cfg.get('models', {}).get('providers', {}) - - # 3. 在 providers 中查找匹配的 baseUrl - base_url = '' - api_key = '' - model_id = parts[-1] if parts else primary - - # 尝试从最长到最短的 provider 名匹配 - for i in range(len(parts) - 1, 0, -1): - provider_name = '/'.join(parts[:i]) - if provider_name in providers: - base_url = providers[provider_name].get('baseUrl', '').rstrip('/') - api_key = _read_api_key(provider_name) - break - - # 如果没找到,尝试第一个部分作为 provider - if not base_url and parts and parts[0] in providers: - base_url = providers[parts[0]].get('baseUrl', '').rstrip('/') - api_key = _read_api_key(parts[0]) - - return { - 'base_url': base_url, - 'api_key': api_key, - 'model': model_id or primary, - } diff --git a/lib/orchestrator.py b/lib/orchestrator.py index a84d453..9020f20 100644 --- a/lib/orchestrator.py +++ b/lib/orchestrator.py @@ -15,11 +15,11 @@ def get_orchestrator(config: dict): except ImportError as e: raise OrchestratorError(f'无法导入 LocalLLMOrchestrator: {e}。请检查 orchestrators/local_llm.py 是否存在。') return LocalLLMOrchestrator(config) - if mode == 'openclaw_subagent': + if mode == 'codex_subagent': try: - from orchestrators.openclaw_subagent import OpenClawSubagentOrchestrator + from orchestrators.codex_subagent import CodexSubagentOrchestrator except ImportError as e: - raise OrchestratorError(f'无法导入 OpenClawSubagentOrchestrator: {e}。请检查 orchestrators/openclaw_subagent.py 是否存在。') - return OpenClawSubagentOrchestrator(config) + raise OrchestratorError(f'无法导入 CodexSubagentOrchestrator: {e}。请检查 orchestrators/codex_subagent.py 是否存在。') + return CodexSubagentOrchestrator(config) raise OrchestratorError(f'不支持的 orchestration 模式: {mode}') diff --git a/lib/orchestrators/openclaw_subagent.py b/lib/orchestrators/codex_subagent.py similarity index 85% rename from lib/orchestrators/openclaw_subagent.py rename to lib/orchestrators/codex_subagent.py index e14f448..fb94ef5 100644 --- a/lib/orchestrators/openclaw_subagent.py +++ b/lib/orchestrators/codex_subagent.py @@ -43,32 +43,32 @@ def parse_file_blocks(code_result: str): return files -class _OpenClawLLM: - """OpenClaw 编排器专用的 LLM 调用器。 +class _CodexTaskLLM: + """Codex skill 编排器专用的 LLM 调用器。 - 从 config.openclaw 读取 base_url / api_key / model。 + 从 config.codex 读取 base_url / api_key / model。 不依赖环境变量(除非配置中未指定 fallback 时才读 env)。 """ def __init__(self, config: dict): - from openclaw_config import detect_openclaw_llm + from codex_config import detect_codex_llm - ocfg = config.get('openclaw', {}) - self.base_url = ocfg.get('base_url', '').rstrip('/') - self.api_key = ocfg.get('api_key', '') - self.model = ocfg.get('model', '') + ccfg = config.get('codex', {}) + self.base_url = ccfg.get('base_url', '').rstrip('/') + self.api_key = ccfg.get('api_key', '') + self.model = ccfg.get('model', '') # fallback: 也支持从环境变量读取 if not self.base_url: - self.base_url = os.getenv('DTFLOW_OPENCLAW_BASE_URL', '').rstrip('/') + self.base_url = os.getenv('DTFLOW_CODEX_BASE_URL', '').rstrip('/') if not self.api_key: - self.api_key = os.getenv('DTFLOW_OPENCLAW_API_KEY', '') + self.api_key = os.getenv('DTFLOW_CODEX_API_KEY', '') if not self.model: - self.model = os.getenv('DTFLOW_OPENCLAW_MODEL', '') + self.model = os.getenv('DTFLOW_CODEX_MODEL', '') - # Fallback: 自动从 OpenClaw 配置读取 + # Fallback: 自动从 Codex/OpenAI-compatible 配置读取 if not all([self.base_url, self.api_key, self.model]): - oc = detect_openclaw_llm() + oc = detect_codex_llm() if not self.base_url: self.base_url = oc.get('base_url', '') if not self.api_key: @@ -76,7 +76,7 @@ def __init__(self, config: dict): if not self.model: self.model = oc.get('model', '') - self.timeout = ocfg.get('timeout_seconds', 900) + self.timeout = ccfg.get('timeout_seconds', 900) def validate(self): missing = [] @@ -88,9 +88,9 @@ def validate(self): missing.append('model') if missing: raise RuntimeError( - f'openclaw 编排器 LLM 配置缺失: {", ".join(missing)}。' - '请在 config.json 的 openclaw 字段中配置 base_url / api_key / model,' - '或设置环境变量 DTFLOW_OPENCLAW_BASE_URL / DTFLOW_OPENCLAW_API_KEY / DTFLOW_OPENCLAW_MODEL。' + f'codex 编排器 LLM 配置缺失: {", ".join(missing)}。' + '请在 config.json 的 codex 字段中配置 base_url / api_key / model,' + '或设置环境变量 DTFLOW_CODEX_BASE_URL / DTFLOW_CODEX_API_KEY / DTFLOW_CODEX_MODEL。' ) def chat(self, system_prompt: str, user_prompt: str, @@ -120,14 +120,14 @@ def chat(self, system_prompt: str, user_prompt: str, return data['choices'][0]['message']['content'] -class OpenClawSubagentOrchestrator(BaseOrchestrator): - """OpenClaw 子 agent 编排器。 +class CodexSubagentOrchestrator(BaseOrchestrator): + """Codex 子任务编排器。 - 与 LocalLLMOrchestrator 结构相同,但使用 config.openclaw 中的独立 - base_url / api_key / model 配置,允许在 OpenClaw skill 内直接调用 + 与 LocalLLMOrchestrator 结构相同,但使用 config.codex 中的独立 + base_url / api_key / model 配置,允许在 Codex skill 内直接调用 任意 OpenAI-compatible 模型接口。 - 如果 config.openclaw 中只提供了 model(如 "Opus"),编排器会在 + 如果 config.codex 中只提供了 model,编排器会在 validate 阶段提醒补充 base_url 和 api_key。 """ @@ -142,7 +142,7 @@ def run(self, action: str, payload: dict) -> dict: return self._run_fix(payload) if action == 'comprehensive_review': return self._run_comprehensive_review(payload) - raise RuntimeError(f'OpenClawSubagentOrchestrator 暂不支持 action: {action}') + raise RuntimeError(f'CodexSubagentOrchestrator 暂不支持 action: {action}') def _parse_or_fallback(self, action: str, raw_text: str, fallback_builder): try: @@ -150,8 +150,8 @@ def _parse_or_fallback(self, action: str, raw_text: str, fallback_builder): except ResultParseError: return fallback_builder(raw_text) - def _make_llm(self) -> _OpenClawLLM: - return _OpenClawLLM(self.config) + def _make_llm(self) -> _CodexTaskLLM: + return _CodexTaskLLM(self.config) def _run_analyze(self, payload: dict) -> dict: llm = self._make_llm() diff --git a/lib/project_board.py b/lib/project_board.py index 4ea090e..3444fcf 100644 --- a/lib/project_board.py +++ b/lib/project_board.py @@ -40,11 +40,11 @@ def load_projects(board_path: Path) -> list[dict]: def save_projects(board_path: Path, projects: list[dict]): board_path.parent.mkdir(parents=True, exist_ok=True) lines = [ - '# PROJECTS.md', + '# DevTaskFlow Project Index', '', - 'DevTaskFlow 项目总看板。', + 'Codex 版 DevTaskFlow 维护的项目索引。', '', - '| 序号 | 项目名 | 状态 | 最新版本 | 路径 | 最后更新 | 备注 |', + '| 序号 | 项目名 | 状态 | 最新版本 | 项目目录 | 最后更新 | 备注 |', '|---|---|---|---|---|---|---|', ] for idx, project in enumerate(projects, start=1): diff --git a/lib/publish_flow.py b/lib/publish_flow.py index 768990f..b32f1b9 100644 --- a/lib/publish_flow.py +++ b/lib/publish_flow.py @@ -134,58 +134,8 @@ def publish(self, project_root: Path, config: dict, **kwargs) -> dict: } -class ClawHubPublishAdapter(BasePublishAdapter): - name = 'clawhub' - - def publish(self, project_root: Path, config: dict, **kwargs) -> dict: - version_dir = get_current_version_dir(project_root, config) - if not version_dir: - raise RuntimeError('没有找到当前版本目录') - - state = StateManager(version_dir) - if state.data.get('status') not in {'sealed', 'deployed', 'all_done'}: - raise RuntimeError(f"当前状态不允许 publish: {state.data.get('status')}") - - # 1. 检查 clawhub CLI 是否可用 - run_cmd(['clawhub', '--cli-version'], project_root) - - # 2. 检查是否已登录 - whoami = run_cmd(['clawhub', 'whoami'], project_root) - if not whoami: - raise RuntimeError('clawhub 未登录,请先运行 clawhub login') - - # 3. 读取 SKILL.md 获取 skill 元信息 - skill_md = project_root / 'SKILL.md' - if not skill_md.exists(): - raise RuntimeError('未找到 SKILL.md,clawhub 发布需要 SKILL.md 文件') - - # 4. 调用 clawhub publish 发布 - skill_path = kwargs.get('skill_path', str(project_root)) - output = run_cmd(['clawhub', 'publish', skill_path], project_root) - - # 5. 记录发布结果到 state - state.data['publish'] = { - 'target': 'clawhub', - 'version': version_dir.name, - 'skill_path': skill_path, - 'whoami': whoami, - 'output': output, - } - state.save() - - return { - 'target': 'clawhub', - 'version': version_dir.name, - 'skill_path': skill_path, - 'whoami': whoami, - 'output': output, - 'message': '已通过 clawhub 发布。', - } - - ADAPTERS = { 'github': GitHubPublishAdapter, - 'clawhub': ClawHubPublishAdapter, } diff --git a/lib/setup_flow.py b/lib/setup_flow.py index 0beff1a..ed8c57a 100644 --- a/lib/setup_flow.py +++ b/lib/setup_flow.py @@ -2,7 +2,7 @@ 支持三档模式: - auto: 自动检测已有配置(极简模式) -- guided: 引导模式(只需填 API Key) +- guided: 引导模式(选择服务、填写 API Key 和模型 ID) - advanced: 高级模式(手动配置所有参数) """ from __future__ import annotations @@ -14,34 +14,16 @@ PRESETS = { '1': { - 'name': 'Claude Opus 4.6(推荐)', - 'base_url': 'https://api.anthropic.com/v1', - 'model_hint': 'claude-opus-4-6', - 'note': '综合能力最强,推荐用于复杂开发任务', - }, - '2': { - 'name': 'GPT 5.4 Pro', - 'base_url': 'https://api.openai.com/v1', - 'model_hint': 'gpt-5.4-pro', - 'note': 'OpenAI 旗舰模型,大型项目首选', - }, - '3': { - 'name': 'GPT 5.4', + 'name': 'OpenAI-compatible API(推荐)', 'base_url': 'https://api.openai.com/v1', - 'model_hint': 'gpt-5.4', - 'note': '性价比高,适合中小型项目', - }, - '4': { - 'name': '小米 Mimo V2 Pro', - 'base_url': 'https://api.xiaomi.com/v1', - 'model_hint': 'mimo-v2-pro', - 'note': '国产模型,中文表现好', + 'model_hint': '', + 'note': '使用你显式配置的 API Key 和模型 ID', }, - '5': { - 'name': '其他模型(手动填写)', + '2': { + 'name': '自定义 OpenAI-compatible API', 'base_url': '', 'model_hint': '', - 'note': '⚠️ 其他模型可能无法完成完整开发任务,建议从以上 4 个中选择', + 'note': '手动填写 API 地址', }, } @@ -165,7 +147,7 @@ def _detect_existing_config(project_root: Path | None = None) -> dict | None: 检测顺序: 1. 当前环境变量 2. 项目目录下的 .env 文件 - 3. OpenClaw 环境下的 LLM 配置 + 3. Codex/OpenAI 环境变量(OPENAI_API_KEY / OPENAI_MODEL) """ base_url = '' api_key = '' @@ -186,32 +168,26 @@ def _detect_existing_config(project_root: Path | None = None) -> dict | None: api_key = api_key or env_config.get('DTFLOW_LLM_API_KEY', '').strip() model = model or env_config.get('DTFLOW_LLM_MODEL', '').strip() - # 3. 尝试检测 OpenClaw 环境变量 + # 3. 尝试检测 Codex/OpenAI 环境变量 if not (base_url and api_key and model): - oc_base = os.environ.get('OPENAI_BASE_URL', '').strip() - oc_key = os.environ.get('OPENAI_API_KEY', '').strip() - oc_model = os.environ.get('OPENAI_MODEL', '').strip() - base_url = base_url or oc_base - api_key = api_key or oc_key - model = model or oc_model - - # 4. 尝试从 OpenClaw 主配置自动检测 + codex_base = os.environ.get('OPENAI_BASE_URL', '').strip() + codex_key = os.environ.get('OPENAI_API_KEY', '').strip() + codex_model = os.environ.get('OPENAI_MODEL', '').strip() + base_url = base_url or codex_base + api_key = api_key or codex_key + model = model or codex_model + + # 4. 尝试从 Codex-friendly 配置自动检测 if not (base_url and api_key and model): try: - from openclaw_config import detect_openclaw_llm - oc = detect_openclaw_llm() + from codex_config import detect_codex_llm + oc = detect_codex_llm(project_root) base_url = base_url or oc.get('base_url', '').strip() api_key = api_key or oc.get('api_key', '').strip() model = model or oc.get('model', '').strip() except Exception: pass - # 5. 再尝试 OpenRouter 等常见变量 - if not base_url: - base_url = os.environ.get('OPENROUTER_BASE_URL', '').strip() - if not api_key: - api_key = os.environ.get('OPENROUTER_API_KEY', '').strip() - # 验证:至少需要 api_key 和 model if api_key and model: # 如果没有 base_url,尝试根据 model 推断 @@ -241,16 +217,6 @@ def _parse_env_file(env_path: Path) -> dict: def _guess_base_url(model: str) -> str: """根据模型名猜测 base_url。""" - model_lower = model.lower() - if 'claude' in model_lower or 'anthropic' in model_lower: - return 'https://api.anthropic.com/v1' - if 'gpt' in model_lower or 'o1' in model_lower or 'o3' in model_lower: - return 'https://api.openai.com/v1' - if 'mimo' in model_lower or 'xiaomi' in model_lower: - return 'https://api.xiaomi.com/v1' - if 'gemini' in model_lower or 'google' in model_lower: - return 'https://generativelanguage.googleapis.com/v1' - # 默认用 OpenAI 兼容格式 return 'https://api.openai.com/v1' @@ -258,15 +224,15 @@ def _guess_base_url(model: str) -> str: def _setup_auto(project_root: Path | None = None) -> int: """极简模式 — 自动检测已有配置并应用。""" - # 优先尝试从 OpenClaw 主配置自动读取 + # 优先尝试从 Codex/OpenAI-compatible 配置自动读取 try: - from openclaw_config import detect_openclaw_llm - oc = detect_openclaw_llm() + from codex_config import detect_codex_llm + oc = detect_codex_llm(project_root) if oc.get('base_url') and oc.get('api_key') and oc.get('model'): os.environ['DTFLOW_LLM_BASE_URL'] = oc['base_url'] os.environ['DTFLOW_LLM_API_KEY'] = oc['api_key'] os.environ['DTFLOW_LLM_MODEL'] = oc['model'] - print(f'✅ 自动使用 OpenClaw 配置: {oc["model"]}') + print(f'✅ 自动使用 Codex/OpenAI 配置: {oc["model"]}') _apply_config(oc, project_root) _run_doctor_check() return 0 @@ -299,9 +265,9 @@ def _setup_auto(project_root: Path | None = None) -> int: # ── 引导模式:只需填 API Key ───────────────────────────────── def _setup_guided(project_root: Path | None = None) -> int: - """引导模式 — 只需选模型 + 填 API Key,其他自动。""" + """引导模式 — 选择服务 + 填 API Key 和模型 ID,其他自动。""" print() - print('🚀 快速配置(只需 2 步)') + print('🚀 快速配置') print('=' * 40) print() print('选择你想用的 AI 服务:') @@ -323,12 +289,12 @@ def _setup_guided(project_root: Path | None = None) -> int: print('❌ API Key 不能为空') return 1 - # 自动推断 base_url 和 model + # 自动推断 base_url,模型名由用户按当前账号可用列表填写 base_url = preset['base_url'] - model = preset['model_hint'] + model = '' - # 如果是"其他模型",需要额外输入 - if choice == '5': + # 自定义 API 需要额外输入地址 + if choice == '2': print() model = _prompt('请输入模型名称') if not model: @@ -338,6 +304,11 @@ def _setup_guided(project_root: Path | None = None) -> int: if not base_url: print('❌ API 地址不能为空') return 1 + else: + model = _prompt('请输入模型名称(使用你平台中可用的模型 ID)', preset.get('model_hint', '')) + if not model: + print('❌ 模型名称不能为空') + return 1 # 测试连接 print() @@ -398,7 +369,7 @@ def _setup_advanced(project_root: Path | None = None) -> int: print() choice = _prompt('请选择(输入数字)', '1') - preset = PRESETS.get(choice, PRESETS['5']) + preset = PRESETS.get(choice, PRESETS['2']) print() diff --git a/requirements-dev.txt b/requirements-dev.txt new file mode 100644 index 0000000..ea031eb --- /dev/null +++ b/requirements-dev.txt @@ -0,0 +1,2 @@ +-r requirements.txt +PyYAML>=6.0 diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..535409c --- /dev/null +++ b/requirements.txt @@ -0,0 +1 @@ +requests>=2.31 diff --git a/templates/config.json b/templates/config.json index c9137cd..880798a 100644 --- a/templates/config.json +++ b/templates/config.json @@ -18,13 +18,13 @@ "deploy": "shell", "archive": "local-copy", "orchestration": "local_llm", - "publish": "clawhub" + "publish": "github" }, - "openclaw": { + "codex": { "base_url": "", "api_key": "", "model": "", - "agent_id": "skill-runner", + "agent_id": "codex-skill-runner", "mode": "run", "timeout_seconds": 900 }, diff --git a/templates/env.example b/templates/env.example index 4931466..711cee2 100644 --- a/templates/env.example +++ b/templates/env.example @@ -4,7 +4,9 @@ DTFLOW_LLM_BASE_URL=https://your-llm-endpoint.example.com/v1 DTFLOW_LLM_API_KEY=your_api_key_here DTFLOW_LLM_MODEL=your_model_name_here -# 可选项:只有你真的需要部署/归档/OpenClaw 时再配置 +# 可选项:只有你真的需要部署/归档或独立 Codex 编排模型时再配置 DTFLOW_DEPLOY_TARGET= DTFLOW_ARCHIVE_TARGET= -DTFLOW_OPENCLAW_ENABLED=false +DTFLOW_CODEX_BASE_URL= +DTFLOW_CODEX_API_KEY= +DTFLOW_CODEX_MODEL=