Files
deta-agent-plugins/README.md
T
ringo 54924cd4fc
CI / contract (push) Has been cancelled
feat(plugin): 稳定命令行入口 ~/.deta/bin/deta(login / status / doctor)
为什么需要:登录助手原先只在插件目录里(宿主缓存路径 <缓存>/bin/deta-login.mjs),普通用户不知道插件装在哪;工具回执让用户「跑登录助手」时给不出可复制的命令。

实现:新增 bin/deta-cli.mjs(login 转交登录助手、status 看凭据来源/运行时/工作区、doctor 自检运行时+凭据+GSA health+MCP 握手,永不打印令牌);启动器每次拉起时幂等注册 ~/.deta/bin/deta(路径随插件更新自动刷新,幂等比较避免重复写);技能与三份 README 的登录口径统一为 \`~/.deta/bin/deta login\`。版本 studio 0.3.3 / writer 0.1.1。

实测:shim 生成与 help/status/doctor 均符合预期,doctor 准确报出唯一缺口(未登录)并握手成功 37 工具。
2026-09-20 12:10:49 +08:00

197 lines
12 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)或源码构建
# 源码构建:在领域服务仓库执行 npm run build:mcp
# 冒烟(应等待 stdin/stdout)
bash plugins/studio/bin/deta-mcp.sh
```
装完即用,**没有 OAuth 登录步骤**。需要云侧能力(项目列表 / 项目同步 / 打开 Studio)时登录一次
(`~/.deta/bin/deta` 由启动器自动注册;助手用法见 `plugins/studio/README.md`「登录助手」):
```bash
~/.deta/bin/deta login # 账号密码 / 邮箱验证码由你本人输入
~/.deta/bin/deta doctor # 自检:运行时 / 凭据 / GSA / MCP 握手
# 登录后开新会话即可,无需 source / launchctl / 重启应用
```
## 本地迭代
插件内容改动后 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
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
```
## 双壳架构(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 # 宿主侧技能(报告取数与纪律)
```