pai-zero 0.7.15 → 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 +376 -51
- package/dist/bin/pai.js.map +1 -1
- package/dist/cli/index.js +376 -51
- package/dist/cli/index.js.map +1 -1
- package/package.json +1 -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
|
};
|
|
@@ -613,6 +619,18 @@ This project uses PAI (Plugin-based AI) for structured AI development.
|
|
|
613
619
|
- **Config**: \`.pai/config.json\`
|
|
614
620
|
|
|
615
621
|
Run \`pai env status\` to check setup, \`pai evaluate\` for quality scoring.
|
|
622
|
+
|
|
623
|
+
### Global Rules
|
|
624
|
+
|
|
625
|
+
- **\uC2EC\uCE35 \uC778\uD130\uBDF0 \uC790\uB3D9 \uC218\uD589**: \uCEE8\uD14D\uC2A4\uD2B8\uAC00 \uBD80\uC871\uD558\uAC70\uB098 \uBAA8\uD638\uD55C \uACBD\uC6B0, AskUserQuestion \uB3C4\uAD6C\uB97C \uC0AC\uC6A9\uD558\uC5EC \uC2EC\uCE35 \uC778\uD130\uBDF0\uB97C \uC790\uB3D9\uC73C\uB85C \uC9C4\uD589\uD569\uB2C8\uB2E4. \uCD94\uCE21\uD558\uC9C0 \uB9D0\uACE0 \uBC18\uB4DC\uC2DC \uC9C8\uBB38\uD558\uC138\uC694.
|
|
626
|
+
- **Ideation \u2192 PRD \uD30C\uC774\uD504\uB77C\uC778**: \`/pai design\` \uC2E4\uD589 \uC2DC ideation.md \u2192 openspec.md \uC21C\uC11C\uB85C \uC2EC\uCE35 \uC778\uD130\uBDF0\uB97C \uD1B5\uD574 \uC791\uC131\uD569\uB2C8\uB2E4.
|
|
627
|
+
- **\uAE30\uC220 \uC81C\uC57D \uD30C\uC545**: \uCF54\uB4DC \uC0DD\uC131 \uC804 \uAE30\uC220\uC801 \uC81C\uC57D \uC0AC\uD56D\uC744 \uC2EC\uCE35 \uC778\uD130\uBDF0\uB85C \uD655\uC778\uD569\uB2C8\uB2E4.
|
|
628
|
+
- **\uD558\uB124\uC2A4 \uC5D4\uC9C0\uB2C8\uC5B4\uB9C1**: AI \uC5D0\uC774\uC804\uD2B8\uAC00 \uC548\uC804\uD558\uAC8C \uC791\uC5C5\uD560 \uC218 \uC788\uB3C4\uB85D \uD14C\uC2A4\uD2B8/\uAC80\uC99D \uD658\uACBD\uC744 \uAD6C\uC131\uD569\uB2C8\uB2E4.
|
|
629
|
+
- **Git \uCEE4\uBC0B \uADDC\uCE59**: \uC791\uC5C5 \uB2E8\uC704\uBCC4\uB85C \uC758\uBBF8 \uC788\uB294 \uCEE4\uBC0B \uBA54\uC2DC\uC9C0\uB97C \uC791\uC131\uD569\uB2C8\uB2E4.
|
|
630
|
+
|
|
631
|
+
### Contribution Guide
|
|
632
|
+
|
|
633
|
+
\uAE30\uC5EC\uC790\uB294 \`CONTRIBUTING.md\`\uB97C \uCC38\uACE0\uD558\uC138\uC694. \uC774 \uAC00\uC774\uB4DC\uB294 \`.claude/skills/\`\uC5D0 \uC2A4\uD0AC\uB85C \uB4F1\uB85D\uB418\uC5B4 \uC790\uB3D9 \uC801\uC6A9\uB429\uB2C8\uB2E4.
|
|
616
634
|
</pai>
|
|
617
635
|
`;
|
|
618
636
|
return {
|
|
@@ -804,8 +822,12 @@ var platform_exports = {};
|
|
|
804
822
|
__export(platform_exports, {
|
|
805
823
|
diagnoseWindowsEnv: () => diagnoseWindowsEnv,
|
|
806
824
|
getPlatformInfo: () => getPlatformInfo,
|
|
825
|
+
getShellRcPath: () => getShellRcPath,
|
|
826
|
+
getYoloAliasLine: () => getYoloAliasLine,
|
|
827
|
+
hasYoloAlias: () => hasYoloAlias,
|
|
807
828
|
isMac: () => isMac,
|
|
808
829
|
isWindows: () => isWindows,
|
|
830
|
+
spawnSubshell: () => spawnSubshell,
|
|
809
831
|
writeEnvFile: () => writeEnvFile
|
|
810
832
|
});
|
|
811
833
|
import os from "os";
|
|
@@ -848,6 +870,41 @@ function getPlatformInfo() {
|
|
|
848
870
|
nodeVersion: process.version
|
|
849
871
|
};
|
|
850
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
|
+
}
|
|
851
908
|
var isWindows, isMac;
|
|
852
909
|
var init_platform = __esm({
|
|
853
910
|
"src/utils/platform.ts"() {
|
|
@@ -887,30 +944,147 @@ async function provisionGitHub(ctx) {
|
|
|
887
944
|
`> \uB9C8\uC9C0\uB9C9 \uC5C5\uB370\uC774\uD2B8: ${now}`,
|
|
888
945
|
"",
|
|
889
946
|
"## \uC9C4\uD589 \uC911",
|
|
890
|
-
|
|
947
|
+
"- [ ] Ideation \uBB38\uC11C \uC791\uC131 \u2014 \uC2EC\uCE35 \uC778\uD130\uBDF0\uB97C \uD1B5\uD574 \uC544\uC774\uB514\uC5B4\uB97C \uAD6C\uCCB4\uD654 (\uB2F4\uB2F9: PAI > Design)",
|
|
891
948
|
"",
|
|
892
949
|
"## \uB2E4\uC74C \uB2E8\uACC4",
|
|
893
|
-
"- [ ] PRD \
|
|
950
|
+
"- [ ] Ideation \uAE30\uBC18 PRD \uC791\uC131 \u2014 \uC2EC\uCE35 \uC778\uD130\uBDF0\uB85C \uB9E5\uB77D/\uAE30\uC220 \uC81C\uC57D \uBCF4\uAC15",
|
|
951
|
+
"- [ ] \uD558\uB124\uC2A4 \uC5D4\uC9C0\uB2C8\uC5B4\uB9C1 \uAD6C\uC131 \uD655\uC778 \u2014 \uC5D0\uC774\uC804\uD2B8 \uC791\uC5C5 \uD658\uACBD \uAC80\uC99D",
|
|
952
|
+
"- [ ] AI \uCF54\uB4DC \uC0DD\uC131 \uC2DC\uC791",
|
|
894
953
|
"",
|
|
895
954
|
"## \uC644\uB8CC",
|
|
896
955
|
`- [x] \uD504\uB85C\uC81D\uD2B8 \uCD08\uAE30\uD654 (${now}) (\uB2F4\uB2F9: PAI > Environment)`,
|
|
897
956
|
"",
|
|
957
|
+
"## \uC791\uC5C5 \uD30C\uC774\uD504\uB77C\uC778",
|
|
958
|
+
"```",
|
|
959
|
+
"1. /pai design \u2192 Ideation \uC2EC\uCE35 \uC778\uD130\uBDF0 \u2192 docs/ideation.md \uC0DD\uC131",
|
|
960
|
+
"2. /pai design \u2192 PRD \uC2EC\uCE35 \uC778\uD130\uBDF0 \u2192 docs/openspec.md \uC791\uC131",
|
|
961
|
+
"3. /pai design \u2192 \uAE30\uC220 \uC81C\uC57D \uC2EC\uCE35 \uC778\uD130\uBDF0 \u2192 \uD558\uB124\uC2A4 \uC5D4\uC9C0\uB2C8\uC5B4\uB9C1 \uD655\uC778",
|
|
962
|
+
"4. AI \uCF54\uB4DC \uC0DD\uC131 \u2192 \uAC80\uC99D \u2192 \uD3C9\uAC00",
|
|
963
|
+
"```",
|
|
964
|
+
"",
|
|
898
965
|
"## \uBA54\uBAA8",
|
|
899
966
|
`- \uBAA8\uB4DC: ${ctx.mode}`,
|
|
900
|
-
"-
|
|
967
|
+
"- \uCEE8\uD14D\uC2A4\uD2B8\uAC00 \uBD80\uC871\uD558\uBA74 AI\uAC00 \uC790\uB3D9\uC73C\uB85C \uC2EC\uCE35 \uC778\uD130\uBDF0\uB97C \uC9C4\uD589\uD569\uB2C8\uB2E4"
|
|
968
|
+
].join("\n") + "\n");
|
|
969
|
+
}
|
|
970
|
+
const contribPath = join3(ctx.cwd, "CONTRIBUTING.md");
|
|
971
|
+
if (!await fs4.pathExists(contribPath)) {
|
|
972
|
+
await fs4.writeFile(contribPath, [
|
|
973
|
+
`# Contributing to ${ctx.projectName}`,
|
|
974
|
+
"",
|
|
975
|
+
"\uC774 \uD504\uB85C\uC81D\uD2B8\uC5D0 \uAE30\uC5EC\uD574 \uC8FC\uC154\uC11C \uAC10\uC0AC\uD569\uB2C8\uB2E4.",
|
|
976
|
+
"",
|
|
977
|
+
"## \uAC1C\uBC1C \uD658\uACBD \uC124\uC815",
|
|
978
|
+
"",
|
|
979
|
+
"```bash",
|
|
980
|
+
"git clone <repo-url>",
|
|
981
|
+
"cd " + ctx.projectName,
|
|
982
|
+
"npm install",
|
|
983
|
+
"```",
|
|
984
|
+
"",
|
|
985
|
+
"## \uBE0C\uB79C\uCE58 \uADDC\uCE59",
|
|
986
|
+
"",
|
|
987
|
+
"- `main` \u2014 \uC548\uC815 \uBC84\uC804",
|
|
988
|
+
"- `feat/<\uAE30\uB2A5\uBA85>` \u2014 \uC0C8 \uAE30\uB2A5 \uAC1C\uBC1C",
|
|
989
|
+
"- `fix/<\uC774\uC288\uBC88\uD638>` \u2014 \uBC84\uADF8 \uC218\uC815",
|
|
990
|
+
"",
|
|
991
|
+
"## \uCEE4\uBC0B \uBA54\uC2DC\uC9C0",
|
|
992
|
+
"",
|
|
993
|
+
"```",
|
|
994
|
+
"feat: \uC0C8 \uAE30\uB2A5 \uCD94\uAC00",
|
|
995
|
+
"fix: \uBC84\uADF8 \uC218\uC815",
|
|
996
|
+
"docs: \uBB38\uC11C \uC218\uC815",
|
|
997
|
+
"refactor: \uB9AC\uD329\uD1A0\uB9C1",
|
|
998
|
+
"test: \uD14C\uC2A4\uD2B8 \uCD94\uAC00/\uC218\uC815",
|
|
999
|
+
"```",
|
|
1000
|
+
"",
|
|
1001
|
+
"## PR \uD504\uB85C\uC138\uC2A4",
|
|
1002
|
+
"",
|
|
1003
|
+
"1. \uBE0C\uB79C\uCE58 \uC0DD\uC131 \u2192 \uC791\uC5C5 \u2192 \uCEE4\uBC0B",
|
|
1004
|
+
"2. `npm test` \uB85C \uD14C\uC2A4\uD2B8 \uD1B5\uACFC \uD655\uC778",
|
|
1005
|
+
"3. PR \uC0DD\uC131 \u2014 \uBCC0\uACBD \uC0AC\uD56D \uC694\uC57D \uC791\uC131",
|
|
1006
|
+
"4. \uB9AC\uBDF0 \uD6C4 \uBA38\uC9C0",
|
|
1007
|
+
"",
|
|
1008
|
+
"## AI \uD611\uC5C5 \uADDC\uCE59",
|
|
1009
|
+
"",
|
|
1010
|
+
"- `CLAUDE.md` \uB97C \uC77D\uACE0 \uD504\uB85C\uC81D\uD2B8 \uCEE8\uD14D\uC2A4\uD2B8\uB97C \uD30C\uC545\uD558\uC138\uC694",
|
|
1011
|
+
"- `/pai evaluate` \uB85C AI \uC900\uBE44\uB3C4\uB97C \uD655\uC778\uD558\uC138\uC694",
|
|
1012
|
+
"- \uCEE8\uD14D\uC2A4\uD2B8\uAC00 \uBD80\uC871\uD558\uBA74 \uCD94\uCE21\uD558\uC9C0 \uB9D0\uACE0 \uC9C8\uBB38\uD558\uC138\uC694",
|
|
1013
|
+
""
|
|
1014
|
+
].join("\n") + "\n");
|
|
1015
|
+
}
|
|
1016
|
+
const contribSkillDir = join3(ctx.cwd, ".claude", "skills");
|
|
1017
|
+
await fs4.ensureDir(contribSkillDir);
|
|
1018
|
+
const contribSkillPath = join3(contribSkillDir, "contributing.md");
|
|
1019
|
+
if (!await fs4.pathExists(contribSkillPath)) {
|
|
1020
|
+
await fs4.writeFile(contribSkillPath, [
|
|
1021
|
+
"---",
|
|
1022
|
+
"name: contributing",
|
|
1023
|
+
'description: "\uAE30\uC5EC\uC790 \uAC00\uC774\uB4DC \u2014 \uBE0C\uB79C\uCE58 \uADDC\uCE59, \uCEE4\uBC0B \uBA54\uC2DC\uC9C0, PR \uD504\uB85C\uC138\uC2A4 \uC790\uB3D9 \uC801\uC6A9"',
|
|
1024
|
+
"---",
|
|
1025
|
+
"",
|
|
1026
|
+
"# Contributing Guide",
|
|
1027
|
+
"",
|
|
1028
|
+
"\uD504\uB85C\uC81D\uD2B8 \uAE30\uC5EC \uC2DC `CONTRIBUTING.md`\uC758 \uADDC\uCE59\uC744 \uC790\uB3D9\uC73C\uB85C \uC801\uC6A9\uD569\uB2C8\uB2E4.",
|
|
1029
|
+
"",
|
|
1030
|
+
"## \uC790\uB3D9 \uC801\uC6A9 \uADDC\uCE59",
|
|
1031
|
+
"",
|
|
1032
|
+
"1. **\uBE0C\uB79C\uCE58**: `feat/`, `fix/`, `docs/`, `refactor/`, `test/` \uC811\uB450\uC0AC \uC0AC\uC6A9",
|
|
1033
|
+
"2. **\uCEE4\uBC0B**: `feat:`, `fix:`, `docs:`, `refactor:`, `test:` \uD615\uC2DD",
|
|
1034
|
+
"3. **PR**: \uBCC0\uACBD \uC0AC\uD56D \uC694\uC57D \uD544\uC218",
|
|
1035
|
+
"4. **\uD14C\uC2A4\uD2B8**: PR \uC804 `npm test` \uD1B5\uACFC \uD544\uC218",
|
|
1036
|
+
"",
|
|
1037
|
+
"## \uC791\uC5C5 \uC2DC \uD655\uC778",
|
|
1038
|
+
"",
|
|
1039
|
+
"- `CONTRIBUTING.md` \uB97C \uC77D\uACE0 \uADDC\uCE59\uC744 \uB530\uB974\uC138\uC694",
|
|
1040
|
+
"- \uCEE4\uBC0B \uBA54\uC2DC\uC9C0\uAC00 \uADDC\uCE59\uC5D0 \uB9DE\uB294\uC9C0 \uD655\uC778\uD558\uC138\uC694",
|
|
1041
|
+
"- PR \uC0DD\uC131 \uC2DC \uBCC0\uACBD \uC0AC\uD56D\uC744 \uC694\uC57D\uD558\uC138\uC694",
|
|
1042
|
+
""
|
|
901
1043
|
].join("\n") + "\n");
|
|
902
1044
|
}
|
|
903
1045
|
const gitignorePath = join3(ctx.cwd, ".gitignore");
|
|
904
1046
|
if (!await fs4.pathExists(gitignorePath)) {
|
|
905
1047
|
await fs4.writeFile(gitignorePath, [
|
|
1048
|
+
"# Dependencies",
|
|
906
1049
|
"node_modules/",
|
|
1050
|
+
"",
|
|
1051
|
+
"# Environment",
|
|
1052
|
+
".env",
|
|
907
1053
|
".env.local",
|
|
908
1054
|
".env*.local",
|
|
1055
|
+
"",
|
|
1056
|
+
"# Build",
|
|
1057
|
+
"dist/",
|
|
1058
|
+
"build/",
|
|
1059
|
+
".next/",
|
|
1060
|
+
"out/",
|
|
1061
|
+
"",
|
|
1062
|
+
"# Services",
|
|
909
1063
|
".vercel",
|
|
910
1064
|
".supabase",
|
|
911
|
-
"
|
|
1065
|
+
"",
|
|
1066
|
+
"# OS",
|
|
912
1067
|
".DS_Store",
|
|
913
|
-
"Thumbs.db"
|
|
1068
|
+
"Thumbs.db",
|
|
1069
|
+
"",
|
|
1070
|
+
"# IDE",
|
|
1071
|
+
".idea/",
|
|
1072
|
+
".vscode/settings.json",
|
|
1073
|
+
"*.swp",
|
|
1074
|
+
"*.swo",
|
|
1075
|
+
"",
|
|
1076
|
+
"# PAI / OMC state",
|
|
1077
|
+
".omc/state/",
|
|
1078
|
+
".omc/sessions/",
|
|
1079
|
+
".omc/logs/",
|
|
1080
|
+
"",
|
|
1081
|
+
"# Logs",
|
|
1082
|
+
"*.log",
|
|
1083
|
+
"npm-debug.log*",
|
|
1084
|
+
"",
|
|
1085
|
+
"# Windows",
|
|
1086
|
+
"desktop.ini",
|
|
1087
|
+
"$RECYCLE.BIN/"
|
|
914
1088
|
].join("\n") + "\n");
|
|
915
1089
|
}
|
|
916
1090
|
}
|
|
@@ -1331,30 +1505,74 @@ PAI Doctor \u2014 \uD658\uACBD \uC9C4\uB2E8
|
|
|
1331
1505
|
`,
|
|
1332
1506
|
"design.md": `---
|
|
1333
1507
|
name: "PAI: Design"
|
|
1334
|
-
description: "
|
|
1508
|
+
description: "Ideation \u2192 PRD \u2192 \uD558\uB124\uC2A4 \uAD6C\uC131\uAE4C\uC9C0 \uC2EC\uCE35 \uC778\uD130\uBDF0 \uAE30\uBC18 \uC124\uACC4"
|
|
1335
1509
|
---
|
|
1336
1510
|
|
|
1337
|
-
# PAI \uC124\uACC4 \
|
|
1511
|
+
# PAI \uC124\uACC4 \u2014 \uC2EC\uCE35 \uC778\uD130\uBDF0 \uAE30\uBC18 \uD30C\uC774\uD504\uB77C\uC778
|
|
1338
1512
|
|
|
1339
1513
|
## \uC778\uC790: $ARGUMENTS
|
|
1340
|
-
- \uC778\uC790 \uC5C6\uC74C \
|
|
1514
|
+
- \uC778\uC790 \uC5C6\uC74C \u2192 \uC804\uCCB4 \uD30C\uC774\uD504\uB77C\uC778 (Ideation \u2192 PRD \u2192 \uD558\uB124\uC2A4)
|
|
1515
|
+
- \`ideation\` \u2192 Ideation\uB9CC \uC218\uD589
|
|
1516
|
+
- \`prd\` \u2192 PRD\uB9CC \uC218\uD589
|
|
1341
1517
|
- \`validate\` \u2192 \uAC80\uC99D\uB9CC \uC218\uD589
|
|
1342
1518
|
|
|
1343
|
-
## \
|
|
1519
|
+
## Phase 1: Ideation (\uC544\uC774\uB514\uC5B4 \uAD6C\uCCB4\uD654)
|
|
1520
|
+
|
|
1521
|
+
**\uBAA9\uD45C**: \uC0AC\uC6A9\uC790\uC758 \uBA38\uB9BF\uC18D \uC544\uC774\uB514\uC5B4\uB97C \`docs/ideation.md\`\uB85C \uAD6C\uCCB4\uD654
|
|
1344
1522
|
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
\uC774\
|
|
1523
|
+
AskUserQuestion \uB3C4\uAD6C\uB85C \uC2EC\uCE35 \uC778\uD130\uBDF0\uB97C \uC9C4\uD589\uD558\uC138\uC694:
|
|
1524
|
+
1. "\uC5B4\uB5A4 \uBB38\uC81C\uB97C \uD574\uACB0\uD558\uACE0 \uC2F6\uC73C\uC138\uC694?" \u2014 \uD575\uC2EC \uACFC\uC81C \uD30C\uC545
|
|
1525
|
+
2. "\uC774 \uC11C\uBE44\uC2A4\uB97C \uC8FC\uB85C \uC0AC\uC6A9\uD560 \uC0AC\uB78C\uC740 \uB204\uAD6C\uC778\uAC00\uC694?" \u2014 \uB300\uC0C1 \uC0AC\uC6A9\uC790
|
|
1526
|
+
3. "\uBE44\uC2B7\uD55C \uC11C\uBE44\uC2A4\uAC00 \uC788\uB2E4\uBA74 \uBB50\uAC00 \uB2E4\uB978\uAC00\uC694?" \u2014 \uCC28\uBCC4\uC810
|
|
1527
|
+
4. "\uBC18\uB4DC\uC2DC \uC788\uC5B4\uC57C \uD560 \uAE30\uB2A5 3\uAC00\uC9C0\uB294?" \u2014 \uD575\uC2EC \uAE30\uB2A5
|
|
1528
|
+
5. "\uC5B8\uC81C\uAE4C\uC9C0 \uB9CC\uB4E4\uACE0 \uC2F6\uC73C\uC138\uC694?" \u2014 \uC77C\uC815 \uC81C\uC57D
|
|
1348
1529
|
|
|
1349
|
-
|
|
1350
|
-
\`docs/openspec.md\`\uB97C \uC77D\uACE0 5\uAC1C \uC139\uC158 \uC644\uC131\uB3C4\uB97C \uAC80\uC99D\uD558\uC138\uC694:
|
|
1351
|
-
1. \uBAA9\uC801 (Purpose) \u2014 \uAD6C\uCCB4\uC801 \uC124\uBA85 \uC788\uB294\uAC00?
|
|
1352
|
-
2. \uC0AC\uC6A9\uC790 (Users) \u2014 \uCD5C\uC18C 1\uAC1C \uC5ED\uD560 \uC815\uC758?
|
|
1353
|
-
3. \uD575\uC2EC \uAE30\uB2A5 (Features) \u2014 \uCD5C\uC18C 1\uAC1C \uAE30\uB2A5 \uAE30\uC220?
|
|
1354
|
-
4. \uAE30\uC220 \uC2A4\uD0DD (Stack) \u2014 1\uAC1C \uC774\uC0C1 \uC815\uC758?
|
|
1355
|
-
5. API \uC5D4\uB4DC\uD3EC\uC778\uD2B8 \u2014 \uCD5C\uC18C 1\uAC1C \uC815\uC758?
|
|
1530
|
+
\uB2F5\uBCC0\uC744 \uC885\uD569\uD558\uC5EC \`docs/ideation.md\`\uB97C \uC0DD\uC131\uD558\uC138\uC694.
|
|
1356
1531
|
|
|
1357
|
-
|
|
1532
|
+
## Phase 2: PRD \uC791\uC131 (\uC81C\uD488 \uC694\uAD6C\uC0AC\uD56D)
|
|
1533
|
+
|
|
1534
|
+
**\uBAA9\uD45C**: Ideation\uC744 \uAE30\uBC18\uC73C\uB85C \`docs/openspec.md\` PRD \uC791\uC131
|
|
1535
|
+
|
|
1536
|
+
\`docs/ideation.md\`\uB97C \uC77D\uACE0, \uBD80\uC871\uD55C \uB9E5\uB77D\uC740 AskUserQuestion\uC73C\uB85C \uBCF4\uAC15:
|
|
1537
|
+
1. "\uAE30\uC220 \uC2A4\uD0DD \uC120\uD638\uAC00 \uC788\uC73C\uC138\uC694?" \u2014 \uD504\uB808\uC784\uC6CC\uD06C/\uC5B8\uC5B4 \uC81C\uC57D
|
|
1538
|
+
2. "\uC678\uBD80 API \uC5F0\uB3D9\uC774 \uD544\uC694\uD55C\uAC00\uC694?" \u2014 \uC758\uC874\uC131 \uD30C\uC545
|
|
1539
|
+
3. "\uB370\uC774\uD130\uB294 \uC5B4\uB5A4 \uAC83\uC744 \uC800\uC7A5\uD574\uC57C \uD558\uB098\uC694?" \u2014 DB \uC2A4\uD0A4\uB9C8 \uD78C\uD2B8
|
|
1540
|
+
4. "\uB85C\uADF8\uC778/\uD68C\uC6D0\uAC00\uC785\uC774 \uD544\uC694\uD55C\uAC00\uC694?" \u2014 \uC778\uC99D \uBC94\uC704
|
|
1541
|
+
|
|
1542
|
+
\uB2F5\uBCC0\uC744 \uC885\uD569\uD558\uC5EC \`docs/openspec.md\` 5\uAC1C \uC139\uC158\uC744 \uC791\uC131:
|
|
1543
|
+
- \uBAA9\uC801 (Purpose)
|
|
1544
|
+
- \uC0AC\uC6A9\uC790 (Users)
|
|
1545
|
+
- \uD575\uC2EC \uAE30\uB2A5 (Features)
|
|
1546
|
+
- \uAE30\uC220 \uC2A4\uD0DD (Stack)
|
|
1547
|
+
- API \uC5D4\uB4DC\uD3EC\uC778\uD2B8
|
|
1548
|
+
|
|
1549
|
+
## Phase 3: \uAE30\uC220 \uC81C\uC57D + \uD558\uB124\uC2A4 \uC5D4\uC9C0\uB2C8\uC5B4\uB9C1
|
|
1550
|
+
|
|
1551
|
+
**\uBAA9\uD45C**: AI \uC5D0\uC774\uC804\uD2B8\uAC00 \uC548\uC804\uD558\uAC8C \uC791\uC5C5\uD560 \uC218 \uC788\uB294 \uD658\uACBD \uD655\uC778
|
|
1552
|
+
|
|
1553
|
+
AskUserQuestion\uC73C\uB85C \uAE30\uC220\uC801 \uC81C\uC57D \uD30C\uC545:
|
|
1554
|
+
1. "\uAE30\uC874\uC5D0 \uC0AC\uC6A9 \uC911\uC778 DB\uB098 \uC11C\uBC84\uAC00 \uC788\uB098\uC694?" \u2014 \uAE30\uC874 \uC778\uD504\uB77C
|
|
1555
|
+
2. "\uBC30\uD3EC \uD658\uACBD\uC740 \uC5B4\uB514\uC778\uAC00\uC694?" \u2014 \uBC30\uD3EC \uC81C\uC57D
|
|
1556
|
+
3. "\uD300\uC5D0\uC11C \uC0AC\uC6A9\uD558\uB294 \uCF54\uB529 \uADDC\uCE59\uC774 \uC788\uB098\uC694?" \u2014 \uC2A4\uD0C0\uC77C \uC81C\uC57D
|
|
1557
|
+
|
|
1558
|
+
\uD558\uB124\uC2A4 \uC5D4\uC9C0\uB2C8\uC5B4\uB9C1 \uD655\uC778:
|
|
1559
|
+
- \`CLAUDE.md\` \u2014 AI \uCEE8\uD14D\uC2A4\uD2B8 \uCDA9\uBD84\uD55C\uC9C0 \uAC80\uC99D
|
|
1560
|
+
- \`.claude/settings.json\` \u2014 \uAD8C\uD55C \uC124\uC815 \uC801\uC808\uD55C\uC9C0 \uD655\uC778
|
|
1561
|
+
- \uD14C\uC2A4\uD2B8 \uD658\uACBD \u2014 \`tests/\` \uB514\uB809\uD1A0\uB9AC + \uD14C\uC2A4\uD2B8 \uD504\uB808\uC784\uC6CC\uD06C \uC874\uC7AC \uD655\uC778
|
|
1562
|
+
- \uBD80\uC871\uD55C \uD56D\uBAA9\uC740 \uC790\uB3D9 \uC0DD\uC131 \uC81C\uC548
|
|
1563
|
+
|
|
1564
|
+
## Phase 4: \uAC80\uC99D
|
|
1565
|
+
|
|
1566
|
+
\uBAA8\uB4E0 Phase \uC644\uB8CC \uD6C4:
|
|
1567
|
+
1. \`docs/ideation.md\` \uC874\uC7AC + \uB0B4\uC6A9 \uD655\uC778
|
|
1568
|
+
2. \`docs/openspec.md\` 5\uAC1C \uC139\uC158 \uC644\uC131\uB3C4 \uAC80\uC99D
|
|
1569
|
+
3. \`handoff.md\` \uC5C5\uB370\uC774\uD2B8 \u2014 \uC644\uB8CC\uB41C \uD56D\uBAA9 \uCCB4\uD06C, \uB2E4\uC74C \uB2E8\uACC4 \uAC31\uC2E0
|
|
1570
|
+
|
|
1571
|
+
## \uC911\uC694 \uC6D0\uCE59
|
|
1572
|
+
|
|
1573
|
+
- **\uCD94\uCE21 \uAE08\uC9C0**: \uCEE8\uD14D\uC2A4\uD2B8\uAC00 \uBD80\uC871\uD558\uBA74 \uBC18\uB4DC\uC2DC AskUserQuestion\uC73C\uB85C \uC9C8\uBB38
|
|
1574
|
+
- **\uC774\uBBF8 \uC874\uC7AC\uD558\uB294 \uD30C\uC77C \uB36E\uC5B4\uC4F0\uC9C0 \uC54A\uC74C** \u2014 \uBCF4\uAC15\uB9CC \uC81C\uC548
|
|
1575
|
+
- **\uAC01 Phase \uC644\uB8CC \uC2DC \uC0AC\uC6A9\uC790\uC5D0\uAC8C \uACB0\uACFC \uC694\uC57D** \uBCF4\uACE0
|
|
1358
1576
|
`,
|
|
1359
1577
|
"validate.md": `---
|
|
1360
1578
|
name: "PAI: Validate"
|
|
@@ -2677,9 +2895,14 @@ async function requestCdAfter(targetDir) {
|
|
|
2677
2895
|
}
|
|
2678
2896
|
async function installShellHelper() {
|
|
2679
2897
|
await fs10.ensureDir(PAI_DIR);
|
|
2680
|
-
|
|
2681
|
-
|
|
2682
|
-
|
|
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();
|
|
2683
2906
|
const sourceLine = 'source "$HOME/.pai/shell-helper.sh"';
|
|
2684
2907
|
if (await fs10.pathExists(rcFile)) {
|
|
2685
2908
|
const content = await fs10.readFile(rcFile, "utf8");
|
|
@@ -2696,15 +2919,36 @@ ${sourceLine}
|
|
|
2696
2919
|
`);
|
|
2697
2920
|
return false;
|
|
2698
2921
|
}
|
|
2699
|
-
|
|
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;
|
|
2700
2943
|
var init_shell_cd = __esm({
|
|
2701
2944
|
"src/utils/shell-cd.ts"() {
|
|
2702
2945
|
"use strict";
|
|
2946
|
+
init_platform();
|
|
2703
2947
|
PAI_DIR = join7(homedir2(), ".pai");
|
|
2704
2948
|
CD_FILE = join7(PAI_DIR, ".cd-after");
|
|
2705
|
-
|
|
2706
|
-
|
|
2707
|
-
|
|
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
|
|
2708
2952
|
pai() {
|
|
2709
2953
|
local cd_target="$HOME/.pai/.cd-after"
|
|
2710
2954
|
rm -f "$cd_target"
|
|
@@ -2721,6 +2965,24 @@ pai() {
|
|
|
2721
2965
|
fi
|
|
2722
2966
|
return $exit_code
|
|
2723
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
|
+
}
|
|
2724
2986
|
`;
|
|
2725
2987
|
}
|
|
2726
2988
|
});
|
|
@@ -3233,16 +3495,16 @@ async function showCompletion(projectName, projectDir, extraTools, isCurrentDir)
|
|
|
3233
3495
|
success("\uC774\uC81C Claude Code\uC640 \uD568\uAED8 PRD \uBB38\uC11C\uB97C \uC791\uC131\uD558\uC138\uC694.");
|
|
3234
3496
|
console.log("");
|
|
3235
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"));
|
|
3236
|
-
const {
|
|
3237
|
-
const shellRc =
|
|
3238
|
-
let
|
|
3498
|
+
const { getShellRcPath: getShellRcPath2, hasYoloAlias: checkYolo } = await Promise.resolve().then(() => (init_platform(), platform_exports));
|
|
3499
|
+
const shellRc = getShellRcPath2();
|
|
3500
|
+
let hasYoloAliasSet = false;
|
|
3239
3501
|
try {
|
|
3240
3502
|
const rcContent = await fs12.readFile(shellRc, "utf8");
|
|
3241
|
-
|
|
3503
|
+
hasYoloAliasSet = checkYolo(rcContent);
|
|
3242
3504
|
} catch {
|
|
3243
3505
|
}
|
|
3244
3506
|
let useYolo = false;
|
|
3245
|
-
if (!
|
|
3507
|
+
if (!hasYoloAliasSet) {
|
|
3246
3508
|
console.log("");
|
|
3247
3509
|
const { mode } = await inquirer.prompt([{
|
|
3248
3510
|
type: "list",
|
|
@@ -3255,10 +3517,12 @@ async function showCompletion(projectName, projectDir, extraTools, isCurrentDir)
|
|
|
3255
3517
|
}]);
|
|
3256
3518
|
if (mode === "yolo") {
|
|
3257
3519
|
useYolo = true;
|
|
3258
|
-
const
|
|
3520
|
+
const { getYoloAliasLine: getYoloAliasLine2 } = await Promise.resolve().then(() => (init_platform(), platform_exports));
|
|
3521
|
+
const aliasLine = getYoloAliasLine2();
|
|
3259
3522
|
try {
|
|
3260
3523
|
const rcContent = await fs12.readFile(shellRc, "utf8").catch(() => "");
|
|
3261
3524
|
if (!rcContent.includes("claude-yolo")) {
|
|
3525
|
+
await fs12.ensureDir(join10(shellRc, ".."));
|
|
3262
3526
|
await fs12.appendFile(shellRc, `
|
|
3263
3527
|
# PAI \u2014 claude-YOLO mode
|
|
3264
3528
|
${aliasLine}
|
|
@@ -3290,12 +3554,8 @@ ${aliasLine}
|
|
|
3290
3554
|
hint("claude \uB97C \uC785\uB825\uD558\uBA74 \uC2DC\uC791\uB429\uB2C8\uB2E4.");
|
|
3291
3555
|
console.log("");
|
|
3292
3556
|
if (!isCurrentDir) {
|
|
3293
|
-
|
|
3294
|
-
|
|
3295
|
-
const shell = process.env.SHELL || "/bin/zsh";
|
|
3296
|
-
execFileSync(shell, ["-l"], { stdio: "inherit", cwd: projectDir });
|
|
3297
|
-
} catch {
|
|
3298
|
-
}
|
|
3557
|
+
const { spawnSubshell: spawnSubshell2 } = await Promise.resolve().then(() => (init_platform(), platform_exports));
|
|
3558
|
+
spawnSubshell2(projectDir);
|
|
3299
3559
|
}
|
|
3300
3560
|
return;
|
|
3301
3561
|
}
|
|
@@ -3344,12 +3604,8 @@ ${aliasLine}
|
|
|
3344
3604
|
cwd: projectDir
|
|
3345
3605
|
});
|
|
3346
3606
|
if (!isCurrentDir) {
|
|
3347
|
-
|
|
3348
|
-
|
|
3349
|
-
const shell = process.env.SHELL || "/bin/zsh";
|
|
3350
|
-
execFileSync(shell, ["-l"], { stdio: "inherit", cwd: projectDir });
|
|
3351
|
-
} catch {
|
|
3352
|
-
}
|
|
3607
|
+
const { spawnSubshell: spawnSubshell2 } = await Promise.resolve().then(() => (init_platform(), platform_exports));
|
|
3608
|
+
spawnSubshell2(projectDir);
|
|
3353
3609
|
}
|
|
3354
3610
|
} catch {
|
|
3355
3611
|
warn(`\uC2E4\uD589 \uC2E4\uD328. \uC9C1\uC811 \uC785\uB825\uD558\uC138\uC694: ${cmd}`);
|
|
@@ -4358,12 +4614,8 @@ async function removeCommand(cwd, options) {
|
|
|
4358
4614
|
} else {
|
|
4359
4615
|
console.log("");
|
|
4360
4616
|
success(`\u2192 cd .. ${colors.dim("\uC0C1\uC704 \uD3F4\uB354\uB85C \uC774\uB3D9")}`);
|
|
4361
|
-
|
|
4362
|
-
|
|
4363
|
-
const shell = process.env.SHELL || "/bin/zsh";
|
|
4364
|
-
execFileSync(shell, ["-l"], { stdio: "inherit", cwd: parentDir });
|
|
4365
|
-
} catch {
|
|
4366
|
-
}
|
|
4617
|
+
const { spawnSubshell: spawnSubshell2 } = await Promise.resolve().then(() => (init_platform(), platform_exports));
|
|
4618
|
+
spawnSubshell2(parentDir);
|
|
4367
4619
|
}
|
|
4368
4620
|
}
|
|
4369
4621
|
var init_remove_cmd = __esm({
|
|
@@ -4773,6 +5025,8 @@ async function wakeupCommand(timeOrAction, schedule = "\uD3C9\uC77C") {
|
|
|
4773
5025
|
await createWakeupScript(config);
|
|
4774
5026
|
if (osPlatform() === "darwin") {
|
|
4775
5027
|
await setupMacOS(config);
|
|
5028
|
+
} else if (osPlatform() === "win32") {
|
|
5029
|
+
await setupWindows(config);
|
|
4776
5030
|
} else {
|
|
4777
5031
|
await setupLinux(config);
|
|
4778
5032
|
}
|
|
@@ -4853,6 +5107,70 @@ ${calendarEntries}
|
|
|
4853
5107
|
hint(`\uC218\uB3D9 \uC124\uC815: sudo pmset repeat wakeorpoweron ${pmsetDays} ${config.time}:00`);
|
|
4854
5108
|
}
|
|
4855
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
|
+
}
|
|
4856
5174
|
async function setupLinux(config) {
|
|
4857
5175
|
const { execa } = await import("execa");
|
|
4858
5176
|
const cronExpr = scheduleToCron(config.time, config.schedule);
|
|
@@ -4882,6 +5200,13 @@ async function disableWakeup() {
|
|
|
4882
5200
|
} catch {
|
|
4883
5201
|
hint("\uC218\uB3D9 \uD574\uC81C: sudo pmset repeat cancel");
|
|
4884
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
|
+
}
|
|
4885
5210
|
} else {
|
|
4886
5211
|
await removeCronEntry();
|
|
4887
5212
|
}
|