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