feat(hosts): WorkBuddy 接入(install-workbuddy:本机 stdio + 技能安装 + 握手自证)
CI / contract (push) Has been cancelled

WorkBuddy 自定义 MCP 支持 command/args/env(取证:其二进制 calculateConfigHash 先判 entry.command),因此走与 Codex 同款的本机 stdio full 工具面,不退远程引擎面。

落地:① 启动器多维护一个 MCP 稳定入口 ~/.deta/bin/deta-mcp-<档位>(指向当前插件副本,升级自动刷新;WB 信任哈希按命令行算,路径稳定=升级不重弹信任);② deta-cli 新增 install-workbuddy [--http]——备份并合并 ~/.workbuddy/mcp.json(同名旧条目与旧远程条目替换掉,防双工具面)、把插件内全部技能装进 ~/.workbuddy/skills/(单一事实源,带 icon.svg)、用宿主将执行的同一条命令做真实握手自证;③ aml-design 技能两处 Codex 特有措辞改宿主中立;④ 契约校验加 E7(装配源齐备 + README 指引);⑤ 探针 scripts/verify-workbuddy.sh(配置形态/稳定入口/技能/握手/WB 日志,5 项断言)。

实测:studio 0.3.16 已装副本重跑幂等通过(握手 39 工具);writer 0.1.7 在沙箱 HOME 验证(deta_writer + report-authoring 技能 + 握手 39 工具)。WB 侧需重启并点一次信任确认。
This commit is contained in:
ringo
2026-09-20 17:13:15 +08:00
parent 7ca4923ac3
commit 1d1000ddf5
16 changed files with 411 additions and 26 deletions
+26
View File
@@ -85,6 +85,11 @@ const RULES = {
what: '运行时包不自洽(缺 runtime/、sha256 或字节数与 manifest 不符、manifest.pluginVersion 与插件版本不符)',
hint: '运行时随插件分发:改动 ant-copilot 后跑 node scripts/sync-runtime.mjs,再升插件版本重装',
},
E7: {
level: 'error',
what: 'WorkBuddy 接入的装配源不齐:插件 skills/ 下没有技能目录,或 README 未写 install-workbuddy',
hint: 'install-workbuddy 把插件内技能装进 ~/.workbuddy/skills/(单一事实源),且 README 必须给用户这条路径',
},
};
const HEADING_BAN = /工具一览|工具清单|工具列表|工具汇总|可用工具|能力一览|能力清单/;
@@ -222,6 +227,27 @@ for (const pluginDir of ['plugins/studio', 'plugins/writer']) {
}
}
// E7:WorkBuddy 接入的装配源(插件技能目录)与 README 指引
for (const pluginDir of ['plugins/studio', 'plugins/writer']) {
const skillsDir = join(ROOT, pluginDir, 'skills');
let count = 0;
if (existsSync(skillsDir)) {
for (const name of readdirSync(skillsDir)) {
if (existsSync(join(skillsDir, name, 'SKILL.md'))) count += 1;
}
}
if (count === 0) {
add('E7', skillsDir, 1, 'skills/ 下没有任何含 SKILL.md 的技能目录(install-workbuddy 的装配源缺失)');
}
}
{
const readmePath = join(ROOT, 'README.md');
const readme = existsSync(readmePath) ? readFileSync(readmePath, 'utf8') : '';
if (!readme.includes('install-workbuddy')) {
add('E7', readmePath, 1, 'README 未写 install-workbuddy(WorkBuddy 用户没有安装路径)');
}
}
if (process.argv.includes('--json')) {
console.log(JSON.stringify({ findings, rules: RULES }, null, 2));
} else {
+87
View File
@@ -0,0 +1,87 @@
#!/usr/bin/env bash
# 探针:WorkBuddy 接入(deta install-workbuddy 的验收)
#
# 断言:
# ① ~/.workbuddy/mcp.json 合法且含 deta_<档位> 的 stdio 条目(command 指向稳定入口,无残留远程条目)
# ② 稳定入口 ~/.deta/bin/deta-mcp-<档位> 存在且可执行
# ③ 技能 ~/.workbuddy/skills/aml-design/ 已安装(SKILL.md + icon.svg)
# ④ 用宿主将要执行的同一条命令做真实 MCP 握手(报工具数)
# ⑤ WorkBuddy 日志里该 server 已握手(非致命:应用未重启时跳过)
#
# 用法:bash scripts/verify-workbuddy.sh [档位,缺省 studio]
set -u
PROFILE="${1:-studio}"
WB="$HOME/.workbuddy"
NAME="deta_${PROFILE}"
SHIM="$HOME/.deta/bin/deta-mcp-${PROFILE}"
pass=0
fail=0
ok() { printf ' PASS %s\n' "$1"; pass=$((pass + 1)); }
no() { printf ' FAIL %s\n' "$1"; fail=$((fail + 1)); }
warn() { printf ' WARN %s\n' "$1"; }
echo "== WorkBuddy 接入检查(档位=${PROFILE},服务名=${NAME})"
# ① 配置
if [ -f "$WB/mcp.json" ]; then
RESULT="$(python3 - "$WB/mcp.json" "$NAME" "$SHIM" <<'PY'
import json, sys
try:
d = json.load(open(sys.argv[1]))
except Exception as e:
print(f'ERR 配置不是合法 JSON: {e}'); sys.exit(0)
servers = (d.get('mcpServers') or {})
name, shim = sys.argv[2], sys.argv[3]
e = servers.get(name)
if not e:
print(f'ERR 缺少 {name} 条目'); sys.exit(0)
if e.get('type') != 'stdio':
print(f"ERR 形态不对: {e.get('type')}"); sys.exit(0)
if e.get('command') != shim:
print(f"ERR command 应为稳定入口: {e.get('command')}"); sys.exit(0)
legacy = [k for k in servers if k == 'deta_mcp']
if legacy:
print(f'ERR 仍残留远程条目: {legacy}'); sys.exit(0)
print('OK')
PY
)"
if [ "$RESULT" = "OK" ]; then ok "mcp.json 条目形态正确(stdio + 稳定入口,无残留)"; else no "$RESULT"; fi
else
no "没有 $WB/mcp.json"
fi
# ② 稳定入口
if [ -x "$SHIM" ]; then ok "稳定入口存在且可执行"; else no "稳定入口缺失或不可执行:$SHIM"; fi
# ③ 技能
if [ -f "$WB/skills/aml-design/SKILL.md" ]; then
if grep -q "list_capabilities" "$WB/skills/aml-design/SKILL.md"; then ok "技能已安装(SKILL.md 含能力目录指引)"; else no "技能内容不完整(缺 list_capabilities 指引)"; fi
if [ -f "$WB/skills/aml-design/icon.svg" ]; then ok "技能图标已安装"; else warn "技能图标缺失(icon.svg)"; fi
else
no "技能未安装:$WB/skills/aml-design/SKILL.md"
fi
# ④ 真实握手(与宿主将执行的是同一条命令)
if [ -x "$SHIM" ]; then
OUT="$(timeout 30 bash "$SHIM" < /dev/null 2>&1 || bash "$SHIM" < /dev/null 2>&1 || true)"
TOOLS="$(printf '%s' "$OUT" | grep -o '工具面: full([0-9]* 个)' | head -1)"
if [ -n "$TOOLS" ]; then ok "握手自证(${TOOLS})"; else no "握手失败:$(printf '%s' "$OUT" | head -2)"; fi
else
no "无法握手:稳定入口不存在"
fi
# ⑤ WorkBuddy 是否已加载(应用未重启时 WARN 而非 FAIL)
LDIR="$WB/logs/$(date +%Y-%m-%d)"
if [ -d "$LDIR" ]; then
if grep -hq "MCP-Connect.*ok configId=custom-mcp:${NAME}" "$LDIR"/*.log 2>/dev/null; then
ok "WorkBuddy 已握手(日志见 MCP-Connect ok)"
else
warn "今天的 WorkBuddy 日志里还没有 ${NAME} 的握手 —— 重启 WorkBuddy 后再看"
fi
else
warn "没有今天的 WorkBuddy 日志目录(应用今天没启动过?)"
fi
echo
echo "结果:${pass} 通过 / ${fail} 失败"
[ "$fail" -eq 0 ]