Files
deta-agent-plugins/README.md
T

235 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# DETA — Agent Plugins
DETA 领域能力在各类 Agent harness 上的分发仓:**品牌 = 市场,产品 = 插件,一个仓承载多产品**。
| 宿主 | 形态 | 安装 |
|------|------|------|
| Codex | 插件(`.codex-plugin/plugin.json` + `skills/` + `.mcp.json`);本仓同时是 Codex 插件市场 `deta` | `codex plugin marketplace add https://git.deta.city/deta/deta-agent-plugins.git` → `codex plugin add studio@deta` |
| dsh (deepseek-harness) | 组合包 bundle(`dsh.bundle.patch` + `cordis.patch.yml`) | `dsh plugin --profile <name> add ./plugins/studio` |
发行标识(Codex 语法 = 插件@市场):**`studio@deta`**、**`writer@deta`**——两个插件互不冲突,
可同时安装(MCP 服务名 `studio_mcp` / `writer_mcp`,工作区各自独立)。新增产品按同一结构落位:
`plugins/<产品>/` 自带 `.codex-plugin/plugin.json`、`.mcp.json`、`package.json`、`cordis.patch.yml`、
`bin/`、`skills/`、`README.md`,市场 `plugins` 数组加一条即可。
能力本体(AML 建筑模型读写、编译校验、围护结构统计、空间邻接查询)以 **MCP 服务**提供,
运行时在**本机**解析(引擎包 / 源码构建),宿主侧只声明"用哪个启动器";
同一份后端、同一个启动器、同一套技能被所有宿主复用,新增宿主只需再加一层声明式壳。
## 职责边界(仓库章程)
本仓是**宿主适配与分发层,零逻辑、不承载契约**。三条铁律:
| 问题 | 归属 | 内容 |
|------|------|------|
| 能力在哪 | **ant-copilot**(唯一来源) | 工具实现、MCP 协议层、启动形态(本机 stdio / 服务端 HTTP)、工具面裁剪、领域技能 |
| 怎么被发现和启动 | **本仓** | 宿主清单(`.codex-plugin/plugin.json`、`cordis.patch.yml`)、连接声明(`.mcp.json`)、启动器、宿主侧技能投影 |
| 怎么在云上跑 | **infra** | 部署 / 证书 / 路由 / 重启;云端只跑 ant-copilot 的构建产物 |
因此本仓**不做**这些事(由 `scripts/check-plugin-contract.mjs` 在 CI 强制):
- 不在文档或技能里列**工具清单 / 工具一览**——工具面按部署形态裁剪,清单必然过期;
取清单的唯一途径是运行时调用 `list_capabilities`(技能必须给出这条指引)。
- 不解释 ant-copilot 的内部常量与实现路径(`DETA_TOOL_SURFACE`、`dist/…` 等)。
- 不把「开发检出路径」当作运行前提——启动器应随包解析运行时(当前仍保留开发检出回落,
校验脚本以 warning 提示,本机引擎包落地后升级为 error)。
- 市场条目与实际插件目录**必须一致**(条目 `name` = 插件清单 `name`、`path` 真实存在),
由校验脚本的 E4 规则强制——改名或加产品时不会留下悬空条目。
**衡量标准**:新增一个工具需要改几处?目标是 **1 处**(ant-copilot 注册工具,
能力目录与文档自动派生),本仓零改动。
## 连接形态(唯一管道:本机 stdio)
```
宿主(Codex / dsh)
└─ 拉起 plugins/<产品>/bin/deta-mcp.sh --profile <产品> ← 各产品带自己的档位,脚本同一份
├─ 解析领域服务运行时:DETA_SERVER_ROOT → ~/.deta/runtime → 本机开发检出
├─ 解析工作目录:DETA_WORKSPACE → ANT_HEADLESS_WORKSPACE → ~/.deta/<产品>/workspace
└─ 执行领域服务运行时入口(打包产物;回落未打包产物时打印警告)
└─ MCP stdio:全量工具面;无 OAuth、无 401、无令牌续期
```
- **本机形态不做 MCP 鉴权**:进程在本机由宿主或用户拉起,天然可信。
- 云侧能力(项目/楼栋列表、同步)是**可选的输入**:注入 `DETA_TOKEN` 即有,缺省时云类工具
返回 `auth_required`,其余工具照常——同一份工具实现,不是两套分支。
- Studio 执行器中继(模拟/画布)需 `ANT_WORKSPACE_BRIDGE_URL` + 项目 ID 三要素齐备。
- **各产品独立命名空间**:MCP 服务名 `studio_mcp` / `writer_mcp`(工具前缀
`mcp__<服务名>__<工具>`),两个插件可同时安装互不冲突;产品间不共享工作区。
- 服务端仍保留 HTTP 形态的服务(数据面/其他客户端用),但它**不是本插件声明的连接形态**;
插件的连接声明只有本机 stdio 一种。
## 内容
| 插件 | 服务名 | 技能 | 能力 | 依赖 |
|------|--------|------|------|------|
| `studio@deta` | `studio_mcp` | `studio:aml-design` | AML 建筑模型读写、编译与校验、围护结构统计、空间邻接查询 | node;领域服务运行时(本机引擎包或源码构建) |
| `writer@deta` | `writer_mcp` | `writer:report-authoring` | 报告/文档产出:读模型、取数据(统计/分析/模拟缓存/气象/规范)、成文 | 同上 |
## 安装(Codex)
```bash
# 从 Git(分发用)
codex plugin marketplace add https://git.deta.city/deta/deta-agent-plugins.git
codex plugin list
codex plugin add studio@deta
```
领域服务运行时随插件包分发,启动器首次拉起时自动安装到 `~/.deta/runtime`,插件升级后自动同步
(只比对哈希,命中就跳过)。需要显式重装、或补装候选预览图的栅格化依赖时:
```bash
~/.deta/bin/deta install-runtime # 安装/更新运行时 + 预览图依赖,并立刻做一次真实 MCP 握手
~/.deta/bin/deta status # 运行时来源(版本 / 提交 / 哈希)、凭据来源、工作区
~/.deta/bin/deta doctor # 端到端自检:运行时 / 凭据 / 编译服务 / MCP 握手
```
**装完即用**:没有额外安装步骤,也不需要终端。需要云侧能力(项目列表 / 新建项目 / 项目同步 /
打开 Studio)时:让助手调 `login` 工具 → 浏览器打开授权地址(首次输一次账号密码或邮箱验证码)→
点「登录并授权」;令牌自动写入 `~/.deta` 并即时生效,过期先静默续期。
命令行形态(无 `login` 工具)的兜底及排查(助手用法见 `plugins/studio/README.md`):
```bash
~/.deta/bin/deta login # 由启动器自动注册;账号密码或 --email-code <邮箱>
~/.deta/bin/deta doctor # 自检:运行时 / 凭据 / GSA / MCP 握手
```
## 本地迭代
插件内容改动后 Codex 不会自动感知,按官方流程打 cachebuster 版本号再重装:
```bash
python3.11 ~/.codex/skills/.system/plugin-creator/scripts/update_plugin_cachebuster.py \
~/Dev/ant/deta-agent-plugins/plugins/studio
codex plugin add studio@deta
```
(版本号形如 `0.1.0+codex.20260910020424`;重装后需开新会话才能加载新技能。)
开发态要跑**工作树**(而不是插件包里那份打包运行时)时,显式指定运行时根:
```bash
DETA_SERVER_ROOT=<领域服务仓库所在路径> bash plugins/studio/bin/deta-mcp.sh --profile studio
```
领域服务改动后,要把新产物同步进插件包(否则同事与你自己装的都是旧运行时),
并顺手升插件版本(契约校验会拦下版本与运行时不一致的情况):
```bash
node scripts/sync-runtime.mjs
node scripts/check-plugin-contract.mjs
bash scripts/verify-runtime-provision.sh # 运行时供给探针(全新 HOME 下 10 项断言)
```
校验清单:
```bash
python3.11 ~/.codex/skills/.system/plugin-creator/scripts/validate_plugin.py \
~/Dev/ant/deta-agent-plugins/plugins/studio
node scripts/check-plugin-contract.mjs # 本仓章程校验(CI 同款)
codex plugin marketplace list
codex mcp list | grep -i studio # 应显示 stdio 形态(Command 列)与 studio_mcp
```
## 接入 WorkBuddy
WorkBuddy 的自定义 MCP 支持 command/args 形态(经其二进制的配置哈希实现取证确认),
因此可以拿到与 Codex 同款的本机 full 工具面:
```bash
~/.deta/bin/deta install-workbuddy # 写 ~/.workbuddy/mcp.json(本机 stdio)+ 装技能 + 握手自证
```
- 稳定入口是 `~/.deta/bin/deta-mcp-<档位>`(随插件升级自动刷新;WorkBuddy 对 MCP 的信任按命令行
算哈希,入口路径稳定 ⇒ 插件升级后不再重弹信任确认);
- 领域技能随安装装进 `~/.workbuddy/skills/`(与 Codex 插件内的是同一份,单一事实源);
- 装完**退出并重启 WorkBuddy**,首次会弹「是否信任 MCP 服务器」→ 点允许,开新对话即可用;
- 无本机运行时的机器用 `~/.deta/bin/deta install-workbuddy --http` 回落为远程引擎面(deta.city,OAuth 授权);
- 验收:`bash scripts/verify-workbuddy.sh`(配置形态 / 稳定入口 / 技能 / 真实握手 / WB 日志);
- **插件升级后重跑一次 `deta install-workbuddy`**(幂等:刷新稳定入口指向与技能内容;不重跑则 WB 仍拉起旧副本)。
## 双壳架构(Codex + dsh 同一产物)
`plugins/studio/` 这一个目录同时是 Codex 插件根与 dsh 组合包根,共享核心、各带一层薄壳:
| 组成 | 文件 | Codex | dsh |
|------|------|-------|-----|
| 插件清单 | `.codex-plugin/plugin.json`(`name` = 产品名) | ✅ 使用 | — |
| MCP 声明 | `.mcp.json`(stdio → `bin/deta-mcp.sh --profile <产品>`,`serverName` = `<产品>_mcp`) | ✅ 使用(可放 Codex 私有键) | — |
| 组合包声明 | `package.json`(`dsh.bundle.patch`) | 忽略 | ✅ 使用 |
| 配置层 | `cordis.patch.yml`(同一启动器,stdio,`serverName` = `<产品>_mcp`) | 忽略 | ✅ 使用 |
| 宿主侧技能 | `skills/aml-design/SKILL.md` | ✅ 共享 | ✅ 共享 |
| 启动器 | `bin/deta-mcp.sh` | ✅ 每产品一份(同一实现,产品差异走 `--profile`) | ✅ |
共享面(两端一致,零适配):
- **技能文件格式**:`<name>/SKILL.md` + frontmatter 必填 `name`/`description`,kebab-case。
Codex 与 dsh(`@deepseek-ai/dsh-skill-filesystem`)要求相同。
- **共享技能根**:两端都扫描 `~/.agents/skills/` 与 `<项目>/.agents/skills/`
(dsh 侧为 rank 500 / 200 的发现根,且显式支持 `<agentsHome>/skills`)。
- **MCP 工具命名**:两端同为 `mcp__<serverName>__<tool>`,我们统一 `serverName = deta`。
各自不同的部分(不共享):
- MCP 的声明位置不同(Codex 读 `.mcp.json`,dsh 读 `cordis.patch.yml` 的 mcp-client 行),
但**都指向同一个启动器**。
- Codex 私有键(`default_tools_approval_mode`、`omit_tools_from`)只写在 `.mcp.json`。
- 分发渠道不同:Codex 走 git 市场,dsh 走 npm / git / tarball。
### dsh 侧安装与验证
```bash
export DETA_PLUGIN_ROOT=~/Dev/ant/deta-agent-plugins/plugins/studio
dsh plugin --profile <name> add "$DETA_PLUGIN_ROOT"
# 只验证配置层是否合并正确(不启动、不需凭据)
cd ~/Dev/ant/deepseek-harness
node apps/cli/lib/bin.js --profile headless --dump-config \
--patch "$DETA_PLUGIN_ROOT/cordis.patch.yml"
# 输出中应出现 `# == .../plugins/studio/cordis.patch.yml` 与 deta-mcp(transport: stdio)
```
## 已知缺陷(实测)
**上游:编码代理 × 模型服务 命名空间重复** —— 会话累积较多本插件工具调用后,代理会在请求里
重复声明 MCP 命名空间,模型服务的 Responses 兼容层拒绝并报
`Duplicate namespace name 'deta'; Namespace names must be unique.`。
应对:完成一个任务后另起会话;撞到该错误不要重试(工作区文件保留)。
复现记录与已排除手段见 `plugins/studio/README.md`。
## 已修缺陷(实测)
| 现象 | 根因 | 修复 |
|------|------|------|
| 写类工具返回 `user cancelled MCP tool call` | MCP 工具默认需审批,非交互模式无法弹窗 | `.mcp.json` 声明 `default_tools_approval_mode: "approve"` |
| 本机 stdio 形态起不来:`ERR_UNSUPPORTED_DIR_IMPORT` | 启动器指向未打包的产物(依赖包目录 import 在 Node ESM 下非法) | 领域服务提供打包入口;启动器优先取打包产物,回落未打包产物时打印警告 |
| 一个插件两种形态并存(远程 URL + 本机 stdio) | 历史遗留,语义冲突 | 统一为本机 stdio 单一管道 |
| 启动器把开发检出当唯一运行前提 | 默认值写死开发检出路径 | 运行时按 `DETA_SERVER_ROOT → ~/.deta/runtime → 开发检出` 解析,回落时打印提示 |
## 目录结构
```
.agents/plugins/marketplace.json # Codex 默认市场(ChatGPT 登录用户)
.agents/plugins/api_marketplace.json # Codex API key 登录用户市场
.gitea/workflows/ci.yml # CI:跑 scripts/check-plugin-contract.mjs
scripts/check-plugin-contract.mjs # 仓库章程校验(工具清单 / 内部实现 / 开发检出依赖)
plugins/studio/ # 产品插件:同一目录 = Codex 插件根 = dsh 组合包根
├── .codex-plugin/plugin.json # Codex 插件清单(name: studio)
├── .mcp.json # Codex MCP 声明(studio_mcp → ./bin/deta-mcp.sh --profile studio)
├── package.json # dsh 组合包声明(dsh.bundle.patch)
├── cordis.patch.yml # dsh 配置层(同一启动器,serverName: studio_mcp)
├── bin/deta-login.mjs # 登录助手(~/.deta/credentials.json + ~/.deta/env)
├── bin/deta-mcp.sh # 本机 stdio 启动器(多产品共用;--profile 区分档位)
├── README.md # 插件说明(连接形态 / 凭据 / 排障)
└── skills/aml-design/SKILL.md # 宿主侧技能(不含工具清单)
plugins/writer/ # 产品插件:报告/文档产出
├── .codex-plugin/plugin.json # Codex 插件清单(name: writer)
├── .mcp.json # Codex MCP 声明(writer_mcp → ./bin/deta-mcp.sh --profile writer)
├── package.json # dsh 组合包声明(dsh.bundle.patch)
├── cordis.patch.yml # dsh 配置层(同一启动器,serverName: writer_mcp)
├── bin/deta-login.mjs # 登录助手(云侧能力用)
├── bin/deta-mcp.sh # 本机 stdio 启动器(同一实现;缺省档位 writer)
├── README.md # 插件说明(连接形态 / 能力边界 / 排障)
└── skills/report-authoring/SKILL.md # 宿主侧技能(报告取数与纪律)
```