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