Files
sproutclaw/.pi/agent/extensions/sproutclaw-setup/index.ts
root 675dd18182
Some checks failed
CI / build-check-test (push) Has been cancelled
chore: sync latest workspace updates
2026-06-15 13:38:22 +08:00

190 lines
5.1 KiB
TypeScript
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.
/**
* sproutclaw / mengya 命令安装扩展
*
* 在 Linux 和 Windows 上分别创建/更新以下命令:
* - mengya源码版Linux: ./pi-test.shWindows: pi-test.bat
* - sproutclaw构建版Linux: ./pi-built.shWindows: 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");
}
},
});
}