@chinhae/atw-cli 0.2.9 → 0.3.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.
Files changed (99) hide show
  1. package/README.md +29 -5
  2. package/dist/commands/init.d.ts.map +1 -1
  3. package/dist/commands/init.js +243 -123
  4. package/dist/commands/init.js.map +1 -1
  5. package/dist/commands/uninstall.d.ts.map +1 -1
  6. package/dist/commands/uninstall.js +18 -3
  7. package/dist/commands/uninstall.js.map +1 -1
  8. package/dist/commands/update.d.ts +0 -3
  9. package/dist/commands/update.d.ts.map +1 -1
  10. package/dist/commands/update.js +45 -0
  11. package/dist/commands/update.js.map +1 -1
  12. package/dist/configurators/index.d.ts +8 -0
  13. package/dist/configurators/index.d.ts.map +1 -1
  14. package/dist/configurators/index.js +19 -0
  15. package/dist/configurators/index.js.map +1 -1
  16. package/dist/migrations/manifests/0.2.10.json +9 -0
  17. package/dist/migrations/manifests/0.3.0.json +3410 -0
  18. package/dist/templates/atw/config.yaml +4 -3
  19. package/dist/templates/atw/index.d.ts +2 -0
  20. package/dist/templates/atw/index.d.ts.map +1 -1
  21. package/dist/templates/atw/index.js +4 -0
  22. package/dist/templates/atw/index.js.map +1 -1
  23. package/dist/templates/atw/scripts/common/noob_mode.py +102 -0
  24. package/dist/templates/atw/scripts/common/session_context.py +7 -0
  25. package/dist/templates/atw/scripts/noob_mode.py +41 -0
  26. package/dist/templates/atw/scripts/tickets.py +66 -10
  27. package/dist/templates/atw/workflow.md +81 -17
  28. package/dist/templates/common/bundled-skills/atw-code-review/SKILL.md +4 -2
  29. package/dist/templates/common/bundled-skills/atw-codebase-design/DESIGN-IT-TWICE.md +1 -1
  30. package/dist/templates/common/bundled-skills/atw-diagnosing-bugs/SKILL.md +2 -2
  31. package/dist/templates/common/bundled-skills/atw-domain-modeling/{CONTEXT-FORMAT.md → GLOSSARY-FORMAT.md} +10 -10
  32. package/dist/templates/common/bundled-skills/atw-domain-modeling/SKILL.md +12 -12
  33. package/dist/templates/common/bundled-skills/atw-handoff/SKILL.md +1 -1
  34. package/dist/templates/common/bundled-skills/atw-implement/SKILL.md +6 -4
  35. package/dist/templates/common/bundled-skills/atw-implement-spec/SKILL.md +79 -0
  36. package/dist/templates/common/bundled-skills/atw-implement-spec/agents/openai.yaml +5 -0
  37. package/dist/templates/common/bundled-skills/atw-improve-codebase-architecture/SKILL.md +5 -5
  38. package/dist/templates/common/bundled-skills/atw-init-repo/SKILL.md +6 -4
  39. package/dist/templates/common/bundled-skills/atw-init-repo/references/domain.md +8 -8
  40. package/dist/templates/common/bundled-skills/atw-init-repo/references/issue-tracker-atw-local.md +5 -2
  41. package/dist/templates/common/bundled-skills/atw-init-repo/references/issue-tracker-atw.md +5 -2
  42. package/dist/templates/common/bundled-skills/atw-init-repo/references/issue-tracker-github.md +5 -4
  43. package/dist/templates/common/bundled-skills/atw-init-repo/references/issue-tracker-gitlab.md +2 -2
  44. package/dist/templates/common/bundled-skills/atw-init-repo/references/triage-labels.md +1 -1
  45. package/dist/templates/common/bundled-skills/atw-interview/SKILL.md +9 -1
  46. package/dist/templates/common/bundled-skills/atw-map/SKILL.md +5 -5
  47. package/dist/templates/common/bundled-skills/atw-noob-mode/SKILL.md +101 -0
  48. package/dist/templates/common/bundled-skills/atw-noob-mode/agents/openai.yaml +3 -0
  49. package/dist/templates/common/bundled-skills/atw-prototype/scripts/build_explorer.py +15 -9
  50. package/dist/templates/common/bundled-skills/atw-spec/SKILL.md +1 -1
  51. package/dist/templates/common/bundled-skills/atw-tdd/SKILL.md +2 -2
  52. package/dist/templates/common/bundled-skills/atw-tickets/SKILL.md +4 -4
  53. package/dist/templates/common/bundled-skills/atw-triage/SKILL.md +2 -2
  54. package/dist/templates/common/commands/continue.md +1 -1
  55. package/dist/templates/opencode/plugins/inject-workflow-state.js +29 -1
  56. package/dist/templates/shared-hooks/inject-subagent-context.py +29 -3
  57. package/dist/templates/shared-hooks/inject-workflow-state.py +27 -3
  58. package/dist/templates/shared-hooks/session-start.py +23 -0
  59. package/dist/templates/snow/SNOW.md +1 -1
  60. package/dist/utils/file-writer.d.ts.map +1 -1
  61. package/dist/utils/file-writer.js +29 -16
  62. package/dist/utils/file-writer.js.map +1 -1
  63. package/dist/utils/interactive-guard.d.ts +2 -2
  64. package/dist/utils/interactive-guard.js +2 -2
  65. package/dist/utils/lang.d.ts +14 -0
  66. package/dist/utils/lang.d.ts.map +1 -0
  67. package/dist/utils/lang.js +20 -0
  68. package/dist/utils/lang.js.map +1 -0
  69. package/dist/utils/optional-skills.d.ts +90 -0
  70. package/dist/utils/optional-skills.d.ts.map +1 -0
  71. package/dist/utils/optional-skills.js +266 -0
  72. package/dist/utils/optional-skills.js.map +1 -0
  73. package/dist/utils/template-fetcher.d.ts +6 -0
  74. package/dist/utils/template-fetcher.d.ts.map +1 -1
  75. package/dist/utils/template-fetcher.js +1 -1
  76. package/dist/utils/template-fetcher.js.map +1 -1
  77. package/package.json +2 -2
  78. package/dist/templates/common/bundled-skills/atw-merge/SKILL.md +0 -14
  79. package/dist/templates/common/bundled-skills/atw-merge/agents/openai.yaml +0 -3
  80. package/dist/templates/common/bundled-skills/dejargonizer/SKILL.md +0 -133
  81. package/dist/templates/common/bundled-skills/noob-mode/SKILL.md +0 -175
  82. package/dist/templates/common/bundled-skills/noob-mode/references/examples.md +0 -418
  83. package/dist/templates/common/bundled-skills/noob-mode/references/glossary.md +0 -368
  84. package/dist/templates/common/bundled-skills/oxy-explanation/SKILL.md +0 -80
  85. package/dist/templates/common/bundled-skills/oxy-learning-hub/SKILL.md +0 -179
  86. package/dist/templates/common/bundled-skills/oxy-learning-hub/assets/course.css +0 -1044
  87. package/dist/templates/common/bundled-skills/oxy-learning-hub/assets/course.js +0 -184
  88. package/dist/templates/common/bundled-skills/oxy-learning-hub/assets/lesson-template.html +0 -125
  89. package/dist/templates/common/bundled-skills/oxy-learning-hub/assets/summary-template.html +0 -659
  90. package/dist/templates/common/bundled-skills/oxy-learning-hub/references/publishing.md +0 -64
  91. package/dist/templates/common/bundled-skills/oxy-learning-hub/references/summary-mode.md +0 -96
  92. package/dist/templates/common/bundled-skills/oxy-learning-hub/references/teaching/GLOSSARY-FORMAT.md +0 -30
  93. package/dist/templates/common/bundled-skills/oxy-learning-hub/references/teaching/LEARNING-RECORD-FORMAT.md +0 -42
  94. package/dist/templates/common/bundled-skills/oxy-learning-hub/references/teaching/MISSION-FORMAT.md +0 -50
  95. package/dist/templates/common/bundled-skills/oxy-learning-hub/references/teaching/RESOURCES-FORMAT.md +0 -40
  96. package/dist/templates/common/bundled-skills/oxy-learning-hub/references/teaching-mode.md +0 -251
  97. package/dist/templates/common/bundled-skills/oxy-learning-hub/references/workspace.md +0 -112
  98. package/dist/templates/common/bundled-skills/oxy-learning-hub/scripts/validate_html.py +0 -198
  99. package/dist/templates/common/bundled-skills/show-me/SKILL.md +0 -127
@@ -3,6 +3,7 @@ import path from "node:path";
3
3
  import chalk from "chalk";
4
4
  import inquirer from "inquirer";
5
5
  import { writeFileAtomic } from "./atomic-write.js";
6
+ import { t } from "./lang.js";
6
7
  import { toPosix } from "./posix.js";
7
8
  // Global write mode (set from CLI options)
8
9
  let globalWriteMode = "ask";
@@ -119,19 +120,19 @@ export async function writeFile(filePath, content, options) {
119
120
  if (options?.executable) {
120
121
  fs.chmodSync(filePath, "755");
121
122
  }
122
- console.log(chalk.yellow(` ↻ Overwritten: ${displayPath}`));
123
+ console.log(chalk.yellow(t(` ↻ Overwritten: ${displayPath}`, ` ↻ 已覆盖:${displayPath}`)));
123
124
  recordWrite(filePath);
124
125
  return true;
125
126
  }
126
127
  if (mode === "skip") {
127
- console.log(chalk.gray(` ○ Skipped: ${displayPath} (already exists)`));
128
+ console.log(chalk.gray(t(` ○ Skipped: ${displayPath} (already exists)`, ` ○ 已跳过:${displayPath}(已存在)`)));
128
129
  // Skipped: atw did NOT write this file — caller should not track it
129
130
  // in the manifest. This is the AGENTS.md skip-existing case.
130
131
  return false;
131
132
  }
132
133
  if (mode === "append") {
133
134
  appendToFile(filePath, content, options);
134
- console.log(chalk.blue(` + Appended: ${displayPath}`));
135
+ console.log(chalk.blue(t(` + Appended: ${displayPath}`, ` + 已追加:${displayPath}`)));
135
136
  // Append: atw added atw content to a user-owned file. Tracking
136
137
  // is risky here (uninstall would unlink the whole file), so we do NOT
137
138
  // record appended files. Users on `--append` get a fresh manifest miss
@@ -143,19 +144,31 @@ export async function writeFile(filePath, content, options) {
143
144
  {
144
145
  type: "list",
145
146
  name: "action",
146
- message: `File "${displayPath}" already exists. What would you like to do?`,
147
+ message: t(`File "${displayPath}" already exists. What would you like to do?`, `文件 "${displayPath}" 已存在,要怎么处理?`),
147
148
  choices: [
148
- { name: "Skip (keep existing)", value: "skip" },
149
- { name: "Overwrite", value: "overwrite" },
150
- { name: "Append to end", value: "append" },
151
- { name: "Skip all remaining conflicts", value: "skip-all" },
152
- { name: "Overwrite all remaining conflicts", value: "overwrite-all" },
153
- { name: "Append all remaining conflicts", value: "append-all" },
149
+ {
150
+ name: t("Skip (keep existing)", "跳过(保留现有内容)"),
151
+ value: "skip",
152
+ },
153
+ { name: t("Overwrite", "覆盖"), value: "overwrite" },
154
+ { name: t("Append to end", "追加到末尾"), value: "append" },
155
+ {
156
+ name: t("Skip all remaining conflicts", "后面的冲突全部跳过"),
157
+ value: "skip-all",
158
+ },
159
+ {
160
+ name: t("Overwrite all remaining conflicts", "后面的冲突全部覆盖"),
161
+ value: "overwrite-all",
162
+ },
163
+ {
164
+ name: t("Append all remaining conflicts", "后面的冲突全部追加"),
165
+ value: "append-all",
166
+ },
154
167
  ],
155
168
  },
156
169
  ]);
157
170
  if (action === "skip") {
158
- console.log(chalk.gray(` ○ Skipped: ${displayPath}`));
171
+ console.log(chalk.gray(t(` ○ Skipped: ${displayPath}`, ` ○ 已跳过:${displayPath}`)));
159
172
  return false;
160
173
  }
161
174
  if (action === "overwrite") {
@@ -163,18 +176,18 @@ export async function writeFile(filePath, content, options) {
163
176
  if (options?.executable) {
164
177
  fs.chmodSync(filePath, "755");
165
178
  }
166
- console.log(chalk.yellow(` ↻ Overwritten: ${displayPath}`));
179
+ console.log(chalk.yellow(t(` ↻ Overwritten: ${displayPath}`, ` ↻ 已覆盖:${displayPath}`)));
167
180
  recordWrite(filePath);
168
181
  return true;
169
182
  }
170
183
  if (action === "append") {
171
184
  appendToFile(filePath, content, options);
172
- console.log(chalk.blue(` + Appended: ${displayPath}`));
185
+ console.log(chalk.blue(t(` + Appended: ${displayPath}`, ` + 已追加:${displayPath}`)));
173
186
  return true;
174
187
  }
175
188
  if (action === "skip-all") {
176
189
  globalWriteMode = "skip";
177
- console.log(chalk.gray(` ○ Skipped: ${displayPath}`));
190
+ console.log(chalk.gray(t(` ○ Skipped: ${displayPath}`, ` ○ 已跳过:${displayPath}`)));
178
191
  return false;
179
192
  }
180
193
  if (action === "overwrite-all") {
@@ -183,14 +196,14 @@ export async function writeFile(filePath, content, options) {
183
196
  if (options?.executable) {
184
197
  fs.chmodSync(filePath, "755");
185
198
  }
186
- console.log(chalk.yellow(` ↻ Overwritten: ${displayPath}`));
199
+ console.log(chalk.yellow(t(` ↻ Overwritten: ${displayPath}`, ` ↻ 已覆盖:${displayPath}`)));
187
200
  recordWrite(filePath);
188
201
  return true;
189
202
  }
190
203
  if (action === "append-all") {
191
204
  globalWriteMode = "append";
192
205
  appendToFile(filePath, content, options);
193
- console.log(chalk.blue(` + Appended: ${displayPath}`));
206
+ console.log(chalk.blue(t(` + Appended: ${displayPath}`, ` + 已追加:${displayPath}`)));
194
207
  return true;
195
208
  }
196
209
  return false;
@@ -1 +1 @@
1
- {"version":3,"file":"file-writer.js","sourceRoot":"","sources":["../../src/utils/file-writer.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"file-writer.js","sourceRoot":"","sources":["../../src/utils/file-writer.ts"],"names":[],"mappings":"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"}
@@ -17,8 +17,8 @@ export declare function refuseNonInteractivePrompt(what: string, hint: string):
17
17
  *
18
18
  * Guard at the prompt, never at the command entry point. Which questions a
19
19
  * run actually reaches depends on the flags it was given: `atw init --claude
20
- * --with-statusline` answers the only question that run would have asked, so
21
- * it completes fine without `--yes`. An entry-point guard keyed on "did they
20
+ * -u <name>` answers every question that run would have asked, so it
21
+ * completes fine without `--yes`. An entry-point guard keyed on "did they
22
22
  * pass --yes" would reject that working invocation — the same mistake in
23
23
  * reverse as the one this guard exists to fix, since a flag expresses consent,
24
24
  * not what kind of shell this is.
@@ -25,8 +25,8 @@ export function refuseNonInteractivePrompt(what, hint) {
25
25
  *
26
26
  * Guard at the prompt, never at the command entry point. Which questions a
27
27
  * run actually reaches depends on the flags it was given: `atw init --claude
28
- * --with-statusline` answers the only question that run would have asked, so
29
- * it completes fine without `--yes`. An entry-point guard keyed on "did they
28
+ * -u <name>` answers every question that run would have asked, so it
29
+ * completes fine without `--yes`. An entry-point guard keyed on "did they
30
30
  * pass --yes" would reject that working invocation — the same mistake in
31
31
  * reverse as the one this guard exists to fix, since a flag expresses consent,
32
32
  * not what kind of shell this is.
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Display language of `atw init`.
3
+ *
4
+ * The user picks it as the first question of an interactive init; every later
5
+ * prompt and message of that run follows it. It is wording only — nothing
6
+ * written into the project depends on it, so it is not persisted and every
7
+ * other command (and any non-interactive init) stays English.
8
+ */
9
+ export type Lang = "en" | "zh";
10
+ export declare function setLang(lang: Lang): void;
11
+ export declare function getLang(): Lang;
12
+ /** Pick the wording for the current language. */
13
+ export declare function t(en: string, zh: string): string;
14
+ //# sourceMappingURL=lang.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lang.d.ts","sourceRoot":"","sources":["../../src/utils/lang.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,MAAM,MAAM,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAI/B,wBAAgB,OAAO,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,CAExC;AAED,wBAAgB,OAAO,IAAI,IAAI,CAE9B;AAED,iDAAiD;AACjD,wBAAgB,CAAC,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAEhD"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Display language of `atw init`.
3
+ *
4
+ * The user picks it as the first question of an interactive init; every later
5
+ * prompt and message of that run follows it. It is wording only — nothing
6
+ * written into the project depends on it, so it is not persisted and every
7
+ * other command (and any non-interactive init) stays English.
8
+ */
9
+ let currentLang = "en";
10
+ export function setLang(lang) {
11
+ currentLang = lang;
12
+ }
13
+ export function getLang() {
14
+ return currentLang;
15
+ }
16
+ /** Pick the wording for the current language. */
17
+ export function t(en, zh) {
18
+ return currentLang === "zh" ? zh : en;
19
+ }
20
+ //# sourceMappingURL=lang.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lang.js","sourceRoot":"","sources":["../../src/utils/lang.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,IAAI,WAAW,GAAS,IAAI,CAAC;AAE7B,MAAM,UAAU,OAAO,CAAC,IAAU;IAChC,WAAW,GAAG,IAAI,CAAC;AACrB,CAAC;AAED,MAAM,UAAU,OAAO;IACrB,OAAO,WAAW,CAAC;AACrB,CAAC;AAED,iDAAiD;AACjD,MAAM,UAAU,CAAC,CAAC,EAAU,EAAE,EAAU;IACtC,OAAO,WAAW,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;AACxC,CAAC"}
@@ -0,0 +1,90 @@
1
+ /**
2
+ * Optional skills offered by `atw init`.
3
+ *
4
+ * They are not part of ATW and do not ship in this package: the list and the
5
+ * skills themselves live in https://github.com/LFT-OXY/oxy-Tools and are
6
+ * downloaded on request. That repo is the only source, including for skills
7
+ * that originate elsewhere — its copies carry local changes an upstream
8
+ * download would lose.
9
+ *
10
+ * What ATW installed is recorded in `.atw/.optional-skills.json`, per skill
11
+ * and skill directory. That record — not `.template-hashes.json`, whose
12
+ * entries must belong to a platform configurator — is what lets `atw update`
13
+ * replace a skill when the index lists another version, and `atw uninstall`
14
+ * remove it. ATW owns a recorded directory as a whole: it is replaced or
15
+ * removed wholesale, local edits included. A same-named directory ATW did not
16
+ * install is never touched.
17
+ */
18
+ export declare const OPTIONAL_SKILLS_INDEX_URL = "https://raw.githubusercontent.com/LFT-OXY/oxy-Tools/main/index.json";
19
+ export interface OptionalSkill {
20
+ /** Directory name the skill is installed under. */
21
+ name: string;
22
+ /**
23
+ * Version the index currently lists. Compared for inequality only — the
24
+ * index is the source of truth, so any other value replaces an installed
25
+ * copy.
26
+ */
27
+ version: string;
28
+ /** Directory inside the oxy-Tools repo. */
29
+ path: string;
30
+ /** One line shown in the picker, per `atw init` language. */
31
+ description: {
32
+ en: string;
33
+ zh: string;
34
+ };
35
+ }
36
+ /** Skill name → the version ATW installed and the skill roots it is in. */
37
+ export type OptionalSkillRecord = Record<string, {
38
+ version: string;
39
+ roots: string[];
40
+ }>;
41
+ export interface OptionalSkillResult {
42
+ name: string;
43
+ version: string;
44
+ /** Version that was installed before, when this run replaced it. */
45
+ previousVersion?: string;
46
+ /** Skill roots the skill was newly copied into. */
47
+ installed: string[];
48
+ /** Skill roots where ATW's own copy was replaced by another version. */
49
+ updated: string[];
50
+ /** Skill roots where ATW's copy is already this version. */
51
+ current: string[];
52
+ /** Skill roots holding a same-named directory ATW did not install. */
53
+ foreign: string[];
54
+ error?: string;
55
+ }
56
+ /**
57
+ * Fetch the optional-skill list. Returns an empty array when it cannot be
58
+ * reached or read — callers skip the step rather than fail the command.
59
+ */
60
+ export declare function fetchOptionalSkills(): Promise<OptionalSkill[]>;
61
+ /**
62
+ * Load what ATW installed. Entries are re-validated on every read: the record
63
+ * names directories that update and uninstall delete, so a hand-edited or
64
+ * corrupted file must not be able to name anything but `<skill root>/<name>`.
65
+ */
66
+ export declare function loadOptionalSkillRecord(cwd: string): OptionalSkillRecord;
67
+ /**
68
+ * Directories of the optional skills ATW installed that are still on disk,
69
+ * as POSIX paths relative to the project root — what `atw uninstall` removes.
70
+ */
71
+ export declare function getInstalledOptionalSkillDirs(cwd: string): string[];
72
+ /**
73
+ * Bring the given skills to the version the index lists, yielding one result
74
+ * per skill as it finishes.
75
+ *
76
+ * Each skill is handled in `skillRoots` plus every root ATW already installed
77
+ * it into, so all of ATW's copies of a skill stay on one version. Per root:
78
+ * - nothing there → installed (only in `skillRoots`; a recorded
79
+ * copy the user has since deleted is forgotten,
80
+ * not put back)
81
+ * - ATW's copy, same version → left as is
82
+ * - ATW's copy, other version → replaced wholesale
83
+ * - somebody else's directory → never touched
84
+ *
85
+ * Pass no `skillRoots` to only refresh what is already installed (`atw
86
+ * update`). All skills share one download of the oxy-Tools repo, and it is
87
+ * not downloaded at all when no skill has anything to copy.
88
+ */
89
+ export declare function installOptionalSkills(cwd: string, skills: readonly OptionalSkill[], skillRoots: readonly string[]): AsyncGenerator<OptionalSkillResult>;
90
+ //# sourceMappingURL=optional-skills.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"optional-skills.d.ts","sourceRoot":"","sources":["../../src/utils/optional-skills.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAaH,eAAO,MAAM,yBAAyB,wEACiC,CAAC;AAcxE,MAAM,WAAW,aAAa;IAC5B,mDAAmD;IACnD,IAAI,EAAE,MAAM,CAAC;IACb;;;;OAIG;IACH,OAAO,EAAE,MAAM,CAAC;IAChB,2CAA2C;IAC3C,IAAI,EAAE,MAAM,CAAC;IACb,6DAA6D;IAC7D,WAAW,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC;CACzC;AAED,2EAA2E;AAC3E,MAAM,MAAM,mBAAmB,GAAG,MAAM,CACtC,MAAM,EACN;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,EAAE,CAAA;CAAE,CACrC,CAAC;AAEF,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,oEAAoE;IACpE,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,mDAAmD;IACnD,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,wEAAwE;IACxE,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,4DAA4D;IAC5D,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,sEAAsE;IACtE,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AA0CD;;;GAGG;AACH,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC,CAgBpE;AAUD;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,MAAM,GAAG,mBAAmB,CAuBxE;AAYD;;;GAGG;AACH,wBAAgB,6BAA6B,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAUnE;AAqBD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAuB,qBAAqB,CAC1C,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,SAAS,aAAa,EAAE,EAChC,UAAU,EAAE,SAAS,MAAM,EAAE,GAC5B,cAAc,CAAC,mBAAmB,CAAC,CAiFrC"}
@@ -0,0 +1,266 @@
1
+ /**
2
+ * Optional skills offered by `atw init`.
3
+ *
4
+ * They are not part of ATW and do not ship in this package: the list and the
5
+ * skills themselves live in https://github.com/LFT-OXY/oxy-Tools and are
6
+ * downloaded on request. That repo is the only source, including for skills
7
+ * that originate elsewhere — its copies carry local changes an upstream
8
+ * download would lose.
9
+ *
10
+ * What ATW installed is recorded in `.atw/.optional-skills.json`, per skill
11
+ * and skill directory. That record — not `.template-hashes.json`, whose
12
+ * entries must belong to a platform configurator — is what lets `atw update`
13
+ * replace a skill when the index lists another version, and `atw uninstall`
14
+ * remove it. ATW owns a recorded directory as a whole: it is replaced or
15
+ * removed wholesale, local edits included. A same-named directory ATW did not
16
+ * install is never touched.
17
+ */
18
+ import { randomUUID } from "node:crypto";
19
+ import fs from "node:fs";
20
+ import os from "node:os";
21
+ import path from "node:path";
22
+ import { downloadTemplate } from "giget";
23
+ import { getSkillRoots, PLATFORM_IDS } from "../configurators/index.js";
24
+ import { DIR_NAMES } from "../constants/paths.js";
25
+ import { TIMEOUTS, withTimeout } from "./template-fetcher.js";
26
+ const OPTIONAL_SKILLS_REPO = "gh:LFT-OXY/oxy-Tools";
27
+ export const OPTIONAL_SKILLS_INDEX_URL = "https://raw.githubusercontent.com/LFT-OXY/oxy-Tools/main/index.json";
28
+ const RECORD_FILE = ".optional-skills.json";
29
+ /**
30
+ * The repo is downloaded as a whole and carries every skill's assets (tens of
31
+ * MB), so it gets far longer than a spec template. A timeout here fails every
32
+ * selected skill at once.
33
+ */
34
+ const SKILL_DOWNLOAD_MS = 300_000;
35
+ /** `name` becomes a directory name; nothing that could leave the skill root. */
36
+ const SKILL_NAME_RE = /^[A-Za-z0-9][A-Za-z0-9._-]*$/;
37
+ function isRecord(value) {
38
+ return typeof value === "object" && value !== null && !Array.isArray(value);
39
+ }
40
+ // =============================================================================
41
+ // Index
42
+ // =============================================================================
43
+ /**
44
+ * Keep only entries that are safe to act on. `name` and `path` become file
45
+ * system paths, so a malformed index must not be able to point outside the
46
+ * skill root or the downloaded repo.
47
+ */
48
+ function parseOptionalSkill(entry) {
49
+ if (!isRecord(entry))
50
+ return null;
51
+ const { name, version, path: skillPath, description } = entry;
52
+ if (typeof name !== "string" || !SKILL_NAME_RE.test(name))
53
+ return null;
54
+ if (typeof version !== "string" || version.length === 0)
55
+ return null;
56
+ if (!isRecord(description) ||
57
+ typeof description.en !== "string" ||
58
+ typeof description.zh !== "string") {
59
+ return null;
60
+ }
61
+ if (typeof skillPath !== "string" ||
62
+ path.isAbsolute(skillPath) ||
63
+ skillPath.split(/[\\/]/).some((part) => part === ".." || part === "")) {
64
+ return null;
65
+ }
66
+ return {
67
+ name,
68
+ version,
69
+ path: skillPath,
70
+ description: { en: description.en, zh: description.zh },
71
+ };
72
+ }
73
+ /**
74
+ * Fetch the optional-skill list. Returns an empty array when it cannot be
75
+ * reached or read — callers skip the step rather than fail the command.
76
+ */
77
+ export async function fetchOptionalSkills() {
78
+ try {
79
+ const res = await fetch(OPTIONAL_SKILLS_INDEX_URL, {
80
+ signal: AbortSignal.timeout(TIMEOUTS.INDEX_FETCH_MS),
81
+ });
82
+ if (!res.ok) {
83
+ throw new Error(`HTTP ${res.status}`);
84
+ }
85
+ const index = await res.json();
86
+ if (!isRecord(index) || !Array.isArray(index.skills))
87
+ return [];
88
+ return index.skills
89
+ .map(parseOptionalSkill)
90
+ .filter((skill) => skill !== null);
91
+ }
92
+ catch {
93
+ return [];
94
+ }
95
+ }
96
+ // =============================================================================
97
+ // Install record
98
+ // =============================================================================
99
+ function recordPath(cwd) {
100
+ return path.join(cwd, DIR_NAMES.WORKFLOW, RECORD_FILE);
101
+ }
102
+ /**
103
+ * Load what ATW installed. Entries are re-validated on every read: the record
104
+ * names directories that update and uninstall delete, so a hand-edited or
105
+ * corrupted file must not be able to name anything but `<skill root>/<name>`.
106
+ */
107
+ export function loadOptionalSkillRecord(cwd) {
108
+ let raw;
109
+ try {
110
+ raw = JSON.parse(fs.readFileSync(recordPath(cwd), "utf-8"));
111
+ }
112
+ catch {
113
+ return {};
114
+ }
115
+ if (!isRecord(raw) || !isRecord(raw.skills))
116
+ return {};
117
+ const knownRoots = new Set(getSkillRoots(PLATFORM_IDS));
118
+ const record = {};
119
+ for (const [name, entry] of Object.entries(raw.skills)) {
120
+ if (!SKILL_NAME_RE.test(name) || !isRecord(entry))
121
+ continue;
122
+ if (typeof entry.version !== "string" || !Array.isArray(entry.roots)) {
123
+ continue;
124
+ }
125
+ const roots = entry.roots.filter((root) => typeof root === "string" && knownRoots.has(root));
126
+ if (roots.length > 0)
127
+ record[name] = { version: entry.version, roots };
128
+ }
129
+ return record;
130
+ }
131
+ function saveOptionalSkillRecord(cwd, record) {
132
+ fs.writeFileSync(recordPath(cwd), JSON.stringify({ version: 1, skills: record }, null, 2) + "\n");
133
+ }
134
+ /**
135
+ * Directories of the optional skills ATW installed that are still on disk,
136
+ * as POSIX paths relative to the project root — what `atw uninstall` removes.
137
+ */
138
+ export function getInstalledOptionalSkillDirs(cwd) {
139
+ const dirs = [];
140
+ for (const [name, entry] of Object.entries(loadOptionalSkillRecord(cwd))) {
141
+ for (const root of entry.roots) {
142
+ if (fs.existsSync(path.join(cwd, root, name))) {
143
+ dirs.push(`${root}/${name}`);
144
+ }
145
+ }
146
+ }
147
+ return dirs;
148
+ }
149
+ // =============================================================================
150
+ // Install / update
151
+ // =============================================================================
152
+ /**
153
+ * Download the oxy-Tools repo into a fresh temp dir, registered for cleanup
154
+ * before the download starts.
155
+ */
156
+ async function downloadRepo(tempDirs) {
157
+ const dir = path.join(os.tmpdir(), `atw-skill-${randomUUID()}`);
158
+ tempDirs.push(dir);
159
+ await withTimeout(downloadTemplate(OPTIONAL_SKILLS_REPO, { dir }), SKILL_DOWNLOAD_MS, "Skill download");
160
+ return dir;
161
+ }
162
+ /**
163
+ * Bring the given skills to the version the index lists, yielding one result
164
+ * per skill as it finishes.
165
+ *
166
+ * Each skill is handled in `skillRoots` plus every root ATW already installed
167
+ * it into, so all of ATW's copies of a skill stay on one version. Per root:
168
+ * - nothing there → installed (only in `skillRoots`; a recorded
169
+ * copy the user has since deleted is forgotten,
170
+ * not put back)
171
+ * - ATW's copy, same version → left as is
172
+ * - ATW's copy, other version → replaced wholesale
173
+ * - somebody else's directory → never touched
174
+ *
175
+ * Pass no `skillRoots` to only refresh what is already installed (`atw
176
+ * update`). All skills share one download of the oxy-Tools repo, and it is
177
+ * not downloaded at all when no skill has anything to copy.
178
+ */
179
+ export async function* installOptionalSkills(cwd, skills, skillRoots) {
180
+ const tempDirs = [];
181
+ let repoDir;
182
+ const record = loadOptionalSkillRecord(cwd);
183
+ try {
184
+ for (const skill of skills) {
185
+ const recorded = record[skill.name];
186
+ const owned = new Set(recorded?.roots);
187
+ const result = {
188
+ name: skill.name,
189
+ version: skill.version,
190
+ installed: [],
191
+ updated: [],
192
+ current: [],
193
+ foreign: [],
194
+ };
195
+ const toInstall = [];
196
+ const toReplace = [];
197
+ for (const root of new Set([...skillRoots, ...owned])) {
198
+ const exists = fs.existsSync(path.join(cwd, root, skill.name));
199
+ if (!exists) {
200
+ if (skillRoots.includes(root))
201
+ toInstall.push(root);
202
+ }
203
+ else if (!owned.has(root)) {
204
+ result.foreign.push(root);
205
+ }
206
+ else if (recorded?.version === skill.version) {
207
+ result.current.push(root);
208
+ }
209
+ else {
210
+ toReplace.push(root);
211
+ }
212
+ }
213
+ try {
214
+ if (toInstall.length > 0 || toReplace.length > 0) {
215
+ repoDir ??= downloadRepo(tempDirs);
216
+ const skillDir = path.join(await repoDir, skill.path);
217
+ if (!fs.existsSync(path.join(skillDir, "SKILL.md"))) {
218
+ throw new Error(`no SKILL.md at ${skill.path} in the skill repo`);
219
+ }
220
+ for (const root of [...toInstall, ...toReplace]) {
221
+ const dest = path.join(cwd, root, skill.name);
222
+ fs.rmSync(dest, { recursive: true, force: true });
223
+ fs.cpSync(skillDir, dest, { recursive: true });
224
+ }
225
+ result.installed = toInstall;
226
+ result.updated = toReplace;
227
+ if (toReplace.length > 0)
228
+ result.previousVersion = recorded?.version;
229
+ }
230
+ // Sorted so the record does not churn in git with install order.
231
+ const roots = [
232
+ ...result.current,
233
+ ...result.updated,
234
+ ...result.installed,
235
+ ].sort();
236
+ const before = JSON.stringify(recorded);
237
+ if (roots.length > 0) {
238
+ record[skill.name] = { version: skill.version, roots };
239
+ }
240
+ else {
241
+ Reflect.deleteProperty(record, skill.name);
242
+ }
243
+ if (JSON.stringify(record[skill.name]) !== before) {
244
+ saveOptionalSkillRecord(cwd, record);
245
+ }
246
+ }
247
+ catch (error) {
248
+ result.error = error instanceof Error ? error.message : String(error);
249
+ }
250
+ yield result;
251
+ }
252
+ }
253
+ finally {
254
+ // Best-effort cleanup; also settles giget's orphaned download promise on
255
+ // timeout (giget has no AbortSignal, so removing the dir ENOENTs it).
256
+ for (const dir of tempDirs) {
257
+ try {
258
+ fs.rmSync(dir, { recursive: true, force: true });
259
+ }
260
+ catch {
261
+ // Best-effort cleanup
262
+ }
263
+ }
264
+ }
265
+ }
266
+ //# sourceMappingURL=optional-skills.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"optional-skills.js","sourceRoot":"","sources":["../../src/utils/optional-skills.ts"],"names":[],"mappings":"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"}
@@ -85,6 +85,12 @@ export declare function normalizeRegistrySource(source: string): string;
85
85
  * @throws Error if provider is unsupported
86
86
  */
87
87
  export declare function parseRegistrySource(source: string): RegistrySource;
88
+ /**
89
+ * Race a promise against a timeout.
90
+ * giget does not support AbortSignal, so we use Promise.race instead.
91
+ * The timer is cleaned up on success to avoid keeping the process alive.
92
+ */
93
+ export declare function withTimeout<T>(promise: Promise<T>, ms: number, label: string): Promise<T>;
88
94
  /**
89
95
  * Fetch available templates from the remote index
90
96
  * Returns empty array on network error or timeout (allows fallback to blank)
@@ -1 +1 @@
1
- {"version":3,"file":"template-fetcher.d.ts","sourceRoot":"","sources":["../../src/utils/template-fetcher.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"template-fetcher.d.ts","sourceRoot":"","sources":["../../src/utils/template-fetcher.ts"],"names":[],"mappings":"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"}
@@ -268,7 +268,7 @@ async function withGigetHost(host, fn) {
268
268
  * giget does not support AbortSignal, so we use Promise.race instead.
269
269
  * The timer is cleaned up on success to avoid keeping the process alive.
270
270
  */
271
- function withTimeout(promise, ms, label) {
271
+ export function withTimeout(promise, ms, label) {
272
272
  let timer;
273
273
  const timeoutPromise = new Promise((_, reject) => {
274
274
  timer = setTimeout(() => reject(new Error(`${label} timed out after ${ms / 1000}s`)), ms);