/** * sproutclaw / mengya 命令安装扩展 * * 启动后自动在 /usr/local/bin/ 下创建 mengya 和 sproutclaw 命令: * - mengya:源码版(./pi-test.sh,tsx + src) * - sproutclaw:构建版(./pi-built.sh,node dist/cli.js) * * 命令 /install-commands 可随时手动重装。 */ import { existsSync, writeFileSync, chmodSync, readFileSync } from "node:fs"; import type { ExtensionAPI } from "@earendil-works/pi-coding-agent"; const SPROUTCLAW_DIR = "/shumengya/project/agent/sproutclaw"; const BIN_DIR = "/usr/local/bin"; const COMMAND_LAUNCHERS: Record = { mengya: "./pi-test.sh", }; function commandScript(launcher: string): string { return `#!/usr/bin/env bash set -euo pipefail cd ${SPROUTCLAW_DIR} exec ${launcher} "$@" `; } function sproutclawScript(): string { return `#!/usr/bin/env bash set -euo pipefail cd ${SPROUTCLAW_DIR} case "\${1:-}" in \tbuild) \t\tshift \t\texec npm run build "\$@" \t\t;; \trun) \t\tshift \t\texec ./pi-built.sh "\$@" \t\t;; \thelp|-h|--help) \t\tcat <<'EOF' sproutclaw - SproutClaw pi 构建版启动器 用法: sproutclaw 启动 pi(构建版) sproutclaw run [args] 同 sproutclaw sproutclaw build 从源码构建所有包 其余参数透传给 pi,例如: sproutclaw --version EOF \t\t;; \t*) \t\texec ./pi-built.sh "\$@" \t\t;; esac `; } /** 创建或修复命令脚本 */ function installCommand(name: string, script: string): boolean { const path = `${BIN_DIR}/${name}`; if (existsSync(path)) { try { const current = readFileSync(path, "utf-8"); if (current === script) return false; } catch { // Rewrite unreadable or invalid command files below. } } writeFileSync(path, script, "utf-8"); chmodSync(path, 0o755); return true; } export default function (pi: ExtensionAPI) { for (const [name, launcher] of Object.entries(COMMAND_LAUNCHERS)) { const created = installCommand(name, commandScript(launcher)); if (created) { console.log(`[sproutclaw-setup] Created /usr/local/bin/${name}`); } } const sproutclawCreated = installCommand("sproutclaw", sproutclawScript()); if (sproutclawCreated) { console.log("[sproutclaw-setup] Created /usr/local/bin/sproutclaw"); } pi.registerCommand("install-commands", { description: "Install mengya (source) and sproutclaw (built) commands to /usr/local/bin", handler: async (_args, ctx) => { let count = 0; for (const [name, launcher] of Object.entries(COMMAND_LAUNCHERS)) { if (installCommand(name, commandScript(launcher))) count++; } if (installCommand("sproutclaw", sproutclawScript())) count++; if (count > 0) { ctx.ui.notify(`Installed ${count} command(s): mengya (source), sproutclaw (build/run)`, "success"); } else { ctx.ui.notify("Commands already up to date", "info"); } }, }); }