- 端点:走 /login(已存在账号的密码校验),不走门户的 /login-or-register(会触发登录即注册) - 新增 -u/--identifier:标识可用 用户名/已验证邮箱/已验证手机号(服务端 LoginIdentifierResolver 解析) - 新增 --email-code:邮箱验证码登录(账号未设密码时的可用路径) - 登录前匿名预检 /login/check:区分「标识未注册」与「密码不匹配」,避免误导性提示 - 失败提示按服务端 msg 映射可执行下一步(未验证/停用/登录方式未开放) - 修复 readLine:TTY 下一次粘贴多行会丢弃换行之后的剩余字符(第二次读取挂起)
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 <name> add ./plugins/deta |
能力本体(AML 建筑模型读写、编译校验、围护结构统计、空间邻接查询)以 MCP 服务提供, 同一份后端与技能被所有宿主复用;新增宿主只需再加一层声明式壳。
命名约定:
ant为内部开发代号,不对外出现;对外产品名统一为 DETA。 插件、市场、MCP 服务、技能一律使用 deta 命名。
安装(Codex)
# 先登录(一次性,需要 deta.city 账号):换取 DETA_TOKEN
node ~/Dev/ant/deta-agent-plugins/plugins/deta/bin/deta-login.mjs
source ~/.deta/env # 让 DETA_TOKEN 进入当前 shell 环境
# 从 Git(分发用)
codex plugin marketplace add https://git.deta.city/deta/deta-agent-plugins.git
# 或本地路径(开发用)
codex plugin marketplace add ~/Dev/ant/deta-agent-plugins
codex plugin list
codex plugin add deta@deta
未登录(环境里没有 DETA_TOKEN)时,MCP 端点会返回 401——含义是
「当前环境没有可用的 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 账号、不隔离工作区,仅供本机迭代领域能力:
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 |
<cwd>/workspace |
AML 工作目录(aml.xml / building.json 落盘处,名称由底层服务决定) |
编译与校验类工具需要编译服务在线(服务端为 DETA_GSA_URL,缺省 localhost:8000);
未在线时返回明确错误,读写类工具可离线工作。
本地迭代
插件内容改动后 Codex 不会自动感知,按官方流程打 cachebuster 版本号再重装:
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;重装后需开新会话才能加载新技能。)
校验清单:
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 直接指向服务入口 |
共享面(两端一致,零适配):
- 技能文件格式:
<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, 因此技能里写裸工具名(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 侧安装与验证
# 安装进某个 profile(pnpm 转发)
dsh plugin --profile <name> add ~/Dev/ant/deta-agent-plugins/plugins/deta
# 公开发布形态(二选一)
npm publish # 用户:dsh plugin --profile <name> add deta-plugin
dsh plugin --profile <name> 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 # 领域技能(两宿主共享)