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