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/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
- await fs10.writeFile(HELPER_FILE, SHELL_HELPER);
2850
- const shellName = process.env.SHELL || "/bin/zsh";
2851
- const rcFile = shellName.includes("zsh") ? join7(homedir2(), ".zshrc") : join7(homedir2(), ".bashrc");
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
- var PAI_DIR, CD_FILE, HELPER_FILE, SHELL_HELPER;
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
- HELPER_FILE = join7(PAI_DIR, "shell-helper.sh");
2875
- SHELL_HELPER = `# PAI shell helper \u2014 \uC790\uB3D9 \uB514\uB809\uD1A0\uB9AC \uC774\uB3D9 \uC9C0\uC6D0
2876
- # pai \uBA85\uB839 \uC2E4\uD589 \uD6C4 .cd-after \uD30C\uC77C\uC774 \uC788\uC73C\uBA74 \uC790\uB3D9\uC73C\uB85C cd
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 { homedir: homedir4 } = await import("os");
3406
- const shellRc = join10(homedir4(), process.env.SHELL?.includes("zsh") ? ".zshrc" : ".bashrc");
3407
- let hasYoloAlias = false;
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
- hasYoloAlias = rcContent.includes("claude-yolo") || rcContent.includes("dangerously-skip-permissions");
3503
+ hasYoloAliasSet = checkYolo(rcContent);
3411
3504
  } catch {
3412
3505
  }
3413
3506
  let useYolo = false;
3414
- if (!hasYoloAlias) {
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 aliasLine = "alias claude-yolo='claude --dangerously-skip-permissions'";
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
- try {
3463
- const { execFileSync } = await import("child_process");
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
- try {
3517
- const { execFileSync } = await import("child_process");
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
- try {
4531
- const { execFileSync } = await import("child_process");
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
  }