/** * sproutclaw / mengya 命令安装扩展 * * 在 Linux 和 Windows 上分别创建/更新以下命令: * - mengya:源码版(Linux: ./pi-test.sh,Windows: pi-test.bat) * - sproutclaw:构建版(Linux: ./pi-built.sh,Windows: pi-built.bat) * * Linux 命令安装到 /usr/local/bin/。 * Windows 批处理文件创建在项目根目录,需要把项目根目录加入 PATH 后全局使用。 * * 命令 /install-commands 可随时手动重装。 */ import { existsSync, writeFileSync, chmodSync, readFileSync } from "node:fs"; import { dirname, join } from "node:path"; import { fileURLToPath } from "node:url"; import type { ExtensionAPI } from "@earendil-works/pi-coding-agent"; const extensionDir = typeof __dirname !== "undefined" ? __dirname : dirname(fileURLToPath(import.meta.url)); const SPROUTCLAW_DIR = dirname(dirname(dirname(dirname(extensionDir)))); const LINUX_BIN_DIR = "/usr/local/bin"; // ---------------------------- Linux scripts ---------------------------- function linuxMengyaScript(): string { return `#!/usr/bin/env bash set -euo pipefail cd "${SPROUTCLAW_DIR}" exec ./pi-test.sh "$@" `; } function linuxSproutclawScript(): 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 `; } // ---------------------------- Windows scripts ---------------------------- function windowsMengyaBat(): string { return `@echo off setlocal set "SCRIPT_DIR=%~dp0" if "%SCRIPT_DIR:~-1%"=="\" set "SCRIPT_DIR=%SCRIPT_DIR:~0,-1%" if not defined PI_CODING_AGENT_DIR ( set "PI_CODING_AGENT_DIR=%SCRIPT_DIR%\.pi\agent" ) call "%SCRIPT_DIR%\pi-test.bat" %* exit /b %ERRORLEVEL% `; } function windowsSproutclawBat(): string { return `@echo off setlocal set "SCRIPT_DIR=%~dp0" if "%SCRIPT_DIR:~-1%"=="\" set "SCRIPT_DIR=%SCRIPT_DIR:~0,-1%" if not defined PI_CODING_AGENT_DIR ( set "PI_CODING_AGENT_DIR=%SCRIPT_DIR%\.pi\agent" ) if "%~1"=="" goto run if /I "%~1"=="run" ( shift goto run ) if /I "%~1"=="build" ( shift npm run build %* exit /b %ERRORLEVEL% ) if /I "%~1"=="help" goto help if "%~1"=="-h" goto help if "%~1"=="--help" goto help :run call "%SCRIPT_DIR%\pi-built.bat" %* exit /b %ERRORLEVEL% :help echo sproutclaw - SproutClaw pi 构建版启动器 echo. echo 用法: echo sproutclaw 启动 pi(构建版) echo sproutclaw run [args] 同 sproutclaw echo sproutclaw build 从源码构建所有包 echo. echo 其余参数透传给 pi,例如: sproutclaw --version exit /b 0 `; } // ---------------------------- Install helpers ---------------------------- function writeIfChanged(path: string, content: string, mode?: number): boolean { if (existsSync(path)) { try { const current = readFileSync(path, "utf-8"); if (current === content) return false; } catch { // Rewrite unreadable or invalid files below. } } writeFileSync(path, content, "utf-8"); if (mode !== undefined) chmodSync(path, mode); return true; } function installLinuxCommands(): string[] { const created: string[] = []; if (writeIfChanged(join(LINUX_BIN_DIR, "mengya"), linuxMengyaScript(), 0o755)) { created.push("/usr/local/bin/mengya"); } if (writeIfChanged(join(LINUX_BIN_DIR, "sproutclaw"), linuxSproutclawScript(), 0o755)) { created.push("/usr/local/bin/sproutclaw"); } return created; } function installWindowsCommands(): string[] { const created: string[] = []; if (writeIfChanged(join(SPROUTCLAW_DIR, "mengya.bat"), windowsMengyaBat())) { created.push(join(SPROUTCLAW_DIR, "mengya.bat")); } if (writeIfChanged(join(SPROUTCLAW_DIR, "sproutclaw.bat"), windowsSproutclawBat())) { created.push(join(SPROUTCLAW_DIR, "sproutclaw.bat")); } return created; } // ---------------------------- Extension entry ---------------------------- export default function (pi: ExtensionAPI) { const isWindows = process.platform === "win32"; function install(): string[] { return isWindows ? installWindowsCommands() : installLinuxCommands(); } const created = install(); for (const path of created) { console.log(`[sproutclaw-setup] Created/updated ${path}`); } pi.registerCommand("install-commands", { description: isWindows ? "Install mengya.bat (source) and sproutclaw.bat (built) to the repo root" : "Install mengya (source) and sproutclaw (built) to /usr/local/bin", handler: async (_args, ctx) => { const paths = install(); if (paths.length > 0) { ctx.ui.notify(`Installed/updated ${paths.length} command(s):\n${paths.join("\n")}`, "success"); } else { ctx.ui.notify("Commands already up to date", "info"); } if (isWindows) { ctx.ui.notify(`请把项目目录加入 PATH 以全局使用:\n${SPROUTCLAW_DIR}`, "info"); } }, }); }