pai-zero 0.8.0 → 0.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin/pai.js +188 -32
- package/dist/bin/pai.js.map +1 -1
- package/dist/cli/index.js +188 -32
- package/dist/cli/index.js.map +1 -1
- package/package.json +6 -1
package/dist/cli/index.js
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
var __defProp = Object.defineProperty;
|
|
2
2
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
3
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
4
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
5
|
+
}) : x)(function(x) {
|
|
6
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
7
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
8
|
+
});
|
|
3
9
|
var __esm = (fn, res) => function __init() {
|
|
4
10
|
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
5
11
|
};
|
|
@@ -816,8 +822,12 @@ var platform_exports = {};
|
|
|
816
822
|
__export(platform_exports, {
|
|
817
823
|
diagnoseWindowsEnv: () => diagnoseWindowsEnv,
|
|
818
824
|
getPlatformInfo: () => getPlatformInfo,
|
|
825
|
+
getShellRcPath: () => getShellRcPath,
|
|
826
|
+
getYoloAliasLine: () => getYoloAliasLine,
|
|
827
|
+
hasYoloAlias: () => hasYoloAlias,
|
|
819
828
|
isMac: () => isMac,
|
|
820
829
|
isWindows: () => isWindows,
|
|
830
|
+
spawnSubshell: () => spawnSubshell,
|
|
821
831
|
writeEnvFile: () => writeEnvFile
|
|
822
832
|
});
|
|
823
833
|
import os from "os";
|
|
@@ -860,6 +870,41 @@ function getPlatformInfo() {
|
|
|
860
870
|
nodeVersion: process.version
|
|
861
871
|
};
|
|
862
872
|
}
|
|
873
|
+
function getShellRcPath() {
|
|
874
|
+
const home = os.homedir();
|
|
875
|
+
if (isWindows) {
|
|
876
|
+
const ps7 = __require("path").join(home, "Documents", "PowerShell", "Microsoft.PowerShell_profile.ps1");
|
|
877
|
+
const ps5 = __require("path").join(home, "Documents", "WindowsPowerShell", "Microsoft.PowerShell_profile.ps1");
|
|
878
|
+
if (fs3.existsSync(__require("path").dirname(ps7))) return ps7;
|
|
879
|
+
return ps5;
|
|
880
|
+
}
|
|
881
|
+
const shell = process.env["SHELL"] || "";
|
|
882
|
+
return shell.includes("zsh") ? __require("path").join(home, ".zshrc") : __require("path").join(home, ".bashrc");
|
|
883
|
+
}
|
|
884
|
+
function spawnSubshell(cwd) {
|
|
885
|
+
const { execFileSync } = __require("child_process");
|
|
886
|
+
try {
|
|
887
|
+
if (isWindows) {
|
|
888
|
+
execFileSync("powershell.exe", ["-NoExit", "-Command", `Set-Location '${cwd}'`], {
|
|
889
|
+
stdio: "inherit",
|
|
890
|
+
cwd
|
|
891
|
+
});
|
|
892
|
+
} else {
|
|
893
|
+
const shell = process.env["SHELL"] || "/bin/zsh";
|
|
894
|
+
execFileSync(shell, ["-l"], { stdio: "inherit", cwd });
|
|
895
|
+
}
|
|
896
|
+
} catch {
|
|
897
|
+
}
|
|
898
|
+
}
|
|
899
|
+
function getYoloAliasLine() {
|
|
900
|
+
if (isWindows) {
|
|
901
|
+
return "function claude-yolo { claude --dangerously-skip-permissions @args }";
|
|
902
|
+
}
|
|
903
|
+
return "alias claude-yolo='claude --dangerously-skip-permissions'";
|
|
904
|
+
}
|
|
905
|
+
function hasYoloAlias(rcContent) {
|
|
906
|
+
return rcContent.includes("claude-yolo") || rcContent.includes("dangerously-skip-permissions");
|
|
907
|
+
}
|
|
863
908
|
var isWindows, isMac;
|
|
864
909
|
var init_platform = __esm({
|
|
865
910
|
"src/utils/platform.ts"() {
|
|
@@ -1035,7 +1080,11 @@ async function provisionGitHub(ctx) {
|
|
|
1035
1080
|
"",
|
|
1036
1081
|
"# Logs",
|
|
1037
1082
|
"*.log",
|
|
1038
|
-
"npm-debug.log*"
|
|
1083
|
+
"npm-debug.log*",
|
|
1084
|
+
"",
|
|
1085
|
+
"# Windows",
|
|
1086
|
+
"desktop.ini",
|
|
1087
|
+
"$RECYCLE.BIN/"
|
|
1039
1088
|
].join("\n") + "\n");
|
|
1040
1089
|
}
|
|
1041
1090
|
}
|
|
@@ -2846,9 +2895,14 @@ async function requestCdAfter(targetDir) {
|
|
|
2846
2895
|
}
|
|
2847
2896
|
async function installShellHelper() {
|
|
2848
2897
|
await fs10.ensureDir(PAI_DIR);
|
|
2849
|
-
|
|
2850
|
-
|
|
2851
|
-
|
|
2898
|
+
if (isWindows) {
|
|
2899
|
+
return installPowerShellHelper();
|
|
2900
|
+
}
|
|
2901
|
+
return installBashHelper();
|
|
2902
|
+
}
|
|
2903
|
+
async function installBashHelper() {
|
|
2904
|
+
await fs10.writeFile(HELPER_FILE_SH, BASH_HELPER);
|
|
2905
|
+
const rcFile = getShellRcPath();
|
|
2852
2906
|
const sourceLine = 'source "$HOME/.pai/shell-helper.sh"';
|
|
2853
2907
|
if (await fs10.pathExists(rcFile)) {
|
|
2854
2908
|
const content = await fs10.readFile(rcFile, "utf8");
|
|
@@ -2865,15 +2919,36 @@ ${sourceLine}
|
|
|
2865
2919
|
`);
|
|
2866
2920
|
return false;
|
|
2867
2921
|
}
|
|
2868
|
-
|
|
2922
|
+
async function installPowerShellHelper() {
|
|
2923
|
+
await fs10.writeFile(HELPER_FILE_PS1, POWERSHELL_HELPER);
|
|
2924
|
+
const rcFile = getShellRcPath();
|
|
2925
|
+
const sourceLine = '. "$env:USERPROFILE\\.pai\\shell-helper.ps1"';
|
|
2926
|
+
await fs10.ensureDir(join7(rcFile, ".."));
|
|
2927
|
+
if (await fs10.pathExists(rcFile)) {
|
|
2928
|
+
const content = await fs10.readFile(rcFile, "utf8");
|
|
2929
|
+
if (content.includes("shell-helper.ps1")) {
|
|
2930
|
+
return true;
|
|
2931
|
+
}
|
|
2932
|
+
await fs10.appendFile(rcFile, `
|
|
2933
|
+
# PAI \u2014 \uC790\uB3D9 \uB514\uB809\uD1A0\uB9AC \uC774\uB3D9
|
|
2934
|
+
${sourceLine}
|
|
2935
|
+
`);
|
|
2936
|
+
return false;
|
|
2937
|
+
}
|
|
2938
|
+
await fs10.writeFile(rcFile, `${sourceLine}
|
|
2939
|
+
`);
|
|
2940
|
+
return false;
|
|
2941
|
+
}
|
|
2942
|
+
var PAI_DIR, CD_FILE, HELPER_FILE_SH, HELPER_FILE_PS1, BASH_HELPER, POWERSHELL_HELPER;
|
|
2869
2943
|
var init_shell_cd = __esm({
|
|
2870
2944
|
"src/utils/shell-cd.ts"() {
|
|
2871
2945
|
"use strict";
|
|
2946
|
+
init_platform();
|
|
2872
2947
|
PAI_DIR = join7(homedir2(), ".pai");
|
|
2873
2948
|
CD_FILE = join7(PAI_DIR, ".cd-after");
|
|
2874
|
-
|
|
2875
|
-
|
|
2876
|
-
|
|
2949
|
+
HELPER_FILE_SH = join7(PAI_DIR, "shell-helper.sh");
|
|
2950
|
+
HELPER_FILE_PS1 = join7(PAI_DIR, "shell-helper.ps1");
|
|
2951
|
+
BASH_HELPER = `# PAI shell helper \u2014 \uC790\uB3D9 \uB514\uB809\uD1A0\uB9AC \uC774\uB3D9 \uC9C0\uC6D0
|
|
2877
2952
|
pai() {
|
|
2878
2953
|
local cd_target="$HOME/.pai/.cd-after"
|
|
2879
2954
|
rm -f "$cd_target"
|
|
@@ -2890,6 +2965,24 @@ pai() {
|
|
|
2890
2965
|
fi
|
|
2891
2966
|
return $exit_code
|
|
2892
2967
|
}
|
|
2968
|
+
`;
|
|
2969
|
+
POWERSHELL_HELPER = `# PAI shell helper \u2014 \uC790\uB3D9 \uB514\uB809\uD1A0\uB9AC \uC774\uB3D9 \uC9C0\uC6D0
|
|
2970
|
+
function pai {
|
|
2971
|
+
$cdTarget = Join-Path $env:USERPROFILE '.pai\\.cd-after'
|
|
2972
|
+
Remove-Item $cdTarget -ErrorAction SilentlyContinue
|
|
2973
|
+
$env:PAI_CD_AFTER = $cdTarget
|
|
2974
|
+
& npx pai-zero @args
|
|
2975
|
+
$exitCode = $LASTEXITCODE
|
|
2976
|
+
if (Test-Path $cdTarget) {
|
|
2977
|
+
$dir = Get-Content $cdTarget -Raw
|
|
2978
|
+
Remove-Item $cdTarget -ErrorAction SilentlyContinue
|
|
2979
|
+
if ($dir -and (Test-Path $dir)) {
|
|
2980
|
+
Set-Location $dir
|
|
2981
|
+
Write-Host " -> cd $dir"
|
|
2982
|
+
}
|
|
2983
|
+
}
|
|
2984
|
+
return $exitCode
|
|
2985
|
+
}
|
|
2893
2986
|
`;
|
|
2894
2987
|
}
|
|
2895
2988
|
});
|
|
@@ -3402,16 +3495,16 @@ async function showCompletion(projectName, projectDir, extraTools, isCurrentDir)
|
|
|
3402
3495
|
success("\uC774\uC81C Claude Code\uC640 \uD568\uAED8 PRD \uBB38\uC11C\uB97C \uC791\uC131\uD558\uC138\uC694.");
|
|
3403
3496
|
console.log("");
|
|
3404
3497
|
console.log(colors.dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
3405
|
-
const {
|
|
3406
|
-
const shellRc =
|
|
3407
|
-
let
|
|
3498
|
+
const { getShellRcPath: getShellRcPath2, hasYoloAlias: checkYolo } = await Promise.resolve().then(() => (init_platform(), platform_exports));
|
|
3499
|
+
const shellRc = getShellRcPath2();
|
|
3500
|
+
let hasYoloAliasSet = false;
|
|
3408
3501
|
try {
|
|
3409
3502
|
const rcContent = await fs12.readFile(shellRc, "utf8");
|
|
3410
|
-
|
|
3503
|
+
hasYoloAliasSet = checkYolo(rcContent);
|
|
3411
3504
|
} catch {
|
|
3412
3505
|
}
|
|
3413
3506
|
let useYolo = false;
|
|
3414
|
-
if (!
|
|
3507
|
+
if (!hasYoloAliasSet) {
|
|
3415
3508
|
console.log("");
|
|
3416
3509
|
const { mode } = await inquirer.prompt([{
|
|
3417
3510
|
type: "list",
|
|
@@ -3424,10 +3517,12 @@ async function showCompletion(projectName, projectDir, extraTools, isCurrentDir)
|
|
|
3424
3517
|
}]);
|
|
3425
3518
|
if (mode === "yolo") {
|
|
3426
3519
|
useYolo = true;
|
|
3427
|
-
const
|
|
3520
|
+
const { getYoloAliasLine: getYoloAliasLine2 } = await Promise.resolve().then(() => (init_platform(), platform_exports));
|
|
3521
|
+
const aliasLine = getYoloAliasLine2();
|
|
3428
3522
|
try {
|
|
3429
3523
|
const rcContent = await fs12.readFile(shellRc, "utf8").catch(() => "");
|
|
3430
3524
|
if (!rcContent.includes("claude-yolo")) {
|
|
3525
|
+
await fs12.ensureDir(join10(shellRc, ".."));
|
|
3431
3526
|
await fs12.appendFile(shellRc, `
|
|
3432
3527
|
# PAI \u2014 claude-YOLO mode
|
|
3433
3528
|
${aliasLine}
|
|
@@ -3459,12 +3554,8 @@ ${aliasLine}
|
|
|
3459
3554
|
hint("claude \uB97C \uC785\uB825\uD558\uBA74 \uC2DC\uC791\uB429\uB2C8\uB2E4.");
|
|
3460
3555
|
console.log("");
|
|
3461
3556
|
if (!isCurrentDir) {
|
|
3462
|
-
|
|
3463
|
-
|
|
3464
|
-
const shell = process.env.SHELL || "/bin/zsh";
|
|
3465
|
-
execFileSync(shell, ["-l"], { stdio: "inherit", cwd: projectDir });
|
|
3466
|
-
} catch {
|
|
3467
|
-
}
|
|
3557
|
+
const { spawnSubshell: spawnSubshell2 } = await Promise.resolve().then(() => (init_platform(), platform_exports));
|
|
3558
|
+
spawnSubshell2(projectDir);
|
|
3468
3559
|
}
|
|
3469
3560
|
return;
|
|
3470
3561
|
}
|
|
@@ -3513,12 +3604,8 @@ ${aliasLine}
|
|
|
3513
3604
|
cwd: projectDir
|
|
3514
3605
|
});
|
|
3515
3606
|
if (!isCurrentDir) {
|
|
3516
|
-
|
|
3517
|
-
|
|
3518
|
-
const shell = process.env.SHELL || "/bin/zsh";
|
|
3519
|
-
execFileSync(shell, ["-l"], { stdio: "inherit", cwd: projectDir });
|
|
3520
|
-
} catch {
|
|
3521
|
-
}
|
|
3607
|
+
const { spawnSubshell: spawnSubshell2 } = await Promise.resolve().then(() => (init_platform(), platform_exports));
|
|
3608
|
+
spawnSubshell2(projectDir);
|
|
3522
3609
|
}
|
|
3523
3610
|
} catch {
|
|
3524
3611
|
warn(`\uC2E4\uD589 \uC2E4\uD328. \uC9C1\uC811 \uC785\uB825\uD558\uC138\uC694: ${cmd}`);
|
|
@@ -4527,12 +4614,8 @@ async function removeCommand(cwd, options) {
|
|
|
4527
4614
|
} else {
|
|
4528
4615
|
console.log("");
|
|
4529
4616
|
success(`\u2192 cd .. ${colors.dim("\uC0C1\uC704 \uD3F4\uB354\uB85C \uC774\uB3D9")}`);
|
|
4530
|
-
|
|
4531
|
-
|
|
4532
|
-
const shell = process.env.SHELL || "/bin/zsh";
|
|
4533
|
-
execFileSync(shell, ["-l"], { stdio: "inherit", cwd: parentDir });
|
|
4534
|
-
} catch {
|
|
4535
|
-
}
|
|
4617
|
+
const { spawnSubshell: spawnSubshell2 } = await Promise.resolve().then(() => (init_platform(), platform_exports));
|
|
4618
|
+
spawnSubshell2(parentDir);
|
|
4536
4619
|
}
|
|
4537
4620
|
}
|
|
4538
4621
|
var init_remove_cmd = __esm({
|
|
@@ -4942,6 +5025,8 @@ async function wakeupCommand(timeOrAction, schedule = "\uD3C9\uC77C") {
|
|
|
4942
5025
|
await createWakeupScript(config);
|
|
4943
5026
|
if (osPlatform() === "darwin") {
|
|
4944
5027
|
await setupMacOS(config);
|
|
5028
|
+
} else if (osPlatform() === "win32") {
|
|
5029
|
+
await setupWindows(config);
|
|
4945
5030
|
} else {
|
|
4946
5031
|
await setupLinux(config);
|
|
4947
5032
|
}
|
|
@@ -5022,6 +5107,70 @@ ${calendarEntries}
|
|
|
5022
5107
|
hint(`\uC218\uB3D9 \uC124\uC815: sudo pmset repeat wakeorpoweron ${pmsetDays} ${config.time}:00`);
|
|
5023
5108
|
}
|
|
5024
5109
|
}
|
|
5110
|
+
async function setupWindows(config) {
|
|
5111
|
+
const { execa } = await import("execa");
|
|
5112
|
+
const [hour, minute] = config.time.split(":").map(Number);
|
|
5113
|
+
const psScriptDir = join17(homedir3(), ".pai");
|
|
5114
|
+
await fs20.ensureDir(psScriptDir);
|
|
5115
|
+
const psScriptPath = join17(psScriptDir, "wakeup.ps1");
|
|
5116
|
+
const claudeCmd = config.launchMode === "yolo" ? "claude --dangerously-skip-permissions" : "claude";
|
|
5117
|
+
const psScript = `# PAI Wakeup \u2014 Claude Code \uC138\uC158 \uC790\uB3D9 \uC2DC\uC791
|
|
5118
|
+
$paiDir = "$env:USERPROFILE\\.pai"
|
|
5119
|
+
$msgFile = Join-Path $paiDir "wakeup-messages.json"
|
|
5120
|
+
$todayFile = Join-Path $paiDir "wakeup-today.txt"
|
|
5121
|
+
|
|
5122
|
+
# Pick random message
|
|
5123
|
+
try {
|
|
5124
|
+
$msgs = Get-Content $msgFile -Raw | ConvertFrom-Json
|
|
5125
|
+
$msg = $msgs[(Get-Random -Maximum $msgs.Count)]
|
|
5126
|
+
} catch {
|
|
5127
|
+
$msg = "Make it work, make it right, make it fast. \u2014 Kent Beck"
|
|
5128
|
+
}
|
|
5129
|
+
Set-Content -Path $todayFile -Value $msg
|
|
5130
|
+
|
|
5131
|
+
# Windows notification
|
|
5132
|
+
[Windows.UI.Notifications.ToastNotificationManager, Windows.UI.Notifications, ContentType = WindowsRuntime] | Out-Null
|
|
5133
|
+
$template = [Windows.UI.Notifications.ToastTemplateType]::ToastText02
|
|
5134
|
+
$xml = [Windows.UI.Notifications.ToastNotificationManager]::GetTemplateContent($template)
|
|
5135
|
+
$text = $xml.GetElementsByTagName("text")
|
|
5136
|
+
$text[0].AppendChild($xml.CreateTextNode("PAI Wakeup")) | Out-Null
|
|
5137
|
+
$text[1].AppendChild($xml.CreateTextNode($msg.Substring(0, [Math]::Min(100, $msg.Length)))) | Out-Null
|
|
5138
|
+
$notifier = [Windows.UI.Notifications.ToastNotificationManager]::CreateToastNotifier("PAI")
|
|
5139
|
+
$notifier.Show([Windows.UI.Notifications.ToastNotification]::new($xml))
|
|
5140
|
+
|
|
5141
|
+
# Open PowerShell with Claude Code
|
|
5142
|
+
Start-Process powershell -ArgumentList "-NoExit", "-Command", "Get-Content '$todayFile'; Write-Host ''; Set-Location '${config.projectDir}'; ${claudeCmd}"
|
|
5143
|
+
`;
|
|
5144
|
+
await fs20.writeFile(psScriptPath, psScript, "utf8");
|
|
5145
|
+
const daysMap = {
|
|
5146
|
+
"\uD3C9\uC77C": "MON,TUE,WED,THU,FRI",
|
|
5147
|
+
"\uB9E4\uC77C": "MON,TUE,WED,THU,FRI,SAT,SUN",
|
|
5148
|
+
"\uC8FC\uB9D0": "SAT,SUN"
|
|
5149
|
+
};
|
|
5150
|
+
const days = daysMap[config.schedule] || daysMap["\uD3C9\uC77C"];
|
|
5151
|
+
await execa("schtasks", ["/delete", "/tn", "PAI-WAKEUP", "/f"]).catch(() => {
|
|
5152
|
+
});
|
|
5153
|
+
try {
|
|
5154
|
+
await execa("schtasks", [
|
|
5155
|
+
"/create",
|
|
5156
|
+
"/tn",
|
|
5157
|
+
"PAI-WAKEUP",
|
|
5158
|
+
"/tr",
|
|
5159
|
+
`powershell.exe -ExecutionPolicy Bypass -File "${psScriptPath}"`,
|
|
5160
|
+
"/sc",
|
|
5161
|
+
"WEEKLY",
|
|
5162
|
+
"/d",
|
|
5163
|
+
days,
|
|
5164
|
+
"/st",
|
|
5165
|
+
`${String(hour).padStart(2, "0")}:${String(minute).padStart(2, "0")}`,
|
|
5166
|
+
"/f"
|
|
5167
|
+
]);
|
|
5168
|
+
success("Windows Task Scheduler \uB4F1\uB85D \uC644\uB8CC");
|
|
5169
|
+
} catch {
|
|
5170
|
+
warn("Task Scheduler \uB4F1\uB85D \uC2E4\uD328");
|
|
5171
|
+
hint("\uAD00\uB9AC\uC790 \uAD8C\uD55C\uC73C\uB85C \uC7AC\uC2DC\uB3C4\uD558\uAC70\uB098, \uC791\uC5C5 \uC2A4\uCF00\uC904\uB7EC\uC5D0\uC11C \uC9C1\uC811 \uB4F1\uB85D\uD558\uC138\uC694");
|
|
5172
|
+
}
|
|
5173
|
+
}
|
|
5025
5174
|
async function setupLinux(config) {
|
|
5026
5175
|
const { execa } = await import("execa");
|
|
5027
5176
|
const cronExpr = scheduleToCron(config.time, config.schedule);
|
|
@@ -5051,6 +5200,13 @@ async function disableWakeup() {
|
|
|
5051
5200
|
} catch {
|
|
5052
5201
|
hint("\uC218\uB3D9 \uD574\uC81C: sudo pmset repeat cancel");
|
|
5053
5202
|
}
|
|
5203
|
+
} else if (osPlatform() === "win32") {
|
|
5204
|
+
try {
|
|
5205
|
+
await execa("schtasks", ["/delete", "/tn", "PAI-WAKEUP", "/f"]);
|
|
5206
|
+
success("Windows Task Scheduler \uC81C\uAC70 \uC644\uB8CC");
|
|
5207
|
+
} catch {
|
|
5208
|
+
hint("\uC218\uB3D9 \uD574\uC81C: schtasks /delete /tn PAI-WAKEUP /f");
|
|
5209
|
+
}
|
|
5054
5210
|
} else {
|
|
5055
5211
|
await removeCronEntry();
|
|
5056
5212
|
}
|