# DETA — Agent Plugins DETA 领域能力在各类 Agent harness 上的分发仓:**一份产物,多个宿主壳**。 | 宿主 | 形态 | 安装 | |------|------|------| | Codex | 插件(`.codex-plugin/plugin.json` + `skills/` + `.mcp.json`);本仓同时是 Codex 插件市场 | `codex plugin marketplace add https://git.deta.city/deta/deta-agent-plugins.git` → `codex plugin add deta@deta` | | dsh (deepseek-harness) | 组合包 bundle(`dsh.bundle.patch` + `cordis.patch.yml`) | `dsh plugin --profile add ./plugins/deta` | 能力本体(AML 建筑模型读写、编译校验、围护结构统计、空间邻接查询)以 MCP 服务提供, 同一份后端与技能被所有宿主复用;新增宿主只需再加一层声明式壳。 ## 安装(Codex) ```bash # 从 Git(分发用) codex plugin marketplace add https://git.deta.city/deta/deta-agent-plugins.git codex plugin list codex plugin add deta@deta # 登录(一次性):打开浏览器完成 deta.city 账号登录 codex mcp login deta_mcp ``` `codex mcp login deta_mcp` 走 OAuth 2.1(授权码 + PKCE S256 + 动态客户端注册):终端给出 `https://deta.city/oauth/authorize?...`,在浏览器里用 deta.city 账号登录并授权即可, 随后 Codex 自行保管令牌并按 refresh token 自动续期。退出登录用 `codex mcp logout deta_mcp`。 不支持 OAuth 的宿主(dsh / 脚本 / CI)改用登录助手换取 `DETA_TOKEN`: ```bash node ~/Dev/ant/deta-agent-plugins/plugins/deta/bin/deta-login.mjs source ~/.deta/env # 让 DETA_TOKEN 进入当前 shell 环境 ``` 未登录时 MCP 端点返回 **401**,并带 OAuth 发现提示头 (`WWW-Authenticate: Bearer resource_metadata="https://deta.city/.well-known/oauth-protected-resource/mcp-api/mcp"`)—— 标准 MCP 客户端据此自动进入浏览器授权流程,含义是「当前环境没有可用的 deta.city 登录态」。 ## 内容 | 插件 | 技能 | 能力 | 依赖 | |------|------|------|------| | `deta` | `deta:aml-design` | AML 建筑模型读写、编译与校验、围护结构统计、空间邻接查询 | node;领域服务已构建 | ## 前置条件 | 项 | 值 | |----|-----| | MCP 端点 | `https://deta.city/mcp-api/mcp`(MCP Streamable HTTP) | | 凭据来源 | **deta.city 账号**;`bin/deta-login.mjs` 登录取令牌,经环境变量 `DETA_TOKEN` 传给 harness | | 凭据文件 | `~/.deta/credentials.json`(令牌 + 账号 + 端点)、`~/.deta/env`(`export DETA_TOKEN=...`),均 0600 | 端点除探活接口(服务端 `GET /health`,经 Nginx 前缀对外为 `/mcp-api/health`)外全部需要鉴权: - 未带凭据 / 凭据失效 → `401`(提示重新登录,不回显凭据); - 服务端认证服务不可用 → `500`,同样不放行; - 各账号在服务端有独立工作区(`<工作区根>/<账号 ID>`),互不可见。 ### 本地 stdio 形态(开发用,默认关闭) 本机开发时也可以直连领域服务的无头 MCP 服务(`bin/deta-mcp.sh`,stdio), 它**不校验 deta.city 账号、不隔离工作区**,仅供本机迭代领域能力: ```bash cd ~/Dev/ant/ant-copilot && npm run build node dist/src/headless/mcp-server.js # 冒烟:应等待 stdin/stdout ``` 该形态的环境变量: | 变量 | 缺省 | 说明 | |------|------|------| | `DETA_SERVER_ROOT` | `~/Dev/ant/ant-copilot` | 领域服务仓库根目录(内部路径) | | `ANT_HEADLESS_WORKSPACE` | `/workspace` | AML 工作目录(`aml.xml` / `building.json` 落盘处,名称由底层服务决定) | 编译与校验类工具需要**编译服务**在线(服务端地址由底层环境变量 `DETA_GSA_URL` 给出,缺省 `localhost:8000`);未在线时返回明确错误,读写类工具可离线工作。 ## 本地迭代 插件内容改动后 Codex 不会自动感知,按官方流程打 cachebuster 版本号再重装: ```bash python3.11 ~/.codex/skills/.system/plugin-creator/scripts/update_plugin_cachebuster.py \ ~/Dev/ant/deta-agent-plugins/plugins/deta codex plugin add deta@deta ``` (版本号形如 `0.1.0+codex.20260910020424`;重装后需开新会话才能加载新技能。) 校验清单: ```bash python3.11 ~/.codex/skills/.system/plugin-creator/scripts/validate_plugin.py \ ~/Dev/ant/deta-agent-plugins/plugins/deta codex plugin marketplace list codex mcp list | grep deta ``` ## 双壳架构(Codex + dsh 同一产物) `plugins/deta/` 这一个目录同时是 Codex 插件根与 dsh 组合包根,共享核心、各带一层薄壳: | 组成 | 文件 | Codex | dsh | |------|------|-------|-----| | 插件清单 | `.codex-plugin/plugin.json` | ✅ 使用 | — | | MCP 声明 | `.mcp.json` | ✅ 使用(可放 Codex 私有键) | — | | 组合包声明 | `package.json`(`dsh.bundle.patch`) | 忽略 | ✅ 使用 | | 配置层 | `cordis.patch.yml` | 忽略 | ✅ 使用 | | 领域技能 | `skills/aml-design/SKILL.md` | ✅ 共享 | ✅ 共享 | | 本地启动器 | `bin/deta-mcp.sh` | ✅ | 由配置层的 `args` 直接指向服务入口 | 共享面(两端一致,零适配): - **技能文件格式**:`/SKILL.md` + frontmatter 必填 `name`/`description`,kebab-case。 Codex 与 dsh(`@deepseek-ai/dsh-skill-filesystem`)要求相同。 - **共享技能根**:两端都扫描 `~/.agents/skills/` 与 `<项目>/.agents/skills/` (dsh 侧为 rank 500 / 200 的发现根,且显式支持 `/skills`)。 把技能放这里即可双端生效,不需要安装插件。 - **MCP 工具命名**:两端同为 `mcp____`,我们统一 `serverName = deta`, 因此技能里写裸工具名(`read_source`、`apply_design`)在两端都能解析。 各自不同的部分(不共享): - MCP 的声明位置不同(Codex 读 `.mcp.json`,dsh 读 `cordis.patch.yml` 的 mcp-client 行)。 - Codex 私有键(`default_tools_approval_mode`、`supports_parallel_tool_calls`)只写在 `.mcp.json`,不影响 dsh;dsh 无审批模式概念。 - 分发渠道不同:Codex 走 git 市场,dsh 走 npm / git / tarball,且 dsh 没有官方市场。 ### dsh 侧安装与验证 ```bash # 安装进某个 profile(pnpm 转发) dsh plugin --profile add ~/Dev/ant/deta-agent-plugins/plugins/deta # 公开发布形态(二选一) npm publish # 用户:dsh plugin --profile add deta-plugin dsh plugin --profile add github:<你>/<仓库> # 需作者提供 prepare + 用户 allowBuilds # 只验证配置层是否合并正确(不启动、不需凭据) cd ~/Dev/ant/deepseek-harness node apps/cli/lib/bin.js --profile headless --dump-config \ --patch ~/Dev/ant/deta-agent-plugins/plugins/deta/cordis.patch.yml # 输出中应出现 `# == .../plugins/deta/cordis.patch.yml` 与 deta-mcp 行 ``` `cordis.patch.yml` 当前默认启用**远程端点**(`streamable-http` + `Authorization: Bearer ${DETA_TOKEN}`,指向 `https://deta.city/mcp-api/mcp`); 本地 stdio 段保留为注释、标注「本机开发用,默认关闭」,需要时手工切换。 ## 已知缺陷(实测,2026-09-10) **上游:编码代理 × 模型服务 命名空间重复** 会话累积较多本插件工具调用后,代理会在请求里重复声明 MCP 命名空间,模型服务的 Responses 兼容层拒绝请求: ``` Duplicate namespace name 'deta'; Namespace names must be unique. ``` 复现记录(同一插件、不同会话长度): | 代理版本 | 会话规模 | 触发位置 | |---------|---------|---------| | 0.144.4 | 一步并发 2 次调用 | input[10]、input[18] | | 0.144.4 | 串行 7–8 次调用 | input[37]、input[47] | | 0.154.0 | 短会话 5 工具 | 未触发 | | 0.154.0 | 长会话(≈15+ 工具) | input[260] | 已排除/无效的手段:`wire_api = "chat"`(该版本已移除,仅支持 responses)、 `features.non_prefixed_mcp_tool_names`(仅去掉命名空间前缀,重复依旧)、 `supports_parallel_tool_calls = false`(削弱并发触发面,长会话仍复现)。 **应对**:完成一个任务后另起会话;撞到该错误不要重试,重开会话即可(工作区文件保留)。 ## 已修缺陷(实测) | 现象 | 根因 | 修复 | |------|------|------| | 写类工具返回 `user cancelled MCP tool call` | MCP 工具默认需审批,非交互模式下无法弹窗 | `.mcp.json` 加 `default_tools_approval_mode: "approve"`(实测 `auto`/`writes` 都会被取消,只有 `approve` 放行) | | 并发调用触发命名空间重复 | 代理并发序列化 | `.mcp.json` 加 `supports_parallel_tool_calls: false` | ## 目录结构 ``` .agents/plugins/marketplace.json # Codex 默认市场(ChatGPT 登录用户) .agents/plugins/api_marketplace.json # Codex API key 登录用户市场 plugins/deta/ # 同一目录 = Codex 插件根 = dsh 组合包根 ├── .codex-plugin/plugin.json # Codex 插件清单 ├── .mcp.json # Codex MCP 声明(远程 streamable-http) ├── package.json # dsh 组合包声明(dsh.bundle.patch) ├── cordis.patch.yml # dsh 配置层(挂载 MCP 服务) ├── bin/deta-login.mjs # 登录助手(~/.deta/credentials.json + ~/.deta/env) ├── bin/deta-mcp.sh # 本地 stdio 启动器(开发用,默认关闭) ├── README.md # 插件说明(安装/凭据/401 语义) └── skills/aml-design/SKILL.md # 领域技能(两宿主共享) ```