# ai-module **Repository Path**: txshare/ai-module ## Basic Information - **Project Name**: ai-module - **Description**: AI会话 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-08-28 - **Last Updated**: 2026-10-26 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # ai-module 统一 Claude、ChatGPT(Codex)和 OpenCode 编码代理的 Python 接口,提供流式输出、会话管理、用量统计、技能模板和 MCP 工具扩展。当前开发版本为 **0.3.0**,变更记录见 [CHANGELOG](CHANGELOG.md)。 本仓库是 WorkNode 的 Git 子模块,在宿主中使用 `core.ai_module` 导入;Python 包名为 `ai-module`,安装后的导入名为 `ai_module`。公共 API 按需加载后端,使用 ChatGPT 时不会初始化 Claude SDK。 ## 环境与安装 | 后端 | Python | 运行依赖 | 接入方式 | | --- | --- | --- | --- | | Claude | 3.10+ | `claude-agent-sdk` 及可用的 Claude CLI/认证配置 | Agent SDK | | ChatGPT / Codex | 3.11+ | 支持 `app-server` 的 Codex CLI | 子进程双向 JSON-RPC | | OpenCode | 3.11+ | OpenCode CLI **1.18.18** 及 `[opencode]` 依赖 | 每轮独立本地 HTTP/SSE 服务 | 在 WorkNode 根目录初始化子模块并安装: ```bash git submodule update --init --recursive python -m pip install -e "core/ai_module[dev]" # 使用 OpenCode 时安装额外依赖 python -m pip install -e "core/ai_module[opencode]" ``` 单独检出 ai-module 后,可在其根目录执行 `python -m pip install -e ".[dev]"`。公共依赖包括 `claude-agent-sdk`、`filelock`、`mcp`、`jsonschema` 和 `PyYAML`;具体范围见 [pyproject.toml](pyproject.toml)。CLI 及其认证需另行准备。 **宿主依赖:** 当前运行层使用 WorkNode 的 `core.bridge.ask_user`、`core.bridge.permission` 和 `core.bridge.specification`;部分配置与历史模块也使用宿主导入路径。单独安装本包不会打包这些宿主模块。以下运行示例应在完整 WorkNode 环境中执行;移植到其他宿主前需适配这些依赖。 ## 快速开始 `run_ai` 在后台线程启动任务并立即返回。命令行程序需等待完成,GUI 程序需把回调转发到界面线程。 ```python import threading from pathlib import Path from core.ai_module import AIConfig, remove_client, run_ai done = threading.Event() client_key = "project-analysis" def finished(code): print("完成,退出码:", code) done.set() run_ai( "总结这个项目的结构", AIConfig( provider="claude", cwd=str(Path.cwd()), permission_mode="plan", ), on_output=lambda text, subtype: print(f"[{subtype}] {text}"), on_error=lambda text: print(text) if text else None, on_finished=finished, client_key=client_key, ) try: done.wait() finally: remove_client(client_key) ``` `AIConfig.provider` 默认是 `claude`,`model=None` 交由后端选择默认模型。兼容入口 `ClaudeConfig` 保留原有默认模型 `glm-5.2`;切换其他后端时建议使用 `AIConfig`,避免传入 Claude 模型和专属限制。 ### ChatGPT / Codex 把上述配置替换为: ```python config = AIConfig( provider="chatgpt", cwd=str(Path.cwd()), permission_mode="plan", model=None, # codex_cli_path=r"C:\path\to\codex.exe", codex_request_timeout=60, ) ``` - ChatGPT 登录:先执行 `codex login`,运行时复用 CLI 登录状态。 - API Key:在 `env_vars=[{"key": "CODEX_API_KEY", "value": "..."}]` 中传入,也支持 `OPENAI_API_KEY`。Key 模式使用项目内 `.worknode/chatgpt/codex/`,与已有 ChatGPT 登录隔离;密钥不要提交到仓库。 - CLI 查找顺序为 `codex_cli_path`、`CODEX_CLI_PATH`、运行环境 PATH,之后检查常用安装目录和 VS Code / VS Code Insiders / Cursor 的 Codex 扩展。显式路径无效时直接报错。 - `model` 原样传递,`effort` 控制推理强度;`codex`、`openai` 是 `chatgpt` 的后端名称别名。 ### OpenCode ```python config = AIConfig( provider="opencode", cwd=str(Path.cwd()), model="provider-id/model-id", permission_mode="plan", opencode_options={ "agent": "plan", "start_timeout": 25, "request_timeout": 30, # "cli_path": r"C:\path\to\opencode.exe", # "variant": "high", # "providers": {...}, }, ) ``` 当前适配器仅接受 CLI 1.18.18。`opencode_options` 支持 `cli_path`、`agent`(`build` / `plan`)、`variant`、`start_timeout`、`request_timeout` 和 `providers`。CLI 路径也可通过 `OPENCODE_CLI_PATH` 或 PATH 提供;供应商认证与模型连接需在对应环境中配置。 每次运行创建独立服务进程和经鉴权的宿主 MCP 网关,结束或停止时回收。原生数据库放在项目 `.worknode/opencode/runtime/` 中,支持 question、permission、todo、续接、分叉和压缩。 ## 公共接口与运行隔离 | 接口 | 语义 | | --- | --- | | `run_ai(prompt, config, *, ..., client_key=...)` | 启动任务;回调参数见下表 | | `request_stop_ai(client_key)` | 立即标记取消并调度中断,解除挂起问答和权限请求 | | `stop_ai(client_key)` / `force_kill_ai(client_key)` | 等待停止 / 强制结束匹配的客户端 | | `is_ai_running(client_key)` | 查询匹配客户端是否仍在运行 | | `remove_client(client_key)` | 停止并移除客户端,释放注册表引用 | | `run_client_key(workspace_key, run_id)` | 构造 `workspace_key::run_id`,隔离同一项目的多次运行 | `*_ai` 与旧 `*_claude` 名称共用实现和客户端注册表,`run_claude` 也按 `config.provider` 分派。管理操作传项目 key 时匹配其下所有 run key;停止或查询时传 `None` 会作用于全部客户端。同一 key 切换后端前必须完成旧客户端清理。 | 回调 | 数据约定 | | --- | --- | | `on_output(text, subtype)` | 助手文本、思考、系统事件、工具调用/结果/diff;最终结果使用 `success` | | `on_error(text)` | 空字符串表示无错误文本;非空字符串表示失败或明确停止原因 | | `on_finished(code)` | 每轮完成一次:空错误文本为 `0`,非空为 `1`;兼容取消路径可能返回 `0`,宿主仍需维护自己的停止状态 | | `on_session_id(session_id)` | 后端原生会话 ID,记录其所属服务 | | `on_status(text)` | 运行状态提示 | | `on_usage(summary)` | token、缓存、模型和工具计数等;后端没有提供或无法可靠计价时不补造美元费用 | 问答、权限、任务列表和代码修改分别使用配置中的 `on_ask_user`、`on_permission_request`、`on_task_list`、`on_code_change`。问答/权限通过 UUID 路由到当前 run 的桥接实例,宿主用相应 `core.bridge` 的响应接口回填结果。 OpenCode 的 `assistant_stream(part_id)` 是临时文本快照:按 run/part 原地更新,空文本时移除,避免重复归档;完成的分析文本走 `assistant`,最终结果走 `success`。 ## 配置、权限与会话 通用字段包括 `cwd`、`model`、`system_prompt`、`system_prompt_append`、`env_vars`、`add_dirs`、`skills`、`mcp_servers`、`permission_mode` 和交互回调。完整定义见 [config.py](config.py)。项目级配置由 [ai_config.py](ai_config.py) 读写 `<项目>/.worknode/settings.yaml`。 项目配置的顶层字段兼容原有 Claude 设置;`service_profiles.chatgpt`、`service_profiles.opencode` 分别保存其他服务的设置。[service_profiles.py](service_profiles.py) 负责投影、校验和合并,切换服务不会把 Claude 的模型、预算或轮数限制带入其他后端。 | `permission_mode` | Codex | OpenCode | | --- | --- | --- | | `plan` / `rejectAll` | 只读沙箱,无审批 | 只读工具策略,禁止编辑、命令及任务写入 | | `default` | 工作区写入,按需审批 | 默认询问,读取类工具放行 | | `acceptEdits` | 工作区写入,按需审批 | 编辑及部分交互工具放行,其余按需询问 | | `dontAsk` | 工作区写入,不请求审批 | 默认拒绝,读取类工具放行 | | `bypassPermissions` / `acceptAll` | 完整访问,无审批 | 默认放行 | Claude 按 SDK 策略处理。`AIConfig.permission_mode` 默认是 `bypassPermissions`,宿主应按实际授权显式选择。各后端对无法等价实现的限制会报错:例如 Codex / OpenCode 不支持 Claude 的美元预算和轮数硬限制;OpenCode 用 `variant` 选择推理档位,不能直接使用 `effort`。MCP 拒绝规则继续在公共工具层生效。 会话续接使用 `session_id` 配合 `resume=True`,分叉使用 `fork_session=True`,压缩使用 `compact=True`。后端归属索引阻止跨服务续接;主会话指针按服务保存。`enable_session_store` 控制本地镜像: | 内容 | 项目内路径 | | --- | --- | | Claude 会话镜像 | `.worknode/sessions/` | | Codex 文本镜像 | `.worknode/chatgpt/sessions/` | | OpenCode 文本镜像 | `.worknode/opencode/sessions/` | | 会话归属 / 主会话指针 | `.worknode/sessions/.providers.json` / `.main-providers.json` | 关闭镜像不会关闭 CLI 自身的原生持久化。独立模型交接摘要当前由 Claude 实现;其他后端可使用原生压缩或本地结论提取,不能用 Claude 模型直接总结其会话。 ### 规格确认与辅助文件 `AIConfig(spec_review_enabled=True, on_ask_user=...)` 启用共享规格确认:先用隔离的只读配置生成规格,再由宿主确认后进入执行阶段。库调用默认关闭,WorkNode 应用入口默认开启。缺少问答回调、取消、全部排除、无效规格或预算耗尽时不会进入执行;规划用量带 `phase="specification"` 单独上报。 每轮请求固定注入辅助文件规则:仅供 AI 分析和执行的草稿、一次性脚本、日志、备份等保存到目标项目 `.worknode/ai_work/`;正式源码、测试和交付文档仍放项目约定的位置。子进程设置 `WORKNODE_AI_WORK_DIR`,并将 `TMPDIR` / `TMP` / `TEMP` 指向其 `tmp/` 子目录。目录无法准备或链接越界时直接失败,已有文件不会自动迁移。这是执行指令与临时目录约束,文件系统隔离由后端权限策略负责。 ## 技能与工具扩展 ### Skills:提示词模板 ```python from core.ai_module import get_skill_registry registry = get_skill_registry() registry.register("review", "检查 {{lang}} 代码中的边界条件", description="代码审查") # 也可 registry.register_file("prompts/review/SKILL.md") config = AIConfig(cwd=str(Path.cwd()), skills=["review"], skill_variables={"lang": "Python"}) ``` 技能支持 `{{变量}}` 渲染和 `SKILL.md` frontmatter。`skill_context_mode` 默认 `on_demand`,按需展开技能内容。 ### Actions:宿主函数 ```python from core.ai_module import get_action_registry @get_action_registry().register("project_status", description="读取项目状态") def project_status(name: str) -> dict: return {"project": name, "status": "ready"} ``` `enable_actions=True`(默认)且注册表非空时自动挂载。内部工具标识为 `mcp__ai_actions__project_status`;按需网关和各后端会适配对外调用名。同步函数在线程池执行,单动作超时 300 秒,失败以工具结果返回。 ### MCP 公共 `toolkit.py` 定义工具,`host_tools.py` 统一组装和执行,`mcp/transport.py` 支持 stdio、HTTP、SSE 和进程内连接。外部 MCP 配置会发现工具、提示词和资源;按需 `describe/call` 网关减少一次性注入的上下文。 | 内建能力 | 配置开关 | 条件 | | --- | --- | --- | | 用户问答 / 非阻塞确认 | `enable_ask_user` / `enable_user_tool` | 配置 `on_ask_user` | | 宿主动作 | `enable_actions` | 注册表非空 | | 历史检索 | `enable_history` | 项目有 `.worknode/context_history/` | | 鸿蒙文档 | `enable_harmony_docs` | 按需检索本地 SDK / 官方资料 | | 鸿蒙设备自动化 | `enable_hypium` | 本机 hypium / hdc 可用;缺少时跳过 | | 代码图谱(实验性) | `enable_code_analysis` | 默认关闭;需 `cwd`、Node.js 20+ 和 npm | 代码图谱上游源码锁定在嵌套子模块 `mcp/code_analysis/codegraph-mcp/`,首次启动自动 `npm ci`,数据库为项目 `.worknode/codegraph/graph.db`。运行与宿主适配位于 `mcp/code_analysis/`,无需修改上游源码。 ## 代码结构与扩展边界 | 模块 | 职责 | | --- | --- | | `__init__.py` / `client.py` / `providers.py` | 惰性公共导出、兼容入口、客户端注册表及后端选择 | | `config.py` / `runtime.py` | 配置与后台线程、回调、停止生命周期 | | `claude/` | SDK 连接、消息、Hook、权限、会话与模型适配 | | `chatgpt/` | Codex 进程、JSON-RPC、事件、动态工具与会话适配 | | `opencode/` | 服务生命周期、HTTP/SSE、交互、模型及用量适配 | | `toolkit.py` / `host_tools.py` / `mcp/` | 中立工具定义、执行、传输和宿主网关 | | `specification.py` / `prompting.py` / `execution_policy.py` | 规格确认、公共提示词和执行规则 | | `auxiliary_files.py` | 辅助目录、临时环境和路径边界校验 | | `session_providers.py` / `session_services.py` / `local_transcripts.py` / `main_sessions.py` | 服务归属、历史分派、文本镜像和主会话指针 | | `ai_config.py` / `service_profiles.py` / `model_catalog.py` / `pricing.py` | 项目设置、服务隔离、模型目录和计价 | | 根层旧 Claude 模块 | 兼容转发到 `claude/`,保留已有导入路径 | 新增后端时在 `providers.py` 注册,后端协议放入独立包并复用公共运行与工具层;公共逻辑避免直接依赖供应商 SDK。交互桥接由宿主负责。`progress_guard.py` 限制连续无进展重试,`shell_changes.py` 对可能写文件的命令记录快照;客户端隔离不等于跨 run 的文件写入锁。 ## 验证与维护 回归测试目前位于 **WorkNode 主仓库**,在宿主根目录运行: ```bash python -m unittest tests.test_ai_providers tests.test_codex_dynamic_tools tests.test_codex_executable tests.test_ai_auxiliary_files tests.test_ai_model_catalog tests.test_ai_config_services tests.test_opencode_provider tests.test_sandbox_lifecycle ``` Codex 协议测试使用本地假服务,不发送真实推理请求;OpenCode 原生集成测试默认跳过,安装受支持 CLI 后设置 `WORKNODE_OPENCODE_INTEGRATION=1` 可运行本地假模型集成测试。其他 UI/宿主验证脚本位于主仓库 `scripts/`。 提交时先在 ai-module 子模块提交代码,再在 WorkNode 提交子模块引用;更新嵌套代码图谱子模块时也应保留准确的 Git 引用。重要功能、兼容变化和修复同步记录到 [CHANGELOG](CHANGELOG.md)。